ts_aimz_uni/pages/shop/index/index.vue
2025-06-17 16:33:04 +08:00

660 lines
15 KiB
Vue

<template>
<view class="page-container" style="background-color: white;">
<view class="search-container-fixed">
<view class="search-box">
<icon class="mr-10" type="search" size="20"></icon>
<input type="text" :value="keywords" @confirm="doSearch" class="search-input" @input="inputKeywords"
placeholder="请输入软著名称" />
<view @click="doSearch">搜索</view>
</view>
</view>
<view class="title-box">
<view :style="{'background-image': 'url('+imgAssets+'/bg_shop_title.png)'}" class="title-bg">
</view>
<view class="title-container">
<text>AI喵著 为您提供一站式服务</text>
<view class="title-hint-box">
<view class="title-hint-item">
<view class="hook"></view>
<text class="title-hint-txt">选的省心</text>
</view>
<view class="title-hint-item">
<view class="hook"></view>
<text class="title-hint-txt">买的放心</text>
</view>
<view class="title-hint-item">
<view class="hook"></view>
<text class="title-hint-txt">用的安心</text>
</view>
</view>
<view class="title-func-box">
<view class="title-func-item" @click="doBuy">
<image class="func-img" src="/static/images/icon_buy.png"></image>
<text class="func-txt">我要买</text>
</view>
<view class="title-func-item" @click="doPurchase">
<image class="func-img" src="/static/images/icon_purchase.png"></image>
<text class="func-txt">已购买</text>
</view>
<view class="title-func-item" @click="doSell">
<image class="func-img" src="/static/images/icon_sell.png"></image>
<text class="func-txt">我要卖</text>
</view>
<view class="title-func-item" @click="doBetray">
<image class="func-img" src="/static/images/icon_betray.png"></image>
<text class="func-txt">已销售</text>
</view>
</view>
</view>
</view>
<view class="container-box">
<view :class="['header', isSticky ? 'sticky': '']">
<view class="divider-20"></view>
<view class="condition-page-box">
<view class="condition-item">
<view class="condition-item-title">软著分类</view>
<scroll-view :scroll-x="true" class="scroll-view_H">
<view class="list-tabs">
<block v-for="(item,index) in typeList" :key="index">
<view
:class="[includes(selType,item.dataId)? 'tab-select':'tab-normal' ,'item-margin']"
@click="bindChooseType" :data-item="item">
{{item.dataName}}
</view>
</block>
</view>
</scroll-view>
</view>
<view class="condition-item mt-20">
<view class="condition-item-title">价格排序</view>
<scroll-view scroll-x style="flex:1;">
<view class="list-tabs ml-20">
<block v-for="(item,index) in ownerList" :key="index">
<view :class="[selOwner==item.dataId? 'tab-select':'tab-normal' ,'item-margin']"
@click="bindChooseOwner" :data-item="item">
<text>{{item.dataName}}</text>
</view>
</block>
</view>
</scroll-view>
</view>
</view>
</view>
<view class="content-container" style="min-height: 600rpx;">
<view class="loading-box">
<containerLoadingVue :loadingVisible="listLoading">
</containerLoadingVue>
</view>
<view class="content-box">
<block v-for="(item,index) in goodsList" :key="index">
<view class="content-item" @click="doDetail" :data-value="item.goodsId">
<view class="content-item-img-box">
<image :src="item.preImg" class="content-item-img" mode="aspectFill"></image>
</view>
<view class="content-item-txt">{{item.goodsName}}</view>
<view class="content-item-bottom">
<rich-text class="content-item-price"
:nodes="moneyTxt(8,14,item.goodsOpenPrice)"></rich-text>
<view class="content-item-time">{{item.goodsLastTime}}</view>
</view>
<view class="special-tag" v-if="includes(item.goodsFlag,'特价')">特价</view>
</view>
</block>
</view>
<uni-load-more :status="hasMore"></uni-load-more>
</view>
</view>
</view>
</template>
<script>
import containerLoadingVue from '../../../components/container-loading.vue'
import {
sImgPrefix
} from '@/common/js/net/mainUrl.js'
import {
moneyTxt,
includes
} from '@/common/js/conver';
import Shop from '@/common/js/net/shop.js'
import {
inject,
isRef
} from 'vue';
export default {
components: {
containerLoadingVue
},
setup() {
const globalData = inject('globalData')
return {
globalData
}
},
data() {
return {
pageData: {
page: 1,
rows: 10,
keywords: '',
priceRangeStart: '',
priceRangeEnd: '',
priceOrder: '',
goodsGetTime: '',
goodsDevelop: '',
goodsType: '', //软著类型
goodsFlag: '',
},
keywords: '',
priceStart: '',
priceEnd: '',
isLoadMore: false,
hasMore: 'more',
listLoading: 'loading',
listRefreshTrig: false,
goodsList: [],
imgPrefix: sImgPrefix,
localAssets: this.globalData.localAssets,
imgAssets: this.globalData.imgAssetsUrl,
typeList: [],
selType: '',
ownerList: [{
dataName: '从高到低',
dataId: 'DESC'
}, {
dataName: '从低到高',
dataId: 'ASC'
}],
selOwner: '',
isSticky: false,
msgType: 'info',
msgHint: '',
msgShow: false,
needRefresh: false
};
},
onLoad(options) {
uni.setNavigationBarTitle({
title: "商城",
});
uni.setNavigationBarColor({
frontColor: "#000000",
backgroundColor: "#FFFFFF",
animation: {
duration: 500,
timingFunc: "easeIn",
},
});
this.doGetDic()
this.doRefreshList()
},
onShow() {
if (this.needRefresh) {
this.needRefresh = false
this.doRefreshList()
}
},
onReachBottom() {
console.log('触底了')
this.doLoadMore()
},
onPageScroll(e) {
this.isSticky = e.scrollTop > 155
},
onPullDownRefresh() {
this.doRefreshList()
},
methods: {
moneyTxt,
includes,
inputKeywords(e) {
this.setData({
keywords: e.detail.value
})
},
doSearch() {
this.doRefreshList()
},
bindChooseType(e) {
uni.pageScrollTo({
scrollTop: 0
})
setTimeout(() => {
const item = e.currentTarget.dataset.item;
let newSelType = this.selType;
const typeArr = newSelType ? newSelType.split(',') : [];
if (typeArr.includes(item.dataId)) {
const index = typeArr.indexOf(item.dataId);
typeArr.splice(index, 1);
} else {
// 添加
typeArr.push(item.dataId);
}
newSelType = typeArr.join(',');
this.selType = newSelType
this.doRefreshList();
}, 500);
},
bindChooseOwner(e) {
const item = e.currentTarget.dataset.item
this.selOwner = this.selOwner == item.dataId ? '' : item.dataId
this.doRefreshList()
},
doGetDic() {
uni.showLoading({
title: '加载中...'
})
const that = this
Shop.doGetGoodsDic('0b00884a-f7a2-425f-93e5-599fbaad4bde')
.then(res => {
uni.hideLoading()
that.typeList = res
})
.catch(err => {
uni.hideLoading()
})
},
//刷新
doRefreshList() {
this.goodsList = []
this.isLoadMore = false
this.hasMore = 'more'
this.pageData.page = 1
this.pageData.keywords = this.keywords
this.pageData.priceOrder = this.selOwner
this.pageData.priceRangeStart = this.priceStart
this.pageData.priceRangeEnd = this.priceEnd
this.pageData.goodsType = this.selType
this.getIndexList(true)
},
//加载更多
doLoadMore() {
const _self = this
if (_self.isLoadMore || _self.hasMore == 'noMore') {
return
}
//判断是否有更多
this.hasMore = 'loading'
this.isLoadMore = true
this.pageData.page = ++this.pageData.page
_self.getIndexList(false)
},
//获取列表
getIndexList(isRefresh) {
const _self = this
_self.listLoading = isRefresh ? 'loading' : ''
Shop.doGetIndexList(_self.pageData)
.then(res => {
uni.stopPullDownRefresh()
var status = 'success'
status = res.rows && res.rows.length > 0 ? 'success' : 'empty'
const list = _self.addPrefixToPreviewImgs(res.rows)
_self.listLoading = isRefresh ? status : ''
_self.goodsList = _self.goodsList.concat(list)
_self.listRefreshTrig = false
_self.isLoadMore = false
_self.hasMore = _self.goodsList.length < res.total ? 'more' : 'noMore'
})
.catch(err => {
uni.stopPullDownRefresh()
_self.listLoading = 'error'
_self.listRefreshTrig = false
_self.isLoadMore = false
_self.hasMore = 'more'
})
},
//为数据中图片添加前缀
addPrefixToPreviewImgs(data) {
const prefix = this.imgPrefix;
return data.map(item => {
if (item.goodsPhoto && item.goodsPhoto != '') {
item.preImg = prefix + item.goodsPhoto
}
return item;
});
},
//我要买
doBuy() {
uni.navigateTo({
url: '/pages/shop/buyGoods/buyGoods',
})
},
//已购买
doPurchase() {
uni.navigateTo({
url: '/pages/shop/purchasedGoods/purchasedGoods',
})
},
//我要卖
doSell() {
uni.navigateTo({
url: '/pages/shop/sellGoods/sellGoods',
})
},
//已销售
doBetray() {
uni.navigateTo({
url: '/pages/shop/soldGoods/soldGoods',
})
},
//详情
doDetail(e) {
const id = e.currentTarget.dataset.value
uni.navigateTo({
url: '/pages/shop/goodsDetail/goodsDetail?id=' + id,
animation: 'fade'
})
}
},
};
</script>
<style lang="scss" scoped>
.search-container-fixed {
position: fixed;
top: 88rpx;
left: 0;
display: flex;
flex-direction: column;
box-sizing: border-box;
width: 100%;
z-index: 99;
background-color: $white-color;
}
.search-box {
background-color: $bg-gray-color;
display: flex;
flex-direction: row;
align-items: center;
margin: 0rpx 30rpx 0rpx 30rpx;
padding: 15rpx 20rpx;
border-radius: 60rpx;
font-size: 28rpx;
}
.search-input {
flex: 1;
}
.divider-20 {
background-color: $bg-gray-input-color;
min-height: 20rpx;
margin: 0rpx -30rpx;
}
.title-box {
position: relative;
margin-top: 60rpx;
padding: 30rpx 0rpx;
}
.title-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 300rpx;
background-size: cover;
}
.title-container {
position: relative;
}
.title-hint-box {
display: flex;
flex-direction: row;
margin-top: 20rpx;
}
.title-hint-item {
display: flex;
flex-direction: row;
align-items: center;
}
.title-hint-item:nth-of-type(n+2) {
margin-left: 30rpx;
}
.title-hint-txt {
margin-left: 8rpx;
font-size: 24rpx;
color: $text-gray-desc-color;
}
.hook {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
background: linear-gradient(0deg, #FFB540 0%, #FF4800 100%);
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.hook::after {
content: "";
display: block;
width: 8rpx;
height: 15rpx;
border: solid white;
border-width: 0 2rpx 2rpx 0;
transform: rotate(45deg);
position: absolute;
top: 6rpx;
}
.title-func-box {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 30rpx;
}
.title-func-item {
display: flex;
flex-direction: column;
align-items: center;
}
/* .title-func-item:nth-of-type(n+2) {
margin-left: 40rpx;
} */
.func-img {
width: 120rpx;
height: 120rpx;
}
.func-txt {
font-size: 28rpx;
color: $text-color;
margin-top: 15rpx;
}
.container-box {
display: flex;
flex-direction: column;
}
.header {
transition: all 0.3s;
background-color: $white-color;
}
.sticky {
position: fixed;
background-color: $white-color;
box-sizing: border-box;
padding: 20rpx 30rpx 0rpx 30rpx;
top: 160rpx;
left: 0;
right: 0;
z-index: 100;
box-shadow: 0 2rpx 4rpx $bg-gray-input-color;
}
.condition-page-box {
display: flex;
flex-direction: column;
padding: 30rpx 0rpx;
}
.condition-item {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.condition-item-title {
white-space: nowrap;
font-size: 24rpx;
}
.scroll-view_H {
width: 75vw;
padding-left: 20rpx;
white-space: nowrap;
}
.list-tabs {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.tab-select {
white-space: nowrap;
line-height: 17px;
border-radius: 5rpx;
background-color: $btn-primary-color;
color: $text-primary-deep-color;
font-size: 24rpx;
text-align: center;
padding: 5rpx 15rpx;
flex-wrap: nowrap;
}
.tab-normal {
background-color: $bg-gray-input-color;
color: $text-gray-hint-color;
white-space: nowrap;
flex-wrap: nowrap;
line-height: 17px;
border-radius: 5rpx;
font-size: 24rpx;
text-align: center;
padding: 5rpx 15rpx;
}
.item-margin {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.item-margin:nth-of-type(n+2) {
margin-left: 20rpx;
}
.content-container {
display: flex;
flex-direction: column;
position: relative;
margin-bottom: 20rpx;
}
.loading-box {
position: absolute;
top: 50%;
left: 50%;
z-index: 99;
transform: translate(-50%, -50%);
}
.content-box {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.content-item {
width: 48%;
margin-top: 20rpx;
position: relative;
}
.content-item:nth-of-type(even) {
margin-left: 20rpx;
}
.special-tag {
display: inline-block;
padding: 0rpx 20rpx;
background-color: $red-color;
color: $white-color;
font-size: 22rpx;
border-bottom-right-radius: 30rpx;
border-top-right-radius: 30rpx;
position: absolute;
top: 0rpx;
left: 0rpx;
}
.special-tag::before {
content: '';
position: absolute;
left: 0rpx;
bottom: -15rpx;
border-width: 18rpx 18rpx 0 0rpx;
border-style: solid;
border-color: $red-color transparent transparent transparent;
}
.content-item-img-box {
border-radius: 10rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 20rpx;
background-color: $bg-gray-input-color;
}
.content-item-img {
width: 200rpx;
height: 260rpx;
}
.content-item-txt {
font-size: 28rpx;
margin-top: 15rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100%;
}
.content-item-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.content-item-time {
font-size: 24rpx;
color: $text-gray-hint-color;
}
.content-item-price {
color: red;
font-size: 28rpx;
}
</style>