ch-tgr-h5/src/views/Trade/Tradelist.vue
2026-06-01 10:16:15 +08:00

366 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<BasePage :back="back">
<div class="tradelist b_l_w">
<div class="tabs">
<van-tabs class="area" v-model:active="TradeArea" color="#f00" title-active-color="#222"
title-inactive-color="#999" line-width="0" line-height=".667vw" @change="changeMall">
<van-tab v-for="i in mallList" :title="i.label" :name="i.value"></van-tab>
</van-tabs>
<van-tabs class="states" v-model:active="activeTab" color="#ca2904" title-active-color="#ca2904"
title-inactive-color="#000" line-width="4vw" line-height=".667vw" @change="onTabChange">
<van-tab title="全部" name=""></van-tab>
<van-tab v-for="i in tradeStates" :title="i.label" :name="String(i.value)"></van-tab>
</van-tabs>
</div>
<van-search v-model="_searchParams.ordernum" left-icon=" " shape="round" placeholder="输入订单号搜索" @search="onSearch"
@clear="onClear">
<template #right-icon>
<van-icon name="/img/sort-search.png" @click="onSearch"></van-icon>
</template>
</van-search>
<BaseList ref="baseList" url="/v1/client/FOrdersClient" :params="searchParams" :parseData="parseData"
style="padding: 3.33vw;" @refresh="onRefresh" @load="onLoad">
<template #default="{ item }">
<div class="list">
<div class="order_box">
<span :class="'state' + item.mallstate" class="state">{{ item.mallstatename.slice(0, 2) }}</span>
<span>订单编号:{{ item.ordernum }}</span>
<img src="/img/copy_b.png" @click="$copyText(item.ordernum); $showSuccessToast('复制成功')" alt="">
</div>
<div class="goods_box">
<img :src="$file(item.shopimg || item.proimg)" alt="">
<div class="goods_info">
<div class="tit">{{ item.shopname || item.proname }}</div>
<div class="spec" v-if="!item.shopname">
<span>{{ item.proskuname }}</span>
<p>x{{ item.buynums }}</p>
</div>
<div class="concession">
<span v-if="item.mallstate !== 5">¥{{ item.proskusaleprice?.toFixed(2) }}</span>
<span v-else>{{ item.proskusaleprice?.toFixed(2) }}积分</span>
<p v-if="item.discountratio && item.mallstate !== 5">惠利{{ item.discountratio }}%</p>
</div>
</div>
</div>
<div class="price" v-if="item.mallstate !== 5">
实付<span><b>{{ item.realmoney?.toFixed(2) }}</b></span>
</div>
<div class="price" v-else>
实付<span><b>{{ item.ordermoney?.toFixed(2) }}</b></span>
</div>
<div class="state_box">
<b :class="'b' + item.state">{{ item.statename }}</b>
<div class="btn_box">
<button v-if="item.state === 0" @click="cancelTrade(item)">取消订单</button>
<button v-if="!item.shopname" @click="$navigate(`TradeDetail?ordernum=${item.ordernum}`)">查看详情</button>
<button v-else @click="$navigate(`MerchantTradeDetail?id=${item.ordernum}`)">查看详情</button>
<button v-if="item.state === 3 || item.state === 4" @click="showLogistics(item)">物流信息</button>
<button v-if="item.state === 3" @click="confirmReceipt(item)">确认收货</button>
<!-- <button v-if="item.state === 3" @click="refundTrade(item)">退款</button> -->
<button v-if="item.state === 0" @click="$navigate(`Pay?ordernum=${item.ordernum}`)">立即支付</button>
</div>
</div>
</div>
</template>
</BaseList>
<van-popup v-model:show="logisticsVisible" round position="bottom" teleport="body">
<div class="logistics-popup">
<div class="logistics-tit">物流信息</div>
<div class="logistics-content">
<div class="logistics-item">
<span class="label">物流公司</span>
<span class="value">{{ currentLogistics?.exportname }}</span>
</div>
<div class="logistics-item">
<span class="label">物流单号</span>
<span class="value">{{ currentLogistics?.exportnum }}</span>
<img src="/img/copy_b.png" @click="$copyText(currentLogistics?.exportnum); $showSuccessToast('复制成功')"
alt="">
</div>
</div>
<div class="logistics-close">
<van-button type="primary" block round color="#ca2904" @click="logisticsVisible = false">关闭</van-button>
</div>
</div>
</van-popup>
</div>
</BasePage>
</template>
<script>
export default {
name: 'TradeList',
data() {
return {
TradeArea: this.$route.query.TradeArea || 0,
activeTab: this.$route.query.state || '',
_searchParams: {
ordernum: '',
state: '',
},
tradeStates: [
{
"value": 0,
"label": "待付款"
},
{
"value": 1,
"label": "待发货"
},
{
"value": 3,
"label": "待收货"
},
{
"value": 4,
"label": "已完成"
},
{
"value": 6,
"label": "已退款"
}
],
mallList: [
{ value: 0, label: '全部订单' },
{
"value": 1,
"label": "礼包订单"
},
{
"value": 3,
"label": "商城订单"
},
{
"value": 4,
"label": "买单订单"
},
{
"value": 5,
"label": "积分订单"
},
],
_initializing: true,
logisticsVisible: false,
currentLogistics: null,
}
},
computed: {
parseData() {
return res => res.data.items
},
searchParams() {
const params = {
ordernum: this._searchParams.ordernum,
state: this._searchParams.state === '' ? '' : Number(this._searchParams.state),
}
if (this.TradeArea !== 0) {
params.mallstate = this.TradeArea
}
return params
},
},
watch: {
'$route.query.TradeArea': {
handler(val) {
this.TradeArea = val !== undefined ? Number(val) : 0
},
immediate: true
},
'$route.query.state': {
handler(val) {
this.activeTab = val || ''
this._searchParams.state = val || ''
},
immediate: true
}
},
beforeRouteLeave(to, from) {
if (to.name === 'TradeDetail' || to.name === 'MerchantTradeDetail') {
sessionStorage.setItem('TradeList_scroll', window.scrollY || 0)
sessionStorage.setItem('TradeList_fromDetail', '1')
}
this._pauseScroll = true
},
mounted() {
const isReturningFromDetail = sessionStorage.getItem('TradeList_fromDetail') === '1'
sessionStorage.removeItem('TradeList_fromDetail')
this.loadFilterOptions()
if (!isReturningFromDetail) {
sessionStorage.setItem('TradeList_scroll', '0')
}
this._pauseScroll = false
window.addEventListener('scroll', this.saveScroll)
this.$refs.baseList?.refresh()
},
onUnmounted() {
window.removeEventListener('scroll', this.saveScroll)
},
methods: {
saveScroll() {
if (this._pauseScroll) return
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
sessionStorage.setItem('TradeList_scroll', scrollTop)
},
onLoad() {
const scrollTop = sessionStorage.getItem('TradeList_scroll')
if (scrollTop && scrollTop !== '0' && !this._scrollRestored) {
this._scrollRestored = true
window.removeEventListener('scroll', this.saveScroll)
this.$nextTick(() => {
window.scrollTo(0, Number(scrollTop))
})
setTimeout(() => {
window.addEventListener('scroll', this.saveScroll)
}, 100)
}
},
// 加载订单状态和类型列表
async loadFilterOptions() {
try {
const [stateRes, areaRes] = await Promise.all([
this.$get('/v1/client/FOrdersClient/orderstate'),
this.$get('/v1/client/EProsClient/mallstate'),
])
this.tradeStates = stateRes.data || []
this.mallList = [{ value: 0, label: '全部订单' }, ...(areaRes.data || [])]
this._initializing = false
} catch (err) {
this.$showFailToast(err.message || '加载失败')
}
},
// Tab 切换 - 订单状态
onTabChange(name) {
this._searchParams.state = name
// this.$refs.baseList?.refresh()
},
// Tab 切换 - 订单类型
changeMall(val) {
this.TradeArea = val
this._searchParams.state = ''
this.activeTab = ''
// 不需要手动 refreshBaseList 的 watch params 会自动触发
},
// 搜索 & 清除
onSearch() {
this.$refs.baseList?.refresh()
},
onClear() {
this._searchParams.ordernum = ''
this.$refs.baseList?.refresh()
},
// 确认收货
confirmReceipt(item) {
this.$showConfirmDialog({ title: '是否确认收货' })
.then(() => this.$put(`/v1/client/FOrdersClient/${item.ordernum}/receipt`))
.then(() => {
this.$showSuccessToast('确认收货成功')
this.$refs.baseList?.refresh()
})
.catch()
},
// 取消订单
cancelTrade(item) {
this.$showConfirmDialog({ title: '是否确认取消订单' })
.then(() => this.$put(`/v1/client/FOrdersClient/${item.ordernum}/cancel`))
.then(() => {
this.$showSuccessToast('取消订单成功')
this.$refs.baseList?.refresh()
})
.catch()
},
// 退款
// refundTrade(item) {
// this.$showConfirmDialog({ title: '是否申请退款' })
// .then(() => this.$get(`/v1/client/FOrdersClient/${item.ordernum}/refund`))
// .then(() => {
// this.$showSuccessToast('退款申请成功')
// this.$refs.baseList?.refresh()
// })
// .catch()
// },
// 显示物流信息
showLogistics(item) {
this.currentLogistics = item
this.logisticsVisible = true
},
back() {
this.$navigate('/My');
},
onRefresh() { },
},
}
</script>
<style lang="less" scoped>
.logistics-popup {
padding: 20px;
.logistics-tit {
font-size: 16px;
font-weight: bold;
text-align: center;
margin-bottom: 20px;
}
.logistics-content {
background: #f5f5f5;
border-radius: 8px;
padding: 15px;
margin-bottom: 20px;
}
.logistics-item {
display: flex;
align-items: center;
margin-bottom: 12px;
&:last-child {
margin-bottom: 0;
}
.label {
width: 70px;
color: #999;
}
.value {
flex: 1;
color: #333;
}
img {
width: 16px;
height: 16px;
margin-left: 8px;
}
}
.logistics-close {
margin-top: 10px;
}
}
</style>