SaleContractModal.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <template>
  2. <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" width="95%" @ok="handleSubmit" :maskClosable="false">
  3. <BasicForm @register="registerForm" ref="formRef" name="SaleContractForm">
  4. <template #quotationProjectName="props">
  5. <a-input-search
  6. v-model:value="props.values.quotationProjectName"
  7. :disabled="notAllowEdit"
  8. readonly
  9. AutoComplete="off"
  10. allow-clear
  11. enter-button="Search"
  12. @search="onSearchProject(props)"
  13. />
  14. </template>
  15. </BasicForm>
  16. <!-- 子表单区域 -->
  17. <a-tabs v-model:activeKey="activeKey" animated @change="handleChangeTabs" style="padding: 24px; padding-top: 0px">
  18. <a-tab-pane tab="销售合同-产品明细" key="saleContractProduct" :forceRender="true">
  19. <a-button type="primary" @click="seleteQuotation" style="margin-top: 10px; margin-bottom: 5px; margin-right: 1%">
  20. 选择报价单(selete quotation)</a-button
  21. >
  22. <a-button type="primary" @click="selectProducts" style="margin-top: 10px; margin-bottom: 5px"> 选择产品(select product)</a-button>
  23. <JVxeTable
  24. keep-source
  25. resizable
  26. ref="saleContractProduct"
  27. :loading="saleContractProductTable.loading"
  28. :columns="saleContractProductTable.columns"
  29. :dataSource="saleContractProductTable.dataSource"
  30. :maxHeight="340"
  31. :rowNumber="true"
  32. :rowSelection="true"
  33. :disabled="formDisabled"
  34. >
  35. <template #action="props">
  36. <!-- <a>关闭(close)</a>
  37. <a-divider type="vertical"/> -->
  38. <a-popconfirm title="确定删除吗?" @confirm="handleDelete1(props)">
  39. <a>删除(delete)</a>
  40. </a-popconfirm>
  41. </template>
  42. </JVxeTable>
  43. </a-tab-pane>
  44. <a-tab-pane tab="销售合同-船明细" key="saleContractShip" :forceRender="true">
  45. <JVxeTable
  46. keep-source
  47. resizable
  48. ref="saleContractShip"
  49. :loading="saleContractShipTable.loading"
  50. :columns="saleContractShipTable.columns"
  51. :dataSource="saleContractShipTable.dataSource"
  52. :maxHeight="340"
  53. :rowNumber="true"
  54. :rowSelection="true"
  55. :disabled="formDisabled"
  56. >
  57. <template #action="props">
  58. <a @click="viewAccessory(props)">查看配件信息(view accessory information)</a>
  59. <a-divider type="vertical" />
  60. <a-popconfirm title="确定删除吗?" @confirm="handleDelete(props)">
  61. <a>删除(delete)</a>
  62. </a-popconfirm>
  63. </template>
  64. </JVxeTable>
  65. </a-tab-pane>
  66. </a-tabs>
  67. <SelectProjectModal ref="SelectProjectModalRef" @select-project="addProject" />
  68. <BaseShipArchiveAccessoriesModal ref="BaseShipArchiveAccessoriesListRef" />
  69. <SelectPrpductModal ref="SelectPrpductModalRef" @select-product="addProduct" />
  70. <SelectQuotationModal ref="SelectQuotationModalRef" @select-quotation="addQuotation" />
  71. </BasicModal>
  72. </template>
  73. <script lang="ts" setup>
  74. import { ref, unref, reactive } from 'vue';
  75. import { BasicModal, useModalInner } from '/@/components/Modal';
  76. import { BasicForm, useForm } from '/@/components/Form/index';
  77. import { JVxeTable } from '/@/components/jeecg/JVxeTable';
  78. import { useJvxeMethod } from '/@/hooks/system/useJvxeMethods.ts';
  79. import { formSchema, saleContractShipColumns, saleContractProductColumns } from '../SaleContract.data';
  80. import {
  81. saveOrUpdate,
  82. saleContractShipList,
  83. saleContractProductList,
  84. querysaleVersonFormShipListByMainId,
  85. querySaleVersonProductListByMainId,
  86. queryVersonHistoryById,
  87. } from '../SaleContract.api';
  88. import { defHttp } from '/@/utils/http/axios';
  89. import SelectProjectModal from '../../../publicComponents/SelectProjectModal.vue';
  90. import SelectQuotationModal from '../../../publicComponents/SelectQuotationModal.vue';
  91. import BaseShipArchiveAccessoriesModal from '../../../publicComponents/BaseShipArchiveAccessoriesModal.vue';
  92. import SelectPrpductModal from '../../../publicComponents/SelectPrpductModal.vue';
  93. import { useUserStore } from '/@/store/modules/user';
  94. import moment from 'moment';
  95. import { message } from 'ant-design-vue';
  96. import { add } from '/@/components/Table/src/componentMap';
  97. // Emits声明
  98. const emit = defineEmits(['register', 'success']);
  99. const userStore = useUserStore();
  100. var customerOption = ref([]);
  101. const isUpdate = ref(true);
  102. var title = ref('');
  103. const formDisabled = ref(false);
  104. const refKeys = ref(['saleContractShip', 'saleContractProduct']);
  105. var notAllowEdit = ref(false);
  106. const activeKey = ref('saleContractProduct');
  107. const saleContractShip = ref();
  108. const saleContractProduct = ref();
  109. const SelectQuotationModalRef = ref();
  110. var SelectProjectModalRef = ref();
  111. var SelectPrpductModalRef = ref();
  112. var BaseShipArchiveAccessoriesListRef = ref();
  113. const tableRefs = { saleContractShip, saleContractProduct };
  114. const saleContractShipTable = reactive({
  115. loading: false,
  116. dataSource: [],
  117. columns: saleContractShipColumns,
  118. });
  119. const saleContractProductTable = reactive({
  120. loading: false,
  121. dataSource: [],
  122. columns: saleContractProductColumns,
  123. });
  124. //表单配置
  125. const [registerForm, { setProps, resetFields, setFieldsValue, validate, getFieldsValue }] = useForm({
  126. schemas: formSchema,
  127. showActionButtonGroup: false,
  128. baseColProps: { span: 12 },
  129. });
  130. //表单赋值
  131. const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
  132. //重置表单
  133. await reset();
  134. getCustomerOptions();
  135. setModalProps({ confirmLoading: false, showCancelBtn: data?.showFooter, showOkBtn: data?.showFooter });
  136. isUpdate.value = !!data?.isUpdate;
  137. formDisabled.value = !data?.showFooter;
  138. title.value = data?.isUpdate ? (unref(formDisabled) ? '详情' : '编辑') : '新增';
  139. title.value = data.isRevise ? '修订(Revise)' : title.value;
  140. if (data.history == 'yes') {
  141. const row = await queryVersonHistoryById(data.record.id);
  142. await setFieldsValue({ ...row });
  143. const saleContractShipList = await querysaleVersonFormShipListByMainId(data.record.id);
  144. saleContractShipTable.dataSource = [...saleContractShipList];
  145. const saleContractProductList = await querySaleVersonProductListByMainId(data.record.id);
  146. saleContractProductTable.dataSource = [...saleContractProductList];
  147. } else if (unref(isUpdate)) {
  148. //表单赋值
  149. await setFieldsValue({
  150. ...data.record,
  151. });
  152. requestSubTableData(saleContractShipList, { id: data?.record?.id }, saleContractShipTable);
  153. requestSubTableData(saleContractProductList, { id: data?.record?.id }, saleContractProductTable);
  154. notAllowEdit.value = true;
  155. } else {
  156. await setFieldsValue({ billDate: moment(new Date()).format('YYYY-MM-DD') });
  157. await setFieldsValue({ salesman: userStore.getUserInfo.username });
  158. await setFieldsValue({ saleDepartment: userStore.getUserInfo.orgCode });
  159. await setFieldsValue({ salesmanName: userStore.getUserInfo.realname });
  160. await setFieldsValue({ saleDepartmentName: userStore.getUserInfo.orgName });
  161. }
  162. // 隐藏底部时禁用整个表单
  163. setProps({ disabled: !data?.showFooter });
  164. });
  165. //方法配置
  166. const [handleChangeTabs, handleSubmit, requestSubTableData, formRef] = useJvxeMethod(
  167. requestAddOrEdit,
  168. classifyIntoFormData,
  169. tableRefs,
  170. activeKey,
  171. refKeys
  172. );
  173. // //设置标题
  174. // const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(formDisabled) ? '编辑' : '详情'));
  175. async function reset() {
  176. await resetFields();
  177. activeKey.value = 'saleContractProduct';
  178. saleContractShipTable.dataSource = [];
  179. saleContractProductTable.dataSource = [];
  180. }
  181. function classifyIntoFormData(allValues) {
  182. if (allValues.formValue.sourceCode == '' || !allValues.formValue.sourceCode) {
  183. message.error('请选择报价单');
  184. } else {
  185. let main = Object.assign({}, allValues.formValue);
  186. return {
  187. ...main, // 展开
  188. saleContractShipList: allValues.tablesValue[0].tableData,
  189. saleContractProductList: allValues.tablesValue[1].tableData,
  190. };
  191. }
  192. }
  193. //表单提交事件
  194. async function requestAddOrEdit(values) {
  195. try {
  196. setModalProps({ confirmLoading: true });
  197. const isRevise = values.status == '1' ? true : false;
  198. //提交表单
  199. await saveOrUpdate(values, isUpdate.value, isRevise);
  200. //关闭弹窗
  201. closeModal();
  202. //刷新列表
  203. emit('success');
  204. } finally {
  205. setModalProps({ confirmLoading: false });
  206. }
  207. }
  208. function onSearchProject(prop) {
  209. SelectProjectModalRef.value.getTable();
  210. }
  211. async function addProject(data) {
  212. if (data.length == 0) {
  213. await setFieldsValue({ quotationProjectName: '' });
  214. await setFieldsValue({ quotationProject: '' });
  215. } else {
  216. await setFieldsValue({ quotationProjectName: data[0].code });
  217. await setFieldsValue({ quotationProject: data[0].id });
  218. await setFieldsValue({ quotationCustomerName: data[0].customerId_dictText });
  219. await setFieldsValue({ quotationCustomer: data[0].customerId });
  220. customerOption.value.map((item) => {
  221. if (item.value == data[0].customerId) {
  222. setFieldsValue({ priority: item.priority });
  223. }
  224. });
  225. }
  226. }
  227. function getCustomerOptions() {
  228. let params = { pageSize: '-1', status: 1 };
  229. defHttp.get({ url: '/cuspCode/cuspCustomerProfile/list', params }, { isTransformResponse: false }).then((res) => {
  230. if (res) {
  231. customerOption.value = [];
  232. res.result.records.forEach((item) => {
  233. customerOption.value.push({
  234. label: item.name,
  235. value: item.id,
  236. priority: item.priority,
  237. });
  238. });
  239. }
  240. });
  241. }
  242. async function handleDelete(prop) {
  243. var newArray = [...saleContractShipTable.dataSource];
  244. newArray.splice(prop.rowIndex, 1);
  245. saleContractShipTable.dataSource = newArray;
  246. }
  247. function viewAccessory(prop) {
  248. BaseShipArchiveAccessoriesListRef.value.getTable(prop.row);
  249. }
  250. function selectProducts() {
  251. SelectPrpductModalRef.value.getTable();
  252. }
  253. async function seleteQuotation() {
  254. let fieldsValue = await getFieldsValue();
  255. fieldsValue.project = fieldsValue.quotationProject;
  256. fieldsValue.projectName = fieldsValue.quotationProjectName;
  257. SelectQuotationModalRef.value.getTable(fieldsValue);
  258. }
  259. function addProduct(data) {
  260. data.map((item) => {
  261. item.productClass = item.classId_dictText;
  262. item.productCode = item.code;
  263. item.unit = item.measurementUnit;
  264. item.productId = item.id;
  265. });
  266. var arrProduct = data.concat(saleContractProductTable.dataSource);
  267. saleContractProductTable.dataSource = arrProduct;
  268. }
  269. async function handleDelete1(prop) {
  270. var newArray = [...saleContractProductTable.dataSource];
  271. newArray.splice(prop.rowIndex, 1);
  272. saleContractProductTable.dataSource = newArray;
  273. if (saleContractProductTable.dataSource.length !== 0) {
  274. var arr = [];
  275. saleContractProductTable.dataSource.map((item) => {
  276. if (item.sourceId) {
  277. arr.push(item.sourceId);
  278. }
  279. });
  280. if (arr.length == 0) {
  281. setFieldsValue({ sourceCode: '' });
  282. notAllowEdit.value = false;
  283. }
  284. } else {
  285. setFieldsValue({ sourceCode: '' });
  286. notAllowEdit.value = false;
  287. reset();
  288. setFieldsValue({ billDate: moment(new Date()).format('YYYY-MM-DD') });
  289. }
  290. }
  291. function addQuotation(data) {
  292. var time = getFieldsValue()
  293. data.map((item) => {
  294. item.model = item.childModel;
  295. item.sourceId = item.childId;
  296. item.taxPrice = item.salePrice;
  297. item.deliveryTime = moment(time.billDate).add(Number(item.deliveryDayChild), 'days').format('YYYY-MM-DD');
  298. });
  299. var arrProduct = data.concat(saleContractProductTable.dataSource);
  300. saleContractProductTable.dataSource = arrProduct;
  301. notAllowEdit.value = true;
  302. setFieldsValue({
  303. sourceCode: data[0].billCode,
  304. quotationProjectName: data[0].quotationProjectName,
  305. quotationProject: data[0].quotationProject,
  306. quotationCustomerName: data[0].quotationCustomerName,
  307. quotationCustomer: data[0].quotationCustomer,
  308. priority: data[0].priority,
  309. productionClass: data[0].productionClass,
  310. model: data[0].headModel,
  311. maker: data[0].maker,
  312. currency: data[0].currency,
  313. exchangeRate: data[0].exchangeRate,
  314. paymentTerms:data[0].paymentTerms,
  315. deliveryTerms:data[0].deliveryTerms
  316. });
  317. getShipList(data[0].headId);
  318. }
  319. function getShipList(id) {
  320. let params = { id: id };
  321. defHttp.get({ url: '/saleCode/saleQuotation/querySaleQuotationShipByMainId', params }, { isTransformResponse: false }).then((res) => {
  322. if (res) {
  323. saleContractShipTable.dataSource = res.result;
  324. }
  325. });
  326. }
  327. </script>
  328. <style lang="less" scoped>
  329. /** 时间和数字输入框样式 */
  330. :deep(.ant-input-number) {
  331. width: 100%;
  332. }
  333. :deep(.ant-calendar-picker) {
  334. width: 100%;
  335. }
  336. /deep/.ant-form-item {
  337. margin-bottom: 8px;
  338. }
  339. /deep/.ant-tabs-nav {
  340. margin: 0px !important;
  341. }
  342. /deep/.ant-modal-body {
  343. padding: 24px !important;
  344. }
  345. </style>