123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- <template>
- <view>
- <view>
- <scroll-view scroll-x class="scroll-view">
- <view class="scroll-view-item-wrapper" v-for="item in tabs" :key="item" @click="onTabClick(item)">
- <view class="scroll-view-item" :class="{active:currentTab===item}">
- <view class="time">
- {{item}}
- </view>
- <view class="status">
- {{tabStatus[item]}}
- </view>
- </view>
- </view>
- </scroll-view>
- </view>
- <view class="product-list">
- <view class="product-item" v-for="item in currentList" :key="item.id">
- <view class="image">
- <image :src="JSON.parse(item.image)[0].url" mode="aspectFit" style="max-width: 100%;max-height: 100%;">
- </image>
- </view>
- <view class="content">
- <view class="title">
- {{item.title}}
- </view>
- <view class="progress">
- <view class="piece">
- 仅剩{{item.stock}}{{item.unitName}}
- </view>
- </view>
- <view class="tag">
- <view class="text">
- 限时价
- </view>
- </view>
- <view class="box">
- <view class="price-box">
- <view class="price">
- <view class="price-small">
- ¥
- </view>
- <view class="price-large">
- {{item.price}}
- </view>
- </view>
- </view>
- <view>
- <view class="btn" @click="onSeckill(item)">
- {{idStatusMap[item.id]===SECKILL_STATUS[1]?'马上抢':idStatusMap[item.id]}}
- </view>
- </view>
- </view>
- </view>
- </view>
- </view>
- </view>
- </template>
- <script>
- import dayjs from 'dayjs'
- import {
- getTime
- } from '../../util'
- const SECKILL_STATUS = {
- 0: '已结束',
- 1: '抢购中',
- 2: '即将开始'
- }
- export default {
- data() {
- return {
- seckillStartTimeMap: {},
- idStatusMap: {},
- currentTab: null,
- SECKILL_STATUS
- }
- },
- computed: {
- tabs() {
- return Object.keys(this.seckillStartTimeMap)
- },
- currentList() {
- return this.seckillStartTimeMap[this.currentTab] || []
- },
- tabStatus() {
- const {
- idStatusMap,
- seckillStartTimeMap
- } = this
- const statusMap = {}
- for (const k in seckillStartTimeMap) {
- statusMap[k] = []
- const list = seckillStartTimeMap[k]
- let status = SECKILL_STATUS[2]
- list.forEach(({
- id
- }) => {
- const _s = idStatusMap[id]
- if (_s === SECKILL_STATUS[0] && status === SECKILL_STATUS[1]) {
- return
- }
- status = _s
- })
- statusMap[k] = status
- }
- if (this.currentTab === null) {
- Object.keys(statusMap).forEach(el => {
- const v = statusMap[el]
- if (v === SECKILL_STATUS[1] && this.currentTab === null) {
- this.currentTab = el
- }
- })
- }
- return statusMap
- }
- },
- mounted() {
- this.listCurrent()
- },
- methods: {
- listCurrent() {
- this.$api.request('get', 'seckill/app/listCurrent', {
- storageId: this.$store.state.storageId,
- sort: '0'
- }).then(({
- data = []
- }) => {
- this.getList(data)
- this.getProductStatus(data)
- })
- },
- getList(data) {
- this.seckillStartTimeMap = {}
- this.idStatusMap = {}
- for (let i = 0; i < data.length; i++) {
- const {
- seckillStartTime
- } = data[i]
- if (!(seckillStartTime in this.seckillStartTimeMap)) {
- this.seckillStartTimeMap[seckillStartTime] = []
- }
- this.seckillStartTimeMap[seckillStartTime].push(data[i])
- }
- },
- getProductStatus(data) {
- this.idStatusMap = {}
- const now = dayjs()
- for (let i = 0; i < data.length; i++) {
- const {
- seckillStartTime,
- id,
- seckillStopTime
- } = data[i]
- if (getTime(seckillStopTime).isBefore(now)) {
- this.idStatusMap[id] = SECKILL_STATUS[0]
- } else if (getTime(seckillStartTime).isAfter(now)) {
- this.idStatusMap[id] = SECKILL_STATUS[2]
- } else {
- this.idStatusMap[id] = SECKILL_STATUS[1]
- }
- }
- if (this.$_timer) {
- clearTimeout(this.$_timer)
- this.$_timer = null
- }
- this.$_timer = setTimeout(() => {
- this.getProductStatus(data)
- }, 1000)
- },
- onTabClick(v) {
- this.currentTab = v
- },
- onSeckill(item) {
- const {
- idStatusMap
- } = this
- const {
- id,
- productId
- } = item
- if (idStatusMap[id] !== SECKILL_STATUS[1]) {
- return
- }
- uni.navigateTo({
- url: `/pages/product/detail?id=${productId}`
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .scroll-view {
- white-space: nowrap;
- width: 100%;
- display: flex;
- align-items: center;
- height: 128rpx;
- background-image: url('../../static/product/bg_seckill.png');
- }
- .scroll-view-item-wrapper {
- display: inline-block;
- height: 100%;
- }
- .scroll-view-item {
- flex-shrink: 0;
- display: flex;
- align-items: center;
- flex-direction: column;
- justify-content: center;
- color: #ffb2b2;
- min-width: 160rpx;
- height: 100%;
- .time {
- font-size: 32rpx;
- line-height: 32rpx;
- font-weight: 700;
- }
- .status {
- font-size: 24rpx;
- line-height: 24rpx;
- font-weight: 500;
- padding-top: 16rpx;
- }
- &.active {
- .time {
- color: #fff;
- font-size: 36rpx;
- line-height: 36rpx;
- }
- .status {
- color: #fff;
- font-size: 28rpx;
- line-height: 28rpx;
- font-weight: 700;
- }
- }
- }
- .product-list {
- width: 100%;
- display: flex;
- justify-content: space-between;
- flex-wrap: wrap;
- margin-top: 20rpx;
- padding-bottom: 32rpx;
- }
- .product-item {
- width: 49%;
- padding: 20rpx 20rpx 38rpx;
- border-radius: 12rpx;
- background-color: #fff;
- margin-bottom: 4%;
- position: relative;
- .image {
- width: 100%;
- height: 320rpx;
- }
- .content {
- width: 100%;
- padding-top: 16rpx;
- }
- .title {
- font-size: 26rpx;
- font-weight: 400;
- color: #333;
- word-break: break-all;
- overflow: hidden;
- text-overflow: ellipsis;
- margin-bottom: 20rpx;
- }
- .progress {
- overflow: hidden;
- background-color: #fff;
- width: 100%;
- border-radius: 20rpx;
- height: 36rpx;
- position: relative;
- border: 1px solid #eb3729;
- .piece {
- position: absolute;
- left: 0;
- right: 0;
- transform: translateY(-50%);
- top: 49%;
- font-size: 22rpx;
- word-wrap: normal;
- text-align: center;
- color: #eb3729;
- }
- }
- .tag {
- display: flex;
- padding-top: 26rpx;
- padding-bottom: 26rpx;
- color: #ff201f;
- font-size: 24rpx;
- .text {
- border: 1px solid #ff201f;
- padding: 8rpx 12rpx;
- border-radius: 12rpx;
- }
- }
- .box {
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: space-between;
- .price-box {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- .price {
- display: flex;
- align-items: flex-end;
- color: #eb0909;
- }
- .price-small {
- font-size: 24rpx;
- }
- .price-large {
- font-size: 36rpx;
- font-weight: 600;
- }
- }
- .btn {
- font-size: 24rpx;
- color: #fff;
- width: 148rpx;
- height: 56rpx;
- border-radius: 4rpx;
- text-align: center;
- line-height: 56rpx;
- position: absolute;
- right: 32rpx;
- bottom: 32rpx;
- background-color: #eb3729;
- }
- }
- }
- </style>
|