top.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. <template>
  2. <view class="wrap">
  3. <u-navbar title="答题榜单" :placeholder="true" bgColor="rgba(255,255,255,0.3)" leftText="返回" :autoBack="true" titleStyle="font-weight:bold;color:#7a5831"></u-navbar>
  4. <view class="top-bg">
  5. <image src="https://huli-app.wenlvti.net/app_static/wuyuan/static/static/imgs/top_bg.png" mode="widthFix"></image>
  6. </view>
  7. <view class="main">
  8. <scroll-view class="top-scroll" scroll-y scroll-with-animation :lower-threshold="100" @scrolltolower="onScrollToLower" :style="{ height: scrollHeight + 'px' }">
  9. <!-- 数据列表 -->
  10. <view class="user-list">
  11. <view class="b-item" v-for="(item, index) in userData.items" :key="index">
  12. <view class="b-sort">
  13. <image :src="'https://huli-app.wenlvti.net/app_static/wuyuan/static/static/imgs/top_' + (index + 1) + '.png'" mode="aspectFit" v-if="index < 3"></image>
  14. <text v-else>{{ index + 1 }}</text>
  15. </view>
  16. <view class="b-avatar">
  17. <image :src="item.avatar_url || '/static/imgs/user.png'" mode="aspectFill"></image>
  18. </view>
  19. <view class="b-user">
  20. <view class="s-name">{{ item.name }}</view>
  21. <view class="s-org">{{ item.group_name }}</view>
  22. </view>
  23. <view class="b-data">
  24. <view class="s-score">{{ item.max_score }}分</view>
  25. <view class="s-time">{{ costTime(item.cost_time) }}</view>
  26. </view>
  27. </view>
  28. </view>
  29. <!-- 加载中 -->
  30. <load-more :loadingType="loadingType" :loadingText="loadingText"></load-more>
  31. </scroll-view>
  32. </view>
  33. <view class="navbar">
  34. <view class="b-mine" @click="onGoLast('max', mineData.max_sid)">
  35. <view class="s-tit1">第</view>
  36. <view class="s-num">{{ mineData.group_top }}</view>
  37. <view class="s-tit2">名</view>
  38. <view class="s-mine">
  39. <image :src="mineData.avatar_url || '/static/imgs/user.png'" mode="aspectFill"></image>
  40. </view>
  41. <view class="s-score">{{ mineData.max_score }}分</view>
  42. <view class="s-time">{{ costTime(mineData.cost_time) }}</view>
  43. </view>
  44. <picker class="b-group" @change="onFilter" :value="groupIndex" :range="groupList" range-key="name">
  45. <view class="b-main">
  46. <view class="s-icon iconfont icon-unfold"></view>
  47. <view class="s-name">{{ groupList[groupIndex].name }}排行</view>
  48. </view>
  49. </picker>
  50. </view>
  51. </view>
  52. </template>
  53. <script>
  54. import { getTopList, getMineTop } from '@/service/api/examine.js';
  55. import Util from '../../common/util';
  56. import mixinsCommon from '@/mixins/common.js';
  57. import mixinsAuth from '../../mixins/auth.js';
  58. // import noneData from '@/components/none-data/none-data.vue';
  59. // import loadMore from '@/components/load-more/load-more.vue';
  60. export default {
  61. mixins: [mixinsCommon, mixinsAuth],
  62. data() {
  63. return {
  64. hasLoad: false,
  65. refreshTime: 0,
  66. scrollHeight: 100,
  67. userData: {
  68. items: []
  69. },
  70. mineData: {},
  71. groupList: [
  72. {
  73. id: 0,
  74. name: '全部'
  75. }
  76. ],
  77. groupIndex: 0,
  78. loadingType: 1,
  79. loadingText: ''
  80. };
  81. },
  82. onLoad(options) {
  83. // switchTab不支持传参,单页才有效
  84. console.log('onLoad', options);
  85. this.initScrollHeight();
  86. if (this.$store.state.examine.topGroupId == -1) {
  87. const groupId = options.groupId || 0;
  88. this.refreshTime = Util.getTimestamp();
  89. this.loadTopList(groupId, true);
  90. this.loadMineTop(groupId, true);
  91. }
  92. },
  93. onShow() {
  94. // switchTab时通过这种方式传参
  95. console.log('onShow', this.$store.state.examine.topGroupId);
  96. const groupId = this.$store.state.examine.topGroupId;
  97. if (groupId != -1) {
  98. this.$store.commit('examine/delTopGroupId');
  99. this.refreshTime = Util.getTimestamp();
  100. this.loadTopList(groupId, true);
  101. this.loadMineTop(groupId, true);
  102. } else {
  103. if (this.hasLoad) {
  104. const timestamp = Util.getTimestamp();
  105. if (timestamp - this.refreshTime >= 5) {
  106. this.refreshTime = timestamp;
  107. this.loadTopList(this.groupList[this.groupIndex].id, true);
  108. this.loadMineTop(this.groupList[this.groupIndex].id, false);
  109. }
  110. }
  111. }
  112. },
  113. computed: {},
  114. methods: {
  115. loadTopList(group, refresh) {
  116. console.log('loadTopList', group, refresh);
  117. if (refresh) {
  118. this.page = 1;
  119. this.userData.items = [];
  120. } else {
  121. this.page++;
  122. }
  123. this.loadingType = 1;
  124. this.loadingText = '';
  125. getTopList(group, this.page, 10).then(([err, res]) => {
  126. console.log('getTopList', err, res);
  127. this.loadingType = -1;
  128. this.hasLoad = true;
  129. if (!err) {
  130. if (res.items.length > 0) {
  131. this.userData.items = [...this.userData.items, ...res.items];
  132. } else {
  133. this.loadingType = 2;
  134. if (this.page == 1) {
  135. this.loadingText = '暂无数据';
  136. }
  137. this.page--; // 重置分页
  138. }
  139. } else {
  140. this.loadingType = 3;
  141. }
  142. });
  143. },
  144. loadMineTop(group, init) {
  145. console.log('loadMineTop', group, init);
  146. getMineTop(group).then(([err, res]) => {
  147. console.log('getMineTop', err, res);
  148. if (!err) {
  149. this.mineData = res.mineData;
  150. this.groupList = res.userGroups;
  151. if (init) {
  152. this.groupList.map((item, index) => {
  153. if (item.id == group) {
  154. this.groupIndex = index;
  155. }
  156. });
  157. }
  158. }
  159. });
  160. },
  161. onFilter(e) {
  162. console.log('onFilter', e.detail.value);
  163. this.groupIndex = e.detail.value;
  164. this.loadTopList(this.groupList[this.groupIndex].id, true);
  165. this.loadMineTop(this.groupList[this.groupIndex].id, false);
  166. },
  167. initScrollHeight() {
  168. const systemInfo = uni.getSystemInfoSync();
  169. const windowHeight = systemInfo.windowHeight;
  170. const searchBarHeight = this.$logic.rpx2px(360);
  171. this.scrollHeight = windowHeight - searchBarHeight;
  172. },
  173. onScrollToLower(e) {
  174. console.log('onScrollToLower', e);
  175. this.loadTopList(this.groupList[this.groupIndex].id, false);
  176. },
  177. onGoLast(from, sessionId) {
  178. if (!sessionId) {
  179. return;
  180. }
  181. uni.navigateTo({
  182. url: '/answer_pages/examine/summary?from=' + from + '&session_id=' + sessionId
  183. });
  184. }
  185. }
  186. };
  187. </script>
  188. <style lang="scss">
  189. // page {
  190. // padding-bottom: env(safe-area-inset-bottom);
  191. // background: $pq-bg-color;
  192. // }
  193. .wrap {
  194. }
  195. .top-bg {
  196. position: relative;
  197. image {
  198. width: 100%;
  199. height: 460upx;
  200. }
  201. }
  202. .main {
  203. padding: 40upx 40upx 160upx 40upx;
  204. display: flex;
  205. flex-direction: column;
  206. }
  207. .top-scroll {
  208. margin-top: -250upx;
  209. padding-bottom: 20upx;
  210. position: relative;
  211. width: 670upx;
  212. height: 100%;
  213. background: #fff;
  214. border-radius: 20upx;
  215. z-index: 100;
  216. }
  217. .user-list {
  218. padding: 40upx 40upx 20upx 10upx;
  219. .b-item {
  220. margin-bottom: 50upx;
  221. height: 100upx;
  222. display: flex;
  223. align-items: center;
  224. justify-content: space-between;
  225. &:last-child {
  226. margin-bottom: 0;
  227. }
  228. .b-sort {
  229. width: 100upx;
  230. display: flex;
  231. justify-content: center;
  232. align-items: center;
  233. text {
  234. font-size: 36upx;
  235. color: #808080;
  236. }
  237. image {
  238. width: 60upx;
  239. height: 60upx;
  240. }
  241. }
  242. .b-avatar {
  243. width: 100upx;
  244. height: 100upx;
  245. image {
  246. width: 100upx;
  247. height: 100upx;
  248. border-radius: 50%;
  249. }
  250. }
  251. .b-user {
  252. margin-left: 20upx;
  253. flex: 1;
  254. display: flex;
  255. flex-direction: column;
  256. .s-name {
  257. font-size: 32upx;
  258. }
  259. .s-org {
  260. margin-top: 10upx;
  261. font-size: 26upx;
  262. color: #a6a6a6;
  263. }
  264. }
  265. .b-data {
  266. display: flex;
  267. flex-direction: column;
  268. align-items: flex-end;
  269. .s-score {
  270. color: #ffc300;
  271. font-size: 40upx;
  272. }
  273. .s-time {
  274. margin-top: 10upx;
  275. color: #a6a6a6;
  276. font-size: 24upx;
  277. }
  278. }
  279. }
  280. }
  281. .navbar {
  282. position: fixed;
  283. z-index: 999;
  284. left: 0;
  285. /* #ifdef H5 */
  286. bottom: calc(100upx + env(safe-area-inset-bottom));
  287. /* #endif */
  288. /* #ifdef MP-WEIXIN */
  289. bottom: 0upx;
  290. /* #endif */
  291. width: 100%;
  292. height: 120upx;
  293. display: flex;
  294. align-items: center;
  295. background: #fff;
  296. border-top: 1upx solid #f7f7f7;
  297. justify-content: space-between;
  298. .b-mine {
  299. margin-left: 20upx;
  300. display: flex;
  301. align-items: center;
  302. .s-tit1,
  303. .s-tit2 {
  304. color: #808080;
  305. font-size: 28upx;
  306. }
  307. .s-num {
  308. margin: 0 10upx;
  309. font-size: 50upx;
  310. color: #da5650;
  311. font-weight: bold;
  312. }
  313. .s-mine {
  314. margin-left: 20upx;
  315. width: 70upx;
  316. height: 70upx;
  317. image {
  318. width: 70upx;
  319. height: 70upx;
  320. border-radius: 50%;
  321. }
  322. }
  323. .s-score {
  324. margin-left: 20upx;
  325. color: #ffc300;
  326. font-size: 36upx;
  327. }
  328. .s-time {
  329. margin-left: 20upx;
  330. color: #808080;
  331. font-size: 24upx;
  332. }
  333. }
  334. .b-group {
  335. margin-right: 20upx;
  336. .b-main {
  337. padding: 0 20upx;
  338. display: flex;
  339. align-items: center;
  340. background: $pq-bg-color;
  341. border-radius: 30upx;
  342. height: 60upx;
  343. .s-icon {
  344. color: #a6a6a6;
  345. font-size: 30upx;
  346. }
  347. .s-name {
  348. margin-left: 10upx;
  349. font-size: 28upx;
  350. color: #a6a6a6;
  351. }
  352. }
  353. }
  354. }
  355. </style>