fix(order): 区分订单操作按钮颜色、待支付不显示退款标签、列表移除售后/投诉入口、修复详情页商品列表被全局样式压缩

This commit is contained in:
pikachu1995@126.com
2026-10-26 17:01:44 +08:00
parent b72c792ade
commit 55a431ddd5
2 changed files with 359 additions and 379 deletions

View File

@@ -40,7 +40,11 @@
<div class="order-sn" v-else> <div class="order-sn" v-else>
{{ order.createTime }}<span>订单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span> {{ order.createTime }}<span>订单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span>
</div> </div>
<div class="order-status">{{ order.isAfterSale ? filterAfterSaleStatus(order.serviceStatus) : filterOrderStatus(order.orderStatus) }}</div> <div class="order-status">
<el-tag size="small" :type="statusTagType(order.isAfterSale ? order.serviceStatus : order.orderStatus)">
{{ order.isAfterSale ? filterAfterSaleStatus(order.serviceStatus) : filterOrderStatus(order.orderStatus) }}
</el-tag>
</div>
</div> </div>
<div class="order-body"> <div class="order-body">
<div class="col-detail"> <div class="col-detail">
@@ -64,12 +68,10 @@
<div class="goods-name hover-color" @click="goodsDetail(goods.skuId, goods.goodsId)">{{ goods.name }}</div> <div class="goods-name hover-color" @click="goodsDetail(goods.skuId, goods.goodsId)">{{ goods.name }}</div>
<div class="goods-num">共{{ goods.num }}件</div> <div class="goods-num">共{{ goods.num }}件</div>
<div class="goods-extra"> <div class="goods-extra">
<span v-if="refundPriceList(goods.isRefund)" class="refund-tag">{{ refundPriceList(goods.isRefund) }}</span> <el-tag v-if="refundPriceList(goods.isRefund) && !isUnpaid(order)" type="warning" size="small">{{ refundPriceList(goods.isRefund) }}</el-tag>
<button v-if="goods.complainStatus == 'NO_APPLY'" type="button" class="sub-btn" @click="complain(order.sn, goodsIndex)">投诉</button>
</div> </div>
</div> </div>
</div> </div>
<button v-if="canAfterSale(order)" type="button" class="sub-btn" @click="applyAfterSale(order.orderItems)">申请售后</button>
</div> </div>
<div class="col-amount"> <div class="col-amount">
<div class="order-amount">{{ $filters.unitPrice(order.flowPrice, "¥") }}</div> <div class="order-amount">{{ $filters.unitPrice(order.flowPrice, "¥") }}</div>
@@ -77,14 +79,14 @@
</div> </div>
<div class="col-ops"> <div class="col-ops">
<template v-if="order.isAfterSale"> <template v-if="order.isAfterSale">
<button type="button" class="text-link" @click="goAfterSaleDetail(order.serviceSn)">售后详情</button> <el-button link type="primary" @click="goAfterSaleDetail(order.serviceSn)">售后详情</el-button>
</template> </template>
<template v-else> <template v-else>
<button v-if="order.allowOperationVO && order.allowOperationVO.pay" type="button" class="op-btn" @click="goPay(order.sn)">去支付</button> <el-button v-if="order.allowOperationVO && order.allowOperationVO.pay" type="primary" size="small" @click="goPay(order.sn)">去支付</el-button>
<button v-if="order.allowOperationVO && order.allowOperationVO.rog" type="button" class="op-btn" @click="received(order.sn)">确认收货</button> <el-button v-if="order.allowOperationVO && order.allowOperationVO.rog" type="primary" size="small" @click="received(order.sn)">确认收货</el-button>
<button type="button" class="text-link" @click="orderDetail(order.sn)">订单详情</button> <el-button link type="primary" @click="orderDetail(order.sn)">订单详情</el-button>
<button v-if="order.allowOperationVO && order.allowOperationVO.cancel" type="button" class="text-link" @click="handleCancelOrder(order.sn)">取消订单</button> <el-button v-if="order.allowOperationVO && order.allowOperationVO.cancel" link type="info" @click="handleCancelOrder(order.sn)">取消订单</el-button>
<button v-if="order.orderStatus === 'COMPLETED'" type="button" class="text-link" @click="delOrder(order.sn)">删除订单</button> <el-button v-if="order.orderStatus === 'COMPLETED'" link type="info" @click="delOrder(order.sn)">删除订单</el-button>
</template> </template>
</div> </div>
</div> </div>
@@ -120,7 +122,11 @@
<div class="order-sn" v-else> <div class="order-sn" v-else>
{{ order.createTime }}<span>订单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span> {{ order.createTime }}<span>订单号 {{ order.sn }}</span><span class="order-store" @click="shopPage(order.storeId)">{{ order.storeName }}</span>
</div> </div>
<div class="order-status">{{ order.isAfterSale ? filterAfterSaleStatus(order.serviceStatus) : filterOrderStatus(order.orderStatus) }}</div> <div class="order-status">
<el-tag size="small" :type="statusTagType(order.isAfterSale ? order.serviceStatus : order.orderStatus)">
{{ order.isAfterSale ? filterAfterSaleStatus(order.serviceStatus) : filterOrderStatus(order.orderStatus) }}
</el-tag>
</div>
</div> </div>
<div class="order-body"> <div class="order-body">
<div class="col-detail"> <div class="col-detail">
@@ -144,12 +150,10 @@
<div class="goods-name hover-color" @click="goodsDetail(goods.skuId, goods.goodsId)">{{ goods.name }}</div> <div class="goods-name hover-color" @click="goodsDetail(goods.skuId, goods.goodsId)">{{ goods.name }}</div>
<div class="goods-num">共{{ goods.num }}件</div> <div class="goods-num">共{{ goods.num }}件</div>
<div class="goods-extra"> <div class="goods-extra">
<span v-if="refundPriceList(goods.isRefund)" class="refund-tag">{{ refundPriceList(goods.isRefund) }}</span> <el-tag v-if="refundPriceList(goods.isRefund) && !isUnpaid(order)" type="warning" size="small">{{ refundPriceList(goods.isRefund) }}</el-tag>
<button v-if="goods.complainStatus == 'NO_APPLY'" type="button" class="sub-btn" @click="complain(order.sn, goodsIndex)">投诉</button>
</div> </div>
</div> </div>
</div> </div>
<button v-if="canAfterSale(order)" type="button" class="sub-btn" @click="applyAfterSale(order.orderItems)">申请售后</button>
</div> </div>
<div class="col-amount"> <div class="col-amount">
<div class="order-amount">{{ $filters.unitPrice(order.flowPrice, "¥") }}</div> <div class="order-amount">{{ $filters.unitPrice(order.flowPrice, "¥") }}</div>
@@ -157,30 +161,20 @@
</div> </div>
<div class="col-ops"> <div class="col-ops">
<template v-if="order.isAfterSale"> <template v-if="order.isAfterSale">
<button type="button" class="text-link" @click="goAfterSaleDetail(order.serviceSn)">售后详情</button> <el-button link type="primary" @click="goAfterSaleDetail(order.serviceSn)">售后详情</el-button>
</template> </template>
<template v-else> <template v-else>
<button v-if="order.allowOperationVO && order.allowOperationVO.pay" type="button" class="op-btn" @click="goPay(order.sn)">去支付</button> <el-button v-if="order.allowOperationVO && order.allowOperationVO.pay" type="primary" size="small" @click="goPay(order.sn)">去支付</el-button>
<button v-if="order.allowOperationVO && order.allowOperationVO.rog" type="button" class="op-btn" @click="received(order.sn)">确认收货</button> <el-button v-if="order.allowOperationVO && order.allowOperationVO.rog" type="primary" size="small" @click="received(order.sn)">确认收货</el-button>
<button type="button" class="text-link" @click="orderDetail(order.sn)">订单详情</button> <el-button link type="primary" @click="orderDetail(order.sn)">订单详情</el-button>
<button v-if="order.allowOperationVO && order.allowOperationVO.cancel" type="button" class="text-link" @click="handleCancelOrder(order.sn)">取消订单</button> <el-button v-if="order.allowOperationVO && order.allowOperationVO.cancel" link type="info" @click="handleCancelOrder(order.sn)">取消订单</el-button>
<button v-if="order.orderStatus === 'COMPLETED'" type="button" class="text-link" @click="delOrder(order.sn)">删除订单</button> <el-button v-if="order.orderStatus === 'COMPLETED'" link type="info" @click="delOrder(order.sn)">删除订单</el-button>
</template> </template>
</div> </div>
</div> </div>
</div> </div>
<el-skeleton size="large" fix v-if="spinShow"></el-skeleton> <el-skeleton size="large" fix v-if="spinShow"></el-skeleton>
</div> </div>
<!-- 选择售后商品 -->
<el-dialog v-model="afterSaleModal" title="请选择申请售后的商品">
<div>
<el-table :data="afterSaleArr" border @row-click="afterSaleSelect">
<el-table-column prop="name" label="商品名称" />
<el-table-column prop="goodsPrice" label="价格" />
</el-table>
</div>
<template #footer><div></div></template>
</el-dialog>
<el-dialog v-model="cancelAvail" title="请选择取消订单原因"> <el-dialog v-model="cancelAvail" title="请选择取消订单原因">
<el-radio-group v-model="cancelParams.reason"> <el-radio-group v-model="cancelParams.reason">
<el-radio :label="item.reason" v-for="item in cancelReason" :key="item.id"> <el-radio :label="item.reason" v-for="item in cancelReason" :key="item.id">
@@ -233,8 +227,6 @@ const changeWay = ref(['全部', '待付款', '待发货', '待收货/使用']);
const activeOrderTab = ref(0); const activeOrderTab = ref(0);
const total = ref(0); // 数据总数 const total = ref(0); // 数据总数
const spinShow = ref(false); // 加载状态 const spinShow = ref(false); // 加载状态
const afterSaleModal = ref(false); // 选择售后商品模态框
const afterSaleArr = ref([]); // 售后商品列表
const cancelAvail = ref(false); // 取消订单modal控制 const cancelAvail = ref(false); // 取消订单modal控制
const cancelReason = ref([]); // 取消订单原因 const cancelReason = ref([]); // 取消订单原因
@@ -312,27 +304,6 @@ function received (sn) { // 确认收货
function goPay (sn) { // 去支付 function goPay (sn) { // 去支付
router.push({path: '/payment', query: {orderType: 'ORDER', sn}}); router.push({path: '/payment', query: {orderType: 'ORDER', sn}});
} }
function applyAfterSale (goodsItem) { // 申请售后
let arr = []
goodsItem.forEach(e => {
if (e.afterSaleStatus === 'NOT_APPLIED'|| e.afterSaleStatus === 'PART_AFTER_SALE') {
arr.push(e)
}
});
if (arr.length === 1) {
router.push({name: 'ApplyAfterSale', query: {sn: arr[0].sn}})
} else {
afterSaleArr.value = arr;
afterSaleModal.value = true
}
}
// 申请售后
function afterSaleSelect (item) {
router.push({name: 'ApplyAfterSale', query: {sn: item.sn}})
}
function complain (sn, goodsIndex) { // 投诉
router.push({name: 'Complain', query: {sn, index: goodsIndex}})
}
function delOrder (sn) { // 删除订单 function delOrder (sn) { // 删除订单
Modal.confirm({ Modal.confirm({
title: '删除订单', title: '删除订单',
@@ -420,11 +391,16 @@ function filterAfterSaleStatus (status) {
const ob = afterSaleStatusList.filter(e => e.status === status); const ob = afterSaleStatusList.filter(e => e.status === status);
return ob && ob[0] ? ob[0].name : status return ob && ob[0] ? ob[0].name : status
} }
function canAfterSale (order) { function statusTagType (status) { // 订单/售后状态对应标签类型
if (order.isAfterSale || order.orderType === 'E_COUPON' || !order.groupAfterSaleStatus) { const map = {
return false UNPAID: 'warning', WAIT_PAY: 'warning', PAID: 'warning',
UNDELIVERED: 'warning', PARTS_DELIVERED: 'warning', DELIVERED: 'warning',
WAIT_SHIP: 'warning', WAIT_USE: 'warning', TAKE: 'warning', STAY_PICKED_UP: 'warning',
APPLY: 'warning', APPLYING: 'warning',
COMPLETED: 'success', COMPLETE: 'success',
CANCELLED: 'info', CANCEL: 'info'
} }
return order.groupAfterSaleStatus.includes('NOT_APPLIED') || order.groupAfterSaleStatus.includes('PART_AFTER_SALE') return map[status] || 'info'
} }
function paymentLabel (order) { function paymentLabel (order) {
const map = { const map = {
@@ -436,11 +412,14 @@ function paymentLabel (order) {
if (order.paymentMethod && map[order.paymentMethod]) { if (order.paymentMethod && map[order.paymentMethod]) {
return map[order.paymentMethod] return map[order.paymentMethod]
} }
if (order.payStatus === 'UNPAID' || order.orderStatus === 'UNPAID') { if (isUnpaid(order)) {
return '待支付' return '待支付'
} }
return '' return ''
} }
function isUnpaid (order) {
return order.payStatus === 'UNPAID' || order.orderStatus === 'UNPAID'
}
watch(() => route.query.tag, () => { watch(() => route.query.tag, () => {
if (props.homePage || route.name !== 'MyOrder') return; if (props.homePage || route.name !== 'MyOrder') return;
@@ -529,7 +508,7 @@ onMounted(() => {
align-items: center; align-items: center;
min-width: 0; min-width: 0;
font-size: 14px; font-size: 14px;
color: #171A26; color: #333;
line-height: 1.5; line-height: 1.5;
span { span {
@@ -630,37 +609,6 @@ onMounted(() => {
margin-top: 6px; margin-top: 6px;
} }
.refund-tag {
padding: 0 6px;
border-radius: 4px;
background: #fff7e8;
color: #ff9900;
font-size: 14px;
line-height: 22px;
}
.sub-btn {
height: 28px;
margin-top: 8px;
padding: 0 10px;
border: 1px solid #ddd;
border-radius: 4px;
background: #fff;
color: #666;
font-size: 14px;
line-height: 26px;
cursor: pointer;
&:hover {
border-color: $theme_color;
color: $theme_color;
}
}
.goods-extra .sub-btn {
margin-top: 0;
}
.col-amount, .col-amount,
.col-ops { .col-ops {
text-align: center; text-align: center;
@@ -685,38 +633,9 @@ onMounted(() => {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
}
.op-btn { :deep(.el-button + .el-button) {
min-width: 96px; margin-left: 0;
height: 32px;
padding: 0 12px;
border: 1px solid $theme_color;
border-radius: 4px;
background: #fff;
color: #171A26;
font-family: inherit;
font-size: 14px;
line-height: 30px;
cursor: pointer;
&:hover {
background: #fff5f4;
}
}
.text-link {
border: none;
background: none;
padding: 0;
color: #171A26;
font-family: inherit;
font-size: 14px;
line-height: 22px;
cursor: pointer;
&:hover {
color: $theme_color;
} }
} }
} }

View File

@@ -1,10 +1,10 @@
<template> <template>
<div class="order-detail" v-if="order.order"> <div class="order-detail" v-if="order.order">
<UserCenterLayout> <UserCenterLayout>
<div class="order-card status-card"> <div class="panel">
<div class="status-head"> <div class="status-head">
<div class="status-main"> <div class="status-main">
<p class="status-text">{{ order.orderStatusValue }}</p> <el-tag :type="statusTagType" effect="dark">{{ order.orderStatusValue }}</el-tag>
<p class="status-sn">订单号:{{ order.order.sn }}</p> <p class="status-sn">订单号:{{ order.order.sn }}</p>
</div> </div>
<div class="status-side"> <div class="status-side">
@@ -23,7 +23,7 @@
" "
> >
<el-button <el-button
type="success" type="primary"
@click="goPay(order.order.sn)" @click="goPay(order.order.sn)"
size="small" size="small"
v-if="order.allowOperationVO.pay" v-if="order.allowOperationVO.pay"
@@ -35,7 +35,6 @@
v-if="order.allowOperationVO.rog" v-if="order.allowOperationVO.rog"
>确认收货</el-button> >确认收货</el-button>
<el-button <el-button
type="danger"
@click="handleCancelOrder(order.order.sn)" @click="handleCancelOrder(order.order.sn)"
v-if="order.allowOperationVO.cancel" v-if="order.allowOperationVO.cancel"
size="small" size="small"
@@ -61,95 +60,152 @@
<p class="verificationCode" v-if="order.order.verificationCode && !isECouponOrder"> <p class="verificationCode" v-if="order.order.verificationCode && !isECouponOrder">
核验码:<span>{{ order.order.verificationCode }}</span> 核验码:<span>{{ order.order.verificationCode }}</span>
</p> </p>
<div class="order-card" v-if="order.order.deliveryMethod === 'LOGISTICS' && !isNonPhysicalOrder"> <div class="panel" v-if="order.order.deliveryMethod === 'LOGISTICS' && !isNonPhysicalOrder">
<h3>收货人信息</h3> <h3>收货人信息</h3>
<p>收货人:{{ order.order.consigneeName }}</p> <div class="info-row">
<p>手机号码:{{ $filters.secrecyMobile( order.order.consigneeMobile ) }}</p> <span class="info-label">收货人</span>
<p> <span class="info-value">{{ order.order.consigneeName }}</span>
收货地址:{{ $filters.unitAddress(order.order.consigneeAddressPath) }} </div>
{{ order.order.consigneeDetail }} <div class="info-row">
</p> <span class="info-label">手机号码</span>
<span class="info-value">{{ $filters.secrecyMobile( order.order.consigneeMobile ) }}</span>
</div>
<div class="info-row">
<span class="info-label">收货地址</span>
<span class="info-value">
{{ $filters.unitAddress(order.order.consigneeAddressPath) }}
{{ order.order.consigneeDetail }}
</span>
</div>
</div> </div>
<div class="order-card" v-if="order.order.deliveryMethod === 'SELF_PICK_UP'"> <div class="panel" v-if="order.order.deliveryMethod === 'SELF_PICK_UP'">
<h3>自提点信息</h3> <h3>自提点信息</h3>
<p>自提点名称:{{ order.order.storeAddressPath }}</p> <div class="info-row">
<p>联系方式:{{ order.order.storeAddressMobile }}</p> <span class="info-label">自提点名称</span>
<span class="info-value">{{ order.order.storeAddressPath }}</span>
</div>
<div class="info-row">
<span class="info-label">联系方式</span>
<span class="info-value">{{ order.order.storeAddressMobile }}</span>
</div>
</div> </div>
<div class="order-card"> <div class="panel">
<h3>付款信息</h3> <h3>付款信息</h3>
<p>支付方式:{{ order.paymentMethodValue }}</p> <div class="info-row">
<p>付款状态:{{ order.payStatusValue }}</p> <span class="info-label">支付方式</span>
<span class="info-value">{{ order.paymentMethodValue }}</span>
</div>
<div class="info-row">
<span class="info-label">付款状态</span>
<span class="info-value">{{ order.payStatusValue }}</span>
</div>
</div> </div>
<div class="order-card" v-if="!order.order.verificationCode && !isNonPhysicalOrder"> <div class="panel" v-if="!order.order.verificationCode && !isNonPhysicalOrder">
<h3>配送信息</h3> <h3>配送信息</h3>
<p>配送方式:{{ displayDeliveryMethodValue }}</p> <div class="info-row">
<p v-if="order.order.deliveryMethod === 'LOGISTICS' && !isNoDeliveryOrder">配送状态:{{ order.deliverStatusValue }}</p> <span class="info-label">配送方式</span>
<span class="info-value">{{ displayDeliveryMethodValue }}</span>
</div>
<div class="info-row" v-if="order.order.deliveryMethod === 'LOGISTICS' && !isNoDeliveryOrder">
<span class="info-label">配送状态</span>
<span class="info-value">{{ order.deliverStatusValue }}</span>
</div>
<template v-if="isNoDeliveryOrder"> <template v-if="isNoDeliveryOrder">
<p v-if="noDeliveryShipTime">发货时间:{{ noDeliveryShipTime }}</p> <div class="info-row" v-if="noDeliveryShipTime">
<p v-if="noDeliveryRemark">配送说明:{{ noDeliveryRemark }}</p> <span class="info-label">发货时间</span>
<span class="info-value">{{ noDeliveryShipTime }}</span>
</div>
<div class="info-row" v-if="noDeliveryRemark">
<span class="info-label">配送说明</span>
<span class="info-value">{{ noDeliveryRemark }}</span>
</div>
</template> </template>
<template v-else> <template v-else>
<p v-if="logistics"> <div class="info-row" v-if="logistics">
物流信息:{{ logistics.shipper || "暂无物流信息" }} <span class="info-label">物流信息</span>
</p> <span class="info-value">{{ logistics.shipper || "暂无物流信息" }}</span>
<p v-if="logistics"> </div>
物流单号:{{ logistics.logisticCode || "暂无物流单号" }} <div class="info-row" v-if="logistics">
</p> <span class="info-label">物流单号</span>
<div class="div-express-log" v-if="logistics"> <span class="info-value">{{ logistics.logisticCode || "暂无物流单号" }}</span>
<div class="express-log"> </div>
<p>订单日志:</p> <div class="info-row" v-if="logistics">
<div v-for="(item, index) in logistics.traces" :key="index"> <span class="info-label">订单日志</span>
<span class="time">{{ item.AcceptTime }}</span> <div class="info-value">
<span class="detail">{{ item.AcceptStation }}</span> <div class="div-express-log">
<div class="express-log">
<div v-for="(item, index) in logistics.traces" :key="index">
<span class="time">{{ item.AcceptTime }}</span>
<span class="detail">{{ item.AcceptStation }}</span>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
</div> </div>
<div class="order-card" v-if="order.order.payStatus === 'PAID'"> <div class="panel" v-if="order.order.payStatus === 'PAID'">
<h3>发票信息</h3> <h3>发票信息</h3>
<!-- 以 li_receipt 为准:needReceipt 可能为 null/false 导致有 receipt 仍显示「未开发票」 --> <!-- 以 li_receipt 为准:needReceipt 可能为 null/false 导致有 receipt 仍显示「未开发票」 -->
<template v-if="hasValidReceipt()"> <template v-if="hasValidReceipt()">
<p>发票类型:{{ formatReceiptType(order.receipt) }}</p> <div class="info-row">
<p>发票抬头:{{ formatReceiptHeaderType(order.receipt) }}</p> <span class="info-label">发票类型</span>
<p v-if="isPersonalReceipt(order.receipt) && order.receipt.personalName"> <span class="info-value">{{ formatReceiptType(order.receipt) }}</span>
个人名称:{{ order.receipt.personalName }} </div>
</p> <div class="info-row">
<p v-if="order.receipt.companyName"> <span class="info-label">发票抬头</span>
单位名称:{{ order.receipt.companyName }} <span class="info-value">{{ formatReceiptHeaderType(order.receipt) }}</span>
</p> </div>
<p v-if="order.receipt.taxpayerId"> <div class="info-row" v-if="isPersonalReceipt(order.receipt) && order.receipt.personalName">
纳税人识别号:{{ order.receipt.taxpayerId }} <span class="info-label">个人名称</span>
</p> <span class="info-value">{{ order.receipt.personalName }}</span>
<p v-if="order.receipt.companyAddress"> </div>
单位地址:{{ order.receipt.companyAddress }} <div class="info-row" v-if="order.receipt.companyName">
</p> <span class="info-label">单位名称</span>
<p v-if="order.receipt.companyPhone"> <span class="info-value">{{ order.receipt.companyName }}</span>
单位电话:{{ order.receipt.companyPhone }} </div>
</p> <div class="info-row" v-if="order.receipt.taxpayerId">
<p v-if="order.receipt.bankName"> <span class="info-label">纳税人识别号</span>
开户银行:{{ order.receipt.bankName }} <span class="info-value">{{ order.receipt.taxpayerId }}</span>
</p> </div>
<p v-if="order.receipt.bankAccount"> <div class="info-row" v-if="order.receipt.companyAddress">
银行账号:{{ order.receipt.bankAccount }} <span class="info-label">单位地址</span>
</p> <span class="info-value">{{ order.receipt.companyAddress }}</span>
<p>发票内容:{{ order.receipt.receiptContent }}</p> </div>
<p v-if="order.receipt.receiptPhone"> <div class="info-row" v-if="order.receipt.companyPhone">
收票人手机:{{ order.receipt.receiptPhone }} <span class="info-label">单位电话</span>
</p> <span class="info-value">{{ order.receipt.companyPhone }}</span>
<p v-if="order.receipt.receiptEmail"> </div>
收票人邮箱:{{ order.receipt.receiptEmail }} <div class="info-row" v-if="order.receipt.bankName">
</p> <span class="info-label">开户银行</span>
<span class="info-value">{{ order.receipt.bankName }}</span>
</div>
<div class="info-row" v-if="order.receipt.bankAccount">
<span class="info-label">银行账号</span>
<span class="info-value">{{ order.receipt.bankAccount }}</span>
</div>
<div class="info-row">
<span class="info-label">发票内容</span>
<span class="info-value">{{ order.receipt.receiptContent }}</span>
</div>
<div class="info-row" v-if="order.receipt.receiptPhone">
<span class="info-label">收票人手机</span>
<span class="info-value">{{ order.receipt.receiptPhone }}</span>
</div>
<div class="info-row" v-if="order.receipt.receiptEmail">
<span class="info-label">收票人邮箱</span>
<span class="info-value">{{ order.receipt.receiptEmail }}</span>
</div>
<div v-if="Number(order.receipt.receiptStatus) === 1" class="receipt-action"> <div v-if="Number(order.receipt.receiptStatus) === 1" class="receipt-action">
<el-button size="small" type="primary" ghost @click="viewReceiptInvoice(order.receipt)"> <el-button size="small" type="primary" @click="viewReceiptInvoice(order.receipt)">
查看发票 查看发票
</el-button> </el-button>
</div> </div>
</template> </template>
<div v-else style="color: #999; margin-left: 5px">未开发票</div> <div v-else class="empty-text">未开发票</div>
</div> </div>
<!-- 卡密信息(当前订单 orderItems;满赠赠品卡密在赠品子单详情查看) --> <!-- 卡密信息(当前订单 orderItems;满赠赠品卡密在赠品子单详情查看) -->
<div class="order-card ecoupon-card-keys" v-if="hasCardKeySection"> <div class="panel ecoupon-card-keys" v-if="hasCardKeySection">
<h3>卡密信息</h3> <h3>卡密信息</h3>
<div <div
v-for="line in cardKeyFulfillLines" v-for="line in cardKeyFulfillLines"
@@ -194,75 +250,62 @@
</div> </div>
<!-- 订单商品 --> <!-- 订单商品 -->
<div class="goods"> <div class="panel goods-panel">
<div class="shop-name"> <div class="shop-name">
<span @click="shopPage(order.order.storeId)">{{order.order.storeName}}</span> <span @click="shopPage(order.order.storeId)">{{order.order.storeName}}</span>
</div> </div>
<table> <div class="goods-list">
<thead> <div class="goods-row" v-for="(goods, goodsIndex) in order.orderItems" :key="goodsIndex">
<tr> <img
<th width="28%">商品</th> class="goods-thumb"
<th width="16%">货号</th> @click="goodsDetail(goods.skuId, goods.goodsId)"
<th width="10%">单价</th> :src="goods.image"
<th width="8%">数量</th> loading="lazy"
<th width="10%">小计</th> decoding="async"
<th width="8%">操作</th> alt=""
</tr> />
</thead> <div class="goods-info">
<tbody> <p
<tr v-for="(goods, goodsIndex) in order.orderItems" :key="goodsIndex"> @click="goodsDetail(goods.skuId, goods.goodsId)"
<td> class="hover-color goods-name"
<div class="goods-cell"> >
<img {{ goods.goodsName }}
@click="goodsDetail(goods.skuId, goods.goodsId)" </p>
:src="goods.image" <p class="goods-sn">货号:{{ goods.id }}</p>
loading="lazy" </div>
decoding="async" <div class="goods-price">
alt="" <span class="unit-price">
/> {{ $filters.unitPrice(goods.goodsPrice, "¥") }} × {{ goods.num }}
<p </span>
@click="goodsDetail(goods.skuId, goods.goodsId)" <span class="subtotal">{{ $filters.unitPrice((goods.goodsPrice * goods.num), "¥") }}</span>
class="hover-color goods-name" </div>
> <div class="goods-actions">
{{ goods.goodsName }} <button
</p> v-if="goods.commentStatus == 'UNFINISHED'"
</div> type="button"
</td> class="comment-text"
<td>{{ goods.id }}</td> @click="comment(order.order.sn, goodsIndex)"
<td>{{ $filters.unitPrice(goods.goodsPrice, "¥") }}</td> >评价</button>
<td>{{ goods.num }}</td> <el-button
<td>{{ $filters.unitPrice((goods.goodsPrice * goods.num), "¥") }}</td> v-if="goods.complainStatus == 'NO_APPLY'"
<td class="order-item-actions"> @click="complain(order.order.sn, goodsIndex)"
<button type="danger"
v-if="goods.commentStatus == 'UNFINISHED'" size="small"
type="button" >投诉</el-button
class="comment-text" >
@click="comment(order.order.sn, goodsIndex)" <el-button
>评价</button> v-if="
<el-button !isECouponOrder &&
v-if="goods.complainStatus == 'NO_APPLY'" (goods.afterSaleStatus.includes('NOT_APPLIED') ||
@click="complain(order.order.sn, goodsIndex)" goods.afterSaleStatus.includes('PART_AFTER_SALE'))
type="danger" "
class="order-item-action-btn mb_5" @click="applyAfterSale(goods.sn)"
size="small" size="small"
>投诉</el-button >申请售后</el-button
> >
<el-button </div>
v-if=" </div>
!isECouponOrder && </div>
(goods.afterSaleStatus.includes('NOT_APPLIED') ||
goods.afterSaleStatus.includes('PART_AFTER_SALE'))
"
@click="applyAfterSale(goods.sn)"
type="default"
size="small"
class="order-item-action-btn mb_5"
>申请售后</el-button
>
</td>
</tr>
</tbody>
</table>
<!-- 订单价格 --> <!-- 订单价格 -->
<div class="order-price"> <div class="order-price">
<div> <div>
@@ -488,6 +531,20 @@ const noDeliveryShipTime = computed(() => {
const pkg = noDeliveryPackages.value[0]; const pkg = noDeliveryPackages.value[0];
return pkg?.logisticsTime || ""; return pkg?.logisticsTime || "";
}); });
const statusTagType = computed(() => {
const map = {
UNPAID: "warning",
PAID: "warning",
UNDELIVERED: "warning",
PARTS_DELIVERED: "warning",
DELIVERED: "warning",
TAKE: "warning",
STAY_PICKED_UP: "warning",
COMPLETED: "success",
CANCELLED: "info",
};
return map[order.value?.order?.orderStatus] || "info";
});
function lineCardKeyRows(line) { function lineCardKeyRows(line) {
return line.cardKeys || []; return line.cardKeys || [];
@@ -720,36 +777,59 @@ onMounted(() => {
} }
} }
.mb_5 {
margin-bottom: 5px;
}
.order-detail { .order-detail {
color: #333; color: #333;
} }
.order-card { .panel {
padding: 4px 0 16px; margin-top: 16px;
margin-bottom: 8px; padding: 16px 20px;
border-bottom: 1px solid #f0f0f0; border: 1px solid #eee;
border-radius: 8px;
background: #fff;
h3 { h3 {
margin: 0 0 12px; margin: 0 0 12px;
font-size: 15px; padding-bottom: 12px;
border-bottom: 1px solid #f5f5f5;
font-size: 16px;
font-weight: 600; font-weight: 600;
color: #333; color: #333;
line-height: 1.4; line-height: 24px;
}
p {
margin: 0;
padding: 4px 0;
color: #666;
line-height: 22px;
} }
} }
.status-card { .info-row {
padding-top: 8px; display: flex;
gap: 16px;
padding: 12px 0;
border-bottom: 1px solid #f5f5f5;
&:last-child {
border-bottom: none;
padding-bottom: 4px;
}
}
.info-label {
flex: 0 0 80px;
color: #999;
font-size: 14px;
line-height: 22px;
}
.info-value {
flex: 1;
min-width: 0;
color: #333;
font-size: 14px;
line-height: 22px;
word-break: break-all;
}
.empty-text {
color: #999;
font-size: 14px;
} }
.status-head { .status-head {
@@ -759,16 +839,17 @@ onMounted(() => {
gap: 16px; gap: 16px;
} }
.status-text { .status-main {
color: $theme_color; display: flex;
font-size: 18px; align-items: center;
font-weight: 600; gap: 12px;
line-height: 1.4; flex-wrap: wrap;
} }
.status-sn { .status-sn {
margin-top: 6px; margin: 0;
color: #666; color: #999;
font-size: 14px;
} }
.status-side { .status-side {
@@ -828,78 +909,61 @@ onMounted(() => {
} }
} }
.goods { .goods-panel {
padding-top: 8px; .shop-name {
} margin: 0 0 12px;
padding-bottom: 12px;
border-bottom: 1px solid #f5f5f5;
font-size: 16px;
font-weight: 600;
.shop-name { span {
margin: 8px 0 12px; color: #333;
font-size: 14px; cursor: pointer;
font-weight: 600;
span { &:hover {
color: #438cde; color: $theme_color;
cursor: pointer; }
&:hover {
color: $theme_color;
} }
} }
} }
table { // 覆盖全局 .goods-list 的 flex 布局,避免订单商品行被压缩
border: 1px solid #eee; .goods-list {
color: #666; display: block;
border-collapse: collapse;
width: 100%;
tr {
border-top: 1px solid #eee;
}
thead > tr {
height: 40px;
background: #fafafa;
}
th {
padding: 0 8px;
font-size: 13px;
font-weight: 500;
color: #666;
}
td {
padding: 12px 8px;
text-align: center;
vertical-align: middle;
&:first-child {
text-align: left;
}
}
} }
.goods-cell { .goods-row {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 16px;
min-width: 0; padding: 12px 0;
border-bottom: 1px solid #f5f5f5;
img { &:last-child {
width: 64px; border-bottom: none;
height: 64px;
border-radius: 6px;
object-fit: cover;
flex-shrink: 0;
background: #f5f5f5;
cursor: pointer;
} }
} }
.goods-thumb {
width: 56px;
height: 56px;
border-radius: 6px;
object-fit: cover;
flex-shrink: 0;
background: #f5f5f5;
cursor: pointer;
}
.goods-info {
flex: 1;
min-width: 0;
}
.goods-name { .goods-name {
min-width: 0; margin: 0;
color: #333; color: #333;
font-size: 14px;
line-height: 20px; line-height: 20px;
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
@@ -909,12 +973,41 @@ table {
cursor: pointer; cursor: pointer;
} }
.order-item-actions { .goods-sn {
vertical-align: middle; margin: 4px 0 0;
color: #999;
font-size: 12px;
line-height: 18px;
}
.goods-price {
flex-shrink: 0;
text-align: right;
.unit-price {
display: block;
color: #999;
font-size: 13px;
line-height: 20px;
}
.subtotal {
display: block;
color: #333;
font-size: 14px;
font-weight: 600;
line-height: 22px;
}
}
.goods-actions {
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 6px;
.comment-text { .comment-text {
display: block;
margin: 0 auto 6px;
padding: 0; padding: 0;
border: 0; border: 0;
background: transparent; background: transparent;
@@ -924,9 +1017,8 @@ table {
cursor: pointer; cursor: pointer;
} }
.order-item-action-btn { .el-button {
display: block; margin: 0;
margin: 0 auto 6px;
min-width: 88px; min-width: 88px;
} }
} }
@@ -958,13 +1050,12 @@ table {
} }
} }
.verificationCode { .verificationCode {
font-size: 20px; margin: 16px 0 0;
margin-bottom: 20px; font-size: 14px;
color: rgb(65, 63, 63); color: #333;
font-weight: bold;
text-align: center;
span { span {
color: $theme_color; font-weight: 600;
} }
} }
@@ -1086,34 +1177,4 @@ table {
} }
} }
} }
.layui-layer-wrap {
dl {
border-top: solid 1px #f5f5f5;
margin-top: -1px;
overflow: hidden;
dt {
font-size: 14px;
line-height: 28px;
display: inline-block;
padding: 8px 1% 8px 0;
color: #999;
}
dd {
font-size: 14px;
line-height: 28px;
display: inline-block;
padding: 8px 0 8px 8px;
border-left: solid 1px #f5f5f5;
.text-box {
line-height: 40px;
color: #333;
word-break: break-all;
}
}
}
}
</style> </style>