rankOverview.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. <!--
  2. [模板] 样式1 - 排名总览
  3. http://localhost:5173/card/#/pages/tpl/style1/rankOverview
  4. https://oss-mbh5.colormaprun.com/card/#/pages/tpl/style1/rankOverview
  5. -->
  6. <template>
  7. <view class="body">
  8. <view v-if="pageReady" class="content uni-column">
  9. <view class="uni-column page-top">
  10. <my-topbar :mcName="mcName" class="topbar-color" @btnBackClick="btnBack"
  11. @btnInfoClick="btnInfo"></my-topbar>
  12. </view>
  13. <view class="mid uni-column uni-jcc">
  14. <view class="mid-1 uni-row uni-jcsb">
  15. <text>排名:<text style="color: #ff0045;">{{totalSysPointRankNum}}</text></text>
  16. <text class="mid-1-name">{{nickName}}</text>
  17. <text>场次:<text style="color: #ff0045;">{{totalNum}}</text></text>
  18. </view>
  19. <view class="mid-2 uni-row uni-jcsa">
  20. <view class="uni-column">
  21. <text class="mid-2-value">{{totalSysPoint}}</text>
  22. <text class="mid-2-text">百味豆</text>
  23. </view>
  24. <view class="mid-line"></view>
  25. <view class="uni-column">
  26. <text class="mid-2-value">{{fmtDistanct(totalDistanct)}}</text>
  27. <text class="mid-2-text">里程 km</text>
  28. </view>
  29. <view class="mid-line"></view>
  30. <view class="uni-column">
  31. <text class="mid-2-value">{{totalCp}}</text>
  32. <text class="mid-2-text">打点数</text>
  33. </view>
  34. <view class="mid-line"></view>
  35. <view class="uni-column">
  36. <text class="mid-2-value">{{fmtPace(fastPace)}}</text>
  37. <text class="mid-2-text">最快配速</text>
  38. </view>
  39. </view>
  40. </view>
  41. <view class="main uni-column">
  42. <text class="main-title">选择比赛路线</text>
  43. <my-pathList ref="myPathList" :style="pathListStyle.style" :pathList="pathList" :mcState="mcState"
  44. :showLine="pathListStyle.showLine" :isNewUser="isNewUser"
  45. @onNewUserPathClick="onNewUserPathClick"></my-pathList>
  46. <!-- <button class="btnGuide" @click="btnGuide">新手引导</button> -->
  47. </view>
  48. <my-popup ref="mypopup" :config="cardConfigData.popupRuleConfig" :dataList="cardConfigData.popupRuleList"
  49. :acttime="acttime"></my-popup>
  50. <my-guide ref="myGuide" @popup-close="onGuideClose"></my-guide>
  51. <!-- <my-popup-map ref="mypopupmap" :point="navPoint"></my-popup-map> -->
  52. </view>
  53. </view>
  54. </template>
  55. <script>
  56. import tools from '/common/tools';
  57. import cardfunc from '../../../common/cardfunc';
  58. // import { localCardConfig } from "./cardconfig/test.js";
  59. import {
  60. localCardConfig
  61. } from "./cardconfig/pattern1.js";
  62. import {
  63. localUserConfig
  64. } from "./cardconfig/test_user.js";
  65. import {
  66. token,
  67. apiMatchRsDetailQuery,
  68. checkResCode
  69. } from '/common/api';
  70. export default {
  71. data() {
  72. return {
  73. cardConfigData: cardfunc.cardConfigData,
  74. pageReady: false,
  75. // audioSrc: "/static/audio/2.mp3",
  76. // audioSrc: "https://oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
  77. // audioSrc: "http://t-oss-mbh5.colormaprun.com/card/static/audio/2.mp3",
  78. pageName: "rankOverview",
  79. firstEnterKey: 'firstEnter-tpl-style1',
  80. rankKey: "rank-tpl-style1",
  81. queryObj: {},
  82. queryString: "",
  83. token: "",
  84. isNewUser: false,
  85. cardconfig: {}, // 卡片配置
  86. userconfig: {}, // 用户配置
  87. ecId: 0, // 卡片id
  88. mcId: 0, // 赛事id
  89. mcType: 0, // 赛事类型 1 普通活动 2 线下赛 3 线上赛
  90. mcName: "", // 赛事名称
  91. acttime: "", // 活动时间
  92. beginSecond: null, // 活动或赛事开始时间戳,单位秒
  93. endSecond: null, // 活动或赛事结束时间戳,单位秒
  94. nickName: "", // 昵称
  95. totalNum: null, // 总场次
  96. totalDistanct: null, // 总距离,单位米
  97. totalDistanctRankNum: null, // 总距离排名
  98. totalCp: null, // 总打点数
  99. totalCpRankNum: null, // 总打点数排名
  100. totalSysPoint: null, // 总百味豆
  101. totalSysPointRankNum: null, // 总百味豆排名
  102. fastPace: null, // 个人最快配速
  103. fastPaceRankNum: null, // 个人最快配速排名
  104. ocaRs: [], // 卡片对应活动集合
  105. interval: null,
  106. mcState: 0, // 赛事/活动状态 0: 未开始 1: 进行中 2: 已结束
  107. pathList: {},
  108. pathListStyle: {},
  109. selectedPath: null,
  110. navPoint: {},
  111. }
  112. },
  113. computed: {
  114. pathListLen() {
  115. return Object.keys(this.pathList).length;
  116. }
  117. },
  118. onLoad(query) { // 类型非必填,可自动推导
  119. // console.log("query:", query);
  120. this.queryObj = query;
  121. this.queryString = tools.objectToQueryString(this.queryObj);
  122. // console.log(queryString);
  123. this.token = query["token"] ?? token;
  124. this.ecId = query["id"] ?? 0;
  125. this.firstEnterKey += "-" + this.ecId;
  126. console.log("firstEnterKey:", this.firstEnterKey);
  127. this.rankKey += "-" + this.ecId;
  128. console.log("rankKey:", this.rankKey);
  129. cardfunc.init(this, this.token, this.ecId);
  130. cardfunc.getCardConfig(this.cardConfigQueryCallback, localCardConfig);
  131. cardfunc.isNewUserQuery(this.isNewUserQueryCallback);
  132. },
  133. // 页面初次渲染完成,此时组件已挂载完成,DOM 树($el)已可用
  134. onReady() {
  135. // this.dealFirstEnter();
  136. },
  137. onShow() {},
  138. onUnload() {
  139. this.clear();
  140. },
  141. methods: {
  142. dealNotice(rank) {
  143. // console.log('[dealFirstEnter]');
  144. let that = this;
  145. uni.getStorage({
  146. key: that.rankKey,
  147. success: (res) => {
  148. // console.log('[getStorage]', that.rankKey, res.data);
  149. const oldRank = res.data;
  150. if (oldRank != rank) {
  151. // that.notice = true;
  152. that.setRankValue(rank);
  153. }
  154. },
  155. fail: (e) => {
  156. console.log('[getStorage] fail', that.rankKey, e);
  157. // that.notice = false;
  158. that.setRankValue(rank);
  159. },
  160. })
  161. },
  162. setRankValue(data) {
  163. let that = this;
  164. uni.setStorage({
  165. key: that.rankKey,
  166. data: data,
  167. success: () => {
  168. console.log('[setStorage] success', that.rankKey, data);
  169. },
  170. fail: (e) => {
  171. console.log('[setStorage] fail', that.rankKey, e);
  172. },
  173. })
  174. },
  175. dealFirstEnter() {
  176. // console.log('[dealFirstEnter]');
  177. let that = this;
  178. uni.getStorage({
  179. key: that.firstEnterKey,
  180. success: (res) => {
  181. console.log('[getStorage]', that.firstEnterKey, res.data);
  182. },
  183. fail: (e) => {
  184. console.log('[getStorage] fail', that.firstEnterKey, e);
  185. that.btnInfo();
  186. that.setFirstEnterValue(true);
  187. },
  188. })
  189. },
  190. setFirstEnterValue(data) {
  191. let that = this;
  192. uni.setStorage({
  193. key: that.firstEnterKey,
  194. data: data,
  195. success: () => {
  196. console.log('[setStorage] success', that.firstEnterKey, data);
  197. },
  198. fail: (e) => {
  199. console.log('[setStorage] fail', that.firstEnterKey, e);
  200. },
  201. })
  202. },
  203. clear() {
  204. if (this.interval != null) {
  205. clearInterval(this.interval);
  206. this.interval = null;
  207. }
  208. },
  209. cardConfigQueryCallback(cardconfig) {
  210. this.cardconfig = cardconfig;
  211. cardfunc.getUserConfig(this.userConfigQueryCallback, localUserConfig);
  212. },
  213. userConfigQueryCallback(userconfig) {
  214. this.userconfig = userconfig;
  215. this.loadConfig();
  216. this.matchRsDetailQuery();
  217. setTimeout(this.dealFirstEnter, 500);
  218. },
  219. loadConfig() {
  220. this.loadCardConfig(this.cardconfig);
  221. this.loadUserConfig(this.userconfig);
  222. this.pageReady = true;
  223. },
  224. loadCardConfig(cardconfig) {
  225. cardconfig = cardfunc.parseCardConfig(cardconfig);
  226. // console.log("[loadCardConfig] cardconfig:", cardconfig);
  227. // 加载卡片通用配置
  228. if (cardconfig.common != undefined) {
  229. cardfunc.loadCardCommonConfig(cardconfig.common);
  230. }
  231. // -------- 加载当前页面的配置 --------
  232. const config = cardfunc.parseCardConfig(cardconfig[this.pageName]);
  233. // console.log("[loadConfig] config_page:", config);
  234. if (config == undefined || config == null) {
  235. return;
  236. }
  237. // 加载CSS样式
  238. const css = config.css;
  239. if (css != undefined && css.length > 0) {
  240. tools.loadCssCode(css);
  241. }
  242. // 加载比赛路线数据
  243. const pathList = config.pathList;
  244. // console.log("[loadConfig] pathList:", pathList);
  245. if (pathList != undefined) {
  246. this.pathList = pathList;
  247. }
  248. // 加载比赛路线样式
  249. const pathListStyle = config.pathListStyle;
  250. // console.log("[loadConfig] pathList:", pathList);
  251. if (pathListStyle != undefined) {
  252. this.pathListStyle = pathListStyle;
  253. }
  254. },
  255. loadUserConfig(userconfig) {
  256. if (!userconfig) {
  257. console.log("[loadUserConfig] userconfig 为空");
  258. return;
  259. }
  260. const config = cardfunc.parseCardConfig(userconfig);
  261. console.log("[loadUserConfig] userconfig:", config);
  262. // 加载用户的弹窗数据
  263. cardfunc.loadUserPopupRule(config);
  264. // 加载比赛路线数据
  265. this.pathList = cardfunc.getUserPathList(config);
  266. },
  267. isNewUserQueryCallback(isNewUser) {
  268. this.isNewUser = isNewUser;
  269. },
  270. // 获取倒计时
  271. getCountdown() {
  272. // console.log(this.endSecond)
  273. if (this.endSecond > 0) {
  274. const now = Date.now() / 1000;
  275. const dif = this.endSecond - now;
  276. // const dif = 3600*24 - 60;
  277. if (dif > 0) {
  278. this.countdown = '距结束 ' + tools.convertSecondsToDHM(dif);
  279. } else {
  280. this.countdown = "活动已结束";
  281. }
  282. // this.countdown = tools.convertSecondsToHMS(dif);
  283. } else {
  284. this.countdown = "距结束 --天--小时";
  285. }
  286. },
  287. // 格式化 距离
  288. fmtDistanct(val) {
  289. if (val < 1000)
  290. return Math.round(val * 10 / 1000) / 10;
  291. else
  292. return Math.round(val / 1000);
  293. },
  294. // 格式化 配速
  295. fmtPace(val) {
  296. return tools.convertSecondsToHMS(val, 2);
  297. },
  298. fmtMcTime(timestamp) {
  299. return tools.fmtMcTime(timestamp);
  300. },
  301. // 获取活动时间
  302. getActtime() {
  303. this.acttime = tools.getActtime(this.beginSecond, this.endSecond);
  304. },
  305. // 卡片对应线上赛多个活动查询
  306. matchRsDetailQuery() {
  307. uni.request({
  308. url: apiMatchRsDetailQuery,
  309. header: {
  310. "Content-Type": "application/x-www-form-urlencoded",
  311. "token": this.token,
  312. },
  313. method: "POST",
  314. data: {
  315. ecId: this.ecId
  316. },
  317. success: (res) => {
  318. // console.log("matchRsDetailQuery", res);
  319. if (checkResCode(res)) {
  320. const data = res.data.data;
  321. this.mcType = data.mcType;
  322. this.mcId = data.mcId;
  323. this.mcName = data.mcName;
  324. this.beginSecond = data.beginSecond;
  325. this.endSecond = data.endSecond;
  326. this.nickName = data.nickName;
  327. this.totalNum = data.totalNum;
  328. this.totalDistanct = data.totalDistanct;
  329. this.totalDistanctRankNum = data.totalDistanctRankNum;
  330. this.totalCp = data.totalCp;
  331. this.totalCpRankNum = data.totalCpRankNum;
  332. this.totalSysPoint = data.totalSysPoint;
  333. this.totalSysPointRankNum = data.totalSysPointRankNum;
  334. this.fastPace = data.fastPace;
  335. this.fastPaceRankNum = data.fastPaceRankNum;
  336. this.ocaRs = data.ocaRs;
  337. this.mcState = tools.checkMcState(this.beginSecond, this.endSecond);
  338. const rank = JSON.stringify(data);
  339. this.dealNotice(rank);
  340. this.getCountdown();
  341. this.getActtime();
  342. this.clear();
  343. this.interval = setInterval(this.getCountdown, 60000);
  344. }
  345. },
  346. fail: (err) => {
  347. console.log("matchRsDetailQuery err", err)
  348. },
  349. });
  350. },
  351. btnBack() {
  352. const url = "/pages/tpl/style1/rankList?" + this.queryString;
  353. tools.appAction(url, "uni.navigateTo");
  354. },
  355. btnInfo() {
  356. // console.log(this.$refs.mypopup);
  357. this.$refs.mypopup.popupOpen();
  358. },
  359. // btnGuide() {
  360. // this.$refs.myGuide.popupOpen();
  361. // },
  362. onOverviewClick(ovtype) {
  363. this.queryObj.ovtype = ovtype;
  364. this.queryString = tools.objectToQueryString(this.queryObj);
  365. const url = "/pages/tpl/style1/rankList?" + this.queryString;
  366. tools.appAction(url, "uni.navigateTo");
  367. },
  368. onNewUserPathClick(data) {
  369. // console.log("onNewUserPathClick:", data);
  370. this.selectedPath = data;
  371. this.$refs.myGuide.popupOpen();
  372. },
  373. onGuideClose() {
  374. if (this.isNewUser && this.selectedPath != null) {
  375. this.$refs.myPathList.to_detail(this.selectedPath);
  376. this.selectedPath = null;
  377. }
  378. }
  379. }
  380. }
  381. </script>
  382. <style scoped>
  383. .content {
  384. width: 100vw;
  385. /* height: 100vh; */
  386. overflow-x: scroll;
  387. }
  388. .page-top {
  389. position: relative;
  390. z-index: 10;
  391. width: 100%;
  392. height: 270px;
  393. padding-top: 36px;
  394. justify-content: space-between;
  395. background-image: url("/static/backgroud/top_bg_egg2.png");
  396. background-repeat: no-repeat;
  397. background-position-x: center;
  398. background-position-y: center;
  399. /* background-position-y: -8px; */
  400. /* background-size: 100% 100%; */
  401. background-size: cover;
  402. }
  403. .topbar-color {
  404. color: #333333;
  405. }
  406. .topbtm {
  407. width: 100%;
  408. margin-bottom: 40px;
  409. justify-content: space-evenly;
  410. }
  411. .topbtm-name {
  412. padding: 5px 12px;
  413. background-color: #9fda39;
  414. border-radius: 5px;
  415. /* backdrop-filter: blur(30px); */
  416. text-align: center;
  417. font-weight: 500;
  418. color: #497400;
  419. font-size: 14px;
  420. }
  421. .mid {
  422. width: 90%;
  423. height: 120px;
  424. position: relative;
  425. z-index: 20;
  426. margin-top: -100px;
  427. background: #ffffff;
  428. border-radius: 9px;
  429. box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.13);
  430. font-family: Source Han Sans CN;
  431. }
  432. .mid-1 {
  433. width: 90%;
  434. /* margin: 12px; */
  435. margin-bottom: 12px;
  436. font-weight: 500;
  437. color: #8e8e8e;
  438. font-size: 14px;
  439. }
  440. .mid-1-name {
  441. max-width: 310rpx;
  442. white-space: nowrap;
  443. overflow: hidden;
  444. text-overflow: ellipsis;
  445. }
  446. .mid-2 {
  447. width: 92%;
  448. /* margin: 0 10px; */
  449. }
  450. .mid-2-value {
  451. font-weight: 900;
  452. font-size: 22px;
  453. }
  454. .mid-2-text {
  455. color: #989898;
  456. font-size: 12px;
  457. }
  458. .mid-line {
  459. width: 0px;
  460. height: 45.04px;
  461. border: 1px solid;
  462. border-color: #e6e6e6;
  463. }
  464. .overview-1 {
  465. width: 111px;
  466. height: 54px;
  467. background: #ffb40b;
  468. border-radius: 50%;
  469. box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
  470. pointer-events: auto;
  471. }
  472. .overview-2 {
  473. margin-top: -43px;
  474. color: #ffffff;
  475. font-size: 18px;
  476. pointer-events: auto;
  477. }
  478. .overview-3 {
  479. width: 111px;
  480. height: 54px;
  481. background: #f39509;
  482. border-radius: 50%;
  483. box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
  484. pointer-events: auto;
  485. }
  486. .overview-4 {
  487. width: 111px;
  488. height: 54px;
  489. background: #81cd00;
  490. border-radius: 50%;
  491. box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
  492. pointer-events: auto;
  493. }
  494. .overview-5 {
  495. width: 111px;
  496. height: 54px;
  497. background: #64cbb0;
  498. border-radius: 50%;
  499. box-shadow: 3px 3px 0px rgba(140, 140, 140, 1);
  500. pointer-events: auto;
  501. }
  502. .ovline1 {
  503. margin-top: 9px;
  504. color: #ffffff;
  505. font-size: 12px;
  506. }
  507. .ovline2 {
  508. color: #ffffff;
  509. font-size: 16px;
  510. }
  511. .main {
  512. width: 100%;
  513. margin-top: 20px;
  514. margin-bottom: 10px;
  515. /* height: 70vh; */
  516. justify-content: space-around;
  517. /* justify-content: space-between; */
  518. }
  519. .main-title {
  520. margin-bottom: 10px;
  521. font-weight: 550;
  522. color: #333333;
  523. font-size: 16px;
  524. }
  525. </style>