mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-06 17:09:08 +08:00
feat(goods, order): 完善预约与订单详情功能
- 预约规则区域的说明中补充可预约时段 - 价格区域的标题和说明改为根据商品类型动态展示 - 优化订单详情中配送信息的展示,仅在实物订单中显示 - 核销记录新增搜索功能,支持按商品名称和核销人筛选 - 精简订单列表搜索表单,移除不必要的字段,界面更简洁
This commit is contained in:
@@ -159,7 +159,7 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 时段划分挂到价格库存区,单实例避免 v-model 互相覆盖 -->
|
||||
<!-- 时段划分挂到预约规则区,单实例避免 v-model 互相覆盖 -->
|
||||
<Teleport
|
||||
v-if="!divisionTarget || divisionReady"
|
||||
:to="divisionTarget || 'body'"
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
<span class="goods-section-index">{{ sectionNo("appointment") }}</span>
|
||||
<div class="goods-section-hd-text">
|
||||
<h3>预约规则</h3>
|
||||
<p>服务模式、可约日期与预约政策</p>
|
||||
<p>服务模式、可约日期、时段与预约政策</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-section-bd">
|
||||
@@ -237,19 +237,23 @@
|
||||
:sku-info="skuInfo"
|
||||
division-target="#appointment-slot-mount"
|
||||
/>
|
||||
<div class="goods-submodule">
|
||||
<div class="goods-submodule-hd">时段划分</div>
|
||||
<div id="appointment-slot-mount"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="goods-section-price" class="goods-section" data-section="price">
|
||||
<div class="goods-section-hd">
|
||||
<span class="goods-section-index">{{ sectionNo("price") }}</span>
|
||||
<div class="goods-section-hd-text">
|
||||
<h3>价格库存</h3>
|
||||
<p>销售模式、时段、规格与库存</p>
|
||||
<h3>{{ priceSectionTitle }}</h3>
|
||||
<p>{{ priceSectionDesc }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-section-bd">
|
||||
<div class="form-item-view">
|
||||
<el-form-item class="form-item-view-el" label="销售模式" prop="salesModel">
|
||||
<el-form-item v-if="showSalesModel" class="form-item-view-el" label="销售模式" prop="salesModel">
|
||||
<el-radio-group
|
||||
v-if="!isVirtualLikeGoods"
|
||||
v-model="baseInfoForm.salesModel"
|
||||
@@ -336,11 +340,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div v-if="isAppointmentGoods" class="goods-submodule">
|
||||
<div class="goods-submodule-hd">时段划分</div>
|
||||
<!-- AppointmentPublishPanel Teleport 挂载点 -->
|
||||
<div id="appointment-slot-mount"></div>
|
||||
</div>
|
||||
<el-alert
|
||||
v-if="isECouponGoods"
|
||||
class="mb_10"
|
||||
type="info"
|
||||
show-icon
|
||||
:closable="false"
|
||||
title="卡密库存不在这里填写。商品保存后,到商品列表的「卡池管理」导入卡密。"
|
||||
/>
|
||||
<div class="layout" style="width: 100%">
|
||||
<el-collapse v-model="open_panel">
|
||||
<el-collapse-item title="自定义规格项" name="1">
|
||||
@@ -569,7 +576,7 @@
|
||||
<span class="goods-section-index">{{ sectionNo("other") }}</span>
|
||||
<div class="goods-section-hd-text">
|
||||
<h3>其他信息</h3>
|
||||
<p>上架状态、运费模板与店内分类</p>
|
||||
<p>{{ otherSectionDesc }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-section-bd">
|
||||
@@ -715,6 +722,24 @@ export default {
|
||||
needsLogistics() {
|
||||
return this.baseInfoForm.goodsType === "PHYSICAL_GOODS";
|
||||
},
|
||||
/** 预约、卡券固定零售,不展示销售模式切换 */
|
||||
showSalesModel() {
|
||||
return !this.isECouponGoods && !this.isAppointmentGoods;
|
||||
},
|
||||
priceSectionTitle() {
|
||||
if (this.isAppointmentGoods) return "规格与可约数量";
|
||||
if (this.isECouponGoods) return "规格价格";
|
||||
return "价格库存";
|
||||
},
|
||||
priceSectionDesc() {
|
||||
if (this.isAppointmentGoods) return "规格、售价与各时段可预约数量";
|
||||
if (this.isECouponGoods) return "规格与售价,库存由卡池管理";
|
||||
return "销售模式、规格与库存";
|
||||
},
|
||||
otherSectionDesc() {
|
||||
if (this.needsLogistics) return "上架状态、运费模板与店内分类";
|
||||
return "上架状态与店内分类";
|
||||
},
|
||||
sectionTabs() {
|
||||
const tabs = [
|
||||
{ name: "basic", label: "基础信息" },
|
||||
@@ -1568,7 +1593,11 @@ export default {
|
||||
this.wholesaleData = response.result.wholesaleList;
|
||||
}
|
||||
|
||||
if (response.result.salesModel === "WHOLESALE") {
|
||||
if (this.isECouponGoods || this.isAppointmentGoods) {
|
||||
this.baseInfoForm.salesModel = "RETAIL";
|
||||
}
|
||||
|
||||
if (response.result.salesModel === "WHOLESALE" && this.showSalesModel) {
|
||||
this.baseInfoForm.weight = response.result.skuList[0].weight;
|
||||
}
|
||||
|
||||
@@ -2228,11 +2257,11 @@ export default {
|
||||
}
|
||||
if (this.isAppointmentGoods) {
|
||||
pushData.push({
|
||||
title: "预约规则",
|
||||
title: "可预约数量",
|
||||
slot: "appointmentCapacity",
|
||||
minWidth: 160,
|
||||
});
|
||||
} else {
|
||||
} else if (!this.isECouponGoods) {
|
||||
pushData.push({
|
||||
title: "库存",
|
||||
slot: "quantity",
|
||||
@@ -2569,7 +2598,7 @@ export default {
|
||||
}
|
||||
if (!this.$refs.appointmentPanel?.validateDivision()) {
|
||||
this.submitLoading = false;
|
||||
this.jumpToTab("price");
|
||||
this.jumpToTab("appointment");
|
||||
return;
|
||||
}
|
||||
Object.assign(submit, this.$refs.appointmentPanel.buildSubmitPayload());
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<el-card style="height: 60px">
|
||||
<div>
|
||||
<el-button v-if="allowOperation.editPrice" type="primary" @click="modifyPrice">调整价格</el-button>
|
||||
<el-button v-if="allowOperation.editConsignee" type="primary" @click="editAddress">修改收货地址</el-button>
|
||||
<el-button v-if="showDelivery && allowOperation.editConsignee" type="primary" @click="editAddress">修改收货地址</el-button>
|
||||
<el-button
|
||||
v-if="allowOperation.showLogistics || orderPackages.length > 0"
|
||||
v-if="showDelivery && (allowOperation.showLogistics || orderPackages.length > 0)"
|
||||
type="primary"
|
||||
@click="checkLogistics"
|
||||
>查看物流</el-button>
|
||||
@@ -14,22 +14,22 @@
|
||||
<el-button v-if="canOrderTake" type="primary" @click="orderTake">
|
||||
{{ isAppointmentOrder ? "预约核销" : "订单核销" }}
|
||||
</el-button>
|
||||
<el-button v-if="canShip" type="primary" @click="openFulfill()">发货</el-button>
|
||||
<el-button v-if="showDelivery && canShip" type="primary" @click="openFulfill()">发货</el-button>
|
||||
<el-button type="primary" @click="modifyRemark">添加备注</el-button>
|
||||
<el-button
|
||||
v-if="allowOperation.showLogistics && logisticsType === 'SHUNFENG'"
|
||||
v-if="showDelivery && allowOperation.showLogistics && logisticsType === 'SHUNFENG'"
|
||||
type="primary"
|
||||
plain
|
||||
@click="sfPrint"
|
||||
>下载面单</el-button>
|
||||
<el-button
|
||||
v-if="canShip && logisticsType !== 'SHUNFENG'"
|
||||
v-if="showDelivery && canShip && logisticsType !== 'SHUNFENG'"
|
||||
type="primary"
|
||||
plain
|
||||
@click="toPrint"
|
||||
>打印电子面单</el-button>
|
||||
<el-button
|
||||
v-if="!isNonPhysicalOrder"
|
||||
v-if="showDelivery"
|
||||
type="primary"
|
||||
plain
|
||||
style="float: right"
|
||||
@@ -68,7 +68,7 @@
|
||||
{{ orderInfo.order.createTime }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-item" v-if="orderInfo.order.verificationCode && !isAppointmentOrder">
|
||||
<div class="div-item" v-if="orderInfo.order.verificationCode && !isAppointmentOrder && !isECouponOrder">
|
||||
<div class="div-item-left">核验码:</div>
|
||||
<div class="div-item-right">{{ orderInfo.order.verificationCode }}</div>
|
||||
</div>
|
||||
@@ -96,7 +96,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-info-col">
|
||||
<div class="order-info-col" v-if="showInvoice">
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == false">
|
||||
<div class="div-item-left">发票信息:</div>
|
||||
<div class="div-item-right">暂无发票信息</div>
|
||||
@@ -148,7 +148,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-info-col">
|
||||
<div class="div-item" v-if="!isECouponOrder && !isAppointmentOrder && orderInfo.order.deliveryMethod != 'SELF_PICK_UP'">
|
||||
<div class="div-item" v-if="showDelivery && orderInfo.order.deliveryMethod != 'SELF_PICK_UP'">
|
||||
<div class="div-item-left">收货信息:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.order.consigneeName }}
|
||||
@@ -157,7 +157,7 @@
|
||||
{{ orderInfo.order.consigneeDetail }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-item" v-if="orderInfo.order.deliveryMethod == 'SELF_PICK_UP'">
|
||||
<div class="div-item" v-if="showDelivery && orderInfo.order.deliveryMethod == 'SELF_PICK_UP'">
|
||||
<div class="div-item-left">自提信息:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.order.storeAddressPath }}
|
||||
@@ -176,61 +176,7 @@
|
||||
<div class="div-item-right">{{ orderInfo.order.remark }}</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="div-item" v-if="orderInfo.order.needReceipt == false">
|
||||
<div class="div-item-left">发票信息:</div>
|
||||
<div class="div-item-right">暂无发票信息</div>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="div-item" v-if="orderInfo.order.needReceipt == true">
|
||||
<div class="div-item-left">发票抬头:</div>
|
||||
<div class="div-item-right">
|
||||
{{
|
||||
orderInfo.receipt && orderInfo.receipt.receiptTitle ? orderInfo.receipt.receiptTitle : "暂无"
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item"
|
||||
v-if="orderInfo.order.needReceipt == true && orderInfo.receipt && orderInfo.receipt.taxpayerId">
|
||||
<div class="div-item-left">发票税号:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.receipt && orderInfo.receipt.taxpayerId ? orderInfo.receipt.taxpayerId : "暂无" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
|
||||
<div class="div-item-left">发票内容:</div>
|
||||
<div class="div-item-right">
|
||||
{{
|
||||
orderInfo.receipt && orderInfo.receipt.receiptContent
|
||||
? orderInfo.receipt.receiptContent
|
||||
: "暂无"
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
|
||||
<div class="div-item-left">发票金额:</div>
|
||||
<div class="div-item-right">
|
||||
{{
|
||||
$filters.unitPrice(
|
||||
orderInfo.receipt && orderInfo.receipt.receiptPrice
|
||||
? orderInfo.receipt.receiptPrice
|
||||
: "暂无",
|
||||
"¥"
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="div-item" v-if="orderInfo.order.needReceipt == true">
|
||||
<div class="div-item-left">是否开票:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.receipt ? (orderInfo.receipt.receiptStatus == 0 ? "未开" : "已开") : "空" }}
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="div-item" v-if="!isNonPhysicalOrder">
|
||||
<div class="div-item" v-if="showDelivery">
|
||||
<div class="div-item-left">配送方式:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.deliveryMethodValue }}
|
||||
@@ -239,7 +185,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card v-if="orderPackages.length" class="mt_10 order-goods-card">
|
||||
<el-card v-if="showDelivery && orderPackages.length" class="mt_10 order-goods-card">
|
||||
<el-divider content-position="left">发货记录</el-divider>
|
||||
<el-table :data="orderPackages" border style="width: 100%">
|
||||
<el-table-column label="发货方式" width="120">
|
||||
@@ -434,7 +380,7 @@
|
||||
<span class="label" v-if="typeList.length == 1 && index == 0" style="font-size:10px !important;"><a @click="gotoHomes" style="display: inline-block;border-top: 1px dashed;border-bottom: 1px dashed;color:black;width:80px;">{{item.promotionName}}:</a><span class="op-split">|</span>
|
||||
<span class="txt" v-if="typeList.length == 1 && index == 0" style="border-top: 1px dashed;border-bottom: 1px dashed;font-size:10px !important;">¥{{ $filters.unitPrice(item.discountPrice) }}</span>
|
||||
</li> -->
|
||||
<li v-if="!isECouponOrder">
|
||||
<li v-if="showDelivery">
|
||||
<span class="label">运费:</span>
|
||||
<span class="txt">{{
|
||||
$filters.unitPrice(orderInfo.order.freightPrice, "¥")
|
||||
@@ -1098,6 +1044,17 @@ export default {
|
||||
isNonPhysicalOrder() {
|
||||
return this.isVirtualOrder || this.isECouponOrder || this.isAppointmentOrder;
|
||||
},
|
||||
/** 实物订单才展示收货、配送、运费和发货记录 */
|
||||
showDelivery() {
|
||||
return !this.isNonPhysicalOrder;
|
||||
},
|
||||
/** 实物订单始终展示发票;卡密、预约、虚拟仅在买家索取发票时展示 */
|
||||
showInvoice() {
|
||||
const order = this.orderInfo && this.orderInfo.order;
|
||||
if (!order) return false;
|
||||
if (order.needReceipt == true) return true;
|
||||
return this.showDelivery;
|
||||
},
|
||||
isAppointmentOrder() {
|
||||
const t = this.orderInfo?.order?.orderType;
|
||||
// 详情未回时用路由 query 兜底
|
||||
|
||||
@@ -11,16 +11,13 @@
|
||||
<el-form-item label="关键字" prop="keywords">
|
||||
<el-input
|
||||
v-model="searchForm.keywords"
|
||||
placeholder="商品名称/收货人/手机号/店铺名称"
|
||||
placeholder="商品名称/收货人/手机号"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单号" prop="orderSn">
|
||||
<el-input v-model="searchForm.orderSn" placeholder="请输入订单号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品名称" prop="goodsName">
|
||||
<el-input v-model="searchForm.goodsName" placeholder="请输入商品名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品类型" prop="goodsType">
|
||||
<el-select v-model="searchForm.goodsType" placeholder="请选择商品类型" clearable>
|
||||
<el-option label="实物商品" value="PHYSICAL_GOODS" />
|
||||
@@ -29,16 +26,12 @@
|
||||
<el-option label="预约商品" value="APPOINTMENT_GOODS" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="收货人" prop="shipName">
|
||||
<el-input v-model="searchForm.shipName" placeholder="请输入收货人姓名" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="订单类型" prop="orderType">
|
||||
<el-select v-model="searchForm.orderPromotionType" placeholder="请选择" clearable>
|
||||
<el-option label="普通订单" value="NORMAL" />
|
||||
<el-option label="拼团订单" value="PINTUAN" />
|
||||
<el-option label="赠品订单" value="GIFT" />
|
||||
<el-option label="积分订单" value="POINTS" />
|
||||
<el-option label="砍价订单" value="KANJIA" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="支付方式" prop="paymentMethod">
|
||||
@@ -205,9 +198,7 @@ export default {
|
||||
orderType: "",
|
||||
orderSn: "",
|
||||
keywords: "",
|
||||
goodsName: "",
|
||||
goodsType: "",
|
||||
shipName: "",
|
||||
orderStatus: "",
|
||||
paymentMethod: "",
|
||||
orderPromotionType: "",
|
||||
@@ -460,8 +451,7 @@ export default {
|
||||
this.getDataList();
|
||||
},
|
||||
getOrderNumData() {
|
||||
// orderNum 接口仅查 li_order;keywords/goodsName 会引用 oi 字段。goodsType 用 EXISTS,可以带上。
|
||||
const { orderStatus, keywords, goodsName, ...searchParams } = this.searchForm;
|
||||
const { orderStatus, pageNumber, pageSize, sort, order, ...searchParams } = this.searchForm;
|
||||
API_Order.getOrderNum(searchParams)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
|
||||
@@ -20,6 +20,37 @@
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="核销记录" name="records">
|
||||
<el-form class="record-search" @submit.prevent @keyup.enter="searchRecords">
|
||||
<el-form-item label="商品名称">
|
||||
<el-input
|
||||
v-model="recordQuery.goodsName"
|
||||
placeholder="请输入商品名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="核销员">
|
||||
<el-input
|
||||
v-model="recordQuery.verifierName"
|
||||
placeholder="请输入核销员"
|
||||
clearable
|
||||
style="width: 160px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="核销时间">
|
||||
<el-date-picker
|
||||
v-model="verifiedRange"
|
||||
type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="searchRecords">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table v-loading="loading" :data="records" border style="width: 100%">
|
||||
<el-table-column prop="code" label="核销码" min-width="120" />
|
||||
<el-table-column prop="orderSn" label="订单编号" min-width="200" show-overflow-tooltip />
|
||||
@@ -104,6 +135,11 @@ export default {
|
||||
total: 0,
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
verifiedRange: null,
|
||||
recordQuery: {
|
||||
goodsName: "",
|
||||
verifierName: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -175,12 +211,24 @@ export default {
|
||||
this.pageNumber = 1;
|
||||
this.loadRecords();
|
||||
},
|
||||
searchRecords() {
|
||||
this.pageNumber = 1;
|
||||
this.loadRecords();
|
||||
},
|
||||
loadRecords() {
|
||||
this.loading = true;
|
||||
getVerificationRecords({
|
||||
const range = this.verifiedRange;
|
||||
const params = {
|
||||
pageNumber: this.pageNumber,
|
||||
pageSize: this.pageSize,
|
||||
})
|
||||
goodsName: (this.recordQuery.goodsName || "").trim(),
|
||||
verifierName: (this.recordQuery.verifierName || "").trim(),
|
||||
};
|
||||
if (range && range.length === 2) {
|
||||
params.startTime = range[0];
|
||||
params.endTime = range[1];
|
||||
}
|
||||
getVerificationRecords(params)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
@@ -203,6 +251,16 @@ export default {
|
||||
gap: 16px;
|
||||
padding: 12px 0 4px;
|
||||
}
|
||||
.record-search {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px 16px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.record-search :deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.preview-meta {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
|
||||
Reference in New Issue
Block a user