addCustomer.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. <template>
  2. <div>
  3. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit" v-loading="loading">
  4. <template #allAddress>
  5. <el-row style="width: 100%">
  6. <el-col :span="8">
  7. <el-form-item prop="countryId">
  8. <el-select v-model="formData.data.countryId" placeholder="国家" filterable @change="(val) => getCityData(val, '20', true)">
  9. <el-option v-for="item in countryData" :label="item.name" :value="item.id">
  10. </el-option>
  11. </el-select>
  12. </el-form-item>
  13. </el-col>
  14. <el-col :span="8">
  15. <el-form-item prop="provinceName">
  16. <selectCity placeholder="省/洲" @change="(val) => getCityData(val, '30', true)" addressId="provinceId" addressName="provinceName"
  17. v-model="formData.data" :data="provinceData">
  18. </selectCity>
  19. </el-form-item>
  20. </el-col>
  21. <el-col :span="8">
  22. <el-form-item prop="cityName">
  23. <selectCity placeholder="城市" addressId="cityId" addressName="cityName" v-model="formData.data" :data="cityData"></selectCity>
  24. </el-form-item>
  25. </el-col>
  26. </el-row>
  27. <el-row style="margin-top: 20px; width: 100%">
  28. <el-col :span="24">
  29. <el-form-item prop="address">
  30. <el-input v-model="formData.data.address" type="textarea">
  31. </el-input>
  32. </el-form-item>
  33. </el-col>
  34. </el-row>
  35. </template>
  36. <template #person>
  37. <div style="width: 100%">
  38. <el-button type="primary" @click="clickAddPerson">添 加</el-button>
  39. <el-table :data="formData.data.customerUserList" style="width: 100%; margin-top: 16px">
  40. <el-table-column label="联系人" width="160">
  41. <template #default="{ row, $index }">
  42. <div style="width: 100%">
  43. <el-form-item :prop="'customerUserList.' + $index + '.name'" :rules="rules.name2" :inline-message="true">
  44. <el-input v-model="row.name" placeholder="请输入联系人" />
  45. </el-form-item>
  46. </div>
  47. </template>
  48. </el-table-column>
  49. <el-table-column label="电子邮箱">
  50. <template #default="{ row, $index }">
  51. <div style="width: 100%">
  52. <el-form-item :prop="'customerUserList.' + $index + '.email'" :rules="rules.email" :inline-message="true">
  53. <el-input v-model="row.email" placeholder="请输入电子邮箱" />
  54. </el-form-item>
  55. </div>
  56. </template>
  57. </el-table-column>
  58. <el-table-column align="center" label="操作" width="120" fixed="right">
  59. <template #default="{ row, $index }">
  60. <el-button type="primary" link @click="clickInformationMore(row, $index)">更多</el-button>
  61. <el-button type="primary" link @click="clickDelete($index)">删除</el-button>
  62. </template>
  63. </el-table-column>
  64. </el-table>
  65. </div>
  66. </template>
  67. </byForm>
  68. <el-dialog title="更多联系方式" v-if="openPerson" v-model="openPerson" width="700">
  69. <el-form :label-position="'top'" :model="formPerson.data" :rules="rulesPerson" ref="person">
  70. <el-form-item label="联系人" prop="name">
  71. <el-input v-model="formPerson.data.name" />
  72. </el-form-item>
  73. <el-form-item label="电子邮箱" prop="email">
  74. <el-input v-model="formPerson.data.email" />
  75. </el-form-item>
  76. <el-form-item label="更多联系方式">
  77. <div style="width: 100%">
  78. <el-button type="primary" @click="clickAddMoreInformation">添 加</el-button>
  79. <el-table :data="formPerson.data.contact" style="width: 100%; margin-top: 16px">
  80. <el-table-column label="类型" width="180">
  81. <template #default="{ row, $index }">
  82. <div style="width: 100%">
  83. <el-form-item :prop="'contact.' + $index + '.type'" :rules="rulesPerson.type" :inline-message="true">
  84. <el-select v-model="row.type" placeholder="请选择类型" style="width: 100%">
  85. <el-option v-for="item in contactType" :key="item.value" :label="item.label" :value="item.value" />
  86. </el-select>
  87. </el-form-item>
  88. </div>
  89. </template>
  90. </el-table-column>
  91. <el-table-column label="联系号码">
  92. <template #default="{ row, $index }">
  93. <div style="width: 100%">
  94. <el-form-item :prop="'contact.' + $index + '.contactNo'" :rules="rulesPerson.contactNo" :inline-message="true">
  95. <el-input v-model="row.contactNo" placeholder="请输入联系号码" />
  96. </el-form-item>
  97. </div>
  98. </template>
  99. </el-table-column>
  100. <el-table-column align="center" label="操作" width="120" fixed="right">
  101. <template #default="{ $index }">
  102. <el-button type="primary" link @click="clickInformationDelete($index)">删除</el-button>
  103. </template>
  104. </el-table-column>
  105. </el-table>
  106. </div>
  107. </el-form-item>
  108. </el-form>
  109. <template #footer>
  110. <el-button @click="openPerson = false" size="large">取 消</el-button>
  111. <el-button type="primary" @click="submitPerson()" size="large">确 定</el-button>
  112. </template>
  113. </el-dialog>
  114. </div>
  115. </template>
  116. <script setup>
  117. import { ElMessage, ElMessageBox } from "element-plus";
  118. import byForm from "@/components/byForm/index";
  119. import useUserStore from "@/store/modules/user";
  120. import selectCity from "@/components/selectCity/index.vue";
  121. const props = defineProps({
  122. modalType: String,
  123. customerId: String,
  124. isPrivate: {
  125. type: Boolean,
  126. default: false,
  127. },
  128. isHighseas: {
  129. type: Boolean,
  130. default: false,
  131. },
  132. });
  133. const modalType = ref("add");
  134. const isHighseas = ref(false);
  135. isHighseas.value = props.isHighseas;
  136. const customerId = ref("");
  137. const { proxy } = getCurrentInstance();
  138. const loading = ref(false);
  139. const customerTag = ref([]);
  140. const customerSource = ref([]);
  141. const customerStatus = ref([]);
  142. const contactType = ref([]);
  143. const userList = ref([]);
  144. const submit = ref(null);
  145. const formData = reactive({
  146. data: {
  147. countryId: "44",
  148. },
  149. });
  150. const getDict = () => {
  151. proxy
  152. .getDictOne([
  153. "customer_tag",
  154. "customer_source",
  155. "customer_status",
  156. "contact_type",
  157. ])
  158. .then((res) => {
  159. customerTag.value = res["customer_tag"].map((x) => ({
  160. label: x.dictValue,
  161. value: x.dictKey,
  162. }));
  163. customerSource.value = res["customer_source"].map((x) => ({
  164. label: x.dictValue,
  165. value: x.dictKey,
  166. }));
  167. customerStatus.value = res["customer_status"].map((x) => ({
  168. label: x.dictValue,
  169. value: x.dictKey,
  170. }));
  171. contactType.value = res["contact_type"].map((x) => ({
  172. label: x.dictValue,
  173. value: x.dictKey,
  174. }));
  175. });
  176. proxy
  177. .get("/tenantUser/list", {
  178. pageNum: 1,
  179. pageSize: 10000,
  180. tenantId: useUserStore().user.tenantId,
  181. })
  182. .then((res) => {
  183. userList.value = res.rows.map((item) => {
  184. return {
  185. label: item.nickName,
  186. value: item.userId,
  187. };
  188. });
  189. });
  190. };
  191. getDict();
  192. const countryData = ref([]);
  193. const provinceData = ref([]);
  194. const cityData = ref([]);
  195. const getCityData = (id, type, isChange) => {
  196. proxy.post("/customizeArea/list", { parentId: id }).then((res) => {
  197. if (type === "20") {
  198. provinceData.value = res;
  199. if (isChange) {
  200. formData.data.provinceId = "";
  201. formData.data.provinceName = "";
  202. formData.data.cityId = "";
  203. formData.data.cityName = "";
  204. }
  205. } else if (type === "30") {
  206. cityData.value = res;
  207. if (isChange) {
  208. formData.data.cityId = "";
  209. formData.data.cityName = "";
  210. }
  211. } else {
  212. countryData.value = res;
  213. }
  214. });
  215. };
  216. getCityData("0");
  217. const getDtl = () => {
  218. loading.value = true;
  219. proxy.post("/customer/detail", { id: customerId.value }).then((res) => {
  220. if (res.tag) {
  221. res.tags = res.tag.split(",");
  222. } else {
  223. res.tags = [];
  224. }
  225. formData.data = res;
  226. getCityData(formData.data.countryId, "20");
  227. if (formData.data.provinceId) {
  228. getCityData(formData.data.provinceId, "30");
  229. }
  230. loading.value = false;
  231. });
  232. };
  233. if (props && props.modalType) {
  234. modalType.value = props.modalType;
  235. if (modalType.value == "add") {
  236. formData.data = {
  237. countryId: "44",
  238. tags: [],
  239. customerUserList: [
  240. {
  241. name: "",
  242. email: "",
  243. },
  244. ],
  245. };
  246. getCityData(formData.data.countryId, "20");
  247. } else if (modalType.value == "edit" && props.customerId) {
  248. customerId.value = props.customerId;
  249. getDtl();
  250. }
  251. }
  252. const formOption = reactive({
  253. inline: true,
  254. labelWidth: 100,
  255. itemWidth: 100,
  256. rules: [],
  257. });
  258. const formConfig = computed(() => {
  259. return [
  260. {
  261. type: "input",
  262. prop: "name",
  263. label: "客户名称",
  264. required: true,
  265. itemWidth: 100,
  266. itemType: "text",
  267. },
  268. {
  269. type: "slot",
  270. slotName: "allAddress",
  271. label: "详细地址",
  272. },
  273. {
  274. type: "select",
  275. label: "客户来源",
  276. prop: "source",
  277. itemWidth: 50,
  278. data: customerSource.value,
  279. },
  280. {
  281. type: "select",
  282. label: "客户类型",
  283. prop: "status",
  284. itemWidth: 50,
  285. data: customerStatus.value,
  286. },
  287. {
  288. type: "select",
  289. label: "业务员",
  290. prop: "userId",
  291. itemWidth: 100,
  292. data: userList.value,
  293. clearable: true,
  294. disabled: modalType.value == "edit" || isHighseas.value,
  295. },
  296. {
  297. type: "select",
  298. label: "客户标签",
  299. prop: "tags",
  300. itemWidth: 100,
  301. multiple: true,
  302. data: customerTag.value,
  303. style: {
  304. width: "100%",
  305. },
  306. },
  307. {
  308. type: "input",
  309. prop: "beneficiaryName",
  310. label: "Beneficiary Name",
  311. required: true,
  312. itemWidth: 50,
  313. itemType: "text",
  314. },
  315. {
  316. type: "input",
  317. prop: "beneficiaryAccountNumber",
  318. label: "Beneficiary Account Number",
  319. required: true,
  320. itemWidth: 50,
  321. itemType: "text",
  322. },
  323. {
  324. type: "input",
  325. prop: "beneficiaryBank",
  326. label: "Beneficiary Bank",
  327. required: true,
  328. itemWidth: 50,
  329. itemType: "text",
  330. },
  331. {
  332. type: "input",
  333. prop: "swiftCode",
  334. label: "Swift Code",
  335. required: true,
  336. itemWidth: 50,
  337. itemType: "text",
  338. },
  339. {
  340. type: "input",
  341. prop: "beneficiaryBankAddress",
  342. label: "Beneficiary Bank Address",
  343. required: true,
  344. itemWidth: 50,
  345. itemType: "text",
  346. },
  347. {
  348. type: "input",
  349. prop: "beneficiaryAddress",
  350. label: "Beneficiary Address",
  351. required: true,
  352. itemWidth: 50,
  353. itemType: "text",
  354. },
  355. {
  356. type: "slot",
  357. slotName: "person",
  358. label: "客户联系人",
  359. },
  360. ];
  361. });
  362. const rules = ref({
  363. name: [{ required: true, message: "请输入客户名称", trigger: "blur" }],
  364. name2: [{ required: true, message: "请输入联系人", trigger: "blur" }],
  365. email: [{ required: true, message: "请输入电子邮箱", trigger: "blur" }],
  366. countryId: [{ required: true, message: "请选择国家", trigger: "change" }],
  367. source: [{ required: true, message: "请选择客户来源", trigger: "change" }],
  368. status: [{ required: true, message: "请选择类型", trigger: "change" }],
  369. });
  370. if (props.isPrivate) {
  371. rules.value.userId = [
  372. { required: true, message: "请选择业务员", trigger: "change" },
  373. ];
  374. }
  375. const clickAddPerson = () => {
  376. if (
  377. formData.data.customerUserList &&
  378. formData.data.customerUserList.length > 0
  379. ) {
  380. formData.data.customerUserList.push({
  381. name: "",
  382. email: "",
  383. });
  384. } else {
  385. formData.data.customerUserList = [
  386. {
  387. name: "",
  388. email: "",
  389. },
  390. ];
  391. }
  392. };
  393. const formPerson = reactive({
  394. data: {},
  395. });
  396. const rulesPerson = ref({
  397. name: [{ required: true, message: "请输入联系人", trigger: "blur" }],
  398. email: [{ required: true, message: "请输入电子邮箱", trigger: "blur" }],
  399. type: [{ required: true, message: "请选择类型", trigger: "change" }],
  400. contactNo: [{ required: true, message: "请输入联系号码", trigger: "blur" }],
  401. });
  402. const person = ref(null);
  403. const openPerson = ref(false);
  404. const moreIndex = ref(0);
  405. const clickInformationMore = (item, index) => {
  406. moreIndex.value = index;
  407. if (item.contactJson) {
  408. item.contact = JSON.parse(item.contactJson);
  409. } else {
  410. item.contact = [];
  411. }
  412. formPerson.data = proxy.deepClone(item);
  413. openPerson.value = true;
  414. };
  415. const clickDelete = (index) => {
  416. formData.data.customerUserList.splice(index, 1);
  417. };
  418. const clickAddMoreInformation = () => {
  419. if (formPerson.data.contact && formPerson.data.contact.length > 0) {
  420. formPerson.data.contact.push({
  421. type: "",
  422. contactNo: "",
  423. });
  424. } else {
  425. formPerson.data.contact = [
  426. {
  427. type: "",
  428. contactNo: "",
  429. },
  430. ];
  431. }
  432. };
  433. const clickInformationDelete = (index) => {
  434. formPerson.data.contact.splice(index, 1);
  435. };
  436. const submitPerson = () => {
  437. person.value.validate((valid) => {
  438. if (valid) {
  439. formPerson.data.contactJson = JSON.stringify(formPerson.data.contact);
  440. formData.data.customerUserList[moreIndex.value] = formPerson.data;
  441. openPerson.value = false;
  442. }
  443. });
  444. };
  445. const handleSubmit = () => {
  446. submit.value.handleSubmit(() => {
  447. if (
  448. formData.data.customerUserList &&
  449. formData.data.customerUserList.length > 0
  450. ) {
  451. formData.data.tag = formData.data.tags.join(",");
  452. loading.value = true;
  453. proxy.post("/customer/" + modalType.value, formData.data).then(
  454. () => {
  455. ElMessage({
  456. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  457. type: "success",
  458. });
  459. proxy.$emit("refreshList");
  460. loading.value = false;
  461. },
  462. (err) => {
  463. console.log(err);
  464. loading.value = false;
  465. }
  466. );
  467. } else {
  468. ElMessage("请添加客户联系人");
  469. }
  470. });
  471. };
  472. defineExpose({
  473. handleSubmit,
  474. });
  475. </script>
  476. <style lang="scss" scoped>
  477. </style>