panhui il y a 4 ans
Parent
commit
3f1b3dd032

+ 233 - 0
src/main/nine-space/src/components/CouponInfo.vue

@@ -0,0 +1,233 @@
+<template>
+    <div class="coupon" @click="choose" :class="{ notUse: notUse }">
+        <div class="coupon-top">
+            <div class="text1">{{ info.name }}</div>
+            <div class="text2">
+                <span>兑换券编码</span>
+                <span>{{ info.id }}</span>
+            </div>
+        </div>
+        <div class="coupon-bottom">
+            <span>有效期至:{{ info.expiration }}</span>
+            <span v-if="info.limited">规定商品可用</span>
+        </div>
+        <template v-if="needChoose && !notUse">
+            <img v-if="chooseId === info.id" class="icon" src="../assets/icon_gouxuan_pre.png" alt="" />
+            <img v-else class="icon" src="../assets/icon_gouxuan_huise.png" alt="" />
+        </template>
+        <div v-else-if="!notUse" class="btn" @click.prevent="goDetail">
+            <span>立即使用</span>
+        </div>
+
+        <div class="tag" v-if="notUse">
+            {{ info.used ? '已使用' : checkTime(this.info) ? '指定藏品使用' : '已过期' }}
+        </div>
+    </div>
+</template>
+
+<script>
+import coupon from '../mixins/coupon';
+export default {
+    props: {
+        info: {
+            type: Object,
+            default: () => {
+                return {};
+            }
+        },
+        chooseId: {
+            type: Number,
+            default: 0
+        },
+        needChoose: {
+            type: Boolean,
+            default: false
+        },
+        collectionId: {
+            type: Number,
+            default: 0
+        }
+    },
+    mixins: [coupon],
+    computed: {
+        notUse() {
+            return this.info.used || !this.checkTime(this.info) || !this.checkUse(this.info, this.collectionId);
+        }
+    },
+    methods: {
+        choose() {
+            if (!this.notUse) {
+                this.$emit('choose', this.info);
+            }
+        },
+        goDetail() {
+            this.$router.replace('/home');
+        }
+    }
+};
+</script>
+
+<style lang="less" scoped>
+.coupon {
+    border-radius: 8px;
+    background: linear-gradient(135deg, rgba(253, 251, 96, 1), rgba(255, 143, 62, 1));
+    position: relative;
+    padding: 0 10px;
+    margin: 8px;
+    display: inline-block;
+    width: calc(100% - 36px);
+    // width: 100%;
+    &::after {
+        content: '';
+        position: absolute;
+        top: 1px;
+        right: 1px;
+        left: 1px;
+        bottom: 1px;
+        border-radius: 8px;
+        background-color: @bg;
+        z-index: 0;
+    }
+
+    div {
+        position: relative;
+        z-index: 1;
+    }
+
+    .coupon-top {
+        padding: 16px 0;
+
+        .text1 {
+            font-size: 18px;
+            font-weight: bold;
+            color: #939599;
+            line-height: 24px;
+            background: linear-gradient(0deg, #fdfb60 0%, #ff8f3e 100%);
+            -webkit-background-clip: text;
+            -webkit-text-fill-color: transparent;
+        }
+
+        .text2 {
+            padding-top: 6px;
+            font-size: 12px;
+            line-height: 17px;
+            color: #939599;
+            span {
+                &:last-child {
+                    color: #fff;
+                    margin-left: 6px;
+                }
+            }
+        }
+    }
+
+    .coupon-bottom {
+        border-top: 1px dashed #ebebeb50;
+        color: #939599;
+        font-size: 11px;
+        line-height: 17px;
+        padding: 9px 0;
+        display: flex;
+        justify-content: space-between;
+        position: relative;
+        &::before {
+            content: '';
+            position: absolute;
+            background-color: #181818;
+            width: 16px;
+            height: 16px;
+            left: -18px;
+            top: -8px;
+            border-radius: 16px;
+        }
+        &::after {
+            content: '';
+            position: absolute;
+            background-color: #181818;
+            width: 16px;
+            height: 16px;
+            right: -18px;
+            top: -8px;
+            border-radius: 16px;
+        }
+    }
+
+    .icon {
+        position: absolute;
+        width: 24px;
+        height: 24px;
+        right: 10px;
+        top: 30px;
+        z-index: 3;
+    }
+
+    &.notUse {
+        background: @bg;
+
+        .coupon-top {
+            .text1 {
+                -webkit-background-clip: none;
+                -webkit-text-fill-color: #939599;
+            }
+            .text2 {
+                span {
+                    &:last-child {
+                        color: #939599;
+                    }
+                }
+            }
+        }
+    }
+}
+
+.btn {
+    position: absolute !important;
+    right: 10px;
+    top: 30px;
+    width: 70px;
+    height: 26px;
+    font-size: 12px;
+    color: #fdfb60;
+    line-height: 26px;
+    text-align: center;
+    border-radius: 16px;
+    background: linear-gradient(135deg, rgba(253, 251, 96, 1), rgba(255, 143, 62, 1));
+    &::after {
+        content: '';
+        position: absolute;
+        top: 1px;
+        left: 1px;
+        right: 1px;
+        bottom: 1px;
+        background-color: @bg;
+        border-radius: 16px;
+        z-index: 0;
+        transition: backgroundColor ease-in-out 0.3s;
+    }
+
+    span {
+        position: relative;
+        z-index: 1;
+    }
+
+    &:active {
+        &::after {
+            background-color: transparent;
+        }
+        color: #fff;
+    }
+}
+
+.tag {
+    font-size: 11px;
+    color: #ffffff;
+    line-height: 18px;
+    height: 18px;
+    background: #939599;
+    border-radius: 0px 8px 0px 8px;
+    padding: 0 7px;
+    position: absolute !important;
+    right: 0;
+    top: 0;
+}
+</style>

+ 17 - 0
src/main/nine-space/src/mixins/coupon.js

@@ -0,0 +1,17 @@
+import dayjs from 'dayjs';
+var isSameOrBefore = require('dayjs/plugin/isSameOrBefore');
+dayjs.extend(isSameOrBefore);
+export default {
+    methods: {
+        checkTime(info) {
+            return dayjs().isSameOrBefore(info.expiration);
+        },
+        checkUse(info, collectionId = 0) {
+            if (collectionId && info.limited) {
+                return [...info.collectionIds].includes(collectionId);
+            } else {
+                return true;
+            }
+        }
+    }
+};

+ 198 - 62
src/main/nine-space/src/views/Store.vue

@@ -3,33 +3,43 @@
         <van-sticky ref="top" :offset-top="bar.value.show ? 46 : 0">
             <div class="top">
                 <div class="top-btn">
-                    <div class="btn" :class="{ active: active === 'explore' }">我拥有的</div>
-                    <!-- <div
-            class="btn"
-            :class="{ active: active === 'creator' }"
-            @click="changeActive('creator')"
-          >
-            我卖出的
-          </div> -->
+                    <div class="btn" :class="{ active: active === 'explore' }" @click="changeActive('explore')">
+                        我拥有的
+                    </div>
+                    <div class="btn" :class="{ active: active === 'creator' }" @click="changeActive('creator')">
+                        我卖出的
+                    </div>
+                    <div class="btn" :class="{ active: active === 'coupon' }" @click="changeActive('coupon')">
+                        兑换券
+                    </div>
                 </div>
-                <div class="search" v-if="isLogin" @click="$router.push('/assetSearch')">
+                <div
+                    class="search"
+                    v-if="isLogin && active !== 'coupon'"
+                    @click="$router.push('/assetSearch?status=' + status)"
+                >
                     <img src="../assets/svgs/search.svg" alt="" />
                 </div>
             </div>
 
-            <van-tabs
-                v-model:active="type"
-                line-width="16"
-                line-height="2"
-                :ellipsis="false"
-                @change="(page = 0), getList()"
-            >
+            <van-tabs v-model:active="type" line-width="16" line-height="2" :ellipsis="false" @click="changeTab">
                 <van-tab
                     :title="item.label"
-                    :name="item.type"
+                    :name="
+                        item.type === 'select' ? (type === item.value[0] ? item.value[1] : item.value[0]) : item.value
+                    "
+                    :title-class="item.type === 'select' && type === item.value[0] ? '' : 'asc'"
                     :key="index"
                     v-for="(item, index) in typeOptions"
-                ></van-tab>
+                >
+                    <template v-if="item.type === 'select'" #title>
+                        <div class="tab">
+                            <span>{{ item.label }}</span>
+                            <van-icon size="8" name="arrow-up" />
+                            <van-icon size="8" name="arrow-down" />
+                        </div>
+                    </template>
+                </van-tab>
             </van-tabs>
 
             <!-- <van-button
@@ -46,12 +56,13 @@
         </van-sticky>
 
         <van-list class="box-list" v-model:loading="loading" :finished="finished" finished-text="" @load="getList">
-            <template v-for="(item, index) in list" :key="index">
-                <asset-info :info="item"></asset-info>
+            <template v-for="(item, index) in showList" :key="index">
+                <coupon-info :info="item" v-if="active == 'coupon'"></coupon-info>
+                <asset-info :info="item" v-else></asset-info>
             </template>
 
             <van-empty
-                v-if="empty"
+                v-if="empty || (showList.length === 0 && !loading)"
                 description="你还有没有藏品哦~"
                 :image="require('../assets/kong_png_maichude.png')"
             />
@@ -71,13 +82,16 @@
 
 <script>
 import AssetInfo from '../components/asset/assetInfo.vue';
+import CouponInfo from '../components/CouponInfo.vue';
 import asset from '../mixins/asset';
+import coupon from '../mixins/coupon';
 export default {
     name: 'discover',
-    mixins: [asset],
+    mixins: [asset, coupon],
     inject: ['bar'],
     components: {
-        AssetInfo
+        AssetInfo,
+        CouponInfo
     },
     data() {
         return {
@@ -87,20 +101,6 @@ export default {
             empty: false,
             list: [],
             label: '全部',
-            typeOptions: [
-                {
-                    label: '全部',
-                    type: ''
-                },
-                {
-                    label: '售卖',
-                    type: 'ON_SALE'
-                },
-                {
-                    label: '仅展示',
-                    type: 'NORMAL'
-                }
-            ],
             showSelect: false,
             actions: [{ name: '选项一' }, { name: '选项二' }, { name: '选项三' }],
             action: null,
@@ -111,6 +111,78 @@ export default {
             name: ''
         };
     },
+    computed: {
+        typeOptions() {
+            if (this.active === 'explore') {
+                return [
+                    {
+                        label: '全部',
+                        value: ''
+                    },
+                    {
+                        label: '售卖',
+                        value: 'ON_SALE'
+                    },
+                    {
+                        label: '仅展示',
+                        value: 'NORMAL'
+                    }
+                ];
+            } else if (this.active === 'creator') {
+                return [
+                    {
+                        label: '全部',
+                        value: 'createdAt,desc'
+                    },
+                    {
+                        label: '价格',
+                        value: ['sellPrice,desc', 'sellPrice,asc'],
+                        type: 'select'
+                    }
+                ];
+            } else {
+                return [
+                    {
+                        label: '未使用',
+                        value: 'CAN_USE'
+                    },
+                    {
+                        label: '不可用',
+                        value: 'CANNOT_USE'
+                    }
+                ];
+            }
+        },
+        showList() {
+            if (this.active === 'coupon') {
+                return [...this.list].filter(item => {
+                    if (this.type === 'CAN_USE') {
+                        return this.checkTime(item);
+                    } else {
+                        return !this.checkTime(item);
+                    }
+                });
+            } else {
+                return this.list;
+            }
+        },
+        sort() {
+            if (this.active === 'creator') {
+                return this.type;
+            } else {
+                return 'createdAt,desc';
+            }
+        },
+        status() {
+            if (this.active === 'explore') {
+                return 'NORMAL,TRADING,GIFTING';
+            } else if (this.active === 'creator') {
+                return 'TRANSFERRED';
+            } else {
+                return '';
+            }
+        }
+    },
     mounted() {
         this.$nextTick(() => {
             this.stiky = this.$refs.top.$el.childNodes[0];
@@ -127,47 +199,75 @@ export default {
             if (this.page === 0) {
                 this.list = [];
             }
-            this.loading = true;
             this.finished = false;
             this.empty = false;
             let form = {
                 page: this.page,
                 size: 20,
+                sort: this.sort,
                 query: {
                     userId: this.$store.state.userInfo.id,
-                    status: 'NORMAL,TRADING,GIFTING'
-                },
-                sort: 'createdAt,desc'
+                    ...this.beforeQuery()
+                }
             };
-            if (this.type === 'NORMAL') {
-                form.query = {
-                    ...form.query,
-                    publicShow: true,
-                    consignment: false
+            this.$http
+                .post(this.active === 'coupon' ? '/userCoupon/all' : '/asset/all', form, { body: 'json' })
+                .then(res => {
+                    this.list = [...this.list, ...res.content];
+                    this.empty = res.empty;
+                    this.loading = false;
+                    this.finished = res.last;
+                    if (!this.finished) {
+                        this.page = this.page + 1;
+                    }
+                });
+        },
+        beforeQuery() {
+            let form = {};
+            if (this.active == 'explore') {
+                form = {
+                    status: this.status
                 };
-            }
-            if (this.type === 'ON_SALE') {
-                form.query = {
-                    ...form.query,
-                    consignment: true
+                if (this.type === 'NORMAL') {
+                    form = {
+                        ...form,
+                        publicShow: true,
+                        consignment: false
+                    };
+                }
+                if (this.type === 'ON_SALE') {
+                    form = {
+                        ...form,
+                        consignment: true
+                    };
+                }
+            } else if (this.active === 'creator') {
+                form = {
+                    status: this.status
+                };
+            } else {
+                form = {
+                    used: false
                 };
             }
-            this.$http.post('/asset/all', form, { body: 'json' }).then(res => {
-                this.list = [...this.list, ...res.content];
-                this.empty = res.empty;
-                this.loading = false;
-                this.finished = res.last;
-                if (!this.finished) {
-                    this.page = this.page + 1;
-                }
-            });
+
+            return form;
         },
         changeActive(active) {
             this.active = active;
+            this.loading = true;
             this.$nextTick(() => {
-                this.bs.value.scrollTo(0, 0);
-                this.bs.value.refresh();
+                this.type = this.typeOptions[0].type;
             });
+            this.page = 0;
+            this.getList();
+        },
+        changeTab() {
+            if (this.active !== 'coupon') {
+                this.loading = true;
+                this.page = 0;
+                this.getList();
+            }
         }
     }
 };
@@ -291,11 +391,29 @@ export default {
     padding: 8px 8px 100px;
 }
 
+.tab {
+    position: relative;
+    padding-right: 14px;
+    .van-icon {
+        position: absolute;
+        right: 0;
+
+        &.van-icon-arrow-down {
+            top: 8px;
+        }
+
+        &.van-icon-arrow-up {
+            bottom: 8px;
+        }
+    }
+}
+
 /deep/.van-tab {
     color: #fff;
     flex-grow: 0;
     padding: 0 0 0 0;
     margin-right: 30px;
+    position: relative;
 
     &.van-tab--active {
         color: @prim;
@@ -312,4 +430,22 @@ export default {
 /deep/.van-action-sheet__description::after {
     border-bottom: 1px solid #f2f2f2;
 }
+
+/deep/.van-tab--active {
+    .tab {
+        .van-icon-arrow-up {
+            color: #646566;
+        }
+    }
+    &.asc {
+        .tab {
+            .van-icon-arrow-up {
+                color: @prim;
+            }
+            .van-icon-arrow-down {
+                color: #646566;
+            }
+        }
+    }
+}
 </style>

+ 1 - 1
src/main/nine-space/src/views/Submit.vue

@@ -21,7 +21,7 @@
                 <div class="text1">GAS费用</div>
                 <div class="text2">¥{{ gas }}</div>
             </div>
-            <div class="info" @click="$router.push('/couponList')">
+            <div class="info" @click="$router.push('/couponList?collectionId=' + info.id)">
                 <div class="text1">优惠券</div>
                 <div class="text2">{{ couponInfo ? '已选择兑换券' : '选择兑换券' }}</div>
             </div>

+ 9 - 2
src/main/nine-space/src/views/asset/Search.vue

@@ -68,14 +68,21 @@ export default {
                 }
             ],
             search: '',
-            url: '/asset/all'
+            url: '/asset/all',
+            status: ''
         };
     },
+    mounted() {
+        if (this.$route.query.status) {
+            this.status = this.$route.query.status;
+        }
+    },
     methods: {
         beforeData() {
             return {
                 query: {
-                    userId: this.$store.state.userInfo.id
+                    userId: this.$store.state.userInfo.id,
+                    status: this.status
                 },
                 search: this.search
             };

+ 39 - 107
src/main/nine-space/src/views/order/CouponList.vue

@@ -1,24 +1,16 @@
 <template>
     <div class="page">
         <van-list class="list" v-model:loading="loading" :finished="finished" finished-text="" @load="getData">
-            <template v-for="(item, index) in list" :key="index">
-                <div class="coupon" @click="choose(item)">
-                    <div class="coupon-top">
-                        <div class="text1">{{ item.name }}</div>
-                        <div class="text2">
-                            <span>兑换券编码</span>
-                            <span>{{ item.id }}</span>
-                        </div>
-                    </div>
-                    <div class="coupon-bottom">
-                        <span>有效期至:{{ item.expiration }}</span>
-                        <span v-if="!item.limited">规定商品可用</span>
-                    </div>
+            <template v-for="(item, index) in useList" :key="index">
+                <coupon-info needChoose :collectionId="collectionId" :info="item" @choose="choose"></coupon-info>
+            </template>
+
+            <van-divider>不可用兑换券</van-divider>
 
-                    <img v-if="chooseId === item.id" class="icon" src="../../assets/icon_gouxuan_pre.png" alt="" />
-                    <img v-else class="icon" src="../../assets/icon_gouxuan_huise.png" alt="" />
-                </div>
+            <template v-for="(item, index) in notUseList" :key="index">
+                <coupon-info needChoose :collectionId="collectionId" :info="item" @choose="choose"></coupon-info>
             </template>
+
             <van-empty v-if="empty" description="暂无兑换券哦~" />
         </van-list>
     </div>
@@ -26,20 +18,40 @@
 
 <script>
 import { mapState } from 'vuex';
+import CouponInfo from '../../components/CouponInfo.vue';
 import list from '../../mixins/list';
+import coupon from '../../mixins/coupon';
 export default {
+    components: { CouponInfo },
     name: 'couponList',
-    mixins: [list],
+    mixins: [list, coupon],
     data() {
         return {
             url: '/userCoupon/all',
             list: [],
             empty: false,
-            chooseId: 0
+            chooseId: 0,
+            size: 40,
+            collectionId: 0
         };
     },
     computed: {
-        ...mapState(['couponInfo'])
+        ...mapState(['couponInfo']),
+        useList() {
+            return [...this.list].filter(item => {
+                return this.checkTime(item) && this.checkUse(item, this.collectionId);
+            });
+        },
+        notUseList() {
+            return [...this.list].filter(item => {
+                return !this.checkTime(item) || !this.checkUse(item, this.collectionId);
+            });
+        }
+    },
+    mounted() {
+        if (this.$route.query.collectionId) {
+            this.collectionId = Number(this.$route.query.collectionId);
+        }
     },
     methods: {
         choose(info) {
@@ -58,96 +70,16 @@ export default {
 
 <style lang="less" scoped>
 .list {
-    padding: 24px 0 50px;
+    padding: 24px 8px 50px;
 }
-.coupon {
-    border-radius: 8px;
-    background: linear-gradient(135deg, rgba(253, 251, 96, 1), rgba(255, 143, 62, 1));
-    position: relative;
-    padding: 0 10px;
-    margin: 0 16px 16px;
-    &::after {
-        content: '';
-        position: absolute;
-        top: 1px;
-        right: 1px;
-        left: 1px;
-        bottom: 1px;
-        border-radius: 8px;
-        background-color: #181818;
-        z-index: 0;
-    }
-
-    div {
-        position: relative;
-        z-index: 1;
-    }
-
-    .coupon-top {
-        padding: 16px 0;
 
-        .text1 {
-            font-size: 18px;
-            font-weight: bold;
-            color: #939599;
-            line-height: 24px;
-            background: linear-gradient(0deg, #fdfb60 0%, #ff8f3e 100%);
-            -webkit-background-clip: text;
-            -webkit-text-fill-color: transparent;
-        }
-
-        .text2 {
-            padding-top: 6px;
-            font-size: 12px;
-            line-height: 17px;
-            color: #939599;
-            span {
-                &:last-child {
-                    color: #fff;
-                    margin-left: 6px;
-                }
-            }
-        }
-    }
-
-    .coupon-bottom {
-        border-top: 1px dashed #ebebeb;
-        color: #939599;
-        font-size: 11px;
-        line-height: 17px;
-        padding: 9px 0;
-        display: flex;
-        justify-content: space-between;
-        position: relative;
-        &::before {
-            content: '';
-            position: absolute;
-            background-color: #181818;
-            width: 16px;
-            height: 16px;
-            left: -18px;
-            top: -8px;
-            border-radius: 16px;
-        }
-        &::after {
-            content: '';
-            position: absolute;
-            background-color: #181818;
-            width: 16px;
-            height: 16px;
-            right: -18px;
-            top: -8px;
-            border-radius: 16px;
-        }
-    }
+.page {
+    background-color: @bg3;
+}
 
-    .icon {
-        position: absolute;
-        width: 24px;
-        height: 24px;
-        right: 10px;
-        top: 30px;
-        z-index: 3;
-    }
+.van-divider {
+    color: #ebebeb50;
+    border-color: #ebebeb50;
+    margin: 32px 8px 8px;
 }
 </style>