批量优化产品和产品分类
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
:title="isEdit ? '编辑项目' : '新增项目'"
|
||||
width="760px"
|
||||
width="960px"
|
||||
:close-on-click-modal="false"
|
||||
@update:model-value="handleClose"
|
||||
@opened="handleOpened"
|
||||
@@ -98,6 +98,13 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<!-- <el-divider content-position="left">
|
||||
产品清单
|
||||
<span class="tip">保存项目时,产品参数将自动写入「产品管理」</span>
|
||||
</el-divider>
|
||||
<ProductList :products="form.products" /> -->
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">保存</el-button>
|
||||
@@ -109,10 +116,12 @@
|
||||
import { ref, reactive, watch } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { createProject, updateProject } from "@/api/crmPipeline";
|
||||
import { getProductList } from "@/api/crmProduct";
|
||||
import { getCrmCustomerList } from "@/api/crm";
|
||||
import { getAllUsers } from "@/api/user";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { PROJECT_STATUS_OPTIONS } from "../../dict";
|
||||
import ProductList from "../../contract/components/ProductList.vue";
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
@@ -146,10 +155,58 @@ const defaultForm = () => ({
|
||||
contact_phone: "",
|
||||
address: "",
|
||||
remark: "",
|
||||
products: [],
|
||||
});
|
||||
|
||||
const form = reactive(defaultForm());
|
||||
|
||||
/** 解析项目产品清单:兼容 JSON 字符串 / 数组 / 空,并补全行内 __key(el-table 的 row-key) */
|
||||
function parseProducts(val) {
|
||||
let arr = [];
|
||||
if (Array.isArray(val)) {
|
||||
arr = val;
|
||||
} else if (typeof val === "string" && val.trim()) {
|
||||
try {
|
||||
const parsed = JSON.parse(val);
|
||||
if (Array.isArray(parsed)) arr = parsed;
|
||||
} catch {
|
||||
arr = [];
|
||||
}
|
||||
}
|
||||
// 缺失 __key 时多行会被当作同一行,导致回显不出来
|
||||
return arr.map((r, i) => ({
|
||||
...r,
|
||||
__key: r && r.__key ? r.__key : `row_${i}_${Date.now()}`,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 兜底回显:存量项目 / 商机转化项目的 products 可能从未写入(null 或空串),
|
||||
* 此时从「产品管理」回查归属本项目的产品,保证编辑时能看到产品清单。
|
||||
*/
|
||||
async function loadProjectProducts(projectId) {
|
||||
try {
|
||||
// 后端 pageSize 上限为 100
|
||||
const res = await getProductList({ project_id: projectId, page: 1, pageSize: 100 });
|
||||
const list = res?.data?.list || [];
|
||||
form.products = list.map((p, i) => ({
|
||||
__key: `row_p${p.id}_${i}`,
|
||||
name: p.product_name || "",
|
||||
product_id: p.id,
|
||||
category: p.category || "",
|
||||
spec: p.spec || "",
|
||||
unit: p.unit || "",
|
||||
quantity: 1,
|
||||
price: Number(p.price) || 0,
|
||||
cost_price: Number(p.cost_price) || 0,
|
||||
tax_rate: Number(p.tax_rate) || 0,
|
||||
remark: p.remark || "",
|
||||
}));
|
||||
} catch (e) {
|
||||
form.products = [];
|
||||
}
|
||||
}
|
||||
|
||||
const rules = {
|
||||
project_name: [{ required: true, message: "请输入项目名称", trigger: "blur" }],
|
||||
};
|
||||
@@ -163,6 +220,15 @@ watch(
|
||||
internalId.value = props.editData.id;
|
||||
Object.assign(form, defaultForm(), props.editData);
|
||||
form.status = Number(props.editData.status) || 1;
|
||||
// 解析项目已关联的产品清单(后端返回 JSON 字符串)
|
||||
const rawProducts = props.editData.products;
|
||||
form.products = parseProducts(rawProducts);
|
||||
// 从未写入过产品清单(null / 空串,而非 "[]")时,从产品管理回查兜底回显
|
||||
const neverSet =
|
||||
rawProducts === null || rawProducts === undefined || String(rawProducts).trim() === "";
|
||||
if (neverSet && form.products.length === 0 && props.editData.id) {
|
||||
loadProjectProducts(props.editData.id);
|
||||
}
|
||||
} else {
|
||||
isEdit.value = false;
|
||||
internalId.value = null;
|
||||
@@ -220,7 +286,7 @@ async function handleSubmit() {
|
||||
if (owner) form.owner_user_name = owner.name;
|
||||
submitting.value = true;
|
||||
try {
|
||||
const payload = { ...form, amount: Number(form.amount) || 0 };
|
||||
const payload = { ...form, amount: Number(form.amount) || 0, products: JSON.stringify(form.products || []) };
|
||||
if (internalId.value) {
|
||||
await updateProject(internalId.value, payload);
|
||||
ElMessage.success("更新成功");
|
||||
@@ -237,3 +303,11 @@ async function handleSubmit() {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user