|
@@ -0,0 +1,469 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="page">
|
|
|
|
|
+ <van-sticky class="preSticky" @change="onSticky" z-index="99">
|
|
|
|
|
+ <div class="navBar" :class="{ isFixed: isFixed }">
|
|
|
|
|
+ <img src="@assets/icon_fanhui2.png" @click="goBack" class="back" alt="" />
|
|
|
|
|
+ <div class="title">{{ collectionInfo.name }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </van-sticky>
|
|
|
|
|
+ <div class="page-top">
|
|
|
|
|
+ <van-image
|
|
|
|
|
+ class="page-bg"
|
|
|
|
|
+ width="100%"
|
|
|
|
|
+ height="220"
|
|
|
|
|
+ :src="getImg(changeImgs(collectionInfo.pic))"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ />
|
|
|
|
|
+ <div class="page-box">
|
|
|
|
|
+ <div class="minter">
|
|
|
|
|
+ <van-image :src="collectionInfo.minterAvatar" width="50" height="50" :radius="100"></van-image>
|
|
|
|
|
+ <div class="minter-title">{{ collectionInfo.minter }}</div>
|
|
|
|
|
+ <div class="sale-list">
|
|
|
|
|
+ <div class="sales">
|
|
|
|
|
+ <span class="sales-fir">流通</span>
|
|
|
|
|
+ <span>{{ totalElements }}份</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="page-pla"></div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="page-content">
|
|
|
|
|
+ <div class="tabs">
|
|
|
|
|
+ <div class="tab" :class="{ prim: sort === 'id,desc' }" @click="changeSelect('id,desc')">
|
|
|
|
|
+ <span>综合排序</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="tab price"
|
|
|
|
|
+ :class="[{ prim: sort === 'price' }, price_direction]"
|
|
|
|
|
+ @click="changeSelect('price')"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span>价格排序</span> <van-icon size="8" name="arrow-up" /> <van-icon size="8" name="arrow-down" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <van-list
|
|
|
|
|
+ class="list"
|
|
|
|
|
+ v-model:loading="loading"
|
|
|
|
|
+ :finished="finished"
|
|
|
|
|
+ finished-text=""
|
|
|
|
|
+ @load="getData"
|
|
|
|
|
+ :immediate-check="false"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="product-info" @click="goDetail(item)" v-for="(item, index) in list" :key="index">
|
|
|
|
|
+ <div class="top">
|
|
|
|
|
+ <div class="user">
|
|
|
|
|
+ <van-image width="24" height="24" radius="24" :src="item.ownerAvatar" fit="cover" />
|
|
|
|
|
+ <span>{{ item.owner }}</span>
|
|
|
|
|
+ <span class="status out" v-if="item.inPaying">支付中</span>
|
|
|
|
|
+ <span class="status out" v-else-if="!item.salable">仅展示</span>
|
|
|
|
|
+ <span class="status prim" v-else>寄售</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="price" v-if="item.salable">¥{{ item.price }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="bottom">
|
|
|
|
|
+ <div class="name">{{ item.name }}</div>
|
|
|
|
|
+ <div class="num" v-if="getNum(item)">#{{ getNum(item) }}</div>
|
|
|
|
|
+ <div class="num" v-else></div>
|
|
|
|
|
+ <div class="buy" v-if="!item.soldOut">
|
|
|
|
|
+ <span>{{ !item.salable ? '去看看' : '去购买' }}</span>
|
|
|
|
|
+
|
|
|
|
|
+ <img src="../../assets/icon-jiantou2.png" alt="" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </van-list>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+let fromRoute = null;
|
|
|
|
|
+import { useRoute } from 'vue-router';
|
|
|
|
|
+import { computed, onMounted, ref } from 'vue';
|
|
|
|
|
+import http from '@/plugins/http';
|
|
|
|
|
+//获取列表
|
|
|
|
|
+import useList from '@/plugins/list';
|
|
|
|
|
+export default {
|
|
|
|
|
+ setup() {
|
|
|
|
|
+ let beforeData = {
|
|
|
|
|
+ query: {
|
|
|
|
|
+ onShelf: true,
|
|
|
|
|
+ del: false,
|
|
|
|
|
+ salable: true,
|
|
|
|
|
+ prefixName: ''
|
|
|
|
|
+ },
|
|
|
|
|
+ sort: 'id,desc'
|
|
|
|
|
+ };
|
|
|
|
|
+ function getBeforeData() {
|
|
|
|
|
+ if (collectionInfo.value.prefixName) {
|
|
|
|
|
+ beforeData.query.prefixName = collectionInfo.value.prefixName;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (sort.value) {
|
|
|
|
|
+ beforeData.sort = sort.value === 'price' ? sort.value + ',' + price_direction.value : sort.value;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ const { empty, loading, finished, list, totalElements, getData } = useList('/collection/all', beforeData);
|
|
|
|
|
+
|
|
|
|
|
+ const collectionId = computed(() => {
|
|
|
|
|
+ return useRoute().query.id;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const collectionInfo = ref({});
|
|
|
|
|
+ const sort = ref('id,desc');
|
|
|
|
|
+ const directions = ['asc', 'desc'];
|
|
|
|
|
+ const price_direction = ref('asc');
|
|
|
|
|
+ onMounted(() => {
|
|
|
|
|
+ finished.value = true;
|
|
|
|
|
+ http.http.get('/collection/get/' + collectionId.value).then(res => {
|
|
|
|
|
+ collectionInfo.value = res;
|
|
|
|
|
+ getBeforeData();
|
|
|
|
|
+ finished.value = false;
|
|
|
|
|
+ getData(true);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ function changeImgs(list = []) {
|
|
|
|
|
+ return list.map(item => {
|
|
|
|
|
+ if (item.type === 'video/mp4') {
|
|
|
|
|
+ return item.thumb;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return item.url;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function getNum(info) {
|
|
|
|
|
+ if (info.number) {
|
|
|
|
|
+ return info.number;
|
|
|
|
|
+ } else if (info.name) {
|
|
|
|
|
+ let number = info.name.split('#')[1];
|
|
|
|
|
+ return number;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return '';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function changeSelect(_sort) {
|
|
|
|
|
+ if (_sort === 'price' && sort.value === _sort) {
|
|
|
|
|
+ let _index = directions.findIndex(item => {
|
|
|
|
|
+ return item === price_direction.value;
|
|
|
|
|
+ });
|
|
|
|
|
+ console.log(_index);
|
|
|
|
|
+ price_direction.value = directions[(_index + 1) % 2];
|
|
|
|
|
+ }
|
|
|
|
|
+ sort.value = _sort;
|
|
|
|
|
+ getBeforeData();
|
|
|
|
|
+ getData(true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const isFixed = ref(false);
|
|
|
|
|
+ function onSticky(_isFixed) {
|
|
|
|
|
+ isFixed.value = _isFixed;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ collectionInfo,
|
|
|
|
|
+ sort,
|
|
|
|
|
+ price_direction,
|
|
|
|
|
+ changeImgs,
|
|
|
|
|
+ getNum,
|
|
|
|
|
+ changeSelect,
|
|
|
|
|
+ getData,
|
|
|
|
|
+ isFixed,
|
|
|
|
|
+ empty,
|
|
|
|
|
+ loading,
|
|
|
|
|
+ finished,
|
|
|
|
|
+ list,
|
|
|
|
|
+ totalElements,
|
|
|
|
|
+ onSticky
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ name: 'prefixNameList',
|
|
|
|
|
+ inject: ['setKeeps', 'scrollWrapper', 'changeScroll'],
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ scrollTop: 0
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ beforeRouteEnter(to, from) {
|
|
|
|
|
+ fromRoute = from;
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ goBack() {
|
|
|
|
|
+ if (!fromRoute || !fromRoute.name) {
|
|
|
|
|
+ this.$router.replace('/home');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$router.back();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ goDetail(info) {
|
|
|
|
|
+ this.$router.push({
|
|
|
|
|
+ path: '/productDetail/' + info.id
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ activated() {
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.changeScroll(this.scrollTop);
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ beforeRouteLeave(to, from, next) {
|
|
|
|
|
+ if (to.name === 'productDetail') {
|
|
|
|
|
+ this.scrollTop = this.scrollWrapper.scrollTop;
|
|
|
|
|
+ this.setKeeps(['prefixNameList']);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.scrollTop = 0;
|
|
|
|
|
+ this.setKeeps(['prefixNameList'], false);
|
|
|
|
|
+ }
|
|
|
|
|
+ next();
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="less" scoped>
|
|
|
|
|
+.page-pla {
|
|
|
|
|
+ height: calc(var(--safe-top) + 160px);
|
|
|
|
|
+}
|
|
|
|
|
+.page-top {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+}
|
|
|
|
|
+.page-box {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ z-index: 20;
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.6);
|
|
|
|
|
+ padding-top: calc(var(--safe-top) + 50px);
|
|
|
|
|
+}
|
|
|
|
|
+.navBar {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ padding: calc(var(--safe-top) + 13px) 0 13px;
|
|
|
|
|
+
|
|
|
|
|
+ .back {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ width: 24px;
|
|
|
|
|
+ height: 24px;
|
|
|
|
|
+ left: 16px;
|
|
|
|
|
+ top: calc(var(--safe-top) + 13px);
|
|
|
|
|
+ }
|
|
|
|
|
+ .title {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #ffffff;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.isFixed {
|
|
|
|
|
+ background-color: #000;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.minter {
|
|
|
|
|
+ .flex-col();
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding-top: 22px;
|
|
|
|
|
+
|
|
|
|
|
+ .minter-title {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #ffffff;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ margin-top: 6px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .sale-list {
|
|
|
|
|
+ margin-top: 8px;
|
|
|
|
|
+
|
|
|
|
|
+ .sales {
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ font-size: @font1;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+
|
|
|
|
|
+ span {
|
|
|
|
|
+ padding: 0 10px;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+ height: 18px;
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ &.sales-fir {
|
|
|
|
|
+ background: #00fe1e;
|
|
|
|
|
+ color: #000000;
|
|
|
|
|
+ }
|
|
|
|
|
+ background-color: rgba(255, 255, 255, 0.08);
|
|
|
|
|
+ color: #00fe1e;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.page-content {
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+ border-radius: 16px 16px 0px 0px;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ z-index: 2;
|
|
|
|
|
+ padding: 10px 16px 16px;
|
|
|
|
|
+}
|
|
|
|
|
+.list {
|
|
|
|
|
+ padding-top: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+.product-info {
|
|
|
|
|
+ background: #f5f7fa;
|
|
|
|
|
+ border-radius: 12px;
|
|
|
|
|
+ padding: 12px;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+
|
|
|
|
|
+ .top {
|
|
|
|
|
+ .flex();
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+
|
|
|
|
|
+ .user {
|
|
|
|
|
+ .flex();
|
|
|
|
|
+ span {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #939599;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ margin-left: 6px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .status {
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ min-width: 44px;
|
|
|
|
|
+ height: 20px;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ border: 1px solid #c8c9cc;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ line-height: 20px;
|
|
|
|
|
+ margin-left: 10px;
|
|
|
|
|
+ // &.prim {
|
|
|
|
|
+ // color: @prim;
|
|
|
|
|
+ // border-color: @prim;
|
|
|
|
|
+ // }
|
|
|
|
|
+ &.out {
|
|
|
|
|
+ background-color: #c8c9cc;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .price {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #000000;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .bottom {
|
|
|
|
|
+ .flex();
|
|
|
|
|
+
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #000000;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ margin-top: 8px;
|
|
|
|
|
+
|
|
|
|
|
+ .name {
|
|
|
|
|
+ max-width: 100px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ }
|
|
|
|
|
+ .num {
|
|
|
|
|
+ flex-grow: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .buy {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ .flex();
|
|
|
|
|
+ img {
|
|
|
|
|
+ width: 18px;
|
|
|
|
|
+ height: 18px;
|
|
|
|
|
+ margin-left: 1px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+.product-info + .product-info {
|
|
|
|
|
+ margin-top: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+.tabs {
|
|
|
|
|
+ .flex();
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ position: sticky;
|
|
|
|
|
+ top: 50px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ z-index: 20;
|
|
|
|
|
+
|
|
|
|
|
+ .tab {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-family: PingFangSC-Regular, PingFang SC;
|
|
|
|
|
+ font-weight: 400;
|
|
|
|
|
+ color: #939599;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ padding: 0 20px;
|
|
|
|
|
+ &.price {
|
|
|
|
|
+ .van-icon {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: 10px;
|
|
|
|
|
+ color: #939599;
|
|
|
|
|
+
|
|
|
|
|
+ &.van-icon-arrow-down {
|
|
|
|
|
+ top: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.van-icon-arrow-up {
|
|
|
|
|
+ bottom: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &::after {
|
|
|
|
|
+ content: '';
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ bottom: -2px;
|
|
|
|
|
+ width: 0;
|
|
|
|
|
+ height: 2px;
|
|
|
|
|
+ background: #131313;
|
|
|
|
|
+ border-radius: 2px;
|
|
|
|
|
+ left: 50%;
|
|
|
|
|
+ transform: translateX(-50%);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.prim {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #000000;
|
|
|
|
|
+
|
|
|
|
|
+ &.desc {
|
|
|
|
|
+ .van-icon {
|
|
|
|
|
+ &.van-icon-arrow-down {
|
|
|
|
|
+ color: #000;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.asc {
|
|
|
|
|
+ .van-icon {
|
|
|
|
|
+ &.van-icon-arrow-up {
|
|
|
|
|
+ color: #000;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &::after {
|
|
|
|
|
+ width: 34px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|