mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-09-20 20:02:05 +08:00
Merge branch 'master' into salesman
This commit is contained in:
@@ -45,7 +45,15 @@
|
||||
<div class="wap-sku">
|
||||
{{ item.goodsUnit }}
|
||||
<el-tag
|
||||
style="margin-left: 10px"
|
||||
v-if="item.goodsType"
|
||||
style="margin-left: 6px"
|
||||
size="small"
|
||||
:type="goodsTypeTagType(item.goodsType)"
|
||||
>
|
||||
{{ goodsTypeLabel(item.goodsType) }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
style="margin-left: 6px"
|
||||
:type="item.salesModel === 'RETAIL' ? 'info' : 'primary'"
|
||||
>
|
||||
{{ item.salesModel === "RETAIL" ? "零售型" : "批发型" }}
|
||||
@@ -53,6 +61,9 @@
|
||||
</div>
|
||||
<div class="wap-content-desc-bottom">
|
||||
<div>¥{{ $filters.unitPrice(item.price) }}</div>
|
||||
<div v-if="item.goodsType === 'E_COUPON'" class="pool-stock-hint">
|
||||
库存 {{ item.quantity != null ? item.quantity : "—" }}(卡池)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,6 +86,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import * as API_Goods from "@/api/goods";
|
||||
import { goodsTypeLabel, goodsTypeTagType } from "@/constants/goodsType";
|
||||
export default {
|
||||
props: {
|
||||
selectedWay: {
|
||||
@@ -129,6 +141,8 @@ export default {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
goodsTypeLabel,
|
||||
goodsTypeTagType,
|
||||
onSearchGoods() {
|
||||
this.goodsData = [];
|
||||
this.goodsParams.pageNumber = 1;
|
||||
@@ -270,7 +284,9 @@ export default {
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.goods-dialog-cascader-popper {
|
||||
z-index: 10001 !important;
|
||||
.pool-stock-hint {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
19
manager/src/constants/cardKey.js
Normal file
19
manager/src/constants/cardKey.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 卡密商品(E_COUPON)— 平台端订单展示用常量
|
||||
*
|
||||
* 平台不管理卡池明文(S-04);本模块仅用于订单详情卡密状态文案。
|
||||
*
|
||||
* @author Mike
|
||||
* @date 2026-07-31
|
||||
*/
|
||||
/** 卡密状态文案(与后端 CardKeyStatusEnum 一致) */
|
||||
export const CARD_KEY_STATUS_TEXT = {
|
||||
UNUSED: "未使用",
|
||||
ALLOCATED: "已分配",
|
||||
RESERVED: "已预占",
|
||||
VOIDED: "已作废",
|
||||
};
|
||||
|
||||
export function formatCardKeyStatus(status) {
|
||||
return CARD_KEY_STATUS_TEXT[status] || status || "—";
|
||||
}
|
||||
35
manager/src/constants/goodsType.js
Normal file
35
manager/src/constants/goodsType.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 卡密商品(E_COUPON)— 平台端公共常量
|
||||
*
|
||||
* @author Mike
|
||||
* @date 2026-08-02
|
||||
*/
|
||||
export const E_COUPON_GOODS_TYPE = "E_COUPON";
|
||||
|
||||
export function isECoupon(goodsType) {
|
||||
return goodsType === E_COUPON_GOODS_TYPE;
|
||||
}
|
||||
|
||||
export function goodsTypeLabel(goodsType) {
|
||||
const map = {
|
||||
E_COUPON: "电子卡券",
|
||||
VIRTUAL_GOODS: "虚拟商品",
|
||||
PHYSICAL_GOODS: "实物商品",
|
||||
};
|
||||
return map[goodsType] || goodsType || "—";
|
||||
}
|
||||
|
||||
export function goodsTypeTagType(goodsType) {
|
||||
if (goodsType === E_COUPON_GOODS_TYPE) return "warning";
|
||||
if (goodsType === "VIRTUAL_GOODS") return "info";
|
||||
return "";
|
||||
}
|
||||
|
||||
export function eCouponStockHint(goodsType) {
|
||||
if (!isECoupon(goodsType)) return "";
|
||||
return "库存来自卡池同步(quantity)";
|
||||
}
|
||||
|
||||
export function promotionPriceMin(goodsType) {
|
||||
return isECoupon(goodsType) ? 0 : 0.01;
|
||||
}
|
||||
@@ -53,6 +53,8 @@
|
||||
>
|
||||
<el-option label="实物商品" value="PHYSICAL_GOODS" />
|
||||
<el-option label="虚拟商品" value="VIRTUAL_GOODS" />
|
||||
<!-- E_COUPON:卡密商品;平台无卡池管理权限(S-04) -->
|
||||
<el-option label="电子卡券" value="E_COUPON" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品分组" prop="groupId">
|
||||
@@ -385,7 +387,8 @@ export default {
|
||||
goodsTypeText(v) {
|
||||
if (v === "PHYSICAL_GOODS") return "实物商品";
|
||||
if (v === "VIRTUAL_GOODS") return "虚拟商品";
|
||||
return "电子卡券";
|
||||
if (v === "E_COUPON") return "电子卡券"; // 卡密商品
|
||||
return v || "—";
|
||||
},
|
||||
marketEnableText(v) {
|
||||
if (v === "DOWN") return "下架";
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<el-button v-if="allowOperation.cancel" plain type="warning" @click="orderCancel">订单取消</el-button>
|
||||
<el-button v-if="orderInfo.order.orderStatus === 'UNPAID'" type="primary" @click="confirmPrice">收款</el-button>
|
||||
<el-button plain @click="orderLog">订单日志</el-button>
|
||||
<el-button v-if="$route.query.orderType != 'VIRTUAL'" plain type="primary" style="float:right;" @click="printOrder">打印发货单</el-button>
|
||||
<el-button v-if="!isNonPhysicalOrder" plain type="primary" style="float:right;" @click="printOrder">打印发货单</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card class="mt_10 clearfix">
|
||||
@@ -90,7 +90,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 36%; float: left">
|
||||
<div class="div-item">
|
||||
<div class="div-item" v-if="!isECouponOrder && orderInfo.order.deliveryMethod != 'SELF_PICK_UP'">
|
||||
<div class="div-item-left">收货信息:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.order.consigneeName }}
|
||||
@@ -165,7 +165,7 @@
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="div-item" v-if="$route.query.orderType != 'VIRTUAL'">
|
||||
<div class="div-item" v-if="!isNonPhysicalOrder">
|
||||
<div class="div-item-left">配送方式:</div>
|
||||
<div class="div-item-right">
|
||||
{{ orderInfo.deliveryMethodValue }}
|
||||
@@ -217,6 +217,41 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- E_COUPON:平台订单详情只读展示卡密,无卡池代管(S-04) -->
|
||||
<div v-if="isECouponOrder" class="ecoupon-card-keys mt_10">
|
||||
<h4>卡密信息</h4>
|
||||
<el-alert
|
||||
v-if="!ecouponCardKeyDelivered"
|
||||
type="info"
|
||||
show-icon
|
||||
:closable="false"
|
||||
title="卡密尚未发放"
|
||||
class="mb_10"
|
||||
/>
|
||||
<el-table
|
||||
v-else-if="ecouponCardKeyRows.length"
|
||||
border
|
||||
:data="ecouponCardKeyRows"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column prop="cardNo" label="卡号" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="cardSecret" label="卡密" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="allocatedTime" label="发卡时间" width="170" />
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ formatCardKeyStatus(row.status || 'ALLOCATED') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row" link type="primary" @click="copyCardKey(row)">复制</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div class="goods-total">
|
||||
<ul>
|
||||
<li>
|
||||
@@ -280,7 +315,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;">¥{{ unitPrice(item.discountPrice) }}</span>
|
||||
</li> -->
|
||||
<li>
|
||||
<li v-if="!isECouponOrder">
|
||||
<span class="label">运费:</span>
|
||||
<span class="txt">{{
|
||||
unitPrice(orderInfo.order.freightPrice, "¥")
|
||||
@@ -440,6 +475,7 @@ import vueQr from "vue-qr";
|
||||
import { printElement } from "@/utils/print";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { unitPrice, clientTypeWay } from "@/utils/filters";
|
||||
import { formatCardKeyStatus } from "@/constants/cardKey";
|
||||
export default {
|
||||
name: "orderList",
|
||||
components: {
|
||||
@@ -447,6 +483,32 @@ export default {
|
||||
multipleMap,
|
||||
"vue-qr": vueQr,
|
||||
},
|
||||
computed: {
|
||||
/** 电子卡券订单:无物流区,卡密来自 orderItems[].cardKeys */
|
||||
isECouponOrder() {
|
||||
const t = this.orderInfo?.order?.orderType;
|
||||
return t === "E_COUPON" || this.$route.query.orderType === "E_COUPON";
|
||||
},
|
||||
isVirtualOrder() {
|
||||
const t = this.orderInfo?.order?.orderType;
|
||||
return t === "VIRTUAL" || this.$route.query.orderType === "VIRTUAL";
|
||||
},
|
||||
isNonPhysicalOrder() {
|
||||
return this.isVirtualOrder || this.isECouponOrder;
|
||||
},
|
||||
ecouponCardKeyDelivered() {
|
||||
return (this.data || []).some((item) => item.cardKeyDelivered);
|
||||
},
|
||||
ecouponCardKeyRows() {
|
||||
const rows = [];
|
||||
(this.data || []).forEach((item) => {
|
||||
(item.cardKeys || []).forEach((ck) => {
|
||||
rows.push({ ...ck });
|
||||
});
|
||||
});
|
||||
return rows;
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
typeList: [],
|
||||
@@ -546,6 +608,23 @@ export default {
|
||||
methods: {
|
||||
unitPrice,
|
||||
clientTypeWay,
|
||||
formatCardKeyStatus,
|
||||
copyCardKey(row) {
|
||||
const text = `卡号:${row.cardNo || ""}\n卡密:${row.cardSecret || ""}`;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
ElMessage.success("已复制到剪贴板");
|
||||
});
|
||||
} else {
|
||||
const ta = document.createElement("textarea");
|
||||
ta.value = text;
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(ta);
|
||||
ElMessage.success("已复制到剪贴板");
|
||||
}
|
||||
},
|
||||
getPromotionText(row) {
|
||||
let resultText = "";
|
||||
if (row && row.promotionType) {
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
import { saveKanJiaActivityGoods } from "@/api/promotion";
|
||||
import { regular } from "@/utils";
|
||||
import skuSelect from "@/components/lili-dialog";
|
||||
import { isECoupon } from "@/constants/goodsType";
|
||||
|
||||
export default {
|
||||
name: "add-kanjia-activity-goods",
|
||||
@@ -175,6 +176,7 @@ export default {
|
||||
|
||||
let checkResult = true;
|
||||
this.form.promotionGoodsList.forEach((res) => {
|
||||
const eCoupon = isECoupon(res.goodsType);
|
||||
if (res.stock <= 0 || res.stock > res.quantity) {
|
||||
checkResult = false;
|
||||
this.$Message.error("活动库存不能为0且不能超过商品库存");
|
||||
@@ -186,9 +188,16 @@ export default {
|
||||
this.$Message.error("结算价格金额格式不正确");
|
||||
return;
|
||||
}
|
||||
if (res.settlementPrice < 0 || res.settlementPrice > res.price) {
|
||||
if (
|
||||
(eCoupon ? res.settlementPrice < 0 : res.settlementPrice <= 0) ||
|
||||
res.settlementPrice > res.price
|
||||
) {
|
||||
checkResult = false;
|
||||
this.$Message.error("结算价格金额不能为0且不能超过商品价格");
|
||||
this.$Message.error(
|
||||
eCoupon
|
||||
? "结算价格不能小于0且不能超过商品价格"
|
||||
: "结算价格金额不能为0且不能超过商品价格"
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!regular.money.test(res.highestPrice)) {
|
||||
@@ -206,9 +215,9 @@ export default {
|
||||
this.$Message.error("最低可砍金额格式错误");
|
||||
return;
|
||||
}
|
||||
if (res.lowestPrice <= 0 || res.lowestPrice > res.price) {
|
||||
if (res.lowestPrice < 0 || (!eCoupon && res.lowestPrice <= 0) || res.lowestPrice > res.price) {
|
||||
checkResult = false;
|
||||
this.$Message.error("最低可砍金额不能为0");
|
||||
this.$Message.error(eCoupon ? "最低可砍金额不能小于0" : "最低可砍金额不能为0");
|
||||
return;
|
||||
}
|
||||
if (parseInt(res.lowestPrice) > parseInt(res.highestPrice)) {
|
||||
@@ -277,6 +286,7 @@ export default {
|
||||
storeId: e.storeId,
|
||||
storeName: e.storeName,
|
||||
skuId: e.id,
|
||||
goodsType: e.goodsType,
|
||||
});
|
||||
});
|
||||
this.form.promotionGoodsList = list;
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
<script>
|
||||
import { getKanJiaActivityGoodsById, editKanJiaActivityGoods } from "@/api/promotion";
|
||||
import { regular } from "@/utils";
|
||||
import { isECoupon } from "@/constants/goodsType";
|
||||
|
||||
export default {
|
||||
name: "editKanjiaActivityGoods",
|
||||
@@ -200,6 +201,8 @@ export default {
|
||||
params.endTime = this.$filters.unixToDate(endDate.getTime() / 1000);
|
||||
delete params.rangeTime;
|
||||
|
||||
const eCoupon = isECoupon(params.goodsType || params.goodsSku?.goodsType);
|
||||
|
||||
if (params.stock <= 0 || params.stock > params.goodsSku.quantity) {
|
||||
this.$Message.error("活动库存不能为0且不能超过商品库存");
|
||||
return;
|
||||
@@ -208,8 +211,15 @@ export default {
|
||||
this.$Message.error("结算价格金额格式不正确");
|
||||
return;
|
||||
}
|
||||
if (params.settlementPrice < 0 || params.settlementPrice > params.price) {
|
||||
this.$Message.error("结算价格金额不能为0且不能超过商品价格");
|
||||
if (
|
||||
(eCoupon ? params.settlementPrice < 0 : params.settlementPrice <= 0) ||
|
||||
params.settlementPrice > params.price
|
||||
) {
|
||||
this.$Message.error(
|
||||
eCoupon
|
||||
? "结算价格不能小于0且不能超过商品价格"
|
||||
: "结算价格金额不能为0且不能超过商品价格"
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!regular.money.test(params.highestPrice)) {
|
||||
@@ -224,8 +234,12 @@ export default {
|
||||
this.$Message.error("最低可砍金额格式错误");
|
||||
return;
|
||||
}
|
||||
if (params.lowestPrice <= 0 || params.lowestPrice > params.price) {
|
||||
this.$Message.error("最低可砍金额不能为0");
|
||||
if (
|
||||
params.lowestPrice < 0 ||
|
||||
(!eCoupon && params.lowestPrice <= 0) ||
|
||||
params.lowestPrice > params.price
|
||||
) {
|
||||
this.$Message.error(eCoupon ? "最低可砍金额不能小于0" : "最低可砍金额不能为0");
|
||||
return;
|
||||
}
|
||||
if (params.lowestPrice > params.highestPrice) {
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
>
|
||||
<el-table-column type="selection" width="60" align="center" />
|
||||
<el-table-column prop="goodsName" label="商品名称" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="类型" width="100">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ goodsTypeLabel(row.goodsType) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="SKU编码" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ row.skuId }}</span>
|
||||
@@ -117,6 +122,7 @@
|
||||
<script>
|
||||
import { addPointsGoods, getPointsGoodsCategoryList } from "@/api/promotion";
|
||||
import skuSelect from "@/components/lili-dialog";
|
||||
import { isECoupon, goodsTypeLabel } from "@/constants/goodsType";
|
||||
|
||||
export default {
|
||||
name: "addPoinsGoods",
|
||||
@@ -160,6 +166,7 @@ export default {
|
||||
await this.getCategory();
|
||||
},
|
||||
methods: {
|
||||
goodsTypeLabel,
|
||||
async getCategory() {
|
||||
let res = await getPointsGoodsCategoryList();
|
||||
this.categoryList = res.result.records;
|
||||
@@ -172,6 +179,13 @@ export default {
|
||||
this.$Modal.warning({ title: "提示", content: "请选择指定商品" });
|
||||
return;
|
||||
}
|
||||
for (const row of params) {
|
||||
const stock = Number(row.quantity) || 0;
|
||||
if (isECoupon(row.goodsType) && Number(row.activeStock) > stock) {
|
||||
this.$Message.error(`【${row.goodsName}】活动库存不能超过卡池库存(${stock})`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.form.startTime = this.form.rangeTime[0];
|
||||
this.form.endTime = this.form.rangeTime[1];
|
||||
const start = this.$filters.unixToDate(this.form.startTime / 1000);
|
||||
@@ -251,6 +265,7 @@ export default {
|
||||
quantity: e.quantity || "",
|
||||
storeName: e.storeName || "",
|
||||
price: e.price || "",
|
||||
goodsType: e.goodsType,
|
||||
};
|
||||
list.push(obj);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user