add.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. <template>
  2. <div class="form">
  3. <van-nav-bar
  4. :title="$t('salesContract.name')"
  5. :left-text="$t('common.back')"
  6. left-arrow
  7. @click-left="onClickLeft"
  8. >
  9. </van-nav-bar>
  10. <testForm
  11. v-model="formData.data"
  12. :formOption="formOption"
  13. :formConfig="formConfig"
  14. :rules="rules"
  15. @onSubmit="onSubmit"
  16. ref="formDom"
  17. ></testForm>
  18. </div>
  19. </template>
  20. <script setup>
  21. import { ref, reactive, getCurrentInstance, onMounted } from "vue";
  22. import { showSuccessToast, showFailToast } from "vant";
  23. import { useRoute } from "vue-router";
  24. import testForm from "@/components/testForm/index.vue";
  25. const proxy = getCurrentInstance().proxy;
  26. const route = useRoute();
  27. const formDom = ref(null);
  28. const formData = reactive({
  29. data: {
  30. salesContractDetailsList: [],
  31. },
  32. });
  33. const rules = {
  34. customerId: [
  35. {
  36. required: true,
  37. message: proxy.t("salesContract.pleaseSelectTheCustomerName"),
  38. },
  39. ],
  40. // deliveryDate: [
  41. // {
  42. // required: true,
  43. // message: proxy.t("salesContract.pleaseSelectTheDeliveryDeadline"),
  44. // },
  45. // ],
  46. payMethod: [
  47. {
  48. required: true,
  49. message: proxy.t("salesContract.pleaseSelectThePaymentMethod"),
  50. },
  51. ],
  52. freightPayer: [
  53. {
  54. required: true,
  55. message: proxy.t("salesContract.PleaseSelectTheFreightPayer"),
  56. },
  57. ],
  58. productId: [
  59. {
  60. required: true,
  61. message: proxy.t("salesContract.pleaseSelectTheProductName"),
  62. },
  63. ],
  64. isCustomized: [
  65. {
  66. required: true,
  67. message: proxy.t("salesContract.pleaseSelectWhetherToCustomize"),
  68. },
  69. ],
  70. unitPrice: [
  71. {
  72. required: true,
  73. message: proxy.t("salesContract.pleaseEnterTheUnitPrice"),
  74. },
  75. ],
  76. quantity: [
  77. {
  78. required: true,
  79. message: proxy.t("salesContract.pleaseEnterTheQuantity"),
  80. },
  81. ],
  82. };
  83. const formOption = reactive({
  84. readonly: false, //用于控制整个表单是否只读
  85. disabled: false,
  86. labelAlign: "top",
  87. scroll: true,
  88. labelWidth: "62pk",
  89. hiddenSubmitBtn: false,
  90. btnConfig: {
  91. isNeed: true,
  92. prop: "salesContractDetailsList",
  93. plain: true,
  94. listTitle: proxy.t("salesContract.contractDetails"),
  95. listConfig: [
  96. {
  97. type: "picker",
  98. label: proxy.t("salesContract.productName"),
  99. prop: "productId",
  100. itemType: "onePicker",
  101. showPicker: false,
  102. readonly: false,
  103. fieldNames: {
  104. text: "label",
  105. value: "value",
  106. },
  107. data: [],
  108. isNeedSearch: true, //是否需要关键字过滤数据
  109. searchKeyword: "",
  110. onSearchData: (keyword) => {
  111. getProductData(keyword);
  112. },
  113. },
  114. {
  115. type: "picker",
  116. label: proxy.t("salesContract.whetherToCustomize"),
  117. prop: "isCustomized",
  118. itemType: "onePicker",
  119. showPicker: false,
  120. readonly: false,
  121. fieldNames: {
  122. text: "label",
  123. value: "value",
  124. },
  125. data: [
  126. {
  127. label: proxy.t("salesContract.yes"),
  128. value: "1",
  129. },
  130. {
  131. label: proxy.t("salesContract.no"),
  132. value: "0",
  133. },
  134. ],
  135. },
  136. {
  137. type: "input",
  138. itemType: "number",
  139. label: proxy.t("salesContract.unitPrice"),
  140. prop: "unitPrice",
  141. clearable: true,
  142. changeFn: (index, val) => {
  143. changeAmount(index);
  144. },
  145. },
  146. {
  147. type: "input",
  148. itemType: "digit",
  149. label: proxy.t("salesContract.quantity"),
  150. prop: "quantity",
  151. clearable: true,
  152. changeFn: (index, val) => {
  153. changeAmount(index);
  154. },
  155. },
  156. {
  157. type: "input",
  158. itemType: "number",
  159. label: proxy.t("salesContract.amountSubtotal"),
  160. prop: "total",
  161. placeholder: proxy.t(
  162. "salesContract.automaticallyCalculatedBasedOnUnitPriceAndQuantity"
  163. ),
  164. readonly: true,
  165. },
  166. {
  167. type: "input",
  168. itemType: "textarea",
  169. label: "备注",
  170. prop: "productRemark",
  171. },
  172. ],
  173. clickFn: () => {
  174. if (
  175. formData.data.salesContractDetailsList &&
  176. formData.data.salesContractDetailsList.length > 0
  177. ) {
  178. formData.data.salesContractDetailsList.push({
  179. productId: "",
  180. quantity: "",
  181. });
  182. } else {
  183. formData.data.salesContractDetailsList = [
  184. {
  185. productId: "",
  186. quantity: "",
  187. },
  188. ];
  189. }
  190. },
  191. },
  192. });
  193. const formConfig = reactive([
  194. {
  195. type: "picker",
  196. label: "卖方公司",
  197. prop: "sellCorporationId",
  198. itemType: "onePicker",
  199. showPicker: false,
  200. fieldNames: {
  201. text: "label",
  202. value: "value",
  203. },
  204. data: [],
  205. changeFn: (val, data) => {
  206. proxy.formChange(val, data, formData);
  207. changeSellId(val.selectedValues[0]);
  208. data.showPicker = false;
  209. },
  210. },
  211. {
  212. type: "input",
  213. itemType: "text",
  214. label: "国家",
  215. prop: "sellCountryName",
  216. },
  217. {
  218. type: "input",
  219. itemType: "text",
  220. label: "省",
  221. prop: "sellProvinceName",
  222. },
  223. {
  224. type: "input",
  225. itemType: "text",
  226. label: "城市",
  227. prop: "sellCityName",
  228. },
  229. {
  230. type: "input",
  231. itemType: "textarea",
  232. label: "详细地址",
  233. prop: "sellAddress",
  234. },
  235. {
  236. type: "picker",
  237. label: "收款账号",
  238. prop: "shroffAccountId",
  239. itemType: "onePicker",
  240. showPicker: false,
  241. fieldNames: {
  242. text: "label",
  243. value: "value",
  244. },
  245. data: [],
  246. changeFn: (val, data) => {
  247. proxy.formChange(val, data, formData);
  248. changeShroffAccount(val.selectedValues[0]);
  249. data.showPicker = false;
  250. },
  251. },
  252. {
  253. type: "input",
  254. itemType: "text",
  255. label: "账户名",
  256. prop: "sellAccountName",
  257. },
  258. {
  259. type: "input",
  260. itemType: "text",
  261. label: "开户行",
  262. prop: "sellOpeningBank",
  263. },
  264. {
  265. type: "input",
  266. itemType: "text",
  267. label: "账号",
  268. prop: "sellAccountOpening",
  269. },
  270. {
  271. type: "input",
  272. itemType: "text",
  273. label: "银行号",
  274. prop: "sellInterbankNumber",
  275. },
  276. {
  277. type: "picker",
  278. label: proxy.t("salesContract.customerName"),
  279. prop: "customerId",
  280. itemType: "onePicker",
  281. showPicker: false,
  282. fieldNames: {
  283. text: "label",
  284. value: "value",
  285. },
  286. data: [],
  287. isNeedSearch: true, //是否需要关键字过滤数据
  288. searchKeyword: "",
  289. onSearchData: (keyword) => {
  290. getCustomerData(keyword);
  291. },
  292. },
  293. {
  294. type: "picker",
  295. label: proxy.t("salesContract.deliveryDeadline"),
  296. prop: "deliveryDate",
  297. itemType: "datePicker",
  298. showPicker: false,
  299. split: "-",
  300. columnsType: ["year", "month", "day"],
  301. },
  302. {
  303. type: "picker",
  304. label: proxy.t("salesContract.paymentMethod"),
  305. prop: "payMethod",
  306. itemType: "onePicker",
  307. showPicker: false,
  308. fieldNames: {
  309. text: "label",
  310. value: "value",
  311. },
  312. data: [],
  313. },
  314. {
  315. type: "picker",
  316. label: proxy.t("salesContract.freightPayer"),
  317. prop: "freightPayer",
  318. itemType: "onePicker",
  319. showPicker: false,
  320. fieldNames: {
  321. text: "label",
  322. value: "value",
  323. },
  324. data: [
  325. {
  326. label: proxy.t("salesContract.partyA"),
  327. value: "0",
  328. },
  329. {
  330. label: proxy.t("salesContract.partyB"),
  331. value: "1",
  332. },
  333. ],
  334. },
  335. {
  336. type: "input",
  337. itemType: "textarea",
  338. label: "交货期限备注",
  339. prop: "deliveryDateRemark",
  340. },
  341. {
  342. type: "input",
  343. itemType: "textarea",
  344. label: "付款方式备注",
  345. prop: "payMethodRemark",
  346. },
  347. {
  348. type: "input",
  349. itemType: "textarea",
  350. label: proxy.t("salesContract.remarks"),
  351. prop: "remark",
  352. },
  353. {
  354. type: "input",
  355. itemType: "number",
  356. label: proxy.t("salesContract.contractTotalAmount"),
  357. prop: "contractAmount",
  358. readonly: true,
  359. },
  360. ]);
  361. const onClickLeft = () => history.back();
  362. const fundsPaymentMethod = ref([]);
  363. const customerData = ref([]);
  364. const accountList = ref([]);
  365. const corporationList = ref([]);
  366. const productData = ref([]);
  367. const getDict = () => {
  368. proxy.getDictOne(["funds_payment_method"]).then((res) => {
  369. fundsPaymentMethod.value = res["funds_payment_method"].data.map((x) => ({
  370. label: x.dictValue,
  371. value: x.dictKey,
  372. }));
  373. formConfig[12].data = fundsPaymentMethod.value;
  374. });
  375. proxy.post("/customer/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
  376. customerData.value = res.data.rows.map((x) => ({
  377. label: x.name,
  378. value: x.id,
  379. }));
  380. formConfig[10].data = customerData.value;
  381. });
  382. proxy
  383. .post("/productInfo/page", { pageNum: 1, pageSize: 9999, definition: "1" })
  384. .then((res) => {
  385. productData.value = res.data.rows.map((x) => ({
  386. label: x.name + ` (${x.spec})`,
  387. value: x.id,
  388. }));
  389. formOption.btnConfig.listConfig[0].data = productData.value;
  390. });
  391. proxy
  392. .post("/accountManagement/page", { pageNum: 1, pageSize: 999 })
  393. .then((res) => {
  394. accountList.value = res.data.rows.map((item) => {
  395. return {
  396. ...item,
  397. label: item.alias,
  398. value: item.id,
  399. };
  400. });
  401. formConfig[5].data = accountList.value;
  402. });
  403. proxy.post("/corporation/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  404. corporationList.value = res.data.rows.map((item) => {
  405. return {
  406. ...item,
  407. label: item.name,
  408. value: item.id,
  409. };
  410. });
  411. formConfig[0].data = corporationList.value;
  412. });
  413. };
  414. const getProductData = (keyword) => {
  415. proxy.post("/productInfo/page", { keyword, definition: "1" }).then((res) => {
  416. productData.value = res.data.rows.map((x) => ({
  417. label: x.name + ` (${x.spec})`,
  418. value: x.id,
  419. }));
  420. formOption.btnConfig.listConfig[0].data = productData.value;
  421. });
  422. };
  423. const getCustomerData = (keyword) => {
  424. proxy.post("/customer/page", { keyword }).then((res) => {
  425. customerData.value = res.data.rows.map((x) => ({
  426. label: x.name,
  427. value: x.id,
  428. }));
  429. formConfig[10].data = customerData.value;
  430. });
  431. };
  432. const getDetails = (id) => {
  433. proxy.post("/salesContract/detail", { id }).then((res) => {
  434. if (res.data && res.data.contractDetailsList.length > 0) {
  435. res.data.salesContractDetailsList = res.data.contractDetailsList;
  436. } else {
  437. res.data.salesContractDetailsList = [];
  438. }
  439. res.data.deliveryDate = res.data.deliveryDate.slice(0, 10);
  440. formData.data = res.data;
  441. changeAmount();
  442. });
  443. };
  444. onMounted(() => {
  445. getDict();
  446. if (route.query.id) {
  447. getDetails(route.query.id);
  448. formOption.readonly = true; //全部只读
  449. formOption.hiddenSubmitBtn = true; //隐藏提交按钮
  450. formOption.btnConfig.isNeed = false;
  451. }
  452. });
  453. const onSubmit = () => {
  454. if (formData.data.salesContractDetailsList.length > 0) {
  455. proxy
  456. .post("/flowProcess/initiate", {
  457. flowKey: "jxst_sales_contract_flow",
  458. data: formData.data,
  459. })
  460. .then(
  461. () => {
  462. showSuccessToast(proxy.t("common.operationSuccessful"));
  463. setTimeout(() => {
  464. onClickLeft();
  465. }, 500);
  466. },
  467. (err) => {
  468. return showFailToast(err.message);
  469. }
  470. );
  471. } else {
  472. return showFailToast(proxy.t("salesContract.pleaseAddContractDetails"));
  473. }
  474. };
  475. const changeSellId = (val) => {
  476. if (val) {
  477. proxy.post("/corporation/detail", { id: val }).then((res) => {
  478. let detailCorporation = res.data;
  479. if (detailCorporation.countryName) {
  480. formData.data.sellCountryName = detailCorporation.countryName;
  481. }
  482. if (detailCorporation.provinceName) {
  483. formData.data.sellProvinceName = detailCorporation.provinceName;
  484. }
  485. if (detailCorporation.cityName) {
  486. formData.data.sellCityName = detailCorporation.cityName;
  487. }
  488. if (detailCorporation.address) {
  489. formData.data.sellAddress = detailCorporation.address;
  490. }
  491. });
  492. }
  493. };
  494. const changeShroffAccount = (val) => {
  495. if (val) {
  496. let data = accountList.value.filter((item) => item.value === val);
  497. if (data && data.length > 0) {
  498. formData.data.sellAccountName = data[0].name;
  499. formData.data.sellOpeningBank = data[0].openingBank;
  500. formData.data.sellInterbankNumber = data[0].interbankNumber;
  501. formData.data.sellAccountOpening = data[0].accountOpening;
  502. }
  503. }
  504. };
  505. const changeAmount = (index) => {
  506. let total = 0;
  507. for (let i = 0; i < formData.data.salesContractDetailsList.length; i++) {
  508. const element = formData.data.salesContractDetailsList[i];
  509. if (element.unitPrice && element.quantity) {
  510. element.total = parseFloat(element.unitPrice * element.quantity).toFixed(
  511. 2
  512. );
  513. total += Number(element.total);
  514. }
  515. }
  516. if (total) {
  517. formData.data.contractAmount = total.toFixed(2);
  518. }
  519. };
  520. </script>
  521. <style lang="scss" scoped>
  522. .form {
  523. margin-bottom: 60px;
  524. }
  525. </style>