1
0

advance.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. <template>
  2. <app-layout>
  3. <view class="ms">
  4. <template v-if="(time_list.length > 0 || is_estimate === 1 ) && loading">
  5. <view class="time-list" >
  6. <scroll-view
  7. class="scroll "
  8. :scroll-x="true"
  9. scroll-with-animation
  10. :scroll-into-view="`${scroll_id}`"
  11. >
  12. <view class="content">
  13. <view
  14. class="item"
  15. :id="`ms_${i}`"
  16. v-for="(t, i) in time_list"
  17. :key="i"
  18. :class="active_index === i ? getTheme + '-m-back ' + getTheme + ' active-item' : 'no-active-item'"
  19. @click="activeTime({open_time: t.open_time, type: 1, date_time: t.date_time}, i)"
  20. >
  21. <view class="open-time">{{t.new_open_time}}</view>
  22. <view class="label">{{t.label}}</view>
  23. <view class="icon" :class="getTheme + '-m-text ' + getTheme"></view>
  24. </view>
  25. <view
  26. class="item teaser"
  27. :class="active_index === time_list.length ? getTheme + '-m-back ' + getTheme + ' active-item' : 'no-active-item'"
  28. :id="`ms_${time_list.length}`"
  29. v-if="is_estimate === 1"
  30. @click="activeTime({open_time: 0, type: 2}, time_list.length)"
  31. >
  32. 预告
  33. <view class="icon" :class="getTheme + '-m-text ' + getTheme"></view>
  34. </view>
  35. </view>
  36. </scroll-view>
  37. <view class="time dir-left-nowrap main-between" v-if="!is_booking">
  38. <view class="left"></view>
  39. <view class="text">限时限量 先到先得</view>
  40. <view class="timing">
  41. <text v-if="time_list[active_index].status === 1">距离本场结束</text>
  42. <text v-if="time_list[active_index].status === 2">本场秒杀已结束</text>
  43. <text v-if="time_list[active_index].status === 0">距离本场开始</text>
  44. <text class="time-html" v-if="time_list[active_index].status === 1 || time_list[active_index].status === 0">{{html}}</text>
  45. </view>
  46. </view>
  47. <view class="empty-goods dir-left-nowrap main-center cross-center" v-if="is_booking">
  48. <image src="/static/image/icon/empty.png"></image>
  49. <view>
  50. <view style="color: #353535;">今日已无更多场次</view>
  51. <view style="color: #999999;">
  52. 下场将于
  53. <text style="color: #ff4544;">{{next_time}}</text>
  54. 开始
  55. </view>
  56. </view>
  57. </view>
  58. </view>
  59. <scroll-view :class="is_booking ? 'is_book_list' : 'goods-list'" :scroll-y="true" @scrolltolower="scrollLower">
  60. <product-list
  61. :empty="nav_bool"
  62. :botHeight="BotHeight"
  63. :list="goods_list"
  64. :theme="getTheme"
  65. :theme-object="themeObject"
  66. :status="time_list[active_index].status"
  67. ></product-list>
  68. </scroll-view>
  69. </template>
  70. <template v-else-if="time_list.length === 0 && is_estimate !== 1 && loading">
  71. <view>
  72. <view class="empty dir-top-nowrap cross-center" >
  73. <image src="../image/empty.png"></image>
  74. <text>暂无秒杀商品</text>
  75. <button :class="[getTheme + '-m-back', getTheme]" @click="router_go">返回首页</button>
  76. </view>
  77. </view>
  78. </template>
  79. </view>
  80. </app-layout>
  81. </template>
  82. <script>
  83. import { mapState, mapGetters } from 'vuex';
  84. import appProductList from '../components/app-product-list.vue';
  85. export default {
  86. name: 'advance',
  87. data() {
  88. return {
  89. time_list: [],
  90. goods_list: [],
  91. next_time: '',
  92. page: 1,
  93. active_index: null,
  94. scroll_id: '',
  95. is_estimate: 0,
  96. open_time: 0,
  97. type: 0,
  98. page_count: 1,
  99. nav_bool: false,
  100. currentRoute: this.$platDiff.route(),
  101. time: -1,
  102. html: '',
  103. is_booking: false,
  104. loading: false
  105. }
  106. },
  107. computed: {
  108. ...mapState({
  109. tabBarNavs: state => state.mallConfig.navbar.navs,
  110. }),
  111. ...mapGetters('iPhoneX', {
  112. BotHeight: 'getBotHeight',
  113. }),
  114. ...mapGetters('mallConfig', {
  115. getTheme: 'getTheme',
  116. }),
  117. themeObject:function() {
  118. return {
  119. back: this.getTheme + '-m-back ' + this.getTheme,
  120. backP: this.getTheme + '-m-back-p ' + this.getTheme,
  121. backO: this.getTheme + '-m-back-o ' + this.getTheme,
  122. theme: this.getTheme,
  123. color: this.getTheme + '-m-text ' + this.getTheme,
  124. sBack: this.getTheme + '-s-back ' + this.getTheme,
  125. border: this.getTheme + '-m-border ' + this.getTheme,
  126. }
  127. },
  128. },
  129. onLoad() {
  130. this.getTimeList().then(() => {
  131. let active_status = false;
  132. this.time_list.map((item, index) => {
  133. if (item.status === 1) {
  134. active_status = true;
  135. this.active_index = index;
  136. this.scroll_id = `ms_${index}`;
  137. item.type = 1;
  138. this.getGoodsList(item);
  139. }
  140. });
  141. this.$nextTick(() => {
  142. this.loading = true;
  143. });
  144. if (active_status === false) {
  145. this.active_index = 0;
  146. if (this.time_list.length > 0) {
  147. this.type = 1;
  148. this.open_time = this.time_list[0].open_time;
  149. this.getGoodsList({
  150. open_time: this.open_time,
  151. type: this.type
  152. });
  153. } else {
  154. if (this.is_estimate === 1) {
  155. this.type = 2;
  156. this.open_time = 0;
  157. this.is_booking = true;
  158. this.getGoodsList({
  159. open_time: this.open_time,
  160. type: this.type,
  161. });
  162. }
  163. }
  164. }
  165. });
  166. // #ifdef MP-WEIXIN
  167. wx.showShareMenu({
  168. menus: ['shareAppMessage', 'shareTimeline']
  169. })
  170. // #endif
  171. },
  172. onShow() {
  173. if (this.type === 1) {
  174. this.set_time(this.time_list[this.active_index].date_time);
  175. }
  176. },
  177. onHide() {
  178. clearInterval(this.time);
  179. },
  180. onUnload() {
  181. clearInterval(this.time);
  182. },
  183. methods: {
  184. async getTimeList() {
  185. uni.showLoading({
  186. title:'加载中...'
  187. });
  188. try {
  189. const res = await this.$request({
  190. url: this.$api.miaosha.time_list,
  191. method: 'get'
  192. });
  193. if (res.code === 0) {
  194. let {is_estimate, list, next_miaosha_date_time} = res.data;
  195. this.time_list = list;
  196. this.is_estimate = is_estimate;
  197. this.next_time = next_miaosha_date_time;
  198. }
  199. } catch (e) {
  200. throw new Error(e);
  201. }
  202. uni.hideLoading();
  203. },
  204. async getGoodsList(item) {
  205. try {
  206. this.open_time = item.open_time;
  207. this.type = item.type;
  208. if (this.type === 1) {
  209. this.set_time(item.date_time);
  210. } else {
  211. clearInterval(this.time);
  212. }
  213. const res = await this.$request({
  214. url: this.$api.miaosha.goods,
  215. data: {
  216. open_time: item.open_time,
  217. type: item.type,
  218. page: this.page,
  219. }
  220. });
  221. if (res.code === 0) {
  222. this.goods_list = res.data.list;
  223. this.page_count = res.data.pagination.page_count;
  224. }
  225. } catch(e) {
  226. throw new Error(e);
  227. }
  228. },
  229. activeTime(item, index) {
  230. this.active_index = index;
  231. this.scroll_id = `ms_${index}`;
  232. this.page = 1;
  233. this.getGoodsList(item);
  234. this.getTimeList();
  235. if (item.type === 2) {
  236. this.is_booking = true;
  237. } else {
  238. this.is_booking = false;
  239. }
  240. },
  241. async scrollLower() {
  242. try {
  243. if (this.page >= this.page_count) return;
  244. this.page++;
  245. const res = await this.$request({
  246. url: this.$api.miaosha.goods,
  247. data: {
  248. open_time: this.open_time,
  249. type: this.type,
  250. page: this.page,
  251. }
  252. });
  253. if (res.code === 0) {
  254. this.goods_list = [...this.goods_list, ...res.data.list];
  255. }
  256. } catch(e) {
  257. throw new Error(e);
  258. }
  259. },
  260. set_nav() {
  261. let currentRoute = this.currentRoute;
  262. for (let i = 0; i < this.tabBarNavs.length; i++) {
  263. if(currentRoute.includes(this.tabBarNavs[i].url.split('?')[0])) {
  264. return this.nav_bool = true;
  265. }
  266. }
  267. return this.nav_bool = false;
  268. },
  269. set_time(data) {
  270. clearInterval(this.time);
  271. if (!data) return;
  272. let time_str = new Date(data.replace(/-/g, '/'));
  273. let time = time_str.getTime() - new Date().getTime();
  274. let day = parseInt((time/1000/60/60/24)%30);
  275. let hou = parseInt((time/1000/60/60)%24);
  276. let min = parseInt((time/1000/60)%60);
  277. let sec = parseInt((time/1000)%60);
  278. if (day > 0) {
  279. this.html = day+"天"+hou+":"+(min<10?"0"+min:min) + ":"+(sec<10?"0"+sec:sec);
  280. } else {
  281. this.html = hou+":"+(min<10?"0"+min:min) + ":"+(sec<10?"0"+sec:sec);
  282. }
  283. this.time = setInterval(() =>{
  284. let time = time_str.getTime() - new Date().getTime();
  285. if (time < 0) {
  286. clearInterval(this.time);
  287. this.time_list[this.active_index].status = 2;
  288. }
  289. let day = parseInt((time/1000/60/60/24)%30);
  290. let hou = parseInt((time/1000/60/60)%24);
  291. let min = parseInt((time/1000/60)%60);
  292. let sec = parseInt((time/1000)%60);
  293. if (day > 0) {
  294. this.html = day+"天"+hou+":"+(min<10?"0"+min:min) + ":"+(sec<10?"0"+sec:sec);
  295. } else {
  296. this.html = hou+":"+(min<10?"0"+min:min) + ":"+(sec<10?"0"+sec:sec);
  297. }
  298. },1000);
  299. },
  300. router_go() {
  301. uni.reLaunch({
  302. url: '/pages/index/index'
  303. })
  304. }
  305. },
  306. onShareAppMessage() {},
  307. // #ifdef MP-WEIXIN
  308. onShareTimeline() {
  309. // 分享朋友圈beta
  310. return this.$shareTimeline({
  311. title: this.$children[0].navigationBarTitle,
  312. query: {
  313. } // 此处填写页面的参数
  314. });
  315. },
  316. // #endif
  317. components: {
  318. 'product-list': appProductList,
  319. },
  320. watch: {
  321. tabBarNavs: {
  322. handler: function() {
  323. this.set_nav();
  324. },
  325. immediate: true,
  326. }
  327. }
  328. }
  329. </script>
  330. <style scoped lang="scss">
  331. .ms {
  332. position: absolute;
  333. height: 100%;
  334. width: 100%;
  335. background: white;
  336. }
  337. .time-list {
  338. width: #{750upx};
  339. height: #{176upx};
  340. position: fixed;
  341. top: 0;
  342. left: 0;
  343. }
  344. .goods-list {
  345. margin-top: #{176upx};
  346. width: #{750upx};
  347. height: calc(100% - #{176upx});
  348. }
  349. .is_book_list {
  350. margin-top: #{350upx};
  351. width: #{750upx};
  352. height: calc(100% - #{350upx});
  353. }
  354. .scroll {
  355. width: #{750upx};
  356. height: #{111upx};
  357. position: relative;
  358. z-index: 1500;
  359. background: #ffffff;
  360. .content {
  361. white-space: nowrap;
  362. /*z-index: 1500;*/
  363. height: #{96upx};
  364. background-color: #30353c;
  365. }
  366. .item {
  367. display: inline-block;
  368. width: #{150upx};
  369. height: #{96upx};
  370. position: relative;
  371. vertical-align:top;
  372. color: #bbbbbb;
  373. > view {
  374. text-align: center;
  375. line-height: 1;
  376. }
  377. }
  378. .teaser {
  379. line-height: #{96upx};
  380. text-align: center;
  381. }
  382. .open-time {
  383. margin-top: #{20upx};
  384. font-size: #{32upx};
  385. }
  386. .label {
  387. margin-top: #{5upx};
  388. font-size: #{22upx};
  389. }
  390. .no-active-item {
  391. background-color: #30353c;
  392. }
  393. .active-item {
  394. color: #ffffff;
  395. .icon {
  396. border: #{20rpx} solid;
  397. border-bottom-color: transparent;
  398. border-left-color: transparent;
  399. border-right-color: transparent;
  400. position: absolute;
  401. bottom: #{-36rpx};
  402. left: 50%;
  403. transform: translateX(-50%);
  404. }
  405. }
  406. }
  407. .time {
  408. background-color: #ffffff;
  409. height: #{80upx};
  410. line-height: #{80rpx};
  411. position: relative;
  412. top: #{-18upx};
  413. .left {
  414. width: #{6upx};
  415. height: 100%;
  416. background-color: #ff4544;
  417. position: absolute;
  418. top: 0;
  419. z-index: 1600;
  420. }
  421. .text {
  422. margin-left: #{20rpx};
  423. font-size: #{28rpx};
  424. color: #ff4544;
  425. }
  426. .timing {
  427. font-size: #{28rpx};
  428. margin-right: #{24rpx};
  429. color: #999999;
  430. }
  431. .time-html {
  432. margin-left: #{12rpx};
  433. color: #353535;
  434. }
  435. }
  436. .empty {
  437. background-color: #ffffff;
  438. width: 100%;
  439. font-size: #{26upx};
  440. >image {
  441. width: #{350upx};
  442. height: #{350upx};
  443. margin-top: #{150upx};
  444. }
  445. >text {
  446. font-size: #{32upx};
  447. color: #353535;
  448. line-height: 1;
  449. margin-top: #{80upx};
  450. }
  451. >button {
  452. padding: 0;
  453. border: 0;
  454. border-radius: #{34upx};
  455. height: #{68upx};
  456. font-size: #{26upx};
  457. text-align: center;
  458. color: #ffffff;
  459. line-height: #{68upx};
  460. width: #{240upx};
  461. margin-top: #{96upx};
  462. }
  463. }
  464. .empty-goods {
  465. margin-top: 45upx;
  466. >image {
  467. width: #{150upx};
  468. height: #{150upx};
  469. }
  470. }
  471. </style>