<script lang="ts" setup name="ListSourceAdd"> /** * 添加/编辑/详情客户 */ import type { Ref } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import type { FormInstance, UploadUserFile } from 'element-plus' import type { ICustomer, customerPerson } from './advice_interface' import showPhoto from '@/views/system/tool/showPhoto.vue' import { UploadFile } from '@/api/measure/file' import { addCustomer, getCustomerDetail, updateCustomer } from '@/api/customer/customer' import { validatePhone } from '@/utils/validate' import { SCHEDULE } from '@/utils/scheduleDict' import type { IAddress } from '@/components/AddressSelect/address-interface' const loading = ref(false) // 表单加载状态 const infoId = ref('') // id const pageType = ref('add') // 页面类型: add, edit, detail const buttonLoading = ref(false) // 按钮加载状态 const textMap: { [key: string]: string } = { edit: '编辑', add: '新建', detail: '详情', }// 字典 // 从路由中获取页面类型参数 const $route = useRoute() if ($route.params && $route.params.type) { pageType.value = $route.params.type as string if ($route.params.id) { infoId.value = $route.params.id as string } } const dataForm: Ref<ICustomer> = ref({ id: '', businessContent: '', customerName: '', customerNo: '', bankAccount: '', bankAccountNumber: '', bankName: '', briefName: '', businessScope: '', grade: '', // 履约评级 companySize: '', // 公司规模 businessSize: '', // 业务规模 evaluation: '', // 整体评价 companyAddress: '', companyArea: '', companyCity: '', companyCountry: '', companyProvince: '', companyAreaName: '', companyCityName: '', companyCountryName: '', companyProvinceName: '', director: '', fax: '', invoiceAddress: '', invoiceArea: '', invoiceCity: '', invoiceCountry: '', invoiceProvince: '', invoiceAreaName: '', invoiceCityName: '', invoiceCountryName: '', invoiceProvinceName: '', mailbox: '', minioFileName: '', mobile: '', phone: '', postalCode: '', remark: '', taxNumber: '', website: '', customerPersonList: [], }) const companyAddress = ref<string[]>([]) // 公司地址 const invoiceAddress = ref<string[]>([]) // 开票地址 const customerPersonList: Ref<customerPerson[]> = ref([]) // 人员列表 const columns = ref([ { text: '人员编号', value: 'personNo', required: false }, { text: '姓名', value: 'name', required: true }, { text: '工作部门', value: 'department', required: false }, { text: '职务', value: 'job', required: false }, { text: '联系方式', value: 'phone', required: true, reg: validatePhone }, ]) const ruleFormRef = ref<FormInstance>() // 人员对象 const addPersonObj: customerPerson = { id: '', personNo: '', name: '', department: '', job: '', phone: '', editable: true, } const SelectionList: Ref<customerPerson[]> = ref([]) // 校验规则 const rules = ref({ customerName: [{ required: true, message: '公司名称不能为空', trigger: 'blur' }], businessContent: [{ required: true, message: '业务内容不能为空', trigger: 'blur' }], taxNumber: [{ required: true, message: '税号不能为空', trigger: 'blur' }], }) // 表单验证规则 // 初始化router const $router = useRouter() // 关闭新增页面的回调 const close = () => { $router.back() } const getInfo = () => { getCustomerDetail({ id: infoId.value }).then((res) => { dataForm.value = res.data companyAddress.value = [dataForm.value.companyCountry, dataForm.value.companyProvince, dataForm.value.companyCity, dataForm.value.companyArea, dataForm.value.companyAddress] invoiceAddress.value = [dataForm.value.invoiceCountry, dataForm.value.invoiceProvince, dataForm.value.invoiceCity, dataForm.value.invoiceArea, dataForm.value.invoiceAddress] }) } // 表格选中 const handleSelectionChange = (e: customerPerson[]) => { SelectionList.value = e } // 公司地址变化后给对象赋值 function companyAddressChange(addressObj: IAddress) { dataForm.value.companyCountry = addressObj.country dataForm.value.companyProvince = addressObj.province dataForm.value.companyCity = addressObj.city dataForm.value.companyArea = addressObj.area dataForm.value.companyAddress = addressObj.address dataForm.value.companyCountryName = addressObj.countryName dataForm.value.companyProvinceName = addressObj.provinceName dataForm.value.companyCityName = addressObj.cityName dataForm.value.companyAreaName = addressObj.areaName } function invoiceAddressChange(addressObj: IAddress) { dataForm.value.invoiceCountry = addressObj.country dataForm.value.invoiceProvince = addressObj.province dataForm.value.invoiceCity = addressObj.city dataForm.value.invoiceArea = addressObj.area dataForm.value.invoiceAddress = addressObj.address dataForm.value.invoiceCountryName = addressObj.countryName dataForm.value.invoiceProvinceName = addressObj.provinceName dataForm.value.invoiceCityName = addressObj.cityName dataForm.value.invoiceAreaName = addressObj.areaName } // 点击增加行 const addRow = () => { // 检查上一行必填项 if (checkPersonList()) { setAllRowReadable() customerPersonList.value.push({ ...addPersonObj }) } } // 检查人员列表 function checkPersonList() { for (let index = 0; index < customerPersonList.value.length; index++) { const item = customerPersonList.value[index] for (const prop of columns.value) { // 检查必填 if (prop.required && !item[prop.value]) { ElMessage.warning(`请先完善第${index + 1}行中${prop.text}`) return false } // 验证正则 if (prop.reg && typeof prop.reg === 'function') { if (!prop.reg(item[prop.value])) { ElMessage.warning(`第${index + 1}行中${prop.text}输入不合法`) return false } } } } return true } // 删除行 const deleteList = () => { customerPersonList.value = customerPersonList.value.filter((item: customerPerson) => { return !SelectionList.value.includes(item) }) } // 打印表单 const printObj = ref({ id: 'form', // 需要打印元素的id popTitle: '客户详情', // 打印配置页上方的标题 extraHead: '<div style="display: flex;flex-direction: column;text-align: center"><h3>客户详情</h3></div>', // 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割 preview: false, // 是否启动预览模式,默认是false standard: '', extarCss: '', }) // 保存 function saveForm(formEl: FormInstance | undefined) { if (!formEl) { return } formEl.validate((valid, fields) => { if (valid) { ElMessageBox.confirm( '确认保存吗?', '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }, ).then(() => { addCustomer(dataForm.value).then((res) => { if (res.code === 200) { dataForm.value.id = res.data.id dataForm.value.customerNo = res.data.customerNo ElMessage.success('已保存') } }) }) } }) } // 提交表单 function submitForm() { if (dataForm.value.id) { const params = { id: dataForm.value.id, formId: SCHEDULE.SUPPLIER_APPROVAL, // 表单id } addCustomer(params).then((res) => { ElMessage.success('提交成功') close() }) } else { ElMessage.info('请先保存再提交!') } } const isShow = ref(false) const testForm = ref({ fileList: [], fileContent: '', }) const fileRef = ref() // 文件上传input const onFileChange = (event: any) => { // 原生上传 console.log(event.target.files) if (event.target.files?.length !== 0) { // 创建formdata对象 const fd = new FormData() fd.append('multipartFile', event.target.files[0]) UploadFile(fd).then((res) => { if (res.code === 200) { dataForm.value.minioFileName = res.data[0] // 重置当前验证 ElMessage.success('文件上传成功') } else { ElMessage.error(res.message) } }) } } const upload = () => { fileRef.value.click() } // 双击行显示输入框 const dblclickRow = (row: customerPerson) => { setAllRowReadable() row.editable = true } // 将所有人员信息列表置为不可编辑状态 function setAllRowReadable() { for (const item of customerPersonList.value) { item.editable = false } } // 非添加页面获取详情 if (pageType.value !== 'add') { getInfo() } </script> <template> <app-container> <detail-page :title="`客户-${textMap[pageType]}`"> <template #btns> <el-button v-if="pageType === 'detail'" v-print="printObj" type="primary"> 打印 </el-button> <el-button v-if="pageType !== 'detail' && dataForm.customerNo" type="primary" @click="submitForm"> 提交 </el-button> <el-button v-if="pageType !== 'detail'" type="primary" @click="saveForm(ruleFormRef)"> 保存 </el-button> <el-button type="info" @click="close"> 关闭 </el-button> </template> <div id="form"> <el-form ref="ruleFormRef" :model="dataForm" :label-width="120" label-position="right" :rules="rules" > <el-row :gutter="24"> <el-col :span="6"> <el-form-item label="客户编号:" prop="customerNo"> <el-input v-model="dataForm.customerNo" :placeholder="pageType === 'detail' ? '' : '系统自动生成'" :class="{ 'detail-input': pageType === 'detail' }" disabled /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="税号:" prop="taxNumber"> <el-input v-model="dataForm.taxNumber" :placeholder="pageType === 'detail' ? '' : '请输入税号'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="邮编:"> <el-input v-model="dataForm.postalCode" :placeholder="pageType === 'detail' ? '' : '请输入邮编'" :disabled="pageType === 'detail'" :class="{ 'detail-input': pageType === 'detail' }" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="手机:"> <el-input v-model="dataForm.mobile" :placeholder="pageType === 'detail' ? '' : '请输入手机'" :disabled="pageType === 'detail'" :class="{ 'detail-input': pageType === 'detail' }" /> </el-form-item> </el-col> </el-row> <el-row :gutter="24"> <el-col :span="6"> <el-form-item label="公司名称:" prop="customerName"> <el-input v-model="dataForm.customerName" :placeholder="pageType === 'detail' ? '' : '请输入公司名称'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="银行账户名:"> <el-input v-model="dataForm.bankAccount" :placeholder="pageType === 'detail' ? '' : '请输入银行账户名'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="负责人:"> <el-input v-model="dataForm.director" :placeholder="pageType === 'detail' ? '' : '请输入负责人'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="邮箱:"> <el-input v-model="dataForm.mailbox" :placeholder="pageType === 'detail' ? '' : '请输入邮箱'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> </el-row> <el-row :gutter="24"> <el-col :span="6"> <el-form-item label="公司简称:"> <el-input v-model="dataForm.briefName" :placeholder="pageType === 'detail' ? '' : '请输入公司简称'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="银行名称:"> <el-input v-model="dataForm.bankName" :placeholder="pageType === 'detail' ? '' : '请输入银行名称'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="电话:"> <el-input v-model="dataForm.phone" :placeholder="pageType === 'detail' ? '' : '请输入电话'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="网址:"> <el-input v-model="dataForm.website" :placeholder="pageType === 'detail' ? '' : '请输入网址'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> </el-row> <el-row :gutter="24"> <el-col :span="6"> <el-form-item label="业务内容:" prop="businessContent"> <el-input v-model="dataForm.businessContent" :placeholder="pageType === 'detail' ? '' : '请输入业务内容'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="银行账号:"> <el-input v-model="dataForm.bankAccountNumber" :placeholder="pageType === 'detail' ? '' : '请输入银行账号'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="传真:"> <el-input v-model="dataForm.fax" :placeholder="pageType === 'detail' ? '' : '请输入传真'" :class="{ 'detail-input': pageType === 'detail' }" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> </el-row> <el-row :gutter="5"> <el-form-item label="公司地址:"> <address-select :data="companyAddress" @on-change="companyAddressChange" /> </el-form-item> </el-row> <el-row :gutter="5"> <el-form-item label="开票地址:"> <address-select :data="invoiceAddress" @on-change="invoiceAddressChange" /> </el-form-item> </el-row> <el-row :gutter="24"> <el-col :span="14"> <el-form-item label="公司业务范围:"> <el-input v-model="dataForm.businessScope" :placeholder="pageType === 'detail' ? '' : '请输入公司业务范围'" :disabled="pageType === 'detail'" :class="{ 'detail-input': pageType === 'detail' }" /> </el-form-item> </el-col> </el-row> <el-row :gutter="24"> <el-col :span="14"> <el-form-item label="备注:"> <el-input v-model="dataForm.remark" :placeholder="pageType === 'detail' ? '' : '请输入备注'" :disabled="pageType === 'detail'" :class="{ 'detail-input': pageType === 'detail' }" /> </el-form-item> </el-col> </el-row> <el-row :gutter="24" class="marg"> <el-col :span="14"> <el-form-item label="附件:"> <show-photo v-if="dataForm.minioFileName" :minio-file-name="dataForm.minioFileName" /> <span v-else-if="pageType === 'detail'">无</span> <input v-show="pageType === ''" ref="fileRef" type="file" @change="onFileChange"> <el-button v-if="pageType !== 'detail'" id="file" type="primary" :disabled="pageType === 'detail'" :style="{ 'margin-left': dataForm.minioFileName === '' ? '0px' : '20px' }" @click="upload"> {{ dataForm.minioFileName === '' ? '上传' : '更换附件' }} </el-button> </el-form-item> </el-col> </el-row> </el-form> </div> </detail-page> <detail-block title="人员信息"> <template v-if="pageType !== 'detail'" #btns> <el-button type="info" @click="deleteList"> 删除行 </el-button> <el-button type="primary" @click="addRow"> 增加行 </el-button> </template> <el-table :data="customerPersonList" border style="width: 100%;" @selection-change="handleSelectionChange" @row-dblclick="dblclickRow" > <el-table-column type="selection" width="38" /> <el-table-column align="center" label="序号" width="80" type="index" /> <el-table-column v-for="item in columns" :key="item.value" :prop="item.value" :label="item.text" align="center" > <template #header> <span v-show="item.required" style="color: red;">*</span><span>{{ item.text }}</span> </template> <template #default="scope"> <span v-if="!scope.row.editable">{{ scope.row[item.value] }}</span> <el-input v-else v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" /> </template> </el-table-column> </el-table> </detail-block> </app-container> </template> <style lang="scss" scoped> // 样式 </style>