wzx 1 年間 前
コミット
9a18f49847
60 ファイル変更9331 行追加1489 行削除
  1. 13 1
      card/App.vue
  2. 15 12
      card/common/api.js
  3. 1 1
      card/common/define.js
  4. 1 0
      card/common/tools.js
  5. 557 0
      card/components/e-select/e-select-built-in.vue
  6. 193 0
      card/components/e-select/e-select.vue
  7. 5 0
      card/components/e-select/uni-pagination-built-in/i18n/en.json
  8. 5 0
      card/components/e-select/uni-pagination-built-in/i18n/es.json
  9. 5 0
      card/components/e-select/uni-pagination-built-in/i18n/fr.json
  10. 12 0
      card/components/e-select/uni-pagination-built-in/i18n/index.js
  11. 5 0
      card/components/e-select/uni-pagination-built-in/i18n/zh-Hans.json
  12. 5 0
      card/components/e-select/uni-pagination-built-in/i18n/zh-Hant.json
  13. 501 0
      card/components/e-select/uni-pagination-built-in/uni-pagination-built-in.vue
  14. 136 0
      card/components/my-pathList/my-pathList.vue
  15. 1 1
      card/components/my-popup-map/my-popup-map.vue
  16. 24 4
      card/components/my-popup/my-popup.vue
  17. 13 3
      card/components/my-ranklist/my-ranklist.vue
  18. 208 0
      card/components/my-tab/my-tab.vue
  19. 3 3
      card/main.js
  20. 48 0
      card/pages.json
  21. 25 55
      card/pages/achievement/index2.vue
  22. 8 1
      card/pages/bm/style1/index.vue
  23. 8 1
      card/pages/bm/style1/rankList.vue
  24. 15 1
      card/pages/bm/style2/cardconfig.md
  25. 15 6
      card/pages/bm/style2/index.vue
  26. 24 7
      card/pages/bm/style2/rankList.vue
  27. 700 717
      card/pages/bm/style2/rankOverview.vue
  28. 678 676
      card/pages/bm/style2/signup.vue
  29. 266 0
      card/pages/bm/style3/cardconfig.md
  30. 484 0
      card/pages/bm/style3/index.vue
  31. 726 0
      card/pages/bm/style3/rankList.vue
  32. 763 0
      card/pages/bm/style3/rankOverview.vue
  33. 685 0
      card/pages/bm/style3/signup.vue
  34. 269 0
      card/pages/bm/style4/cardconfig.md
  35. 481 0
      card/pages/bm/style4/index.vue
  36. 862 0
      card/pages/bm/style4/rankList.vue
  37. 764 0
      card/pages/bm/style4/rankOverview.vue
  38. 807 0
      card/pages/bm/style4/signup.vue
  39. BIN
      card/static/backgroud/top_bg2.png
  40. BIN
      card/static/backgroud/top_bg_egg.png
  41. BIN
      card/static/backgroud/top_bg_egg2.png
  42. BIN
      card/static/backgroud/top_bg_egg3.png
  43. BIN
      card/static/backgroud/top_bg_sddx.png
  44. BIN
      card/static/backgroud/top_bg_sea.png
  45. BIN
      card/static/cardbg/shanda.png
  46. BIN
      card/static/cardbg/xfl4.png
  47. BIN
      card/static/cardbg/xfl5.png
  48. BIN
      card/static/common/aotizhongxin.png
  49. BIN
      card/static/common/award.png
  50. BIN
      card/static/common/baihuagongyuan.png
  51. BIN
      card/static/common/btn_dhjd.png
  52. BIN
      card/static/common/egg.png
  53. BIN
      card/static/common/ingame.gif
  54. BIN
      card/static/common/ingame2.gif
  55. BIN
      card/static/common/lingxiucheng.png
  56. BIN
      card/static/common/muniushan.png
  57. BIN
      card/static/common/nav.png
  58. BIN
      card/static/common/quanchenggongyuan.png
  59. BIN
      card/static/common/wslgwcs.png
  60. BIN
      card/static/logo/xfl2.png

+ 13 - 1
card/App.vue

@@ -48,13 +48,17 @@
 	}
 	
 	.uni-jct {
-		justify-content: start;
+		justify-content: flex-start;
 	}
 	
 	.uni-jcc {
 		justify-content: center;
 	}
 	
+	.uni-jce {
+		justify-content: flex-end;
+	}
+	
 	.uni-jcsa {
 		justify-content: space-around;
 	}
@@ -67,6 +71,14 @@
 		justify-content: space-evenly;
 	}
 	
+	.uni-ais {
+		align-items: flex-start;
+	}
+	
+	.uni-aie {
+		align-items: flex-end;
+	}
+	
 	.hidden {
 		visibility: hidden;
 	}

+ 15 - 12
card/common/api.js

@@ -3,8 +3,8 @@ export const apiServer = process.env.API_BASE_URL;
 // console.log("ossUrl", ossUrl);
 // console.log("apiServer", apiServer);
 
-export const token = '';
-// export const token = '0f6adcb8d72e5e44552dd70175609240';
+// export const token = '';
+export const token = '96ba3c924394934f7d30fa869a94ce0d';
 
 // 卡片基本信息查询
 export const apiCardBaseQuery = apiServer + 'CardBaseQuery';
@@ -57,7 +57,16 @@ export const apiUnReadMessageQuery = apiServer + 'UnReadMessageQuery';
 // 标记消息已读
 export const apiReadMessage = apiServer + 'ReadMessage';
 
+// 卡片对应地图列表详情查询
+export const apiMapListQuery = apiServer + 'MapListQuery';
 
+// 赛事总成绩统计查询
+export const apiCompStatisticQuery = apiServer + 'CompStatisticQuery';
+
+
+
+
+import tools from '/common/tools';
 
 // 检测request的返回值
 export function checkResCode(res) {
@@ -69,12 +78,9 @@ export function checkResCode(res) {
 			icon: 'none',
 			duration: 3000
 		});
+		
 		const url = `action://to_login/`;
-		if (tools) {
-			tools.appAction(url);
-		} else {
-			window.location.href = url;
-		}
+		tools.appAction(url);
 		return false;
 	} else {
 		uni.showToast({
@@ -98,12 +104,9 @@ export function checkToken(token) {
 			icon: 'none',
 			duration: 3000
 		});
+		
 		const url = `action://to_login/`;
-		if (tools) {
-			tools.appAction(url);
-		} else {
-			window.location.href = url;
-		}
+		tools.appAction(url);
 		return false;
 	}
 };

+ 1 - 1
card/common/define.js

@@ -25,5 +25,5 @@ export const defaultPopUpDataList = [
 			title: "基本标识",
 			img: "/static/common/jbbs.png",
 		}
-	},
+	}
 ];

+ 1 - 0
card/common/tools.js

@@ -2,6 +2,7 @@ var tools = {
 	
 	// 导航到彩图奔跑APP内的某个页面或执行APP内部的某些功能
 	appAction(url) {
+		console.log("appAction", url);
 		// console.log("getApp", getApp());
 		// getApp().$audio.destroy();
 		// getApp().$audio.pause();

+ 557 - 0
card/components/e-select/e-select-built-in.vue

@@ -0,0 +1,557 @@
+<template>
+  <view
+    class="e-select-box"
+    :style="{ width: width, minWidth: minWidth }">
+    <view
+      class="e-select"
+      :class="{ 'e-select-disabled': disabled }">
+      <view
+        class="e-select-input-box"
+		@click="inputClick ? toggleSelector() : ''"
+        >
+		<!-- @click="toggleSelector" -->
+        <!-- 微信小程序input组件在部分安卓机型上会出现文字重影,placeholder抖动问题,2019年时微信小程序就有这个问题,一直没修复,估计短时间内也别指望修复了 -->
+        <input
+          class="e-select-input-text"
+          :placeholder="placeholder"
+          placeholder-class="e-select-input-placeholder"
+          v-model="currentData"
+          @input="filter"
+          v-if="search && !disabled" />
+        <view
+          class="e-select-input-text"
+          :class="{
+            'e-select-input-placeholder': !(currentData || currentData === 0),
+          }"
+          v-else>
+          {{ currentData || currentData === 0 ? currentData : placeholder }}
+        </view>
+        <!-- 清空图标,用一个更大的盒子包裹图标,便于点击 -->
+        <view
+          class="e-select-icon"
+          @click.stop="clearVal"
+          v-if="currentData && clearable && !disabled">
+          <uni-icons
+            type="clear"
+            color="#e1e1e1"
+            size="16"></uni-icons>
+        </view>
+        <!-- 箭头图标,同上 -->
+        <view
+          class="e-select-icon"
+		  @click.stop="toggleSelector"
+          v-else>
+          <uni-icons
+            size="16"
+            color="#6A6A6A"
+            type="top"
+            class="arrowAnimation"
+            :class="showSelector ? 'e-select-top' : 'e-select-bottom'"></uni-icons>
+        </view>
+      </view>
+      <!-- 全屏遮罩-->
+      <view
+        class="e-select--mask"
+        v-if="showSelector"
+        @click.stop="toggleSelector" />
+      <!-- 选项列表 这里用v-show是因为微信小程序会报警告 [Component] slot "" is not found,v-if会导致开发工具不能正确识别到slot -->
+      <!-- https://developers.weixin.qq.com/community/minihome/doc/000c8295730700d1cd7c81b9656c00 -->
+      <view
+        class="e-select-selector"
+        :style="
+          position === 'top'
+            ? 'bottom: calc(0px + 42px)'
+            : 'top: calc(100% + 12px)'
+        "
+        v-show="showSelector">
+        <!-- 三角小箭头 -->
+        <view
+          :class="
+            position === 'top' ? 'e-popper-arrow-bottom' : 'e-popper-arrow'
+          "></view>
+        <scroll-view
+          scroll-y="true"
+          :scroll-top="scrollTop"
+          class="e-select-selector-scroll"
+          :style="{ maxHeight: maxHeight }"
+          :scroll-into-view="scrollToId"
+          :scroll-with-animation="scrollWithAnimation"
+          v-if="showSelector">
+          <view
+            class="e-select-selector-empty"
+            v-if="currentOptions.length === 0">
+            <text>{{ emptyTips }}</text>
+          </view>
+          <!-- 非空,渲染选项列表 -->
+          <view
+            v-else
+            class="e-select-selector-item"
+            :class="[
+              { highlight: currentData == item[props.text] },
+              {
+                'e-select-selector-item-disabled': item[props.disabled],
+              },
+            ]"
+            v-for="(item, index) in currentOptions"
+            :key="index"
+            @click="change(item, index)">
+            <view
+              id="scrollToId"
+              v-if="currentData == item[props.text]"></view>
+            <text>{{ item[props.text] }}</text>
+          </view>
+        </scroll-view>
+        <slot />
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'e-select',
+  data() {
+    return {
+      // 是否显示下拉选择列表
+      showSelector: false,
+      // 当前选项列表
+      currentOptions: [],
+      // 过滤后的选项列表
+      filterOptions: [],
+      // 当前值
+      currentData: '',
+      // 滚动高度
+      scrollTop: 0,
+      // 滚动至的id
+      scrollToId: 'scrollToId',
+      // 滚动动画
+      scrollWithAnimation: false,
+    };
+  },
+  props: {
+    // vue2 v-model传值方式
+    value: {
+      type: [String, Number],
+      default: '',
+    },
+    // vue3 v-model传值方式
+    modelValue: {
+      type: [String, Number],
+      default: '',
+    },
+    // 选项列表
+    options: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    // 选项列表自定义数据格式
+    props: {
+      type: Object,
+      default: () => {
+        return {
+          text: 'text',
+          value: 'value',
+          disabled: 'disabled',
+        };
+      },
+    },
+	// 是否允许输入框响应点击事件
+	inputClick: {
+	  type: Boolean,
+	  default: true,
+	},
+    // 占位文本
+    placeholder: {
+      type: String,
+      default: '请选择',
+    },
+    // 输入框宽度
+    width: {
+      type: String,
+      default: '100%',
+    },
+    // 输入框最小宽度
+    minWidth: {
+      type: String,
+      default: '120rpx',
+    },
+    // 选项列表悬浮框最大高度
+    maxHeight: {
+      type: String,
+      default: '160px',
+    },
+    // 选项列表空值占位空值占位
+    emptyTips: {
+      type: String,
+      default: '暂无选项',
+    },
+    // 是否可清空
+    clearable: {
+      type: Boolean,
+      default: false,
+    },
+    // 是否禁用
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
+    // 是否开启搜索
+    search: {
+      type: Boolean,
+      default: true,
+    },
+    // 是否开启搜索的滚动动画
+    animation: {
+      type: Boolean,
+      default: true,
+    },
+    // 悬浮框位置top/bottom
+    position: {
+      type: String,
+      default: 'bottom',
+    },
+    // 分页每页条数
+    pageSize: {
+      type: Number,
+      default: 0,
+    },
+    // 分页当前页数
+    pageIndex: {
+      type: Number,
+      default: 1,
+    },
+  },
+  watch: {
+    options: {
+      handler(val) {
+        this.filterOptions = val.slice();
+        this.initOptions();
+        this.initData();
+      },
+      immediate: true,
+      deep: true,
+    },
+    modelValue: {
+      handler() {
+        this.initData();
+      },
+      immediate: true,
+    },
+    value: {
+      handler() {
+        this.initData();
+      },
+      immediate: true,
+    },
+    pageSize() {
+      this.initOptions();
+    },
+    pageIndex() {
+      this.initOptions();
+    },
+  },
+  methods: {
+    /** 处理数据,此函数用于兼容vue2 vue3 */
+    initData() {
+      this.currentData = '';
+      // vue2
+      if (this.value || this.value === 0) {
+        for (let i = 0; i < this.options.length; i++) {
+          const item = this.options[i];
+          if (item[this.props.value] === this.value) {
+            this.currentData = item[this.props.text];
+            this.$emit('getText', this.currentData);
+            // 如果分页,初始化分页当前页数
+            if (this.pageSize && this.pageIndex) {
+              this.$emit('update:pageIndex', Math.floor(i / this.pageSize) + 1);
+            }
+            return;
+          }
+        }
+      }
+      // vue3
+      else if (this.modelValue || this.modelValue === 0) {
+        for (let i = 0; i < this.options.length; i++) {
+          const item = this.options[i];
+          if (item[this.props.value] === this.modelValue) {
+            this.currentData = item[this.props.text];
+            this.$emit('getText', this.currentData);
+            if (this.pageSize && this.pageIndex) {
+              this.$emit('update:pageIndex', Math.floor(i / this.pageSize) + 1);
+            }
+            return;
+          }
+        }
+      }
+    },
+    /** 初始化选项列表 */
+    initOptions() {
+      // 设置分页情况下列表
+      if (this.pageSize && this.pageIndex) {
+        this.currentOptions = this.filterOptions.slice(
+          (this.pageIndex - 1) * this.pageSize,
+          this.pageIndex * this.pageSize
+        );
+      } else {
+        this.currentOptions = this.filterOptions;
+      }
+      // scrollTop变化,才能触发滚动顶部,再低如0.01则不能触发,真神奇
+      this.scrollTop = 0.1;
+      this.$nextTick(() => {
+        this.scrollTop = 0;
+      });
+    },
+    /** 过滤选项列表,会自动回到顶部 */
+    filter() {
+      // 回到分页第一页
+      this.$emit('update:pageIndex', 1);
+      this.$emit('getText', this.currentData);
+      if (this.currentData) {
+        this.filterOptions = this.options.filter((item) => {
+          return item[this.props.text].indexOf(this.currentData) > -1;
+        });
+        this.$emit('update:total', this.filterOptions.length);
+      }
+      // 等待update:pageIndex事件执行完成
+      setTimeout(() => {
+        this.initOptions();
+      }, 0);
+    },
+    /** 改变值 */
+    change(item, index) {
+      if (item[this.props.disabled]) return;
+      const data = {
+        index,
+        ...item,
+      };
+      this.$emit('change', data);
+      this.emit(data);
+      this.toggleSelector();
+    },
+    /** 传递父组件值 */
+    emit(item) {
+      this.$emit('input', item[this.props.value]);
+      this.$emit('update:modelValue', item[this.props.value]);
+    },
+    /** 清空值 */
+    clearVal() {
+      this.$emit('change', 'clear');
+      this.$emit('input', '');
+      this.$emit('update:modelValue', '');
+    },
+    /** 切换下拉显示 */
+    toggleSelector() {
+      if (this.disabled) return;
+      this.showSelector = !this.showSelector;
+      if (this.showSelector) {
+        // 设计理念:只在filter时触发滚动动画,因为每次打开就触发,用户体验不好
+        if (this.animation) {
+          setTimeout(() => {
+            // 开启滚动动画
+            this.scrollWithAnimation = true;
+          }, 100);
+        }
+      } else {
+        // 关闭时重新初始化
+        this.filterOptions = this.options.slice();
+        this.initData();
+        this.initOptions();
+        this.$emit('update:total', this.options.length);
+        this.scrollWithAnimation = false;
+      }
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.e-select-box {
+  display: flex;
+  align-items: center;
+  width: 100%;
+  box-sizing: border-box;
+  cursor: pointer;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+.e-select {
+  width: 100%;
+  border-radius: 4px;
+  box-sizing: border-box;
+  display: flex;
+  align-items: center;
+  user-select: none;
+  position: relative;
+  border: 1px solid #dcdfe6;
+}
+
+.e-select-disabled {
+  background-color: #f5f7fa;
+  cursor: not-allowed;
+}
+
+.e-select-input-box {
+  width: 100%;
+  padding: 0px 20rpx;
+  min-height: 34px;
+  position: relative;
+  display: flex;
+  flex: 1;
+  flex-direction: row;
+  align-items: center;
+
+  .e-select-input-text {
+    color: #303030;
+    width: 100%;
+    color: #333;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    -o-text-overflow: ellipsis;
+    overflow: hidden;
+    font-size: 28rpx;
+  }
+
+  .e-select-input-placeholder {
+    font-size: 28rpx;
+    color: #999999;
+  }
+
+  .e-select-icon {
+    width: 50px;
+    padding-right: 3px;
+    height: 100%;
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+  }
+
+  .arrowAnimation {
+    transition: transform 0.3s;
+  }
+
+  // .top {
+  .e-select-top {
+    transform: rotateZ(0deg);
+  }
+
+  // .bottom {
+  .e-select-bottom {
+    transform: rotateZ(180deg);
+  }
+}
+
+.e-select--mask {
+  position: fixed;
+  top: 0;
+  bottom: 0;
+  right: 0;
+  left: 0;
+  z-index: 999;
+}
+
+.e-select-selector {
+  box-sizing: border-box;
+  position: absolute;
+  left: 0;
+  width: 100%;
+  background-color: #ffffff;
+  border: 1px solid #ebeef5;
+  border-radius: 6px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  z-index: 999;
+  padding: 4px 2px;
+  transition: all 1s;
+
+  .e-select-selector-scroll {
+    box-sizing: border-box;
+
+    .e-select-selector-empty,
+    .e-select-selector-item {
+      display: flex;
+      cursor: pointer;
+      line-height: 35rpx;
+      font-size: 28rpx;
+      text-align: left;
+      padding: 15rpx 10px;
+    }
+
+    .e-select-selector-item:hover {
+      background-color: #f9f9f9;
+    }
+
+    .e-select-selector-empty:last-child,
+    .e-select-selector-item:last-child {
+      border-bottom: none;
+    }
+
+    .e-select-selector-item-disabled {
+      color: #b1b1b1;
+      cursor: not-allowed;
+    }
+
+    .highlight {
+      color: #409eff;
+      font-weight: bold;
+      background-color: #f5f7fa;
+      border-radius: 3px;
+    }
+  }
+}
+
+.e-popper-arrow,
+.e-popper-arrow::after,
+.e-popper-arrow-bottom,
+.e-popper-arrow-bottom::after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  left: 50%;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 6px;
+}
+
+.e-popper-arrow {
+  filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+  top: -6px;
+  left: 50%;
+  transform: translateX(-50%);
+  margin-right: 3px;
+  border-top-width: 0;
+  border-bottom-color: #ebeef5;
+}
+
+.e-popper-arrow::after {
+  content: ' ';
+  top: 1px;
+  margin-left: -6px;
+  border-top-width: 0;
+  border-bottom-color: #fff;
+}
+
+.e-popper-arrow-bottom {
+  filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+  bottom: -6px;
+  left: 50%;
+  transform: translateX(-50%);
+  margin-right: 3px;
+  border-bottom-width: 0;
+  border-top-color: #ebeef5;
+}
+
+.e-popper-arrow-bottom::after {
+  content: ' ';
+  bottom: 1px;
+  margin-left: -6px;
+  border-bottom-width: 0;
+  border-top-color: #fff;
+}
+
+/* 设置定位元素的位置 */
+#scrollToId {
+  margin-top: -15rpx;
+}
+</style>

+ 193 - 0
card/components/e-select/e-select.vue

@@ -0,0 +1,193 @@
+<template>
+  <e-select-built-in
+    v-model="selectData"
+    :options="options"
+    :props="props"
+	:inputClick="inputClick"
+    :placeholder="placeholder"
+    :width="width"
+    :minWidth="minWidth"
+    :maxHeight="maxHeight"
+    :emptyTips="emptyTips"
+    :clearable="clearable"
+    :disabled="disabled"
+    :search="search"
+    :animation="animation"
+    :position="position"
+    :pageSize="pageSize"
+    :pageIndex="pageIndex"
+    @update:pageIndex="updatePageIndex"
+    @update:total="updateTotal"
+    @change="changeSelect">
+    <uni-pagination-built-in
+      v-if="pageSize"
+      show-icon="true"
+      :total="total"
+      :pageSize="pageSize"
+      :current="pageIndex"
+      @change="changePage"></uni-pagination-built-in>
+  </e-select-built-in>
+</template>
+
+<script>
+import eSelectBuiltIn from './e-select-built-in.vue';
+import uniPaginationBuiltIn from './uni-pagination-built-in/uni-pagination-built-in.vue';
+export default {
+  components: {
+    eSelectBuiltIn,
+    uniPaginationBuiltIn,
+  },
+  props: {
+    // vue2 v-model传值方式
+    value: {
+      type: [String, Number],
+      default: '',
+    },
+    // vue3 v-model传值方式
+    modelValue: {
+      type: [String, Number],
+      default: '',
+    },
+    // 选项列表
+    options: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    // 选项列表自定义数据格式
+    props: {
+      type: Object,
+      default: () => {
+        return {
+          text: 'text',
+          value: 'value',
+          disabled: 'disabled',
+        };
+      },
+    },
+	// 是否允许输入框响应点击事件
+	inputClick: {
+	  type: Boolean,
+	  default: true,
+	},
+    // 占位文本
+    placeholder: {
+      type: String,
+      default: '请选择',
+    },
+    // 输入框宽度
+    width: {
+      type: String,
+      default: '100%',
+    },
+    // 输入框最小宽度
+    minWidth: {
+      type: String,
+      default: '120rpx',
+    },
+    // 选项列表悬浮框最大高度
+    maxHeight: {
+      type: String,
+      default: '160px',
+    },
+    // 选项列表空值占位空值占位
+    emptyTips: {
+      type: String,
+      default: '暂无选项',
+    },
+    // 是否可清空
+    clearable: {
+      type: Boolean,
+      default: false,
+    },
+    // 是否禁用
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
+    // 是否开启搜索
+    search: {
+      type: Boolean,
+      default: true,
+    },
+    // 是否开启搜索的滚动动画
+    animation: {
+      type: Boolean,
+      default: true,
+    },
+    // 悬浮框位置top/bottom
+    position: {
+      type: String,
+      default: 'bottom',
+    },
+    // 分页每页条数
+    pageSize: {
+      type: Number,
+      default: 0,
+    },
+  },
+  data() {
+    return {
+      // 前端分页,总数就是下拉列表总数,不应由用户来控制,放在组件内部
+      total: 0,
+      // 前端分页,当前分页不应由用户来控制,放在组件内部
+      pageIndex: 1,
+      selectData: '',
+    };
+  },
+  watch: {
+    options: {
+      handler(val) {
+        this.total = val.length;
+      },
+      immediate: true,
+      deep: true,
+    },
+    modelValue: {
+      handler() {
+        this.initData();
+      },
+      immediate: true,
+    },
+    value: {
+      handler() {
+        this.initData();
+      },
+      immediate: true,
+    },
+    selectData: {
+      handler(val) {
+        this.$emit('input', val);
+        this.$emit('update:modelValue', val);
+      },
+    },
+  },
+  methods: {
+    /** 处理数据,此函数用于兼容vue2 vue3 */
+    initData() {
+      // vue2
+      if (this.value || this.value === 0) {
+        this.selectData = this.value;
+      }
+      // vue3
+      else if (this.modelValue || this.modelValue === 0) {
+        this.selectData = this.modelValue;
+      }
+    },
+    updatePageIndex(pageIndex) {
+      this.pageIndex = pageIndex;
+    },
+    updateTotal(total) {
+      this.total = total;
+    },
+    changePage(data) {
+      this.pageIndex = data.current;
+      this.$emit('changePage', data);
+    },
+    changeSelect(data) {
+      // this.$emit('change', data);
+    },
+  },
+};
+</script>

+ 5 - 0
card/components/e-select/uni-pagination-built-in/i18n/en.json

@@ -0,0 +1,5 @@
+{
+	"uni-pagination.prevText": "prev",
+	"uni-pagination.nextText": "next",
+	"uni-pagination.piecePerPage": "piece/page"
+}

+ 5 - 0
card/components/e-select/uni-pagination-built-in/i18n/es.json

@@ -0,0 +1,5 @@
+{
+	"uni-pagination.prevText": "anterior",
+	"uni-pagination.nextText": "prxima",
+	"uni-pagination.piecePerPage": "Art¨ªculo/P¨¢gina"
+}

+ 5 - 0
card/components/e-select/uni-pagination-built-in/i18n/fr.json

@@ -0,0 +1,5 @@
+{
+	"uni-pagination.prevText": "précédente",
+	"uni-pagination.nextText": "suivante",
+	"uni-pagination.piecePerPage": "Articles/Pages"
+}

+ 12 - 0
card/components/e-select/uni-pagination-built-in/i18n/index.js

@@ -0,0 +1,12 @@
+import en from './en.json'
+import es from './es.json'
+import fr from './fr.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	es,
+	fr,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}

+ 5 - 0
card/components/e-select/uni-pagination-built-in/i18n/zh-Hans.json

@@ -0,0 +1,5 @@
+{
+	"uni-pagination.prevText": "上一页",
+	"uni-pagination.nextText": "下一页",
+	"uni-pagination.piecePerPage": "条/页"
+}

+ 5 - 0
card/components/e-select/uni-pagination-built-in/i18n/zh-Hant.json

@@ -0,0 +1,5 @@
+{
+	"uni-pagination.prevText": "上一頁",
+	"uni-pagination.nextText": "下一頁",
+	"uni-pagination.piecePerPage": "條/頁"
+}

+ 501 - 0
card/components/e-select/uni-pagination-built-in/uni-pagination-built-in.vue

