addCustomer.vue 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. <template>
  2. <div>
  3. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit" v-loading="loading">
  4. <template #name>
  5. <div style="width: 100%">
  6. <el-autocomplete v-model="formData.data.name" :fetch-suggestions="querySearch" clearable placeholder="请输入" style="width:100%" />
  7. </div>
  8. </template>
  9. <template #allAddress>
  10. <el-row style="width: 100%">
  11. <el-col :span="8">
  12. <el-form-item prop="countryId" class="wid100">
  13. <el-select v-model="formData.data.countryId" placeholder="国家" filterable style="width:100%"
  14. @change="(val) => getCityData(val, '20', true)">
  15. <el-option v-for="item in countryData" :label="item.name" :value="item.id">
  16. </el-option>
  17. </el-select>
  18. </el-form-item>
  19. </el-col>
  20. <el-col :span="8">
  21. <el-form-item prop="provinceName" class="wid100">
  22. <selectCity placeholder="省/洲" @change="(val) => getCityData(val, '30', true)" style="width:100%" addressId="provinceId"
  23. addressName="provinceName" v-model="formData.data" :data="provinceData">
  24. </selectCity>
  25. </el-form-item>
  26. </el-col>
  27. <el-col :span="8">
  28. <el-form-item prop="cityName" class="wid100">
  29. <selectCity placeholder="城市" addressId="cityId" addressName="cityName" style="width:100%" v-model="formData.data" :data="cityData">
  30. </selectCity>
  31. </el-form-item>
  32. </el-col>
  33. </el-row>
  34. <el-row style=" width: 100%">
  35. <el-col :span="24">
  36. <el-form-item prop="address" class="margin-b-0 wid100">
  37. <el-input v-model="formData.data.address" type="textarea" placeholder="详细地址">
  38. </el-input>
  39. </el-form-item>
  40. </el-col>
  41. </el-row>
  42. </template>
  43. <template #person>
  44. <div style="width: 100%">
  45. <el-button type="primary" @click="clickAddPerson" v-if="!formOption.disabled">添 加</el-button>
  46. <el-table :data="formData.data.customerUserList" style="width: 100%; ">
  47. <el-table-column label="姓名" width="150" fixed="left">
  48. <template #default="{ row, $index }">
  49. <div style="width: 100%">
  50. <el-form-item :prop="'customerUserList.' + $index + '.name'" class="margin-b-0 wid100" :rules="rules.name2" :inline-message="true">
  51. <el-input v-model="row.name" placeholder="请输入" />
  52. </el-form-item>
  53. </div>
  54. </template>
  55. </el-table-column>
  56. <el-table-column label="性别" width="100" fixed="left">
  57. <template #default="{ row, $index }">
  58. <div style="width: 100%">
  59. <el-form-item :prop="'customerUserList.' + $index + '.sex'" class="margin-b-0 wid100" :rules="rules.sex" :inline-message="true">
  60. <el-select v-model="row.sex" placeholder="请选择" style="width: 100%">
  61. <el-option :label="'男'" :value="'1'" />
  62. <el-option :label="'女'" :value="'2'" />
  63. </el-select>
  64. </el-form-item>
  65. </div>
  66. </template>
  67. </el-table-column>
  68. <el-table-column label="职位" width="150" fixed="left">
  69. <template #default="{ row, $index }">
  70. <div style="width: 100%">
  71. <el-form-item :prop="'customerUserList.' + $index + '.position'" class="margin-b-0 wid100" :rules="rules.position"
  72. :inline-message="true">
  73. <el-input v-model="row.position" placeholder="请输入" />
  74. </el-form-item>
  75. </div>
  76. </template>
  77. </el-table-column>
  78. <el-table-column label="是否企业关键KP" width="150" fixed="left">
  79. <template #default="{ row, $index }">
  80. <div style="width: 100%">
  81. <el-form-item :prop="'customerUserList.' + $index + '.isKp'" class="margin-b-0 wid100" :rules="rules.isKp" :inline-message="true">
  82. <el-select v-model="row.isKp" placeholder="请选择" style="width: 100%">
  83. <el-option :label="'是'" :value="1" />
  84. <el-option :label="'否'" :value="0" />
  85. </el-select>
  86. </el-form-item>
  87. </div>
  88. </template>
  89. </el-table-column>
  90. <el-table-column label="手机号" width="150" fixed="left">
  91. <template #default="{ row, $index }">
  92. <div style="width: 100%">
  93. <el-form-item :prop="'customerUserList.' + $index + '.phone'" class="margin-b-0 wid100" :rules="rules.phone" :inline-message="true">
  94. <el-input v-model="row.phone" placeholder="请输入" />
  95. </el-form-item>
  96. </div>
  97. </template>
  98. </el-table-column>
  99. <el-table-column label="微信" width="150">
  100. <template #default="{ row, $index }">
  101. <div style="width: 100%">
  102. <el-form-item :prop="'customerUserList.' + $index + '.weChat'" class="margin-b-0 wid100" :rules="rules.weChat"
  103. :inline-message="true">
  104. <el-input v-model="row.weChat" placeholder="请输入" />
  105. </el-form-item>
  106. </div>
  107. </template>
  108. </el-table-column>
  109. <el-table-column label="旺旺" width="150">
  110. <template #default="{ row, $index }">
  111. <div style="width: 100%">
  112. <el-form-item :prop="'customerUserList.' + $index + '.wangWang'" class="margin-b-0 wid100" :rules="rules.wangWang"
  113. :inline-message="true">
  114. <el-input v-model="row.wangWang" placeholder="请输入" />
  115. </el-form-item>
  116. </div>
  117. </template>
  118. </el-table-column>
  119. <el-table-column label="联系电话" width="150">
  120. <template #default="{ row, $index }">
  121. <div style="width: 100%">
  122. <el-form-item :prop="'customerUserList.' + $index + '.tel'" class="margin-b-0 wid100" :rules="rules.tel" :inline-message="true">
  123. <el-input v-model="row.tel" placeholder="请输入" />
  124. </el-form-item>
  125. </div>
  126. </template>
  127. </el-table-column>
  128. <el-table-column label="WhatsApp" width="150">
  129. <template #default="{ row, $index }">
  130. <div style="width: 100%">
  131. <el-form-item :prop="'customerUserList.' + $index + '.whatsApp'" class="margin-b-0 wid100" :rules="rules.whatsApp"
  132. :inline-message="true">
  133. <el-input v-model="row.whatsApp" placeholder="请输入" />
  134. </el-form-item>
  135. </div>
  136. </template>
  137. </el-table-column>
  138. <el-table-column label="QQ" width="150">
  139. <template #default="{ row, $index }">
  140. <div style="width: 100%">
  141. <el-form-item :prop="'customerUserList.' + $index + '.qq'" class="margin-b-0 wid100" :rules="rules.qq" :inline-message="true">
  142. <el-input v-model="row.qq" placeholder="请输入" />
  143. </el-form-item>
  144. </div>
  145. </template>
  146. </el-table-column>
  147. <el-table-column label="Skype" width="150">
  148. <template #default="{ row, $index }">
  149. <div style="width: 100%">
  150. <el-form-item :prop="'customerUserList.' + $index + '.skype'" class="margin-b-0 wid100" :rules="rules.skype" :inline-message="true">
  151. <el-input v-model="row.skype" placeholder="请输入" />
  152. </el-form-item>
  153. </div>
  154. </template>
  155. </el-table-column>
  156. <el-table-column label="LinkedIn" width="150">
  157. <template #default="{ row, $index }">
  158. <div style="width: 100%">
  159. <el-form-item :prop="'customerUserList.' + $index + '.linkedIn'" class="margin-b-0 wid100" :rules="rules.linkedIn"
  160. :inline-message="true">
  161. <el-input v-model="row.linkedIn" placeholder="请输入" />
  162. </el-form-item>
  163. </div>
  164. </template>
  165. </el-table-column>
  166. <el-table-column label="Facebook" width="150">
  167. <template #default="{ row, $index }">
  168. <div style="width: 100%">
  169. <el-form-item :prop="'customerUserList.' + $index + '.facebook'" class="margin-b-0 wid100" :rules="rules.facebook"
  170. :inline-message="true">
  171. <el-input v-model="row.facebook" placeholder="请输入" />
  172. </el-form-item>
  173. </div>
  174. </template>
  175. </el-table-column>
  176. <el-table-column label="Dirrect Line" width="150">
  177. <template #default="{ row, $index }">
  178. <div style="width: 100%">
  179. <el-form-item :prop="'customerUserList.' + $index + '.directLine'" class="margin-b-0 wid100" :rules="rules.directLine"
  180. :inline-message="true">
  181. <el-input v-model="row.directLine" placeholder="请输入" />
  182. </el-form-item>
  183. </div>
  184. </template>
  185. </el-table-column>
  186. <el-table-column label="邮箱" width="150">
  187. <template #default="{ row, $index }">
  188. <div style="width: 100%">
  189. <el-form-item :prop="'customerUserList.' + $index + '.email'" class="margin-b-0 wid100" :rules="rules.email" :inline-message="true">
  190. <el-input v-model="row.email" placeholder="请输入" />
  191. </el-form-item>
  192. </div>
  193. </template>
  194. </el-table-column>
  195. <el-table-column align="center" label="操作" width="80" fixed="right" v-if="!formOption.disabled">
  196. <template #default="{ row, $index }">
  197. <!-- <el-button type="primary" link @click="clickInformationMore(row, $index)">更多</el-button> -->
  198. <el-button type="primary" link @click="clickDelete($index)">删除</el-button>
  199. </template>
  200. </el-table-column>
  201. </el-table>
  202. </div>
  203. </template>
  204. </byForm>
  205. <el-dialog title="更多联系方式" v-if="openPerson" v-model="openPerson" width="700">
  206. <el-form :label-position="'right'" :model="formPerson.data" :rules="rulesPerson" ref="person" label-width="100px">
  207. <el-form-item label="联系人" prop="name">
  208. <el-input v-model="formPerson.data.name" placeholder="请输入" />
  209. </el-form-item>
  210. <el-form-item label="电子邮箱" prop="email">
  211. <el-input v-model="formPerson.data.email" placeholder="请输入" />
  212. </el-form-item>
  213. <el-form-item label="更多联系方式">
  214. <div style="width: 100%">
  215. <el-button type="primary" @click="clickAddMoreInformation">添 加</el-button>
  216. <el-table :data="formPerson.data.contact" style="width: 100%; margin-top: 16px">
  217. <el-table-column label="类型" width="180">
  218. <template #default="{ row, $index }">
  219. <div style="width: 100%">
  220. <el-form-item :prop="'contact.' + $index + '.type'" class="margin-b-0 wid100" :rules="rulesPerson.type" :inline-message="true">
  221. <el-select v-model="row.type" placeholder="请选择类型" style="width: 100%">
  222. <el-option v-for="item in contactType" :key="item.value" :label="item.label" :value="item.value" />
  223. </el-select>
  224. </el-form-item>
  225. </div>
  226. </template>
  227. </el-table-column>
  228. <el-table-column label="联系号码">
  229. <template #default="{ row, $index }">
  230. <div style="width: 100%">
  231. <el-form-item :prop="'contact.' + $index + '.contactNo'" class="margin-b-0 wid100" :rules="rulesPerson.contactNo"
  232. :inline-message="true">
  233. <el-input v-model="row.contactNo" placeholder="请输入联系号码" />
  234. </el-form-item>
  235. </div>
  236. </template>
  237. </el-table-column>
  238. <el-table-column align="center" label="操作" width="120" fixed="right">
  239. <template #default="{ $index }">
  240. <el-button type="primary" link @click="clickInformationDelete($index)">删除</el-button>
  241. </template>
  242. </el-table-column>
  243. </el-table>
  244. </div>
  245. </el-form-item>
  246. </el-form>
  247. <template #footer>
  248. <el-button @click="openPerson = false" size="default">取 消</el-button>
  249. <el-button type="primary" @click="submitPerson()" size="default">确 定</el-button>
  250. </template>
  251. </el-dialog>
  252. </div>
  253. </template>
  254. <script setup>
  255. import { ElMessage, ElMessageBox } from "element-plus";
  256. import byForm from "@/components/byForm/index";
  257. import useUserStore from "@/store/modules/user";
  258. import selectCity from "@/components/selectCity/index.vue";
  259. const props = defineProps({
  260. modalType: String,
  261. customerId: String,
  262. customerMail: {
  263. type: String,
  264. default: "",
  265. },
  266. isPrivate: {
  267. type: Boolean,
  268. default: false,
  269. },
  270. isHighseas: {
  271. type: Boolean,
  272. default: false,
  273. },
  274. });
  275. const modalType = ref("add");
  276. const isHighseas = ref(false);
  277. isHighseas.value = props.isHighseas;
  278. const customerId = ref("");
  279. const { proxy } = getCurrentInstance();
  280. const loading = ref(false);
  281. const userList = ref([]);
  282. const deptData = ref([]);
  283. const customerSlevelData = ref([]);
  284. const customerTag = computed(
  285. () => proxy.useUserStore().allDict["customer_tag"]
  286. );
  287. const customerSource = computed(
  288. () => proxy.useUserStore().allDict["customer_source"]
  289. );
  290. const customerStatus = computed(
  291. () => proxy.useUserStore().allDict["customer_status"]
  292. );
  293. const contactType = computed(
  294. () => proxy.useUserStore().allDict["contact_type"]
  295. );
  296. const settlementWay = computed(
  297. () => proxy.useUserStore().allDict["settlement_way"]
  298. );
  299. const customerSlevel = computed(
  300. () => proxy.useUserStore().allDict["customer_slevel"]
  301. );
  302. const customerScale = computed(
  303. () => proxy.useUserStore().allDict["customer_scale"]
  304. );
  305. const customerState = computed(
  306. () => proxy.useUserStore().allDict["customer_state"]
  307. );
  308. const newoldCustomer = computed(
  309. () => proxy.useUserStore().allDict["newold_customer"]
  310. );
  311. const invoiceType = computed(
  312. () => proxy.useUserStore().allDict["invoice_type"]
  313. );
  314. const cooperationStatus = computed(
  315. () => proxy.useUserStore().allDict["cooperation_status"]
  316. );
  317. const submit = ref(null);
  318. const formData = reactive({
  319. data: {
  320. countryId: "44",
  321. },
  322. });
  323. const getDict = () => {
  324. proxy
  325. .get("/tenantUser/list", {
  326. pageNum: 1,
  327. pageSize: 10000,
  328. tenantId: proxy.useUserStore().user.tenantId,
  329. })
  330. .then((res) => {
  331. userList.value = res.rows.map((item) => {
  332. return {
  333. label: item.nickName,
  334. value: item.userId,
  335. };
  336. });
  337. });
  338. proxy
  339. .post("/customerLv/page", {
  340. pageNum: 1,
  341. pageSize: 999,
  342. })
  343. .then((res) => {
  344. customerSlevelData.value = res.rows.map((x) => ({
  345. label: x.lvName,
  346. value: x.id,
  347. }));
  348. });
  349. proxy
  350. .get("/tenantDept/list", {
  351. pageNum: 1,
  352. pageSize: 9999,
  353. keyword: "",
  354. ancestors: proxy.useUserStore().user.companyId,
  355. tenantId: proxy.useUserStore().user.tenantId,
  356. // type: 2,
  357. })
  358. .then((res) => {
  359. deptData.value = proxy.handleTree(res.data, "deptId");
  360. });
  361. };
  362. getDict();
  363. const countryData = ref([]);
  364. const provinceData = ref([]);
  365. const cityData = ref([]);
  366. const getCityData = (id, type, isChange = false) => {
  367. proxy.post("/customizeArea/list", { parentId: id }).then((res) => {
  368. if (type === "20") {
  369. provinceData.value = res;
  370. if (isChange) {
  371. formData.data.provinceId = "";
  372. formData.data.provinceName = "";
  373. formData.data.cityId = "";
  374. formData.data.cityName = "";
  375. }
  376. } else if (type === "30") {
  377. cityData.value = res;
  378. if (isChange) {
  379. formData.data.cityId = "";
  380. formData.data.cityName = "";
  381. }
  382. } else {
  383. countryData.value = res;
  384. }
  385. });
  386. };
  387. getCityData("0");
  388. const formOption = reactive({
  389. disabled: false,
  390. inline: true,
  391. labelWidth: 120,
  392. itemWidth: 100,
  393. rules: [],
  394. });
  395. const getDtl = () => {
  396. loading.value = true;
  397. proxy.post("/customer/detail", { id: customerId.value }).then((res) => {
  398. if (res.tag) {
  399. res.tags = res.tag.split(",");
  400. } else {
  401. res.tags = [];
  402. }
  403. formData.data = res;
  404. getCityData(formData.data.countryId, "20");
  405. if (formData.data.provinceId) {
  406. getCityData(formData.data.provinceId, "30");
  407. }
  408. proxy
  409. .post("/fileInfo/getList", { businessIdList: [customerId.value] })
  410. .then((fileObj) => {
  411. if (fileObj[customerId.value] && fileObj[customerId.value].length > 0) {
  412. formData.data.fileList = fileObj[customerId.value]
  413. .filter((x) => x.businessType == "10")
  414. .map((item) => {
  415. return {
  416. ...item,
  417. name: item.fileName,
  418. url: item.fileUrl,
  419. };
  420. });
  421. formData.data.imgFileList = fileObj[customerId.value]
  422. .filter((x) => x.businessType == "20")
  423. .map((item) => {
  424. return {
  425. ...item,
  426. name: item.fileName,
  427. url: item.fileUrl,
  428. };
  429. });
  430. if (
  431. formData.data.imgFileList &&
  432. formData.data.imgFileList.length > 0
  433. ) {
  434. formData.data.imageUrl = formData.data.imgFileList[0].fileUrl;
  435. }
  436. } else {
  437. formData.data.fileList = [];
  438. formData.data.imgFileList = [];
  439. }
  440. });
  441. loading.value = false;
  442. });
  443. };
  444. if (props && props.modalType) {
  445. modalType.value = props.modalType;
  446. if (modalType.value == "add") {
  447. formData.data = {
  448. countryId: "44",
  449. tags: [],
  450. fileList: [],
  451. imgFileList: [],
  452. customerUserList: [
  453. {
  454. name: "",
  455. email: "",
  456. },
  457. ],
  458. };
  459. if (props.customerMail) {
  460. formData.data.customerUserList[0].email = props.customerMail;
  461. }
  462. getCityData(formData.data.countryId, "20");
  463. } else if (
  464. (modalType.value == "edit" || modalType.value == "detail") &&
  465. props.customerId
  466. ) {
  467. customerId.value = props.customerId;
  468. getDtl();
  469. // 详情禁用
  470. if (modalType.value == "detail") {
  471. formOption.disabled = true;
  472. }
  473. }
  474. }
  475. const formConfig = computed(() => {
  476. return [
  477. // {
  478. // type: "input",
  479. // prop: "name",
  480. // label: "客户名称",
  481. // required: true,
  482. // itemWidth: 100,
  483. // itemType: "text",
  484. // },
  485. {
  486. type: "title1",
  487. title: "基本信息",
  488. },
  489. {
  490. type: "slot",
  491. slotName: "name",
  492. prop: "name",
  493. label: "客户名称",
  494. },
  495. {
  496. type: "input",
  497. prop: "customerCode",
  498. label: "客户编号",
  499. itemWidth: 100,
  500. itemType: "text",
  501. },
  502. {
  503. type: "slot",
  504. slotName: "allAddress",
  505. label: "详细地址",
  506. },
  507. // {
  508. // type: "input",
  509. // prop: "mainPart",
  510. // label: "客户名称",
  511. // itemWidth: 50,
  512. // itemType: "text",
  513. // },
  514. // {
  515. // type: "input",
  516. // prop: "minorPart",
  517. // label: "公司/客户客体",
  518. // itemWidth: 50,
  519. // itemType: "text",
  520. // },
  521. {
  522. type: "select",
  523. label: "业务员",
  524. prop: "userId",
  525. itemWidth: 25,
  526. data: userList.value,
  527. clearable: true,
  528. disabled: isHighseas.value,
  529. },
  530. {
  531. type: "treeSelect",
  532. prop: "deptId",
  533. label: "业务部门",
  534. data: deptData.value,
  535. propsTreeLabel: "deptName",
  536. propsTreeValue: "deptId",
  537. itemWidth: 25,
  538. },
  539. {
  540. type: "input",
  541. prop: "mainCategories",
  542. label: "主营品类",
  543. itemWidth: 25,
  544. itemType: "text",
  545. },
  546. {
  547. type: "select",
  548. label: "公司规模",
  549. prop: "companySize",
  550. itemWidth: 25,
  551. data: customerScale.value,
  552. },
  553. {
  554. type: "select",
  555. label: "客户结算方式",
  556. prop: "settlementMode",
  557. itemWidth: 25,
  558. data: settlementWay.value,
  559. },
  560. {
  561. type: "select",
  562. label: "客户类型",
  563. prop: "status",
  564. itemWidth: 25,
  565. data: customerStatus.value,
  566. },
  567. {
  568. type: "select",
  569. label: "客户分级",
  570. prop: "customerLvId",
  571. itemWidth: 25,
  572. data: customerSlevelData.value,
  573. },
  574. {
  575. type: "input",
  576. prop: "maintainLevel",
  577. label: "维系级别",
  578. itemWidth: 25,
  579. itemType: "text",
  580. },
  581. {
  582. type: "select",
  583. label: "新老客户",
  584. prop: "newOld",
  585. itemWidth: 25,
  586. data: newoldCustomer.value,
  587. },
  588. {
  589. type: "input",
  590. prop: "annualQuantity",
  591. label: "要求年订单量",
  592. itemWidth: 25,
  593. itemType: "text",
  594. },
  595. {
  596. type: "input",
  597. prop: "followUpAsk",
  598. label: "回访要求",
  599. itemWidth: 25,
  600. itemType: "text",
  601. },
  602. {
  603. type: "input",
  604. prop: "remind",
  605. label: "提醒设定",
  606. itemWidth: 25,
  607. itemType: "text",
  608. },
  609. {
  610. type: "date",
  611. itemType: "date",
  612. prop: "createGroupTime",
  613. label: "建群时间",
  614. itemWidth: 25,
  615. },
  616. {
  617. type: "select",
  618. label: "客户状态",
  619. prop: "state",
  620. itemWidth: 25,
  621. data: customerState.value,
  622. },
  623. {
  624. type: "select",
  625. label: "客户来源",
  626. prop: "source",
  627. itemWidth: 25,
  628. data: customerSource.value,
  629. },
  630. {
  631. type: "input",
  632. prop: "fax",
  633. label: "传真",
  634. required: true,
  635. itemWidth: 25,
  636. itemType: "text",
  637. },
  638. {
  639. type: "select",
  640. label: "客户标签",
  641. prop: "tags",
  642. itemWidth: 100,
  643. multiple: true,
  644. data: customerTag.value,
  645. style: {
  646. width: "100%",
  647. },
  648. },
  649. // {
  650. // type: "input",
  651. // prop: "beneficiaryName",
  652. // label: "Beneficiary Name",
  653. // required: true,
  654. // itemWidth: 50,
  655. // itemType: "text",
  656. // },
  657. // {
  658. // type: "input",
  659. // prop: "beneficiaryAccountNumber",
  660. // label: "Beneficiary Account Number",
  661. // required: true,
  662. // itemWidth: 50,
  663. // itemType: "text",
  664. // },
  665. // {
  666. // type: "input",
  667. // prop: "beneficiaryBank",
  668. // label: "Beneficiary Bank",
  669. // required: true,
  670. // itemWidth: 50,
  671. // itemType: "text",
  672. // },
  673. // {
  674. // type: "input",
  675. // prop: "swiftCode",
  676. // label: "Swift Code",
  677. // required: true,
  678. // itemWidth: 50,
  679. // itemType: "text",
  680. // },
  681. // {
  682. // type: "input",
  683. // prop: "beneficiaryBankAddress",
  684. // label: "Beneficiary Bank Address",
  685. // required: true,
  686. // itemWidth: 50,
  687. // itemType: "text",
  688. // },
  689. // {
  690. // type: "input",
  691. // prop: "beneficiaryAddress",
  692. // label: "Beneficiary Address",
  693. // required: true,
  694. // itemWidth: 50,
  695. // itemType: "text",
  696. // },
  697. {
  698. type: "title1",
  699. title: "联系人",
  700. },
  701. {
  702. type: "slot",
  703. slotName: "person",
  704. label: "客户联系人",
  705. },
  706. {
  707. type: "title1",
  708. title: "客户对公财务信息",
  709. },
  710. {
  711. type: "select",
  712. label: "发票信息",
  713. prop: "invoiceType",
  714. itemWidth: 25,
  715. data: invoiceType.value,
  716. },
  717. {
  718. type: "select",
  719. label: "合作状态",
  720. prop: "cooperateStatus",
  721. itemWidth: 25,
  722. data: cooperationStatus.value,
  723. },
  724. {
  725. type: "input",
  726. prop: "accountName",
  727. label: "公司名称",
  728. itemWidth: 25,
  729. itemType: "text",
  730. },
  731. {
  732. type: "input",
  733. prop: "dutyParagraph",
  734. label: "税号",
  735. itemWidth: 25,
  736. itemType: "text",
  737. },
  738. {
  739. type: "input",
  740. prop: "accountAddress",
  741. label: "地址",
  742. itemWidth: 25,
  743. itemType: "text",
  744. },
  745. {
  746. type: "input",
  747. prop: "accountTel",
  748. label: "电话",
  749. itemWidth: 25,
  750. itemType: "text",
  751. },
  752. {
  753. type: "input",
  754. prop: "accountBank",
  755. label: "开户行(对公)",
  756. itemWidth: 25,
  757. itemType: "text",
  758. },
  759. {
  760. type: "input",
  761. prop: "accountNumber",
  762. label: "开户账号(对公)",
  763. itemWidth: 25,
  764. itemType: "text",
  765. },
  766. {
  767. type: "title1",
  768. title: "客户对私财务信息",
  769. },
  770. {
  771. type: "input",
  772. prop: "privAccountName",
  773. label: "账户名称",
  774. itemWidth: 25,
  775. itemType: "text",
  776. },
  777. {
  778. type: "input",
  779. prop: "privAccountBank",
  780. label: "开户行(对私)",
  781. itemWidth: 25,
  782. itemType: "text",
  783. },
  784. {
  785. type: "input",
  786. prop: "privAccountNumber",
  787. label: "开户账号(对私)",
  788. itemWidth: 25,
  789. itemType: "text",
  790. },
  791. {
  792. type: "upload",
  793. listType: "text",
  794. accept: "",
  795. prop: "fileList",
  796. label: "客户附件信息",
  797. itemWidth: 100,
  798. },
  799. {
  800. type: "uploadImg",
  801. // listType: "picture-card",
  802. // limit: 1,
  803. // accept: ".gif, .jpeg, .jpg, .png",
  804. prop: "imgFileList",
  805. imgProp: "imageUrl",
  806. label: "客户图片信息",
  807. itemWidth: 100,
  808. },
  809. {
  810. type: "title1",
  811. title: "跟进下单数据",
  812. isShow: modalType.value == "detail",
  813. },
  814. {
  815. type: "date",
  816. itemType: "date",
  817. prop: "lastFollowTime",
  818. label: "客情时间",
  819. itemWidth: 25,
  820. placeholder: " ",
  821. disabled: true,
  822. isShow: modalType.value == "detail",
  823. },
  824. {
  825. type: "input",
  826. prop: "followCount",
  827. label: "跟进次数",
  828. itemWidth: 25,
  829. itemType: "text",
  830. placeholder: " ",
  831. disabled: true,
  832. isShow: modalType.value == "detail",
  833. },
  834. {
  835. type: "date",
  836. itemType: "date",
  837. prop: "lastSaleDate",
  838. label: "最近下单时间",
  839. itemWidth: 25,
  840. placeholder: " ",
  841. disabled: true,
  842. isShow: modalType.value == "detail",
  843. },
  844. {
  845. type: "input",
  846. prop: "lastSaleDay",
  847. label: "下单距离天数",
  848. itemWidth: 25,
  849. itemType: "text",
  850. placeholder: " ",
  851. disabled: true,
  852. isShow: modalType.value == "detail",
  853. },
  854. {
  855. type: "input",
  856. prop: "orderCount",
  857. label: "下单次数",
  858. itemWidth: 25,
  859. itemType: "text",
  860. placeholder: " ",
  861. disabled: true,
  862. isShow: modalType.value == "detail",
  863. },
  864. // {
  865. // type: "number",
  866. // prop: "flatPrice",
  867. // label: "每年成交金额",
  868. // precision: 2,
  869. // min: 0,
  870. // controls: false,
  871. // itemWidth: 25,
  872. // disabled: false,
  873. // },
  874. {
  875. type: "number",
  876. prop: "orderAmountSum",
  877. label: "成交总金额",
  878. precision: 2,
  879. min: 0,
  880. controls: false,
  881. itemWidth: 25,
  882. placeholder: " ",
  883. disabled: true,
  884. isShow: modalType.value == "detail",
  885. },
  886. ];
  887. });
  888. const rules = ref({
  889. name: [{ required: true, message: "请输入公司/客户主体", trigger: "blur" }],
  890. customerCode: [
  891. { required: true, message: "请输入客户编号", trigger: "blur" },
  892. ],
  893. name2: [{ required: true, message: "请输入", trigger: "blur" }],
  894. // email: [{ required: true, message: "请输入电子邮箱", trigger: "blur" }],
  895. sex: [{ required: true, message: "请选择性别", trigger: "change" }],
  896. position: [{ required: true, message: "请输入职位", trigger: "blur" }],
  897. phone: [{ required: true, message: "请输入手机", trigger: "blur" }],
  898. countryId: [{ required: true, message: "请选择国家", trigger: "change" }],
  899. source: [{ required: true, message: "请选择客户来源", trigger: "change" }],
  900. status: [{ required: true, message: "请选择类型", trigger: "change" }],
  901. mainPart: [
  902. { required: true, message: "请选择公司/客户主体", trigger: "change" },
  903. ],
  904. minorPart: [
  905. { required: true, message: "请选择公司/客户客体", trigger: "change" },
  906. ],
  907. // userId: [{ required: true, message: "请选择业务员", trigger: "change" }],
  908. deptId: [{ required: true, message: "请选择业务部门", trigger: "change" }],
  909. level: [{ required: true, message: "请选择客户分级", trigger: "change" }],
  910. maintainLevel: [
  911. { required: true, message: "请输入维系级别", trigger: "blur" },
  912. ],
  913. newOld: [{ required: true, message: "请选择新老客户", trigger: "change" }],
  914. annualQuantity: [
  915. { required: true, message: "请输入要求年订单量", trigger: "blur" },
  916. ],
  917. followUpAsk: [{ required: true, message: "请输入回访要求", trigger: "blur" }],
  918. remind: [{ required: true, message: "请输入提醒设定", trigger: "blur" }],
  919. createGroupTime: [
  920. { required: true, message: "请选择建群时间", trigger: "change" },
  921. ],
  922. });
  923. if (props.isPrivate) {
  924. rules.value.userId = [
  925. { required: true, message: "请选择业务员", trigger: "change" },
  926. ];
  927. }
  928. const clickAddPerson = () => {
  929. if (
  930. formData.data.customerUserList &&
  931. formData.data.customerUserList.length > 0
  932. ) {
  933. formData.data.customerUserList.push({
  934. name: "",
  935. email: "",
  936. sex: "",
  937. position: "",
  938. tel: "",
  939. phone: "",
  940. qq: "",
  941. skype: "",
  942. facebook: "",
  943. isKp: "",
  944. weChat: "",
  945. wangWang: "",
  946. whatsApp: "",
  947. linkedIn: "",
  948. directLine: "",
  949. });
  950. } else {
  951. formData.data.customerUserList = [
  952. {
  953. name: "",
  954. email: "",
  955. sex: "",
  956. position: "",
  957. tel: "",
  958. phone: "",
  959. qq: "",
  960. skype: "",
  961. facebook: "",
  962. isKp: "",
  963. weChat: "",
  964. wangWang: "",
  965. whatsApp: "",
  966. linkedIn: "",
  967. directLine: "",
  968. },
  969. ];
  970. }
  971. };
  972. const formPerson = reactive({
  973. data: {},
  974. });
  975. const rulesPerson = ref({
  976. name: [{ required: true, message: "请输入", trigger: "blur" }],
  977. email: [{ required: true, message: "请输入电子邮箱", trigger: "blur" }],
  978. type: [{ required: true, message: "请选择类型", trigger: "change" }],
  979. contactNo: [{ required: true, message: "请输入联系号码", trigger: "blur" }],
  980. });
  981. const person = ref(null);
  982. const openPerson = ref(false);
  983. const moreIndex = ref(0);
  984. const clickInformationMore = (item, index) => {
  985. moreIndex.value = index;
  986. if (item.contactJson) {
  987. item.contact = JSON.parse(item.contactJson);
  988. } else {
  989. item.contact = [];
  990. }
  991. formPerson.data = proxy.deepClone(item);
  992. openPerson.value = true;
  993. };
  994. const clickDelete = (index) => {
  995. formData.data.customerUserList.splice(index, 1);
  996. };
  997. const clickAddMoreInformation = () => {
  998. if (formPerson.data.contact && formPerson.data.contact.length > 0) {
  999. formPerson.data.contact.push({
  1000. type: "",
  1001. contactNo: "",
  1002. });
  1003. } else {
  1004. formPerson.data.contact = [
  1005. {
  1006. type: "",
  1007. contactNo: "",
  1008. },
  1009. ];
  1010. }
  1011. };
  1012. const clickInformationDelete = (index) => {
  1013. formPerson.data.contact.splice(index, 1);
  1014. };
  1015. const submitPerson = () => {
  1016. person.value.validate((valid) => {
  1017. if (valid) {
  1018. formPerson.data.contactJson = JSON.stringify(formPerson.data.contact);
  1019. formData.data.customerUserList[moreIndex.value] = formPerson.data;
  1020. openPerson.value = false;
  1021. }
  1022. });
  1023. };
  1024. const handleSubmit = () => {
  1025. submit.value.handleSubmit(() => {
  1026. if (
  1027. formData.data.customerUserList &&
  1028. formData.data.customerUserList.length > 0
  1029. ) {
  1030. formData.data.tag = formData.data.tags.join(",");
  1031. loading.value = true;
  1032. proxy.post("/customer/" + modalType.value, formData.data).then(
  1033. () => {
  1034. ElMessage({
  1035. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  1036. type: "success",
  1037. });
  1038. proxy.$emit("refreshList");
  1039. loading.value = false;
  1040. },
  1041. (err) => {
  1042. console.log(err);
  1043. loading.value = false;
  1044. }
  1045. );
  1046. } else {
  1047. ElMessage("请添加客户联系人");
  1048. }
  1049. });
  1050. };
  1051. const querySearch = (queryString, callback) => {
  1052. proxy
  1053. .post("/customer/page", {
  1054. pageNum: 1,
  1055. pageSize: 20,
  1056. name: queryString,
  1057. })
  1058. .then((res) => {
  1059. if (res.rows && res.rows.length > 0) {
  1060. res.rows = res.rows.map((item) => {
  1061. return {
  1062. ...item,
  1063. value: item.name,
  1064. };
  1065. });
  1066. callback(res.rows);
  1067. } else {
  1068. callback([]);
  1069. }
  1070. });
  1071. };
  1072. defineExpose({
  1073. handleSubmit,
  1074. });
  1075. </script>
  1076. <style lang="scss" scoped>
  1077. </style>