This commit is contained in:
2026-10-08 18:34:09 +08:00
commit 2933904f4c
905 changed files with 112129 additions and 0 deletions
+784
View File
@@ -0,0 +1,784 @@
<template> <!-- 订单列表 -->
<view class="wrap">
<u-sticky offset-top="0" customNavHeight="0">
<uititle title="订单管理"></uititle>
</u-sticky>
<u-subsection :list="subsectionList" :current="subsectionActive" activeColor="#A92924"
@change="sectionChange" fontSize="16"></u-subsection>
<view class="tab-box">
<view class="item" :class="{active: activeName === 'all'}" @click="handTab('all')">全部</view>
<view class="item" :class="{active: activeName === 0}" @click="handTab(0)">待付款</view>
<view class="item" :class="{active: activeName === 1}" @click="handTab(1)">待发货</view>
<view class="item" :class="{active: activeName === 2}" @click="handTab(2)">待收货</view>
<view class="item" :class="{active: activeName === 5}" @click="handTab(5)">待退款</view>
<view class="item" :class="{active: activeName === 4}" @click="handTab(4)">已完成</view>
<view class="item" :class="{active: activeName === 6}" @click="handTab(6)">退款成功</view>
<view class="item" :class="{active: activeName === 7}" @click="handTab(7)">退款失败</view>
</view>
<view class="p-20 flex justify-start items-center">
<view class="mr-15">
<u-icon name="arrow-down" label-pos="left" :label="typeStr" @click="showTypeFilter = true"/>
</view>
<u-search v-model="keyword" placeholder="请输入订单号" @blur="query(1)" @custom="query(1)"
@clear="query(1)"/>
</view>
<view class="list-box">
<!-- 1 -->
<view class="item bg-white" v-for="(item, index) in tableData.rows" :key="index">
<view class="state">
<view class="no">{{ item.orderNo }}</view>
<view class="bage" v-if="item.signMethod !== 1">{{
orderStatusList[item.orderStatus]
}}
</view>
</view>
<view class="mt-15 text-25 text-gray flex justify-start items-center">
<text>{{ orderTypeList[item.type] }}</text>
<text class="text-25 text-gray" v-if="item.type === 1">({{
item.subType === 0 ? '企业' : '产品'
}})
</text>
</view>
<text class=" text-25 text-main" v-if="item.type === 3">(过期时间:{{
item.upgradeExpiredAt
}})
</text>
<text class=" text-25 text-main" v-if="item.type === 8 && item.spot && item.spot.topExpiredAt">过期时间:{{
dayjs(item.spot.topExpiredAt).format('YYYY-MM-DD HH:mm:ss')
}}({{
item.goods[0].goodsId === '-1' ? '全国' : provincesData.find(province => parseInt(province.code) === parseInt(item.goods[0].goodsId)).name
}})
</text>
<view class="mt-15 text-25 text-gray">{{ item._add_time_str }}</view>
<text class="mt-15 text-25 text-main" v-if="item.type > 3 && item.payList">
最新支付状态:{{ item.buyerStatusStr }}
</text>
<text class="mt-15 text-25 text-main" v-if="item.type < 4 && item.orderStatus === 7">
退款拒绝原因:{{ item.refundRefuseReason }}
</text>
<template v-if="item.type === 0">
<view class="p-20 mb-20 flex justify-start items-start" v-for="(goods, goodsIndex) in item.goods"
:key="goodsIndex">
<u-image :src="getGoodsImage(goods)" width="150rpx" height="150rpx" v-if="getGoodsImage(goods)"/>
<view class="flex flex-col justify-start items-start ml-20 text-25">
<text class="font-bold mb-15 text-28">{{ goods.goodsName }}</text>
<text class="text-gray" v-if="item.type === 0 && goods.sku">{{ goods.sku.label }}</text>
<text class=" font-bold text-main" v-if="item.type === 0 && goods.sku">¥{{
goods.sku.values
}}
</text>
<text class=" font-bold flex-1" v-else>¥{{ goods.goodsPrice }}</text>
<text class="">x{{ goods.num }}</text>
</view>
<text class="text-35 font-bold flex-1 text-main" v-if="item.type === 0 && goods.sku">¥{{
parseFloat(goods.sku.values) * goods.num
}}
</text>
<text class="text-35 font-bold flex-1 text-main" v-else>¥{{
parseFloat(goods.goodsPrice) * goods.num
}}
</text>
</view>
</template>
<view class="tool" v-if="item.type < 4 || (item.type > 6 && item.type !== 14)">
<view class="price">
<text class="mr-10" v-if="item.orderStatus !== 10">总金额:</text>
<text v-else class="red mr-10">待报价:</text>
<template v-if="item.orderStatus !== 10">
<text
:class="[parseFloat(item.offAmount) !== parseFloat(item.amount) ? 'text-line-through text-gray': 'red']">
¥{{ item.amount ? parseFloat(item.amount).toFixed(2) : '' }}
</text>
<text class="red"
v-if="parseFloat(item.offAmount) !== parseFloat(item.amount)">
¥{{ item.offAmount }}
</text>
</template>
</view>
<view class="status">
<view class="icon">
<img v-if="item.orderStatus === 0" src="/static/images/order/toBePaid.png"
alt=""/>
</view>
</view>
</view>
<view class="operate">
<template v-if="(item.type > 3 && item.type < 7) || [14, 15].includes(item.type)">
<view class="mx-15">
<u-button plain size="mini" class="btn-buy pointer" @click="showOtherUser(item)">
联系交易方
</u-button>
</view>
<template v-if="item.type > 3 && item.orderStatus < 3 && item.isSeller">
<template
v-if="!item.payList || !['尾款', '货到付款'].includes(item.payList.type) || (['尾款', '货到付款'].includes(item.payList.type) && item.payList.buyerRefuse)">
<view class="mx-15">
<u-button type="primary" size="mini" class="pointer"
@click="makePayList(item)">
创建支付单
</u-button>
</view>
</template>
</template>
<template v-if="item.type > 3 && item.payStatus > 0">
<view class="mx-15">
<u-button type="warning" size="mini" class="pointer"
@click="showPayList(item)">
查看支付单
</u-button>
</view>
</template>
<template v-if="item.contractId">
<view class="mx-15">
<u-button plain size="mini" class="btn-buy pointer"
@click="viewContract(item.contractId)">
查看合同
</u-button>
</view>
</template>
</template>
<template v-if="[0, 1, 2, 3, 7, 8, 9].includes(item.type)">
<view class="mx-15">
<u-button plain size="mini" type="primary"
v-if="[0, 1].includes(item.type)"
@click="showGoods(item)">商品列表
</u-button>
</view>
<template v-if="item.orderStatus === 0">
<view class="mx-15">
<u-button plain size="mini" type="primary" class="btn-close pointer"
@click="navTo(`/pages/shop/pay?id=${item._id}`)"
>去支付
</u-button>
</view>
<view class="mx-15">
<u-button plain size="mini" class="pointer" type="info"
@click="cancel(item)"
>取消订单
</u-button>
</view>
<template v-if="item.orderStatus === 4">
<view class="mx-15">
<u-button plain size="mini"
@click="showServicePhone()">客服电话
</u-button>
</view>
<view class="mx-15">
<u-button plain size="mini"
@click="showServiceQR()">客服二维码
</u-button>
</view>
</template>
</template>
<template v-if="item.orderStatus >= 2 && item.type === 0">
<view class="mx-15">
<u-button plain size="mini" class="btn-buy pointer"
@click="showExpressInfo(item)">
物流信息
</u-button>
</view>
<template v-if="item.isBuyer && item.orderStatus === 2">
<view class="mx-15">
<u-button size="mini" type="success"
@click="confirmExpress(item._id)">
确认收货
</u-button>
</view>
</template>
</template>
<view class="mx-15">
<u-button size="mini" type="success" v-if="item.orderStatus === 11 && item.isSeller"
@click.native="changeOrderStatus(item._id, 3)">已完成
</u-button>
</view>
<view class="mx-15">
<u-button size="mini" type="success" v-if="item.orderStatus === 3 && item.isBuyer"
@click.native="changeOrderStatus(item._id, 4)">确认完成
</u-button>
</view>
</template>
<view v-if="item.orderStatus === 1 && item.isSeller && item.type === 0">
<u-button plain size="mini" type="primary" @click="setExpress(item)">发货</u-button>
</view>
<view class="mx-15"
v-if="([1, 2, 4, 7, 8, 9].includes(item.orderStatus)
&& ((item.type > 3 && item.hasPay && item.isBuyer)
|| (item.type < 3 && [1, 2, 3, 4, 7, 8, 9].includes(item.orderStatus) && item.isBuyer)
))">
<u-button plain size="mini" class="btn-close pointer"
@click="showRefund(item)">申请退款
</u-button>
</view>
</view>
</view>
</view>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="100%">
<make-pay v-if="dialogVisible && clickedInfo && dialogType === 'create'" :info="clickedInfo"
@close="dialogVisible = false;query(1)" :pay-type-list="payTypeList"/>
<pay-list v-else-if="dialogVisible && dialogType === 'pay-list'" :pay-list="payList"
@refresh="payRefresh" @close="dialogVisible = false"/>
<goods v-if="dialogVisible && dialogType === 'goods-list'" :goods="clickedInfo.goods" :order="clickedInfo"
:selfProduct="clickedInfo.selfProduct"/>
<set-express v-if="dialogVisible && dialogType === 'set-express'" :id="clickedInfo._id" :info="clickedInfo"
@close="dialogVisible = false;query(1)"/>
<set-refund v-if="dialogVisible && dialogType === 'set-refund'" :id="clickedInfo._id"
@close="dialogVisible = false;query(1)"/>
<express-info v-if="dialogVisible && dialogType === 'express-info'" :info="clickedInfo"
@close="dialogVisible = false;"/>
</el-dialog>
<contact-modal ref="contactModal"/>
<u-picker :show="showTypeFilter" :columns="[subsectionActive === 0 ? sellerTypeFilter : otherTypeFilter]" keyName="label"
@cancel="showTypeFilter = false" @close="showTypeFilter = false" closeOnClickOverlay
@confirm="confirmType">
<template #more>
<text @click="reset">重置</text>
</template>
</u-picker>
</view>
</template>
<script>
import uititle from "@/components/common/title.vue";
import MakePay from "@/pages/shop/components/makePay.vue";
import PayList from "@/pages/shop/components/payList.vue";
import Goods from "./components/goods.vue";
import SetExpress from "@/pages/shop/components/setExpress.vue";
import SetRefund from "@/pages/shop/components/setRefund.vue";
import ExpressInfo from "@/pages/shop/components/expressInfo.vue";
import dayjs from "dayjs";
import provinces from '@/util/address/provinces.json'
import citys from '@/util/address/citys.json'
import areas from '@/util/address/areas.json'
import ContactModal from "@/components/ContactModal.vue";
const CREATE_PAY_LIST_CONFIRM_CONTENT = `1、您已充分知悉、了解并认可本订单及合同的全部内容以及各方的权利义务;
2、请您按照订单或合同约定创建支付单,否则将存在被驳回的风险。若申请被驳回,请及时沟通处理,完成整改后再次提交。`
export default {
components: {ContactModal, ExpressInfo, SetRefund, SetExpress, Goods, PayList, MakePay, uititle},
data() {
return {
provincesData: provinces,
isLoadMore: false, //默认关闭,请求列表数据超过一屏之后开启
subsectionList: ['我卖出的', '我购买的', '线下交易'],
subsectionActive: 0,
dialogVisible: false,
dialogType: '',
dialogTitle: '',
clickedInfo: null,
activeName: 'all',
value: '',
options: [{
value: '自主交易',
label: '自主交易'
}],
pageIndex: 1,
menuIndex: '0',
formData: {
status: null,
tradeMethod: null
},
tableData: {
total: 0,
rows: []
},
pageSize: 500,
orderType: null,
orderTypeList: [
'商城订单',
'金久信自营增值服务',
'保证金',
'会员升级',
'询价订单',
'加工订单',
'旧货订单',
'报价次数',
'现货广告',
'旧货加急',
'旧货次数',
'金久信学堂下载次数',
'合同下载',
'金久信签约宝次数',
'金久信签约宝',
'金久信自营询价',
],
orderStatusList: [
'待支付',
'待发货',
'待收货',
'待确认',
'已完成',
'退款审核中',
'退款成功',
'退款拒绝',
'',
'',
'待报价',
'已派单待完成',
],
payList: [],
keyword: '',
orderPayList: [],
payInfo: {},
payTypeList: ['预付款', '进度款', '尾款', '货到付款', '全款'],
topExpiredAt: '',
typeStr: '全部类型',
showTypeFilter: false,
sellerTypeFilter: [
{
label: '商城订单',
value: 0
},
{
label: '询价订单',
value: 4
},
{
label: '加工订单',
value: 5
},
{
label: '旧货交易订单',
value: 6
},
],
otherTypeFilter: [
{
label: '商城订单',
value: 0
},
{
label: '询价订单',
value: 4
},
{
label: '加工订单',
value: 5
},
{
label: '旧货交易订单',
value: 6
},
],
};
},
methods: {
dayjs,
getGoodsImage(goods) {
if (!goods) return ''
if (goods.sku && goods.sku.image) return goods.sku.image
if (goods.goods && goods.goods.cover) return goods.goods.cover
return ''
},
sectionChange(index) {
this.subsectionActive = index
this.query()
},
handTab(index) {
this.activeName = index
this.query()
},
async query(pageIndex = 1, resetFilter = false, activeName = null) {
if (resetFilter) {
this.keyword = null
this.orderType = null
}
if (activeName) this.activeName = activeName
this.tableData = await vk.callFunction({
url: 'client/order/kh/getList',
title: '请求中...',
data: {
pageIndex,
pageSize: this.pageSize,
keyword: this.keyword,
isSeller: this.subsectionActive === 0 ? 1 : 0,
type: this.orderType,
signMethod: this.subsectionActive === 2 ? 1 : null,
orderStatus: this.activeName === 'all ' ? null : parseInt(this.activeName),
},
});
this.tableData.rows.map(item => {
item.buyerStatusStr = ''
if (item.type > 3 && item.payList) {
item.buyerStatusStr = `${item.payList.type}-`
if (item.payList.buyerRefuse) {
item.buyerStatusStr += `买家已拒绝:${item.payList.refuseReason}。`
if (item.isSeller) item.buyerStatusStr += '请等待卖家重新创建支付单'
else item.buyerStatusStr += '请重新创建支付单'
} else {
if (item.payList.hasPaid) {
if (item.payList.sellerConfirm) item.buyerStatusStr += '卖家已确认收款'
else item.buyerStatusStr += '买家已支付,待卖家确认收款'
} else item.buyerStatusStr += '买家未支付'
}
}
return item
})
},
reset() {
this.orderType = null
this.typeStr = '全部类型'
this.keyword = null
this.showTypeFilter = false
this.query(1)
},
contact(item) {
try {
const mobile = item.isBuyer ? item.seller.mobile : item.buyer.mobile
uni.showModal({
title: '',
content: `交易方联系方式:${mobile}`,
showCancel: false
})
} catch (e) {
uni.showModal({
title: '',
content: `交易方未留下联系方式`,
showCancel: false
})
}
},
async makePayList(item) {
const confirmed = await new Promise(resolve => {
uni.showModal({
title: '创建支付单', content: CREATE_PAY_LIST_CONFIRM_CONTENT,
confirmText: '我已知晓', cancelText: '取消', showCancel: true,
success: res => resolve(res.confirm), fail: () => resolve(false)
})
})
if (!confirmed) return
const {rows} = await vk.callFunction({
url: 'client/order/kh/orderPayList',
title: '请求中...',
data: {
id: item._id
},
});
if (rows.length > 0 && !rows[rows.length - 1].buyerRefuse && !rows[rows.length - 1].sellerConfirm) {
return this.$message.error('还有未确认的支付单,无法继续创建。请到支付单中查看并确认收款')
}
this.orderPayList = rows
this.clickedInfo = item
this.dialogType = 'create'
this.dialogTitle = '创建支付单'
this.dialogVisible = true
},
async showPayList(item) {
this.clickedInfo = item
await this.getPayList()
this.dialogVisible = true
this.dialogTitle = '查看支付单'
this.dialogType = 'pay-list'
},
async getPayList() {
const {rows} = await vk.callFunction({
url: 'client/order/kh/orderPayList',
title: '请求中...',
data: {id: this.clickedInfo._id}
})
this.payList = rows
},
viewContract(contractId) {
vk.callFunction({
url: 'client/contract/kh/viewContract',
title: '请求中...',
data: {
contractId
},
success: (res) => {
// window.open(res.data)
window.location.href = res.data
}
});
},
navTo(url) {
vk.navigateTo({
url: url
})
},
async buyerRefuse(index) {
this.payList[index].buyerRefuse = true
await vk.callFunction({
url: 'client/order/kh/payRefuse',
title: '请求中...',
data: {
id: this.payList[index]._id
}
})
},
showGoods(item) {
this.clickedInfo = item;
this.dialogTitle = '商品列表'
this.dialogType = 'goods-list';
this.dialogVisible = true
},
showRefund(item) {
this.clickedInfo = item;
this.dialogTitle = '退款申请'
this.dialogType = 'set-refund';
this.dialogVisible = true
},
setExpress(item) {
this.clickedInfo = item;
this.dialogTitle = '发货'
this.dialogType = 'set-express';
this.dialogVisible = true
},
showExpressInfo(item) {
this.clickedInfo = item;
this.dialogTitle = '发货详情'
this.dialogType = 'express-info';
this.dialogVisible = true
},
confirmExpress(id) {
uni.showModal({
title: '提示',
content: '只确认数量和金额,质保按双方合同约定内容执行',
success: async res => {
if (res.confirm) {
await vk.callFunction({
url: 'client/order/kh/changeOrderStatus',
title: '请求中...',
data: {
id,
orderStatus: 4
}
})
this.activeName = '4'
await this.query(1)
}
}
})
},
payRefresh(menuIndex) {
this.getPayList()
this.query(1, null, menuIndex)
},
async cancel({_id}) {
uni.showModal({
title: '提示',
content: '确认取消订单吗?',
success: async res => {
if (res.confirm) {
await vk.callFunction({
url: 'client/order/kh/changeOrderStatus',
title: '请求中...',
data: {
id: _id,
orderStatus: -1
}
})
await this.query(1)
}
}
})
},
async showServicePhone() {
const res = await vk.callFunction({
url: 'client/dict/pub/getDetail',
data: {
id: '657d8fca55b337cfadbe1063'
}
})
uni.showModal({
title: '平台客服',
content: res.content,
showCancel: false
})
},
async showServiceQR() {
const res = await vk.callFunction({
url: 'client/dict/pub/getDetail',
data: {
id: '657d9025e0ec19b5040feb40'
}
})
const h = this.$createElement;
this.$confirm(`<image src="${res.content}" style="width: 100px;height: 100px;"/>`, '平台客服二维码', {
cancelButtonText: '关闭',
showConfirmButton: false,
dangerouslyUseHTMLString: true
})
},
async changeOrderStatus(id, orderStatus) {
await vk.callFunction({
url: 'client/order/kh/changeOrderStatus',
data: {
id,
orderStatus
}
})
await this.query(1)
},
showOtherUser(item) {
const mine = item.isBuyer ? item.buyer : item.seller
const otherUser = item.isBuyer ? item.seller : item.buyer
const mineName = mine.accountType === 2 ? mine.company.companyName : mine.person.personName
const otherName = otherUser.accountType === 2 ? otherUser.company.companyName : otherUser.person.personName
this.$refs.contactModal.open(otherUser.businessCard.companyMobile, mine.businessCard.companyMobile, otherName, mineName)
},
confirmType({value}) {
this.orderType = value[0].value
this.typeStr = value[0].label
this.query(1)
this.showTypeFilter = false
}
},
onLoad(option) {
if (option.menuIndex) this.subsectionActive = parseInt(option.menuIndex)
if (option.keyword) this.keyword = option.keyword
this.query()
},
/*上拉加载更多*/
onReachBottom() {
// uni.showToast({title: '加载更多……', icon: 'none'})
// /*防止重复请求*/
// if (!this.isLoadMore) {
// this.isLoadMore = true
// }
}
}
</script>
<style lang="scss">
/deep/ .u-button--mini {
padding: 0 1px !important;
}
.tab-box {
display: flex;
justify-content: space-between;
margin: 0 30rpx;
border-bottom: 1px solid #e5e5e5;
font-size: 26rpx;
line-height: 88rpx;
color: #2d2d2d;
overflow-x: scroll;
.active {
position: relative;
color: #A92924;
}
.active::after {
position: absolute;
left: 50%;
bottom: -3px;
z-index: 9;
margin-left: -34rpx;
display: block;
content: '';
width: 68rpx;
height: 4px;
border-radius: 2px;
background-color: #A92924;
}
.item {
flex-shrink: 0;
margin-right: 20rpx;
}
}
.list-box {
padding: 10rpx 30rpx;
.item {
margin-top: 30rpx;
padding: 16rpx 30rpx 10rpx;
// border: 1px solid #e3e3e3;
border-radius: 20rpx;
box-shadow: 0 0 3px 3px #e3e3e3;
.info-box {
display: flex;
padding: 16rpx 0;
.img {
width: 180rpx;
height: 106rpx;
border-radius: 10rpx;
overflow: hidden;
}
.info {
flex: 1;
flex-wrap: wrap;
padding-left: 20rpx;
.title {
width: 100%;
height: 36rpx;
font-size: 28rpx;
line-height: 36rpx;
color: #2a2a2a;
overflow: hidden;
}
.type {
font-size: 24rpx;
line-height: 32rpx;
color: #A92924;
}
.code {
font-size: 24rpx;
line-height: 32rpx;
color: #d7d7d7;
}
}
}
.state {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 28rpx;
line-height: 30rpx;
font-weight: bold;
.no {
color: #222222;
}
.bage {
font-size: 25rpx;
color: #ff9600;
}
}
.operate {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 20rpx 0;
font-size: 24rpx;
line-height: 48rpx;
color: #2a2a2a;
.link {
margin-left: 20rpx;
// width: 156rpx;
height: 48rpx;
padding: 0 12rpx;
text-align: center;
border-radius: 12rpx;
}
.link-1 {
color: #FFFFFF;
border: 1px solid #A92924;
background-color: #A92924;
}
.link-2 {
color: #999999;
border: 1px solid #999999;
background-color: #FFFFFF;
}
}
}
}
</style>