@@ -0,0 +1,501 @@
+<template>
+  <view class="uni-pagination">
+    <!-- #ifndef MP -->
+    <picker
+      v-if="showPageSize === true || showPageSize === 'true'"
+      class="select-picker"
+      mode="selector"
+      :value="pageSizeIndex"
+      :range="pageSizeRange"
+      @change="pickerChange"
+      @cancel="pickerClick"
+      @click.native="pickerClick">
+      <button type="default" size="mini" :plain="true">
+        <text>{{ pageSizeRange[pageSizeIndex] }} {{ piecePerPage }}</text>
+        <uni-icons
+          class="select-picker-icon"
+          type="arrowdown"
+          size="12"
+          color="#999"></uni-icons>
+      </button>
+    </picker>
+    <!-- #endif -->
+    <!-- #ifndef APP-NVUE -->
+    <view class="uni-pagination__total is-phone-hide">共 {{ total }} 条</view>
+    <!-- #endif -->
+    <view
+      class="uni-pagination__btn"
+      :class="
+        currentIndex === 1
+          ? 'uni-pagination--disabled'
+          : 'uni-pagination--enabled'
+      "
+      :hover-class="currentIndex === 1 ? '' : 'uni-pagination--hover'"
+      :hover-start-time="20"
+      :hover-stay-time="70"
+      @click="clickLeft">
+      <template v-if="showIcon === true || showIcon === 'true'">
+        <uni-icons color="#666" size="16" type="left" />
+      </template>
+      <template v-else>
+        <text class="uni-pagination__child-btn">{{ prevPageText }}</text>
+      </template>
+    </view>
+    <view class="uni-pagination__num uni-pagination__num-flex-none">
+      <view class="uni-pagination__num-current">
+        <text
+          class="uni-pagination__num-current-text is-pc-hide current-index-text">
+          {{ currentIndex }}
+        </text>
+        <text class="uni-pagination__num-current-text is-pc-hide">
+          /{{ maxPage || 0 }}
+        </text>
+        <!-- #ifndef APP-NVUE -->
+        <view
+          v-for="(item, index) in paper"
+          :key="index"
+          :class="{ 'page--active': item === currentIndex }"
+          class="uni-pagination__num-tag tag--active is-phone-hide"
+          @click.top="selectPage(item, index)">
+          <text>{{ item }}</text>
+        </view>
+        <!-- #endif -->
+      </view>
+    </view>
+    <view
+      class="uni-pagination__btn"
+      :class="
+        currentIndex >= maxPage
+          ? 'uni-pagination--disabled'
+          : 'uni-pagination--enabled'
+      "
+      :hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'"
+      :hover-start-time="20"
+      :hover-stay-time="70"
+      @click="clickRight">
+      <template v-if="showIcon === true || showIcon === 'true'">
+        <uni-icons color="#666" size="16" type="right" />
+      </template>
+      <template v-else>
+        <text class="uni-pagination__child-btn">{{ nextPageText }}</text>
+      </template>
+    </view>
+  </view>
+</template>
+
+<script>
+/**
+ * Pagination 分页器
+ * @description 分页器组件,用于展示页码、请求数据等
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=32
+ * @property {String} prevText 左侧按钮文字
+ * @property {String} nextText 右侧按钮文字
+ * @property {String} piecePerPageText 条/页文字
+ * @property {Number} current 当前页
+ * @property {Number} total 数据总量
+ * @property {Number} pageSize 每页数据量
+ * @property {Boolean} showIcon = [true|false] 是否以 icon 形式展示按钮
+ * @property {Boolean} showPageSize = [true|false] 是否展示每页条数
+ * @property {Array} pageSizeRange = [20, 50, 100, 500] 每页条数选框
+ * @event {Function} change 点击页码按钮时触发 ,e={type,current} current为当前页,type值为:next/prev,表示点击的是上一页还是下一个
+ * * @event {Function} pageSizeChange 当前每页条数改变时触发 ,e={pageSize} pageSize 为当前所选的每页条数
+ */
+
+import { initVueI18n } from "@dcloudio/uni-i18n";
+import messages from "./i18n/index.js";
+const { t } = initVueI18n(messages);
+export default {
+  name: "UniPagination",
+  emits: ["update:modelValue", "input", "change", "pageSizeChange"],
+  props: {
+    value: {
+      type: [Number, String],
+      default: 1,
+    },
+    modelValue: {
+      type: [Number, String],
+      default: 1,
+    },
+    prevText: {
+      type: String,
+    },
+    nextText: {
+      type: String,
+    },
+    piecePerPageText: {
+      type: String,
+    },
+    current: {
+      type: [Number, String],
+      default: 1,
+    },
+    total: {
+      // 数据总量
+      type: [Number, String],
+      default: 0,
+    },
+    pageSize: {
+      // 每页数据量
+      type: [Number, String],
+      default: 10,
+    },
+    showIcon: {
+      // 是否以 icon 形式展示按钮
+      type: [Boolean, String],
+      default: false,
+    },
+    showPageSize: {
+      // 是否以 icon 形式展示按钮
+      type: [Boolean, String],
+      default: false,
+    },
+    pagerCount: {
+      type: Number,
+      default: 7,
+    },
+    pageSizeRange: {
+      type: Array,
+      default: () => [20, 50, 100, 500],
+    },
+  },
+  data() {
+    return {
+      pageSizeIndex: 0,
+      currentIndex: 1,
+      paperData: [],
+      pickerShow: false,
+    };
+  },
+  computed: {
+    piecePerPage() {
+      return this.piecePerPageText || t("uni-pagination.piecePerPage");
+    },
+    prevPageText() {
+      return this.prevText || t("uni-pagination.prevText");
+    },
+    nextPageText() {
+      return this.nextText || t("uni-pagination.nextText");
+    },
+    maxPage() {
+      let maxPage = 1;
+      let total = Number(this.total);
+      let pageSize = Number(this.pageSize);
+      if (total && pageSize) {
+        maxPage = Math.ceil(total / pageSize);
+      }
+      return maxPage;
+    },
+    paper() {
+      const num = this.currentIndex;
+      // TODO 最大页数
+      const pagerCount = this.pagerCount;
+      // const total = 181
+      const total = this.total;
+      const pageSize = this.pageSize;
+      let totalArr = [];
+      let showPagerArr = [];
+      let pagerNum = Math.ceil(total / pageSize);
+      for (let i = 0; i < pagerNum; i++) {
+        totalArr.push(i + 1);
+      }
+      showPagerArr.push(1);
+      const totalNum = totalArr[totalArr.length - (pagerCount + 1) / 2];
+      totalArr.forEach((item, index) => {
+        if ((pagerCount + 1) / 2 >= num) {
+          if (item < pagerCount + 1 && item > 1) {
+            showPagerArr.push(item);
+          }
+        } else if (num + 2 <= totalNum) {
+          if (
+            item > num - (pagerCount + 1) / 2 &&
+            item < num + (pagerCount + 1) / 2
+          ) {
+            showPagerArr.push(item);
+          }
+        } else {
+          if (
+            (item > num - (pagerCount + 1) / 2 ||
+              pagerNum - pagerCount < item) &&
+            item < totalArr[totalArr.length - 1]
+          ) {
+            showPagerArr.push(item);
+          }
+        }
+      });
+      if (pagerNum > pagerCount) {
+        if ((pagerCount + 1) / 2 >= num) {
+          showPagerArr[showPagerArr.length - 1] = "...";
+        } else if (num + 2 <= totalNum) {
+          showPagerArr[1] = "...";
+          showPagerArr[showPagerArr.length - 1] = "...";
+        } else {
+          showPagerArr[1] = "...";
+        }
+        showPagerArr.push(totalArr[totalArr.length - 1]);
+      } else {
+        if ((pagerCount + 1) / 2 >= num) {
+        } else if (num + 2 <= totalNum) {
+        } else {
+          showPagerArr.shift();
+          showPagerArr.push(totalArr[totalArr.length - 1]);
+        }
+      }
+
+      return showPagerArr;
+    },
+  },
+  watch: {
+    current: {
+      immediate: true,
+      handler(val, old) {
+        if (val < 1) {
+          this.currentIndex = 1;
+        } else {
+          this.currentIndex = val;
+        }
+      },
+    },
+    value: {
+      immediate: true,
+      handler(val) {
+        if (Number(this.current) !== 1) return;
+        if (val < 1) {
+          this.currentIndex = 1;
+        } else {
+          this.currentIndex = val;
+        }
+      },
+    },
+    pageSizeIndex(val) {
+      this.$emit("pageSizeChange", this.pageSizeRange[val]);
+    },
+  },
+  methods: {
+    pickerChange(e) {
+      this.pageSizeIndex = e.detail.value;
+      this.pickerClick();
+    },
+    pickerClick() {
+      // #ifdef H5
+      const body = document.querySelector("body");
+      if (!body) return;
+
+      const className = "uni-pagination-picker-show";
+      this.pickerShow = !this.pickerShow;
+
+      if (this.pickerShow) {
+        body.classList.add(className);
+      } else {
+        setTimeout(() => body.classList.remove(className), 300);
+      }
+      // #endif
+    },
+    // 选择标签
+    selectPage(e, index) {
+      if (parseInt(e)) {
+        this.currentIndex = e;
+        this.change("current");
+      } else {
+        let pagerNum = Math.ceil(this.total / this.pageSize);
+        // let pagerNum = Math.ceil(181 / this.pageSize)
+        // 上一页
+        if (index <= 1) {
+          if (this.currentIndex - 5 > 1) {
+            this.currentIndex -= 5;
+          } else {
+            this.currentIndex = 1;
+          }
+          return;
+        }
+        // 下一页
+        if (index >= 6) {
+          if (this.currentIndex + 5 > pagerNum) {
+            this.currentIndex = pagerNum;
+          } else {
+            this.currentIndex += 5;
+          }
+          return;
+        }
+      }
+    },
+    clickLeft() {
+      if (Number(this.currentIndex) === 1) {
+        return;
+      }
+      this.currentIndex -= 1;
+      this.change("prev");
+    },
+    clickRight() {
+      if (Number(this.currentIndex) >= this.maxPage) {
+        return;
+      }
+      this.currentIndex += 1;
+      this.change("next");
+    },
+    change(e) {
+      this.$emit("input", this.currentIndex);
+      this.$emit("update:modelValue", this.currentIndex);
+      this.$emit("change", {
+        type: e,
+        current: this.currentIndex,
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+$uni-primary: #2979ff !default;
+.uni-pagination {
+  /* #ifndef APP-NVUE */
+  display: flex;
+  /* #endif */
+  position: relative;
+  overflow: hidden;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.uni-pagination__total {
+  font-size: 14px;
+  color: #999;
+  margin-right: 15px;
+}
+
+.uni-pagination__btn {
+  /* #ifndef APP-NVUE */
+  display: flex;
+  cursor: pointer;
+  /* #endif */
+  padding: 0 8px;
+  line-height: 30px;
+  font-size: 12px;
+  position: relative;
+  background-color: #f0f0f0;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  text-align: center;
+  border-radius: 5px;
+  // border-width: 1px;
+  // border-style: solid;
+  // border-color: $uni-border-color;
+}
+
+.uni-pagination__child-btn {
+  /* #ifndef APP-NVUE */
+  display: flex;
+  /* #endif */
+  font-size: 12px;
+  position: relative;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  text-align: center;
+  color: #666;
+  font-size: 12px;
+}
+
+.uni-pagination__num {
+  /* #ifndef APP-NVUE */
+  display: flex;
+  /* #endif */
+  flex: 1;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  height: 30px;
+  line-height: 30px;
+  font-size: 12px;
+  color: #666;
+  margin: 0 5px;
+}
+
+.uni-pagination__num-tag {
+  /* #ifdef H5 */
+  cursor: pointer;
+  min-width: 30px;
+  /* #endif */
+  margin: 0 5px;
+  height: 30px;
+  text-align: center;
+  line-height: 30px;
+  // border: 1px red solid;
+  color: #999;
+  border-radius: 4px;
+  // border-width: 1px;
+  // border-style: solid;
+  // border-color: $uni-border-color;
+}
+
+.uni-pagination__num-current {
+  /* #ifndef APP-NVUE */
+  display: flex;
+  /* #endif */
+  flex-direction: row;
+}
+
+.uni-pagination__num-current-text {
+  font-size: 15px;
+}
+
+.current-index-text {
+  color: $uni-primary;
+}
+
+.uni-pagination--enabled {
+  color: #333333;
+  opacity: 1;
+}
+
+.uni-pagination--disabled {
+  opacity: 0.5;
+  /* #ifdef H5 */
+  cursor: default;
+  /* #endif */
+}
+
+.uni-pagination--hover {
+  color: rgba(0, 0, 0, 0.6);
+  background-color: #eee;
+}
+
+.tag--active:hover {
+  color: $uni-primary;
+}
+
+.page--active {
+  color: #fff;
+  background-color: $uni-primary;
+}
+
+.page--active:hover {
+  color: #fff;
+}
+
+/* #ifndef APP-NVUE */
+.is-pc-hide {
+  display: block;
+}
+
+.is-phone-hide {
+  display: none;
+}
+
+// @media screen and (min-width: 450px) {
+//   .is-pc-hide {
+//     display: none;
+//   }
+
+//   .is-phone-hide {
+//     display: block;
+//   }
+
+//   .uni-pagination__num-flex-none {
+//     flex: none;
+//   }
+// }
+
+/* #endif */
+</style>

+ 136 - 0
card/components/my-pathList/my-pathList.vue

@@ -0,0 +1,136 @@
+<template>
+	<view class="main-path uni-row" :style="style ? style : 'justify-content: space-evenly;'" v-for="num of pathListLen" :key="'row-' + num">
+		<template v-for="(item, index) in pathList['row'+ num]" :key="'row-' + num + '-' + index">
+			<view v-if="item.type == 1 || item.type == 2">
+				<image mode="aspectFit" class="pathimg" :src="item.img" @click="onPathImgClick(item)">
+				</image>
+			</view>
+			<view v-if="item.type == 3" class="path-nav uni-row uni-aie">
+				<image mode="aspectFit" class="pathimg2" :src="item.pathImg" @click="onPathImgClick(item, 'path')">
+				</image>
+				<view class="uni-column">
+					<image mode="aspectFit" class="navimg" :src="item.navImg" @click="onPathImgClick(item, 'nav')"></image>
+					<text class="navtext">(导航)</text>
+				</view>
+			</view>
+		</template>
+		<view v-if="showLine && num < pathListLen" class="line"></view>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	
+	export default {
+		name:"my-pathList",
+		props: {
+			pathList: {},
+			mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+			showLine: false	,// 是否显示线条
+			style: ""
+		},
+		data() {
+			return {
+				navPoint: {},
+			};
+		},
+		computed: {
+			pathListLen() {
+				return Object.keys(this.pathList).length;
+			}
+		},
+		methods: {
+			onPathImgClick(item, type='') {
+				//item.type 1: 比赛路线  2: 导航到指定地点
+				if (item.type == 1) {
+					this.dealPathClick(item);
+				} else if (item.type == 2) {
+					this.dealNavClick(item);
+				} else if (item.type == 3) {
+					if (type == 'path') {
+						this.dealPathClick(item);
+					} else if (type == 'nav') {
+						this.dealNavClick(item);
+					}
+				}
+			},
+			dealPathClick(item) {
+				// 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				if (this.mcState == 1) {
+					const url = `action://to_detail/?id=${item.path.ocaId}&matchType=${item.path.mcType}`;
+					// window.location.href = url;
+					tools.appAction(url);
+				} else if (this.mcState == 0) {
+					uni.showToast({
+						title: '比赛尚未开始',
+						icon: 'none',
+						duration: 3000
+					});
+				} else if (this.mcState == 2) {
+					uni.showToast({
+						title: '比赛已结束',
+						icon: 'none',
+						duration: 3000
+					});
+				}
+			},
+			dealNavClick(item) {
+				this.navPoint = item.point;
+				// this.$refs.mypopupmap.popupOpen();
+				
+				const url =
+					`action://to_map_app?title=${this.navPoint.name}&latitude=${this.navPoint.latitude}&longitude=${this.navPoint.longitude}`;
+				// window.location.href = url;
+				tools.appAction(url);
+			}
+		}
+	}
+</script>
+
+<style scoped>
+
+	.pathimg {
+		width: 127px;
+		height: 115px;
+	}
+
+	.pathimg2 {
+		width: 106px;
+		height: 80px;
+	}
+
+	.navimg {
+		width: 25px;
+		height: 25px;
+	}
+
+	.navtext {
+		font-weight: 500;
+		color: #aaaaaa;
+		font-size: 10px;
+		font-family: Source Han Sans CN;
+	}
+
+	.main-path {
+		width: 90%;
+		margin-top: 10px;
+		margin-bottom: 10px;
+		flex-wrap: wrap;
+		/* justify-content: flex-start; */
+		/* justify-content: space-evenly; */
+	}
+	
+	.path-nav {
+		width: 50%;
+		justify-content: center;
+	}
+	
+	.line {
+		width: 100%;
+		height: 0px;
+		margin: 20px 5% 0 5%;
+		border: 1px dashed;
+		border-color: #c6c6c6;
+	}
+	
+</style>

+ 1 - 1
card/components/my-popup-map/my-popup-map.vue

@@ -88,7 +88,7 @@
 		}
 	}
 </script>
-<style lang="scss">
+<style lang="scss" scoped>
 	.uni-popup-share {
 		background-color: #fff;
 		border-top-left-radius: 11px;

+ 24 - 4
card/components/my-popup/my-popup.vue

@@ -6,7 +6,7 @@
 				:interval="5000">
 				<swiper-item v-for="(item, index) in dataList" :key="index">
 					<!-- 标题 + 图片 + 活动时间 + 活动简介 -->
-					<view class="swiper-item-view uni-column" v-if="item.type == 1">
+					<view v-if="item.type == 1" class="swiper-item-view uni-column">
 						<text class="swiper-item-title">{{item.data.title}}</text>
 						<image mode="aspectFit" class="swiper-item-image" :src="item.data.img"></image>
 						<view class="swiper-item-time uni-row">
@@ -22,7 +22,7 @@
 					</view>
 
 					<!-- 标题 + 图片 -->
-					<view class="swiper-item-view uni-column" v-if="item.type == 2">
+					<view v-if="item.type == 2" class="swiper-item-view uni-column">
 						<text class="swiper-item-title">{{item.data.title}}</text>
 						<image mode="aspectFit" style="height: 474rpx; margin-bottom: 50rpx;" :src="item.data.img">
 						</image>
@@ -32,7 +32,7 @@
 					</view>
 
 					<!-- 标题 + 图片 + 活动简介 -->
-					<view class="swiper-item-view swiper-item-view-bg uni-column" v-if="item.type == 3">
+					<view v-if="item.type == 3" class="swiper-item-view swiper-item-view-bg uni-column">
 						<text class="swiper-item-title">{{item.data.title}}</text>
 						<image mode="aspectFit" style="height: 280rpx; margin-top: 50rpx;" :src="item.data.img"></image>
 						<text class="swiper-item-content2">{{item.data.content}}</text>
@@ -42,7 +42,7 @@
 					</view>
 
 					<!-- 标题 + 图片 + 二维码 -->
-					<view class="swiper-item-view swiper-item-view-bg2 uni-jct uni-column" v-if="item.type == 4">
+					<view v-if="item.type == 4" class="swiper-item-view swiper-item-view-bg2 uni-jct uni-column">
 						<text class="swiper-item-title">{{item.data.title}}</text>
 						<image mode="aspectFit" style="height: 260rpx; margin-top: 10rpx;" :src="item.data.img"></image>
 						<text class="swiper-item-content3">{{item.data.content}}</text>
@@ -60,6 +60,16 @@
 							续</button>
 						<button v-else class="swiper-item-button" @click="popupClose">关 闭</button>
 					</view>
+					
+					<!-- 标题 + 图片(点击图片打开地图APP进行地点定位) -->
+					<view v-if="item.type == 5" class="swiper-item-view uni-column">
+						<text class="swiper-item-title">{{item.data.title}}</text>
+						<image mode="aspectFit" style="height: 474rpx; margin-bottom: 50rpx;" :src="item.data.img" @click="dealNavClick(item.data.point)">
+						</image>
+						<button v-if="index < dataList.length - 1" class="swiper-item-button" @click="swiperNext">继
+							续</button>
+						<button v-else class="swiper-item-button" @click="popupClose">确 定</button>
+					</view>
 
 				</swiper-item>
 			</swiper>
@@ -115,6 +125,12 @@
 				this.isOpen = false;
 				this.$emit('popup-close');
 			},
+			dealNavClick(navPoint) {
+				const url =
+					`action://to_map_app?title=${navPoint.name}&latitude=${navPoint.latitude}&longitude=${navPoint.longitude}`;
+				window.location.href = url;
+				// tools.appAction(url);
+			}
 			// getTeamName(teamType, teamIndex) {
 			// 	return teamName[teamType][teamIndex];
 			// },
@@ -244,4 +260,8 @@
 	::v-deep .uni-swiper-dots-horizontal {
 		bottom: 200rpx;
 	}
+	
+	// ::v-deep .uni-swiper-dot-active {
+	// 	background: #ff870e !important;
+	// }
 </style>

+ 13 - 3
card/components/my-ranklist/my-ranklist.vue

@@ -6,11 +6,15 @@
 				<text class="item-rankNum"
 					:class="getMedalClass(item.rankNum)">{{item.rankNum > 0 ? item.rankNum : '--'}}</text>
 				<view class="item-detail uni-row">
-					<text
-						class="item-userName">{{ teamType >= 0 ? getTeamName(teamType, item.userName) : item.userName}}</text>
+					<view class="uni-row">
+						<text class="item-userName">{{ teamType >= 0 ? getTeamName(teamType, item.userName) : item.userName}}</text>
+						<image class="item-inGame" v-if="item.isInGame == 1" mode="aspectFit" src="/static/common/ingame.gif"></image>
+					</view>
 					<text class="item-totalTime" v-if="rankType == 'totalDistance'">{{fmtDistanct(item.inRankNum)}} km</text>
 					<text class="item-totalTime" v-else-if="rankType == 'fastPace'">{{fmtPace(item.inRankNum)}}</text>
+					<text class="item-totalTime" v-else-if="rankType == 'rightAnswerPer'">{{item.inRankNum}}%</text>
 					<text class="item-totalTime" v-else-if="rankType == 'totalCp' || rankType == 'totalSysPoint'">{{item.inRankNum}} 个</text>
+					<text class="item-totalTime" v-else-if="rankType == 'speed'">{{fmtTime(item.inRankNum)}}</text>
 					<text class="item-totalTime" v-else>{{fmtTime(item.totalTime)}}</text>
 				</view>
 			</template>
@@ -32,7 +36,7 @@
 				type: Number,
 				default: -1
 			},
-			rankType: {	// totalDistance:总距离 totalCp:打点数 totalSysPoint:百味豆 fastPace:配速
+			rankType: {	// totalDistance:总距离 totalCp:打点数 totalSysPoint:百味豆 fastPace:配速 rightAnswerPer:答题正确率 speed:速度
 				type: String,
 				default: ""
 			},
@@ -275,6 +279,12 @@
 		font-size: 30rpx;
 	}
 
+	.item-inGame {
+		width: 36rpx;
+		height: 60rpx;
+		margin-left: 20rpx;
+	}
+
 	.item-totalTime {
 		font-size: 26rpx;
 		font-weight: 550;

+ 208 - 0
card/components/my-tab/my-tab.vue

@@ -0,0 +1,208 @@
+<template>
+	<view class="tab uni-row" :style="'font-size: ' + fontSize + 'px;'">
+		<template v-for="(item,index) in tabItems" :key="index">
+			<text v-if="typeof item == 'string'" :class="getClassList(index)" :style="getTextStyle(index)" @click="onTabClick(index)">{{item}}</text>
+			<e-select v-if="typeof item == 'object'" :style="getSelectStyle()" v-model="item.selectValue" 
+				:options="item.data" :search="false" :inputClick="false" :clearable="false" :class="getClassList(index)"
+				@click="onTabClick(index)" @getText="getESelectText" @change="eSelectChange"></e-select>
+		</template>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "my-tab",
+		props: {
+			initActIndex: {
+				type: Number,
+				default: 0
+			},
+			tabItems: {
+				type: Array,
+				default: null
+			},
+			tabItemsMark: {
+				type: Array,
+				default: null
+			},
+			type: {
+				type: Number,
+				default: 0
+			},
+			fontSize: {
+				type: Number,
+				default: 16
+			},
+		},
+		emits: ['onTabClick', 'onSelectChange'],
+		data() {
+			return {
+				tabCurrent: 0,
+				selectedID: 0
+			};
+		},
+		mounted() {
+			// console.log("initActIndex:" , this.initActIndex);
+			this.tabCurrent = this.initActIndex;
+		},
+		methods: {
+			getClassList(index) {
+				// console.log("index:", index);
+				let classList = "";
+				if (this.tabCurrent == index) {
+					classList = "tab-active";
+					if (this.type == 1 && this.tabItems.length > 1) {
+						if (index == 0) {
+							classList += " boder-radius-left";
+						} else if (index == (this.tabItems.length - 1)) {
+							classList += " boder-radius-right";
+						}
+					} else {
+						classList += " boder-radius-all";
+					}
+				} else {
+					classList = "tab-unactive";
+					if (this.type == 1) {
+						if (index < (this.tabItems.length - 1)) {
+							classList += " boder-solid-right";
+						}
+					}
+				}
+				// console.log("classList:", classList);
+				return classList;
+			},
+			getTextStyle(index) {
+				if (this.tabItemsMark == null || index > this.tabItemsMark.length - 1) {
+					return;
+				}
+				
+				let styleStr = "";
+				const mark = this.tabItemsMark[index];
+				if (mark.textColor.length > 0) {
+					if (this.tabCurrent != index) {
+						styleStr += "color: " + mark.textColor + ";";
+					}
+					styleStr += "background: url('" + mark.icon + "') no-repeat;";
+					styleStr += "background-position-x: 90%;";
+					styleStr += "background-position-y: 2%;";
+					styleStr += "background-size: 14px;";
+				}
+				console.log("getTextStyle: ", styleStr);
+				return styleStr;
+			},
+			getSelectStyle() {
+				let styleStr = "";
+				// const len = this.tabItems.length;
+				// if (len > 0) {
+				// 	styleStr = "width: " + 100 / len + "%;";
+				// }
+				// console.log("getSelectStyle", styleStr);
+				return styleStr;
+			},
+			onTabClick(index) {
+				// console.log("onTabClick:", index);
+				this.tabCurrent = index;
+				this.$emit('onTabClick', index);
+			},
+			// 获取输入框中值
+			getESelectText(data) {
+				// console.log("getESelectText:", data);
+			},
+			// 获取选择选项值
+			eSelectChange(data) {
+				// console.log("eSelectChange:", data);
+				this.$emit('onSelectChange', data);
+			},
+		}
+	}
+</script>
+
+<style scoped>
+	.tab {
+		width: 90%;
+		height: 60rpx;
+		margin-top: 30rpx;
+		background: #e7ecef;
+		border-radius: 18px;
+		justify-content: space-around;
+		
+		font-size: 16px;
+		font-weight: 500;
+		line-height: 60rpx;
+		text-align: center;
+	}
+
+	.tab-active {
+		width: 100%;
+		height: 60rpx;
+		background: #2e85ec;
+		color: #ffffff;
+	}
+
+	.tab-unactive {
+		width: 100%;
+		height: 60rpx;
+		color: #818181;
+	}
+	
+	.tab-corner-mark {
+		background-image: url('/static/common/award.png');
+		background-repeat: no-repeat;
+		background-position: center;
+		background-size: cover;
+	}
+
+	.boder-radius-all {
+		border-radius: 18px;
+	}
+
+	.boder-radius-left {
+		border-radius: 18px 0 0 18px;
+	}
+
+	.boder-radius-right {
+		border-radius: 0 18px 18px 0;
+	}
+
+	.boder-solid-left {
+		border-left: #d7d7d7 1px solid;
+	}
+
+	.boder-solid-right {
+		border-right: #d7d7d7 1px solid;
+	}
+
+	/deep/ .e-select {
+		border: none !important;
+	}
+	
+	/deep/ .e-select-input-text {
+		color: inherit !important;
+	}
+	
+	/deep/ .e-select-selector-item {
+		color: #818181;
+	}
+	
+	/deep/ .e-select-selector .e-select-selector-scroll .highlight {
+		color: #409eff !important;
+	}
+	
+	/deep/ .uni-icons {
+		color: inherit !important;
+	}
+	
+	/deep/ .e-select-input-placeholder {
+		color: inherit !important;
+		line-height: 60rpx !important;
+	}
+	
+	/deep/ .e-select-input-text {
+		width: 90% !important;
+	}
+	
+	/deep/ .e-select-icon {
+		/* width: 26px !important; */
+		width: 10% !important;
+	}
+</style>

+ 3 - 3
card/main.js

@@ -1,11 +1,11 @@
 import App from './App'
-import audio from "./common/audio.js";
+// import audio from "./common/audio.js";
 	
 // #ifndef VUE3
 import Vue from 'vue'
 import './uni.promisify.adaptor'
 Vue.config.productionTip = false
-Vue.prototype.$audio = audio;
+// Vue.prototype.$audio = audio;
 App.mpType = 'app'
 const app = new Vue({
   ...App
@@ -17,7 +17,7 @@ app.$mount()
 import { createSSRApp } from 'vue'
 export function createApp() {
   const app = createSSRApp(App)
-  app.config.globalProperties.$audio = audio;
+  // app.config.globalProperties.$audio = audio;
   return {
     app
   }

+ 48 - 0
card/pages.json

@@ -83,6 +83,54 @@
 			"style": {
 				"navigationBarTitleText": "[报名] 样式2 - 排名列表"
 			}
+		},
+		{
+			"path": "pages/bm/style3/index",
+			"style": {
+				"navigationBarTitleText": "[报名] 样式3"
+			}
+		},
+		{
+			"path": "pages/bm/style3/signup",
+			"style": {
+				"navigationBarTitleText": "[报名] 样式3 - 报名"
+			}
+		},
+		{
+			"path": "pages/bm/style3/rankOverview",
+			"style": {
+				"navigationBarTitleText": "[报名] 样式3 - 排名总览"
+			}
+		},
+		{
+			"path": "pages/bm/style3/rankList",
+			"style": {
+				"navigationBarTitleText": "[报名] 样式3 - 排名列表"
+			}
+		},
+		{
+			"path": "pages/bm/style4/index",
+			"style": {
+				"navigationBarTitleText": "[报名] 样式4"
+			}
+		},
+		{
+			"path": "pages/bm/style4/signup",
+			"style": {
+				"navigationBarTitleText": "[报名] 样式4 - 报名"
+			}
+		},
+		{
+			"path": "pages/bm/style4/rankOverview",
+			"style": {
+				"navigationBarTitleText": "[报名] 样式4 - 排名总览"
+			}
+		},
+		{
+			"path": "pages/bm/style4/rankList",
+			"style": {
+				"navigationBarTitleText": "[报名] 样式4 - 排名列表"
+			}
 		}
 	],
 	"globalStyle": {

+ 25 - 55
card/pages/achievement/index2.vue

@@ -7,17 +7,14 @@ https://oss-mbh5.colormaprun.com/card/#/pages/achievement/index2
 	<view class="body">
 		<view class="content uni-column">
 			<view class="topbar uni-row">
-				<view></view>
+				<uni-icons v-if="showBack" type="left" class="topbar-back" @click="btnBack"></uni-icons>
+				<text v-else></text>
 				<text>成就</text>
 				<text style="color: rgba(46, 133, 236, 1);"></text>
 			</view>
-			<view class="tab uni-row">
-				<text :class="tabCurrent == 0 ? 'tab-active boder-radius-left' : 'tab-unactive boder-solid-right'"
-					@click="tabCurrent=0">挑战</text>
-				<text :class="tabCurrent == 1 ? 'tab-active' : 'tab-unactive'" @click="tabCurrent=1">奖牌</text>
-				<text :class="tabCurrent == 2 ? 'tab-active boder-radius-right' : 'tab-unactive boder-solid-left'"
-					@click="tabCurrent=2">兑换</text>
-			</view>
+			
+			<my-tab ref="tab1" :initActIndex="tabCurrent" :tabItems="tabItems" :type="1" @onTabClick="onTabClick"></my-tab>
+			
 			<view class="main">
 				<!-- 挑战 -->
 				<view v-if="tabCurrent == 0">
@@ -120,6 +117,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/achievement/index2
 				unReadMessageRs: [], // 未读消息列表
 				mqIdListStr: "", // 已读消息id列表 逗号分隔
 
+				tabItems: ["挑战", "奖牌", "兑换"],
 				tabCurrent: 0,
 				popupDataList: [], // 弹窗数据:新获取的成就
 				popupAchdet: [], // 弹窗数据:用户点击的成就列表项
@@ -129,6 +127,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/achievement/index2
 					name: "泉城广场定向赛起始点",
 				},
 				interval: null,
+				showBack: false, // 是否在导航栏显示返回按钮
 			}
 		},
 		computed: {},
@@ -138,6 +137,8 @@ https://oss-mbh5.colormaprun.com/card/#/pages/achievement/index2
 			this.queryString = tools.objectToQueryString(this.queryObj);
 			// console.log(queryString);
 			this.token = query["token"] ?? token;
+			this.tabCurrent = parseInt(query["tabCurrent"] ?? 0);
+			this.showBack = query["tabCurrent"] >= 0 ? true : false;
 
 			this.getMonthlyChallengeQuery();
 			this.getAchievementQuery();
@@ -426,6 +427,13 @@ https://oss-mbh5.colormaprun.com/card/#/pages/achievement/index2
 					this.getExchangeListQuery();
 				}
 			},
+			btnBack() {
+				window.history.back();
+			},
+			onTabClick(val) {
+				// console.log("onTabClick: ", val);
+				this.tabCurrent = val;
+			},
 			test() {
 				// this.$refs.mypopupmap.popupOpen();
 				const url =
@@ -447,57 +455,19 @@ https://oss-mbh5.colormaprun.com/card/#/pages/achievement/index2
 
 	.topbar {
 		width: 90%;
-		margin-top: 70rpx;
+		margin-top: 72rpx;
 		justify-content: space-between;
 		font-weight: 550;
 		color: #333333;
-		font-size: 16px;
-	}
-
-	.tab {
-		width: 90%;
-		height: 60rpx;
-		margin-top: 30rpx;
-		background: #e7ecef;
-		border-radius: 18px;
-		justify-content: space-around;
-	}
-
-	.tab-active {
-		width: 50%;
-		height: 60rpx;
-		background: #2e85ec;
-		font-weight: 500;
-		color: #ffffff;
-		font-size: 16px;
-		text-align: center;
-		line-height: 60rpx;
+		font-size: 18px;
 	}
-
-	.tab-unactive {
-		width: 50%;
-		height: 60rpx;
-		font-weight: 500;
-		color: #818181;
-		font-size: 16px;
-		text-align: center;
-		line-height: 60rpx;
-	}
-
-	.boder-radius-left {
-		border-radius: 18px 0 0 18px;
-	}
-
-	.boder-radius-right {
-		border-radius: 0 18px 18px 0;
-	}
-
-	.boder-solid-left {
-		border-left: #d7d7d7 1px solid;
-	}
-
-	.boder-solid-right {
-		border-right: #d7d7d7 1px solid;
+	
+	.topbar-back {
+		width: 43rpx;
+		height: 43rpx;
+		color: inherit !important;
+		font-size: 48rpx !important;
+		/* opacity: 0; */
 	}
 
 	.main {

+ 8 - 1
card/pages/bm/style1/index.vue

@@ -53,6 +53,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style1/index
 				endSecond: null, // 卡片结束时间戳,单位秒
 				
 				isJoin: null, // 是否报名
+				isFinished: false, // 赛事是否结束
 				
 				// mcId: 0, // 赛事id
 				// mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
@@ -172,6 +173,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style1/index
 						this.countdown = tools.convertSecondsToDHM(dif);
 					} else {
 						this.countdown = "已结束";
+						this.isFinished = true;
 					}
 					// this.countdown = tools.convertSecondsToHMS(dif);
 				} else {
@@ -326,7 +328,12 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style1/index
 					// uni.reLaunch({
 					// 	url: '/pages/bm/style1/signup?full=true&' + this.queryString
 					// });
-					window.location.href = `${ossUrl}#/pages/bm/style1/signup?${this.queryString}&full=true`;
+					if (!this.isFinished) {	// 赛事未结束
+						window.location.href = `${ossUrl}#/pages/bm/style1/signup?${this.queryString}&full=true`;
+					}
+					else {	// 赛事已结束
+						window.location.href = `${ossUrl}#/pages/bm/style1/rankOverview?${this.queryString}&full=true`;
+					}
 				}
 				
 			}

+ 8 - 1
card/pages/bm/style1/rankList.vue

@@ -36,7 +36,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style1/rankList
 			</view>
 			<view class="main uni-column">
 				<uni-segmented-control class="main-tab" :current="tabCurrent" :values="tabItems"
-					@clickItem="onClickTabItem" styleType="button" activeColor="#2e85ec"></uni-segmented-control>
+					@clickItem="onClickTabItem" styleType="button" :activeColor="tabActiveColor"></uni-segmented-control>
 				<view class="tab-view uni-column">
 					<!-- 总排名 -->
 					<my-ranklist v-show="tabCurrent === 0" :rankRs="rankList.totalRankRs"></my-ranklist>
@@ -114,6 +114,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style1/rankList
 				dispArrStr: "", // 要显示的集合范围 (total,team,in,other)
 				tabItems: [],
 				tabCurrent: 0,
+				tabActiveColor: "#2e85ec",
 				
 				cssTop: "",
 				popupDataList: [],
@@ -233,6 +234,11 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style1/rankList
 				}
 				console.log("[loadConfig] cssTop:", this.cssTop);
 				
+				const tabActiveColor = config.tabActiveColor;
+				if (tabActiveColor != undefined && tabActiveColor.length > 0) {
+					this.tabActiveColor = tabActiveColor;
+				}
+				
 				// 加载队伍类型  0: 红黄蓝紫 1: 学生/家长
 				if (config.teamType != undefined && config.teamType >= 0) {
 					this.teamType = config.teamType;
@@ -333,6 +339,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style1/rankList
 								background-size: auto 27vh, auto 22vh , cover;
 							}
 						`,
+						"tabActiveColor": "#ff870d",
 						"popupDataList": [
 							{
 								"type": 1,

+ 15 - 1
card/pages/bm/style2/cardconfig.md

@@ -71,7 +71,21 @@
 	}
 },
 "rankOverview": {
-	"css": "",
+	"css": "
+		.top{
+			position: relative;
+			z-index: 10;
+			width: 100%;
+			height: 300px;
+			padding-top: 36px;
+			justify-content: space-between;
+			background-image: url('static/backgroud/top_bg_sea.png');
+			background-repeat: no-repeat;
+			background-position-x: center;
+			background-position-y: bottom;
+			background-size: cover;
+		}
+	",
 	"pathList": {
 		"row1": [{
 				"type": 2, // 1: 比赛路线  2: 导航到指定地点

+ 15 - 6
card/pages/bm/style2/index.vue

@@ -42,7 +42,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/index
 			return {
 				// audioSrc: "/static/audio/2.mp3",
 				// audioSrc: "https://oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
-				audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				// audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
 				pageName: "index",
 				rankKey: "rank-bm-style2",
 				queryObj: {},
@@ -56,6 +56,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/index
 				endSecond: null, // 卡片结束时间戳,单位秒
 				
 				isJoin: null, // 是否报名
+				isFinished: false, // 赛事是否结束
 				
 				// mcId: 0, // 赛事id
 				// mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
@@ -103,9 +104,9 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/index
 		},
 		methods: {
 			playMusic() {
-				if (this.$audio.audioStatus == 0 || this.$audio.audioSrc != this.audioSrc) {
-					this.$audio.playAudio(this.audioSrc);
-				}
+				// if (this.$audio.audioStatus == 0 || this.$audio.audioSrc != this.audioSrc) {
+				// 	this.$audio.playAudio(this.audioSrc);
+				// }
 			},
 			dealNotice(rank) {
 				// console.log('[dealNotice]');
@@ -180,6 +181,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/index
 						this.countdown = tools.convertSecondsToDHM(dif);
 					} else {
 						this.countdown = "已结束";
+						this.isFinished = true;
 					}
 					// this.countdown = tools.convertSecondsToHMS(dif);
 				} else {
@@ -355,13 +357,20 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/index
 					// uni.reLaunch({
 					// 	url: '/pages/bm/style1/rankList?full=true&' + this.queryString
 					// });
-					window.location.href = `${ossUrl}#/pages/bm/style2/rankOverview?${this.queryString}&full=true`;
+					// window.location.href = `${ossUrl}#/pages/bm/style2/rankOverview?${this.queryString}&full=true`;
+					window.location.href = `${ossUrl}#/pages/bm/style2/rankList?${this.queryString}&full=true`;
 				}
 				else {	// 未报名
 					// uni.reLaunch({
 					// 	url: '/pages/bm/style1/signup?full=true&' + this.queryString
 					// });
-					window.location.href = `${ossUrl}#/pages/bm/style2/signup?${this.queryString}&full=true`;
+					if (!this.isFinished) {	// 赛事未结束
+						window.location.href = `${ossUrl}#/pages/bm/style2/signup?${this.queryString}&full=true`;
+					}
+					else {	// 赛事已结束
+						// window.location.href = `${ossUrl}#/pages/bm/style2/rankOverview?${this.queryString}&full=true`;
+						window.location.href = `${ossUrl}#/pages/bm/style2/rankList?${this.queryString}&full=true`;
+					}
 				}
 			}
 		}

+ 24 - 7
card/pages/bm/style2/rankList.vue

@@ -8,8 +8,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankList
 		<view class="content uni-column">
 			<view class="uni-column" :class="cssTop">
 				<view class="topbar uni-row" :class="cssTopbarColor">
-					<!-- <image mode="aspectFit" class="topbar-back" @click="btnBack" src="/static/default/back.png"></image> -->
-					<text class="topbar-back" @click="btnBack">&lt;</text>
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
 					<text class="mcName">{{mcName}}</text>
 					<text class="topbar-rule" @click="btnInfo">规则</text>
 					<!-- <image mode="aspectFit" class="topbar-info" @click="btnInfo" src="/static/default/info.png"></image> -->
@@ -21,7 +20,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankList
 			</view>
 			<view class="main uni-column">
 				<uni-segmented-control class="main-tab" :current="tabCurrent" :values="tabItems"
-					@clickItem="onClickTabItem" styleType="button" activeColor="#81cd00"></uni-segmented-control>
+					@clickItem="onClickTabItem" styleType="button" :activeColor="tabActiveColor"></uni-segmented-control>
 				<view class="tab-view uni-column">
 					<!-- 总距离 -->
 					<my-ranklist v-show="tabCurrent === 0" :rankRs="rankList.totalDistanceRs" rank-type="totalDistance"></my-ranklist>
@@ -36,7 +35,8 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankList
 					<my-ranklist v-show="tabCurrent === 3" :rankRs="rankList.fastPaceRs" rank-type="fastPace"></my-ranklist>
 				</view>
 
-				<button class="btnBack" @click="btnBack">返回</button>
+				<button class="btnBack" @click="btnStartGame">我要比赛</button>
+				<!-- <button class="btnBack" @click="btnBack">返回</button> -->
 			</view>
 			
 			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
@@ -104,6 +104,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankList
 				dispArrStr: "totalDistance,totalCp,totalSysPoint,fastPace", // 要显示的集合范围
 				tabItems: ["总距离", "打点数", "百味豆", "配速"],
 				tabCurrent: 0,
+				tabActiveColor: "#81cd00",
 				
 				cssTop: "",
 				cssTopbarColor: "",
@@ -243,6 +244,11 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankList
 				console.log("[loadConfig] cssTop:", this.cssTop);
 				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
 				
