mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-08-06 10:57:26 +08:00
feat(buyer): 增强商品详情与支付逻辑
- 引入 buyerLogin 工具,优化商品详情页的链接跳转逻辑,确保未登录用户能正确重定向到登录页面 - 更新商品 SKU 详情 API,支持未登录状态下的访问 - 修改支付 API,新增 skipMessage 参数以控制支付提示信息 - 改进商品列表与支付页面的用户体验,确保更流畅的操作流程 - 规范化商品类型与库存提示,提升用户体验
This commit is contained in:
@@ -33,12 +33,13 @@ export function goodsDetail (goodsId) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// id获取商品Sku详情
|
// id获取商品Sku详情(支持未登录浏览,登录后可选携带 token)
|
||||||
export function goodsSkuDetail (params) {
|
export function goodsSkuDetail (params) {
|
||||||
return request({
|
return request({
|
||||||
url: `/buyer/goods/goods/sku/${params.goodsId}/${params.skuId}`,
|
url: `/buyer/goods/goods/sku/${params.goodsId}/${params.skuId}`,
|
||||||
method: Method.GET,
|
method: Method.GET,
|
||||||
needToken: true,
|
needToken: false,
|
||||||
|
optionalToken: true,
|
||||||
params
|
params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,13 @@ export function tradeDetail (params) {
|
|||||||
* @param payClient 调起方式 可用值:APP,NATIVE,JSAPI,H5
|
* @param payClient 调起方式 可用值:APP,NATIVE,JSAPI,H5
|
||||||
* @param sn 订单编号
|
* @param sn 订单编号
|
||||||
*/
|
*/
|
||||||
export function pay (params) {
|
export function pay (params, config = {}) {
|
||||||
return request({
|
return request({
|
||||||
url: `/buyer/payment/cashier/pay/${params.paymentMethod}/${params.paymentClient}`,
|
url: `/buyer/payment/cashier/pay/${params.paymentMethod}/${params.paymentClient}`,
|
||||||
needToken: true,
|
needToken: true,
|
||||||
method: Method.GET,
|
method: Method.GET,
|
||||||
params
|
params,
|
||||||
|
skipMessage: !!config.skipMessage,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ export function applyThird (params) {
|
|||||||
export function getDetailById (id) {
|
export function getDetailById (id) {
|
||||||
return request({
|
return request({
|
||||||
url: `/buyer/store/store/get/detail/${id}`,
|
url: `/buyer/store/store/get/detail/${id}`,
|
||||||
needToken: true,
|
needToken: false,
|
||||||
|
optionalToken: true,
|
||||||
method: Method.GET
|
method: Method.GET
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,7 +259,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
|
||||||
<div class="add-buy-car-box">
|
<div class="add-buy-car-box">
|
||||||
<div class="item-select">
|
<div class="item-select">
|
||||||
<div class="item-select-title">
|
<div class="item-select-title">
|
||||||
@@ -339,6 +338,14 @@
|
|||||||
@click="buyNow"
|
@click="buyNow"
|
||||||
>立即购买</el-button
|
>立即购买</el-button
|
||||||
>
|
>
|
||||||
|
<el-alert
|
||||||
|
v-if="isECouponGoods"
|
||||||
|
class="e-coupon-after-sale-notice"
|
||||||
|
type="warning"
|
||||||
|
:closable="false"
|
||||||
|
show-icon
|
||||||
|
:title="eCouponAfterSaleHint()"
|
||||||
|
/>
|
||||||
<el-tooltip content="观看视频" v-if="skuDetail.goodsVideo">
|
<el-tooltip content="观看视频" v-if="skuDetail.goodsVideo">
|
||||||
<img class="view-video" @click="showGoodsVideo = true" :src="playIcon" alt="">
|
<img class="view-video" @click="showGoodsVideo = true" :src="playIcon" alt="">
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@@ -374,6 +381,7 @@ import {
|
|||||||
getECouponMaxBuyNum,
|
getECouponMaxBuyNum,
|
||||||
createEmptyPromotionMap,
|
createEmptyPromotionMap,
|
||||||
resolveECouponCartType,
|
resolveECouponCartType,
|
||||||
|
eCouponAfterSaleHint,
|
||||||
E_COUPON_CART_BUY_NOW,
|
E_COUPON_CART_BUY_NOW,
|
||||||
E_COUPON_CART_PINTUAN,
|
E_COUPON_CART_PINTUAN,
|
||||||
E_COUPON_CART_POINTS,
|
E_COUPON_CART_POINTS,
|
||||||
@@ -476,6 +484,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
eCouponAfterSaleHint,
|
||||||
// 初始化video
|
// 初始化video
|
||||||
initVideo(){
|
initVideo(){
|
||||||
if(!this.goodsVideo ){
|
if(!this.goodsVideo ){
|
||||||
@@ -724,8 +733,8 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// 用户登录才会判断是否收藏
|
// 用户登录才会判断是否收藏(须同时有 token,避免残留 userInfo 触发 401 跳转登录)
|
||||||
if (this.Cookies.getItem("userInfo")) {
|
if (this.Cookies.getItem("accessToken") && this.Cookies.getItem("userInfo")) {
|
||||||
isCollection("GOODS", this.skuDetail.id).then((res) => {
|
isCollection("GOODS", this.skuDetail.id).then((res) => {
|
||||||
if (res.success && res.result) {
|
if (res.success && res.result) {
|
||||||
this.isCollected = true;
|
this.isCollected = true;
|
||||||
@@ -1052,6 +1061,22 @@ export default {
|
|||||||
border-top: 1px dotted $border_color;
|
border-top: 1px dotted $border_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.e-coupon-after-sale-notice {
|
||||||
|
width: fit-content;
|
||||||
|
max-width: 420px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding: 4px 10px;
|
||||||
|
|
||||||
|
:deep(.el-alert__content) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-alert__title) {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.add-buy-car-row {
|
.add-buy-car-row {
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ export function isECouponOrder(orderType) {
|
|||||||
return orderType === E_COUPON_ORDER_TYPE;
|
return orderType === E_COUPON_ORDER_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 详情页提示:卡密交付后不支持买家售后(FR-B-04) */
|
||||||
|
export const E_COUPON_AFTER_SALE_HINT =
|
||||||
|
"卡密交付后不支持买家售后,请确认商品信息后再购买。";
|
||||||
|
|
||||||
|
export function eCouponAfterSaleHint() {
|
||||||
|
return E_COUPON_AFTER_SALE_HINT;
|
||||||
|
}
|
||||||
|
|
||||||
/** 可售库存:E_COUPON 读 SKU quantity(由卡池 syncSkuStock 同步) */
|
/** 可售库存:E_COUPON 读 SKU quantity(由卡池 syncSkuStock 同步) */
|
||||||
export function getECouponStock(sku) {
|
export function getECouponStock(sku) {
|
||||||
if (!sku) return 0;
|
if (!sku) return 0;
|
||||||
@@ -132,23 +140,19 @@ function normalizeCardKeyFulfillLine(source) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 汇总 E_COUPON 主单行 + 满赠子单摘要的履约行 */
|
/** 汇总当前订单 orderItems 中的卡密履约行(不含满赠子单;赠品卡密在赠品子单详情单独查看) */
|
||||||
export function collectCardKeyFulfillLines(orderItems = [], giftSummaries = []) {
|
export function collectCardKeyFulfillLines(orderItems = []) {
|
||||||
const lines = [];
|
const lines = [];
|
||||||
(orderItems || []).forEach((item) => {
|
(orderItems || []).forEach((item) => {
|
||||||
if (!isCardKeyFulfillApplicable(item)) return;
|
if (!isCardKeyFulfillApplicable(item)) return;
|
||||||
lines.push(normalizeCardKeyFulfillLine(item));
|
lines.push(normalizeCardKeyFulfillLine(item));
|
||||||
});
|
});
|
||||||
(giftSummaries || []).forEach((gift) => {
|
|
||||||
lines.push(normalizeCardKeyFulfillLine({ ...gift, isGift: true }));
|
|
||||||
});
|
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function orderHasCardKeySection({ orderItems, giftSummaries, isECouponOrder } = {}) {
|
export function orderHasCardKeySection({ orderItems, isECouponOrder } = {}) {
|
||||||
if (isECouponOrder) return true;
|
if (isECouponOrder) return true;
|
||||||
if (Array.isArray(giftSummaries) && giftSummaries.length > 0) return true;
|
if (collectCardKeyFulfillLines(orderItems).length > 0) return true;
|
||||||
if (collectCardKeyFulfillLines(orderItems, []).length > 0) return true;
|
|
||||||
return (orderItems || []).some(
|
return (orderItems || []).some(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.goodsType === E_COUPON_GOODS_TYPE ||
|
item.goodsType === E_COUPON_GOODS_TYPE ||
|
||||||
@@ -167,15 +171,14 @@ export function flattenCardKeyFulfillLines(lines, withGoodsName = false) {
|
|||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 订单是否含已交付或可展示的卡密行(含满赠 E_COUPON 子单行) */
|
/** 当前订单是否含已交付卡密(仅 orderItems,不含满赠子单) */
|
||||||
export function orderHasCardKeyContent(orderItems, giftSummaries) {
|
export function orderHasCardKeyContent(orderItems) {
|
||||||
const lines = collectCardKeyFulfillLines(orderItems, giftSummaries);
|
return flattenCardKeyFulfillLines(collectCardKeyFulfillLines(orderItems)).length > 0;
|
||||||
return flattenCardKeyFulfillLines(lines).length > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 扁平化订单项卡密(仅 cardKeyDelivered 且含 cardKeys;兼容旧逻辑) */
|
/** 扁平化当前订单 orderItems 卡密 */
|
||||||
export function flattenOrderCardKeys(orderItems, withGoodsName = false, giftSummaries) {
|
export function flattenOrderCardKeys(orderItems, withGoodsName = false) {
|
||||||
const lines = collectCardKeyFulfillLines(orderItems, giftSummaries);
|
const lines = collectCardKeyFulfillLines(orderItems);
|
||||||
if (lines.some((line) => line.status)) {
|
if (lines.some((line) => line.status)) {
|
||||||
return flattenCardKeyFulfillLines(lines, withGoodsName);
|
return flattenCardKeyFulfillLines(lines, withGoodsName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import storage from "@/plugins/storage";
|
|||||||
import { fetchAndApplyTheme } from "@/utils/theme";
|
import { fetchAndApplyTheme } from "@/utils/theme";
|
||||||
import { getThemeSetting } from "@/api/common.js";
|
import { getThemeSetting } from "@/api/common.js";
|
||||||
import config from "@/config";
|
import config from "@/config";
|
||||||
|
import { openLink } from "@/utils/buyerLogin";
|
||||||
|
|
||||||
const { aMapSecurityJsCode, inputMaxLength } = config;
|
const { aMapSecurityJsCode, inputMaxLength } = config;
|
||||||
|
|
||||||
@@ -36,12 +37,7 @@ app.config.globalProperties.Cookies = storage;
|
|||||||
app.config.globalProperties.$inputMaxLength = inputMaxLength;
|
app.config.globalProperties.$inputMaxLength = inputMaxLength;
|
||||||
|
|
||||||
app.config.globalProperties.linkTo = function (url) {
|
app.config.globalProperties.linkTo = function (url) {
|
||||||
if (!url) return;
|
openLink(url, router);
|
||||||
if (url.substr(0, 1) === "/") {
|
|
||||||
window.open(location.origin + url, "_blank");
|
|
||||||
} else {
|
|
||||||
window.open(url, "_blank");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
app.config.globalProperties.connectCs = function (
|
app.config.globalProperties.connectCs = function (
|
||||||
|
|||||||
@@ -140,8 +140,8 @@ export default {
|
|||||||
if (!this.goodsMsg.data.intro) {
|
if (!this.goodsMsg.data.intro) {
|
||||||
this.goodsMsg.data.intro = ''
|
this.goodsMsg.data.intro = ''
|
||||||
}
|
}
|
||||||
// 判断是否收藏
|
// 判断是否收藏(须同时有 token,避免未登录/ token 失效时误跳登录页)
|
||||||
if (this.Cookies.getItem("userInfo")) {
|
if (this.Cookies.getItem("accessToken") && this.Cookies.getItem("userInfo")) {
|
||||||
isStoreCollection("STORE", this.goodsMsg.data.storeId).then((res) => {
|
isStoreCollection("STORE", this.goodsMsg.data.storeId).then((res) => {
|
||||||
if (res.success && res.result) {
|
if (res.success && res.result) {
|
||||||
this.storeCollected = true;
|
this.storeCollected = true;
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ import { Message } from "@/utils/message";
|
|||||||
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
|
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
|
||||||
import GoodsClassNav from "@/components/nav/GoodsClassNav";
|
import GoodsClassNav from "@/components/nav/GoodsClassNav";
|
||||||
import * as apiGoods from "@/api/goods";
|
import * as apiGoods from "@/api/goods";
|
||||||
|
import { isBuyerLoggedIn, redirectToLogin } from "@/utils/buyerLogin";
|
||||||
export default {
|
export default {
|
||||||
name: "GoodsList",
|
name: "GoodsList",
|
||||||
beforeRouteEnter(to, from, next) {
|
beforeRouteEnter(to, from, next) {
|
||||||
@@ -201,12 +202,15 @@ export default {
|
|||||||
this.getGoodsList();
|
this.getGoodsList();
|
||||||
},
|
},
|
||||||
goGoodsDetail(skuId, goodsId) {
|
goGoodsDetail(skuId, goodsId) {
|
||||||
// 跳转商品详情
|
const location = {
|
||||||
let routeUrl = this.$router.resolve({
|
|
||||||
path: "/goodsDetail",
|
path: "/goodsDetail",
|
||||||
query: { skuId, goodsId },
|
query: { skuId, goodsId },
|
||||||
});
|
};
|
||||||
window.open(routeUrl.href, "_blank");
|
if (!isBuyerLoggedIn()) {
|
||||||
|
redirectToLogin(this.$router, location);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.open(this.$router.resolve(location).href, "_blank");
|
||||||
},
|
},
|
||||||
goShopPage(id) {
|
goShopPage(id) {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
|||||||
@@ -132,7 +132,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<div v-else style="color: #999; margin-left: 5px">未开发票</div>
|
<div v-else style="color: #999; margin-left: 5px">未开发票</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 卡密信息(E_COUPON 主单或满赠子单,以 cardKeyFulfillStatus 为准) -->
|
<!-- 卡密信息(当前订单 orderItems;满赠赠品卡密在赠品子单详情查看) -->
|
||||||
<div class="order-card ecoupon-card-keys" v-if="hasCardKeySection">
|
<div class="order-card ecoupon-card-keys" v-if="hasCardKeySection">
|
||||||
<h3>卡密信息</h3>
|
<h3>卡密信息</h3>
|
||||||
<div
|
<div
|
||||||
@@ -140,9 +140,6 @@
|
|||||||
:key="line.key"
|
:key="line.key"
|
||||||
class="ecoupon-fulfill-block"
|
class="ecoupon-fulfill-block"
|
||||||
>
|
>
|
||||||
<div v-if="cardKeyFulfillLines.length > 1" class="ecoupon-fulfill-title">
|
|
||||||
{{ line.goodsName || (line.isGift ? "满赠电子卡券" : "电子卡券") }}
|
|
||||||
</div>
|
|
||||||
<el-alert
|
<el-alert
|
||||||
v-if="line.status !== 'DELIVERED'"
|
v-if="line.status !== 'DELIVERED'"
|
||||||
:type="cardKeyFulfillAlertType(line.status)"
|
:type="cardKeyFulfillAlertType(line.status)"
|
||||||
@@ -158,13 +155,6 @@
|
|||||||
<div class="ecoupon-card-keys-pc">
|
<div class="ecoupon-card-keys-pc">
|
||||||
<el-table border :data="lineCardKeyRows(line)" style="width: 100%">
|
<el-table border :data="lineCardKeyRows(line)" style="width: 100%">
|
||||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
<el-table-column
|
|
||||||
v-if="cardKeyFulfillLines.length > 1"
|
|
||||||
prop="goodsName"
|
|
||||||
label="商品"
|
|
||||||
min-width="120"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
<el-table-column prop="cardNo" label="卡号" min-width="140" show-overflow-tooltip />
|
<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="cardSecret" label="卡密" min-width="120" show-overflow-tooltip />
|
||||||
<el-table-column prop="allocatedTime" label="发卡时间" width="170" />
|
<el-table-column prop="allocatedTime" label="发卡时间" width="170" />
|
||||||
@@ -446,36 +436,25 @@ export default {
|
|||||||
isNonPhysicalOrder() {
|
isNonPhysicalOrder() {
|
||||||
return this.isVirtualOrder || this.isECouponOrder;
|
return this.isVirtualOrder || this.isECouponOrder;
|
||||||
},
|
},
|
||||||
/** 是否展示卡密区块(含满赠 E_COUPON 子单 giftECouponOrders) */
|
/** 是否展示卡密区块(仅当前订单 orderItems) */
|
||||||
hasCardKeySection() {
|
hasCardKeySection() {
|
||||||
return orderHasCardKeySection({
|
return orderHasCardKeySection({
|
||||||
orderItems: this.order.orderItems,
|
orderItems: this.order.orderItems,
|
||||||
giftSummaries: this.order.giftECouponOrders,
|
|
||||||
isECouponOrder: this.isECouponOrder,
|
isECouponOrder: this.isECouponOrder,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
cardKeyFulfillLines() {
|
cardKeyFulfillLines() {
|
||||||
return collectCardKeyFulfillLines(
|
return collectCardKeyFulfillLines(this.order.orderItems);
|
||||||
this.order.orderItems,
|
|
||||||
this.order.giftECouponOrders
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
ecouponCardKeyRows() {
|
ecouponCardKeyRows() {
|
||||||
return flattenOrderCardKeys(
|
return flattenOrderCardKeys(this.order.orderItems, false);
|
||||||
this.order.orderItems,
|
|
||||||
false,
|
|
||||||
this.order.giftECouponOrders
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
cardKeyFulfillAlertType,
|
cardKeyFulfillAlertType,
|
||||||
resolveCardKeyFulfillMessage,
|
resolveCardKeyFulfillMessage,
|
||||||
lineCardKeyRows(line) {
|
lineCardKeyRows(line) {
|
||||||
return (line.cardKeys || []).map((ck) => ({
|
return line.cardKeys || [];
|
||||||
...ck,
|
|
||||||
goodsName: line.goodsName,
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
copyCardKey(row) {
|
copyCardKey(row) {
|
||||||
const text = `卡号:${row.cardNo || ""}\n卡密:${row.cardSecret || ""}`;
|
const text = `卡号:${row.cardNo || ""}\n卡密:${row.cardSecret || ""}`;
|
||||||
@@ -821,12 +800,6 @@ table {
|
|||||||
border-top: 1px dashed #eee;
|
border-top: 1px dashed #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ecoupon-fulfill-title {
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ecoupon-card-keys-pc {
|
.ecoupon-card-keys-pc {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,19 +11,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="pay-way">{{params.paymentMethod === 'ALIPAY' ? '支付宝支付' : '微信支付'}}</div>
|
<div class="pay-way">{{ payWayName }}支付</div>
|
||||||
<div class="qrcode">
|
<div class="qrcode">
|
||||||
<div style="width:200px;height:200px;border:1px solid #eee;">
|
<div class="qrcode-box">
|
||||||
<vue-qr :text="qrcode" :margin="0" colorDark="#000" colorLight="#fff" :size="200"></vue-qr>
|
<div v-if="payLoading" class="qrcode-status">正在生成支付二维码...</div>
|
||||||
|
<div v-else-if="payError" class="qrcode-status qrcode-status--error">
|
||||||
|
<p>{{ payError }}</p>
|
||||||
|
<p class="qrcode-status-tip">您可点击「重新支付」重试,或返回选择其他支付方式</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="intro">
|
<vue-qr
|
||||||
<el-icon><Iphone /></el-icon> 请使用{{params.paymentMethod === 'ALIPAY' ? '支付宝' : '微信'}}扫码付款
|
v-else
|
||||||
|
:text="qrcode"
|
||||||
|
:margin="0"
|
||||||
|
colorDark="#000"
|
||||||
|
colorLight="#fff"
|
||||||
|
:size="200"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="!payError" class="intro">
|
||||||
|
<el-icon><Iphone /></el-icon> 请使用{{ payWayName }}扫码付款
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-div">
|
<div class="btn-div">
|
||||||
<p class="mb_10">支付成功后自动跳转,如未跳转请点击按钮手动跳转。。。</p>
|
<p class="mb_10">支付成功后自动跳转,如未跳转请点击按钮手动跳转。。。</p>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="handlePay">重新支付</el-button>
|
<el-button :loading="payLoading" @click="handlePay">重新支付</el-button>
|
||||||
<el-button type="success" @click="$router.push('/payDone')">支付成功</el-button>
|
<el-button type="success" @click="$router.push('/payDone')">支付成功</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,47 +53,79 @@ export default {
|
|||||||
components: { vueQr, Iphone },
|
components: { vueQr, Iphone },
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
qrcode: '', // 二维码
|
qrcode: '',
|
||||||
params: this.$route.query, // 参数
|
params: this.$route.query,
|
||||||
interval: null, // 定时器
|
interval: null,
|
||||||
num: 0 // 商品数
|
num: 0,
|
||||||
|
payLoading: false,
|
||||||
|
payError: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
payWayName () {
|
||||||
|
return this.params.paymentMethod === 'ALIPAY' ? '支付宝' : '微信';
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 获取支付二维码
|
formatPayError (rawMessage) {
|
||||||
|
const message = (rawMessage || '').trim();
|
||||||
|
if (!message || message === '支付业务异常,请稍后重试') {
|
||||||
|
return `${this.payWayName}支付暂不可用,请稍后重试或选择其他支付方式`;
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
clearPayPoll () {
|
||||||
|
if (this.interval) {
|
||||||
|
clearInterval(this.interval);
|
||||||
|
this.interval = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
handlePay () {
|
handlePay () {
|
||||||
|
this.clearPayPoll();
|
||||||
const params = this.$route.query;
|
const params = this.$route.query;
|
||||||
pay(params).then(res => {
|
this.payLoading = true;
|
||||||
if (res.success) {
|
this.payError = '';
|
||||||
|
this.qrcode = '';
|
||||||
|
pay(params, { skipMessage: true })
|
||||||
|
.then((res) => {
|
||||||
|
this.payLoading = false;
|
||||||
|
if (res.success && res.result) {
|
||||||
this.qrcode = res.result;
|
this.qrcode = res.result;
|
||||||
this.num = 0;
|
this.num = 0;
|
||||||
this.interval = setInterval(this.callback, 5000);
|
this.interval = setInterval(this.callback, 5000);
|
||||||
} else {
|
return;
|
||||||
Message.error(res.message)
|
}
|
||||||
|
this.payError = this.formatPayError(res.message);
|
||||||
|
Message.error(this.payError);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
this.payLoading = false;
|
||||||
|
this.payError = this.formatPayError(err?.message || err?.data?.message);
|
||||||
|
Message.error(this.payError);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
callback () {
|
||||||
|
this.num++;
|
||||||
|
if (this.num >= 7) {
|
||||||
|
this.clearPayPoll();
|
||||||
|
}
|
||||||
|
const params = JSON.parse(JSON.stringify(this.$route.query));
|
||||||
|
delete params.paymentMethod;
|
||||||
|
delete params.paymentClient;
|
||||||
|
payCallback(params).then((res) => {
|
||||||
|
if (res.result) {
|
||||||
|
this.clearPayPoll();
|
||||||
|
this.$router.push({ path: '/payDone', query: { orderType: this.$route.query.orderType } });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
callback () { // 支付回调接口
|
|
||||||
this.num++;
|
|
||||||
if (this.num >= 7) {
|
|
||||||
clearInterval(this.interval);
|
|
||||||
this.interval = null;
|
|
||||||
}
|
|
||||||
let params = JSON.parse(JSON.stringify(this.$route.query));
|
|
||||||
delete params.paymentMethod;
|
|
||||||
delete params.paymentClient;
|
|
||||||
payCallback(params).then(res => {
|
|
||||||
if (res.result) {
|
|
||||||
clearInterval(this.interval);
|
|
||||||
this.interval = null;
|
|
||||||
this.$router.push({path: '/payDone', query: {orderType: this.$route.query.orderType}});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.handlePay();
|
this.handlePay();
|
||||||
}
|
},
|
||||||
|
beforeUnmount () {
|
||||||
|
this.clearPayPoll();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -125,6 +169,33 @@ export default {
|
|||||||
margin: 30px 0 0 70px;
|
margin: 30px 0 0 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qrcode-box {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode-status {
|
||||||
|
padding: 16px;
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode-status--error {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode-status-tip {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.intro {
|
.intro {
|
||||||
background-color: #ff7674;
|
background-color: #ff7674;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
@@ -143,6 +214,9 @@ export default {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #409eff;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.price {
|
.price {
|
||||||
@@ -153,4 +227,7 @@ export default {
|
|||||||
.head-right {
|
.head-right {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
.mb_10 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
@click="goGoodsDetail(item.id)"
|
@click="goGoodsDetail(item.id)"
|
||||||
>
|
>
|
||||||
<div class="goods-show-img">
|
<div class="goods-show-img">
|
||||||
<img :src="item.goodsSku.thumbnail" />
|
<img :src="itemThumbnail(item)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="goods-show-price">
|
<div class="goods-show-price">
|
||||||
<span>
|
<span>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="goods-show-detail">
|
<div class="goods-show-detail">
|
||||||
<span>{{ item.goodsSku.goodsName }}</span>
|
<span>{{ itemGoodsName(item) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="goods-show-num">
|
<div class="goods-show-num">
|
||||||
已有<span>{{ item.commentNum || 0 }}</span>人评价
|
已有<span>{{ item.commentNum || 0 }}</span>人评价
|
||||||
@@ -70,6 +70,13 @@ export default {
|
|||||||
this.getCate()
|
this.getCate()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
/** 列表 API 返回 PointsGoods(thumbnail/goodsName 在顶层);详情 API 才有 goodsSku */
|
||||||
|
itemThumbnail (item) {
|
||||||
|
return item?.goodsSku?.thumbnail || item?.thumbnail || ''
|
||||||
|
},
|
||||||
|
itemGoodsName (item) {
|
||||||
|
return item?.goodsSku?.goodsName || item?.goodsName || ''
|
||||||
|
},
|
||||||
getList () { // 获取列表
|
getList () { // 获取列表
|
||||||
pointGoods(this.params).then(res => {
|
pointGoods(this.params).then(res => {
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ service.interceptors.request.use(
|
|||||||
|
|
||||||
const accessToken = Storage.getItem("accessToken");
|
const accessToken = Storage.getItem("accessToken");
|
||||||
if (accessToken && (config.needToken || config.optionalToken)) {
|
if (accessToken && (config.needToken || config.optionalToken)) {
|
||||||
config.headers["accessToken"] = accessToken;
|
|
||||||
try {
|
try {
|
||||||
const jwtData = JSON.parse(
|
const jwtData = JSON.parse(
|
||||||
decodeURIComponent(
|
decodeURIComponent(
|
||||||
@@ -80,12 +79,23 @@ service.interceptors.request.use(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (jwtData.exp < Math.round(new Date() / 1000)) {
|
const expired = jwtData.exp < Math.round(new Date() / 1000);
|
||||||
refresh({ response: { config } });
|
if (expired) {
|
||||||
|
if (config.needToken) {
|
||||||
|
return refresh({ response: { config } });
|
||||||
|
}
|
||||||
|
// 公开接口:丢弃过期 token,匿名继续请求,避免浏览商品时被引导登录
|
||||||
|
Storage.removeItem("accessToken");
|
||||||
|
Storage.removeItem("refreshToken");
|
||||||
|
} else {
|
||||||
|
config.headers["accessToken"] = accessToken;
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Storage.removeItem("accessToken");
|
Storage.removeItem("accessToken");
|
||||||
Storage.removeItem("refreshToken");
|
Storage.removeItem("refreshToken");
|
||||||
|
if (config.needToken) {
|
||||||
|
return refresh({ response: { config } });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
59
buyer/src/utils/buyerLogin.js
Normal file
59
buyer/src/utils/buyerLogin.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 买家端登录态与商品详情跳转校验
|
||||||
|
*
|
||||||
|
* @author Mike
|
||||||
|
* @date 2026-08-05
|
||||||
|
*/
|
||||||
|
import storage from "@/plugins/storage";
|
||||||
|
|
||||||
|
export function isBuyerLoggedIn() {
|
||||||
|
const rawUserInfo = storage.getItem("userInfo");
|
||||||
|
if (rawUserInfo) {
|
||||||
|
try {
|
||||||
|
return !!JSON.parse(rawUserInfo).username;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !!storage.getItem("accessToken");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseInternalLink(url) {
|
||||||
|
const [path, search = ""] = url.split("?");
|
||||||
|
const query = {};
|
||||||
|
if (search) {
|
||||||
|
new URLSearchParams(search).forEach((value, key) => {
|
||||||
|
query[key] = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { path, query };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isGoodsDetailPath(path) {
|
||||||
|
return path === "/goodsDetail";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function redirectToLogin(router, location) {
|
||||||
|
router.push({
|
||||||
|
path: "/login",
|
||||||
|
query: {
|
||||||
|
rePath: location.path,
|
||||||
|
query: JSON.stringify(location.query || {}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 内部链接跳转;访问商品详情前校验登录(首页装修、列表等共用) */
|
||||||
|
export function openLink(url, router) {
|
||||||
|
if (!url) return;
|
||||||
|
if (url.charAt(0) !== "/") {
|
||||||
|
window.open(url, "_blank");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const location = parseInternalLink(url);
|
||||||
|
if (!isBuyerLoggedIn() && isGoodsDetailPath(location.path)) {
|
||||||
|
redirectToLogin(router, location);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.open(router.resolve(url).href, "_blank");
|
||||||
|
}
|
||||||
@@ -236,7 +236,6 @@
|
|||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
<el-table-column prop="goodsName" label="商品" min-width="140" show-overflow-tooltip />
|
|
||||||
<el-table-column prop="cardNo" label="卡号" min-width="140" show-overflow-tooltip />
|
<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="cardSecret" label="卡密" min-width="120" show-overflow-tooltip />
|
||||||
<el-table-column prop="allocatedTime" label="发卡时间" width="170" />
|
<el-table-column prop="allocatedTime" label="发卡时间" width="170" />
|
||||||
@@ -504,10 +503,7 @@ export default {
|
|||||||
const rows = [];
|
const rows = [];
|
||||||
(this.data || []).forEach((item) => {
|
(this.data || []).forEach((item) => {
|
||||||
(item.cardKeys || []).forEach((ck) => {
|
(item.cardKeys || []).forEach((ck) => {
|
||||||
rows.push({
|
rows.push({ ...ck });
|
||||||
...ck,
|
|
||||||
goodsName: item.goodsName,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return rows;
|
return rows;
|
||||||
|
|||||||
@@ -92,22 +92,19 @@ function normalizeCardKeyFulfillLine(source) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function collectCardKeyFulfillLines(orderItems = [], giftSummaries = []) {
|
/** 汇总当前订单 orderItems 中的卡密履约行(不含满赠子单;赠品卡密在赠品子单详情单独查看) */
|
||||||
|
export function collectCardKeyFulfillLines(orderItems = []) {
|
||||||
const lines = [];
|
const lines = [];
|
||||||
(orderItems || []).forEach((item) => {
|
(orderItems || []).forEach((item) => {
|
||||||
if (!isCardKeyFulfillApplicable(item)) return;
|
if (!isCardKeyFulfillApplicable(item)) return;
|
||||||
lines.push(normalizeCardKeyFulfillLine(item));
|
lines.push(normalizeCardKeyFulfillLine(item));
|
||||||
});
|
});
|
||||||
(giftSummaries || []).forEach((gift) => {
|
|
||||||
lines.push(normalizeCardKeyFulfillLine({ ...gift, isGift: true }));
|
|
||||||
});
|
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function orderHasCardKeySection({ orderItems, giftSummaries, isECouponOrder } = {}) {
|
export function orderHasCardKeySection({ orderItems, isECouponOrder } = {}) {
|
||||||
if (isECouponOrder) return true;
|
if (isECouponOrder) return true;
|
||||||
if (Array.isArray(giftSummaries) && giftSummaries.length > 0) return true;
|
if (collectCardKeyFulfillLines(orderItems).length > 0) return true;
|
||||||
if (collectCardKeyFulfillLines(orderItems, []).length > 0) return true;
|
|
||||||
return (orderItems || []).some(
|
return (orderItems || []).some(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.goodsType === E_COUPON_GOODS_TYPE ||
|
item.goodsType === E_COUPON_GOODS_TYPE ||
|
||||||
@@ -126,13 +123,13 @@ export function flattenCardKeyFulfillLines(lines, withGoodsName = false) {
|
|||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 订单是否含已交付卡密(含满赠子单) */
|
/** 当前订单是否含已交付卡密(仅 orderItems) */
|
||||||
export function orderHasCardKeyContent(orderItems, giftSummaries) {
|
export function orderHasCardKeyContent(orderItems) {
|
||||||
return flattenCardKeyFulfillLines(collectCardKeyFulfillLines(orderItems, giftSummaries)).length > 0;
|
return flattenCardKeyFulfillLines(collectCardKeyFulfillLines(orderItems)).length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function flattenOrderCardKeys(orderItems, withGoodsName = false, giftSummaries) {
|
export function flattenOrderCardKeys(orderItems, withGoodsName = false) {
|
||||||
const lines = collectCardKeyFulfillLines(orderItems, giftSummaries);
|
const lines = collectCardKeyFulfillLines(orderItems);
|
||||||
if (lines.some((line) => line.status)) {
|
if (lines.some((line) => line.status)) {
|
||||||
return flattenCardKeyFulfillLines(lines, withGoodsName);
|
return flattenCardKeyFulfillLines(lines, withGoodsName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="search card-key-pool">
|
<div class="search card-key-pool">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div v-if="goodsName" class="pool-header">
|
<div v-if="goodsName || skuOptions.length" class="pool-header">
|
||||||
<el-button @click="goBack">返回</el-button>
|
<el-button @click="goBack">返回</el-button>
|
||||||
<span class="pool-meta">
|
<span v-if="goodsName" class="pool-meta">
|
||||||
<strong>商品:</strong>{{ goodsName }}
|
<strong>商品:</strong>{{ goodsName }}
|
||||||
</span>
|
</span>
|
||||||
|
<div v-if="skuOptions.length" class="pool-sku-select">
|
||||||
|
<span class="pool-sku-label">规格 SKU</span>
|
||||||
|
<el-select
|
||||||
|
v-model="skuId"
|
||||||
|
:loading="skuLoading"
|
||||||
|
placeholder="请选择规格"
|
||||||
|
filterable
|
||||||
|
style="width: 320px"
|
||||||
|
@change="onSkuChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in skuOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="formatSkuOptionLabel(item)"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-alert
|
<el-alert
|
||||||
@@ -167,9 +185,17 @@
|
|||||||
max-height="320"
|
max-height="320"
|
||||||
border
|
border
|
||||||
>
|
>
|
||||||
<el-table-column prop="row" label="行号" width="80" />
|
<el-table-column label="行号" width="80" align="center">
|
||||||
<el-table-column prop="cardNo" label="卡号" min-width="120" />
|
<template #default="{ row: failItem }">
|
||||||
<el-table-column prop="reason" label="失败原因" min-width="200" />
|
<span v-if="failItem">{{ failItem.row }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="卡号" min-width="120">
|
||||||
|
<template #default="{ row: failItem }">
|
||||||
|
<span v-if="failItem">{{ failItem.cardNo || "—" }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="reason" label="失败原因" min-width="200" show-overflow-tooltip />
|
||||||
</el-table>
|
</el-table>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button type="primary" @click="importResultVisible = false">确定</el-button>
|
<el-button type="primary" @click="importResultVisible = false">确定</el-button>
|
||||||
@@ -204,6 +230,7 @@ import {
|
|||||||
exportCardKey,
|
exportCardKey,
|
||||||
downloadImportTemplate,
|
downloadImportTemplate,
|
||||||
} from "@/api/cardKey";
|
} from "@/api/cardKey";
|
||||||
|
import { getQueryGoodsIdGoodsList } from "@/api/goods";
|
||||||
import {
|
import {
|
||||||
formatCardKeyStatus,
|
formatCardKeyStatus,
|
||||||
CARD_KEY_STATUS_TAG,
|
CARD_KEY_STATUS_TAG,
|
||||||
@@ -223,6 +250,8 @@ export default {
|
|||||||
skuId: "",
|
skuId: "",
|
||||||
goodsId: "",
|
goodsId: "",
|
||||||
goodsName: "",
|
goodsName: "",
|
||||||
|
skuOptions: [],
|
||||||
|
skuLoading: false,
|
||||||
statusTab: "ALL",
|
statusTab: "ALL",
|
||||||
stats: null,
|
stats: null,
|
||||||
poolLocked: false,
|
poolLocked: false,
|
||||||
@@ -271,6 +300,20 @@ export default {
|
|||||||
];
|
];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
"$route.query": {
|
||||||
|
handler() {
|
||||||
|
const prevSkuId = this.skuId;
|
||||||
|
this.initFromRoute();
|
||||||
|
if (this.skuId && this.skuId !== prevSkuId) {
|
||||||
|
this.resetPoolViewState();
|
||||||
|
this.loadStats();
|
||||||
|
this.getList();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
formatStatus: formatCardKeyStatus,
|
formatStatus: formatCardKeyStatus,
|
||||||
statusTag(status) {
|
statusTag(status) {
|
||||||
@@ -285,6 +328,65 @@ export default {
|
|||||||
this.goodsId = q.goodsId || "";
|
this.goodsId = q.goodsId || "";
|
||||||
this.goodsName = q.goodsName || "";
|
this.goodsName = q.goodsName || "";
|
||||||
},
|
},
|
||||||
|
formatSkuOptionLabel(sku) {
|
||||||
|
if (!sku) return "";
|
||||||
|
const spec = sku.simpleSpecs || sku.sn || sku.id;
|
||||||
|
const qty =
|
||||||
|
sku.poolStock != null && sku.poolStock !== ""
|
||||||
|
? sku.poolStock
|
||||||
|
: sku.quantity != null
|
||||||
|
? sku.quantity
|
||||||
|
: "—";
|
||||||
|
return `${spec}(库存 ${qty})`;
|
||||||
|
},
|
||||||
|
resetPoolViewState() {
|
||||||
|
this.statusTab = "ALL";
|
||||||
|
this.searchForm.pageNumber = 1;
|
||||||
|
this.searchForm.cardNo = "";
|
||||||
|
this.importRange = [];
|
||||||
|
this.poolLocked = false;
|
||||||
|
this.stats = null;
|
||||||
|
this.data = [];
|
||||||
|
this.total = 0;
|
||||||
|
},
|
||||||
|
/** 卡池变更后刷新 SKU 选择器中的可售库存(后端 syncSkuStock → quantity) */
|
||||||
|
refreshSkuOptionStock() {
|
||||||
|
if (!this.goodsId) return Promise.resolve();
|
||||||
|
return this.loadSkuOptions();
|
||||||
|
},
|
||||||
|
async loadSkuOptions() {
|
||||||
|
if (!this.goodsId) {
|
||||||
|
this.skuOptions = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.skuLoading = true;
|
||||||
|
try {
|
||||||
|
const res = await getQueryGoodsIdGoodsList(this.goodsId);
|
||||||
|
if (res.success) {
|
||||||
|
this.skuOptions = (res.result || []).filter((s) => !s.deleteFlag);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
this.skuOptions = [];
|
||||||
|
} finally {
|
||||||
|
this.skuLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSkuChange(newSkuId) {
|
||||||
|
if (!newSkuId) return;
|
||||||
|
this.skuId = newSkuId;
|
||||||
|
this.resetPoolViewState();
|
||||||
|
this.$router.replace({
|
||||||
|
path: this.$route.path,
|
||||||
|
query: {
|
||||||
|
...this.$route.query,
|
||||||
|
skuId: newSkuId,
|
||||||
|
goodsId: this.goodsId,
|
||||||
|
goodsName: this.goodsName,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.loadStats();
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
onStatusTabClick(tab) {
|
onStatusTabClick(tab) {
|
||||||
this.statusTab = tab.paneName;
|
this.statusTab = tab.paneName;
|
||||||
this.searchForm.pageNumber = 1;
|
this.searchForm.pageNumber = 1;
|
||||||
@@ -370,6 +472,7 @@ export default {
|
|||||||
this.importResultVisible = true;
|
this.importResultVisible = true;
|
||||||
this.loadStats();
|
this.loadStats();
|
||||||
this.getList();
|
this.getList();
|
||||||
|
this.refreshSkuOptionStock();
|
||||||
} else {
|
} else {
|
||||||
this.checkPoolLocked(res);
|
this.checkPoolLocked(res);
|
||||||
}
|
}
|
||||||
@@ -407,6 +510,7 @@ export default {
|
|||||||
this.addVisible = false;
|
this.addVisible = false;
|
||||||
this.loadStats();
|
this.loadStats();
|
||||||
this.getList();
|
this.getList();
|
||||||
|
this.refreshSkuOptionStock();
|
||||||
} else {
|
} else {
|
||||||
this.checkPoolLocked(res);
|
this.checkPoolLocked(res);
|
||||||
}
|
}
|
||||||
@@ -426,6 +530,7 @@ export default {
|
|||||||
this.$Message.success("作废成功");
|
this.$Message.success("作废成功");
|
||||||
this.loadStats();
|
this.loadStats();
|
||||||
this.getList();
|
this.getList();
|
||||||
|
this.refreshSkuOptionStock();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -445,8 +550,15 @@ export default {
|
|||||||
this.exportLoading = false;
|
this.exportLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
init() {
|
async init() {
|
||||||
this.initFromRoute();
|
this.initFromRoute();
|
||||||
|
if (this.goodsId) {
|
||||||
|
await this.loadSkuOptions();
|
||||||
|
}
|
||||||
|
if (!this.skuId && this.skuOptions.length) {
|
||||||
|
this.onSkuChange(this.skuOptions[0].id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.skuId) {
|
if (this.skuId) {
|
||||||
this.loadStats();
|
this.loadStats();
|
||||||
this.getList();
|
this.getList();
|
||||||
@@ -475,6 +587,18 @@ export default {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pool-sku-select {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pool-sku-label {
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.goods-tab {
|
.goods-tab {
|
||||||
:deep(.el-tabs__item) {
|
:deep(.el-tabs__item) {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
@@ -1,58 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="goods-operation">
|
<div class="goods-operation">
|
||||||
<div class="step-list">
|
<!-- 填写商品详细信息(含商品类型、商品分类) -->
|
||||||
<el-steps :active="activestep" align-center style="height: 60px; margin-top: 10px">
|
<second-step ref="second" :firstData="firstData" v-if="activestep === 1"></second-step>
|
||||||
<el-step title="选择商品品类" />
|
<!-- 发布完成 -->
|
||||||
<el-step title="填写商品详情" />
|
<third-step ref="third" v-if="activestep === 2"></third-step>
|
||||||
<el-step title="商品发布成功" />
|
|
||||||
</el-steps>
|
|
||||||
</div>
|
|
||||||
<!-- 第一步 选择分类 -->
|
|
||||||
<first-step ref='first' v-show="activestep === 0" @change="getFirstData"></first-step>
|
|
||||||
<!-- 第二步 商品详细信息 -->
|
|
||||||
<second-step ref='second' :firstData="firstData" v-if="activestep === 1"></second-step>
|
|
||||||
<!-- 第三步 发布完成 -->
|
|
||||||
<third-step ref='third' v-if="activestep === 2"></third-step>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import firstStep from './goodsOperationFirst'
|
import secondStep from "./goodsOperationSec";
|
||||||
import secondStep from './goodsOperationSec'
|
import thirdStep from "./goodsOperationThird";
|
||||||
import thirdStep from './goodsOperationThird'
|
|
||||||
export default {
|
export default {
|
||||||
name: "addGoods",
|
name: "addGoods",
|
||||||
components: {
|
components: {
|
||||||
firstStep,
|
|
||||||
secondStep,
|
secondStep,
|
||||||
thirdStep
|
thirdStep,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
/** 当前激活步骤*/
|
/** 当前激活步骤:1 填写详情,2 发布成功 */
|
||||||
activestep: 0,
|
activestep: 1,
|
||||||
firstData: {}, // 第一步传递的数据
|
firstData: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
// 选择商品分类回调
|
|
||||||
getFirstData (item) {
|
|
||||||
this.firstData = item;
|
|
||||||
this.activestep = 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
// 编辑商品、模板、复制商品
|
window.scrollTo(0, 0);
|
||||||
if (this.$route.query.id || this.$route.query.draftId || this.$route.query.copyId) {
|
},
|
||||||
this.activestep = 1;
|
|
||||||
} else {
|
|
||||||
this.activestep = 0
|
|
||||||
this.$refs.first.selectGoodsType = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -1,249 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div></div>
|
||||||
<!-- 选择商品类型 -->
|
|
||||||
<el-dialog v-model="selectGoodsType" width="550px" :show-close="false">
|
|
||||||
<div class="goods-type-list">
|
|
||||||
<div
|
|
||||||
class="goods-type-item"
|
|
||||||
:class="{ 'active-goods-type': item.check }"
|
|
||||||
@click="handleClickGoodsType(item)"
|
|
||||||
v-for="(item, index) in goodsTypeWay"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<img :src="item.img" />
|
|
||||||
<div>
|
|
||||||
<h2>{{ item.title }}</h2>
|
|
||||||
<p>{{ item.desc }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<div class="goods-type-actions">
|
|
||||||
<el-button @click="cancelGoodsType">取消</el-button>
|
|
||||||
<el-button type="primary" @click="confirmGoodsType">确认</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
<!-- 商品分类 -->
|
|
||||||
<div class="content-goods-publish">
|
|
||||||
<div class="goods-category">
|
|
||||||
<ul v-if="categoryListLevel1.length > 0">
|
|
||||||
<li
|
|
||||||
v-for="(item, index) in categoryListLevel1"
|
|
||||||
:class="{ activeClass: category[0].name === item.name }"
|
|
||||||
@click="handleSelectCategory(item, index, 1)"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<span>{{ item.name }}</span>
|
|
||||||
<span>></span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul v-if="categoryListLevel2.length > 0">
|
|
||||||
<li
|
|
||||||
v-for="(item, index) in categoryListLevel2"
|
|
||||||
:class="{ activeClass: category[1].name === item.name }"
|
|
||||||
@click="handleSelectCategory(item, index, 2)"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<span>{{ item.name }}</span>
|
|
||||||
<span>></span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<ul v-if="categoryListLevel3.length > 0">
|
|
||||||
<li
|
|
||||||
v-for="(item, index) in categoryListLevel3"
|
|
||||||
:class="{ activeClass: category[2].name === item.name }"
|
|
||||||
@click="handleSelectCategory(item, index, 3)"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<span>{{ item.name }}</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<p class="current-goods-category">
|
|
||||||
您当前选择的商品类别是:
|
|
||||||
<span>{{ category[0].name }}</span>
|
|
||||||
<span v-show="category[1].name">> {{ category[1].name }}</span>
|
|
||||||
<span v-show="category[2].name">> {{ category[2].name }}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<!-- 底部按钮 -->
|
|
||||||
<div class="footer">
|
|
||||||
<div class="footer-btns">
|
|
||||||
<el-button type="primary" @click="openGoodsTypeDialog">商品类型</el-button>
|
|
||||||
<el-button type="primary" @click="next">下一步</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import * as API_GOODS from "@/api/goods";
|
/** 商品类型与分类已迁移至 goodsOperationSec.vue 基本信息区 */
|
||||||
import goodsType1Img from "@/assets/goodsType1.png";
|
|
||||||
import goodsType2Img from "@/assets/goodsType2.png";
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
name: "goodsOperationFirst",
|
||||||
return {
|
|
||||||
selectGoodsType: false, // 展示选择商品分类modal
|
|
||||||
/** 商品类型选项;E_COUPON 为卡密商品(与 VIRTUAL_GOODS 核销型区分,见 FR-S-01) */
|
|
||||||
goodsTypeWay: [
|
|
||||||
{
|
|
||||||
title: "实物商品",
|
|
||||||
img: goodsType1Img,
|
|
||||||
desc: "零售批发,物流配送",
|
|
||||||
type: "PHYSICAL_GOODS",
|
|
||||||
check: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "虚拟商品",
|
|
||||||
img: goodsType2Img,
|
|
||||||
desc: "虚拟核验,无需物流",
|
|
||||||
type: "VIRTUAL_GOODS",
|
|
||||||
check: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "电子卡券",
|
|
||||||
img: goodsType2Img,
|
|
||||||
desc: "卡密自动发卡,无需物流",
|
|
||||||
type: "E_COUPON", // goodsType;库存由卡池同步,非手动填写
|
|
||||||
check: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
// 商品分类选择数组
|
|
||||||
category: [
|
|
||||||
{ name: "", id: "" },
|
|
||||||
{ name: "", id: "" },
|
|
||||||
{ name: "", id: "" },
|
|
||||||
],
|
|
||||||
// 商品类型
|
|
||||||
goodsType: "",
|
|
||||||
pendingGoodsType: "",
|
|
||||||
/** 1级分类列表*/
|
|
||||||
categoryListLevel1: [],
|
|
||||||
/** 2级分类列表*/
|
|
||||||
categoryListLevel2: [],
|
|
||||||
/** 3级分类列表*/
|
|
||||||
categoryListLevel3: [],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
selectGoodsType(val) {
|
|
||||||
if (val) {
|
|
||||||
this.syncGoodsTypeSelection();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
syncGoodsTypeSelection() {
|
|
||||||
this.pendingGoodsType = this.goodsType;
|
|
||||||
this.goodsTypeWay.forEach((item) => {
|
|
||||||
item.check = item.type === this.goodsType;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
openGoodsTypeDialog() {
|
|
||||||
this.selectGoodsType = true;
|
|
||||||
},
|
|
||||||
// 点击商品类型(仅临时选中,确认后才生效)
|
|
||||||
handleClickGoodsType(val) {
|
|
||||||
this.goodsTypeWay.forEach((item) => {
|
|
||||||
item.check = item.type === val.type;
|
|
||||||
});
|
|
||||||
this.pendingGoodsType = val.type;
|
|
||||||
},
|
|
||||||
cancelGoodsType() {
|
|
||||||
this.syncGoodsTypeSelection();
|
|
||||||
this.selectGoodsType = false;
|
|
||||||
},
|
|
||||||
confirmGoodsType() {
|
|
||||||
if (!this.pendingGoodsType) {
|
|
||||||
this.$Message.error("请选择商品类型");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.goodsType = this.pendingGoodsType;
|
|
||||||
this.selectGoodsType = false;
|
|
||||||
},
|
|
||||||
/** 选择商城商品分类 */
|
|
||||||
handleSelectCategory(row, index, level) {
|
|
||||||
if (level === 1) {
|
|
||||||
this.category.forEach((cate) => {
|
|
||||||
(cate.name = ""), (cate.id = "");
|
|
||||||
});
|
|
||||||
this.category[0].name = row.name;
|
|
||||||
this.category[0].id = row.id;
|
|
||||||
this.categoryListLevel2 = this.categoryListLevel1[index].children;
|
|
||||||
this.categoryListLevel3 = [];
|
|
||||||
} else if (level === 2) {
|
|
||||||
this.category[1].name = row.name;
|
|
||||||
this.category[1].id = row.id;
|
|
||||||
this.category[2].name = "";
|
|
||||||
this.category[2].id = "";
|
|
||||||
this.categoryListLevel3 = this.categoryListLevel2[index].children;
|
|
||||||
} else {
|
|
||||||
this.category[2].name = row.name;
|
|
||||||
this.category[2].id = row.id;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/** 查询下一级 商城商品分类*/
|
|
||||||
GET_NextLevelCategory(row) {
|
|
||||||
const _id = row && row.id !== 0 ? row.id : 0;
|
|
||||||
API_GOODS.getGoodsCategoryAll().then((res) => {
|
|
||||||
if (res.success && res.result) {
|
|
||||||
this.categoryListLevel1 = res.result;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 下一步
|
|
||||||
next() {
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
if (!this.goodsType) {
|
|
||||||
this.$Message.error("请选择商品类型");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.category[0].name) {
|
|
||||||
this.$Message.error("请选择商品分类");
|
|
||||||
return;
|
|
||||||
} else if (!this.category[2].name) {
|
|
||||||
this.$Message.error("必须选择到三级分类");
|
|
||||||
return;
|
|
||||||
} else if (this.category[2].name) {
|
|
||||||
let params = {
|
|
||||||
category: this.category,
|
|
||||||
goodsType: this.goodsType,
|
|
||||||
};
|
|
||||||
this.$emit("change", params);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.GET_NextLevelCategory();
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import "./addGoods.scss";
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-btns {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.goods-type-actions {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 12px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-goods-publish {
|
|
||||||
.goods-category li.activeClass {
|
|
||||||
background-color: #409eff;
|
|
||||||
border-color: #409eff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -8,12 +8,37 @@
|
|||||||
<div class="base-info-item">
|
<div class="base-info-item">
|
||||||
<h4>基本信息</h4>
|
<h4>基本信息</h4>
|
||||||
<div class="form-item-view">
|
<div class="form-item-view">
|
||||||
<el-form-item label="商品分类">
|
<el-form-item label="商品类型" prop="goodsType">
|
||||||
<span class="goods-category-name">{{
|
<el-select
|
||||||
baseInfoForm.categoryName[0]
|
v-model="baseInfoForm.goodsType"
|
||||||
}}</span>
|
placeholder="请选择商品类型"
|
||||||
<span> > {{ baseInfoForm.categoryName[1] }}</span>
|
style="width: 260px"
|
||||||
<span> > {{ baseInfoForm.categoryName[2] }}</span>
|
popper-class="goods-type-select-popper"
|
||||||
|
@change="handleGoodsTypeChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in goodsTypeOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
|
<div class="goods-type-option">
|
||||||
|
<span class="goods-type-option-label">{{ item.label }}</span>
|
||||||
|
<span class="goods-type-option-desc">{{ item.desc }}</span>
|
||||||
|
</div>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<div v-if="currentGoodsTypeDesc" class="form-tip">{{ currentGoodsTypeDesc }}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品分类" prop="categoryPath">
|
||||||
|
<el-cascader
|
||||||
|
v-model="selectedCategory"
|
||||||
|
:options="categoryList"
|
||||||
|
placeholder="请选择商品分类"
|
||||||
|
clearable
|
||||||
|
style="width: 260px"
|
||||||
|
@change="handleCategoryChange"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="商品名称" prop="goodsName">
|
<el-form-item label="商品名称" prop="goodsName">
|
||||||
<el-input v-model="baseInfoForm.goodsName" clearable placeholder="商品名称" style="width: 260px" type="text" />
|
<el-input v-model="baseInfoForm.goodsName" clearable placeholder="商品名称" style="width: 260px" type="text" />
|
||||||
@@ -494,7 +519,6 @@
|
|||||||
<!-- 底部按钮 -->
|
<!-- 底部按钮 -->
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="footer-btns">
|
<div class="footer-btns">
|
||||||
<el-button type="primary" @click="pre">上一步</el-button>
|
|
||||||
<el-button :loading="submitLoading" type="primary" @click="save">
|
<el-button :loading="submitLoading" type="primary" @click="save">
|
||||||
{{ $route.query.id ? "保存" : "保存商品" }}
|
{{ $route.query.id ? "保存" : "保存商品" }}
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -575,6 +599,12 @@ export default {
|
|||||||
needsLogistics() {
|
needsLogistics() {
|
||||||
return this.baseInfoForm.goodsType === "PHYSICAL_GOODS";
|
return this.baseInfoForm.goodsType === "PHYSICAL_GOODS";
|
||||||
},
|
},
|
||||||
|
currentGoodsTypeDesc() {
|
||||||
|
const matched = this.goodsTypeOptions.find(
|
||||||
|
(item) => item.value === this.baseInfoForm.goodsType
|
||||||
|
);
|
||||||
|
return matched ? matched.desc : "";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
// 表单验证项,商品价格
|
// 表单验证项,商品价格
|
||||||
@@ -608,6 +638,16 @@ export default {
|
|||||||
accessToken: "", //令牌token
|
accessToken: "", //令牌token
|
||||||
goodsParams: [],
|
goodsParams: [],
|
||||||
categoryId: "", // 商品分类第三级id
|
categoryId: "", // 商品分类第三级id
|
||||||
|
/** 商品类型选项 */
|
||||||
|
goodsTypeOptions: [
|
||||||
|
{ label: "实物商品", value: "PHYSICAL_GOODS", desc: "零售批发,物流配送" },
|
||||||
|
{ label: "虚拟商品", value: "VIRTUAL_GOODS", desc: "虚拟核验,无需物流" },
|
||||||
|
{ label: "电子卡券", value: "E_COUPON", desc: "卡密自动发卡,无需物流" },
|
||||||
|
],
|
||||||
|
/** 商城分类级联数据 */
|
||||||
|
categoryList: [],
|
||||||
|
/** 商城分类选中值 [一级id, 二级id, 三级id] */
|
||||||
|
selectedCategory: [],
|
||||||
//提交状态
|
//提交状态
|
||||||
submitLoading: false,
|
submitLoading: false,
|
||||||
//上传图片路径
|
//上传图片路径
|
||||||
@@ -729,6 +769,8 @@ export default {
|
|||||||
/** 存储未通过校验的单元格位置 */
|
/** 存储未通过校验的单元格位置 */
|
||||||
validateError: [],
|
validateError: [],
|
||||||
baseInfoFormRule: {
|
baseInfoFormRule: {
|
||||||
|
goodsType: [{ required: true, message: "请选择商品类型", trigger: "change" }],
|
||||||
|
categoryPath: [{ required: true, message: "请选择商品分类", trigger: "change" }],
|
||||||
goodsName: [regular.REQUIRED, regular.WHITE_SPACE, regular.VARCHAR60],
|
goodsName: [regular.REQUIRED, regular.WHITE_SPACE, regular.VARCHAR60],
|
||||||
price: [regular.REQUIRED, { validator: checkPrice }],
|
price: [regular.REQUIRED, { validator: checkPrice }],
|
||||||
sellingPoint: [regular.REQUIRED, regular.VARCHAR60],
|
sellingPoint: [regular.REQUIRED, regular.VARCHAR60],
|
||||||
@@ -986,9 +1028,79 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pre() {
|
/** 加载商城商品分类树 */
|
||||||
// 上一步
|
loadCategoryList() {
|
||||||
this.$parent.activestep--;
|
return API_GOODS.getGoodsCategoryAll().then((res) => {
|
||||||
|
if (res.success && res.result) {
|
||||||
|
this.categoryList = this.formatCategoryTree(res.result);
|
||||||
|
this.syncSelectedCategoryFromPath();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
formatCategoryTree(list) {
|
||||||
|
return (list || []).map((item) => ({
|
||||||
|
value: String(item.id),
|
||||||
|
label: item.name,
|
||||||
|
children: (item.children || []).map((child) => ({
|
||||||
|
value: String(child.id),
|
||||||
|
label: child.name,
|
||||||
|
children: (child.children || []).map((grandson) => ({
|
||||||
|
value: String(grandson.id),
|
||||||
|
label: grandson.name,
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
syncSelectedCategoryFromPath() {
|
||||||
|
const path = this.baseInfoForm.categoryPath;
|
||||||
|
if (!path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const ids = path.split(",").filter(Boolean).map(String);
|
||||||
|
if (ids.length >= 3) {
|
||||||
|
this.selectedCategory = ids;
|
||||||
|
this.categoryId = ids[2];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getCategoryNames(ids) {
|
||||||
|
const names = [];
|
||||||
|
let options = this.categoryList;
|
||||||
|
ids.forEach((id) => {
|
||||||
|
const found = (options || []).find((item) => item.value === id);
|
||||||
|
if (found) {
|
||||||
|
names.push(found.label);
|
||||||
|
options = found.children || [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return names;
|
||||||
|
},
|
||||||
|
handleGoodsTypeChange() {
|
||||||
|
if (this.isVirtualLikeGoods) {
|
||||||
|
this.baseInfoForm.salesModel = "RETAIL";
|
||||||
|
}
|
||||||
|
if (this.isECouponGoods) {
|
||||||
|
this.baseInfoForm.templateId = 0;
|
||||||
|
}
|
||||||
|
this.renderTableData(this.skuTableData);
|
||||||
|
},
|
||||||
|
handleCategoryChange(val) {
|
||||||
|
if (!val || val.length < 3) {
|
||||||
|
this.selectedCategory = val || [];
|
||||||
|
this.categoryId = "";
|
||||||
|
this.baseInfoForm.categoryPath = "";
|
||||||
|
this.baseInfoForm.categoryName = [];
|
||||||
|
this.baseInfoForm.brandId = 0;
|
||||||
|
this.brandList = [];
|
||||||
|
this.goodsParams = [];
|
||||||
|
this.params_panel = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.categoryId = val[2];
|
||||||
|
this.baseInfoForm.categoryPath = val.join(",");
|
||||||
|
this.baseInfoForm.categoryName = this.getCategoryNames(val);
|
||||||
|
this.baseInfoForm.brandId = 0;
|
||||||
|
this.getGoodsBrandList();
|
||||||
|
this.GET_GoodsParams();
|
||||||
},
|
},
|
||||||
// 预览图片
|
// 预览图片
|
||||||
handleView(url) {
|
handleView(url) {
|
||||||
@@ -1265,6 +1377,7 @@ export default {
|
|||||||
this.baseInfoForm = { ...this.baseInfoForm, ...response.result };
|
this.baseInfoForm = { ...this.baseInfoForm, ...response.result };
|
||||||
this.baseInfoForm.release = 1; //即使是被放入仓库,修改的时候也会显示会立即发布
|
this.baseInfoForm.release = 1; //即使是被放入仓库,修改的时候也会显示会立即发布
|
||||||
this.categoryId = response.result.categoryPath.split(",")[2];
|
this.categoryId = response.result.categoryPath.split(",")[2];
|
||||||
|
this.syncSelectedCategoryFromPath();
|
||||||
|
|
||||||
// 如果是复制商品,需要清除ID,确保提交时作为新商品
|
// 如果是复制商品,需要清除ID,确保提交时作为新商品
|
||||||
if (this.$route.query.copyId) {
|
if (this.$route.query.copyId) {
|
||||||
@@ -1301,19 +1414,6 @@ export default {
|
|||||||
this.GET_ShopGoodsLabel();
|
this.GET_ShopGoodsLabel();
|
||||||
this.GET_GoodsUnit();
|
this.GET_GoodsUnit();
|
||||||
|
|
||||||
if (this.firstData.category) {
|
|
||||||
const cateId = [];
|
|
||||||
this.baseInfoForm.categoryName = [];
|
|
||||||
this.firstData.category.forEach((cate) => {
|
|
||||||
this.baseInfoForm.categoryName.push(cate.name);
|
|
||||||
cateId.push(cate.id);
|
|
||||||
});
|
|
||||||
this.categoryId = cateId[2];
|
|
||||||
|
|
||||||
this.baseInfoForm.categoryPath = cateId.toString();
|
|
||||||
}
|
|
||||||
this.firstData.goodsType &&
|
|
||||||
(this.baseInfoForm.goodsType = this.firstData.goodsType);
|
|
||||||
/** 查询商品参数 */
|
/** 查询商品参数 */
|
||||||
this.GET_GoodsParams();
|
this.GET_GoodsParams();
|
||||||
},
|
},
|
||||||
@@ -2204,6 +2304,10 @@ export default {
|
|||||||
this.$Message.error(`以下参数为必填项:${missingParams.join('、')}`);
|
this.$Message.error(`以下参数为必填项:${missingParams.join('、')}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!this.selectedCategory || this.selectedCategory.length < 3) {
|
||||||
|
this.$Message.error("必须选择到三级分类");
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.submitLoading = true;
|
this.submitLoading = true;
|
||||||
this.$refs["baseInfoForm"].validate((valid) => {
|
this.$refs["baseInfoForm"].validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
@@ -2362,38 +2466,21 @@ export default {
|
|||||||
accessToken: this.getStore("accessToken"),
|
accessToken: this.getStore("accessToken"),
|
||||||
};
|
};
|
||||||
this.GET_ShipTemplate()
|
this.GET_ShipTemplate()
|
||||||
|
this.loadCategoryList();
|
||||||
if (this.$route.query.id || this.$route.query.draftId) {
|
if (this.$route.query.id || this.$route.query.draftId) {
|
||||||
// 编辑商品、模板
|
// 编辑商品、模板
|
||||||
this.GET_GoodData(this.$route.query.id, this.$route.query.draftId);
|
this.GET_GoodData(this.$route.query.id, this.$route.query.draftId);
|
||||||
} else if (this.$route.query.copyId) {
|
} else if (this.$route.query.copyId) {
|
||||||
// 复制商品
|
// 复制商品
|
||||||
this.GET_GoodData(this.$route.query.copyId);
|
this.GET_GoodData(this.$route.query.copyId);
|
||||||
} else {
|
} else if (this.firstData.tempId) {
|
||||||
// 新增商品、模板
|
|
||||||
if (this.firstData.tempId) {
|
|
||||||
// 选择模板
|
// 选择模板
|
||||||
this.GET_GoodData("", this.firstData.tempId);
|
this.GET_GoodData("", this.firstData.tempId);
|
||||||
} else {
|
} else {
|
||||||
const cateId = [];
|
// 新增商品
|
||||||
this.firstData.category.forEach((cate) => {
|
|
||||||
this.baseInfoForm.categoryName.push(cate.name);
|
|
||||||
cateId.push(cate.id);
|
|
||||||
});
|
|
||||||
this.categoryId = cateId[2];
|
|
||||||
this.baseInfoForm.categoryPath = cateId.toString();
|
|
||||||
this.baseInfoForm.goodsType = this.firstData.goodsType;
|
|
||||||
|
|
||||||
|
|
||||||
/** 获取该商城分类下 商品参数信息 */
|
|
||||||
this.GET_GoodsParams();
|
|
||||||
/** 查询品牌列表 */
|
|
||||||
this.getGoodsBrandList();
|
|
||||||
// 获取商品单位
|
|
||||||
this.GET_GoodsUnit();
|
this.GET_GoodsUnit();
|
||||||
// 获取当前店铺分类
|
|
||||||
this.GET_ShopGoodsLabel();
|
this.GET_ShopGoodsLabel();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -2505,4 +2592,58 @@ export default {
|
|||||||
.refresh-icon {
|
.refresh-icon {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-tip {
|
||||||
|
color: #666;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-top: 4px;
|
||||||
|
max-width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-type-option {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-type-option-label {
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-type-option-desc {
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="scss">
|
||||||
|
.goods-type-select-popper {
|
||||||
|
.el-select-dropdown__item {
|
||||||
|
height: auto;
|
||||||
|
min-height: 58px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-type-option {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-type-option-label {
|
||||||
|
color: #303133;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-type-option-desc {
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
<div class="content-goods-publish">
|
<div class="content-goods-publish">
|
||||||
<div class="success" style="text-align: left">
|
<div class="success" style="text-align: left">
|
||||||
<h1>恭喜您,商品发布成功!</h1>
|
<h1>恭喜您,商品发布成功!</h1>
|
||||||
<div class="goToGoodsList" @click="gotoGoodsList">
|
|
||||||
<a>去店铺查看商品列表>></a>
|
|
||||||
</div>
|
|
||||||
<div class="operation">
|
<div class="operation">
|
||||||
<h3>您还可以:</h3>
|
<h3>您还可以:</h3>
|
||||||
<div>
|
<div>
|
||||||
@@ -34,5 +31,17 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "./addGoods.scss";
|
@import "./addGoods.scss";
|
||||||
|
|
||||||
|
.success {
|
||||||
|
a {
|
||||||
|
color: #409eff;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #66b1ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -61,8 +61,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="wap-content-desc-bottom">
|
<div class="wap-content-desc-bottom">
|
||||||
<div>¥{{ $filters.unitPrice(item.price) }}</div>
|
<div>¥{{ $filters.unitPrice(item.price) }}</div>
|
||||||
<div v-if="item.goodsType === 'E_COUPON'" class="pool-stock-hint">
|
<div v-if="showStockHint(item)" class="stock-hint">
|
||||||
库存 {{ item.quantity != null ? item.quantity : "—" }}(卡池)
|
库存 {{ item.quantity != null ? item.quantity : "—" }}<template v-if="item.goodsType === 'E_COUPON'">(卡池)</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,6 +142,9 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
goodsTypeLabel,
|
goodsTypeLabel,
|
||||||
goodsTypeTagType,
|
goodsTypeTagType,
|
||||||
|
showStockHint(item) {
|
||||||
|
return ["PHYSICAL_GOODS", "VIRTUAL_GOODS", "E_COUPON"].includes(item.goodsType);
|
||||||
|
},
|
||||||
onSearchGoods() {
|
onSearchGoods() {
|
||||||
this.goodsData = [];
|
this.goodsData = [];
|
||||||
this.goodsParams.pageNumber = 1;
|
this.goodsParams.pageNumber = 1;
|
||||||
@@ -261,16 +264,41 @@ export default {
|
|||||||
position: relative;
|
position: relative;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
height: 340px;
|
height: 340px;
|
||||||
|
align-content: flex-start;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.wap-content-item {
|
.wap-content-item {
|
||||||
width: 210px;
|
position: relative;
|
||||||
|
width: calc((100% - 56px) / 4);
|
||||||
|
box-sizing: border-box;
|
||||||
margin: 10px 7px;
|
margin: 10px 7px;
|
||||||
padding: 6px 0;
|
padding: 6px 8px;
|
||||||
}
|
background: #fff;
|
||||||
.active {
|
border-radius: 4px;
|
||||||
background: url("../../assets/selected.png") no-repeat;
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
background-position: right;
|
min-width: 0;
|
||||||
background-size: 10%;
|
|
||||||
|
:deep(.wap-content-desc) {
|
||||||
|
width: auto;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background: url("../../assets/selected.png") no-repeat center / contain;
|
||||||
|
z-index: 2;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.loading-mask {
|
.loading-mask {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -280,10 +308,15 @@ export default {
|
|||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
.pool-stock-hint {
|
.wap-content-desc-bottom {
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.stock-hint {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #999;
|
color: #999;
|
||||||
margin-top: 4px;
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="flag"
|
v-model="flag"
|
||||||
width="1160px"
|
width="1200px"
|
||||||
top="120px"
|
top="120px"
|
||||||
:z-index="10000"
|
:z-index="10000"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
|
|||||||
@@ -257,7 +257,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 卡密信息(E_COUPON 主单或满赠子单,以 cardKeyFulfillStatus 为准) -->
|
<!-- 卡密信息(当前订单 orderItems;满赠赠品卡密在赠品子单详情查看) -->
|
||||||
<div v-if="hasCardKeySection" class="ecoupon-card-keys mt_10">
|
<div v-if="hasCardKeySection" class="ecoupon-card-keys mt_10">
|
||||||
<h4>卡密信息</h4>
|
<h4>卡密信息</h4>
|
||||||
<div
|
<div
|
||||||
@@ -265,9 +265,6 @@
|
|||||||
:key="line.key"
|
:key="line.key"
|
||||||
class="ecoupon-fulfill-block"
|
class="ecoupon-fulfill-block"
|
||||||
>
|
>
|
||||||
<div v-if="cardKeyFulfillLines.length > 1" class="ecoupon-fulfill-title mb_10">
|
|
||||||
{{ line.goodsName || (line.isGift ? "满赠电子卡券" : "电子卡券") }}
|
|
||||||
</div>
|
|
||||||
<el-alert
|
<el-alert
|
||||||
v-if="line.status !== 'DELIVERED'"
|
v-if="line.status !== 'DELIVERED'"
|
||||||
:type="cardKeyFulfillAlertType(line.status)"
|
:type="cardKeyFulfillAlertType(line.status)"
|
||||||
@@ -284,13 +281,6 @@
|
|||||||
class="mb_10"
|
class="mb_10"
|
||||||
>
|
>
|
||||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
<el-table-column
|
|
||||||
v-if="cardKeyFulfillLines.length > 1"
|
|
||||||
prop="goodsName"
|
|
||||||
label="商品"
|
|
||||||
min-width="140"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
<el-table-column prop="cardNo" label="卡号" min-width="140" show-overflow-tooltip />
|
<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="cardSecret" label="卡密" min-width="120" show-overflow-tooltip />
|
||||||
<el-table-column prop="allocatedTime" label="发卡时间" width="170" />
|
<el-table-column prop="allocatedTime" label="发卡时间" width="170" />
|
||||||
@@ -889,15 +879,14 @@ export default {
|
|||||||
hasCardKeySection() {
|
hasCardKeySection() {
|
||||||
return orderHasCardKeySection({
|
return orderHasCardKeySection({
|
||||||
orderItems: this.data,
|
orderItems: this.data,
|
||||||
giftSummaries: this.orderInfo.giftECouponOrders,
|
|
||||||
isECouponOrder: this.isECouponOrder,
|
isECouponOrder: this.isECouponOrder,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
cardKeyFulfillLines() {
|
cardKeyFulfillLines() {
|
||||||
return collectCardKeyFulfillLines(this.data, this.orderInfo.giftECouponOrders);
|
return collectCardKeyFulfillLines(this.data);
|
||||||
},
|
},
|
||||||
ecouponCardKeyRows() {
|
ecouponCardKeyRows() {
|
||||||
return flattenOrderCardKeys(this.data, true, this.orderInfo.giftECouponOrders);
|
return flattenOrderCardKeys(this.data, true);
|
||||||
},
|
},
|
||||||
canPartDelivery() {
|
canPartDelivery() {
|
||||||
if (!this.allowOperation.ship) return false;
|
if (!this.allowOperation.ship) return false;
|
||||||
@@ -934,10 +923,7 @@ export default {
|
|||||||
cardKeyFulfillAlertType,
|
cardKeyFulfillAlertType,
|
||||||
resolveCardKeyFulfillMessage,
|
resolveCardKeyFulfillMessage,
|
||||||
lineCardKeyRows(line) {
|
lineCardKeyRows(line) {
|
||||||
return (line.cardKeys || []).map((ck) => ({
|
return line.cardKeys || [];
|
||||||
...ck,
|
|
||||||
goodsName: line.goodsName,
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
copyCardKey(row) {
|
copyCardKey(row) {
|
||||||
const text = `卡号:${row.cardNo || ""}\n卡密:${row.cardSecret || ""}`;
|
const text = `卡号:${row.cardNo || ""}\n卡密:${row.cardSecret || ""}`;
|
||||||
|
|||||||
@@ -113,7 +113,7 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="form.giftFlag" label="赠品" prop="giftId">
|
<el-form-item v-if="form.giftFlag" label="赠品" prop="giftId">
|
||||||
<p class="describe">电子卡券赠品支付后自动发卡;卡池不足时仅取消赠品子单,不影响主订单。</p>
|
<div class="gift-field">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.giftId"
|
v-model="form.giftId"
|
||||||
filterable
|
filterable
|
||||||
@@ -131,6 +131,8 @@
|
|||||||
:label="giftOptionLabel(item)"
|
:label="giftOptionLabel(item)"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
<p class="describe describe-block">电子卡券赠品支付后自动发卡;卡池不足时仅取消赠品子单,不影响主订单。</p>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="form.pointFlag" label="赠积分" prop="point">
|
<el-form-item v-if="form.pointFlag" label="赠积分" prop="point">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -513,6 +515,17 @@ h4 {
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
.describe-block {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 4px;
|
||||||
|
line-height: 1.5;
|
||||||
|
max-width: 260px;
|
||||||
|
}
|
||||||
|
.gift-field {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
.link-text {
|
.link-text {
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
Reference in New Issue
Block a user