feat(oa/crm): 优化报价单编辑与供应商管理功能

- 新增报价物料编辑对话框,支持计划内外物料管理
- 选择 引入销售物料组件,提升物料录入效率
- 优化供应商管理页面,调整注册资本为数字输入框
- 在供应商列表中显示创建人与创建时间字段
- 重构供应商信息选择逻辑,区分计划内外供应商

- 调整报价单基础信息表单布局,将单列改为双列展示
- 优化报价明细表格展示,增加规格描述与物料ID字段
- 更新供货方联系人信息绑定逻辑,支持手动填写
- 增加报价单模板导出功能,支持选中记录导出
- 补充完善相关类型定义,增加supplierName与ownerName字段
dev
zangch@mesnac.com 1 month ago
parent 070d61f490
commit a5a0039c1c

@ -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;
}

@ -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;
}

@ -6,7 +6,7 @@
<div style="margin-bottom: 12px; text-align: center; font-weight: bold; font-size: 18px">添加报价单基本信息</div>
<div class="basic-center">
<el-row :gutter="20">
<el-col :span="24">
<el-col :span="12">
<el-form-item label="报价单编号" prop="quoteCode">
<el-input v-model="form.quoteCode" placeholder="自动生成">
<template #append>
@ -15,7 +15,7 @@
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="报价单名称" prop="quoteName">
<el-input v-model="form.quoteName" placeholder="请输入报价单名称" />
</el-form-item>
@ -45,54 +45,50 @@
</el-form-item>
</el-col>
-->
<el-col :span="24">
<el-col :span="12">
<el-form-item label="报价日期" prop="quoteDate">
<el-date-picker clearable v-model="form.quoteDate" type="date" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择报价日期" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="有效期起" prop="validFrom">
<el-date-picker clearable v-model="form.validFrom" type="date" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择有效期起" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="有效期止" prop="validTo">
<el-date-picker clearable v-model="form.validTo" type="date" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择有效期止" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="交货期(天)" prop="deliveryPeriod">
<!-- 使用数字输入框禁用随表单统一控制 -->
<el-input-number v-model="form.deliveryPeriod" :min="0" :precision="0" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="交货方式" prop="deliveryMethod">
<el-input v-model="form.deliveryMethod" placeholder="请输入交货方式" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="付款方式" prop="paymentMethod">
<el-input v-model="form.paymentMethod" placeholder="请输入付款方式" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="币种" prop="currencyType">
<el-select v-model="form.currencyType" placeholder="请选择币种">
<el-option v-for="dict in currency_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="含税信息" prop="taxIncludedInfo">
<el-input v-model="form.taxIncludedInfo" placeholder="如含13%增值税" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-col :span="12">
<el-form-item label="税率(%)" prop="taxRate">
<!-- 使用数字输入框两位小数步长0.01 -->
<el-input-number v-model="form.taxRate" :min="0" :precision="2" :step="0.01" style="width: 100%" />
@ -146,6 +142,81 @@
</el-row>
</div>
</el-card>
<!-- 报价物料编辑对话框 -->
<el-dialog :title="materialDialog.title" v-model="materialDialog.visible" width="800px" append-to-body>
<el-form ref="materialFormRef" :model="materialForm" :rules="materialRules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="计划标识" prop="planFlag">
<el-radio-group v-model="materialForm.planFlag">
<el-radio v-for="dict in plan_flag" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="产品名称" prop="productName">
<el-input v-model="materialForm.productName" placeholder="请输入产品名称">
<template #suffix>
<el-icon style="cursor: pointer" v-if="materialForm.planFlag === '1'" @click="openSaleMaterialSelect">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="规格描述" prop="specificationDescription">
<el-input v-model="materialForm.specificationDescription" placeholder="请输入规格描述" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="数量" prop="amount">
<el-input-number v-model="materialForm.amount" placeholder="请输入数量" style="width: 100%" @change="calculateSubtotal" :precision="2" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料单位" prop="unitId">
<el-select v-model="materialForm.unitId" placeholder="请选择物料单位">
<el-option v-for="item in unitInfoList" :key="item.unitId" :label="item.unitName" :value="item.unitId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="税率(%)" prop="taxRate">
<el-input-number v-model="materialForm.taxRate" placeholder="请输入税率" style="width: 100%" @change="calculateBeforePrice" :precision="2" :min="0" :max="100" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="未税单价" prop="beforePrice">
<el-input-number v-model="materialForm.beforePrice" placeholder="自动计算" style="width: 100%" :precision="2" :controls="false" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="含税单价" prop="includingPrice">
<el-input-number v-model="materialForm.includingPrice" placeholder="请输入含税单价" style="width: 100%" :precision="2" @change="calculateBeforePrice" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="小计" prop="subtotal">
<el-input-number v-model="materialForm.subtotal" placeholder="自动计算" style="width: 100%" readonly :precision="2" :controls="false" disabled />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="materialForm.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitMaterialForm"> </el-button>
<el-button @click="cancelMaterial"> </el-button>
</div>
</template>
</el-dialog>
<!-- 销售物料选择 -->
<SaleMaterialSelect ref="saleMaterialSelectRef" :multiple="false" @confirm-call-back="saleMaterialSelectCallBack" />
<!-- 客户方/供货方信息左右并列对称布局 -->
<el-row :gutter="20" style="margin-top: 20px">
@ -182,12 +253,25 @@
</template>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="供货方联系人" prop="supplierContactId">
<el-select v-model="form.supplierContactId" filterable placeholder="请选择供货方联系人" @change="onSupplierContactChanged">
<el-option v-for="c in supplierContactList" :key="c.contactId" :label="c.contactName + ' - ' + (c.phoneNumber||'')" :value="c.contactId" />
<el-form-item label="计划标识" prop="supplierPlanFlag">
<el-radio-group v-model="supplierPlanFlag" @change="onSupplierPlanFlagChanged">
<el-radio value="1">计划内</el-radio>
<el-radio value="2">计划外</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="supplierPlanFlag === '1'">
<el-form-item label="供应商" prop="supplierContactId">
<el-select v-model="form.supplierContactId" filterable placeholder="请选择供应商" @change="onSupplierChanged">
<el-option v-for="s in supplierList" :key="s.supplierId" :label="s.supplierName" :value="s.supplierId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="供货方联系人" prop="supplierContactName">
<el-input v-model="form.supplierContactName" placeholder="供货方联系人" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="供货方联系电话" prop="supplierContactPhone">
<el-input v-model="form.supplierContactPhone" placeholder="供货方联系电话" />
@ -241,61 +325,44 @@
<div style="text-align: left; font-weight: bold; font-size: 18px">报价明细表格</div>
</template>
<div style="margin-bottom: 12px">
<el-button type="primary" icon="Plus" @click="addMaterialRow" :disabled="isView">新增物料</el-button>
<el-button type="primary" icon="Plus" @click="handleAddMaterial" :disabled="isView">新增物料</el-button>
</div>
<el-table :data="materialRows" border show-summary :summary-method="getSummary">
<el-table-column label="序号" width="80" align="center">
<template #default="scope">{{ scope.$index + 1 }}</template>
</el-table-column>
<el-table-column label="产品名称" min-width="160" align="center">
<el-table-column label="产品名称" align="center" prop="productName" min-width="160" />
<el-table-column label="规格描述" align="center" prop="specificationDescription" min-width="160" />
<el-table-column label="物料ID" align="center" prop="materialId" width="120" />
<el-table-column label="销售物料ID" align="center" prop="relationMaterialId" width="140" />
<el-table-column label="数量" align="center" prop="amount" width="120">
<template #default="scope">
<el-select v-model="scope.row.materialId" filterable placeholder="选择SAP物料" style="width: 100%" @change="onMaterialChange(scope.row)" :disabled="isView">
<el-option v-for="m in materialList" :key="m.materialId" :label="m.materialName" :value="m.materialId" />
</el-select>
{{ scope.row.amount ? Number(scope.row.amount).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="单位" width="120" align="center">
<el-table-column label="单位ID" align="center" prop="unitId" width="120" />
<el-table-column label="未税单价" align="center" prop="beforePrice" width="140">
<template #default="scope">
<el-input v-model="scope.row.unitName" placeholder="单位" :disabled="isView" />
{{ scope.row.beforePrice ? Number(scope.row.beforePrice).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="数量" width="160" align="center">
<el-table-column label="税率(%)" align="center" prop="taxRate" width="120">
<template #default="scope">
<el-input-number v-model="scope.row.amount" :min="0" :precision="2" style="width: 100%" :disabled="isView"
@update:modelValue="(val:any)=>onAmountChange(scope.row,val)" />
{{ scope.row.taxRate ? Number(scope.row.taxRate).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="未税单价" width="180" align="center">
<el-table-column label="含税单价" align="center" prop="includingPrice" width="140">
<template #default="scope">
<el-input-number v-model="scope.row.beforePrice" :min="0" :precision="2" style="width: 100%" :disabled="isView"
@update:modelValue="(val:any)=>onBeforePriceChange(scope.row,val)" />
{{ scope.row.includingPrice ? Number(scope.row.includingPrice).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="税率(%)" width="160" align="center">
<el-table-column label="小计" align="center" prop="subtotal" width="140">
<template #default="scope">
<el-input-number v-model="scope.row.taxRate" :min="0" :precision="2" style="width: 100%" :disabled="isView"
@update:modelValue="(val:any)=>onTaxRateChange(scope.row,val)" />
{{ scope.row.subtotal ? Number(scope.row.subtotal).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="含税单价" width="180" align="center">
<el-table-column label="备注" align="center" prop="remark" min-width="140" />
<el-table-column label="操作" align="center" fixed="right" width="150" v-if="!isView">
<template #default="scope">
<el-input-number v-model="scope.row.includingPrice" :min="0" :precision="2" style="width: 100%" :disabled="isView"
@update:modelValue="(val:any)=>onIncludingPriceChange(scope.row,val)" />
</template>
</el-table-column>
<el-table-column label="小计" width="140" align="center">
<template #default="scope">
{{ (scope.row.subtotal ?? 0).toFixed(2) }}
</template>
</el-table-column>
<el-table-column label="备注" min-width="160" align="center">
<template #default="scope">
<el-input v-model="scope.row.remark" :disabled="isView" />
</template>
</el-table-column>
<el-table-column label="操作" width="120" align="center">
<template #default="scope">
<el-button v-if="!isView" link type="danger" icon="Delete" @click="removeRow(scope.$index)"></el-button>
<el-button link type="primary" icon="Edit" @click="handleEditMaterial(scope.row)"></el-button>
<el-button link type="danger" icon="Delete" @click="handleDeleteMaterial(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
@ -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<any>(proxy?.useDict('business_direction', 'currency_type', 'quote_category', 'contract_type'));
const { business_direction, currency_type, quote_category, contract_type, plan_flag } = toRefs<any>(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<any[]>([]);
const customerContactList = ref<any[]>([]);
const supplierContactList = ref<any[]>([]);
const supplierList = ref<any[]>([]);
// 12
const supplierPlanFlag = ref<string>('1');
//
const unitInfoList = ref<any[]>([]);
const getUnitInfoListSelect = async () => {
const res = await getBaseUnitInfoList(null);
unitInfoList.value = res.data || [];
};
//
const materialDialog = reactive({ visible: false, title: '' });
const materialFormRef = ref<ElFormInstance>();
const initMaterialFormData: CrmQuoteMaterialForm & { planFlag?: string } = {
quoteMaterialId: undefined,
planFlag: '2', // 12
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<CrmQuoteMaterialForm & { planFlag?: string }>({ ...initMaterialFormData });
const materialRules = {
productName: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }],
amount: [{ required: true, message: '数量不能为空', trigger: 'blur' }],
taxRate: [{ required: true, message: '税率不能为空', trigger: 'blur' }]
};
const saleMaterialSelectRef = ref<InstanceType<typeof SaleMaterialSelect>>();
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<CrmQuoteMaterialForm[]>([]);
@ -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)),

@ -104,8 +104,8 @@
<el-form-item label="客户方电子邮箱" prop="customerContactEmail">
<el-input v-model="queryParams.customerContactEmail" placeholder="请输入客户方电子邮箱" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="供货方联系人ID" prop="supplierContactId">
<el-input v-model="queryParams.supplierContactId" placeholder="请输入供货方联系人ID" clearable @keyup.enter="handleQuery" />
<el-form-item label="供货方ID" prop="supplierContactId">
<el-input v-model="queryParams.supplierContactId" placeholder="请输入供货方ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="供货方联系人" prop="supplierContactName">
<el-input v-model="queryParams.supplierContactName" placeholder="请输入供货方联系人" clearable @keyup.enter="handleQuery" />
@ -159,6 +159,9 @@
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/crm:crmQuoteInfo:export']"></el-button>
</el-col>
<el-col :span="1.8">
<el-button type="primary" plain icon="Document" :disabled="single" @click="handleExportTemplate()" v-hasPermi="['oa/crm:crmQuoteInfo:exportTemplate']"></el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@ -223,7 +226,7 @@
<el-table-column label="客户方联系人" align="center" prop="customerContactName" v-if="columns[23].visible"/>
<el-table-column label="客户方联系电话" align="center" prop="customerContactPhone" v-if="columns[24].visible"/>
<el-table-column label="客户方电子邮箱" align="center" prop="customerContactEmail" v-if="columns[25].visible"/>
<el-table-column label="供货方联系人ID" align="center" prop="supplierContactId" v-if="columns[26].visible"/>
<el-table-column label="供货方ID" align="center" prop="supplierContactId" v-if="columns[26].visible"/>
<el-table-column label="供货方联系人" align="center" prop="supplierContactName" v-if="columns[27].visible"/>
<el-table-column label="供货方联系电话" align="center" prop="supplierContactPhone" v-if="columns[28].visible"/>
<el-table-column label="供货方电子邮箱" align="center" prop="supplierContactEmail" v-if="columns[29].visible"/>
@ -255,6 +258,9 @@
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/crm:crmQuoteInfo:remove']"></el-button>
</el-tooltip>
<el-tooltip content="模板导出" placement="top">
<el-button link type="warning" icon="Document" @click="handleExportTemplate(scope.row)" v-hasPermi="['oa/crm:crmQuoteInfo:exportTemplate']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
@ -388,8 +394,8 @@
<el-form-item label="客户方电子邮箱" prop="customerContactEmail">
<el-input v-model="form.customerContactEmail" placeholder="请输入客户方电子邮箱" />
</el-form-item>
<el-form-item label="供货方联系人ID" prop="supplierContactId">
<el-input v-model="form.supplierContactId" placeholder="请输入供货方联系人ID" />
<el-form-item label="供货方ID" prop="supplierContactId">
<el-input v-model="form.supplierContactId" placeholder="请输入供货方ID" />
</el-form-item>
<el-form-item label="供货方联系人" prop="supplierContactName">
<el-input v-model="form.supplierContactName" placeholder="请输入供货方联系人" />
@ -445,9 +451,11 @@
<script setup name="CrmQuoteInfo" lang="ts">
import { useRoute, useRouter } from 'vue-router';
import { listCrmQuoteInfo, getCrmQuoteInfo, delCrmQuoteInfo, addCrmQuoteInfo, updateCrmQuoteInfo } from '@/api/oa/crm/crmQuoteInfo';
import { listCrmQuoteInfo, getCrmQuoteInfo, delCrmQuoteInfo, addCrmQuoteInfo, updateCrmQuoteInfo, exportQuoteTemplate } from '@/api/oa/crm/crmQuoteInfo';
import { CrmQuoteInfoVO, CrmQuoteInfoQuery, CrmQuoteInfoForm } from '@/api/oa/crm/crmQuoteInfo/types';
import { getCrmCustomerContactList } from '@/api/oa/crm/customerContact';
import FileSaver from 'file-saver';
import { blobValidate } from '@/utils/ruoyi';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
@ -499,7 +507,7 @@ const columns = ref<FieldOption[]>([
{ key: 23, label: `客户方联系人`, visible: false },
{ key: 24, label: `客户方联系电话`, visible: false },
{ key: 25, label: `客户方电子邮箱`, visible: false },
{ key: 26, label: `供货方联系人ID`, visible: false },
{ key: 26, label: `供货方ID`, visible: false },
{ key: 27, label: `供货方联系人`, visible: false },
{ key: 28, label: `供货方联系电话`, visible: false },
{ key: 29, label: `供货方电子邮箱`, visible: false },
@ -708,6 +716,29 @@ const handleExport = () => {
}, `crmQuoteInfo_${new Date().getTime()}.xlsx`)
}
/** 模板导出支持选中或行内按钮GET Blob 下载) */
const handleExportTemplate = async (row?: CrmQuoteInfoVO) => {
const _quoteId = row?.quoteId || ids.value[0];
if (!_quoteId) {
proxy?.$modal.msgWarning('请先选择一条报价记录');
return;
}
try {
const resp: Blob = await exportQuoteTemplate(_quoteId);
// JSON
if (blobValidate(resp)) {
FileSaver.saveAs(resp, `报价单_${new Date().getTime()}.xlsx`);
} else {
const resText = await resp.text();
const rspObj = JSON.parse(resText);
proxy?.$modal.msgError(rspObj.msg || '导出失败');
}
} catch (e) {
console.error(e);
proxy?.$modal.msgError('导出失败,请联系管理员');
}
}
let crmCustomerContactList = ref([]);
const getCustomerContactList = async () => {
const res = await getCrmCustomerContactList(null);

@ -165,6 +165,7 @@
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改供应商信息对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="760px" append-to-body>
<el-form ref="crmSupplierInfoFormRef" :model="form" :rules="rules" label-width="110px" class="supplier-form">
@ -213,7 +214,7 @@
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="注册资本" prop="registeredCapital">
<el-input v-model="form.registeredCapital" placeholder="请输入注册资本" />
<el-input-number v-model="form.registeredCapital" placeholder="请输入注册资本" />
</el-form-item>
</el-col>
<el-col :md="24">
@ -423,8 +424,8 @@
{ key: 26, label: `激活标识`, visible: true },
{ key: 27, label: `删除标志`, visible: false },
{ key: 28, label: `创建部门`, visible: false },
{ key: 29, label: `创建人`, visible: false },
{ key: 30, label: `创建时间`, visible: false },
{ key: 29, label: `创建人`, visible: true },
{ key: 30, label: `创建时间`, visible: true },
{ key: 31, label: `更新人`, visible: false },
{ key: 32, label: `更新时间`, visible: false },
]);
@ -456,6 +457,7 @@
ossId: undefined,
remark: undefined,
activeFlag: undefined,
ownerName: undefined,
}
const data = reactive<PageData<CrmSupplierInfoForm, CrmSupplierInfoQuery>>({
form: {...initFormData},
@ -486,6 +488,7 @@
detailedAddress: undefined,
ossId: undefined,
activeFlag: undefined,
ownerName: undefined,
params: {
}
},

Loading…
Cancel
Save