+				const tabActiveColor = config.tabActiveColor;
+				if (tabActiveColor != undefined && tabActiveColor.length > 0) {
+					this.tabActiveColor = tabActiveColor;
+				}
+				
 				// 加载弹窗数据
 				const popupDataList = config.popupDataList;
 				// console.log("[loadConfig] popupDataList:", popupDataList);
@@ -331,6 +337,7 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankList
 								background-size: cover;
 							}
 						`,
+						"tabActiveColor": "#ff870d",
 						"popupDataList": [{
 								"type": 1,
 								"data": {
@@ -516,6 +523,15 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankList
 			},
 			btnBack() {
 				// window.history.back();
+				// uni.navigateTo({
+				// 	url: "/pages/bm/style2/rankOverview?" + this.queryString
+				// });
+				
+				const url = `action://to_home/`;
+				// window.location.href = url;
+				tools.appAction(url);
+			},
+			btnStartGame() {
 				uni.navigateTo({
 					url: "/pages/bm/style2/rankOverview?" + this.queryString
 				});
@@ -560,10 +576,11 @@ https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankList
 	}
 	
 	.topbar-back {
-		/* width: 43rpx; */
-		/* height: 43rpx; */
+		width: 43rpx;
+		height: 43rpx;
+		color: inherit !important;
+		font-size: 48rpx !important;
 		/* opacity: 0; */
-		font-size: 50rpx;
 	}
 	
 	.topbar-info {

+ 700 - 717
card/pages/bm/style2/rankOverview.vue

@@ -1,718 +1,701 @@
-<!-- 
-[报名] 样式2 - 排名总览
-http://localhost:5173/card/#/pages/bm/style2/rankOverview
-https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankOverview
- -->
-<template>
-	<view class="body">
-		<view class="content">
-			<view class="uni-column" :class="cssTop">
-				<view class="topbar uni-row" :class="cssTopbarColor">
-					<!-- <image mode="aspectFit" class="topbar-back" @click="btnBack" src="/static/default/back.png"></image> -->
-					<text class="topbar-back" @click="btnBack">&lt;</text>
-					<text class="mcName" @click="playMusic">{{mcName}}</text>
-					<text class="topbar-rule" @click="btnInfo">规则</text>
-					<!-- <image mode="aspectFit" class="topbar-info" @click="btnInfo" src="/static/default/info.png"></image> -->
-				</view>
-
-				<view class="topbtm uni-column">
-					<text class="topbtm-name">姓名:{{nickName}}</text>
-				</view>
-			</view>
-			<view class="top-oval">
-				<text class="top-oval-text" @click="onOverviewClick('totalNum')">点击查看排行榜</text>
-			</view>
-
-			<view class="mid uni-column">
-				<view class="mid-1 uni-row uni-jcsb">
-					<view class="overview-1 uni-column" @click="onOverviewClick('totalDistanct')">
-						<text class="ovline1">总距离 {{fmtDistanct(totalDistanct)}} km</text>
-						<text class="ovline2">第 {{totalDistanctRankNum > 0 ? totalDistanctRankNum : '- -'}} 名</text>
-					</view>
-					<view class="overview-2 uni-column" @click="onOverviewClick('totalNum')">
-						<text class="">总场次 {{totalNum}}</text>
-					</view>
-					<view class="overview-3 uni-column" @click="onOverviewClick('totalCp')">
-						<text class="ovline1">总打点数 {{totalCp}} 个</text>
-						<text class="ovline2">第 {{totalCpRankNum > 0 ? totalCpRankNum : '- -'}} 名</text>
-					</view>
-				</view>
-				<view class="mid-2 uni-row uni-jcse">
-					<view class="overview-4 uni-column" @click="onOverviewClick('totalSysPoint')">
-						<text class="ovline1">总百味豆 {{totalSysPoint}} 个</text>
-						<text class="ovline2">第 {{totalSysPointRankNum > 0 ? totalSysPointRankNum : '- -'}} 名</text>
-					</view>
-					<view class="overview-5 uni-column" @click="onOverviewClick('fastPace')">
-						<text class="ovline1">最快配速 {{fmtPace(fastPace)}}</text>
-						<text class="ovline2">第 {{fastPaceRankNum > 0 ? fastPaceRankNum : '- -'}} 名</text>
-					</view>
-				</view>
-			</view>
-
-			<view class="main uni-column">
-				<text class="main-title">选择比赛路线</text>
-				<view class="main-path uni-row">
-					<view v-for="(item, index) in pathList.row1" :key="'row1-' + index">
-						<image mode="aspectFit" class="pathimg" :src="item.img" @click="onPathImgClick(item)"></image>
-					</view>
-				</view>
-				<view class="main-path uni-row">
-					<view v-for="(item, index) in pathList.row2" :key="'row2-' + index">
-						<image mode="aspectFit" class="pathimg" :src="item.img" @click="onPathImgClick(item)"></image>
-					</view>
-				</view>
-			</view>
-
-			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
-			<!-- <my-popup-map ref="mypopupmap" :point="navPoint"></my-popup-map> -->
-		</view>
-	</view>
-</template>
-
-<script>
-	import tools from '/common/tools';
-	import {
-		defaultPopUpDataList
-	} from '/common/define';
-	import {
-		token,
-		apiMatchRsDetailQuery,
-		apiCardConfigQuery,
-		checkResCode
-	} from '/common/api';
-
-	export default {
-		data() {
-			return {
-				// audioSrc: "/static/audio/2.mp3",
-				// audioSrc: "https://oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
-				audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
-				pageName: "rankOverview",
-				firstEnterKey: 'firstEnter-bm-style2',
-				rankKey: "rank-bm-style2",
-				queryObj: {},
-				queryString: "",
-				token: "",
-
-				ecId: 0, // 卡片id
-				mcId: 0, // 赛事id
-				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
-				mcName: "", // 赛事名称
-				acttime: "", // 活动时间
-				beginSecond: null, // 活动或赛事开始时间戳,单位秒
-				endSecond: null, // 活动或赛事结束时间戳,单位秒
-				nickName: "", // 昵称
-				totalNum: null, // 总场次
-				totalDistanct: null, // 总距离,单位米
-				totalDistanctRankNum: null, // 总距离排名
-				totalCp: null, // 总打点数
-				totalCpRankNum: null, // 总打点数排名
-				totalSysPoint: null, // 总百味豆
-				totalSysPointRankNum: null, // 总百味豆排名
-				fastPace: null, // 个人最快配速
-				fastPaceRankNum: null, // 个人最快配速排名
-				ocaRs: [], // 卡片对应活动集合
-
-				interval: null,
-				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
-				cssTop: "",
-				cssTopbarColor: "",
-				pathList: {},
-				popupDataList: [],
-				navPoint: {},
-			}
-		},
-		computed: {},
-		onLoad(query) { // 类型非必填,可自动推导
-			// console.log("query:", query);
-			this.queryObj = query;
-			// this.queryString = tools.objectToQueryString(this.queryObj);
-			// console.log(queryString);
-			this.token = query["token"] ?? token;
-			this.ecId = query["id"] ?? 0;
-
-			this.firstEnterKey += "-" + this.ecId;
-			console.log("firstEnterKey:", this.firstEnterKey);
-
-			this.rankKey += "-" + this.ecId;
-			console.log("rankKey:", this.rankKey);
-
-			tools.removeCssCode();
-
-			this.getCardConfigQuery();
-		},
-		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
-		onReady() {
-			// this.dealFirstEnter();
-			// this.playMusic();
-		},
-		onShow() {
-			// uni.showToast({
-			// 	icon: "none",
-			// 	title: "[rankOverview] onShow"
-			// })
-			// if (this.$audio.audioStatus == 2 && this.$audio.audioSrc == this.audioSrc) {
-			// 	this.$audio.play();
-			// }
-		},
-		onUnload() {
-			this.clear();
-		},
-		methods: {
-			playMusic() {
-				return;
-				// uni.showToast({
-				// 	title: 'playMusic',
-				// 	icon: 'none',
-				// 	duration: 2000
-				// });
-				if (this.$audio.audioStatus == 0 || this.$audio.audioSrc != this.audioSrc) {
-					this.$audio.playAudio(this.audioSrc);
-				}
-			},
-			dealNotice(rank) {
-				// console.log('[dealFirstEnter]');
-				let that = this;
-				uni.getStorage({
-					key: that.rankKey,
-					success: (res) => {
-						console.log('[getStorage]', that.rankKey, res.data);
-						const oldRank = res.data;
-						if (oldRank != rank) {
-							// that.notice = true;
-							that.setRankValue(rank);
-						}
-					},
-					fail: (e) => {
-						console.log('[getStorage] fail', that.rankKey, e);
-						// that.notice = false;
-						that.setRankValue(rank);
-					},
-				})
-			},
-			setRankValue(data) {
-				let that = this;
-				uni.setStorage({
-					key: that.rankKey,
-					data: data,
-					success: () => {
-						console.log('[setStorage] success', that.rankKey, data);
-					},
-					fail: (e) => {
-						console.log('[setStorage] fail', that.rankKey, e);
-					},
-				})
-			},
-			dealFirstEnter() {
-				// console.log('[dealFirstEnter]');
-				let that = this;
-				uni.getStorage({
-					key: that.firstEnterKey,
-					success: (res) => {
-						console.log('[getStorage]', that.firstEnterKey, res.data);
-					},
-					fail: (e) => {
-						console.log('[getStorage] fail', that.firstEnterKey, e);
-						that.btnInfo();
-						that.setFirstEnterValue(true);
-					},
-				})
-			},
-			setFirstEnterValue(data) {
-				let that = this;
-				uni.setStorage({
-					key: that.firstEnterKey,
-					data: data,
-					success: () => {
-						console.log('[setStorage] success', that.firstEnterKey, data);
-					},
-					fail: (e) => {
-						console.log('[setStorage] fail', that.firstEnterKey, e);
-					},
-				})
-			},
-			clear() {
-				if (this.interval != null) {
-					clearInterval(this.interval);
-					this.interval = null;
-				}
-			},
-			loadConfig(config) {
-				// console.log("config", config);
-
-				// 加载CSS样式
-				const css = config.css;
-				if (css != undefined && css.length > 0) {
-					tools.loadCssCode(css);
-
-					if (css.indexOf(".top{") >= 0) {
-						this.cssTop = "top";
-					}
-					if (css.indexOf(".topbar-color{") >= 0) {
-						this.cssTopbarColor = "topbar-color";
-					}
-				}
-
-				if (this.cssTop == "") {
-					this.cssTop = "top-default";
-				}
-				if (this.cssTopbarColor == "") {
-					this.cssTopbarColor = "topbar-color-default";
-				}
-				console.log("[loadConfig] cssTop:", this.cssTop);
-				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
-
-				// 加载比赛路线数据
-				const pathList = config.pathList;
-				// console.log("[loadConfig] pathList:", pathList);
-				if (pathList != undefined) {
-					this.pathList = pathList;
-				}
-
-				// 加载弹窗数据
-				const popupDataList = config.popupDataList;
-				// console.log("[loadConfig] popupDataList:", popupDataList);
-				if (popupDataList != undefined && popupDataList.length > 0) {
-					for (var i = 0; i < popupDataList.length; i++) {
-						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
-						if (popupDataList[i] == 'default') {
-							for (var j = 0; j < defaultPopUpDataList.length; j++) {
-								this.popupDataList.push(defaultPopUpDataList[j]);
-							}
-						} else {
-							this.popupDataList.push(popupDataList[i]);
-						}
-					}
-				} else {
-					this.popupDataList = defaultPopUpDataList;
-					console.log("[loadConfig] popupDataList 加载默认列表");
-				}
-				// console.log("[loadConfig] popupDataList:", this.popupDataList);
-			},
-			// 获取倒计时
-			getCountdown() {
-				// console.log(this.endSecond)
-				if (this.endSecond > 0) {
-					const now = Date.now() / 1000;
-					const dif = this.endSecond - now;
-					// const dif = 3600*24 - 60;
-					if (dif > 0) {
-						this.countdown = '距结束 ' + tools.convertSecondsToDHM(dif);
-					} else {
-						this.countdown = "活动已结束";
-					}
-					// this.countdown = tools.convertSecondsToHMS(dif);
-				} else {
-					this.countdown = "距结束 --天--小时";
-				}
-			},
-			// 格式化 距离
-			fmtDistanct(val) {
-				if (val < 1000)
-					return Math.round(val * 10 / 1000) / 10;
-				else
-					return Math.round(val / 1000);
-			},
-			// 格式化 配速
-			fmtPace(val) {
-				return tools.convertSecondsToHMS(val, 2);
-			},
-			fmtMcTime(timestamp) {
-				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
-				// var Y = date.getFullYear() + '-';
-				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
-				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
-				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
-				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
-				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
-
-				const timeStr = M + D + h + m;
-				// console.log("timeStr", timeStr);
-				return timeStr;
-			},
-			// 获取活动时间
-			getActtime() {
-				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
-			},
-			getCardConfigQuery() {
-				uni.request({
-					url: apiCardConfigQuery,
-					header: {
-						"Content-Type": "application/x-www-form-urlencoded",
-						"token": this.token,
-					},
-					method: "POST",
-					data: {
-						ecId: this.ecId,
-						pageName: this.pageName
-					},
-					success: (res) => {
-						// console.log("getCardConfigQuery", res)
-						const data = res.data.data;
-						// console.log("configJson", data.configJson);
-						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
-						// console.log("configJson", data.configJson);
-						/* const config = {
-							"css": `
-							`,
-							"pathList": {
-								"row1": [{
-										"type": 2, // 1: 比赛路线  2: 导航到指定地点
-										"img": "/static/common/dhdqdwz.png",
-										"point": {
-											"longitude": 117.022194,
-											"latitude": 36.661612,
-											"name": "小飞龙定向赛起始点"
-										}
-									},
-									{
-										"type": 1, // 1: 比赛路线  2: 导航到指定地点
-										"img": "/static/common/cjlx12dw.png",
-										"path": {
-											"ocaId": 1,
-											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
-										}
-									}
-								],
-								"row2": [{
-										"type": 1, // 1: 比赛路线  2: 导航到指定地点
-										"img": "/static/common/zjlx16dw.png",
-										"path": {
-											"ocaId": 2,
-											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
-										}
-									},
-									{
-										"type": 1, // 1: 比赛路线  2: 导航到指定地点
-										"img": "/static/common/gjlx20dw.png",
-										"path": {
-											"ocaId": 3,
-											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
-										}
-									}
-								]
-							},
-							"popupDataList": [{
-									"type": 1,
-									"data": {
-										"title": "小飞龙定向赛",
-										"img": "/static/logo/xfl.png",
-										"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
-									}
-								},
-								{
-									type: 2,
-									data: {
-										title: "规则",
-										img: "/static/common/guize.png",
-									}
-								}, {
-									type: 2,
-									data: {
-										title: "奖励",
-										img: "/static/common/jiangli.png",
-									}
-								},
-								"default"
-							]
-						}; */
-
-						this.loadConfig(config);
-						this.matchRsDetailQuery();
-
-						setTimeout(this.dealFirstEnter, 500);
-					},
-					fail: (err) => {
-						console.log("getCardConfigQuery err", err)
-					},
-				});
-			},
-			// 卡片对应线上赛多个活动查询
-			matchRsDetailQuery() {
-				uni.request({
-					url: apiMatchRsDetailQuery,
-					header: {
-						"Content-Type": "application/x-www-form-urlencoded",
-						"token": this.token,
-					},
-					method: "POST",
-					data: {
-						ecId: this.ecId
-					},
-					success: (res) => {
-						console.log("matchRsDetailQuery", res);
-						if (checkResCode(res)) {
-							const data = res.data.data;
-							this.mcType = data.mcType;
-							this.mcId = data.mcId;
-							this.mcName = data.mcName;
-							this.beginSecond = data.beginSecond;
-							this.endSecond = data.endSecond;
-							this.nickName = data.nickName;
-							this.totalNum = data.totalNum;
-							this.totalDistanct = data.totalDistanct;
-							this.totalDistanctRankNum = data.totalDistanctRankNum;
-							this.totalCp = data.totalCp;
-							this.totalCpRankNum = data.totalCpRankNum;
-							this.totalSysPoint = data.totalSysPoint;
-							this.totalSysPointRankNum = data.totalSysPointRankNum;
-							this.fastPace = data.fastPace;
-							this.fastPaceRankNum = data.fastPaceRankNum;
-							this.ocaRs = data.ocaRs;
-
-							this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
-
-							const rank = JSON.stringify(data);
-							this.dealNotice(rank);
-
-							this.getCountdown();
-							this.getActtime();
-
-							this.clear();
-							this.interval = setInterval(this.getCountdown, 60000);
-						}
-					},
-					fail: (err) => {
-						console.log("matchRsDetailQuery err", err)
-					},
-				});
-			},
-			btnBack() {
-				// window.history.back();
-				const url = `action://to_home/`;
-				// window.location.href = url;
-				tools.appAction(url);
-			},
-			btnInfo() {
-				// console.log(this.$refs.mypopup);
-				this.$refs.mypopup.popupOpen();
-			},
-			onOverviewClick(ovtype) {
-				this.queryObj.ovtype = ovtype;
-				this.queryString = tools.objectToQueryString(this.queryObj);
-				uni.navigateTo({
-					url: "/pages/bm/style2/rankList?" + this.queryString
-				});
-			},
-			onPathImgClick(item) {
-				//item.type 1: 比赛路线  2: 导航到指定地点
-				if (item.type == 1) {
-					// 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
-					if (this.mcState == 1) {
-						const url = `action://to_detail/?id=${item.path.ocaId}&matchType=${item.path.mcType}`;
-						// window.location.href = url;
-						tools.appAction(url);
-					} else if (this.mcState == 0) {
-						uni.showToast({
-							title: '比赛尚未开始',
-							icon: 'none',
-							duration: 3000
-						});
-					} else if (this.mcState == 2) {
-						uni.showToast({
-							title: '比赛已结束',
-							icon: 'none',
-							duration: 3000
-						});
-					}
-				} else if (item.type == 2) {
-					this.navPoint = item.point;
-					// this.$refs.mypopupmap.popupOpen();
-					
-					const url = `action://to_map_app?title=${this.navPoint.name}&latitude=${this.navPoint.latitude}&longitude=${this.navPoint.longitude}`;
-					// window.location.href = url;
-					tools.appAction(url);
-				}
-			},
-		}
-	}
-</script>
-
-<style scoped>
-	.content {
-		width: 100vw;
-		height: 100vh;
-		overflow-x: hidden;
-	}
-
-	.top-default {
-		position: relative;
-		z-index: 10;
-		width: 100%;
-		height: 300px;
-		padding-top: 36px;
-		justify-content: space-between;
-		background-image: url("/static/backgroud/top_bg_aoti2.png");
-		background-repeat: no-repeat;
-		background-position-x: center;
-		background-position-y: bottom;
-		/* background-size: 100% 100%; */
-		background-size: cover;
-	}
-
-	.top-oval {
-		position: relative;
-		z-index: 0;
-		margin-top: -180px;
-		margin-left: -10%;
-		width: 120%;
-		height: 280px;
-		background: linear-gradient(180deg, #ffffff 12.18%, #eeeeee 100%);
-		border-radius: 50%;
-		text-align: center;
-	}
-	
-	.top-oval-text {
-		color: #333333;
-		font-size: 13px;
-		line-height: 386px;
-		pointer-events: auto;
-	}
-
-	.topbar {
-		width: 90%;
-		justify-content: space-between;
-	}
-
-	.topbar-color-default {
-		color: #5b9100;
-	}
-
-	.topbar-back {
-		/* width: 43rpx; */
-		/* height: 43rpx; */
-		/* opacity: 0; */
-		font-size: 50rpx;
-	}
-
-	.topbar-info {
-		width: 46rpx;
-		height: 46rpx;
-	}
-
-	.topbar-rule {
-		font-size: 32rpx;
-	}
-
-	.mcName {
-		font-size: 40rpx;
-		font-weight: 550;
-	}
-
-	.topbtm {
-		width: 100%;
-		/* height: 60rpx; */
-		margin-bottom: 40px;
-		justify-content: space-evenly;
-	}
-
-	.topbtm-name {
-		/* width: 320rpx; */
-		/* height: 28px; */
-		padding: 5px 12px;
-		background-color: #9fda39;
-		border-radius: 5px;
-		/* backdrop-filter: blur(30px); */
-		text-align: center;
-		font-weight: 500;
-		color: #497400;
-		font-size: 14px;
-	}
-
-	.mid {
-		position: relative;
-		z-index: 20;
-		margin-top: -130px;
-		pointer-events: none;
-	}
-
-	.mid-1 {
-		width: 92%;
-	}
-
-	.mid-2 {
-		width: 66%;
-	}
-
-	.overview-1 {
-		width: 111px;
-		height: 54px;
-		background: #ffb40b;
-		border-radius: 50%;
-		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
-		pointer-events: auto;
-	}
-
-	.overview-2 {
-		margin-top: -43px;
-		color: #ffffff;
-		font-size: 18px;
-		pointer-events: auto;
-	}
-
-	.overview-3 {
-		width: 111px;
-		height: 54px;
-		background: #f39509;
-		border-radius: 50%;
-		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
-		pointer-events: auto;
-	}
-
-	.overview-4 {
-		width: 111px;
-		height: 54px;
-		background: #81cd00;
-		border-radius: 50%;
-		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
-		pointer-events: auto;
-	}
-
-	.overview-5 {
-		width: 111px;
-		height: 54px;
-		background: #64cbb0;
-		border-radius: 50%;
-		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
-		pointer-events: auto;
-	}
-
-	.ovline1 {
-		margin-top: 9px;
-		color: #ffffff;
-		font-size: 12px;
-	}
-
-	.ovline2 {
-		color: #ffffff;
-		font-size: 16px;
-	}
-
-	.main {
-		width: 100%;
-		margin-top: 36px;
-		margin-bottom: 10px;
-		/* height: 70vh; */
-		justify-content: space-around;
-		/* justify-content: space-between; */
-	}
-
-	.main-title {
-		margin-bottom: 10px;
-		font-weight: 550;
-		color: #333333;
-		font-size: 16px;
-	}
-
-	.pathimg {
-		width: 127px;
-		height: 115px;
-	}
-
-	.main-path {
-		width: 90%;
-		margin-top: 10px;
-		margin-bottom: 10px;
-		justify-content: space-evenly;
-	}
+<!-- 
+[报名] 样式2 - 排名总览
+http://localhost:5173/card/#/pages/bm/style2/rankOverview
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/rankOverview
+ -->
+<template>
+	<view class="body">
+		<view class="content">
+			<view class="uni-column" :class="cssTop">
+				<view class="topbar uni-row" :class="cssTopbarColor">
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
+					<text class="mcName" @click="playMusic">{{mcName}}</text>
+					<text class="topbar-rule" @click="btnInfo">规则</text>
+					<!-- <image mode="aspectFit" class="topbar-info" @click="btnInfo" src="/static/default/info.png"></image> -->
+				</view>
+
+				<view class="topbtm uni-column">
+					<text class="topbtm-name">姓名:{{nickName}}</text>
+				</view>
+			</view>
+			<view class="top-oval">
+				<!-- <text class="top-oval-text" @click="onOverviewClick('totalNum')">点击查看排行榜</text> -->
+			</view>
+
+			<view class="mid uni-column">
+				<view class="mid-1 uni-row uni-jcsb">
+					<view class="overview-1 uni-column" @click="onOverviewClick('totalDistanct')">
+						<text class="ovline1">总距离 {{fmtDistanct(totalDistanct)}} km</text>
+						<text class="ovline2">第 {{totalDistanctRankNum > 0 ? totalDistanctRankNum : '- -'}} 名</text>
+					</view>
+					<view class="overview-2 uni-column" @click="onOverviewClick('totalNum')">
+						<text class="">总场次 {{totalNum}}</text>
+					</view>
+					<view class="overview-3 uni-column" @click="onOverviewClick('totalCp')">
+						<text class="ovline1">总打点数 {{totalCp}} 个</text>
+						<text class="ovline2">第 {{totalCpRankNum > 0 ? totalCpRankNum : '- -'}} 名</text>
+					</view>
+				</view>
+				<view class="mid-2 uni-row uni-jcse">
+					<view class="overview-4 uni-column" @click="onOverviewClick('totalSysPoint')">
+						<text class="ovline1">总百味豆 {{totalSysPoint}} 个</text>
+						<text class="ovline2">第 {{totalSysPointRankNum > 0 ? totalSysPointRankNum : '- -'}} 名</text>
+					</view>
+					<view class="overview-5 uni-column" @click="onOverviewClick('fastPace')">
+						<text class="ovline1">最快配速 {{fmtPace(fastPace)}}</text>
+						<text class="ovline2">第 {{fastPaceRankNum > 0 ? fastPaceRankNum : '- -'}} 名</text>
+					</view>
+				</view>
+			</view>
+
+			<view class="main uni-column">
+				<text class="main-title">选择比赛路线</text>
+				<my-pathList :style="pathListStyle.style" :pathList="pathList" :mcState="mcState" :showLine="pathListStyle.showLine"></my-pathList>
+			</view>
+
+			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
+			<!-- <my-popup-map ref="mypopupmap" :point="navPoint"></my-popup-map> -->
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	import {
+		defaultPopUpDataList
+	} from '/common/define';
+	import {
+		token,
+		apiMatchRsDetailQuery,
+		apiCardConfigQuery,
+		checkResCode
+	} from '/common/api';
+
+	export default {
+		data() {
+			return {
+				// audioSrc: "/static/audio/2.mp3",
+				// audioSrc: "https://oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				// audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				pageName: "rankOverview",
+				firstEnterKey: 'firstEnter-bm-style2',
+				rankKey: "rank-bm-style2",
+				queryObj: {},
+				queryString: "",
+				token: "",
+
+				ecId: 0, // 卡片id
+				mcId: 0, // 赛事id
+				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				mcName: "", // 赛事名称
+				acttime: "", // 活动时间
+				beginSecond: null, // 活动或赛事开始时间戳,单位秒
+				endSecond: null, // 活动或赛事结束时间戳,单位秒
+				nickName: "", // 昵称
+				totalNum: null, // 总场次
+				totalDistanct: null, // 总距离,单位米
+				totalDistanctRankNum: null, // 总距离排名
+				totalCp: null, // 总打点数
+				totalCpRankNum: null, // 总打点数排名
+				totalSysPoint: null, // 总百味豆
+				totalSysPointRankNum: null, // 总百味豆排名
+				fastPace: null, // 个人最快配速
+				fastPaceRankNum: null, // 个人最快配速排名
+				ocaRs: [], // 卡片对应活动集合
+
+				interval: null,
+				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				cssTop: "",
+				cssTopbarColor: "",
+				pathList: {},
+				pathListStyle: {},
+				popupDataList: [],
+				navPoint: {},
+			}
+		},
+		computed: {
+			pathListLen() {
+				return Object.keys(this.pathList).length;
+			}
+		},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log("query:", query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+
+			this.firstEnterKey += "-" + this.ecId;
+			console.log("firstEnterKey:", this.firstEnterKey);
+
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+
+			tools.removeCssCode();
+
+			this.getCardConfigQuery();
+		},
+		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
+		onReady() {
+			// this.dealFirstEnter();
+			// this.playMusic();
+		},
+		onShow() {
+			// uni.showToast({
+			// 	icon: "none",
+			// 	title: "[rankOverview] onShow"
+			// })
+			// if (this.$audio.audioStatus == 2 && this.$audio.audioSrc == this.audioSrc) {
+			// 	this.$audio.play();
+			// }
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			playMusic() {
+				return;
+				// uni.showToast({
+				// 	title: 'playMusic',
+				// 	icon: 'none',
+				// 	duration: 2000
+				// });
+				// if (this.$audio.audioStatus == 0 || this.$audio.audioSrc != this.audioSrc) {
+				// 	this.$audio.playAudio(this.audioSrc);
+				// }
+			},
+			dealNotice(rank) {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							// that.notice = true;
+							that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						// that.notice = false;
+						that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			dealFirstEnter() {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.firstEnterKey,
+					success: (res) => {
+						console.log('[getStorage]', that.firstEnterKey, res.data);
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.firstEnterKey, e);
+						that.btnInfo();
+						that.setFirstEnterValue(true);
+					},
+				})
+			},
+			setFirstEnterValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.firstEnterKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.firstEnterKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.firstEnterKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+
+				// 加载CSS样式
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+
+					if (css.indexOf(".top{") >= 0) {
+						this.cssTop = "top";
+					}
+					if (css.indexOf(".topbar-color{") >= 0) {
+						this.cssTopbarColor = "topbar-color";
+					}
+				}
+
+				if (this.cssTop == "") {
+					this.cssTop = "top-default";
+				}
+				if (this.cssTopbarColor == "") {
+					this.cssTopbarColor = "topbar-color-default";
+				}
+				console.log("[loadConfig] cssTop:", this.cssTop);
+				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
+
+				// 加载比赛路线数据
+				const pathList = config.pathList;
+				// console.log("[loadConfig] pathList:", pathList);
+				if (pathList != undefined) {
+					this.pathList = pathList;
+				}
+
+				// 加载比赛路线样式
+				const pathListStyle = config.pathListStyle;
+				// console.log("[loadConfig] pathList:", pathList);
+				if (pathListStyle != undefined) {
+					this.pathListStyle = pathListStyle;
+				}
+
+				// 加载弹窗数据
+				const popupDataList = config.popupDataList;
+				// console.log("[loadConfig] popupDataList:", popupDataList);
+				if (popupDataList != undefined && popupDataList.length > 0) {
+					for (var i = 0; i < popupDataList.length; i++) {
+						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
+						if (popupDataList[i] == 'default') {
+							for (var j = 0; j < defaultPopUpDataList.length; j++) {
+								this.popupDataList.push(defaultPopUpDataList[j]);
+							}
+						} else {
+							this.popupDataList.push(popupDataList[i]);
+						}
+					}
+				} else {
+					this.popupDataList = defaultPopUpDataList;
+					console.log("[loadConfig] popupDataList 加载默认列表");
+				}
+				// console.log("[loadConfig] popupDataList:", this.popupDataList);
+			},
+			// 获取倒计时
+			getCountdown() {
+				// console.log(this.endSecond)
+				if (this.endSecond > 0) {
+					const now = Date.now() / 1000;
+					const dif = this.endSecond - now;
+					// const dif = 3600*24 - 60;
+					if (dif > 0) {
+						this.countdown = '距结束 ' + tools.convertSecondsToDHM(dif);
+					} else {
+						this.countdown = "活动已结束";
+					}
+					// this.countdown = tools.convertSecondsToHMS(dif);
+				} else {
+					this.countdown = "距结束 --天--小时";
+				}
+			},
+			// 格式化 距离
+			fmtDistanct(val) {
+				if (val < 1000)
+					return Math.round(val * 10 / 1000) / 10;
+				else
+					return Math.round(val / 1000);
+			},
+			// 格式化 配速
+			fmtPace(val) {
+				return tools.convertSecondsToHMS(val, 2);
+			},
+			fmtMcTime(timestamp) {
+				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				// var Y = date.getFullYear() + '-';
+				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+
+				const timeStr = M + D + h + m;
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			// 获取活动时间
+			getActtime() {
+				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
+			},
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardConfigQuery", res)
+						const data = res.data.data;
+						// console.log("configJson", data.configJson);
+						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", data.configJson);
+						/* const config = {
+							"css": `
+								.top{
+									position: relative;
+									z-index: 10;
+									width: 100%;
+									height: 300px;
+									padding-top: 36px;
+									justify-content: space-between;
+									background-image: url('static/backgroud/top_bg_sea.png');
+									background-repeat: no-repeat;
+									background-position-x: center;
+									background-position-y: bottom;
+									background-size: cover;
+								}
+							`,
+							"pathList": {
+								"row1": [{
+										"type": 2, // 1: 比赛路线  2: 导航到指定地点
+										"img": "/static/common/dhdqdwz.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "小飞龙定向赛起始点"
+										}
+									},
+									{
+										"type": 1, // 1: 比赛路线  2: 导航到指定地点
+										"img": "/static/common/cjlx12dw.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										}
+									}
+								],
+								"row2": [{
+										"type": 1, // 1: 比赛路线  2: 导航到指定地点
+										"img": "/static/common/zjlx16dw.png",
+										"path": {
+											"ocaId": 2,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										}
+									},
+									{
+										"type": 1, // 1: 比赛路线  2: 导航到指定地点
+										"img": "/static/common/gjlx20dw.png",
+										"path": {
+											"ocaId": 3,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										}
+									}
+								]
+							},
+							"pathListStyle" : {
+								"showLine" : false,
+								"style": "justify-content: space-evenly;"
+							},
+							"popupDataList": [{
+									"type": 1,
+									"data": {
+										"title": "小飞龙定向赛",
+										"img": "/static/logo/xfl.png",
+										"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+									}
+								},
+								{
+									type: 2,
+									data: {
+										title: "规则",
+										img: "/static/common/guize.png",
+									}
+								}, {
+									type: 2,
+									data: {
+										title: "奖励",
+										img: "/static/common/jiangli.png",
+									}
+								},
+								"default"
+							]
+						}; */
+
+						this.loadConfig(config);
+						this.matchRsDetailQuery();
+
+						setTimeout(this.dealFirstEnter, 500);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						console.log("matchRsDetailQuery", res);
+						if (checkResCode(res)) {
+							const data = res.data.data;
+							this.mcType = data.mcType;
+							this.mcId = data.mcId;
+							this.mcName = data.mcName;
+							this.beginSecond = data.beginSecond;
+							this.endSecond = data.endSecond;
+							this.nickName = data.nickName;
+							this.totalNum = data.totalNum;
+							this.totalDistanct = data.totalDistanct;
+							this.totalDistanctRankNum = data.totalDistanctRankNum;
+							this.totalCp = data.totalCp;
+							this.totalCpRankNum = data.totalCpRankNum;
+							this.totalSysPoint = data.totalSysPoint;
+							this.totalSysPointRankNum = data.totalSysPointRankNum;
+							this.fastPace = data.fastPace;
+							this.fastPaceRankNum = data.fastPaceRankNum;
+							this.ocaRs = data.ocaRs;
+
+							this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+
+							const rank = JSON.stringify(data);
+							this.dealNotice(rank);
+
+							this.getCountdown();
+							this.getActtime();
+
+							this.clear();
+							this.interval = setInterval(this.getCountdown, 60000);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			btnBack() {
+				// window.history.back();
+				// const url = `action://to_home/`;
+				// window.location.href = url;
+				// tools.appAction(url);
+				
+				uni.navigateTo({
+					url: "/pages/bm/style2/rankList?" + this.queryString
+				});
+			},
+			btnInfo() {
+				// console.log(this.$refs.mypopup);
+				this.$refs.mypopup.popupOpen();
+			},
+			onOverviewClick(ovtype) {
+				this.queryObj.ovtype = ovtype;
+				this.queryString = tools.objectToQueryString(this.queryObj);
+				uni.navigateTo({
+					url: "/pages/bm/style2/rankList?" + this.queryString
+				});
+			},
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		height: 100vh;
+		overflow-x: hidden;
+	}
+
+	.top-default {
+		position: relative;
+		z-index: 10;
+		width: 100%;
+		height: 300px;
+		padding-top: 36px;
+		justify-content: space-between;
+		background-image: url("/static/backgroud/top_bg_aoti2.png");
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: bottom;
+		/* background-size: 100% 100%; */
+		background-size: cover;
+	}
+
+	.top-oval {
+		position: relative;
+		z-index: 0;
+		margin-top: -180px;
+		margin-left: -10%;
+		width: 120%;
+		height: 280px;
+		background: linear-gradient(180deg, #ffffff 12.18%, #eeeeee 100%);
+		border-radius: 50%;
+		text-align: center;
+	}
+	
+	.top-oval-text {
+		color: #333333;
+		font-size: 13px;
+		line-height: 386px;
+		pointer-events: auto;
+	}
+
+	.topbar {
+		width: 90%;
+		justify-content: space-between;
+	}
+
+	.topbar-color-default {
+		color: #5b9100;
+	}
+
+	.topbar-back {

+		width: 43rpx;

+		height: 43rpx;

+		color: inherit !important;

+		font-size: 48rpx !important;

+		/* opacity: 0; */

+	}
+
+	.topbar-info {
+		width: 46rpx;
+		height: 46rpx;
+	}
+
+	.topbar-rule {
+		font-size: 32rpx;
+	}
+
+	.mcName {
+		font-size: 40rpx;
+		font-weight: 550;
+	}
+
+	.topbtm {
+		width: 100%;
+		/* height: 60rpx; */
+		margin-bottom: 40px;
+		justify-content: space-evenly;
+	}
+
+	.topbtm-name {
+		/* width: 320rpx; */
+		/* height: 28px; */
+		padding: 5px 12px;
+		background-color: #9fda39;
+		border-radius: 5px;
+		/* backdrop-filter: blur(30px); */
+		text-align: center;
+		font-weight: 500;
+		color: #497400;
+		font-size: 14px;
+	}
+
+	.mid {
+		position: relative;
+		z-index: 20;
+		margin-top: -130px;
+		pointer-events: none;
+	}
+
+	.mid-1 {
+		width: 92%;
+	}
+
+	.mid-2 {
+		width: 66%;
+	}
+
+	.overview-1 {
+		width: 111px;
+		height: 54px;
+		background: #ffb40b;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-2 {
+		margin-top: -43px;
+		color: #ffffff;
+		font-size: 18px;
+		pointer-events: auto;
+	}
+
+	.overview-3 {
+		width: 111px;
+		height: 54px;
+		background: #f39509;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-4 {
+		width: 111px;
+		height: 54px;
+		background: #81cd00;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-5 {
+		width: 111px;
+		height: 54px;
+		background: #64cbb0;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.ovline1 {
+		margin-top: 9px;
+		color: #ffffff;
+		font-size: 12px;
+	}
+
+	.ovline2 {
+		color: #ffffff;
+		font-size: 16px;
+	}
+
+	.main {
+		width: 100%;
+		margin-top: 36px;
+		margin-bottom: 10px;
+		/* height: 70vh; */
+		justify-content: space-around;
+		/* justify-content: space-between; */
+	}
+
+	.main-title {
+		margin-bottom: 10px;
+		font-weight: 550;
+		color: #333333;
+		font-size: 16px;
+	}
+
 </style>

+ 678 - 676
card/pages/bm/style2/signup.vue

@@ -1,677 +1,679 @@
-<!-- 
-[报名] 样式2 - 报名
-http://localhost:5173/card/#/pages/bm/style2/signup
-https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/signup
- -->
-<template>
-	<view class="body">
-		<view class="content uni-column">
-			<view class="uni-column" :class="cssTop">
-				<view class="topbar uni-row" :class="cssTopbarColor">
-					<!-- <image mode="aspectFit" class="topbar-back" @click="btnBack" src="/static/default/back.png"></image> -->
-					<text class="topbar-back" @click="btnBack">&lt;</text>
-					<text class="mcName">{{mcName}}</text>
-					<text class="topbar-rule" @click="btnInfo">规则</text>
-				</view>
-			</view>
-			<view class="main uni-column">
-				<view class="timebar uni-row">
-					<image mode="aspectFit" class="clock" src="/static/default/clock.png"></image>
-					<text class="acttime">{{acttime}}</text>
-				</view>
-				
-				<input class="uni-input" maxlength="30" placeholder="请填写姓名" v-model="nickName" />
-
-				<view class="introduce uni-column">
-					<text class="introduce-title">{{introduce.title}}</text>
-					<text class="introduce-content">{{introduce.content}}</text>
-				</view>
-				<button class="btnSignup btnSignup-enable" v-if="mcState<=1" @click="btnSignup">报 名</button>
-				<button class="btnSignup btnSignup-disable" v-if="mcState==2">活动已结束</button>
-			</view>
-
-			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
-
-			<uni-popup ref="alertDialog" type="dialog">
-				<uni-popup-dialog type="info" cancelText="取消" confirmText="确认" title="您填写的姓名:" @confirm="dialogConfirm"
-					@close="dialogClose">
-					<view class="dialog-content uni-column">
-						<text class="dialog-content-1">{{nickName}}</text>
-					</view>
-				</uni-popup-dialog>
-			</uni-popup>
-		</view>
-	</view>
-</template>
-
-<script>
-	import tools from '../../../common/tools';
-	import {
-		defaultPopUpDataList
-	} from '../../../common/define';
-	import {
-		token,
-		apiCardDetailQuery,
-		apiOnlineMcSignUpDetail,
-		apiOnlineMcSignUp,
-		apiCardConfigQuery,
-		apiMatchRsDetailQuery,
-		checkResCode,
-		checkToken
-	} from '../../../common/api';
-
-	export default {
-		data() {
-			return {
-				pageName: "signup",
-				firstEnterKey: 'firstEnter-bm-style2',
-				rankKey: "rank-bm-style2",
-				queryObj: {},
-				queryString: "",
-				from: "", // 来源页面
-				token: "",
-				ecId: 0, // 卡片id
-				mcId: 0, // 赛事id
-				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
-				mcName: "", // 赛事名称
-				acttime: "", // 活动时间
-				beginSecond: null, // 活动或赛事开始时间戳,单位秒
-				endSecond: null, // 活动或赛事结束时间戳,单位秒
-				coiId: 0, // 已报名单位id
-				coiName: "", // 已报名单位名称,可为空
-				teamNum: 0, // 已报名队伍编号,可为0
-				nickName: "", // 昵称
-				// coiRs: [], // 组织信息集合
-				// orgList: [], // 分组下拉列表数据源
-				// teamList: [], // 
-				interval: null,
-
-				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
-				// teamType: 0, // 队伍类型  0: 红黄蓝紫 1: 学生/家长
-				cssTop: "",
-				cssTopbarColor: "",
-				cssLogo: "",
-				introduce: {
-					title: "",
-					content: ""
-				},
-				popupDataList: [],
-			}
-		},
-		computed: {},
-		onLoad(query) { // 类型非必填,可自动推导
-			// console.log(query);
-			this.queryObj = query;
-			this.queryString = tools.objectToQueryString(this.queryObj);
-			// console.log(queryString);
-			this.from = query["from"] ?? "";
-			this.token = query["token"] ?? token;
-			this.ecId = query["id"] ?? 0;
-
-			this.firstEnterKey += "-" + this.ecId;
-			console.log("firstEnterKey:", this.firstEnterKey);
-
-			this.rankKey += "-" + this.ecId;
-			console.log("rankKey:", this.rankKey);
-
-			tools.removeCssCode();
-
-			this.getCardConfigQuery();
-			this.getCardDetailQuery();
-			this.matchRsDetailQuery();
-		},
-		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
-		onReady() {
-			// this.dealFirstEnter();
-		},
-		onUnload() {
-			this.clear();
-		},
-		methods: {
-			dealNotice(rank) {
-				// console.log('[dealNotice]');
-				let that = this;
-				uni.getStorage({
-					key: that.rankKey,
-					success: (res) => {
-						console.log('[getStorage]', that.rankKey, res.data);
-						const oldRank = res.data;
-						if (oldRank != rank) {
-							// that.notice = true;
-							that.setRankValue(rank);
-						}
-					},
-					fail: (e) => {
-						console.log('[getStorage] fail', that.rankKey, e);
-						// that.notice = false;
-						that.setRankValue(rank);
-					},
-				})
-			},
-			setRankValue(data) {
-				let that = this;
-				uni.setStorage({
-					key: that.rankKey,
-					data: data,
-					success: () => {
-						console.log('[setStorage] success', that.rankKey, data);
-					},
-					fail: (e) => {
-						console.log('[setStorage] fail', that.rankKey, e);
-					},
-				})
-			},
-			dealFirstEnter() {
-				// console.log('[dealFirstEnter]');
-				let that = this;
-				uni.getStorage({
-					key: that.firstEnterKey,
-					success: (res) => {
-						console.log('[getStorage]', that.firstEnterKey, res.data);
-					},
-					fail: (e) => {
-						console.log('[getStorage] fail', that.firstEnterKey, e);
-						that.btnInfo();
-						that.setFirstEnterValue(true);
-					},
-				})
-			},
-			setFirstEnterValue(data) {
-				let that = this;
-				uni.setStorage({
-					key: that.firstEnterKey,
-					data: data,
-					success: () => {
-						console.log('[setStorage] success', that.firstEnterKey, data);
-					},
-					fail: (e) => {
-						console.log('[setStorage] fail', that.firstEnterKey, e);
-					},
-				})
-			},
-			clear() {
-				if (this.interval != null) {
-					clearInterval(this.interval);
-					this.interval = null;
-				}
-			},
-			loadConfig(config) {
-				// console.log("config", config);
-
-				// 加载CSS样式
-				const css = config.css;
-				if (css != undefined && css.length > 0) {
-					tools.loadCssCode(css);
-
-					if (css.indexOf(".top{") >= 0) {
-						this.cssTop = "top";
-					}
-					if (css.indexOf(".topbar-color{") >= 0) {
-						this.cssTopbarColor = "topbar-color";
-					}
-				}
-
-				if (this.cssTop == "") {
-					this.cssTop = "top-default";
-				}
-				if (this.cssTopbarColor == "") {
-					this.cssTopbarColor = "topbar-color-default";
-				}
-				console.log("[loadConfig] cssTop:", this.cssTop);
-				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
-
-				// 加载队伍类型  0: 红黄蓝紫 1: 学生/家长
-				/* if (config.teamType != undefined && config.teamType >= 0) {
-					this.teamType = config.teamType;
-				} */
-
-				// 加载介绍内容
-				const introduce = config.introduce;
-				if (introduce != undefined) {
-					if (introduce.title != undefined) {
-						this.introduce.title = introduce.title;
-					}
-					if (introduce.content != undefined) {
-						this.introduce.content = introduce.content;
-					}
-				}
-
-				// 加载弹窗数据
-				const popupDataList = config.popupDataList;
-				// console.log("[loadConfig] popupDataList:", popupDataList);
-				if (popupDataList != undefined && popupDataList.length > 0) {
-					for (var i = 0; i < popupDataList.length; i++) {
-						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
-						if (popupDataList[i] == 'default') {
-							for (var j = 0; j < defaultPopUpDataList.length; j++) {
-								this.popupDataList.push(defaultPopUpDataList[j]);
-							}
-						} else {
-							this.popupDataList.push(popupDataList[i]);
-						}
-					}
-				} else {
-					this.popupDataList = defaultPopUpDataList;
-					console.log("[loadConfig] popupDataList 加载默认列表");
-				}
-				// console.log("[loadConfig] popupDataList:", this.popupDataList);
-			},
-			fmtMcTime(timestamp) {
-				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
-				// var Y = date.getFullYear() + '-';
-				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
-				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
-				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
-				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
-				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
-
-				const timeStr = M + D + h + m;
-				// console.log("timeStr", timeStr);
-				return timeStr;
-			},
-			// 获取倒计时
-			getActtime() {
-				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
-			},
-			getCardConfigQuery() {
-				uni.request({
-					url: apiCardConfigQuery,
-					header: {
-						"Content-Type": "application/x-www-form-urlencoded",
-						"token": this.token,
-					},
-					method: "POST",
-					data: {
-						ecId: this.ecId,
-						pageName: this.pageName
-					},
-					success: (res) => {
-						// console.log("getCardConfigQuery", res)
-						const data = res.data.data;
-						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
-						// console.log("configJson", data.configJson);
-						/* const config = {
-							"css": `
-								.top{
-									width: 100%;
-									height: 230px;
-									padding-top: 36px;
-									justify-content: space-between;
-									background-image: url("static/backgroud/top_bg_aoti.png");
-									background-repeat: no-repeat;
-									background-position: center;
-									background-size: cover;
-								}
-								.topbar-color{
-									color: #5b9100;
-								}
-								.swiper-item-button {
-									background-color: #81cd00 !important;
-								}
-							`,
-							"popupDataList": [{
-									"type": 1,
-									"data": {
-										"title": "小飞龙定向赛",
-										"img": "/static/common/aoti.png",
-										"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
-									}
-								},
-								"default"
-							],
-							"introduce": {
-								"title": "介绍:",
-								"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
-							}
-						}; */
-
-						this.loadConfig(config);
-
-						setTimeout(this.dealFirstEnter, 500);
-					},
-					fail: (err) => {
-						console.log("getCardConfigQuery err", err)
-					},
-				});
-			},
-			// 卡片信息查询
-			getCardDetailQuery() {
-				uni.request({
-					url: apiCardDetailQuery,
-					header: {
-						"Content-Type": "application/x-www-form-urlencoded",
-						"token": this.token
-					},
-					method: "POST",
-					data: {
-						ecId: this.ecId
-					},
-					success: (res) => {
-						// console.log("getCardDetailQuery", res);
-						const data = res.data.data;
-						this.mcType = data.mcType;
-						this.mcId = data.mcId;
-						this.mcName = data.mcName;
-						this.beginSecond = data.beginSecond;
-						this.endSecond = data.endSecond;
-						this.coiId = data.coiId;
-						this.coiName = data.coiName;
-						this.teamNum = data.teamNum;
-
-						this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
-
-						this.getActtime();
-						// this.getOnlineMcSignUpDetail();
-
-						this.clear();
-						this.interval = setInterval(this.getActtime, 60000);
-					},
-					fail: (err) => {
-						console.log("getCardDetailQuery err", err)
-					},
-				});
-			},
-			// 卡片对应线上赛多个活动查询
-			matchRsDetailQuery() {
-				uni.request({
-					url: apiMatchRsDetailQuery,
-					header: {
-						"Content-Type": "application/x-www-form-urlencoded",
-						"token": this.token,
-					},
-					method: "POST",
-					data: {
-						ecId: this.ecId
-					},
-					success: (res) => {
-						// console.log("matchRsDetailQuery", res);
-						if (res.data.code == 0) {
-							const data = res.data.data;
-							const rank = JSON.stringify(data);
-							this.dealNotice(rank);
-						}
-					},
-					fail: (err) => {
-						console.log("matchRsDetailQuery err", err)
-					},
-				});
-			},
-			// 卡片用户当前排名查询
-			// getUserCurrentRankNumQuery() {
-			// 	uni.request({
-			// 		url: apiUserCurrentRankNumQuery,
-			// 		header: {
-			// 			"Content-Type": "application/x-www-form-urlencoded",
-			// 			"token": this.token,
-			// 		},
-			// 		method: "POST",
-			// 		data: {
-			// 			ecId: this.ecId
-			// 		},
-			// 		success: (res) => {
-			// 			// console.log("getUserCurrentRankNumQuery", res)
-			// 			if (res.data.code == 0) {
-			// 				const data = res.data.data;
-			// 				const rankNum = data.rankNum;
-			// 				this.dealNotice(rankNum);
-			// 			}
-			// 		},
-			// 		fail: (err) => {
-			// 			console.log("getUserCurrentRankNumQuery err", err)
-			// 		},
-			// 	});
-			// },
-			// 线上赛报名页面信息详情
-			/* getOnlineMcSignUpDetail() {
-				uni.request({
-					url: apiOnlineMcSignUpDetail,
-					header: {
-						"Content-Type": "application/x-www-form-urlencoded",
-						"token": this.token,
-					},
-					method: "POST",
-					data: {
-						mcId: this.mcId,
-					},
-					success: (res) => {
-						// console.log("getOnlineMcSignUpDetail", res)
-						this.coiRs = res.data.data.coiRs;
-						const rsNum = this.coiRs.length;
-						this.orgList = [];
-						for (let i = 0; i < rsNum; i++) {
-							this.orgList[i] = {};
-							this.orgList[i].value = this.coiRs[i].coiId;
-							this.orgList[i].text = this.coiRs[i].coiName;
-							this.orgList[i].teamNum = this.coiRs[i].teamNum;
-						}
-						// console.log("orgList", this.orgList);
-						if (this.coiId > 0) {
-							this.orgChange(this.coiId, false);
-						}
-					},
-					fail: (err) => {
-						console.log("getOnlineMcSignUpDetail err", err)
-					},
-				});
-			}, */
-			// 线上赛报名
-			onlineMcSignUp() {
-				uni.request({
-					url: apiOnlineMcSignUp,
-					header: {
-						"Content-Type": "application/x-www-form-urlencoded",
-						"token": this.token,
-					},
-					method: "POST",
-					data: {
-						mcId: this.mcId,
-						coiId: this.coiId,
-						selectTeam: this.teamNum,
-						nickName: this.nickName
-					},
-					success: (res) => {
-						// console.log("onlineMcSignUp", res);
-
-						if (checkResCode(res)) {
-							uni.showToast({
-								title: '比赛报名成功!',
-								icon: 'none',
-								duration: 3000
-							});
-
-							uni.navigateTo({
-								url: '/pages/bm/style2/rankOverview?' + this.queryString
-							});
-						}
-					},
-					fail: (err) => {
-						console.log("onlineMcSignUp err", err);
-						uni.showToast({
-							title: '出错了,报名失败',
-							icon: 'none',
-							duration: 3000
-						});
-					},
-				});
-			},
-			btnBack() {
-				// console.log("from:", this.from)
-				if (this.from != '') {
-					// window.history.back();
-					uni.navigateTo({
-						url: '/pages/bm/style2/rankList?' + this.queryString
-					});
-				} else {
-					const url = `action://to_home/`;
-					// window.location.href = url;
-					tools.appAction(url);
-				}
-			},
-			btnInfo() {
-				this.$refs.mypopup.popupOpen();
-			},
-			btnSignup() {
-				if (!checkToken(this.token)) {
-					return;
-				}
-
-				if (!(this.nickName.trim().length > 0)) {
-					uni.showToast({
-						title: '请填写姓名',
-						icon: 'none',
-						duration: 2000
-					});
-					return;
-				}
-
-				this.nickName = this.nickName.trim();
-				this.$refs.alertDialog.open();
-			},
-			dialogConfirm() {
-				this.onlineMcSignUp();
-			},
-			dialogClose() {}
-		}
-	}
-</script>
-
-<style scoped>
-	.content {
-		width: 100vw;
-		height: 100vh;
-	}
-
-	.top-default {
-		width: 100%;
-		height: 230px;
-		padding-top: 36px;
-		justify-content: space-between;
-		background-image: url("/static/backgroud/top_bg_aoti.png");
-		background-repeat: no-repeat;
-		background-position: center;
-		background-size: cover;
-	}
-
-	.topbar {
-		width: 90%;
-		justify-content: space-between;
-	}
-
-	.topbar-color-default {
-		color: #5b9100;
-	}
-
-	.topbar-back {
-		/* width: 43rpx; */
-		/* height: 43rpx; */
-		/* opacity: 0; */
-		font-size: 50rpx;
-	}
-
-	.topbar-rule {
-		font-size: 32rpx;
-	}
-
-	.mcName {
-		font-size: 40rpx;
-		font-weight: 550;
-	}
-
-	.main {
-		width: 76%;
-		min-height: 800rpx;
-		/* margin-top: 20rpx; */
-		justify-content: space-around;
-	}
-
-	.timebar {
-		width: 80%;
-		height: 65rpx;
-		margin-top: 20rpx;
-		padding: 0 50rpx;
-		justify-content: space-evenly;
-		background: #ffffff;
-		border: 0.5px solid;
-		border-color: #e7e7e7;
-		border-radius: 20px;
-		box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.13);
-	}
-
-	.acttime {
-		font-weight: 550;
-		color: #333333;
-		font-size: 30rpx;
-	}
-
-	.clock {
-		width: 30rpx;
-		height: 30rpx;
-		margin-right: 20rpx;
-	}
-	
-	.uni-input {
-		width: 90%;
-		height: 85rpx;
-		padding: 0 30rpx;
-		background: #f1f1f1;
-		border-radius: 9px;
-	}
-	
-	.input-placeholder {
-		color: #333333;
-		font-size: 16px;
-	}
-
-	.introduce {
-		margin-top: 10rpx;
-		margin-bottom: 80rpx;
-		align-items: flex-start;
-		justify-content: space-around;
-	}
-
-	.introduce-title {
-		color: #333333;
-		font-size: 30rpx;
-		line-height: 60rpx;
-	}
-
-	.introduce-content {
-		color: #333333;
-		font-size: 25rpx;
-		line-height: 36rpx;
-	}
-
-	.btnSignup {
-		width: 100%;
-		height: 100rpx;
-		margin-bottom: 30rpx;
-		color: white;
-		font-weight: bold;
-		line-height: 100rpx;
-		border-radius: 55rpx;
-	}
-
-	.btnSignup-enable {
-		background-color: #81cd00;
-	}
-
-	.btnSignup-disable {
-		background-color: #c3c3c3;
-	}
-
-	.dialog-content {
-		width: 279px;
-		height: 110px;
-		background: #f1f1f1;
-		border-radius: 9px;
-		justify-content: center;
-		text-align: center;
-		font-weight: 550;
-		color: #333333;
-	}
-
-	.dialog-content-1 {
-		font-size: 40rpx;
-	}
-
+<!-- 
+[报名] 样式2 - 报名
+http://localhost:5173/card/#/pages/bm/style2/signup
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style2/signup
+ -->
+<template>
+	<view class="body">
+		<view class="content uni-column">
+			<view class="uni-column" :class="cssTop">
+				<view class="topbar uni-row" :class="cssTopbarColor">
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
+					<text class="mcName">{{mcName}}</text>
+					<text class="topbar-rule" @click="btnInfo">规则</text>
+				</view>
+			</view>
+			<view class="main uni-column">
+				<view class="timebar uni-row">
+					<image mode="aspectFit" class="clock" src="/static/default/clock.png"></image>
+					<text class="acttime">{{acttime}}</text>
+				</view>
+				
+				<input class="uni-input" maxlength="30" placeholder="请填写姓名" v-model="nickName" />
+
+				<view class="introduce uni-column">
+					<text class="introduce-title">{{introduce.title}}</text>
+					<text class="introduce-content">{{introduce.content}}</text>
+				</view>
+				<button class="btnSignup btnSignup-enable" v-if="mcState<=1" @click="btnSignup">报 名</button>
+				<button class="btnSignup btnSignup-disable" v-if="mcState==2">活动已结束</button>
+			</view>
+
+			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
+
+			<uni-popup ref="alertDialog" type="dialog">
+				<uni-popup-dialog type="info" cancelText="取消" confirmText="确认" title="您填写的姓名:" @confirm="dialogConfirm"
+					@close="dialogClose">
+					<view class="dialog-content uni-column">
+						<text class="dialog-content-1">{{nickName}}</text>
+					</view>
+				</uni-popup-dialog>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '../../../common/tools';
+	import {
+		defaultPopUpDataList
+	} from '../../../common/define';
+	import {
+		token,
+		apiCardDetailQuery,
+		apiOnlineMcSignUpDetail,
+		apiOnlineMcSignUp,
+		apiCardConfigQuery,
+		apiMatchRsDetailQuery,
+		checkResCode,
+		checkToken
+	} from '../../../common/api';
+
+	export default {
+		data() {
+			return {
+				pageName: "signup",
+				firstEnterKey: 'firstEnter-bm-style2',
+				rankKey: "rank-bm-style2",
+				queryObj: {},
+				queryString: "",
+				from: "", // 来源页面
+				token: "",
+				ecId: 0, // 卡片id
+				mcId: 0, // 赛事id
+				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				mcName: "", // 赛事名称
+				acttime: "", // 活动时间
+				beginSecond: null, // 活动或赛事开始时间戳,单位秒
+				endSecond: null, // 活动或赛事结束时间戳,单位秒
+				coiId: 0, // 已报名单位id
+				coiName: "", // 已报名单位名称,可为空
+				teamNum: 0, // 已报名队伍编号,可为0
+				nickName: "", // 昵称
+				// coiRs: [], // 组织信息集合
+				// orgList: [], // 分组下拉列表数据源
+				// teamList: [], // 
+				interval: null,
+
+				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				// teamType: 0, // 队伍类型  0: 红黄蓝紫 1: 学生/家长
+				cssTop: "",
+				cssTopbarColor: "",
+				cssLogo: "",
+				introduce: {
+					title: "",
+					content: ""
+				},
+				popupDataList: [],
+			}
+		},
+		computed: {},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log(query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.from = query["from"] ?? "";
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+
+			this.firstEnterKey += "-" + this.ecId;
+			console.log("firstEnterKey:", this.firstEnterKey);
+
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+
+			tools.removeCssCode();
+
+			this.getCardConfigQuery();
+			this.getCardDetailQuery();
+			this.matchRsDetailQuery();
+		},
+		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
+		onReady() {
+			// this.dealFirstEnter();
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			dealNotice(rank) {
+				// console.log('[dealNotice]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							// that.notice = true;
+							that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						// that.notice = false;
+						that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			dealFirstEnter() {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.firstEnterKey,
+					success: (res) => {
+						console.log('[getStorage]', that.firstEnterKey, res.data);
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.firstEnterKey, e);
+						that.btnInfo();
+						that.setFirstEnterValue(true);
+					},
+				})
+			},
+			setFirstEnterValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.firstEnterKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.firstEnterKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.firstEnterKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+
+				// 加载CSS样式
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+
+					if (css.indexOf(".top{") >= 0) {
+						this.cssTop = "top";
+					}
+					if (css.indexOf(".topbar-color{") >= 0) {
+						this.cssTopbarColor = "topbar-color";
+					}
+				}
+
+				if (this.cssTop == "") {
+					this.cssTop = "top-default";
+				}
+				if (this.cssTopbarColor == "") {
+					this.cssTopbarColor = "topbar-color-default";
+				}
+				console.log("[loadConfig] cssTop:", this.cssTop);
+				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
+
+				// 加载队伍类型  0: 红黄蓝紫 1: 学生/家长
+				/* if (config.teamType != undefined && config.teamType >= 0) {
+					this.teamType = config.teamType;
+				} */
+
+				// 加载介绍内容
+				const introduce = config.introduce;
+				if (introduce != undefined) {
+					if (introduce.title != undefined) {
+						this.introduce.title = introduce.title;
+					}
+					if (introduce.content != undefined) {
+						this.introduce.content = introduce.content;
+					}
+				}
+
+				// 加载弹窗数据
+				const popupDataList = config.popupDataList;
+				// console.log("[loadConfig] popupDataList:", popupDataList);
+				if (popupDataList != undefined && popupDataList.length > 0) {
+					for (var i = 0; i < popupDataList.length; i++) {
+						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
+						if (popupDataList[i] == 'default') {
+							for (var j = 0; j < defaultPopUpDataList.length; j++) {
+								this.popupDataList.push(defaultPopUpDataList[j]);
+							}
+						} else {
+							this.popupDataList.push(popupDataList[i]);
+						}
+					}
+				} else {
+					this.popupDataList = defaultPopUpDataList;
+					console.log("[loadConfig] popupDataList 加载默认列表");
+				}
+				// console.log("[loadConfig] popupDataList:", this.popupDataList);
+			},
+			fmtMcTime(timestamp) {
+				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				// var Y = date.getFullYear() + '-';
+				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+
+				const timeStr = M + D + h + m;
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			// 获取倒计时
+			getActtime() {
+				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
+			},
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardConfigQuery", res)
+						const data = res.data.data;
+						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", data.configJson);
+						/* const config = {
+							"css": `
+								.top{
+									width: 100%;
+									height: 230px;
+									padding-top: 36px;
+									justify-content: space-between;
+									background-image: url("static/backgroud/top_bg_aoti.png");
+									background-repeat: no-repeat;
+									background-position: center;
+									background-size: cover;
+								}
+								.topbar-color{
+									color: #5b9100;
+								}
+								.swiper-item-button {
+									background-color: #81cd00 !important;
+								}
+							`,
+							"popupDataList": [{
+									"type": 1,
+									"data": {
+										"title": "小飞龙定向赛",
+										"img": "/static/common/aoti.png",
+										"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+									}
+								},
+								"default"
+							],
+							"introduce": {
+								"title": "介绍:",
+								"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+							}
+						}; */
+
+						this.loadConfig(config);
+
+						setTimeout(this.dealFirstEnter, 500);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 卡片信息查询
+			getCardDetailQuery() {
+				uni.request({
+					url: apiCardDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("getCardDetailQuery", res);
+						const data = res.data.data;
+						this.mcType = data.mcType;
+						this.mcId = data.mcId;
+						this.mcName = data.mcName;
+						this.beginSecond = data.beginSecond;
+						this.endSecond = data.endSecond;
+						this.coiId = data.coiId;
+						this.coiName = data.coiName;
+						this.teamNum = data.teamNum;
+
+						this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+
+						this.getActtime();
+						// this.getOnlineMcSignUpDetail();
+
+						this.clear();
+						this.interval = setInterval(this.getActtime, 60000);
+					},
+					fail: (err) => {
+						console.log("getCardDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("matchRsDetailQuery", res);
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							const rank = JSON.stringify(data);
+							this.dealNotice(rank);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片用户当前排名查询
+			// getUserCurrentRankNumQuery() {
+			// 	uni.request({
+			// 		url: apiUserCurrentRankNumQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getUserCurrentRankNumQuery", res)
+			// 			if (res.data.code == 0) {
+			// 				const data = res.data.data;
+			// 				const rankNum = data.rankNum;
+			// 				this.dealNotice(rankNum);
+			// 			}
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getUserCurrentRankNumQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 线上赛报名页面信息详情
+			/* getOnlineMcSignUpDetail() {
+				uni.request({
+					url: apiOnlineMcSignUpDetail,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcId: this.mcId,
+					},
+					success: (res) => {
+						// console.log("getOnlineMcSignUpDetail", res)
+						this.coiRs = res.data.data.coiRs;
+						const rsNum = this.coiRs.length;
+						this.orgList = [];
+						for (let i = 0; i < rsNum; i++) {
+							this.orgList[i] = {};
+							this.orgList[i].value = this.coiRs[i].coiId;
+							this.orgList[i].text = this.coiRs[i].coiName;
+							this.orgList[i].teamNum = this.coiRs[i].teamNum;
+						}
+						// console.log("orgList", this.orgList);
+						if (this.coiId > 0) {
+							this.orgChange(this.coiId, false);
+						}
+					},
+					fail: (err) => {
+						console.log("getOnlineMcSignUpDetail err", err)
+					},
+				});
+			}, */
+			// 线上赛报名
+			onlineMcSignUp() {
+				uni.request({
+					url: apiOnlineMcSignUp,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcId: this.mcId,
+						coiId: this.coiId,
+						selectTeam: this.teamNum,
+						nickName: this.nickName
+					},
+					success: (res) => {
+						// console.log("onlineMcSignUp", res);
+
+						if (checkResCode(res)) {
+							uni.showToast({
+								title: '比赛报名成功!',
+								icon: 'none',
+								duration: 3000
+							});
+
+							uni.navigateTo({
+								// url: '/pages/bm/style2/rankOverview?' + this.queryString
+								url: '/pages/bm/style2/rankList?' + this.queryString
+							});
+						}
+					},
+					fail: (err) => {
+						console.log("onlineMcSignUp err", err);
+						uni.showToast({
+							title: '出错了,报名失败',
+							icon: 'none',
+							duration: 3000
+						});
+					},
+				});
+			},
+			btnBack() {
+				// console.log("from:", this.from)
+				if (this.from != '') {
+					// window.history.back();
+					uni.navigateTo({
+						url: '/pages/bm/style2/rankList?' + this.queryString
+					});
+				} else {
+					const url = `action://to_home/`;
+					// window.location.href = url;
+					tools.appAction(url);
+				}
+			},
+			btnInfo() {
+				this.$refs.mypopup.popupOpen();
+			},
+			btnSignup() {
+				if (!checkToken(this.token)) {
+					return;
+				}
+
+				if (!(this.nickName.trim().length > 0)) {
+					uni.showToast({
+						title: '请填写姓名',
+						icon: 'none',
+						duration: 2000
+					});
+					return;
+				}
+
+				this.nickName = this.nickName.trim();
+				this.$refs.alertDialog.open();
+			},
+			dialogConfirm() {
+				this.onlineMcSignUp();
+			},
+			dialogClose() {}
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		height: 100vh;
+	}
+
+	.top-default {
+		width: 100%;
+		height: 230px;
+		padding-top: 36px;
+		justify-content: space-between;
+		background-image: url("/static/backgroud/top_bg_aoti.png");
+		background-repeat: no-repeat;
+		background-position: center;
+		background-size: cover;
+	}
+
+	.topbar {
+		width: 90%;
+		justify-content: space-between;
+	}
+
+	.topbar-color-default {
+		color: #5b9100;
+	}
+
+	.topbar-back {

+		width: 43rpx;

+		height: 43rpx;

+		color: inherit !important;

+		font-size: 48rpx !important;

+		/* opacity: 0; */

+	}
+
+	.topbar-rule {
+		font-size: 32rpx;
+	}
+
+	.mcName {
+		font-size: 40rpx;
+		font-weight: 550;
+	}
+
+	.main {
+		width: 76%;
+		min-height: 800rpx;
+		/* margin-top: 20rpx; */
+		justify-content: space-around;
+	}
+
+	.timebar {
+		width: 80%;
+		height: 65rpx;
+		margin-top: 20rpx;
+		padding: 0 50rpx;
+		justify-content: space-evenly;
+		background: #ffffff;
+		border: 0.5px solid;
+		border-color: #e7e7e7;
+		border-radius: 20px;
+		box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.13);
+	}
+
+	.acttime {
+		font-weight: 550;
+		color: #333333;
+		font-size: 30rpx;
+	}
+
+	.clock {
+		width: 30rpx;
+		height: 30rpx;
+		margin-right: 20rpx;
+	}
+	
+	.uni-input {
+		width: 90%;
+		height: 85rpx;
+		padding: 0 30rpx;
+		background: #f1f1f1;
+		border-radius: 9px;
+	}
+	
+	.input-placeholder {
+		color: #333333;
+		font-size: 16px;
+	}
+
+	.introduce {
+		width: 100%;
+		margin-top: 10rpx;
+		margin-bottom: 80rpx;
+		align-items: flex-start;
+		justify-content: space-around;
+	}
+
+	.introduce-title {
+		color: #333333;
+		font-size: 30rpx;
+		line-height: 60rpx;
+	}
+
+	.introduce-content {
+		color: #333333;
+		font-size: 25rpx;
+		line-height: 36rpx;
+	}
+
+	.btnSignup {
+		width: 100%;
+		height: 100rpx;
+		margin-bottom: 30rpx;
+		color: white;
+		font-weight: bold;
+		line-height: 100rpx;
+		border-radius: 55rpx;
+	}
+
+	.btnSignup-enable {
+		background-color: #81cd00;
+	}
+
+	.btnSignup-disable {
+		background-color: #c3c3c3;
+	}
+
+	.dialog-content {
+		width: 279px;
+		height: 110px;
+		background: #f1f1f1;
+		border-radius: 9px;
+		justify-content: center;
+		text-align: center;
+		font-weight: 550;
+		color: #333333;
+	}
+
+	.dialog-content-1 {
+		font-size: 40rpx;
+	}
+
 </style>

+ 266 - 0
card/pages/bm/style3/cardconfig.md

@@ -0,0 +1,266 @@
+卡片页面定制
+
+[小飞龙]
+
+"index": {
+	"css": "
+		.content-bg{
+			background: url('static/cardbg/xfl5.png');
+			background-size: cover;
+		}
+		.logo{
+			width: 40vw;
+			height: 40vw;
+			background: url('static/logo/xfl2.png') no-repeat center;
+			background-size: contain;
+		}
+		.mod-text{
+			color: #000000 !important;
+		}
+		.mod-button{
+			color: #ffffff !important;
+			background-color: #9d4f00 !important;
+		}
+	"
+},
+"signup": {
+	"css": "
+		.top{
+			width: 100%;
+			height: 170px;
+			padding-top: 36px;
+			justify-content: space-between;
+			background-image: url('static/backgroud/top_bg_egg3.png');
+			background-repeat: no-repeat;
+			background-position: center;
+			background-size: cover;
+		}
+		.topbar-color{
+			color: #333333;
+		}
+		.btnSignup-enable {
+			background-color: #ff870e !important;
+		}
+		.swiper-item-button {
+			background-color: #ff870e !important;
+		}
+	",
+	"popupDataList": [{
+			"type": 1,
+			"data": {
+				"title": "小飞龙定向赛",
+				"img": "/static/common/egg.png",
+				"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "规则",
+				img: "/static/common/guize.png",
+			}
+		}, {
+			type: 2,
+			data: {
+				title: "奖励",
+				img: "/static/common/jiangli.png",
+			}
+		},
+		"default"
+	],
+	"introduce": {
+		"title": "介绍:",
+		"content": " · 小飞龙定向赛再次来袭!这次有五个场地哟~\r\n · 神秘“蛋叔”闪亮登场~\r\n · 蛋叔放大招,百味豆换鸡蛋!\r\n · 时不可待!冲鸭!\r\n\r\n · 能不能把蛋叔整郁闷,就看你的啦~\r\n · 还等啥?火速报名吧!"
+	}
+},
+"rankOverview": {
+	"css": "
+		.top{
+			position: relative;
+			z-index: 10;
+			width: 100%;
+			height: 270px;
+			padding-top: 36px;
+			justify-content: space-between;
+			background-image: url('static/backgroud/top_bg_egg2.png');
+			background-repeat: no-repeat;
+			background-position-x: center;
+			background-position-y: -8px;
+			background-size: 100% 100%;
+		}
+	",
+	"pathList": {
+		"row1": [{
+				"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+				"pathImg": "/static/common/lingxiucheng.png",
+				"path": {
+					"ocaId": 1,
+					"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				},
+				"navImg": "/static/common/nav.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "领秀城起始点"
+				}
+			},
+			{
+				"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+				"pathImg": "/static/common/quanchenggongyuan.png",
+				"path": {
+					"ocaId": 1,
+					"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				},
+				"navImg": "/static/common/nav.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "泉城公园起始点"
+				}
+			}
+		],
+		"row2": [{
+				"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+				"pathImg": "/static/common/baihuagongyuan.png",
+				"path": {
+					"ocaId": 1,
+					"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				},
+				"navImg": "/static/common/nav.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "百花公园起始点"
+				}
+			},
+			{
+				"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+				"pathImg": "/static/common/aotizhongxin.png",
+				"path": {
+					"ocaId": 1,
+					"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				},
+				"navImg": "/static/common/nav.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "奥体中心起始点"
+				}
+			}
+		],
+		"row3": [{
+			"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+			"pathImg": "/static/common/muniushan.png",
+			"path": {
+				"ocaId": 1,
+				"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+			},
+			"navImg": "/static/common/nav.png",
+			"point": {
+				"longitude": 117.022194,
+				"latitude": 36.661612,
+				"name": "牧牛山起始点"
+			}
+		}]
+	},
+	"pathListStyle" : {
+		"showLine" : true,
+		"style": "justify-content: flex-start;"
+	},
+	"popupDataList": [{
+			"type": 1,
+			"data": {
+				"title": "小飞龙定向赛",
+				"img": "/static/common/egg.png",
+				"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "规则",
+				img: "/static/common/guize.png",
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "奖励",
+				img: "/static/common/jiangli.png",
+			}
+		},
+		"default"
+	]
+},
+"rankList": {
+	"css": "
+		.top{
+			width: 100%;
+			height: 170px;
+			padding-top: 36px;
+			justify-content: space-between;
+			background-image: url('static/backgroud/top_bg_egg3.png');
+			background-repeat: no-repeat;
+			background-position: center;
+			background-size: cover;
+		}
+		.topbar-color{
+			color: #333333;
+		}
+		.topbtm-name{
+			background-color: #c77f34 !important;
+			color: #ffffff !important;
+		}
+		.topbtm-egg{
+			background-color: #c6690a !important;
+			color: #ffffff !important;
+		}
+		.btnBack{
+			background-color: #ff870d !important;
+		}
+		.swiper-item-button {
+			background-color: #ff870e !important;
+		}
+		.uni-swiper-dot-active {
+			background: #ff870e !important;
+		}
+	",
+	"tabActiveColor": "#ff870d",
+	"popupDataList": [{
+			"type": 1,
+			"data": {
+				"title": "小飞龙定向赛",
+				"img": "/static/common/egg.png",
+				"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "规则",
+				img: "/static/common/guize.png",
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "奖励",
+				img: "/static/common/jiangli.png",
+			}
+		},
+		"default"
+	],
+	"popupExchgList": [{
+			"type": 5,
+			"data": {
+				"title": "兑换地点",
+				"img": "/static/common/wslgwcs.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "万盛隆购物超市"
+				}
+			}
+		}
+	]
+}

+ 484 - 0
card/pages/bm/style3/index.vue

@@ -0,0 +1,484 @@
+<!-- 
+[报名] 样式3 - 卡片页
+http://localhost:5173/card/#/pages/bm/style3/index
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style3/index
+ -->
+<template>
+	<view class="body body-radius">
+		<view class="content" :class="cssContentBg" @click="btnClick">
+			<view class="top uni-row">
+				<view class="top-right uni-row">
+					<image mode="aspectFit" class="clock" src="/static/default/clock.png"></image>
+					<view class="countdown">{{countdown}}</view>
+				</view>
+			</view>
+			<view class="main uni-column">
+				<!-- <image mode="aspectFit" :class="cssLogo" :src="logoSrc"></image> -->
+				<view :class="cssLogo"></view>
+				<view class="uni-row" style="position: relative;">
+					<image v-if="notice" mode="aspectFit" src="/static/common/notice.png" class="notice"></image>
+					<text class="type mod-text">{{type}}</text>
+				</view>
+				<text class="name mod-text">{{ecName}}</text>
+				<button class="button mod-button">{{btnText}}</button>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '../../../common/tools';
+	import {
+		token,
+		ossUrl,
+		apiCardBaseQuery,
+		apiUserJoinCardQuery,
+		apiCardConfigQuery,
+		apiMatchRsDetailQuery
+	} from '../../../common/api';
+	
+	export default {
+		data() {
+			return {
+				// audioSrc: "/static/audio/2.mp3",
+				// audioSrc: "https://oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				// audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				pageName: "index",
+				rankKey: "rank-bm-style3",
+				queryObj: {},
+				queryString: "",
+				token: "",
+				
+				ecId: 0, // 卡片id
+				ecName: '', // 卡片名称
+				ecDesc: '', // 卡片简介
+				beginSecond: null, // 卡片开始时间戳,单位秒
+				endSecond: null, // 卡片结束时间戳,单位秒
+				
+				isJoin: null, // 是否报名
+				isFinished: false, // 赛事是否结束
+				
+				// mcId: 0, // 赛事id
+				// mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				// mcName: "", // 赛事名称
+				
+				countdown: "", // 倒计时
+				interval: null,
+				
+				cssContentBg: "",
+				cssLogo: "",
+				// logoSrc: "",
+				type: "",
+				btnText: "",
+				notice: false,	// 是否显示(小红点)通知图标
+			}
+		},
+		computed: {},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log(query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+			
+			// this.contentBg = "content-bg-" + (query["bg"] ?? "green");
+			// this.logoSrc = "/static/logo/" + (query["logo"] ?? "jbs") + '.png';
+			this.type = query["type"] ?? "锦标赛";
+			this.btnText = query["btnText"] ?? "开始比赛";
+			
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+			
+			tools.removeCssCode();
+			
+			this.getCardBaseQuery();
+			this.getCardConfigQuery();
+			this.matchRsDetailQuery();
+		},
+		onShow() {
+			this.getUserJoinCardQuery();
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			playMusic() {
+				// if (this.$audio.audioStatus == 0 || this.$audio.audioSrc != this.audioSrc) {
+				// 	this.$audio.playAudio(this.audioSrc);
+				// }
+			},
+			dealNotice(rank) {
+				// console.log('[dealNotice]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							that.notice = true;
+							// that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						that.notice = true;
+						// that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+					
+					if (css.indexOf(".content-bg{") >= 0) {
+						this.cssContentBg = "content-bg";
+					}
+					if (css.indexOf(".logo{") >= 0) {
+						this.cssLogo = "logo";
+					}
+				}
+				
+				if (this.cssContentBg == "") {
+					this.cssContentBg = "content-bg-default";
+				}
+				if (this.cssLogo == "") {
+					this.cssLogo = "logo-default";
+				}
+				console.log("[loadConfig] cssContentBg:", this.cssContentBg);
+				console.log("[loadConfig] cssLogo:", this.cssLogo);
+			},
+			// 获取倒计时
+			getCountdown() {
+				// console.log(this.endSecond)
+				if (this.endSecond > 0) {
+					const now = Date.now() / 1000;
+					const dif = this.endSecond - now;
+					// const dif = 3600*24 - 60;
+					if (dif > 0) {
+						this.countdown = tools.convertSecondsToDHM(dif);
+					} else {
+						this.countdown = "已结束";
+						this.isFinished = true;
+					}
+					// this.countdown = tools.convertSecondsToHMS(dif);
+				} else {
+					this.countdown = "--天--小时";
+				}
+			},
+			// 卡片基本信息查询
+			getCardBaseQuery() {
+				uni.request({
+					url: apiCardBaseQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardBaseQuery", res)
+						const data = res.data.data;
+						
+						this.ecName = data.ecName;
+						this.ecDesc = data.ecDesc;
+						this.beginSecond = data.beginSecond;
+						this.endSecond = data.endSecond;
+						
+						this.getCountdown();
+						
+						this.clear();
+						this.interval = setInterval(this.getCountdown, 60000);
+					},
+					fail: (err) => {
+						console.log("getCardBaseQuery err", err)
+					},
+				});
+			},
+			// 卡片配置信息查询
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						console.log("getCardConfigQuery", res);
+						const data = res.data.data;
+						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", config);
+						/* const config = {
+						"css": `
+							.content-bg{
+								background: url('static/cardbg/xfl5.png');
+								background-size: cover;
+							}
+							
+							.logo{
+								width: 40vw;
+								height: 40vw;
+								background: url('static/logo/xfl2.png') no-repeat center;
+								background-size: contain;
+							}
+							
+							.mod-text{
+								color: #000000 !important;
+							}
+							
+							.mod-button{
+								color: #ffffff !important;
+								background-color: #9d4f00 !important;
+							}
+						`
+						}; */
+						
+						this.loadConfig(config);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 用户是否已经报名卡片对应赛事查询
+			getUserJoinCardQuery() {
+				uni.request({
+					url: apiUserJoinCardQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("getUserJoinCardQuery", res)
+						const code = res.data.code;
+						const data = res.data.data;
+						if (code == 0) {
+							this.isJoin = data.isJoin;
+							/*if (this.isJoin) {
+								this.btnText = "已报名";
+							} else {
+								this.btnText = "未报名";
+							} */
+						}
+					},
+					fail: (err) => {
+						console.log("getUserJoinCardQuery err", err)
+					},
+				});
+			},
+			// 卡片用户当前排名查询
+			// getUserCurrentRankNumQuery() {
+			// 	uni.request({
+			// 		url: apiUserCurrentRankNumQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getUserCurrentRankNumQuery", res)
+			// 			if (res.data.code == 0) {
+			// 				const data = res.data.data;
+			// 				const rankNum = data.rankNum;
+			// 				this.dealNotice(rankNum);
+			// 			}
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getUserCurrentRankNumQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("matchRsDetailQuery", res);
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							const rank = JSON.stringify(data);
+							this.dealNotice(rank);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			btnClick() {
+				// this.playMusic();
+				
+				if (this.isJoin) {	// 已报名
+					// uni.reLaunch({
+					// 	url: '/pages/bm/style1/rankList?full=true&' + this.queryString
+					// });
+					// window.location.href = `${ossUrl}#/pages/bm/style3/rankOverview?${this.queryString}&full=true`;
+					window.location.href = `${ossUrl}#/pages/bm/style3/rankList?${this.queryString}&full=true`;
+				}
+				else {	// 未报名
+					// uni.reLaunch({
+					// 	url: '/pages/bm/style1/signup?full=true&' + this.queryString
+					// });
+					if (!this.isFinished) {	// 赛事未结束
+						window.location.href = `${ossUrl}#/pages/bm/style3/signup?${this.queryString}&full=true`;
+					}
+					else {	// 赛事已结束
+						// window.location.href = `${ossUrl}#/pages/bm/style3/rankOverview?${this.queryString}&full=true`;
+						window.location.href = `${ossUrl}#/pages/bm/style3/rankList?${this.queryString}&full=true`;
+					}
+				}
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		height: 100vh;
+	}
+
+	.content-bg-default {
+		background: linear-gradient(180deg, #7aedff 0%, #047200 100%);
+		/* background: linear-gradient(180deg, #178bff 0%, #004d9b 100%); */
+		/* background: linear-gradient(180deg, #7aedff 0%, #8d2219 100%); */
+	}
+	
+	.top {
+		width: 100%;
+		justify-content: flex-end;
+	}
+
+	.top-right {
+		min-width: 180rpx;
+		height: 80rpx;
+		margin-top: 30rpx;
+		margin-right: 30rpx;
+		padding-left: 16rpx;
+		padding-right: 16rpx;
+		background-color: rgba(0, 0, 0, 0.3);
+		border-radius: 12px;
+	}
+
+	.clock {
+		width: 50rpx;
+		height: 50rpx;
+		margin-right: 12rpx;
+	}
+
+	.countdown {
+		min-width: 120rpx;
+		text-align: center;
+		font-family: Roboto;
+		color: #ffffff;
+		font-size: 46rpx;
+		/* letter-spacing: 2rpx; */
+	}
+
+	.main {
+		width: 100%;
+		height: 700rpx;
+		margin-top: 20rpx;
+		justify-content: space-evenly;
+	}
+
+	.logo-default {
+		width: 50vw;
+		height: 50vw;
+		background-image: url('/static/logo/jbs.png');
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: center;
+		background-size: contain;
+	}
+
+	.notice {
+		width: 30rpx;
+		height: 30rpx;
+		/* margin-right: 30rpx; */
+		position: absolute;
+		left: -60rpx;
+	}
+	
+	.type {
+		opacity: 60%;
+		/* line-height: 25px; */
+		font-family: Roboto;
+		color: #ffffff;
+		font-size: 40rpx;
+		text-align: center;
+	}
+
+	.name {
+		font-family: Roboto;
+		color: #ffffff;
+		font-size: 50rpx;
+		text-align: center;
+	}
+
+	.button {
+		width: 320rpx;
+		height: 86rpx;
+		margin-top: 30rpx;
+		color: #000000;
+		background: #ffffff;
+		border-radius: 56rpx;
+		font-size: 46rpx;
+		line-height: 80rpx;
+	}
+	
+	/* .mod-text {
+		color: #FF6203 !important;
+	}
+	
+	.mod-button {
+		color: #ffffff !important;
+		background-color: #FF6203 !important;
+	} */
+	
+</style>

+ 726 - 0
card/pages/bm/style3/rankList.vue

@@ -0,0 +1,726 @@
+<!-- 
+[报名] 样式3 - 排名列表
+http://localhost:5173/card/#/pages/bm/style3/rankList
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style3/rankList
+ -->
+<template>
+	<view class="body">
+		<view class="content uni-column">
+			<view class="uni-column" :class="cssTop">
+				<view class="topbar uni-row" :class="cssTopbarColor">
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
+					<text class="mcName">{{mcName}}</text>
+					<text class="topbar-rule" @click="btnInfo">规则</text>
+					<!-- <image mode="aspectFit" class="topbar-info" @click="btnInfo" src="/static/default/info.png"></image> -->
+				</view>
+				
+				<view class="topbtm uni-row">
+					<!-- <view class="topbtm-null"></view> -->
+					<view class="topbtm-egg" @click="btnMyEgg">蛋叔券</view>
+					<text class="topbtm-name">{{nickName}}</text>
+					<view class="topbtm-egg" @click="btnExchg">兑换地址</view>
+				</view>
+			</view>
+			<view class="main uni-column">
+				<uni-segmented-control class="main-tab" :current="tabCurrent" :values="tabItems"
+					@clickItem="onClickTabItem" styleType="button" :activeColor="tabActiveColor"></uni-segmented-control>
+				<view class="tab-view uni-column">
+					<!-- 总距离 -->
+					<my-ranklist v-show="tabCurrent === 0" :rankRs="rankList.totalDistanceRs" rank-type="totalDistance"></my-ranklist>
+
+					<!-- 打点数 -->
+					<my-ranklist v-show="tabCurrent === 1" :rankRs="rankList.totalCpRs" rank-type="totalCp"></my-ranklist>
+					
+					<!-- 百味豆 -->
+					<my-ranklist v-show="tabCurrent === 2" :rankRs="rankList.totalSysPointRs" rank-type="totalSysPoint"></my-ranklist>
+					
+					<!-- 配速 -->
+					<my-ranklist v-show="tabCurrent === 3" :rankRs="rankList.fastPaceRs" rank-type="fastPace"></my-ranklist>
+				</view>
+
+				<button class="btnBack" @click="btnStartGame">我要比赛</button>
+				<!-- <button class="btnBack" @click="btnBack">返回</button> -->
+			</view>
+			
+			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
+			<my-popup ref="mypopupExchg" :dataList="popupExchgList"></my-popup>
+			
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	import { teamName, defaultPopUpDataList } from '/common/define';
+	import {
+		token,
+		apiMatchRsDetailQuery,
+		apiCardRankDetailQuery,
+		apiCardConfigQuery,
+		apiUserCurrentRankNumQuery,
+		apiIsAllowMcSignUp,
+		checkResCode
+	} from '/common/api';
+	
+	export default {
+		data() {
+			return {
+				pageName: "rankList",
+				firstEnterKey: 'firstEnter-bm-style3',
+				rankKey: "rank-bm-style3",
+				queryObj: {},
+				queryString: "",
+				token: "",
+				ovtype: "",
+
+				ecId: 0, // 卡片id
+				mcId: 0, // 赛事id
+				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				mcName: "", // 赛事名称
+				acttime: "", // 活动时间
+				beginSecond: null, // 活动或赛事开始时间戳,单位秒
+				endSecond: null, // 活动或赛事结束时间戳,单位秒
+				ocaId: 0,	// 关联id,带入到App活动详情页面
+				nickName: "", // 昵称
+				// totalNum: null, // 总场次
+				// totalDistanct: null, // 总距离,单位米
+				// totalDistanctRankNum: null, // 总距离排名
+				// totalCp: null, // 总打点数
+				// totalCpRankNum: null, // 总打点数排名
+				// totalSysPoint: null, // 总百味豆
+				// totalSysPointRankNum: null, // 总百味豆排名
+				// fastPace: null, // 个人最快配速
+				// fastPaceRankNum: null, // 个人最快配速排名
+				// ocaRs: [], // 卡片对应活动集合
+
+				mcState: 0 ,	// 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				allowMcSignUp: false,	// 是否允许重新分组
+				countdown: "", // 倒计时
+				rankList: { // 排名列表
+					totalDistanceRs: [],
+					totalCpRs: [],
+					totalSysPointRs: [],
+					fastPaceRs: []
+				},
+				interval: null,
+				
+				teamType: 0, // 队伍类型
+				dispArrStr: "totalDistance,totalCp,totalSysPoint,fastPace", // 要显示的集合范围
+				tabItems: ["总距离", "打点数", "百味豆", "配速"],
+				tabCurrent: 0,
+				tabActiveColor: "#81cd00",
+				
+				cssTop: "",
+				cssTopbarColor: "",
+				popupDataList: [],
+				popupExchgList: []
+			}
+		},
+		computed: {},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log(query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+			this.ovtype = query["ovtype"] ?? "";
+			
+			this.firstEnterKey += "-" + this.ecId;
+			console.log("firstEnterKey:", this.firstEnterKey);
+
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+			
+			tools.removeCssCode();
+			
+			this.getCardConfigQuery();
+			this.dealOvtype();
+		},
+		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
+		onReady() {
+			// this.dealFirstEnter();
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			dealOvtype() {
+				if (this.ovtype == "totalDistance") {
+					this.tabCurrent = 0;
+				} else if (this.ovtype == "totalCp") {
+					this.tabCurrent = 1;
+				} else if (this.ovtype == "totalSysPoint") {
+					this.tabCurrent = 2;
+				} else if (this.ovtype == "fastPace") {
+					this.tabCurrent = 3;
+				}
+				console.log(`dealOvtype: ${this.ovtype} tabCurrent: ${this.tabCurrent}`);
+			},
+			dealNotice(rank) {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							// that.notice = true;
+							that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						// that.notice = false;
+						that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			dealFirstEnter() {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.firstEnterKey,
+					success: (res) => {
+						console.log('[getStorage]', that.firstEnterKey, res.data);
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.firstEnterKey, e);
+						that.btnInfo();
+						that.setFirstEnterValue(true);
+					},
+				})
+			},
+			setFirstEnterValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.firstEnterKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.firstEnterKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.firstEnterKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+				
+				// 加载CSS样式
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+					
+					if (css.indexOf(".top{") >= 0) {
+						this.cssTop = "top";
+					}
+					if (css.indexOf(".topbar-color{") >= 0) {
+						this.cssTopbarColor = "topbar-color";
+					}
+				}
+				
+				if (this.cssTop == "") {
+					this.cssTop = "top-default";
+				}
+				if (this.cssTopbarColor == "") {
+					this.cssTopbarColor = "topbar-color-default";
+				}
+				console.log("[loadConfig] cssTop:", this.cssTop);
+				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
+				
+				const tabActiveColor = config.tabActiveColor;
+				if (tabActiveColor != undefined && tabActiveColor.length > 0) {
+					this.tabActiveColor = tabActiveColor;
+				}
+				
+				// 加载弹窗数据
+				const popupDataList = config.popupDataList;
+				// console.log("[loadConfig] popupDataList:", popupDataList);
+				if (popupDataList != undefined && popupDataList.length > 0) {
+					for (var i = 0; i < popupDataList.length; i++) {
+						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
+						if (popupDataList[i] == 'default') {
+							for (var j = 0; j < defaultPopUpDataList.length; j++) {
+								this.popupDataList.push(defaultPopUpDataList[j]);
+							}
+						} else {
+							this.popupDataList.push(popupDataList[i]);
+						}
+					}
+				} else {
+					this.popupDataList = defaultPopUpDataList;
+					console.log("[loadConfig] popupDataList 加载默认列表");
+				}
+				// console.log("[loadConfig] popupDataList:", this.popupDataList);
+				
+				// 加载弹窗(兑换地点)数据
+				const popupExchgList = config.popupExchgList;
+				if (popupExchgList != undefined && popupExchgList.length > 0) {
+					for (var i = 0; i < popupExchgList.length; i++) {
+						// console.log("[loadConfig] popupExchgList", i, popupExchgList[i]);
+						this.popupExchgList.push(popupExchgList[i]);
+					}
+				}
+				// console.log("[loadConfig] popupExchgList:", this.popupExchgList);
+			},
+			// 获取倒计时
+			getCountdown() {
+				// console.log(this.endSecond)
+				if (this.endSecond > 0) {
+					const now = Date.now() / 1000;
+					const dif = this.endSecond - now;
+					// const dif = 3600*24 - 60;
+					if (dif > 0) {
+						this.countdown = '距结束 ' + tools.convertSecondsToDHM(dif);
+					} else {
+						this.countdown = "活动已结束";
+					}
+					// this.countdown = tools.convertSecondsToHMS(dif);
+				} else {
+					this.countdown = "距结束 --天--小时";
+				}
+			},
+			fmtMcTime(timestamp) {
+				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				// var Y = date.getFullYear() + '-';
+				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+
+				const timeStr = M + D + h + m;
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			// 获取活动时间
+			getActtime() {
+				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
+			},
+			getTeamName(teamType, teamIndex) {
+				return teamName[teamType][teamIndex];
+			},
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardConfigQuery", res)
+						const data = res.data.data;
+						// console.log("configJson", data.configJson);
+						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", data.configJson);
+						/* const config = {
+						"css": `
+							.top{
+								width: 100%;
+								height: 170px;
+								padding-top: 36px;
+								justify-content: space-between;
+								background-image: url('static/backgroud/top_bg_egg3.png');
+								background-repeat: no-repeat;
+								background-position: center;
+								background-size: cover;
+							}
+							.topbar-color{
+								color: #333333;
+							}
+							.topbtm-name{
+								background-color: #c77f34 !important;
+								color: #ffffff !important;
+							}
+							.topbtm-egg{
+								background-color: #c6690a !important;
+								color: #ffffff !important;
+							}
+							.btnBack{
+								background-color: #ff870d !important;
+							}
+							.swiper-item-button {
+								background-color: #ff870e !important;
+							}
+							.uni-swiper-dot-active {
+								background: #ff870e !important;
+							}
+						`,
+						"tabActiveColor": "#ff870d",
+						"popupDataList": [{
+								"type": 1,
+								"data": {
+									"title": "小飞龙定向赛",
+									"img": "/static/common/egg.png",
+									"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+								}
+							},
+							"default"
+						],
+						"popupExchgList": [{
+								"type": 5,
+								"data": {
+									"title": "兑换地点",
+									"img": "/static/common/wslgwcs.png",
+									"point": {
+										"longitude": 117.022194,
+										"latitude": 36.661612,
+										"name": "万盛隆购物超市"
+									}
+								}
+							}
+						]
+						}; */
+						
+						this.loadConfig(config);
+						this.matchRsDetailQuery();
+						
+						setTimeout(this.dealFirstEnter, 500);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 卡片对应活动或赛事详情查询
+			// getCardDetailQuery() {
+			// 	uni.request({
+			// 		url: apiCardDetailQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getCardDetailQuery", res)
+			// 			const data = res.data.data;
+			// 			this.mcType = data.mcType;
+			// 			this.mcId = data.mcId;
+			// 			this.mcName = data.mcName;
+			// 			this.beginSecond = data.beginSecond;
+			// 			this.endSecond = data.endSecond;
+			// 			this.coiName = data.coiName;
+			// 			this.teamNum = data.teamNum;
+						
+			// 			this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+						
+			// 			this.getCountdown();
+			// 			this.getActtime();
+			// 			this.getCardRankDetailQuery();
+
+			// 			this.clear();
+			// 			this.interval = setInterval(this.getCountdown, 60000);
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getCardDetailQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("matchRsDetailQuery", res);
+						if (checkResCode(res)) {
+							const data = res.data.data;
+							this.mcType = data.mcType;
+							this.mcId = data.mcId;
+							this.mcName = data.mcName;
+							this.beginSecond = data.beginSecond;
+							this.endSecond = data.endSecond;
+							this.nickName = data.nickName;
+							// this.totalNum = data.totalNum;
+							// this.totalDistanct = data.totalDistanct;
+							// this.totalDistanctRankNum = data.totalDistanctRankNum;
+							// this.totalCp = data.totalCp;
+							// this.totalCpRankNum = data.totalCpRankNum;
+							// this.totalSysPoint = data.totalSysPoint;
+							// this.totalSysPointRankNum = data.totalSysPointRankNum;
+							// this.fastPace = data.fastPace;
+							// this.fastPaceRankNum = data.fastPaceRankNum;
+							// this.ocaRs = data.ocaRs;
+				
+							this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+				
+							this.getCountdown();
+							this.getActtime();
+							this.getCardRankDetailQuery();
+				
+							this.clear();
+							this.interval = setInterval(this.getCountdown, 60000);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			// 排名查询
+			getCardRankDetailQuery() {
+				uni.request({
+					url: apiCardRankDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcIdListStr: this.mcId,
+						mcType: this.mcType,
+						dispArrStr: this.dispArrStr
+					},
+					success: (res) => {
+						console.log("getCardRankDetailQuery", res);
+						const rankdata = res.data.data;
+						this.rankList.totalDistanceRs = rankdata.totalDistanceRs;
+						this.rankList.totalCpRs = rankdata.totalCpRs;
+						this.rankList.totalSysPointRs = rankdata.totalSysPointRs;
+						this.rankList.fastPaceRs = rankdata.fastPaceRs;
+					},
+					fail: (err) => {
+						console.log("getCardRankDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片用户当前排名查询
+			// getUserCurrentRankNumQuery() {
+			// 	uni.request({
+			// 		url: apiUserCurrentRankNumQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getUserCurrentRankNumQuery", res)
+			// 			if (res.data.code == 0) {
+			// 				const data = res.data.data;
+			// 				const rankNum = data.rankNum;
+			// 				this.dealNotice(rankNum);
+			// 			}
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getUserCurrentRankNumQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 是否允许重新分组(报名)
+			isAllowMcSignUp() {
+				uni.request({
+					url: apiIsAllowMcSignUp,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("isAllowMcSignUp", res)
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							this.allowMcSignUp = data.allowSignUp;
+						}
+					},
+					fail: (err) => {
+						console.log("isAllowMcSignUp err", err)
+					},
+				});
+			},
+			btnBack() {
+				// window.history.back();
+				/* uni.navigateTo({
+					url: "/pages/bm/style3/rankOverview?" + this.queryString
+				}); */
+				
+				const url = `action://to_home/`;
+				// window.location.href = url;
+				tools.appAction(url);
+			},
+			btnStartGame() {
+				uni.navigateTo({
+					url: "/pages/bm/style3/rankOverview?" + this.queryString
+				});
+			},
+			btnInfo() {
+				// console.log(this.$refs.mypopup);
+				this.$refs.mypopup.popupOpen();
+			},
+			btnMyEgg() {
+				uni.navigateTo({
+					url: "/pages/achievement/index2?tabCurrent=2&" + this.queryString
+				});
+			},
+			btnExchg() {
+				this.$refs.mypopupExchg.popupOpen();
+			},
+			onClickTabItem(e) {
+				if (this.tabCurrent != e.currentIndex) {
+					this.tabCurrent = e.currentIndex;
+				}
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		height: 100vh;
+	}
+
+	.top-default {
+		width: 100%;
+		height: 170px;
+		padding-top: 36px;
+		justify-content: space-between;
+		background-image: url("/static/backgroud/top_bg2.png");
+		background-repeat: no-repeat;
+		background-position: center;
+		background-size: cover;
+	}
+	
+	.topbar {
+		width: 90%;
+		justify-content: space-between;
+	}
+
+	.topbar-color-default {
+		color: #5b9100;
+	}
+	
+	.topbar-back {

+		width: 43rpx;

+		height: 43rpx;

+		color: inherit !important;

+		font-size: 48rpx !important;

+		/* opacity: 0; */

+	}
+	
+	.topbar-info {
+		width: 46rpx;
+		height: 46rpx;
+	}
+	
+	.topbar-rule {
+		font-size: 32rpx;
+	}
+	
+	.mcName {
+		font-size: 40rpx;
+		font-weight: 550;
+	}
+	
+	.topbtm {
+		width: 100%;
+		margin-bottom: 5px;
+		justify-content: space-around;
+	}
+	
+	.topbtm-name {
+		padding: 3px 12px;
+		background-color: #9fda39;
+		border-radius: 5px;
+		text-align: center;
+		font-weight: 500;
+		color: #497400;
+		font-size: 14px;
+	}
+	
+	.topbtm-egg {
+		width: 60px;
+		padding: 3px 12px;
+		background-color: #9fda39;
+		border-radius: 50px;
+		text-align: center;
+		color: #497400;
+		font-size: 14px;
+	}
+	
+	.topbtm-null {
+		width: 60px;
+		padding: 3px 12px;
+	}
+	
+	.cal {
+		width: 46rpx;
+		height: 46rpx;
+		margin-right: 20rpx;
+	}
+	
+	.main {
+		width: 100%;
+		/* height: 70vh; */
+		flex-grow: 1;
+		justify-content: space-around;
+		/* justify-content: space-between; */
+	}
+
+	.main-tab {
+		width: 90%;
+		margin-top: 20rpx;
+	}
+
+	.tab-view {
+		width: 100%;
+		/* height: 69vh; */
+		flex-grow: 1;
+	}
+
+	.btnBack {
+		width: 70%;
+		/* height: 6vh; */
+		height: 80rpx;
+		/* margin-bottom: 1vh; */
+		margin-bottom: 20rpx;
+		/* font-weight: bold; */
+		color: white;
+		font-size: 32rpx;
+		line-height: 80rpx;
+		border-radius: 27px;
+		background-color: #81cd00;
+	}
+	
+</style>

+ 763 - 0
card/pages/bm/style3/rankOverview.vue

@@ -0,0 +1,763 @@
+<!-- 
+[报名] 样式3 - 排名总览
+http://localhost:5173/card/#/pages/bm/style3/rankOverview
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style3/rankOverview
+ -->
+<template>
+	<view class="body">
+		<view class="content uni-column">
+			<view class="uni-column" :class="cssTop">
+				<view class="topbar uni-row" :class="cssTopbarColor">
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
+					<text class="mcName" @click="playMusic">{{mcName}}</text>
+					<text class="topbar-rule" @click="btnInfo">规则</text>
+					<!-- <image mode="aspectFit" class="topbar-info" @click="btnInfo" src="/static/default/info.png"></image> -->
+				</view>
+			</view>
+			
+			<view class="mid uni-column">
+				<view class="mid-1 uni-row uni-jcsb">
+					<text>{{nickName}}</text>
+					<text>总场次:{{totalNum}}</text>
+				</view>
+				<view class="mid-2 uni-row uni-jcsa">
+					<view class="uni-column">
+						<text class="mid-2-value" style="color: #ff0045;">{{totalSysPoint}}</text>
+						<text class="mid-2-text">百味豆(个)</text>
+					</view>
+
+					<view class="mid-line"></view>
+
+					<view class="uni-column">
+						<text class="mid-2-value">{{fmtDistanct(totalDistanct)}}</text>
+						<text class="mid-2-text">总里程km</text>
+					</view>
+
+					<view class="mid-line"></view>
+					<view class="uni-column">
+						<text class="mid-2-value">{{totalCp}}</text>
+						<text class="mid-2-text">打点数(个)</text>
+					</view>
+
+					<view class="mid-line"></view>
+
+					<view class="uni-column">
+						<text class="mid-2-value">{{fmtPace(fastPace)}}</text>
+						<text class="mid-2-text">最快配速</text>
+					</view>
+				</view>
+			</view>
+
+			<view class="main uni-column">
+				<text class="main-title">选择比赛路线</text>
+				<my-pathList :style="pathListStyle.style" :pathList="pathList" :mcState="mcState" :showLine="pathListStyle.showLine"></my-pathList>
+			</view>
+
+			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
+			<!-- <my-popup-map ref="mypopupmap" :point="navPoint"></my-popup-map> -->
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	import {
+		defaultPopUpDataList
+	} from '/common/define';
+	import {
+		token,
+		apiMatchRsDetailQuery,
+		apiCardConfigQuery,
+		checkResCode
+	} from '/common/api';
+
+	export default {
+		data() {
+			return {
+				// audioSrc: "/static/audio/2.mp3",
+				// audioSrc: "https://oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				// audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				pageName: "rankOverview",
+				firstEnterKey: 'firstEnter-bm-style3',
+				rankKey: "rank-bm-style3",
+				queryObj: {},
+				queryString: "",
+				token: "",
+
+				ecId: 0, // 卡片id
+				mcId: 0, // 赛事id
+				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				mcName: "", // 赛事名称
+				acttime: "", // 活动时间
+				beginSecond: null, // 活动或赛事开始时间戳,单位秒
+				endSecond: null, // 活动或赛事结束时间戳,单位秒
+				nickName: "", // 昵称
+				totalNum: null, // 总场次
+				totalDistanct: null, // 总距离,单位米
+				totalDistanctRankNum: null, // 总距离排名
+				totalCp: null, // 总打点数
+				totalCpRankNum: null, // 总打点数排名
+				totalSysPoint: null, // 总百味豆
+				totalSysPointRankNum: null, // 总百味豆排名
+				fastPace: null, // 个人最快配速
+				fastPaceRankNum: null, // 个人最快配速排名
+				ocaRs: [], // 卡片对应活动集合
+
+				interval: null,
+				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				cssTop: "",
+				cssTopbarColor: "",
+				pathList: {},
+				pathListStyle: {},
+				popupDataList: [],
+				navPoint: {},
+			}
+		},
+		computed: {
+			pathListLen() {
+				return Object.keys(this.pathList).length;
+			}
+		},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log("query:", query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+
+			this.firstEnterKey += "-" + this.ecId;
+			console.log("firstEnterKey:", this.firstEnterKey);
+
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+
+			tools.removeCssCode();
+
+			this.getCardConfigQuery();
+		},
+		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
+		onReady() {
+			// this.dealFirstEnter();
+			// this.playMusic();
+		},
+		onShow() {
+			// uni.showToast({
+			// 	icon: "none",
+			// 	title: "[rankOverview] onShow"
+			// })
+			// if (this.$audio.audioStatus == 2 && this.$audio.audioSrc == this.audioSrc) {
+			// 	this.$audio.play();
+			// }
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			playMusic() {
+				return;
+				// uni.showToast({
+				// 	title: 'playMusic',
+				// 	icon: 'none',
+				// 	duration: 2000
+				// });
+				// if (this.$audio.audioStatus == 0 || this.$audio.audioSrc != this.audioSrc) {
+				// 	this.$audio.playAudio(this.audioSrc);
+				// }
+			},
+			dealNotice(rank) {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							// that.notice = true;
+							that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						// that.notice = false;
+						that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			dealFirstEnter() {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.firstEnterKey,
+					success: (res) => {
+						console.log('[getStorage]', that.firstEnterKey, res.data);
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.firstEnterKey, e);
+						that.btnInfo();
+						that.setFirstEnterValue(true);
+					},
+				})
+			},
+			setFirstEnterValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.firstEnterKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.firstEnterKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.firstEnterKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+
+				// 加载CSS样式
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+
+					if (css.indexOf(".top{") >= 0) {
+						this.cssTop = "top";
+					}
+					if (css.indexOf(".topbar-color{") >= 0) {
+						this.cssTopbarColor = "topbar-color";
+					}
+				}
+
+				if (this.cssTop == "") {
+					this.cssTop = "top-default";
+				}
+				if (this.cssTopbarColor == "") {
+					this.cssTopbarColor = "topbar-color-default";
+				}
+				console.log("[loadConfig] cssTop:", this.cssTop);
+				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
+
+				// 加载比赛路线数据
+				const pathList = config.pathList;
+				// console.log("[loadConfig] pathList:", pathList);
+				if (pathList != undefined) {
+					this.pathList = pathList;
+				}
+				
+				// 加载比赛路线样式
+				const pathListStyle = config.pathListStyle;
+				// console.log("[loadConfig] pathList:", pathList);
+				if (pathListStyle != undefined) {
+					this.pathListStyle = pathListStyle;
+				}
+
+				// 加载弹窗数据
+				const popupDataList = config.popupDataList;
+				// console.log("[loadConfig] popupDataList:", popupDataList);
+				if (popupDataList != undefined && popupDataList.length > 0) {
+					for (var i = 0; i < popupDataList.length; i++) {
+						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
+						if (popupDataList[i] == 'default') {
+							for (var j = 0; j < defaultPopUpDataList.length; j++) {
+								this.popupDataList.push(defaultPopUpDataList[j]);
+							}
+						} else {
+							this.popupDataList.push(popupDataList[i]);
+						}
+					}
+				} else {
+					this.popupDataList = defaultPopUpDataList;
+					console.log("[loadConfig] popupDataList 加载默认列表");
+				}
+				// console.log("[loadConfig] popupDataList:", this.popupDataList);
+			},
+			// 获取倒计时
+			getCountdown() {
+				// console.log(this.endSecond)
+				if (this.endSecond > 0) {
+					const now = Date.now() / 1000;
+					const dif = this.endSecond - now;
+					// const dif = 3600*24 - 60;
+					if (dif > 0) {
+						this.countdown = '距结束 ' + tools.convertSecondsToDHM(dif);
+					} else {
+						this.countdown = "活动已结束";
+					}
+					// this.countdown = tools.convertSecondsToHMS(dif);
+				} else {
+					this.countdown = "距结束 --天--小时";
+				}
+			},
+			// 格式化 距离
+			fmtDistanct(val) {
+				if (val < 1000)
+					return Math.round(val * 10 / 1000) / 10;
+				else
+					return Math.round(val / 1000);
+			},
+			// 格式化 配速
+			fmtPace(val) {
+				return tools.convertSecondsToHMS(val, 2);
+			},
+			fmtMcTime(timestamp) {
+				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				// var Y = date.getFullYear() + '-';
+				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+
+				const timeStr = M + D + h + m;
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			// 获取活动时间
+			getActtime() {
+				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
+			},
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardConfigQuery", res)
+						const data = res.data.data;
+						// console.log("configJson", data.configJson);
+						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", data.configJson);
+						/* const config = {
+							"css": `
+								.top{
+									position: relative;
+									z-index: 10;
+									width: 100%;
+									height: 270px;
+									padding-top: 36px;
+									justify-content: space-between;
+									background-image: url('static/backgroud/top_bg_egg2.png');
+									background-repeat: no-repeat;
+									background-position-x: center;
+									background-position-y: -8px;
+									background-size: 100% 100%;
+								}
+							`,
+							"pathList": {
+								"row1": [{
+										"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+										"pathImg": "/static/common/lingxiucheng.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										},
+										"navImg": "/static/common/nav.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "领秀城起始点"
+										}
+									},
+									{
+										"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+										"pathImg": "/static/common/quanchenggongyuan.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										},
+										"navImg": "/static/common/nav.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "泉城公园起始点"
+										}
+									}
+								],
+								"row2": [{
+										"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+										"pathImg": "/static/common/baihuagongyuan.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										},
+										"navImg": "/static/common/nav.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "百花公园起始点"
+										}
+									},
+									{
+										"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+										"pathImg": "/static/common/aotizhongxin.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										},
+										"navImg": "/static/common/nav.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "奥体中心起始点"
+										}
+									}
+								],
+								"row3": [{
+									"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+									"pathImg": "/static/common/muniushan.png",
+									"path": {
+										"ocaId": 1,
+										"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+									},
+									"navImg": "/static/common/nav.png",
+									"point": {
+										"longitude": 117.022194,
+										"latitude": 36.661612,
+										"name": "牧牛山起始点"
+									}
+								}]
+							},
+							"pathListStyle" : {
+								"showLine" : true,
+								"style": "justify-content: flex-start;"
+							},
+							"popupDataList": [{
+									"type": 1,
+									"data": {
+										"title": "小飞龙定向赛",
+										"img": "/static/logo/xfl.png",
+										"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+									}
+								},
+								{
+									type: 2,
+									data: {
+										title: "规则",
+										img: "/static/common/guize.png",
+									}
+								}, {
+									type: 2,
+									data: {
+										title: "奖励",
+										img: "/static/common/jiangli.png",
+									}
+								},
+								"default"
+							]
+						}; */
+
+						this.loadConfig(config);
+						this.matchRsDetailQuery();
+
+						setTimeout(this.dealFirstEnter, 500);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						console.log("matchRsDetailQuery", res);
+						if (checkResCode(res)) {
+							const data = res.data.data;
+							this.mcType = data.mcType;
+							this.mcId = data.mcId;
+							this.mcName = data.mcName;
+							this.beginSecond = data.beginSecond;
+							this.endSecond = data.endSecond;
+							this.nickName = data.nickName;
+							this.totalNum = data.totalNum;
+							this.totalDistanct = data.totalDistanct;
+							this.totalDistanctRankNum = data.totalDistanctRankNum;
+							this.totalCp = data.totalCp;
+							this.totalCpRankNum = data.totalCpRankNum;
+							this.totalSysPoint = data.totalSysPoint;
+							this.totalSysPointRankNum = data.totalSysPointRankNum;
+							this.fastPace = data.fastPace;
+							this.fastPaceRankNum = data.fastPaceRankNum;
+							this.ocaRs = data.ocaRs;
+
+							this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+
+							const rank = JSON.stringify(data);
+							this.dealNotice(rank);
+
+							this.getCountdown();
+							this.getActtime();
+
+							this.clear();
+							this.interval = setInterval(this.getCountdown, 60000);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			btnBack() {
+				// const url = `action://to_home/`;
+				// window.location.href = url;
+				// tools.appAction(url);
+
+				uni.navigateTo({
+					url: "/pages/bm/style3/rankList?" + this.queryString
+				});
+			},
+			btnInfo() {
+				// console.log(this.$refs.mypopup);
+				this.$refs.mypopup.popupOpen();
+			},
+			onOverviewClick(ovtype) {
+				this.queryObj.ovtype = ovtype;
+				this.queryString = tools.objectToQueryString(this.queryObj);
+				uni.navigateTo({
+					url: "/pages/bm/style3/rankList?" + this.queryString
+				});
+			},
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		/* height: 100vh; */
+		overflow-x: scroll;
+	}
+
+	.top-default {
+		position: relative;
+		z-index: 10;
+		width: 100%;
+		height: 270px;
+		padding-top: 36px;
+		justify-content: space-between;
+		background-image: url("/static/backgroud/top_bg_egg2.png");
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: -8px;
+		background-size: 100% 100%;
+		/* background-size: cover; */
+	}
+
+	/* .top-oval {
+		position: relative;
+		z-index: 0;
+		margin-top: -180px;
+		margin-left: -10%;
+		width: 120%;
+		height: 280px;
+		background: linear-gradient(180deg, #ffffff 12.18%, #eeeeee 100%);
+		border-radius: 50%;
+		text-align: center;
+	}
+
+	.top-oval-text {
+		color: #333333;
+		font-size: 13px;
+		line-height: 386px;
+		pointer-events: auto;
+	}
+ */
+	.topbar {
+		width: 90%;
+		justify-content: space-between;
+	}
+
+	.topbar-color-default {
+		color: #333333;
+	}
+
+	.topbar-back {

+		width: 43rpx;

+		height: 43rpx;

+		color: inherit !important;

+		font-size: 48rpx !important;

+		/* opacity: 0; */

+	}
+
+	.topbar-info {
+		width: 46rpx;
+		height: 46rpx;
+	}
+
+	.topbar-rule {
+		font-size: 32rpx;
+	}
+
+	.mcName {
+		font-size: 40rpx;
+		font-weight: 550;
+	}
+
+	.topbtm {
+		width: 100%;
+		/* height: 60rpx; */
+		margin-bottom: 40px;
+		justify-content: space-evenly;
+	}
+
+	.topbtm-name {
+		/* width: 320rpx; */
+		/* height: 28px; */
+		padding: 5px 12px;
+		background-color: #9fda39;
+		border-radius: 5px;
+		/* backdrop-filter: blur(30px); */
+		text-align: center;
+		font-weight: 500;
+		color: #497400;
+		font-size: 14px;
+	}
+
+	.mid {
+		width: 90%;
+		height: 120px;
+		position: relative;
+		z-index: 20;
+		margin-top: -100px;
+		background: #ffffff;
+		border-radius: 9px;
+		box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.13);
+		font-family: Source Han Sans CN;
+	}
+
+	.mid-1 {
+		width: 90%;
+		margin: 12px;
+		font-weight: 500;
+		color: #8e8e8e;
+		font-size: 14px;
+	}
+
+	.mid-2 {
+		width: 92%;
+		/* margin: 0 10px; */
+	}
+
+	.mid-2-value {
+		font-weight: 900;
+		font-size: 22px;
+	}
+
+	.mid-2-text {
+		color: #989898;
+		font-size: 12px;
+	}
+
+	.mid-line {
+		width: 0px;
+		height: 45.04px;
+		border: 1px solid;
+		border-color: #e6e6e6;
+	}
+
+	.overview-1 {
+		width: 111px;
+		height: 54px;
+		background: #ffb40b;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-2 {
+		margin-top: -43px;
+		color: #ffffff;
+		font-size: 18px;
+		pointer-events: auto;
+	}
+
+	.overview-3 {
+		width: 111px;
+		height: 54px;
+		background: #f39509;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-4 {
+		width: 111px;
+		height: 54px;
+		background: #81cd00;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-5 {
+		width: 111px;
+		height: 54px;
+		background: #64cbb0;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.ovline1 {
+		margin-top: 9px;
+		color: #ffffff;
+		font-size: 12px;
+	}
+
+	.ovline2 {
+		color: #ffffff;
+		font-size: 16px;
+	}
+
+	.main {
+		width: 100%;
+		margin-top: 20px;
+		margin-bottom: 10px;
+		/* height: 70vh; */
+		justify-content: space-around;
+		/* justify-content: space-between; */
+	}
+
+	.main-title {
+		margin-bottom: 10px;
+		font-weight: 550;
+		color: #333333;
+		font-size: 16px;
+	}
+</style>

+ 685 - 0
card/pages/bm/style3/signup.vue

@@ -0,0 +1,685 @@
+<!-- 
+[报名] 样式3 - 报名
+http://localhost:5173/card/#/pages/bm/style3/signup
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style3/signup
+ -->
+<template>
+	<view class="body">
+		<view class="content uni-column">
+			<view class="uni-column" :class="cssTop">
+				<view class="topbar uni-row" :class="cssTopbarColor">
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
+					<text class="mcName">{{mcName}}</text>
+					<text class="topbar-rule" @click="btnInfo">规则</text>
+				</view>
+			</view>
+			<view class="main uni-column">
+				<view class="timebar uni-row">
+					<image mode="aspectFit" class="clock" src="/static/default/clock.png"></image>
+					<text class="acttime">{{acttime}}</text>
+				</view>
+				
+				<input class="uni-input" maxlength="30" placeholder="请填写姓名" v-model="nickName" />
+
+				<view class="introduce uni-column">
+					<text class="introduce-title">{{introduce.title}}</text>
+					<text class="introduce-content">{{introduce.content}}</text>
+				</view>
+				<button class="btnSignup btnSignup-enable" v-if="mcState<=1" @click="btnSignup">报 名</button>
+				<button class="btnSignup btnSignup-disable" v-if="mcState==2">活动已结束</button>
+			</view>
+
+			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
+
+			<uni-popup ref="alertDialog" type="dialog">
+				<uni-popup-dialog type="info" cancelText="取消" confirmText="确认" title="您填写的姓名:" @confirm="dialogConfirm"
+					@close="dialogClose">
+					<view class="dialog-content uni-column">
+						<text class="dialog-content-1">{{nickName}}</text>
+					</view>
+				</uni-popup-dialog>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '../../../common/tools';
+	import {
+		defaultPopUpDataList
+	} from '../../../common/define';
+	import {
+		token,
+		apiCardDetailQuery,
+		apiOnlineMcSignUpDetail,
+		apiOnlineMcSignUp,
+		apiCardConfigQuery,
+		apiMatchRsDetailQuery,
+		checkResCode,
+		checkToken
+	} from '../../../common/api';
+
+	export default {
+		data() {
+			return {
+				pageName: "signup",
+				firstEnterKey: 'firstEnter-bm-style3',
+				rankKey: "rank-bm-style3",
+				queryObj: {},
+				queryString: "",
+				from: "", // 来源页面
+				token: "",
+				ecId: 0, // 卡片id
+				mcId: 0, // 赛事id
+				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				mcName: "", // 赛事名称
+				acttime: "", // 活动时间
+				beginSecond: null, // 活动或赛事开始时间戳,单位秒
+				endSecond: null, // 活动或赛事结束时间戳,单位秒
+				coiId: 0, // 已报名单位id
+				coiName: "", // 已报名单位名称,可为空
+				teamNum: 0, // 已报名队伍编号,可为0
+				nickName: "", // 昵称
+				// coiRs: [], // 组织信息集合
+				// orgList: [], // 分组下拉列表数据源
+				// teamList: [], // 
+				interval: null,
+
+				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				// teamType: 0, // 队伍类型  0: 红黄蓝紫 1: 学生/家长
+				cssTop: "",
+				cssTopbarColor: "",
+				cssLogo: "",
+				introduce: {
+					title: "",
+					content: ""
+				},
+				popupDataList: [],
+			}
+		},
+		computed: {},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log(query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.from = query["from"] ?? "";
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+
+			this.firstEnterKey += "-" + this.ecId;
+			console.log("firstEnterKey:", this.firstEnterKey);
+
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+
+			tools.removeCssCode();
+
+			this.getCardConfigQuery();
+			this.getCardDetailQuery();
+			this.matchRsDetailQuery();
+		},
+		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
+		onReady() {
+			// this.dealFirstEnter();
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			dealNotice(rank) {
+				// console.log('[dealNotice]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							// that.notice = true;
+							that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						// that.notice = false;
+						that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			dealFirstEnter() {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.firstEnterKey,
+					success: (res) => {
+						console.log('[getStorage]', that.firstEnterKey, res.data);
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.firstEnterKey, e);
+						that.btnInfo();
+						that.setFirstEnterValue(true);
+					},
+				})
+			},
+			setFirstEnterValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.firstEnterKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.firstEnterKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.firstEnterKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+
+				// 加载CSS样式
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+
+					if (css.indexOf(".top{") >= 0) {
+						this.cssTop = "top";
+					}
+					if (css.indexOf(".topbar-color{") >= 0) {
+						this.cssTopbarColor = "topbar-color";
+					}
+				}
+
+				if (this.cssTop == "") {
+					this.cssTop = "top-default";
+				}
+				if (this.cssTopbarColor == "") {
+					this.cssTopbarColor = "topbar-color-default";
+				}
+				console.log("[loadConfig] cssTop:", this.cssTop);
+				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
+
+				// 加载队伍类型  0: 红黄蓝紫 1: 学生/家长
+				/* if (config.teamType != undefined && config.teamType >= 0) {
+					this.teamType = config.teamType;
+				} */
+
+				// 加载介绍内容
+				const introduce = config.introduce;
+				if (introduce != undefined) {
+					if (introduce.title != undefined) {
+						this.introduce.title = introduce.title;
+					}
+					if (introduce.content != undefined) {
+						this.introduce.content = introduce.content;
+					}
+				}
+
+				// 加载弹窗数据
+				const popupDataList = config.popupDataList;
+				// console.log("[loadConfig] popupDataList:", popupDataList);
+				if (popupDataList != undefined && popupDataList.length > 0) {
+					for (var i = 0; i < popupDataList.length; i++) {
+						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
+						if (popupDataList[i] == 'default') {
+							for (var j = 0; j < defaultPopUpDataList.length; j++) {
+								this.popupDataList.push(defaultPopUpDataList[j]);
+							}
+						} else {
+							this.popupDataList.push(popupDataList[i]);
+						}
+					}
+				} else {
+					this.popupDataList = defaultPopUpDataList;
+					console.log("[loadConfig] popupDataList 加载默认列表");
+				}
+				// console.log("[loadConfig] popupDataList:", this.popupDataList);
+			},
+			fmtMcTime(timestamp) {
+				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				// var Y = date.getFullYear() + '-';
+				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+
+				const timeStr = M + D + h + m;
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			// 获取倒计时
+			getActtime() {
+				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
+			},
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardConfigQuery", res)
+						const data = res.data.data;
+						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", data.configJson);
+						/* const config = {
+							"css": `
+								.top{
+									width: 100%;
+									height: 170px;
+									padding-top: 36px;
+									justify-content: space-between;
+									background-image: url('static/backgroud/top_bg_egg3.png');
+									background-repeat: no-repeat;
+									background-position: center;
+									background-size: cover;
+								}
+								.topbar-color{
+									color: #333333;
+								}
+								.btnSignup-enable {
+									background-color: #ff870e !important;
+								}
+								.swiper-item-button {
+									background-color: #ff870e !important;
+								}
+							`,
+							"popupDataList": [{
+									"type": 1,
+									"data": {
+										"title": "小飞龙定向赛",
+										"img": "/static/common/egg.png",
+										"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+									}
+								},
+								"default"
+							],
+							"introduce": {
+								"title": "介绍:",
+								"content": " · 小飞龙定向赛再次来袭!这次有五个场地哟~\r\n · 神秘“蛋叔”闪亮登场~\r\n · 蛋叔放大招,百味豆换鸡蛋!\r\n · 时不可待!冲鸭!\r\n\r\n · 能不能把蛋叔整郁闷,就看你的啦~\r\n · 还等啥?火速报名吧!"
+							}
+						}; */
+
+						this.loadConfig(config);
+
+						setTimeout(this.dealFirstEnter, 500);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 卡片信息查询
+			getCardDetailQuery() {
+				uni.request({
+					url: apiCardDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("getCardDetailQuery", res);
+						const data = res.data.data;
+						this.mcType = data.mcType;
+						this.mcId = data.mcId;
+						this.mcName = data.mcName;
+						this.beginSecond = data.beginSecond;
+						this.endSecond = data.endSecond;
+						this.coiId = data.coiId;
+						this.coiName = data.coiName;
+						this.teamNum = data.teamNum;
+
+						this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+
+						this.getActtime();
+						// this.getOnlineMcSignUpDetail();
+
+						this.clear();
+						this.interval = setInterval(this.getActtime, 60000);
+					},
+					fail: (err) => {
+						console.log("getCardDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("matchRsDetailQuery", res);
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							const rank = JSON.stringify(data);
+							this.dealNotice(rank);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片用户当前排名查询
+			// getUserCurrentRankNumQuery() {
+			// 	uni.request({
+			// 		url: apiUserCurrentRankNumQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getUserCurrentRankNumQuery", res)
+			// 			if (res.data.code == 0) {
+			// 				const data = res.data.data;
+			// 				const rankNum = data.rankNum;
+			// 				this.dealNotice(rankNum);
+			// 			}
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getUserCurrentRankNumQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 线上赛报名页面信息详情
+			/* getOnlineMcSignUpDetail() {
+				uni.request({
+					url: apiOnlineMcSignUpDetail,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcId: this.mcId,
+					},
+					success: (res) => {
+						// console.log("getOnlineMcSignUpDetail", res)
+						this.coiRs = res.data.data.coiRs;
+						const rsNum = this.coiRs.length;
+						this.orgList = [];
+						for (let i = 0; i < rsNum; i++) {
+							this.orgList[i] = {};
+							this.orgList[i].value = this.coiRs[i].coiId;
+							this.orgList[i].text = this.coiRs[i].coiName;
+							this.orgList[i].teamNum = this.coiRs[i].teamNum;
+						}
+						// console.log("orgList", this.orgList);
+						if (this.coiId > 0) {
+							this.orgChange(this.coiId, false);
+						}
+					},
+					fail: (err) => {
+						console.log("getOnlineMcSignUpDetail err", err)
+					},
+				});
+			}, */
+			// 线上赛报名
+			onlineMcSignUp() {
+				uni.request({
+					url: apiOnlineMcSignUp,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcId: this.mcId,
+						coiId: this.coiId,
+						selectTeam: this.teamNum,
+						nickName: this.nickName
+					},
+					success: (res) => {
+						// console.log("onlineMcSignUp", res);
+
+						if (checkResCode(res)) {
+							uni.showToast({
+								title: '比赛报名成功!',
+								icon: 'none',
+								duration: 3000
+							});
+
+							uni.navigateTo({
+								// url: '/pages/bm/style3/rankOverview?' + this.queryString
+								url: '/pages/bm/style3/rankList?' + this.queryString
+							});
+						}
+					},
+					fail: (err) => {
+						console.log("onlineMcSignUp err", err);
+						uni.showToast({
+							title: '出错了,报名失败',
+							icon: 'none',
+							duration: 3000
+						});
+					},
+				});
+			},
+			btnBack() {
+				// console.log("from:", this.from)
+				if (this.from != '') {
+					// window.history.back();
+					uni.navigateTo({
+						url: '/pages/bm/style3/rankList?' + this.queryString
+					});
+				} else {
+					const url = `action://to_home/`;
+					// window.location.href = url;
+					tools.appAction(url);
+				}
+			},
+			btnInfo() {
+				this.$refs.mypopup.popupOpen();
+			},
+			btnSignup() {
+				if (!checkToken(this.token)) {
+					return;
+				}
+
+				if (!(this.nickName.trim().length > 0)) {
+					uni.showToast({
+						title: '请填写姓名',
+						icon: 'none',
+						duration: 2000
+					});
+					return;
+				}
+
+				this.nickName = this.nickName.trim();
+				this.$refs.alertDialog.open();
+			},
+			dialogConfirm() {
+				this.onlineMcSignUp();
+			},
+			dialogClose() {}
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		height: 100vh;
+	}
+
+	.top-default {
+		width: 100%;
+		height: 170px;
+		padding-top: 36px;
+		justify-content: space-between;
+		background-image: url("/static/backgroud/top_bg_egg3.png");
+		background-repeat: no-repeat;
+		background-position: center;
+		background-size: cover;
+	}
+
+	.topbar {
+		width: 90%;
+		justify-content: space-between;
+	}
+
+	.topbar-color-default {
+		color: #333333;
+	}
+
+	.topbar-back {

+		width: 43rpx;

+		height: 43rpx;

+		color: inherit !important;

+		font-size: 48rpx !important;

+		/* opacity: 0; */

+	}
+
+	.topbar-rule {
+		font-size: 32rpx;
+	}
+
+	.mcName {
+		font-size: 40rpx;
+		font-weight: 550;
+	}
+
+	.main {
+		width: 76%;
+		min-height: 800rpx;
+		/* margin-top: 20rpx; */
+		justify-content: space-around;
+	}
+
+	.timebar {
+		width: 80%;
+		height: 65rpx;
+		margin-top: 20rpx;
+		padding: 0 50rpx;
+		justify-content: space-evenly;
+		background: #ffffff;
+		border: 0.5px solid;
+		border-color: #e7e7e7;
+		border-radius: 20px;
+		box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.13);
+	}
+
+	.acttime {
+		font-weight: 550;
+		color: #333333;
+		font-size: 30rpx;
+	}
+
+	.clock {
+		width: 30rpx;
+		height: 30rpx;
+		margin-right: 20rpx;
+	}
+	
+	.uni-input {
+		width: 90%;
+		height: 85rpx;
+		/* margin-top: 30rpx; */
+		padding: 0 30rpx;
+		background: #f1f1f1;
+		border-radius: 9px;
+	}
+	
+	.input-placeholder {
+		color: #333333;
+		font-size: 16px;
+	}
+
+	.introduce {
+		width: 100%;
+		margin-top: 10rpx;
+		margin-bottom: 30rpx;
+		align-items: flex-start;
+		justify-content: space-around;
+	}
+
+	.introduce-title {
+		color: #333333;
+		font-size: 30rpx;
+		line-height: 60rpx;
+		font-family: Source Han Sans CN;
+	}
+
+	.introduce-content {
+		color: #333333;
+		font-size: 25rpx;
+		line-height: 36rpx;
+		font-family: Source Han Sans CN;
+	}
+
+	.btnSignup {
+		width: 100%;
+		height: 100rpx;
+		margin-bottom: 30rpx;
+		color: white;
+		font-weight: bold;
+		line-height: 100rpx;
+		border-radius: 55rpx;
+	}
+
+	.btnSignup-enable {
+		background-color: #81cd00;
+	}
+
+	.btnSignup-disable {
+		background-color: #c3c3c3;
+	}
+
+	.dialog-content {
+		width: 279px;
+		height: 110px;
+		background: #f1f1f1;
+		border-radius: 9px;
+		justify-content: center;
+		text-align: center;
+		font-weight: 550;
+		color: #333333;
+	}
+
+	.dialog-content-1 {
+		font-size: 40rpx;
+	}
+
+</style>

+ 269 - 0
card/pages/bm/style4/cardconfig.md

@@ -0,0 +1,269 @@
+卡片页面定制
+
+[山大]
+
+index卡片URL参数:type=团建活动&btnText=进入活动
+signup卡片URL参数:labelName=姓名&labelOrg=院系
+
+"index": {
+	"css": "
+		.content-bg{
+			background: url('static/cardbg/shanda.png');
+			background-size: cover;
+		}
+		.logo{
+			width: 40vw;
+			height: 40vw;
+			background: url('static/logo/sddx.png') no-repeat center;
+			background-size: contain;
+		}
+		.mod-text{
+			color: #ffffff !important;
+		}
+		.mod-button{
+			color: #942914 !important;
+			background-color: #ffffff !important;
+		}
+	"
+},
+"signup": {
+	"css": "
+		.top{
+			width: 100%;
+			height: 170px;
+			padding-top: 36px;
+			justify-content: space-between;
+			background-image: url('static/backgroud/top_bg_egg3.png');
+			background-repeat: no-repeat;
+			background-position: center;
+			background-size: cover;
+		}
+		.topbar-color{
+			color: #333333;
+		}
+		.btnSignup-enable {
+			background-color: #ff870e !important;
+		}
+		.swiper-item-button {
+			background-color: #ff870e !important;
+		}
+	",
+	"popupDataList": [{
+			"type": 1,
+			"data": {
+				"title": "小飞龙定向赛",
+				"img": "/static/common/egg.png",
+				"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "规则",
+				img: "/static/common/guize.png",
+			}
+		}, {
+			type: 2,
+			data: {
+				title: "奖励",
+				img: "/static/common/jiangli.png",
+			}
+		},
+		"default"
+	],
+	"introduce": {
+		"title": "介绍:",
+		"content": " · 小飞龙定向赛再次来袭!这次有五个场地哟~\r\n · 神秘“蛋叔”闪亮登场~\r\n · 蛋叔放大招,百味豆换鸡蛋!\r\n · 时不可待!冲鸭!\r\n\r\n · 能不能把蛋叔整郁闷,就看你的啦~\r\n · 还等啥?火速报名吧!"
+	}
+},
+"rankOverview": {
+	"css": "
+		.top{
+			position: relative;
+			z-index: 10;
+			width: 100%;
+			height: 270px;
+			padding-top: 36px;
+			justify-content: space-between;
+			background-image: url('static/backgroud/top_bg_egg2.png');
+			background-repeat: no-repeat;
+			background-position-x: center;
+			background-position-y: -8px;
+			background-size: 100% 100%;
+		}
+	",
+	"pathList": {
+		"row1": [{
+				"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+				"pathImg": "/static/common/lingxiucheng.png",
+				"path": {
+					"ocaId": 1,
+					"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				},
+				"navImg": "/static/common/nav.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "领秀城起始点"
+				}
+			},
+			{
+				"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+				"pathImg": "/static/common/quanchenggongyuan.png",
+				"path": {
+					"ocaId": 1,
+					"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				},
+				"navImg": "/static/common/nav.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "泉城公园起始点"
+				}
+			}
+		],
+		"row2": [{
+				"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+				"pathImg": "/static/common/baihuagongyuan.png",
+				"path": {
+					"ocaId": 1,
+					"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				},
+				"navImg": "/static/common/nav.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "百花公园起始点"
+				}
+			},
+			{
+				"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+				"pathImg": "/static/common/aotizhongxin.png",
+				"path": {
+					"ocaId": 1,
+					"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				},
+				"navImg": "/static/common/nav.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "奥体中心起始点"
+				}
+			}
+		],
+		"row3": [{
+			"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+			"pathImg": "/static/common/muniushan.png",
+			"path": {
+				"ocaId": 1,
+				"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+			},
+			"navImg": "/static/common/nav.png",
+			"point": {
+				"longitude": 117.022194,
+				"latitude": 36.661612,
+				"name": "牧牛山起始点"
+			}
+		}]
+	},
+	"pathListStyle" : {
+		"showLine" : true,
+		"style": "justify-content: flex-start;"
+	},
+	"popupDataList": [{
+			"type": 1,
+			"data": {
+				"title": "小飞龙定向赛",
+				"img": "/static/common/egg.png",
+				"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "规则",
+				img: "/static/common/guize.png",
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "奖励",
+				img: "/static/common/jiangli.png",
+			}
+		},
+		"default"
+	]
+},
+"rankList": {
+	"css": "
+		.top{
+			width: 100%;
+			height: 170px;
+			padding-top: 36px;
+			justify-content: space-between;
+			background-image: url('static/backgroud/top_bg_egg3.png');
+			background-repeat: no-repeat;
+			background-position: center;
+			background-size: cover;
+		}
+		.topbar-color{
+			color: #333333;
+		}
+		.topbtm-name{
+			background-color: #c77f34 !important;
+			color: #ffffff !important;
+		}
+		.topbtm-egg{
+			background-color: #c6690a !important;
+			color: #ffffff !important;
+		}
+		.btnBack{
+			background-color: #ff870d !important;
+		}
+		.swiper-item-button {
+			background-color: #ff870e !important;
+		}
+		.uni-swiper-dot-active {
+			background: #ff870e !important;
+		}
+	",
+	"tabActiveColor": "#ff870d",
+	"popupDataList": [{
+			"type": 1,
+			"data": {
+				"title": "小飞龙定向赛",
+				"img": "/static/common/egg.png",
+				"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "规则",
+				img: "/static/common/guize.png",
+			}
+		},
+		{
+			type: 2,
+			data: {
+				title: "奖励",
+				img: "/static/common/jiangli.png",
+			}
+		},
+		"default"
+	],
+	"popupExchgList": [{
+			"type": 5,
+			"data": {
+				"title": "兑换地点",
+				"img": "/static/common/wslgwcs.png",
+				"point": {
+					"longitude": 117.022194,
+					"latitude": 36.661612,
+					"name": "万盛隆购物超市"
+				}
+			}
+		}
+	]
+}

+ 481 - 0
card/pages/bm/style4/index.vue

@@ -0,0 +1,481 @@
+<!-- 
+[报名] 样式4 - 卡片页
+http://localhost:5173/card/#/pages/bm/style4/index
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style4/index
+ -->
+<template>
+	<view class="body body-radius">
+		<view class="content" :class="cssContentBg" @click="btnClick">
+			<view class="top uni-row">
+				<view class="top-right uni-row">
+					<image mode="aspectFit" class="clock" src="/static/default/clock.png"></image>
+					<view class="countdown">{{countdown}}</view>
+				</view>
+			</view>
+			<view class="main uni-column">
+				<!-- <image mode="aspectFit" :class="cssLogo" :src="logoSrc"></image> -->
+				<view :class="cssLogo"></view>
+				<view class="uni-row" style="position: relative;">
+					<image v-if="notice" mode="aspectFit" src="/static/common/notice.png" class="notice"></image>
+					<text class="type mod-text">{{type}}</text>
+				</view>
+				<text class="name mod-text">{{ecName}}</text>
+				<button class="button mod-button">{{btnText}}</button>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '../../../common/tools';
+	import {
+		token,
+		ossUrl,
+		apiCardBaseQuery,
+		apiUserJoinCardQuery,
+		apiCardConfigQuery,
+		apiMatchRsDetailQuery
+	} from '../../../common/api';
+	
+	export default {
+		data() {
+			return {
+				// audioSrc: "/static/audio/2.mp3",
+				// audioSrc: "https://oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				// audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				pageName: "index",
+				rankKey: "rank-bm-style4",
+				queryObj: {},
+				queryString: "",
+				token: "",
+				
+				ecId: 0, // 卡片id
+				ecName: '', // 卡片名称
+				ecDesc: '', // 卡片简介
+				beginSecond: null, // 卡片开始时间戳,单位秒
+				endSecond: null, // 卡片结束时间戳,单位秒
+				
+				isJoin: null, // 是否报名
+				isFinished: false, // 赛事是否结束
+				
+				// mcId: 0, // 赛事id
+				// mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				// mcName: "", // 赛事名称
+				
+				countdown: "", // 倒计时
+				interval: null,
+				
+				cssContentBg: "",
+				cssLogo: "",
+				// logoSrc: "",
+				type: "",
+				btnText: "",
+				notice: false,	// 是否显示(小红点)通知图标
+			}
+		},
+		computed: {},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log(query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+			
+			// this.contentBg = "content-bg-" + (query["bg"] ?? "green");
+			// this.logoSrc = "/static/logo/" + (query["logo"] ?? "jbs") + '.png';
+			this.type = query["type"] ?? "锦标赛";
+			this.btnText = query["btnText"] ?? "开始比赛";
+			
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+			
+			tools.removeCssCode();
+			
+			this.getCardBaseQuery();
+			this.getCardConfigQuery();
+			this.matchRsDetailQuery();
+		},
+		onShow() {
+			this.getUserJoinCardQuery();
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			playMusic() {
+				// if (this.$audio.audioStatus == 0 || this.$audio.audioSrc != this.audioSrc) {
+				// 	this.$audio.playAudio(this.audioSrc);
+				// }
+			},
+			dealNotice(rank) {
+				// console.log('[dealNotice]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							that.notice = true;
+							// that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						that.notice = true;
+						// that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+					
+					if (css.indexOf(".content-bg{") >= 0) {
+						this.cssContentBg = "content-bg";
+					}
+					if (css.indexOf(".logo{") >= 0) {
+						this.cssLogo = "logo";
+					}
+				}
+				
+				if (this.cssContentBg == "") {
+					this.cssContentBg = "content-bg-default";
+				}
+				if (this.cssLogo == "") {
+					this.cssLogo = "logo-default";
+				}
+				console.log("[loadConfig] cssContentBg:", this.cssContentBg);
+				console.log("[loadConfig] cssLogo:", this.cssLogo);
+			},
+			// 获取倒计时
+			getCountdown() {
+				// console.log(this.endSecond)
+				if (this.endSecond > 0) {
+					const now = Date.now() / 1000;
+					const dif = this.endSecond - now;
+					// const dif = 3600*24 - 60;
+					if (dif > 0) {
+						this.countdown = tools.convertSecondsToDHM(dif);
+					} else {
+						this.countdown = "已结束";
+						this.isFinished = true;
+					}
+					// this.countdown = tools.convertSecondsToHMS(dif);
+				} else {
+					this.countdown = "--天--小时";
+				}
+			},
+			// 卡片基本信息查询
+			getCardBaseQuery() {
+				uni.request({
+					url: apiCardBaseQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardBaseQuery", res)
+						const data = res.data.data;
+						
+						this.ecName = data.ecName;
+						this.ecDesc = data.ecDesc;
+						this.beginSecond = data.beginSecond;
+						this.endSecond = data.endSecond;
+						
+						this.getCountdown();
+						
+						this.clear();
+						this.interval = setInterval(this.getCountdown, 60000);
+					},
+					fail: (err) => {
+						console.log("getCardBaseQuery err", err)
+					},
+				});
+			},
+			// 卡片配置信息查询
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						console.log("getCardConfigQuery", res);
+						const data = res.data.data;
+						// const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", config);
+						const config = {
+						"css": `
+							.content-bg{
+								background: url('static/cardbg/shanda.png');
+								background-size: cover;
+							}
+							.logo{
+								width: 40vw;
+								height: 40vw;
+								background: url('static/logo/sddx.png') no-repeat center;
+								background-size: contain;
+							}
+							.mod-text{
+								color: #ffffff !important;
+							}
+							.mod-button{
+								color: #942914 !important;
+								background-color: #ffffff !important;
+							}
+						`
+						};
+						
+						this.loadConfig(config);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 用户是否已经报名卡片对应赛事查询
+			getUserJoinCardQuery() {
+				uni.request({
+					url: apiUserJoinCardQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("getUserJoinCardQuery", res)
+						const code = res.data.code;
+						const data = res.data.data;
+						if (code == 0) {
+							this.isJoin = data.isJoin;
+							/*if (this.isJoin) {
+								this.btnText = "已报名";
+							} else {
+								this.btnText = "未报名";
+							} */
+						}
+					},
+					fail: (err) => {
+						console.log("getUserJoinCardQuery err", err)
+					},
+				});
+			},
+			// 卡片用户当前排名查询
+			// getUserCurrentRankNumQuery() {
+			// 	uni.request({
+			// 		url: apiUserCurrentRankNumQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getUserCurrentRankNumQuery", res)
+			// 			if (res.data.code == 0) {
+			// 				const data = res.data.data;
+			// 				const rankNum = data.rankNum;
+			// 				this.dealNotice(rankNum);
+			// 			}
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getUserCurrentRankNumQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("matchRsDetailQuery", res);
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							const rank = JSON.stringify(data);
+							this.dealNotice(rank);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			btnClick() {
+				// this.playMusic();
+				
+				if (this.isJoin) {	// 已报名
+					// uni.reLaunch({
+					// 	url: '/pages/bm/style1/rankList?full=true&' + this.queryString
+					// });
+					// window.location.href = `${ossUrl}#/pages/bm/style4/rankOverview?${this.queryString}&full=true`;
+					window.location.href = `${ossUrl}#/pages/bm/style4/rankList?${this.queryString}&full=true`;
+				}
+				else {	// 未报名
+					// uni.reLaunch({
+					// 	url: '/pages/bm/style1/signup?full=true&' + this.queryString
+					// });
+					if (!this.isFinished) {	// 赛事未结束
+						window.location.href = `${ossUrl}#/pages/bm/style4/signup?${this.queryString}&full=true`;
+					}
+					else {	// 赛事已结束
+						// window.location.href = `${ossUrl}#/pages/bm/style4/rankOverview?${this.queryString}&full=true`;
+						window.location.href = `${ossUrl}#/pages/bm/style4/rankList?${this.queryString}&full=true`;
+					}
+				}
+			}
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		height: 100vh;
+	}
+
+	.content-bg-default {
+		background: linear-gradient(180deg, #7aedff 0%, #047200 100%);
+		/* background: linear-gradient(180deg, #178bff 0%, #004d9b 100%); */
+		/* background: linear-gradient(180deg, #7aedff 0%, #8d2219 100%); */
+	}
+	
+	.top {
+		width: 100%;
+		justify-content: flex-end;
+	}
+
+	.top-right {
+		min-width: 180rpx;
+		height: 80rpx;
+		margin-top: 30rpx;
+		margin-right: 30rpx;
+		padding-left: 16rpx;
+		padding-right: 16rpx;
+		background-color: rgba(0, 0, 0, 0.3);
+		border-radius: 12px;
+	}
+
+	.clock {
+		width: 50rpx;
+		height: 50rpx;
+		margin-right: 12rpx;
+	}
+
+	.countdown {
+		min-width: 120rpx;
+		text-align: center;
+		font-family: Roboto;
+		color: #ffffff;
+		font-size: 46rpx;
+		/* letter-spacing: 2rpx; */
+	}
+
+	.main {
+		width: 100%;
+		height: 700rpx;
+		margin-top: 20rpx;
+		justify-content: space-evenly;
+	}
+
+	.logo-default {
+		width: 50vw;
+		height: 50vw;
+		background-image: url('/static/logo/jbs.png');
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: center;
+		background-size: contain;
+	}
+
+	.notice {
+		width: 30rpx;
+		height: 30rpx;
+		/* margin-right: 30rpx; */
+		position: absolute;
+		left: -60rpx;
+	}
+	
+	.type {
+		opacity: 60%;
+		/* line-height: 25px; */
+		font-family: Roboto;
+		color: #ffffff;
+		font-size: 40rpx;
+		text-align: center;
+	}
+
+	.name {
+		font-family: Roboto;
+		color: #ffffff;
+		font-size: 50rpx;
+		text-align: center;
+	}
+
+	.button {
+		width: 320rpx;
+		height: 86rpx;
+		margin-top: 30rpx;
+		color: #000000;
+		background: #ffffff;
+		border-radius: 56rpx;
+		font-size: 46rpx;
+		line-height: 80rpx;
+	}
+	
+	/* .mod-text {
+		color: #FF6203 !important;
+	}
+	
+	.mod-button {
+		color: #ffffff !important;
+		background-color: #FF6203 !important;
+	} */
+	
+</style>

+ 862 - 0
card/pages/bm/style4/rankList.vue

@@ -0,0 +1,862 @@
+<!-- 
+[报名] 样式3 - 排名列表
+http://localhost:5173/card/#/pages/bm/style4/rankList
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style4/rankList
+ -->
+<template>
+	<view class="body">
+		<view class="content uni-column">
+			<view class="uni-column" :class="cssTop">
+				<view class="topbar uni-row" :class="cssTopbarColor">
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
+					<text class="mcName">{{mcName}}</text>
+					<text class="topbar-rule" @click="btnInfo">规则</text>
+					<!-- <image mode="aspectFit" class="topbar-info" @click="btnInfo" src="/static/default/info.png"></image> -->
+				</view>
+
+				<view class="topcontent uni-column uni-jcsa">
+					<view class="logo"></view>
+					<view class="tcbar uni-row uni-jcsb">
+						<text class="tcbar-text">赛事总里程:{{fmtDistanct(totalDistance)}} 千米</text>
+						<text class="tcbar-text">校园文化输出:{{totalRightAnswerNum}} 次</text>
+					</view>
+				</view>
+
+				<!-- <view class="topbtm uni-row">
+					<view class="topbtm-egg" @click="btnMyEgg">蛋叔券</view>
+					<text class="topbtm-name">{{nickName}}</text>
+					<view class="topbtm-egg" @click="btnExchg">兑换地址</view>
+				</view> -->
+			</view>
+			<view class="main uni-column">
+				<my-tab ref="tab1" :tabItems="tab1Items" :type="1" @onTabClick="onTab1Click" @onSelectChange="onSelectChange"></my-tab>
+				<my-tab ref="tab2" :tabItems="tab2Items" :tabItemsMark="tab2ItemsMark" :type="0" @onTabClick="onTab2Click" :fontSize="12"></my-tab>
+				
+				<view class="tab-view uni-column">
+					<!-- 团体成绩列表 -->
+					<template v-if="tab1Current==0" v-for="(item, index) in rank1List" :key="index">
+						<my-ranklist v-show="tab2Current === index" :rankRs="rankList[item]"
+							:rank-type="rankTypeList[index]"></my-ranklist>
+					</template>
+						
+					<!-- 个人成绩列表 -->
+					<template v-if="tab1Current==1" v-for="(item, index) in rank2List" :key="index">
+						<my-ranklist v-show="tab2Current === index" :rankRs="rankList[item]"
+							:rank-type="rankTypeList[index]"></my-ranklist>
+					</template>
+				</view>
+
+				<button class="btnBack" @click="btnStartGame">我要比赛</button>
+				<!-- <button class="btnBack" @click="btnBack">返回</button> -->
+			</view>
+
+			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
+			<my-popup ref="mypopupExchg" :dataList="popupExchgList"></my-popup>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	import {
+		teamName,
+		defaultPopUpDataList
+	} from '/common/define';
+	import {
+		token,
+		apiMatchRsDetailQuery,
+		apiCardRankDetailQuery,
+		apiCardConfigQuery,
+		apiUserCurrentRankNumQuery,
+		apiIsAllowMcSignUp,
+		apiMapListQuery,
+		apiCompStatisticQuery,
+		checkResCode
+	} from '/common/api';
+
+	export default {
+		data() {
+			return {
+				pageName: "rankList",
+				firstEnterKey: 'firstEnter-bm-style4',
+				rankKey: "rank-bm-style4",
+				queryObj: {},
+				queryString: "",
+				token: "",
+				ovtype: "",
+
+				ecId: 0, // 卡片id
+				mcId: 0, // 赛事id
+				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				mcName: "", // 赛事名称
+				acttime: "", // 活动时间
+				beginSecond: null, // 活动或赛事开始时间戳,单位秒
+				endSecond: null, // 活动或赛事结束时间戳,单位秒
+				ocaId: 0, // 关联id,带入到App活动详情页面
+				nickName: "", // 昵称
+				
+				mapList: [], // 卡片对应地图列表详情
+				totalDistance: 0, // 赛事所有人累计里程,单位米
+				totalRightAnswerNum: 0, // 赛事所有人正确答题数(校园文化输出)
+
+				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				allowMcSignUp: false, // 是否允许重新分组
+				countdown: "", // 倒计时
+				rankList: { // 排名列表
+					// totalDistanceRs: [],
+					// totalCpRs: [],
+					// totalSysPointRs: [],
+					// fastPaceRs: []
+				},
+				interval: null,
+
+				teamType: 0, // 队伍类型
+				// dispArrStr: "totalDistance,totalCp,totalSysPoint,fastPace",
+				dispArrStr: "teamCp,teamDistance,teamRightAnswerPer,teamPace,teamSpeed,regionCp,regionDistance,regionRightAnswerPer,regionPace,regionSpeed", // 要显示的集合范围
+				tab1Current: 0,
+				tab2Current: 0,
+				tab1Items: ["团体"],
+				// tab1Items: ["团体", {
+				// 	selectValue: 1,
+				// 	data: [
+				// 		{text: "个人(中心校区)", value: 1},
+				// 		{text: "个人(千佛山校区南区)", value: 2},
+				// 		{text: "个人(兴隆校区)", value: 3}
+				// 	]}
+				// ],
+				// tab2Items: ["总距离", "打点数", "百味豆", "配速"],
+				tab2Items: ["总里程", "累计打点", "校园文化", "最快配速", "单场用时"],
+				tab2ItemsMark: [
+					{textColor: "#ff6203", icon: "static/common/award.png"}
+				],
+				tabActiveColor: "#81cd00",
+				
+				// 成绩类型列表
+				rankTypeList: ["totalDistance", "totalCp", "rightAnswerPer", "fastPace", "speed"],
+				// 团体成绩列表
+				rank1List: ["teamDistanceRs", "teamCpRs", "teamRightAnswerPerRs", "teamPaceRs", "teamSpeedRs"],
+				// 个人成绩列表
+				rank2List: ["regionDistanceRs", "regionCpRs", "regionRightAnswerPerRs", "regionPaceRs", "regionSpeedRs"],
+
+				cssTop: "",
+				cssTopbarColor: "",
+				popupDataList: [],
+				popupExchgList: []
+			}
+		},
+		computed: {},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log(query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+			this.ovtype = query["ovtype"] ?? "";
+
+			this.firstEnterKey += "-" + this.ecId;
+			console.log("firstEnterKey:", this.firstEnterKey);
+
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+
+			tools.removeCssCode();
+
+			this.getCardConfigQuery();
+		},
+		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
+		onReady() {
+			// this.dealFirstEnter();
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			dealNotice(rank) {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							// that.notice = true;
+							that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						// that.notice = false;
+						that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			dealFirstEnter() {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.firstEnterKey,
+					success: (res) => {
+						console.log('[getStorage]', that.firstEnterKey, res.data);
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.firstEnterKey, e);
+						that.btnInfo();
+						that.setFirstEnterValue(true);
+					},
+				})
+			},
+			setFirstEnterValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.firstEnterKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.firstEnterKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.firstEnterKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+
+				// 加载CSS样式
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+
+					if (css.indexOf(".top{") >= 0) {
+						this.cssTop = "top";
+					}
+					if (css.indexOf(".topbar-color{") >= 0) {
+						this.cssTopbarColor = "topbar-color";
+					}
+				}
+
+				if (this.cssTop == "") {
+					this.cssTop = "top-default";
+				}
+				if (this.cssTopbarColor == "") {
+					this.cssTopbarColor = "topbar-color-default";
+				}
+				console.log("[loadConfig] cssTop:", this.cssTop);
+				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
+
+				const tabActiveColor = config.tabActiveColor;
+				if (tabActiveColor != undefined && tabActiveColor.length > 0) {
+					this.tabActiveColor = tabActiveColor;
+				}
+
+				// 加载弹窗数据
+				const popupDataList = config.popupDataList;
+				// console.log("[loadConfig] popupDataList:", popupDataList);
+				if (popupDataList != undefined && popupDataList.length > 0) {
+					for (var i = 0; i < popupDataList.length; i++) {
+						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
+						if (popupDataList[i] == 'default') {
+							for (var j = 0; j < defaultPopUpDataList.length; j++) {
+								this.popupDataList.push(defaultPopUpDataList[j]);
+							}
+						} else {
+							this.popupDataList.push(popupDataList[i]);
+						}
+					}
+				} else {
+					this.popupDataList = defaultPopUpDataList;
+					console.log("[loadConfig] popupDataList 加载默认列表");
+				}
+				// console.log("[loadConfig] popupDataList:", this.popupDataList);
+
+				// 加载弹窗(兑换地点)数据
+				const popupExchgList = config.popupExchgList;
+				if (popupExchgList != undefined && popupExchgList.length > 0) {
+					for (var i = 0; i < popupExchgList.length; i++) {
+						// console.log("[loadConfig] popupExchgList", i, popupExchgList[i]);
+						this.popupExchgList.push(popupExchgList[i]);
+					}
+				}
+				// console.log("[loadConfig] popupExchgList:", this.popupExchgList);
+			},
+			// 获取倒计时
+			getCountdown() {
+				// console.log(this.endSecond)
+				if (this.endSecond > 0) {
+					const now = Date.now() / 1000;
+					const dif = this.endSecond - now;
+					// const dif = 3600*24 - 60;
+					if (dif > 0) {
+						this.countdown = '距结束 ' + tools.convertSecondsToDHM(dif);
+					} else {
+						this.countdown = "活动已结束";
+					}
+					// this.countdown = tools.convertSecondsToHMS(dif);
+				} else {
+					this.countdown = "距结束 --天--小时";
+				}
+			},
+			// 格式化 距离
+			fmtDistanct(val) {
+				return Math.round(val * 100 / 1000) / 100;
+				/* if (val < 10000)
+					return Math.round(val * 10 / 1000) / 10;
+				else
+					return Math.round(val / 1000); */
+			},
+			fmtMcTime(timestamp) {
+				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				// var Y = date.getFullYear() + '-';
+				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+
+				const timeStr = M + D + h + m;
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			// 获取活动时间
+			getActtime() {
+				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
+			},
+			getTeamName(teamType, teamIndex) {
+				return teamName[teamType][teamIndex];
+			},
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardConfigQuery", res)
+						const data = res.data.data;
+						// console.log("configJson", data.configJson);
+						// const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", data.configJson);
+						const config = {
+							"css": `
+							.top{
+								width: 100%;
+								height: 170px;
+								padding-top: 36px;
+								justify-content: space-between;
+								background-image: url('static/backgroud/top_bg_sddx.png');
+								background-repeat: no-repeat;
+								background-position-x: center;
+								background-position-y: bottom;
+								background-size: cover;
+							}
+							.topbar-color{
+								color: #ffffff;
+							}
+							.btnBack{
+								background-color: #a43a07 !important;
+							}
+							.swiper-item-button {
+								background-color: #a43a07 !important;
+							}
+							.uni-swiper-dot-active {
+								background: #a43a07 !important;
+							}
+						`,
+							"tabActiveColor": "#a43a07",
+							"popupDataList": [{
+									"type": 1,
+									"data": {
+										"title": "小飞龙定向赛",
+										"img": "/static/common/egg.png",
+										"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+									}
+								},
+								"default"
+							],
+							"popupExchgList": [{
+								"type": 5,
+								"data": {
+									"title": "兑换地点",
+									"img": "/static/common/wslgwcs.png",
+									"point": {
+										"longitude": 117.022194,
+										"latitude": 36.661612,
+										"name": "万盛隆购物超市"
+									}
+								}
+							}]
+						};
+
+						this.loadConfig(config);
+						this.matchRsDetailQuery();
+
+						setTimeout(this.dealFirstEnter, 500);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 卡片对应活动或赛事详情查询
+			// getCardDetailQuery() {
+			// 	uni.request({
+			// 		url: apiCardDetailQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getCardDetailQuery", res)
+			// 			const data = res.data.data;
+			// 			this.mcType = data.mcType;
+			// 			this.mcId = data.mcId;
+			// 			this.mcName = data.mcName;
+			// 			this.beginSecond = data.beginSecond;
+			// 			this.endSecond = data.endSecond;
+			// 			this.coiName = data.coiName;
+			// 			this.teamNum = data.teamNum;
+
+			// 			this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+
+			// 			this.getCountdown();
+			// 			this.getActtime();
+			// 			this.getCardRankDetailQuery();
+
+			// 			this.clear();
+			// 			this.interval = setInterval(this.getCountdown, 60000);
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getCardDetailQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("matchRsDetailQuery", res);
+						if (checkResCode(res)) {
+							const data = res.data.data;
+							this.mcType = data.mcType;
+							this.mcId = data.mcId;
+							this.mcName = data.mcName;
+							this.beginSecond = data.beginSecond;
+							this.endSecond = data.endSecond;
+							this.nickName = data.nickName;
+							// this.totalNum = data.totalNum;
+							// this.totalDistanct = data.totalDistanct;
+							// this.totalDistanctRankNum = data.totalDistanctRankNum;
+							// this.totalCp = data.totalCp;
+							// this.totalCpRankNum = data.totalCpRankNum;
+							// this.totalSysPoint = data.totalSysPoint;
+							// this.totalSysPointRankNum = data.totalSysPointRankNum;
+							// this.fastPace = data.fastPace;
+							// this.fastPaceRankNum = data.fastPaceRankNum;
+							// this.ocaRs = data.ocaRs;
+
+							this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+
+							this.getCountdown();
+							this.getActtime();
+							this.mapListQuery();
+							this.compStatisticQuery();
+							this.getCardRankDetailQuery();
+
+							this.clear();
+							this.interval = setInterval(this.getCountdown, 60000);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片对应地图列表详情查询
+			mapListQuery() {
+				uni.request({
+					url: apiMapListQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcId: this.mcId
+					},
+					success: (res) => {
+						console.log("mapListQuery", res);
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							this.mapList = data;
+							
+							let mapItems = {
+								selectValue: 0,
+								data: []
+							};
+							for (var i = 0; i < data.length; i++) {
+								if (i == 0) {
+									mapItems.selectValue = data[i].ocaId;
+								}
+								let map  = {};
+								map.text = "个人(" + data[i].mapName + ")";
+								map.value = data[i].ocaId;
+								mapItems.data.push(map);
+							}
+							this.tab1Items.push(mapItems);
+						}
+					},
+					fail: (err) => {
+						console.log("mapListQuery err", err);
+					},
+				});
+			},
+			// 赛事总成绩统计查询
+			compStatisticQuery() {
+				uni.request({
+					url: apiCompStatisticQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcId: this.mcId
+					},
+					success: (res) => {
+						console.log("compStatisticQuery", res);
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							this.totalDistance = data.totalDistance;
+							this.totalRightAnswerNum = data.totalRightAnswerNum;
+						}
+					},
+					fail: (err) => {
+						console.log("compStatisticQuery err", err);
+					},
+				});
+			},
+			// 排名查询
+			getCardRankDetailQuery() {
+				uni.request({
+					url: apiCardRankDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcIdListStr: this.mcId,
+						mcType: this.mcType,
+						ocaId: this.ocaId,
+						dispArrStr: this.dispArrStr
+					},
+					success: (res) => {
+						console.log("getCardRankDetailQuery", res);
+						const rankdata = res.data.data;
+						// this.rankList.totalDistanceRs = rankdata.totalDistanceRs;
+						// this.rankList.totalCpRs = rankdata.totalCpRs;
+						// this.rankList.totalSysPointRs = rankdata.totalSysPointRs;
+						// this.rankList.fastPaceRs = rankdata.fastPaceRs;
+						this.rankList = rankdata;
+					},
+					fail: (err) => {
+						console.log("getCardRankDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片用户当前排名查询
+			// getUserCurrentRankNumQuery() {
+			// 	uni.request({
+			// 		url: apiUserCurrentRankNumQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getUserCurrentRankNumQuery", res)
+			// 			if (res.data.code == 0) {
+			// 				const data = res.data.data;
+			// 				const rankNum = data.rankNum;
+			// 				this.dealNotice(rankNum);
+			// 			}
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getUserCurrentRankNumQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 是否允许重新分组(报名)
+			isAllowMcSignUp() {
+				uni.request({
+					url: apiIsAllowMcSignUp,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("isAllowMcSignUp", res)
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							this.allowMcSignUp = data.allowSignUp;
+						}
+					},
+					fail: (err) => {
+						console.log("isAllowMcSignUp err", err)
+					},
+				});
+			},
+			btnBack() {
+				// window.history.back();
+				/* uni.navigateTo({
+					url: "/pages/bm/style4/rankOverview?" + this.queryString
+				}); */
+
+				const url = `action://to_home/`;
+				// window.location.href = url;
+				tools.appAction(url);
+			},
+			btnStartGame() {
+				uni.navigateTo({
+					url: "/pages/bm/style4/rankOverview?" + this.queryString
+				});
+			},
+			btnInfo() {
+				// console.log(this.$refs.mypopup);
+				this.$refs.mypopup.popupOpen();
+			},
+			btnMyEgg() {
+				uni.navigateTo({
+					url: "/pages/achievement/index2?tabCurrent=2&" + this.queryString
+				});
+			},
+			btnExchg() {
+				this.$refs.mypopupExchg.popupOpen();
+			},
+			onTab1Click(val) {
+				// console.log("onTab1Click: ", val);
+				this.tab1Current = val;
+			},
+			onTab2Click(val) {
+				// console.log("onTab2Click: ", val);
+				this.tab2Current = val;
+			},
+			onSelectChange(val) {
+				console.log("onSelectChange: ", val);
+				this.ocaId = val.value;
+				this.getCardRankDetailQuery();
+			},
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		height: 100vh;
+	}
+
+	.top-default {
+		width: 100%;
+		height: 170px;
+		padding-top: 36px;
+		justify-content: space-between;
+		background-image: url('static/backgroud/top_bg_sddx.png');
+		background-repeat: no-repeat;
+		background-position: center;
+		background-size: cover;
+	}
+
+	.topbar {
+		width: 90%;
+		justify-content: space-between;
+	}
+
+	.topbar-color-default {
+		color: #ffffff !important;
+	}
+
+	.topbar-back {
+		width: 43rpx;
+		height: 43rpx;
+		color: inherit !important;
+		font-size: 48rpx !important;
+		/* opacity: 0; */
+	}
+
+	.topbar-info {
+		width: 46rpx;
+		height: 46rpx;
+	}
+
+	.topbar-rule {
+		font-size: 32rpx;
+	}
+
+	.topcontent {
+		width: 90%;
+		/* height: 90%; */
+		margin-bottom: 20px;
+	}
+
+	.logo {
+		width: 80px;
+		height: 80px;
+		margin-top: 10px;
+		margin-bottom: 10px;
+		background-image: url('/static/logo/sddx.png');
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: center;
+		background-size: contain;
+	}
+
+	.tcbar {
+		width: 92%;
+		padding: 6px 12px;
+		background: #9a300e;
+		border-radius: 6px;
+	}
+
+	.tcbar-text {
+		font-family: Source Han Sans CN;
+		font-weight: 500;
+		color: #f3d809;
+		font-size: 13px;
+	}
+
+	.mcName {
+		font-size: 40rpx;
+		font-weight: 550;
+	}
+
+	.topbtm {
+		width: 100%;
+		margin-bottom: 5px;
+		justify-content: space-around;
+	}
+
+	.topbtm-name {
+		padding: 3px 12px;
+		background-color: #9fda39;
+		border-radius: 5px;
+		text-align: center;
+		font-weight: 500;
+		color: #497400;
+		font-size: 14px;
+	}
+
+	.topbtm-egg {
+		width: 60px;
+		padding: 3px 12px;
+		background-color: #c6690a;
+		border-radius: 50px;
+		text-align: center;
+		color: #ffffff;
+		font-size: 14px;
+	}
+
+	.topbtm-null {
+		width: 60px;
+		padding: 3px 12px;
+	}
+
+	.cal {
+		width: 46rpx;
+		height: 46rpx;
+		margin-right: 20rpx;
+	}
+
+	.main {
+		width: 100%;
+		/* height: 70vh; */
+		flex-grow: 1;
+		justify-content: space-around;
+		/* justify-content: space-between; */
+	}
+
+	/deep/ .tab-active {
+		background-color: #a43a07 !important;
+	}
+
+	.main-tab {
+		width: 90%;
+		margin-top: 20rpx;
+	}
+
+	.tab-view {
+		width: 100%;
+		/* height: 69vh; */
+		flex-grow: 1;
+	}
+
+	.btnBack {
+		width: 70%;
+		/* height: 6vh; */
+		height: 80rpx;
+		/* margin-bottom: 1vh; */
+		margin-bottom: 20rpx;
+		/* font-weight: bold; */
+		color: white;
+		font-size: 32rpx;
+		line-height: 80rpx;
+		border-radius: 27px;
+		background-color: #ff870d;
+	}
+	
+	/* .swiper-item-button {
+		background-color: #ff870e !important;
+	}
+	
+	.uni-swiper-dot-active {
+		background: #ff870e !important;
+	} */
+	
+</style>

+ 764 - 0
card/pages/bm/style4/rankOverview.vue

@@ -0,0 +1,764 @@
+<!-- 
+[报名] 样式3 - 排名总览
+http://localhost:5173/card/#/pages/bm/style4/rankOverview
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style4/rankOverview
+ -->
+<template>
+	<view class="body">
+		<view class="content uni-column">
+			<view class="uni-column" :class="cssTop">
+				<view class="topbar uni-row" :class="cssTopbarColor">
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
+					<text class="mcName" @click="playMusic">{{mcName}}</text>
+					<text class="topbar-rule" @click="btnInfo">规则</text>
+					<!-- <image mode="aspectFit" class="topbar-info" @click="btnInfo" src="/static/default/info.png"></image> -->
+				</view>
+			</view>
+			
+			<view class="mid uni-column">
+				<view class="mid-1 uni-row uni-jcsb">
+					<text>{{nickName}}</text>
+					<text>总场次:{{totalNum}}</text>
+				</view>
+				<view class="mid-2 uni-row uni-jcsa">
+					<view class="uni-column">
+						<text class="mid-2-value" style="color: #ff0045;">{{totalSysPoint}}</text>
+						<text class="mid-2-text">百味豆(个)</text>
+					</view>
+
+					<view class="mid-line"></view>
+
+					<view class="uni-column">
+						<text class="mid-2-value">{{fmtDistanct(totalDistanct)}}</text>
+						<text class="mid-2-text">总里程km</text>
+					</view>
+
+					<view class="mid-line"></view>
+					<view class="uni-column">
+						<text class="mid-2-value">{{totalCp}}</text>
+						<text class="mid-2-text">打点数(个)</text>
+					</view>
+
+					<view class="mid-line"></view>
+
+					<view class="uni-column">
+						<text class="mid-2-value">{{fmtPace(fastPace)}}</text>
+						<text class="mid-2-text">最快配速</text>
+					</view>
+				</view>
+			</view>
+
+			<view class="main uni-column">
+				<text class="main-title">选择比赛路线</text>
+				<my-pathList :style="pathListStyle.style" :pathList="pathList" :mcState="mcState" :showLine="pathListStyle.showLine"></my-pathList>
+			</view>
+
+			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
+			<!-- <my-popup-map ref="mypopupmap" :point="navPoint"></my-popup-map> -->
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '/common/tools';
+	import {
+		defaultPopUpDataList
+	} from '/common/define';
+	import {
+		token,
+		apiMatchRsDetailQuery,
+		apiCardConfigQuery,
+		checkResCode
+	} from '/common/api';
+
+	export default {
+		data() {
+			return {
+				// audioSrc: "/static/audio/2.mp3",
+				// audioSrc: "https://oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				// audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
+				pageName: "rankOverview",
+				firstEnterKey: 'firstEnter-bm-style4',
+				rankKey: "rank-bm-style4",
+				queryObj: {},
+				queryString: "",
+				token: "",
+
+				ecId: 0, // 卡片id
+				mcId: 0, // 赛事id
+				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				mcName: "", // 赛事名称
+				acttime: "", // 活动时间
+				beginSecond: null, // 活动或赛事开始时间戳,单位秒
+				endSecond: null, // 活动或赛事结束时间戳,单位秒
+				nickName: "", // 昵称
+				totalNum: null, // 总场次
+				totalDistanct: null, // 总距离,单位米
+				totalDistanctRankNum: null, // 总距离排名
+				totalCp: null, // 总打点数
+				totalCpRankNum: null, // 总打点数排名
+				totalSysPoint: null, // 总百味豆
+				totalSysPointRankNum: null, // 总百味豆排名
+				fastPace: null, // 个人最快配速
+				fastPaceRankNum: null, // 个人最快配速排名
+				ocaRs: [], // 卡片对应活动集合
+
+				interval: null,
+				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				cssTop: "",
+				cssTopbarColor: "",
+				pathList: {},
+				pathListStyle: {},
+				popupDataList: [],
+				navPoint: {},
+			}
+		},
+		computed: {
+			pathListLen() {
+				return Object.keys(this.pathList).length;
+			}
+		},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log("query:", query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+
+			this.firstEnterKey += "-" + this.ecId;
+			console.log("firstEnterKey:", this.firstEnterKey);
+
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+
+			tools.removeCssCode();
+
+			this.getCardConfigQuery();
+		},
+		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
+		onReady() {
+			// this.dealFirstEnter();
+			// this.playMusic();
+		},
+		onShow() {
+			// uni.showToast({
+			// 	icon: "none",
+			// 	title: "[rankOverview] onShow"
+			// })
+			// if (this.$audio.audioStatus == 2 && this.$audio.audioSrc == this.audioSrc) {
+			// 	this.$audio.play();
+			// }
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			playMusic() {
+				return;
+				// uni.showToast({
+				// 	title: 'playMusic',
+				// 	icon: 'none',
+				// 	duration: 2000
+				// });
+				// if (this.$audio.audioStatus == 0 || this.$audio.audioSrc != this.audioSrc) {
+				// 	this.$audio.playAudio(this.audioSrc);
+				// }
+			},
+			dealNotice(rank) {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							// that.notice = true;
+							that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						// that.notice = false;
+						that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			dealFirstEnter() {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.firstEnterKey,
+					success: (res) => {
+						console.log('[getStorage]', that.firstEnterKey, res.data);
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.firstEnterKey, e);
+						that.btnInfo();
+						that.setFirstEnterValue(true);
+					},
+				})
+			},
+			setFirstEnterValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.firstEnterKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.firstEnterKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.firstEnterKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+
+				// 加载CSS样式
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+
+					if (css.indexOf(".top{") >= 0) {
+						this.cssTop = "top";
+					}
+					if (css.indexOf(".topbar-color{") >= 0) {
+						this.cssTopbarColor = "topbar-color";
+					}
+				}
+
+				if (this.cssTop == "") {
+					this.cssTop = "top-default";
+				}
+				if (this.cssTopbarColor == "") {
+					this.cssTopbarColor = "topbar-color-default";
+				}
+				console.log("[loadConfig] cssTop:", this.cssTop);
+				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
+
+				// 加载比赛路线数据
+				const pathList = config.pathList;
+				// console.log("[loadConfig] pathList:", pathList);
+				if (pathList != undefined) {
+					this.pathList = pathList;
+				}
+				
+				// 加载比赛路线样式
+				const pathListStyle = config.pathListStyle;
+				// console.log("[loadConfig] pathList:", pathList);
+				if (pathListStyle != undefined) {
+					this.pathListStyle = pathListStyle;
+				}
+
+				// 加载弹窗数据
+				const popupDataList = config.popupDataList;
+				// console.log("[loadConfig] popupDataList:", popupDataList);
+				if (popupDataList != undefined && popupDataList.length > 0) {
+					for (var i = 0; i < popupDataList.length; i++) {
+						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
+						if (popupDataList[i] == 'default') {
+							for (var j = 0; j < defaultPopUpDataList.length; j++) {
+								this.popupDataList.push(defaultPopUpDataList[j]);
+							}
+						} else {
+							this.popupDataList.push(popupDataList[i]);
+						}
+					}
+				} else {
+					this.popupDataList = defaultPopUpDataList;
+					console.log("[loadConfig] popupDataList 加载默认列表");
+				}
+				// console.log("[loadConfig] popupDataList:", this.popupDataList);
+			},
+			// 获取倒计时
+			getCountdown() {
+				// console.log(this.endSecond)
+				if (this.endSecond > 0) {
+					const now = Date.now() / 1000;
+					const dif = this.endSecond - now;
+					// const dif = 3600*24 - 60;
+					if (dif > 0) {
+						this.countdown = '距结束 ' + tools.convertSecondsToDHM(dif);
+					} else {
+						this.countdown = "活动已结束";
+					}
+					// this.countdown = tools.convertSecondsToHMS(dif);
+				} else {
+					this.countdown = "距结束 --天--小时";
+				}
+			},
+			// 格式化 距离
+			fmtDistanct(val) {
+				return Math.round(val * 100 / 1000) / 100;
+				/* if (val < 1000)
+					return Math.round(val * 10 / 1000) / 10;
+				else
+					return Math.round(val / 1000); */
+			},
+			// 格式化 配速
+			fmtPace(val) {
+				return tools.convertSecondsToHMS(val, 2);
+			},
+			fmtMcTime(timestamp) {
+				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				// var Y = date.getFullYear() + '-';
+				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+
+				const timeStr = M + D + h + m;
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			// 获取活动时间
+			getActtime() {
+				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
+			},
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardConfigQuery", res)
+						const data = res.data.data;
+						// console.log("configJson", data.configJson);
+						const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", data.configJson);
+						/* const config = {
+							"css": `
+								.top{
+									position: relative;
+									z-index: 10;
+									width: 100%;
+									height: 270px;
+									padding-top: 36px;
+									justify-content: space-between;
+									background-image: url('static/backgroud/top_bg_egg2.png');
+									background-repeat: no-repeat;
+									background-position-x: center;
+									background-position-y: -8px;
+									background-size: 100% 100%;
+								}
+							`,
+							"pathList": {
+								"row1": [{
+										"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+										"pathImg": "/static/common/lingxiucheng.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										},
+										"navImg": "/static/common/nav.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "领秀城起始点"
+										}
+									},
+									{
+										"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+										"pathImg": "/static/common/quanchenggongyuan.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										},
+										"navImg": "/static/common/nav.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "泉城公园起始点"
+										}
+									}
+								],
+								"row2": [{
+										"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+										"pathImg": "/static/common/baihuagongyuan.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										},
+										"navImg": "/static/common/nav.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "百花公园起始点"
+										}
+									},
+									{
+										"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+										"pathImg": "/static/common/aotizhongxin.png",
+										"path": {
+											"ocaId": 1,
+											"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+										},
+										"navImg": "/static/common/nav.png",
+										"point": {
+											"longitude": 117.022194,
+											"latitude": 36.661612,
+											"name": "奥体中心起始点"
+										}
+									}
+								],
+								"row3": [{
+									"type": 3, // 1: 比赛路线  2: 导航到指定地点  3: 比赛路线 + 导航
+									"pathImg": "/static/common/muniushan.png",
+									"path": {
+										"ocaId": 1,
+										"mcType": 3 // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+									},
+									"navImg": "/static/common/nav.png",
+									"point": {
+										"longitude": 117.022194,
+										"latitude": 36.661612,
+										"name": "牧牛山起始点"
+									}
+								}]
+							},
+							"pathListStyle" : {
+								"showLine" : true,
+								"style": "justify-content: flex-start;"
+							},
+							"popupDataList": [{
+									"type": 1,
+									"data": {
+										"title": "小飞龙定向赛",
+										"img": "/static/logo/xfl.png",
+										"content": "济南奥体中心“一场三馆”包括体育场、体育馆、网球馆和游泳馆,呈现出“东荷西柳”的总体布局。 体育场以济南的“市树”柳树为母题,将垂柳柔美飘逸的形态固化为建筑语言。"
+									}
+								},
+								{
+									type: 2,
+									data: {
+										title: "规则",
+										img: "/static/common/guize.png",
+									}
+								}, {
+									type: 2,
+									data: {
+										title: "奖励",
+										img: "/static/common/jiangli.png",
+									}
+								},
+								"default"
+							]
+						}; */
+
+						this.loadConfig(config);
+						this.matchRsDetailQuery();
+
+						setTimeout(this.dealFirstEnter, 500);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						console.log("matchRsDetailQuery", res);
+						if (checkResCode(res)) {
+							const data = res.data.data;
+							this.mcType = data.mcType;
+							this.mcId = data.mcId;
+							this.mcName = data.mcName;
+							this.beginSecond = data.beginSecond;
+							this.endSecond = data.endSecond;
+							this.nickName = data.nickName;
+							this.totalNum = data.totalNum;
+							this.totalDistanct = data.totalDistanct;
+							this.totalDistanctRankNum = data.totalDistanctRankNum;
+							this.totalCp = data.totalCp;
+							this.totalCpRankNum = data.totalCpRankNum;
+							this.totalSysPoint = data.totalSysPoint;
+							this.totalSysPointRankNum = data.totalSysPointRankNum;
+							this.fastPace = data.fastPace;
+							this.fastPaceRankNum = data.fastPaceRankNum;
+							this.ocaRs = data.ocaRs;
+
+							this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+
+							const rank = JSON.stringify(data);
+							this.dealNotice(rank);
+
+							this.getCountdown();
+							this.getActtime();
+
+							this.clear();
+							this.interval = setInterval(this.getCountdown, 60000);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			btnBack() {
+				// const url = `action://to_home/`;
+				// window.location.href = url;
+				// tools.appAction(url);
+
+				uni.navigateTo({
+					url: "/pages/bm/style4/rankList?" + this.queryString
+				});
+			},
+			btnInfo() {
+				// console.log(this.$refs.mypopup);
+				this.$refs.mypopup.popupOpen();
+			},
+			onOverviewClick(ovtype) {
+				this.queryObj.ovtype = ovtype;
+				this.queryString = tools.objectToQueryString(this.queryObj);
+				uni.navigateTo({
+					url: "/pages/bm/style4/rankList?" + this.queryString
+				});
+			},
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		/* height: 100vh; */
+		overflow-x: scroll;
+	}
+
+	.top-default {
+		position: relative;
+		z-index: 10;
+		width: 100%;
+		height: 270px;
+		padding-top: 36px;
+		justify-content: space-between;
+		background-image: url("/static/backgroud/top_bg_egg2.png");
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: -8px;
+		background-size: 100% 100%;
+		/* background-size: cover; */
+	}
+
+	/* .top-oval {
+		position: relative;
+		z-index: 0;
+		margin-top: -180px;
+		margin-left: -10%;
+		width: 120%;
+		height: 280px;
+		background: linear-gradient(180deg, #ffffff 12.18%, #eeeeee 100%);
+		border-radius: 50%;
+		text-align: center;
+	}
+
+	.top-oval-text {
+		color: #333333;
+		font-size: 13px;
+		line-height: 386px;
+		pointer-events: auto;
+	}
+ */
+	.topbar {
+		width: 90%;
+		justify-content: space-between;
+	}
+
+	.topbar-color-default {
+		color: #333333;
+	}
+
+	.topbar-back {
+		width: 43rpx;
+		height: 43rpx;
+		color: inherit !important;
+		font-size: 48rpx !important;
+		/* opacity: 0; */
+	}
+
+	.topbar-info {
+		width: 46rpx;
+		height: 46rpx;
+	}
+
+	.topbar-rule {
+		font-size: 32rpx;
+	}
+
+	.mcName {
+		font-size: 40rpx;
+		font-weight: 550;
+	}
+
+	.topbtm {
+		width: 100%;
+		/* height: 60rpx; */
+		margin-bottom: 40px;
+		justify-content: space-evenly;
+	}
+
+	.topbtm-name {
+		/* width: 320rpx; */
+		/* height: 28px; */
+		padding: 5px 12px;
+		background-color: #9fda39;
+		border-radius: 5px;
+		/* backdrop-filter: blur(30px); */
+		text-align: center;
+		font-weight: 500;
+		color: #497400;
+		font-size: 14px;
+	}
+
+	.mid {
+		width: 90%;
+		height: 120px;
+		position: relative;
+		z-index: 20;
+		margin-top: -100px;
+		background: #ffffff;
+		border-radius: 9px;
+		box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.13);
+		font-family: Source Han Sans CN;
+	}
+
+	.mid-1 {
+		width: 90%;
+		margin: 12px;
+		font-weight: 500;
+		color: #8e8e8e;
+		font-size: 14px;
+	}
+
+	.mid-2 {
+		width: 92%;
+		/* margin: 0 10px; */
+	}
+
+	.mid-2-value {
+		font-weight: 900;
+		font-size: 22px;
+	}
+
+	.mid-2-text {
+		color: #989898;
+		font-size: 12px;
+	}
+
+	.mid-line {
+		width: 0px;
+		height: 45.04px;
+		border: 1px solid;
+		border-color: #e6e6e6;
+	}
+
+	.overview-1 {
+		width: 111px;
+		height: 54px;
+		background: #ffb40b;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-2 {
+		margin-top: -43px;
+		color: #ffffff;
+		font-size: 18px;
+		pointer-events: auto;
+	}
+
+	.overview-3 {
+		width: 111px;
+		height: 54px;
+		background: #f39509;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-4 {
+		width: 111px;
+		height: 54px;
+		background: #81cd00;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.overview-5 {
+		width: 111px;
+		height: 54px;
+		background: #64cbb0;
+		border-radius: 50%;
+		box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
+		pointer-events: auto;
+	}
+
+	.ovline1 {
+		margin-top: 9px;
+		color: #ffffff;
+		font-size: 12px;
+	}
+
+	.ovline2 {
+		color: #ffffff;
+		font-size: 16px;
+	}
+
+	.main {
+		width: 100%;
+		margin-top: 20px;
+		margin-bottom: 10px;
+		/* height: 70vh; */
+		justify-content: space-around;
+		/* justify-content: space-between; */
+	}
+
+	.main-title {
+		margin-bottom: 10px;
+		font-weight: 550;
+		color: #333333;
+		font-size: 16px;
+	}
+</style>

