diff --git a/src/api/oa/crm/crmQuoteInfo/types.ts b/src/api/oa/crm/crmQuoteInfo/types.ts
index b85bf92..5f1bcb6 100644
--- a/src/api/oa/crm/crmQuoteInfo/types.ts
+++ b/src/api/oa/crm/crmQuoteInfo/types.ts
@@ -130,7 +130,7 @@ export interface CrmQuoteInfoVO {
customerContactEmail: string;
/**
- * 供货方联系人ID
+ * 供货方ID
*/
supplierContactId: string | number;
@@ -174,6 +174,11 @@ export interface CrmQuoteInfoVO {
*/
flowStatus: string;
+ /**
+ * 供应商名称
+ */
+ supplierName: string;
+
/**
* 备注
*/
@@ -318,7 +323,7 @@ export interface CrmQuoteInfoForm extends BaseEntity {
customerContactEmail?: string;
/**
- * 供货方联系人ID
+ * 供货方ID
*/
supplierContactId?: string | number;
@@ -372,6 +377,11 @@ export interface CrmQuoteInfoForm extends BaseEntity {
*/
itemsBo?: CrmQuoteMaterialForm[];
+ /**
+ * 供应商名称
+ */
+ supplierName?: string;
+
}
export interface CrmQuoteInfoQuery extends PageQuery {
@@ -502,7 +512,7 @@ export interface CrmQuoteInfoQuery extends PageQuery {
customerContactEmail?: string;
/**
- * 供货方联系人ID
+ * 供货方ID
*/
supplierContactId?: string | number;
@@ -550,6 +560,12 @@ export interface CrmQuoteInfoQuery extends PageQuery {
* 日期范围参数
*/
params?: any;
+
+ /**
+ * 供应商名称
+ */
+ supplierName?: string;
+
}
diff --git a/src/api/oa/crm/crmSupplierInfo/types.ts b/src/api/oa/crm/crmSupplierInfo/types.ts
index 1d0f481..7c58139 100644
--- a/src/api/oa/crm/crmSupplierInfo/types.ts
+++ b/src/api/oa/crm/crmSupplierInfo/types.ts
@@ -267,6 +267,11 @@ export interface CrmSupplierInfoForm extends BaseEntity {
*/
activeFlag?: string;
+ /**
+ * 归属人员名称
+ */
+ ownerName?: string;
+
}
export interface CrmSupplierInfoQuery extends PageQuery {
@@ -395,6 +400,11 @@ export interface CrmSupplierInfoQuery extends PageQuery {
* 日期范围参数
*/
params?: any;
+
+ /**
+ * 归属人员名称
+ */
+ ownerName?: string;
}
diff --git a/src/views/oa/crm/crmQuoteInfo/edit.vue b/src/views/oa/crm/crmQuoteInfo/edit.vue
index 40183b9..24e7817 100644
--- a/src/views/oa/crm/crmQuoteInfo/edit.vue
+++ b/src/views/oa/crm/crmQuoteInfo/edit.vue
@@ -6,7 +6,7 @@
添加报价单基本信息
-
+
@@ -15,7 +15,7 @@
-
+
@@ -45,54 +45,50 @@
-->
-
+
-
-
+
-
+
-
-
+
-
+
-
-
+
-
+
-
-
+
-
+
@@ -146,6 +142,81 @@
+
+
+
+
+
+
+
+ {{ dict.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -182,12 +253,25 @@
-
-
-
+
+
+ 计划内
+ 计划外
+
+
+
+
+
+
+
+
+
+
+
+
@@ -241,61 +325,44 @@
报价明细表格
- 新增物料
+ 新增物料
-
- {{ scope.$index + 1 }}
-
-
+
+
+
+
+
-
-
-
+ {{ scope.row.amount ? Number(scope.row.amount).toFixed(2) : '0.00' }}
-
+
+
-
+ {{ scope.row.beforePrice ? Number(scope.row.beforePrice).toFixed(2) : '0.00' }}
-
+
- onAmountChange(scope.row,val)" />
+ {{ scope.row.taxRate ? Number(scope.row.taxRate).toFixed(2) : '0.00' }}
-
+
- onBeforePriceChange(scope.row,val)" />
+ {{ scope.row.includingPrice ? Number(scope.row.includingPrice).toFixed(2) : '0.00' }}
-
+
- onTaxRateChange(scope.row,val)" />
+ {{ scope.row.subtotal ? Number(scope.row.subtotal).toFixed(2) : '0.00' }}
-
+
+
- onIncludingPriceChange(scope.row,val)" />
-
-
-
-
- {{ (scope.row.subtotal ?? 0).toFixed(2) }}
-
-
-
-
-
-
-
-
-
- 删除
+ 编辑
+ 删除
@@ -331,10 +398,13 @@ import { CrmQuoteInfoForm } from '@/api/oa/crm/crmQuoteInfo/types';
import type { CrmQuoteMaterialForm } from '@/api/oa/crm/crmQuoteMaterial/types';
import { getBaseMaterialInfoList } from '@/api/oa/base/materialInfo';
import { getCrmCustomerContactList } from '@/api/oa/crm/customerContact';
+import { getCrmSupplierInfoList } from '@/api/oa/crm/crmSupplierInfo';
import { getRuleGenerateCode } from '@/api/system/codeRule';
+import { getBaseUnitInfoList } from '@/api/oa/base/unitInfo';
+import SaleMaterialSelect from '@/components/SaleMaterialSelect/index.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { business_direction, currency_type, quote_category, contract_type } = toRefs(proxy?.useDict('business_direction', 'currency_type', 'quote_category', 'contract_type'));
+const { business_direction, currency_type, quote_category, contract_type, plan_flag } = toRefs(proxy?.useDict('business_direction', 'currency_type', 'quote_category', 'contract_type', 'plan_flag'));
const router = useRouter();
const route = useRoute();
@@ -382,7 +452,118 @@ const rules = {
// 下拉数据
const materialList = ref([]);
const customerContactList = ref([]);
-const supplierContactList = ref([]);
+const supplierList = ref([]);
+// 供应商计划标识:1计划内,2计划外
+const supplierPlanFlag = ref('1');
+
+// 单位下拉数据
+const unitInfoList = ref([]);
+const getUnitInfoListSelect = async () => {
+ const res = await getBaseUnitInfoList(null);
+ unitInfoList.value = res.data || [];
+};
+
+// 物料编辑弹窗与表单
+const materialDialog = reactive({ visible: false, title: '' });
+const materialFormRef = ref();
+const initMaterialFormData: CrmQuoteMaterialForm & { planFlag?: string } = {
+ quoteMaterialId: undefined,
+ planFlag: '2', // 1计划内,2计划外
+ quoteId: undefined,
+ productName: undefined,
+ specificationDescription: undefined,
+ materialId: undefined,
+ relationMaterialId: undefined,
+ amount: undefined,
+ unitId: undefined,
+ unitName: undefined,
+ beforePrice: undefined,
+ taxRate: undefined,
+ includingPrice: undefined,
+ subtotal: undefined,
+ remark: undefined,
+ activeFlag: '1'
+};
+const materialForm = ref({ ...initMaterialFormData });
+const materialRules = {
+ productName: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }],
+ amount: [{ required: true, message: '数量不能为空', trigger: 'blur' }],
+ taxRate: [{ required: true, message: '税率不能为空', trigger: 'blur' }]
+};
+const saleMaterialSelectRef = ref>();
+const openSaleMaterialSelect = () => saleMaterialSelectRef.value?.open();
+const saleMaterialSelectCallBack = (data: any) => {
+ const list = data || [];
+ if (list.length) {
+ const m = list[0];
+ materialForm.value.materialId = m.materialId;
+ materialForm.value.relationMaterialId = m.relationMaterialId;
+ materialForm.value.productName = m.saleMaterialName || m.materialName;
+ if (m.unitName) materialForm.value.unitName = m.unitName;
+ }
+};
+const resetMaterialForm = () => {
+ materialForm.value = { ...initMaterialFormData };
+ materialFormRef.value?.resetFields();
+};
+const cancelMaterial = () => {
+ resetMaterialForm();
+ materialDialog.visible = false;
+};
+const calculateBeforePrice = () => {
+ const tax = Number(materialForm.value.taxRate);
+ const including = Number(materialForm.value.includingPrice);
+ if (!isNaN(tax) && !isNaN(including)) {
+ const divisor = 1 + tax / 100;
+ if (divisor > 0) {
+ materialForm.value.beforePrice = Number((including / divisor).toFixed(2));
+ }
+ }
+ calculateSubtotal();
+};
+const calculateSubtotal = () => {
+ const amount = Number(materialForm.value.amount);
+ const including = Number(materialForm.value.includingPrice);
+ if (!isNaN(amount) && !isNaN(including)) {
+ materialForm.value.subtotal = Number((amount * including).toFixed(2));
+ }
+};
+const handleAddMaterial = () => {
+ resetMaterialForm();
+ materialForm.value.quoteId = form.quoteId as any;
+ materialDialog.visible = true;
+ materialDialog.title = '新增报价物料';
+};
+const handleEditMaterial = (row: CrmQuoteMaterialForm) => {
+ resetMaterialForm();
+ materialForm.value = { ...(row as any), planFlag: (row as any).materialId ? '1' : '2' };
+ materialDialog.visible = true;
+ materialDialog.title = '编辑报价物料';
+};
+const handleDeleteMaterial = async (row: CrmQuoteMaterialForm) => {
+ await proxy?.$modal.confirm('是否确认删除该报价物料?');
+ const idx = materialRows.value.findIndex((x: any) => x.quoteMaterialId === (row as any).quoteMaterialId);
+ if (idx !== -1) materialRows.value.splice(idx, 1);
+ else {
+ const i2 = materialRows.value.indexOf(row);
+ if (i2 !== -1) materialRows.value.splice(i2, 1);
+ }
+ proxy?.$modal.msgSuccess('删除成功');
+};
+const submitMaterialForm = () => {
+ materialFormRef.value?.validate((valid: boolean) => {
+ if (!valid) return;
+ if ((materialForm.value as any).quoteMaterialId) {
+ const idx = materialRows.value.findIndex((x: any) => x.quoteMaterialId === (materialForm.value as any).quoteMaterialId);
+ if (idx !== -1) materialRows.value[idx] = { ...materialForm.value } as any;
+ } else {
+ const newItem = { ...materialForm.value, quoteMaterialId: Date.now() } as any;
+ materialRows.value.push(newItem);
+ }
+ proxy?.$modal.msgSuccess('操作成功');
+ materialDialog.visible = false;
+ });
+};
// 物料行
const materialRows = ref([]);
@@ -409,7 +590,20 @@ const getSummary = (param: any) => {
};
const addMaterialRow = () => {
- materialRows.value.push({ amount: 0, beforePrice: 0, taxRate: Number(form.taxRate || 0), includingPrice: 0, subtotal: 0 } as CrmQuoteMaterialForm);
+ // 默认支持非标:预留自填名称与规格;单位可手填
+ materialRows.value.push({
+ materialId: undefined,
+ unitId: undefined,
+ unitName: '',
+ productName: '',
+ specificationDescription: '',
+ amount: 0,
+ beforePrice: 0,
+ taxRate: Number(form.taxRate || 0),
+ includingPrice: 0,
+ subtotal: 0,
+ remark: ''
+ } as CrmQuoteMaterialForm);
};
const removeRow = (idx: number) => materialRows.value.splice(idx, 1);
// 工具:数值化与保留两位小数
@@ -477,14 +671,32 @@ const onCustomerContactChanged = (id: any) => {
form.customerContactPhone = c?.phoneNumber || '';
form.customerContactEmail = c?.email || '';
};
-const onSupplierContactChanged = (id: any) => {
- const c = supplierContactList.value.find((x: any) => x.contactId === id);
- form.supplierContactName = c?.contactName || '';
- form.supplierContactPhone = c?.phoneNumber || '';
- form.supplierContactEmail = c?.email || '';
+// 供应商计划标识变化处理
+const onSupplierPlanFlagChanged = (flag: string) => {
+ supplierPlanFlag.value = flag;
+ // 切换计划标识时清空供应商选择
+ form.supplierContactId = undefined;
+ form.supplierContactName = '';
+ form.supplierContactPhone = '';
+ form.supplierContactEmail = '';
+};
+// 供应商选择变化处理(计划内供应商)
+const onSupplierChanged = (supplierId: any) => {
+ const supplier = supplierList.value.find((x: any) => x.supplierId === supplierId);
+ if (supplier) {
+ // 从供应商信息中带出联系人、电话、邮箱(可编辑)
+ form.supplierContactName = supplier.contactPerson || '';
+ form.supplierContactPhone = supplier.contactPhone || supplier.contactMobile || '';
+ form.supplierContactEmail = supplier.contactEmail || '';
+ }
};
const onMaterialChange = (row: any) => {
- // 可扩展:根据选中物料带出单位等
+ // 根据选中物料带出单位与名称(若有),提升录入效率
+ const m = materialList.value.find((x: any) => x.materialId === row.materialId);
+ if (m) {
+ if (m.unitName) row.unitName = m.unitName;
+ if (!row.productName && m.materialName) row.productName = m.materialName;
+ }
};
// 生成报价单编号(codeRuleCode=1004)
@@ -553,7 +765,10 @@ onMounted(async () => {
materialList.value = materialRes.data || [];
const contactRes = await getCrmCustomerContactList({});
customerContactList.value = contactRes.data || [];
- supplierContactList.value = contactRes.data || [];
+ // 加载供应商列表(计划内供应商)
+ const supplierRes = await getCrmSupplierInfoList({});
+ supplierList.value = supplierRes.data || [];
+ await getUnitInfoListSelect();
// 编辑场景
const id = route.query.id || route.params.id;
@@ -569,8 +784,19 @@ onMounted(async () => {
if (!form.customerContactPhone || !form.customerContactEmail || !form.customerContactName) {
onCustomerContactChanged(form.customerContactId);
}
- if (!form.supplierContactPhone || !form.supplierContactEmail || !form.supplierContactName) {
- onSupplierContactChanged(form.supplierContactId);
+ // 供应商信息回填:判断是否为计划内供应商
+ if (form.supplierContactId) {
+ const supplier = supplierList.value.find((x: any) => x.supplierId === form.supplierContactId);
+ if (supplier) {
+ // 计划内供应商
+ supplierPlanFlag.value = '1';
+ if (!form.supplierContactPhone || !form.supplierContactEmail || !form.supplierContactName) {
+ onSupplierChanged(form.supplierContactId);
+ }
+ } else {
+ // 计划外供应商
+ supplierPlanFlag.value = '2';
+ }
}
// 仅使用后端VO内联返回的 itemsVo,前端不再单独请求子表接口
const inlineItems = (res.data as any)?.itemsVo;
@@ -581,8 +807,11 @@ onMounted(async () => {
quoteId: r.quoteId,
itemNo: r.itemNo,
materialId: r.materialId,
+ relationMaterialId: r.relationMaterialId,
unitId: r.unitId,
unitName: r.unitName,
+ productName: r.productName,
+ specificationDescription: r.specificationDescription,
amount: Number(r.amount ?? 0),
beforePrice: Number(r.beforePrice ?? 0),
taxRate: Number(r.taxRate ?? (form.taxRate ?? 0)),
diff --git a/src/views/oa/crm/crmQuoteInfo/index.vue b/src/views/oa/crm/crmQuoteInfo/index.vue
index de0bea8..19535b7 100644
--- a/src/views/oa/crm/crmQuoteInfo/index.vue
+++ b/src/views/oa/crm/crmQuoteInfo/index.vue
@@ -104,8 +104,8 @@
-
-
+
+
@@ -159,6 +159,9 @@
导出
+
+ 模板导出
+
@@ -223,7 +226,7 @@
-
+
@@ -255,6 +258,9 @@
+
+
+
@@ -388,8 +394,8 @@
-
-
+
+
@@ -445,9 +451,11 @@