mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-07 17:38:55 +08:00
fix(goods): 修复商品发布校验失败后保存按钮一直处于loading的问题
This commit is contained in:
@@ -2374,8 +2374,15 @@ function changeSelect(v) {
|
|||||||
}
|
}
|
||||||
baseInfoForm.value.storeCategoryPath = ids;
|
baseInfoForm.value.storeCategoryPath = ids;
|
||||||
}
|
}
|
||||||
/** 添加商品 **/
|
/**
|
||||||
|
* 保存/发布商品
|
||||||
|
* 包含表单校验、业务逻辑预校验、SKU组装及接口提交全流程
|
||||||
|
*/
|
||||||
function save() {
|
function save() {
|
||||||
|
// 防重复提交:若当前已有请求处于 loading 状态,则直接拦截
|
||||||
|
if (submitLoading.value) return;
|
||||||
|
|
||||||
|
// 1. 规格项与规格值查重校验
|
||||||
if (containsSameSkuItem.value) {
|
if (containsSameSkuItem.value) {
|
||||||
jumpToTab("price");
|
jumpToTab("price");
|
||||||
Message.error("存在重复规格项!");
|
Message.error("存在重复规格项!");
|
||||||
@@ -2386,6 +2393,8 @@ function save() {
|
|||||||
Message.error("存在重复规格值!");
|
Message.error("存在重复规格值!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. 检查分类下的必填商品参数是否均已填写
|
||||||
let checkFlag = false;
|
let checkFlag = false;
|
||||||
let missingParams = [];
|
let missingParams = [];
|
||||||
goodsParams.value.forEach((param) => {
|
goodsParams.value.forEach((param) => {
|
||||||
@@ -2404,9 +2413,17 @@ function save() {
|
|||||||
Message.error(`以下参数为必填项:${missingParams.join('、')}`);
|
Message.error(`以下参数为必填项:${missingParams.join('、')}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
submitLoading.value = true;
|
|
||||||
baseInfoFormRef.value.validate((valid, fields) => {
|
// 3. 执行 el-form 表单校验(在校验未通过时不开启 loading,直接引导用户修改)
|
||||||
if (valid) {
|
baseInfoFormRef.value.validate(async (valid, fields) => {
|
||||||
|
try {
|
||||||
|
if (!valid) {
|
||||||
|
jumpToTab(tabForInvalidFields(fields));
|
||||||
|
Message.error("还有必填项未做处理,请检查表单");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 批发销售模式:校验并同步阶梯价格与数量
|
||||||
if (baseInfoForm.value.salesModel === "WHOLESALE") {
|
if (baseInfoForm.value.salesModel === "WHOLESALE") {
|
||||||
for (let i = 0; i < wholesaleData.value.length; i++) {
|
for (let i = 0; i < wholesaleData.value.length; i++) {
|
||||||
checkWholesaleNum(i);
|
checkWholesaleNum(i);
|
||||||
@@ -2416,46 +2433,52 @@ function save() {
|
|||||||
baseInfoForm.value.wholesaleList = wholesaleData.value;
|
baseInfoForm.value.wholesaleList = wholesaleData.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否是复制商品
|
// 判断是否是复制商品(复制商品时不复用原有 goodsId,重新生成)
|
||||||
if (!route.query.copyId) {
|
if (!route.query.copyId) {
|
||||||
baseInfoForm.value.goodsId = goodsId;
|
baseInfoForm.value.goodsId = goodsId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同步富文本编辑器内容至表单对象
|
||||||
syncIntroFromEditors();
|
syncIntroFromEditors();
|
||||||
let submit = JSON.parse(JSON.stringify(baseInfoForm.value));
|
let submit = JSON.parse(JSON.stringify(baseInfoForm.value));
|
||||||
|
|
||||||
|
// 5. 商品主图相册校验
|
||||||
if (
|
if (
|
||||||
submit.goodsGalleryFiles &&
|
submit.goodsGalleryFiles &&
|
||||||
submit.goodsGalleryFiles.length <= 0
|
submit.goodsGalleryFiles.length <= 0
|
||||||
) {
|
) {
|
||||||
submitLoading.value = false;
|
|
||||||
jumpToTab("specs");
|
jumpToTab("specs");
|
||||||
Message.error("请上传商品图片");
|
Message.error("请上传商品图片");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const invalidGalleryFiles = submit.goodsGalleryFiles.filter((url) =>
|
const invalidGalleryFiles = (submit.goodsGalleryFiles || []).filter((url) =>
|
||||||
invalidGoodsGalleryFiles.value.includes(url)
|
invalidGoodsGalleryFiles.value.includes(url)
|
||||||
);
|
);
|
||||||
if (invalidGalleryFiles.length > 0) {
|
if (invalidGalleryFiles.length > 0) {
|
||||||
submitLoading.value = false;
|
|
||||||
jumpToTab("specs");
|
jumpToTab("specs");
|
||||||
Message.error("存在已失效的商品主图,请删除后重新上传");
|
Message.error("存在已失效的商品主图,请删除后重新上传");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 兜底运费模板与品牌默认值
|
||||||
if (submit.templateId === "") submit.templateId = 0;
|
if (submit.templateId === "") submit.templateId = 0;
|
||||||
if (submit.brandId === "" || submit.brandId == null) submit.brandId = 0;
|
if (submit.brandId === "" || submit.brandId == null) submit.brandId = 0;
|
||||||
|
|
||||||
|
// 6. 电子卡券商品特殊参数处理
|
||||||
if (isECouponGoods.value) {
|
if (isECouponGoods.value) {
|
||||||
submit.templateId = 0;
|
submit.templateId = 0;
|
||||||
submit.salesModel = "RETAIL";
|
submit.salesModel = "RETAIL";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 7. 预约服务商品特殊参数与预约时段规则校验
|
||||||
if (isAppointmentGoods.value) {
|
if (isAppointmentGoods.value) {
|
||||||
submit.templateId = 0;
|
submit.templateId = 0;
|
||||||
submit.salesModel = "RETAIL";
|
submit.salesModel = "RETAIL";
|
||||||
if (!appointmentPanel.value?.validateRules()) {
|
if (!appointmentPanel.value?.validateRules()) {
|
||||||
submitLoading.value = false;
|
|
||||||
jumpToTab("appointment");
|
jumpToTab("appointment");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!appointmentPanel.value?.validateDivision()) {
|
if (!appointmentPanel.value?.validateDivision()) {
|
||||||
submitLoading.value = false;
|
|
||||||
jumpToTab("appointment");
|
jumpToTab("appointment");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2466,17 +2489,18 @@ function save() {
|
|||||||
|
|
||||||
if (flag) {
|
if (flag) {
|
||||||
Message.error(paramValue + " 参数值不能为空");
|
Message.error(paramValue + " 参数值不能为空");
|
||||||
submitLoading.value = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 8. 商品单位有效性检查
|
||||||
if (goodsUnitList.value && !goodsUnitList.value.find(i => i === baseInfoForm.value.goodsUnit)) {
|
if (goodsUnitList.value && !goodsUnitList.value.find(i => i === baseInfoForm.value.goodsUnit)) {
|
||||||
submit.goodsUnit = ""
|
submit.goodsUnit = "";
|
||||||
Message.error("商品单位不存在");
|
Message.error("商品单位不存在");
|
||||||
submitLoading.value = false;
|
|
||||||
jumpToTab("basic");
|
jumpToTab("basic");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 9. 组装 SKU 列表数据
|
||||||
let skuInfoNames = skuInfo.value.map((n) => n.name);
|
let skuInfoNames = skuInfo.value.map((n) => n.name);
|
||||||
submit.skuList = [];
|
submit.skuList = [];
|
||||||
let containEmptyImage = false;
|
let containEmptyImage = false;
|
||||||
@@ -2489,6 +2513,7 @@ function save() {
|
|||||||
sn: sku.sn,
|
sn: sku.sn,
|
||||||
images: [],
|
images: [],
|
||||||
};
|
};
|
||||||
|
// 若开启规格图片,将第1个规格项关联的图片注入对应 SKU
|
||||||
if (openImage.value) {
|
if (openImage.value) {
|
||||||
skuInfo.value[0].spec_values.forEach(item => {
|
skuInfo.value[0].spec_values.forEach(item => {
|
||||||
if (!item.images || item.images.length === 0) {
|
if (!item.images || item.images.length === 0) {
|
||||||
@@ -2496,10 +2521,9 @@ function save() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (item.value === sku[skuInfo.value[0].name]) {
|
if (item.value === sku[skuInfo.value[0].name]) {
|
||||||
skuCopy.images = item.images
|
skuCopy.images = item.images;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
if (sku.weight) {
|
if (sku.weight) {
|
||||||
skuCopy.weight = sku.weight;
|
skuCopy.weight = sku.weight;
|
||||||
@@ -2518,13 +2542,22 @@ function save() {
|
|||||||
}
|
}
|
||||||
submit.skuList.push(skuCopy);
|
submit.skuList.push(skuCopy);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 规格图片完整性校验
|
||||||
if (containEmptyImage) {
|
if (containEmptyImage) {
|
||||||
Message.error("开启规格图片,所有规格图片不能为空!");
|
Message.error("开启规格图片,所有规格图片不能为空!");
|
||||||
submitLoading.value = false;
|
|
||||||
jumpToTab("price");
|
jumpToTab("price");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (submit.goodsGalleryFiles.length > 0) {
|
|
||||||
|
// 10. 前置校验:商品规格必须至少包含一个(避免向后端提交空 SKU 列表导致 400 校验失败)
|
||||||
|
if (!submit.skuList || submit.skuList.length === 0) {
|
||||||
|
jumpToTab("price");
|
||||||
|
Message.error("规格必须要有一个!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (submit.goodsGalleryFiles && submit.goodsGalleryFiles.length > 0) {
|
||||||
submit.goodsGalleryList = submit.goodsGalleryFiles.map(
|
submit.goodsGalleryList = submit.goodsGalleryFiles.map(
|
||||||
(i) => i
|
(i) => i
|
||||||
);
|
);
|
||||||
@@ -2536,34 +2569,35 @@ function save() {
|
|||||||
submit.recommend
|
submit.recommend
|
||||||
? (submit.recommend = true)
|
? (submit.recommend = true)
|
||||||
: (submit.recommend = false);
|
: (submit.recommend = false);
|
||||||
// 判断是否是复制商品
|
|
||||||
if (goodsId && !route.query.copyId) {
|
// 11. 前端所有校验均通过,正式发起网络请求并激活保存按钮 loading
|
||||||
API_GOODS.editGoods(goodsId, submit).then((res) => {
|
submitLoading.value = true;
|
||||||
if (res.success) {
|
try {
|
||||||
submitLoading.value = false;
|
if (goodsId && !route.query.copyId) {
|
||||||
|
// 编辑商品
|
||||||
|
const res = await API_GOODS.editGoods(goodsId, submit);
|
||||||
|
if (res && res.success) {
|
||||||
router.go(-1);
|
router.go(-1);
|
||||||
} else {
|
|
||||||
submitLoading.value = false;
|
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
} else {
|
||||||
submitLoading.value = false;
|
// 新增商品 / 复制商品
|
||||||
Message.error("保存失败,请重试");
|
const res = await API_GOODS.createGoods(submit);
|
||||||
});
|
if (res && res.success) {
|
||||||
} else {
|
|
||||||
API_GOODS.createGoods(submit).then((res) => {
|
|
||||||
if (res.success) {
|
|
||||||
submitLoading.value = false;
|
|
||||||
proxy.$parent.activestep = 2;
|
proxy.$parent.activestep = 2;
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
} else {
|
|
||||||
submitLoading.value = false;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// 请求失败时,Axios 响应拦截器已统一弹出错误提示(如业务校验 400 报错)
|
||||||
|
console.error("保存商品请求异常:", err);
|
||||||
|
} finally {
|
||||||
|
// 关键兜底:无论成功、业务失败、网络超时还是接口报错,确保复位 submitLoading,防止按钮卡死
|
||||||
|
submitLoading.value = false;
|
||||||
}
|
}
|
||||||
} else {
|
} catch (e) {
|
||||||
|
// 捕获表单数据组装阶段可能的意外异常,确保 loading 状态准确复位
|
||||||
submitLoading.value = false;
|
submitLoading.value = false;
|
||||||
jumpToTab(tabForInvalidFields(fields));
|
console.error("表单处理异常:", e);
|
||||||
Message.error("还有必填项未做处理,请检查表单");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user