+ 807 - 0
card/pages/bm/style4/signup.vue

@@ -0,0 +1,807 @@
+<!-- 
+[报名] 样式3 - 报名
+http://localhost:5173/card/#/pages/bm/style4/signup
+https://oss-mbh5.colormaprun.com/card/#/pages/bm/style4/signup
+ -->
+<template>
+	<view class="body">
+		<view class="content uni-column">
+			<view class="uni-column" :class="cssTop">
+				<view class="topbar uni-row" :class="cssTopbarColor">
+					<uni-icons type="left" class="topbar-back" @click="btnBack"></uni-icons>
+					<text class="mcName">{{mcName}}</text>
+					<text class="topbar-rule" @click="btnInfo">规则</text>
+				</view>
+				<view class="topcontent uni-column uni-jcsa">
+					<view class="logo"></view>
+					<text class="top-acttime">{{fmtMcTime2(beginSecond, endSecond)}}</text>
+				</view>
+			</view>
+			<view class="main uni-column">
+				<view class="timebar uni-row">
+					<image mode="aspectFit" class="clock" src="/static/default/clock.png"></image>
+					<text class="acttime">{{acttime}}</text>
+				</view>
+
+				<input class="uni-input" maxlength="30" :placeholder="'请填写'+labelName" v-model="nickName" />
+				<e-select v-model="coiId" :options="coiRs" :props="eSelectionProps"
+					clearable :placeholder="'请选择'+labelOrg" @getText="getESelectText" @change="eSelectChange"></e-select>
+
+				<view class="introduce uni-column">
+					<text class="introduce-title">{{introduce.title}}</text>
+					<text class="introduce-content">{{introduce.content}}</text>
+				</view>
+				<button class="btnSignup btnSignup-enable" v-if="mcState<=1" @click="btnSignup">报 名</button>
+				<button class="btnSignup btnSignup-disable" v-if="mcState==2">活动已结束</button>
+			</view>
+
+			<my-popup ref="mypopup" :dataList="popupDataList" :acttime="acttime"></my-popup>
+
+			<!-- <uni-popup ref="alertDialog" type="dialog">
+				<uni-popup-dialog type="info" cancelText="取消" confirmText="确认" title="您填写的姓名:" @confirm="dialogConfirm"
+					@close="dialogClose">
+					<view class="dialog-content uni-column">
+						<text class="dialog-content-1">{{nickName}}</text>
+					</view>
+				</uni-popup-dialog>
+			</uni-popup> -->
+			
+			<uni-popup ref="alertDialog" type="dialog">
+				<uni-popup-dialog type="info" cancelText="取消" confirmText="确认" title="你的报名信息:" @confirm="dialogConfirm"
+					@close="dialogClose">
+					<view class="dialog-content uni-column">
+						<text class="dialog-content-1">{{mcName}}</text>
+						<view class="uni-column uni-ais">
+							<text class="dialog-content-2">{{labelName}}: {{nickName}}</text>
+							<text class="dialog-content-2">{{labelOrg}}: {{coiName}}</text>
+							<!-- <text class="dialog-content-2">{{teamName}}</text> -->
+						</view>
+					</view>
+				</uni-popup-dialog>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from '../../../common/tools';
+	import {
+		defaultPopUpDataList
+	} from '../../../common/define';
+	import {
+		token,
+		apiCardDetailQuery,
+		apiOnlineMcSignUpDetail,
+		apiOnlineMcSignUp,
+		apiCardConfigQuery,
+		apiMatchRsDetailQuery,
+		checkResCode,
+		checkToken
+	} from '../../../common/api';
+
+	export default {
+		data() {
+			return {
+				pageName: "signup",
+				firstEnterKey: 'firstEnter-bm-style4',
+				rankKey: "rank-bm-style4",
+				queryObj: {},
+				queryString: "",
+				from: "", // 来源页面
+				token: "",
+				labelName: "",
+				labelOrg: "",
+				ecId: 0, // 卡片id
+				mcId: 0, // 赛事id
+				mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
+				mcName: "", // 赛事名称
+				acttime: "", // 活动时间
+				beginSecond: null, // 活动或赛事开始时间戳,单位秒
+				endSecond: null, // 活动或赛事结束时间戳,单位秒
+				coiId: 0, // 已报名单位id
+				coiName: "", // 已报名单位名称,可为空
+				teamNum: 0, // 已报名队伍编号,可为0
+				nickName: "", // 昵称
+				coiRs: [], // 组织信息集合
+				// orgList: [], // 分组下拉列表数据源
+				// teamList: [], // 
+				interval: null,
+
+				mcState: 0, // 赛事/活动状态 0: 未开始  1: 进行中  2: 已结束
+				// teamType: 0, // 队伍类型  0: 红黄蓝紫 1: 学生/家长
+				cssTop: "",
+				cssTopbarColor: "",
+				cssLogo: "",
+				introduce: {
+					title: "",
+					content: ""
+				},
+				popupDataList: [],
+
+				eSelectionProps: {
+					text: 'coiName',
+					value: 'coiId',
+					// disabled: 'noallowed'
+				}
+			}
+		},
+		computed: {},
+		onLoad(query) { // 类型非必填,可自动推导
+			// console.log(query);
+			this.queryObj = query;
+			this.queryString = tools.objectToQueryString(this.queryObj);
+			// console.log(queryString);
+			this.from = query["from"] ?? "";
+			this.token = query["token"] ?? token;
+			this.ecId = query["id"] ?? 0;
+			this.labelName = query["labelName"] ?? "昵称";
+			this.labelOrg = query["labelOrg"] ?? "组织";
+
+			this.firstEnterKey += "-" + this.ecId;
+			console.log("firstEnterKey:", this.firstEnterKey);
+
+			this.rankKey += "-" + this.ecId;
+			console.log("rankKey:", this.rankKey);
+
+			tools.removeCssCode();
+
+			this.getCardConfigQuery();
+			this.getCardDetailQuery();
+			this.matchRsDetailQuery();
+		},
+		// 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
+		onReady() {
+			// this.dealFirstEnter();
+		},
+		onUnload() {
+			this.clear();
+		},
+		methods: {
+			dealNotice(rank) {
+				// console.log('[dealNotice]');
+				let that = this;
+				uni.getStorage({
+					key: that.rankKey,
+					success: (res) => {
+						console.log('[getStorage]', that.rankKey, res.data);
+						const oldRank = res.data;
+						if (oldRank != rank) {
+							// that.notice = true;
+							that.setRankValue(rank);
+						}
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.rankKey, e);
+						// that.notice = false;
+						that.setRankValue(rank);
+					},
+				})
+			},
+			setRankValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.rankKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.rankKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.rankKey, e);
+					},
+				})
+			},
+			dealFirstEnter() {
+				// console.log('[dealFirstEnter]');
+				let that = this;
+				uni.getStorage({
+					key: that.firstEnterKey,
+					success: (res) => {
+						console.log('[getStorage]', that.firstEnterKey, res.data);
+					},
+					fail: (e) => {
+						console.log('[getStorage] fail', that.firstEnterKey, e);
+						that.btnInfo();
+						that.setFirstEnterValue(true);
+					},
+				})
+			},
+			setFirstEnterValue(data) {
+				let that = this;
+				uni.setStorage({
+					key: that.firstEnterKey,
+					data: data,
+					success: () => {
+						console.log('[setStorage] success', that.firstEnterKey, data);
+					},
+					fail: (e) => {
+						console.log('[setStorage] fail', that.firstEnterKey, e);
+					},
+				})
+			},
+			clear() {
+				if (this.interval != null) {
+					clearInterval(this.interval);
+					this.interval = null;
+				}
+			},
+			loadConfig(config) {
+				// console.log("config", config);
+
+				// 加载CSS样式
+				const css = config.css;
+				if (css != undefined && css.length > 0) {
+					tools.loadCssCode(css);
+
+					if (css.indexOf(".top{") >= 0) {
+						this.cssTop = "top";
+					}
+					if (css.indexOf(".topbar-color{") >= 0) {
+						this.cssTopbarColor = "topbar-color";
+					}
+				}
+
+				if (this.cssTop == "") {
+					this.cssTop = "top-default";
+				}
+				if (this.cssTopbarColor == "") {
+					this.cssTopbarColor = "topbar-color-default";
+				}
+				console.log("[loadConfig] cssTop:", this.cssTop);
+				console.log("[loadConfig] cssTopbarColor:", this.cssTopbarColor);
+
+				// 加载队伍类型  0: 红黄蓝紫 1: 学生/家长
+				/* if (config.teamType != undefined && config.teamType >= 0) {
+					this.teamType = config.teamType;
+				} */
+
+				// 加载介绍内容
+				const introduce = config.introduce;
+				if (introduce != undefined) {
+					if (introduce.title != undefined) {
+						this.introduce.title = introduce.title;
+					}
+					if (introduce.content != undefined) {
+						this.introduce.content = introduce.content;
+					}
+				}
+
+				// 加载弹窗数据
+				const popupDataList = config.popupDataList;
+				// console.log("[loadConfig] popupDataList:", popupDataList);
+				if (popupDataList != undefined && popupDataList.length > 0) {
+					for (var i = 0; i < popupDataList.length; i++) {
+						// console.log("[loadConfig] popupDataList", i, popupDataList[i]);
+						if (popupDataList[i] == 'default') {
+							for (var j = 0; j < defaultPopUpDataList.length; j++) {
+								this.popupDataList.push(defaultPopUpDataList[j]);
+							}
+						} else {
+							this.popupDataList.push(popupDataList[i]);
+						}
+					}
+				} else {
+					this.popupDataList = defaultPopUpDataList;
+					console.log("[loadConfig] popupDataList 加载默认列表");
+				}
+				// console.log("[loadConfig] popupDataList:", this.popupDataList);
+			},
+			fmtMcTime(timestamp) {
+				var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				// var Y = date.getFullYear() + '-';
+				var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+				var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
+				var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
+				var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
+				// var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
+
+				const timeStr = M + D + h + m;
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			// 获取倒计时
+			getActtime() {
+				this.acttime = this.fmtMcTime(this.beginSecond) + " 至 " + this.fmtMcTime(this.endSecond);
+			},
+			fmtMcTime2(timestamp1, timestamp2) {
+				const date1 = new Date(timestamp1 * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+				const date2 = new Date(timestamp2 * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+
+				const Y1 = date1.getFullYear();
+				const Y2 = date2.getFullYear();
+				const M1 = date1.getMonth() + 1;
+				const M2 = date2.getMonth() + 1;
+				const D1 = date1.getDate();
+				const D2 = date2.getDate();
+
+				var timeStr1 = Y1 + '.' + M1 + '.' + D1;
+				var timeStr2 = '';
+
+				if (Y2 != Y1) {
+					timeStr2 += Y2 + '.' + M2 + '.' + D2;
+				} else if (M2 != M1) {
+					timeStr2 += M2 + '.' + D2;
+				} else if (D2 != D1) {
+					timeStr2 += D2;
+				}
+
+				var timeStr = timeStr1;
+				if (timeStr2.length > 0) {
+					timeStr += '-' + timeStr2;
+				}
+				// console.log("timeStr", timeStr);
+				return timeStr;
+			},
+			getCardConfigQuery() {
+				uni.request({
+					url: apiCardConfigQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId,
+						pageName: this.pageName
+					},
+					success: (res) => {
+						// console.log("getCardConfigQuery", res)
+						const data = res.data.data;
+						// const config = data.configJson != "" ? JSON.parse(data.configJson) : "";
+						// console.log("configJson", data.configJson);
+						const config = {
+							"css": `
+								.top2{
+									width: 100%;
+									height: 220px;
+									padding-top: 36px;
+									justify-content: space-between;
+									background-image: url('static/backgroud/top_bg_sddx.png');
+									background-repeat: no-repeat;
+									background-position: center;
+									background-size: cover;
+								}
+								.topbar-color{
+									color: #ffffff;
+								}
+								.btnSignup-enable {
+									background-color: #a43a07 !important;
+								}
+								.swiper-item-button {
+									background-color: #a43a07 !important;
+								}
+								.uni-swiper-dot-active {
+									background: #a43a07 !important;
+								}
+							`,
+							"popupDataList": [{
+									"type": 1,
+									"data": {
+										"title": "小飞龙定向赛",
+										"img": "/static/logo/sddx.png",
+										"content": "  开学季来袭!山大校园定向赛燃情启幕!探索校园每一个角落,挑战智慧与体能,全校师生共同开启新学期活力篇章!等你来挑战!"
+									}
+								},
+								"default"
+							],
+							"introduce": {
+								"title": "介绍:",
+								"content": "  开学季来袭!山大校园定向赛燃情启幕!探索校园每一个角落,挑战智慧与体能,全校师生共同开启新学期活力篇章!等你来挑战!"
+							}
+						};
+
+						this.loadConfig(config);
+
+						setTimeout(this.dealFirstEnter, 500);
+					},
+					fail: (err) => {
+						console.log("getCardConfigQuery err", err)
+					},
+				});
+			},
+			// 卡片信息查询
+			getCardDetailQuery() {
+				uni.request({
+					url: apiCardDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						console.log("getCardDetailQuery", res);
+						const data = res.data.data;
+						this.mcType = data.mcType;
+						this.mcId = data.mcId;
+						this.mcName = data.mcName;
+						this.beginSecond = data.beginSecond;
+						this.endSecond = data.endSecond;
+						this.coiId = data.coiId;
+						this.coiName = data.coiName;
+						this.teamNum = data.teamNum;
+						this.nickName = data.nickName;
+
+						this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
+
+						this.getActtime();
+						this.getOnlineMcSignUpDetail();
+
+						this.clear();
+						this.interval = setInterval(this.getActtime, 60000);
+					},
+					fail: (err) => {
+						console.log("getCardDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片对应线上赛多个活动查询
+			matchRsDetailQuery() {
+				uni.request({
+					url: apiMatchRsDetailQuery,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						ecId: this.ecId
+					},
+					success: (res) => {
+						// console.log("matchRsDetailQuery", res);
+						if (res.data.code == 0) {
+							const data = res.data.data;
+							const rank = JSON.stringify(data);
+							this.dealNotice(rank);
+						}
+					},
+					fail: (err) => {
+						console.log("matchRsDetailQuery err", err)
+					},
+				});
+			},
+			// 卡片用户当前排名查询
+			// getUserCurrentRankNumQuery() {
+			// 	uni.request({
+			// 		url: apiUserCurrentRankNumQuery,
+			// 		header: {
+			// 			"Content-Type": "application/x-www-form-urlencoded",
+			// 			"token": this.token,
+			// 		},
+			// 		method: "POST",
+			// 		data: {
+			// 			ecId: this.ecId
+			// 		},
+			// 		success: (res) => {
+			// 			// console.log("getUserCurrentRankNumQuery", res)
+			// 			if (res.data.code == 0) {
+			// 				const data = res.data.data;
+			// 				const rankNum = data.rankNum;
+			// 				this.dealNotice(rankNum);
+			// 			}
+			// 		},
+			// 		fail: (err) => {
+			// 			console.log("getUserCurrentRankNumQuery err", err)
+			// 		},
+			// 	});
+			// },
+			// 线上赛报名页面信息详情
+			getOnlineMcSignUpDetail() {
+				uni.request({
+					url: apiOnlineMcSignUpDetail,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcId: this.mcId,
+					},
+					success: (res) => {
+						console.log("getOnlineMcSignUpDetail", res);
+						this.coiRs = res.data.data.coiRs;
+						if (this.nickName == undefined || this.nickName == '') {
+							this.nickName = res.data.data.name;
+						}
+						/* const rsNum = this.coiRs.length;
+						this.orgList = [];
+						for (let i = 0; i < rsNum; i++) {
+							this.orgList[i] = {};
+							this.orgList[i].value = this.coiRs[i].coiId;
+							this.orgList[i].text = this.coiRs[i].coiName;
+							this.orgList[i].teamNum = this.coiRs[i].teamNum;
+						}
+						// console.log("orgList", this.orgList);
+						if (this.coiId > 0) {
+							this.orgChange(this.coiId, false);
+						} */
+					},
+					fail: (err) => {
+						console.log("getOnlineMcSignUpDetail err", err)
+					},
+				});
+			},
+			// 线上赛报名
+			onlineMcSignUp() {
+				uni.request({
+					url: apiOnlineMcSignUp,
+					header: {
+						"Content-Type": "application/x-www-form-urlencoded",
+						"token": this.token,
+					},
+					method: "POST",
+					data: {
+						mcId: this.mcId,
+						coiId: this.coiId,
+						selectTeam: this.teamNum,
+						nickName: this.nickName
+					},
+					success: (res) => {
+						// console.log("onlineMcSignUp", res);
+
+						if (checkResCode(res)) {
+							uni.showToast({
+								title: '比赛报名成功!',
+								icon: 'none',
+								duration: 3000
+							});
+
+							uni.navigateTo({
+								// url: '/pages/bm/style4/rankOverview?' + this.queryString
+								url: '/pages/bm/style4/rankList?' + this.queryString
+							});
+						}
+					},
+					fail: (err) => {
+						console.log("onlineMcSignUp err", err);
+						uni.showToast({
+							title: '出错了,报名失败',
+							icon: 'none',
+							duration: 3000
+						});
+					},
+				});
+			},
+			btnBack() {
+				// console.log("from:", this.from)
+				if (this.from != '') {
+					// window.history.back();
+					uni.navigateTo({
+						url: '/pages/bm/style4/rankList?' + this.queryString
+					});
+				} else {
+					const url = `action://to_home/`;
+					// window.location.href = url;
+					tools.appAction(url);
+				}
+			},
+			btnInfo() {
+				this.$refs.mypopup.popupOpen();
+			},
+			btnSignup() {
+				if (!checkToken(this.token)) {
+					return;
+				}
+				
+				if (!(this.nickName.trim().length > 0)) {
+					uni.showToast({
+						title: `请填写${this.labelName}`,
+						icon: 'none',
+						duration: 2000
+					});
+					return;
+				}
+				
+				if (!(this.coiId > 0)) {
+					uni.showToast({
+						title: `请选择${this.labelOrg}`,
+						icon: 'none',
+						duration: 2000
+					});
+					return;
+				}
+
+				this.nickName = this.nickName.trim();
+				// this.coiName = tools.getSelectedText(this.orgList, this.coiId);
+				// this.teamName = tools.getSelectedText(this.teamList, this.teamNum);
+				
+				this.$refs.alertDialog.open();
+			},
+			dialogConfirm() {
+				this.onlineMcSignUp();
+			},
+			dialogClose() {
+			},
+			// 获取输入框中值
+			getESelectText(data) {
+				console.log("getESelectText:", data);
+				this.coiName = data;
+			},
+			// 获取选择选项值
+			eSelectChange(data) {
+				console.log("eSelectChange:", data);
+			},
+		}
+	}
+</script>
+
+<style scoped>
+	.content {
+		width: 100vw;
+		height: 100vh;
+	}
+
+	.top-default {
+		width: 100%;
+		height: 220px;
+		padding-top: 36px;
+		justify-content: space-between;
+		background-image: url('static/backgroud/top_bg_sddx.png');
+		background-repeat: no-repeat;
+		background-position: center;
+		background-size: cover;
+	}
+
+	.topbar {
+		width: 90%;
+		justify-content: space-between;
+	}
+
+	.topbar-color-default {
+		color: #333333;
+	}
+
+	.topbar-back {
+		width: 43rpx;
+		height: 43rpx;
+		color: inherit !important;
+		font-size: 48rpx !important;
+		/* opacity: 0; */
+	}
+
+	.topbar-rule {
+		font-size: 32rpx;
+	}
+
+	.topcontent {
+		height: 90%;
+		margin-bottom: 30px;
+	}
+
+	.logo {
+		width: 80px;
+		height: 80px;
+		margin-top: 10px;
+		background-image: url('/static/logo/sddx.png');
+		background-repeat: no-repeat;
+		background-position-x: center;
+		background-position-y: center;
+		background-size: contain;
+	}
+
+	.top-acttime {
+		text-shadow: 3px 3px 0px #640008;
+		font-family: YouSheBiaoTiHei;
+		/* font-family: Arial, Helvetica, sans-serif; */
+		font-weight: bold;
+		color: #ffee0b;
+		font-size: 26px;
+	}
+
+	.mcName {
+		font-size: 40rpx;
+		font-weight: 550;
+	}
+
+	.main {
+		width: 76%;
+		min-height: 800rpx;
+		/* margin-top: 20rpx; */
+		justify-content: space-around;
+	}
+
+	.timebar {
+		width: 80%;
+		height: 65rpx;
+		/* margin-top: 20rpx; */
+		margin-top: -64rpx;
+		padding: 0 50rpx;
+		justify-content: space-evenly;
+		background: #ffffff;
+		border: 0.5px solid;
+		border-color: #e7e7e7;
+		border-radius: 20px;
+		box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.13);
+	}
+
+	.acttime {
+		font-weight: 550;
+		color: #333333;
+		font-size: 30rpx;
+	}
+
+	.clock {
+		width: 30rpx;
+		height: 30rpx;
+		margin-right: 20rpx;
+	}
+
+	.uni-input {
+		width: 90%;
+		height: 68rpx;
+		/* margin-top: 30rpx; */
+		padding: 0 26rpx;
+		/* background: #f1f1f1; */
+		border: 1px solid #dcdfe6;
+		border-radius: 4px;
+	}
+
+	.input-placeholder {
+		color: #333333;
+		font-size: 16px;
+	}
+
+	.introduce {
+		width: 100%;
+		margin-top: 10rpx;
+		margin-bottom: 30rpx;
+		align-items: flex-start;
+		justify-content: space-around;
+	}
+
+	.introduce-title {
+		color: #333333;
+		font-size: 30rpx;
+		line-height: 60rpx;
+		font-family: Source Han Sans CN;
+	}
+
+	.introduce-content {
+		color: #333333;
+		font-size: 25rpx;
+		line-height: 36rpx;
+		font-family: Source Han Sans CN;
+	}
+
+	.btnSignup {
+		width: 100%;
+		height: 100rpx;
+		margin-bottom: 30rpx;
+		color: white;
+		font-weight: bold;
+		line-height: 100rpx;
+		border-radius: 55rpx;
+	}
+
+	.btnSignup-enable {
+		background-color: #81cd00;
+	}
+
+	.btnSignup-disable {
+		background-color: #c3c3c3;
+	}
+
+	.dialog-content {
+		width: 280px;
+		height: 110px;
+		padding: 0 20px;
+		background: #f1f1f1;
+		border-radius: 9px;
+		justify-content: center;
+		text-align: center;
+		font-weight: 550;
+		color: #333333;
+	}
+
+	.dialog-content-1 {
+		font-size: 34rpx;
+		margin-bottom: 30rpx;
+	}
+	
+	.dialog-content-2 {
+		font-size: 28rpx;
+		margin-bottom: 10rpx;
+		text-align: left;
+	}
+</style>

BIN
card/static/backgroud/top_bg2.png


BIN
card/static/backgroud/top_bg_egg.png


BIN
card/static/backgroud/top_bg_egg2.png


BIN
card/static/backgroud/top_bg_egg3.png


BIN
card/static/backgroud/top_bg_sddx.png


BIN
card/static/backgroud/top_bg_sea.png


BIN
card/static/cardbg/shanda.png


BIN
card/static/cardbg/xfl4.png


BIN
card/static/cardbg/xfl5.png


BIN
card/static/common/aotizhongxin.png


BIN
card/static/common/award.png


BIN
card/static/common/baihuagongyuan.png


BIN
card/static/common/btn_dhjd.png


BIN
card/static/common/egg.png


BIN
card/static/common/ingame.gif


BIN
card/static/common/ingame2.gif


BIN
card/static/common/lingxiucheng.png


BIN
card/static/common/muniushan.png


BIN
card/static/common/nav.png


BIN
card/static/common/quanchenggongyuan.png


BIN
card/static/common/wslgwcs.png


BIN
card/static/logo/xfl2.png