edit.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. <template>
  2. <el-drawer
  3. v-model="visible"
  4. size="90%"
  5. title="编辑客户"
  6. direction="rtl"
  7. @close="handleBack"
  8. destroy-on-close
  9. class="form-drawer custom-edit-drawer"
  10. >
  11. <template #header>
  12. <div class="drawer-header-custom">
  13. <div class="header-left">
  14. <el-button link icon="ArrowLeft" @click="handleBack">返回</el-button>
  15. <span class="header-divider">|</span>
  16. <span class="header-title">基本信息 / <span class="customer-no">客户编号:{{ form.customerNo }}</span></span>
  17. </div>
  18. <div class="header-ops">
  19. <el-button type="primary" icon="Check" @click="handleSubmit" class="submit-btn" :loading="submitting">提交</el-button>
  20. </div>
  21. </div>
  22. </template>
  23. <div class="add-customer-container" v-loading="loading">
  24. <el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="custom-form" label-position="right" label-suffix=":">
  25. <div class="form-title">基本信息</div>
  26. <div class="form-section">
  27. <el-row :gutter="20">
  28. <el-col :span="24">
  29. <el-form-item label="工商名称">
  30. <el-input :model-value="rawCustomerData.businessCustomerName || form.businessCustomerName || ''" disabled />
  31. </el-form-item>
  32. </el-col>
  33. </el-row>
  34. <el-row :gutter="20">
  35. <el-col :span="8">
  36. <el-form-item label="归属公司">
  37. <el-select :model-value="rawCustomerData.companyName || rawCustomerData.customerBusinessVo?.companyName || ''" class="w100" disabled>
  38. <el-option :label="rawCustomerData.companyName || rawCustomerData.customerBusinessVo?.companyName || ''" :value="rawCustomerData.companyName || rawCustomerData.customerBusinessVo?.companyName || ''" />
  39. </el-select>
  40. </el-form-item>
  41. </el-col>
  42. <el-col :span="8">
  43. <el-form-item label="客户来源" prop="customerSourceId">
  44. <el-select v-model="form.customerSourceId" placeholder="请选择" class="w100">
  45. <el-option v-for="item in sourceOptions" :key="item.value" :label="item.label" :value="item.value" />
  46. </el-select>
  47. </el-form-item>
  48. </el-col>
  49. <el-col :span="8">
  50. <el-form-item label="企业类型" prop="enterpriseTypeId">
  51. <el-select v-model="form.enterpriseTypeId" placeholder="请选择" class="w100">
  52. <el-option v-for="item in corpTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
  53. </el-select>
  54. </el-form-item>
  55. </el-col>
  56. </el-row>
  57. <el-row :gutter="20">
  58. <el-col :span="8">
  59. <el-form-item label="客户等级">
  60. <el-select :model-value="rawCustomerData.customerLevelName || rawCustomerData.customerBusinessVo?.customerLevelName || ''" class="w100" disabled>
  61. <el-option :label="rawCustomerData.customerLevelName || rawCustomerData.customerBusinessVo?.customerLevelName || ''" :value="rawCustomerData.customerLevelName || rawCustomerData.customerBusinessVo?.customerLevelName || ''" />
  62. </el-select>
  63. </el-form-item>
  64. </el-col>
  65. <el-col :span="8">
  66. <el-form-item label="企业规模">
  67. <el-select :model-value="rawCustomerData.enterpriseScale || ''" class="w100" disabled>
  68. <el-option :label="rawCustomerData.enterpriseScale || ''" :value="rawCustomerData.enterpriseScale || ''" />
  69. </el-select>
  70. </el-form-item>
  71. </el-col>
  72. <el-col :span="8">
  73. <el-form-item label="企业邮箱">
  74. <el-input :model-value="rawCustomerData.email || ''" disabled />
  75. </el-form-item>
  76. </el-col>
  77. </el-row>
  78. <el-row :gutter="20">
  79. <el-col :span="8">
  80. <el-form-item label="办公电话">
  81. <el-input :model-value="rawCustomerData.landline || ''" disabled />
  82. </el-form-item>
  83. </el-col>
  84. <el-col :span="8">
  85. <el-form-item label="行业">
  86. <el-select :model-value="rawCustomerData.industryName || ''" class="w100" disabled>
  87. <el-option :label="rawCustomerData.industryName || ''" :value="rawCustomerData.industryName || ''" />
  88. </el-select>
  89. </el-form-item>
  90. </el-col>
  91. <el-col :span="8">
  92. <el-form-item label="国家">
  93. <el-input :model-value="'中国'" disabled />
  94. </el-form-item>
  95. </el-col>
  96. </el-row>
  97. <el-row :gutter="20">
  98. <el-col :span="8">
  99. <el-form-item label="省份">
  100. <el-input :model-value="rawCustomerData.regProvincialName || ''" disabled />
  101. </el-form-item>
  102. </el-col>
  103. <el-col :span="8">
  104. <el-form-item label="城市">
  105. <el-input :model-value="rawCustomerData.regCityName || ''" disabled />
  106. </el-form-item>
  107. </el-col>
  108. </el-row>
  109. <el-row :gutter="20">
  110. <el-col :span="24">
  111. <el-form-item label="办公地址">
  112. <el-input :model-value="rawCustomerData.address || rawCustomerData.customerBusinessVo?.address || ''" disabled />
  113. </el-form-item>
  114. </el-col>
  115. </el-row>
  116. </div>
  117. <div class="form-title">工商信息</div>
  118. <div class="form-section">
  119. <el-row :gutter="20">
  120. <el-col :span="24">
  121. <el-form-item label="工商名称">
  122. <el-input :model-value="rawCustomerData.businessCustomerName || form.businessCustomerName || ''" disabled />
  123. </el-form-item>
  124. </el-col>
  125. </el-row>
  126. <el-row :gutter="20">
  127. <el-col :span="8">
  128. <el-form-item label="社会信用代码">
  129. <el-input :model-value="rawCustomerData.customerBusinessVo?.socialCreditCode || rawCustomerData.customerBusinessInfoVo?.socialCreditCode || ''" disabled />
  130. </el-form-item>
  131. </el-col>
  132. <el-col :span="8">
  133. <el-form-item label="法定代表人">
  134. <el-input :model-value="rawCustomerData.customerBusinessVo?.legalPersonName || rawCustomerData.customerBusinessInfoVo?.legalPersonName || ''" disabled />
  135. </el-form-item>
  136. </el-col>
  137. <el-col :span="8">
  138. <el-form-item label="注册资本">
  139. <el-input :model-value="rawCustomerData.customerBusinessVo?.registeredCapital || rawCustomerData.customerBusinessInfoVo?.registeredCapital || ''" disabled />
  140. </el-form-item>
  141. </el-col>
  142. </el-row>
  143. <el-row :gutter="20">
  144. <el-col :span="8">
  145. <el-form-item label="成立日期">
  146. <el-input :model-value="rawCustomerData.customerBusinessVo?.establishmentDate || rawCustomerData.customerBusinessInfoVo?.establishmentDate || ''" disabled />
  147. </el-form-item>
  148. </el-col>
  149. <el-col :span="8">
  150. <el-form-item label="吊销日期">
  151. <el-input :model-value="rawCustomerData.customerBusinessVo?.revocationDate || rawCustomerData.customerBusinessInfoVo?.revocationDate || ''" disabled />
  152. </el-form-item>
  153. </el-col>
  154. <el-col :span="8">
  155. <el-form-item label="登记状态">
  156. <el-input :model-value="rawCustomerData.customerBusinessVo?.registrationStatusName || rawCustomerData.customerBusinessInfoVo?.registrationStatus || ''" disabled />
  157. </el-form-item>
  158. </el-col>
  159. </el-row>
  160. <el-row :gutter="20">
  161. <el-col :span="24">
  162. <el-form-item label="注册地址">
  163. <el-input :model-value="rawCustomerData.customerBusinessVo?.businessAddress || rawCustomerData.customerBusinessInfoVo?.businessAddress || ''" disabled />
  164. </el-form-item>
  165. </el-col>
  166. </el-row>
  167. <el-row :gutter="20" class="mt-20">
  168. <el-col :span="8">
  169. <el-form-item label="营业执照">
  170. <image-upload v-model="form.businessLicense" :limit="1" :is-show-tip="false" disabled />
  171. </el-form-item>
  172. </el-col>
  173. <el-col :span="8">
  174. <el-form-item label="正面身份证">
  175. <image-upload v-model="form.legalPersonCardFront" :limit="1" :is-show-tip="false" disabled />
  176. </el-form-item>
  177. </el-col>
  178. <el-col :span="8">
  179. <el-form-item label="反面身份证">
  180. <image-upload v-model="form.legalPersonCardBack" :limit="1" :is-show-tip="false" disabled />
  181. </el-form-item>
  182. </el-col>
  183. </el-row>
  184. </div>
  185. <div class="form-title">销售信息</div>
  186. <div class="form-section">
  187. <el-row :gutter="20">
  188. <el-col :span="8">
  189. <el-form-item label="合作状况">
  190. <el-select v-model="form.status" placeholder="请选择" class="w100" clearable>
  191. <el-option v-for="item in cooperationOptions" :key="item.value" :label="item.label" :value="item.value" />
  192. </el-select>
  193. </el-form-item>
  194. </el-col>
  195. <el-col :span="8">
  196. <el-form-item label="开票类型">
  197. <el-input :model-value="rawCustomerData.sellInvoiceType || ''" disabled />
  198. </el-form-item>
  199. </el-col>
  200. <el-col :span="8">
  201. <el-form-item label="归属部门">
  202. <el-input :model-value="rawCustomerData.belongingDepartmentName || rawCustomerData.deptName || ''" disabled />
  203. </el-form-item>
  204. </el-col>
  205. </el-row>
  206. <el-row :gutter="20">
  207. <el-col :span="8">
  208. <el-form-item label="采购规模(万)">
  209. <el-input v-model="form.annualProcurementScale" placeholder="请输入采购规模" class="w100"></el-input>
  210. </el-form-item>
  211. </el-col>
  212. <el-col :span="8">
  213. <el-form-item label="销售目标(万)">
  214. <el-input v-model="form.salesTarget" placeholder="请输入销售目标" class="w100"></el-input>
  215. </el-form-item>
  216. </el-col>
  217. <el-col :span="8">
  218. <el-form-item label="采购方式">
  219. <el-select v-model="form.procurementMethod" placeholder="请选择" class="w100" clearable multiple>
  220. <el-option v-for="item in purchaseWayOptions" :key="item.value" :label="item.label" :value="item.value" />
  221. </el-select>
  222. </el-form-item>
  223. </el-col>
  224. </el-row>
  225. <el-row :gutter="20">
  226. <el-col :span="8">
  227. <el-form-item label="信用等级">
  228. <el-input :model-value="rawCustomerData.customerSalesInfoVo?.creditLevel || rawCustomerData.customerLevelName || ''" disabled />
  229. </el-form-item>
  230. </el-col>
  231. <el-col :span="8">
  232. <el-form-item label="授信额度">
  233. <el-input :model-value="rawCustomerData.customerSalesInfoVo?.creditAmount || '0.00'" disabled />
  234. </el-form-item>
  235. </el-col>
  236. <el-col :span="8">
  237. <el-form-item label="应收账款">
  238. <el-input :model-value="rawCustomerData.customerSalesInfoVo?.accountsReceivable || ''" disabled />
  239. </el-form-item>
  240. </el-col>
  241. </el-row>
  242. <el-row :gutter="20">
  243. <el-col :span="8">
  244. <el-form-item label="预收账款">
  245. <el-input :model-value="rawCustomerData.customerSalesInfoVo?.prepaidAmount || rawCustomerData.deptCredit || ''" disabled />
  246. </el-form-item>
  247. </el-col>
  248. <el-col :span="8">
  249. <el-form-item label="剩余额度">
  250. <el-input :model-value="rawCustomerData.customerSalesInfoVo?.remainingQuota || '0.00'" disabled />
  251. </el-form-item>
  252. </el-col>
  253. </el-row>
  254. </div>
  255. </el-form>
  256. </div>
  257. </el-drawer>
  258. </template>
  259. <script setup name="CustomerValidEdit">
  260. import { ref, reactive, onMounted, getCurrentInstance, toRefs } from 'vue';
  261. import { useRoute, useRouter } from 'vue-router';
  262. import { listCompanyOption, getCustomerInfo, updateCustomerInfo } from "@/api/customer/customerPool";
  263. import { listIndustryCategory } from "@/api/customer/industryCategory";
  264. import { listLevel } from "@/api/customer/customerLevel";
  265. import { listComStaff } from "@/api/system/comStaff/index";
  266. import { listCustomerTypeOption } from "@/api/customer/customerDict";
  267. import { listEnterpriseScale } from "@/api/customer/enterpriseScale";
  268. import { listProvinceWithCities } from "@/api/customer/addressArea";
  269. import { deptTreeSelect } from "@/api/system/dept";
  270. const proxy = getCurrentInstance().proxy;
  271. const { K0001: sourceOptions, Q0001: corpTypeOptions, cooperation_status: cooperationOptions, X0001: purchaseWayOptions } = toRefs(reactive(proxy.useDict("K0001", "Q0001", "cooperation_status", "X0001")));
  272. const route = useRoute();
  273. const router = useRouter();
  274. const formRef = ref(null);
  275. const loading = ref(false);
  276. const visible = ref(false);
  277. const submitting = ref(false);
  278. const rawCustomerData = ref({});
  279. const form = reactive({
  280. id: undefined,
  281. customerNo: '',
  282. belongCompanyId: undefined,
  283. customerName: '',
  284. businessCustomerName: '',
  285. customerSourceId: undefined,
  286. enterpriseTypeId: undefined,
  287. enterpriseScaleId: undefined,
  288. customerTypeId: undefined,
  289. industryCategoryId: undefined,
  290. customerLevelId: undefined,
  291. landline: '',
  292. fax: '',
  293. url: '',
  294. postCode: '',
  295. email: '',
  296. regProvincialNo: '',
  297. regCityNo: '',
  298. regCountyNo: '',
  299. areaArray: [],
  300. provincialCityCounty: '',
  301. address: '',
  302. salesPersonId: undefined,
  303. serviceStaffId: undefined,
  304. belongingDepartmentId: undefined,
  305. idCardFront: '',
  306. idCardBack: '',
  307. customerBusinessBo: {
  308. businessCustomerName: '', socialCreditCode: '', legalPersonName: '',
  309. registeredCapital: '', establishmentDate: '', registrationStatus: '',
  310. registrationAuthority: '', paidInCapital: '', revocationDate: '',
  311. businessAddress: '', businessLicense: '', legalPersonCardUrl: ''
  312. },
  313. customerSalesInfoBo: { procurementScale: '', salesTarget: '' },
  314. status: undefined,
  315. procurementMethod: undefined
  316. });
  317. const rules = reactive({
  318. belongCompanyId: [{ required: true, message: "所属公司不能为空", trigger: "change" }],
  319. customerName: [
  320. { required: true, message: "客户名称不能为空", trigger: "blur" },
  321. { max: 100, message: "客户名称不能超过100个字符", trigger: "blur" }
  322. ],
  323. businessCustomerName: [
  324. { required: true, message: "工商名称不能为空", trigger: "blur" },
  325. { max: 100, message: "工商名称不能超过100个字符", trigger: "blur" }
  326. ],
  327. customerSourceId: [{ required: true, message: "客户来源不能为空", trigger: "change" }],
  328. enterpriseTypeId: [{ required: true, message: "企业类型不能为空", trigger: "change" }],
  329. enterpriseScaleId: [{ required: true, message: "企业规模不能为空", trigger: "change" }],
  330. customerTypeId: [{ required: true, message: "客户类别不能为空", trigger: "change" }],
  331. industryCategoryId: [{ required: true, message: "所属行业不能为空", trigger: "change" }],
  332. customerLevelId: [{ required: true, message: "客户等级不能为空", trigger: "change" }],
  333. landline: [
  334. { required: true, message: "固定电话不能为空", trigger: "blur" },
  335. { pattern: /^([0-9-]{7,20})$/, message: "请输入正确的电话号码", trigger: "blur" }
  336. ],
  337. fax: [
  338. { pattern: /^([0-9-]{7,20})$/, message: "请输入正确的传真号码", trigger: "blur" }
  339. ],
  340. url: [
  341. { pattern: /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([\/\w .-]*)*\/?$/, message: "请输入正确的网址", trigger: "blur" }
  342. ],
  343. postCode: [
  344. { pattern: /^\d{6}$/, message: "请输入正确的6位邮政编码", trigger: "blur" }
  345. ],
  346. email: [
  347. { pattern: /^([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/, message: "请输入正确的邮箱地址", trigger: "blur" }
  348. ],
  349. areaArray: [{ required: true, message: "详细地区不能为空", trigger: "change", type: 'array' }],
  350. 'customerBusinessBo.businessCustomerName': [{ max: 100, message: "企业工商名称不能超过100个字符", trigger: "blur" }],
  351. 'customerBusinessBo.socialCreditCode': [
  352. { pattern: /^[A-Za-z0-9]{18}$/, message: "请输入正确的18位统一社会信用代码", trigger: "blur" }
  353. ],
  354. 'customerBusinessBo.legalPersonName': [{ max: 50, message: "法人姓名不能超过50个字符", trigger: "blur" }],
  355. 'customerBusinessBo.registeredCapital': [{ max: 50, message: "注册资本不能超过50个字符", trigger: "blur" }],
  356. 'customerBusinessBo.registrationAuthority': [{ max: 100, message: "登记机关不能超过100个字符", trigger: "blur" }],
  357. 'customerBusinessBo.registrationStatus': [{ max: 50, message: "登记状态不能超过50个字符", trigger: "blur" }],
  358. 'customerBusinessBo.paidInCapital': [{ max: 50, message: "实缴资本不能超过50个字符", trigger: "blur" }],
  359. 'customerBusinessBo.businessAddress': [{ max: 200, message: "详细地址不能超过200个字符", trigger: "blur" }]
  360. });
  361. const companyOptions = ref([]);
  362. const industryOptions = ref([]);
  363. const levelOptions = ref([]);
  364. const staffOptions = ref([]);
  365. const scaleOptions = ref([]);
  366. const categoryOptions = ref([]);
  367. const areaOptions = ref([]);
  368. const deptOptions = ref([]);
  369. const initOptions = async () => {
  370. listCompanyOption().then(res => companyOptions.value = res.data || []).catch(e => console.error("公司选项接口404或出错", e));
  371. listIndustryCategory().then(res => industryOptions.value = res.data || res.rows || []).catch(e => console.error("行业类别接口404或出错", e));
  372. listLevel().then(res => levelOptions.value = res.rows || []).catch(e => console.error("客户等级接口404或出错", e));
  373. listComStaff({ pageSize: 1000 }).then(res => staffOptions.value = res.rows || res.data || []).catch(e => console.error("员工选项接口404或出错", e));
  374. listEnterpriseScale().then(res => scaleOptions.value = res.data || res.rows || []).catch(e => console.error("企业规模接口404或出错", e));
  375. listCustomerTypeOption().then(res => {
  376. categoryOptions.value = res.data || res.rows || [];
  377. }).catch(e => {
  378. console.error("客户类别接口加载失败:", e);
  379. });
  380. listProvinceWithCities().then(res => {
  381. const list = res.rows || [];
  382. areaOptions.value = handleTree(list, "id", "parentId");
  383. }).catch(e => console.error("省市联动接口出错", e));
  384. deptTreeSelect().then(res => {
  385. const data = res.data || res.rows || [];
  386. deptOptions.value = proxy.handleTree(data, "deptId");
  387. }).catch(e => console.error("部门树接口404或出错", e));
  388. };
  389. const loadData = (id) => {
  390. loading.value = true;
  391. getCustomerInfo(id).then(res => {
  392. const data = res.data;
  393. if (!data) return;
  394. rawCustomerData.value = data;
  395. Object.assign(form, data);
  396. const biz = data.customerBusinessVo || data.customerBusinessInfoVo || {};
  397. form.customerBusinessBo = {
  398. customerId: data.id,
  399. businessCustomerName: biz.businessCustomerName || data.businessCustomerName,
  400. socialCreditCode: biz.socialCreditCode,
  401. legalPersonName: biz.legalPersonName,
  402. registeredCapital: biz.registeredCapital,
  403. registrationAuthority: biz.registrationAuthority,
  404. establishmentDate: biz.establishmentDate,
  405. revocationDate: biz.revocationDate,
  406. registrationStatus: biz.registrationStatus,
  407. paidInCapital: biz.paidInCapital,
  408. businessAddress: biz.businessAddress || data.address,
  409. businessLicense: biz.businessLicense,
  410. legalPersonCardUrl: biz.legalPersonCardUrl
  411. };
  412. const sales = data.customerSalesInfoVo || data.customerSalesVo || {};
  413. form.customerSalesInfoBo = {
  414. id: sales.id,
  415. customerId: data.id,
  416. procurementScale: sales.procurementScale || data.annualProcurementScale,
  417. salesTarget: sales.salesTarget || data.salesTarget,
  418. creditLevel: sales.creditLevel,
  419. creditAmount: sales.creditAmount,
  420. accountsReceivable: sales.accountsReceivable,
  421. prepaidAmount: sales.prepaidAmount || data.deptCredit,
  422. remainingQuota: sales.remainingQuota
  423. };
  424. form.status = data.status || data.cooperationStatus;
  425. form.procurementMethod = data.procurementMethod;
  426. // 解析身份证回显
  427. const cardUrls = biz.legalPersonCardUrl ? biz.legalPersonCardUrl.split(',') : [];
  428. form.idCardFront = cardUrls[0] || '';
  429. form.idCardBack = cardUrls[1] || '';
  430. // 显式处理字典项回显和类型转换
  431. const sourceVal = data.customerSourceId || sales.customerSource || sales.customerSourceId;
  432. form.customerSourceId = sourceVal ? String(sourceVal).split(',')[0] : undefined;
  433. const typeVal = data.enterpriseTypeId || data.enterpriseType;
  434. form.enterpriseTypeId = typeVal ? String(typeVal) : undefined;
  435. const scaleVal = data.enterpriseScaleId || data.enterpriseScale || data.scaleId;
  436. form.enterpriseScaleId = scaleVal ? String(scaleVal) : undefined;
  437. form.customerTypeId = data.customerTypeId ? String(data.customerTypeId) : undefined;
  438. const industryVal = data.industryCategoryId || data.industryId;
  439. form.industryCategoryId = industryVal ? Number(industryVal) : undefined;
  440. const levelVal = data.customerLevelId || data.levelId || data.customerLevel;
  441. form.customerLevelId = levelVal ? String(levelVal) : undefined;
  442. // 地区回显处理
  443. if (data.regProvincialNo && data.regCityNo && data.regCountyNo) {
  444. form.areaArray = [Number(data.regProvincialNo), Number(data.regCityNo), Number(data.regCountyNo)];
  445. } else {
  446. form.areaArray = [];
  447. }
  448. loading.value = false;
  449. }).catch(() => {
  450. loading.value = false;
  451. });
  452. };
  453. const handleAreaChange = (val) => {
  454. if (val && val.length === 3) {
  455. form.regProvincialNo = val[0];
  456. form.regCityNo = val[1];
  457. form.regCountyNo = val[2];
  458. // 同步到 provincialCityCounty 以防后端其他地方用到
  459. form.provincialCityCounty = val.join(',');
  460. } else {
  461. form.regProvincialNo = '';
  462. form.regCityNo = '';
  463. form.regCountyNo = '';
  464. form.provincialCityCounty = '';
  465. }
  466. };
  467. const handleBack = () => {
  468. visible.value = false;
  469. setTimeout(() => {
  470. router.push('/customer/valid');
  471. }, 300);
  472. };
  473. const handleSubmit = () => {
  474. formRef.value.validate(valid => {
  475. if (valid) {
  476. submitting.value = true;
  477. // 提交前合并身份证地址
  478. const cards = [];
  479. if (form.idCardFront) cards.push(form.idCardFront);
  480. if (form.idCardBack) cards.push(form.idCardBack);
  481. form.customerBusinessBo.legalPersonCardUrl = cards.join(',');
  482. updateCustomerInfo(form).then(() => {
  483. proxy.$modal.msgSuccess("修改成功");
  484. handleBack();
  485. }).finally(() => {
  486. submitting.value = false;
  487. });
  488. }
  489. });
  490. };
  491. const open = (id) => {
  492. visible.value = true;
  493. loadData(id);
  494. };
  495. onMounted(() => {
  496. initOptions();
  497. const id = route.query.id;
  498. if (id) {
  499. loadData(id);
  500. }
  501. });
  502. defineExpose({ open });
  503. /** 构造树型结构数据 */
  504. function handleTree(data, id, parentId, children) {
  505. let config = {
  506. id: id || 'id',
  507. parentId: parentId || 'parentId',
  508. childrenList: children || 'children'
  509. };
  510. var childrenListMap = {};
  511. var nodeIds = {};
  512. var tree = [];
  513. for (let d of data) {
  514. let pId = d[config.parentId];
  515. if (childrenListMap[pId] == null) {
  516. childrenListMap[pId] = [];
  517. }
  518. nodeIds[d[config.id]] = d;
  519. childrenListMap[pId].push(d);
  520. }
  521. for (let d of data) {
  522. let pId = d[config.parentId];
  523. if (nodeIds[pId] == null) {
  524. tree.push(d);
  525. }
  526. }
  527. for (let t of tree) {
  528. adaptToChildrenList(t);
  529. }
  530. function adaptToChildrenList(o) {
  531. if (childrenListMap[o[config.id]] !== null) {
  532. o[config.childrenList] = childrenListMap[o[config.id]];
  533. }
  534. if (o[config.childrenList]) {
  535. for (let c of o[config.childrenList]) {
  536. adaptToChildrenList(c);
  537. }
  538. }
  539. }
  540. return tree;
  541. }
  542. </script>
  543. <style lang="scss">
  544. .el-overlay {
  545. .custom-edit-drawer {
  546. width: 90% !important;
  547. .el-drawer__header { margin-bottom: 0; padding: 0; }
  548. .el-drawer__body { padding: 24px; }
  549. .el-form-item__label {
  550. font-size: 13px;
  551. color: #606266;
  552. font-weight: normal !important;
  553. white-space: nowrap !important;
  554. overflow: visible !important;
  555. display: inline-block !important;
  556. }
  557. .form-title {
  558. font-weight: normal !important;
  559. }
  560. /* 隐藏上传组件提示语 */
  561. .el-upload__tip {
  562. display: none !important;
  563. }
  564. }
  565. }
  566. .drawer-header-custom {
  567. height: 64px; display: flex; justify-content: space-between; align-items: center;
  568. padding: 0 24px; border-bottom: 1px solid #f1f5f9; background-color: #fff; width: 100%;
  569. .header-left {
  570. display: flex; align-items: center; gap: 12px;
  571. .header-divider { color: #e2e8f0; }
  572. }
  573. .header-title { font-size: 14px; color: #1e293b; }
  574. }
  575. .form-title {
  576. font-size: 13px;
  577. color: #64748b;
  578. margin: 32px 0 16px;
  579. padding-bottom: 8px;
  580. border-bottom: 1px solid #f1f5f9;
  581. }
  582. .form-section {
  583. padding: 8px 0;
  584. }
  585. /* 统一输入组件宽度 */
  586. .custom-form {
  587. .el-input, .el-select, .el-date-editor, .el-cascader, .el-tree-select {
  588. width: 100% !important;
  589. }
  590. }
  591. .upload-item {
  592. display: flex;
  593. flex-direction: column;
  594. gap: 8px;
  595. }
  596. .w100 { width: 100%; }
  597. .static-text { color: #333; font-size: 14px; }
  598. </style>