quotationFormForm.vue 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. <template>
  2. <a-spin :spinning="loading">
  3. <JFormContainer :disabled="disabled">
  4. <template #detail>
  5. <a-form v-bind="formItemLayout" name="quotationFormForm" ref="formRef">
  6. <a-row>
  7. <a-col :span="12">
  8. <a-form-item
  9. label="报价单号(bill code)"
  10. v-bind="validateInfos.billCode"
  11. id="quotationFormForm-billCode"
  12. name="billCode"
  13. :labelCol="formItemLayout.labelCol1"
  14. :wrapperCol="formItemLayout.wrapperCol1"
  15. >
  16. <a-input v-model:value="formData.billCode" placeholder="自动生成" disabled />
  17. </a-form-item>
  18. </a-col>
  19. <a-col :span="12">
  20. <a-form-item label="单据日期(bill date)" v-bind="validateInfos.billDate" id="quotationFormForm-billDate" name="billDate">
  21. <a-date-picker
  22. placeholder="请选择单据日期(bill date)"
  23. v-model:value="formData.billDate"
  24. value-format="YYYY-MM-DD"
  25. disabled
  26. style="width: 100%"
  27. allow-clear
  28. />
  29. </a-form-item>
  30. </a-col>
  31. <a-col :span="12">
  32. <a-form-item label="报价项目(quotation project)" v-bind="validateInfos.quotationProjectName" id="quotationFormForm-quotationProjectName" name="quotationProjectName">
  33. <a-input-search
  34. v-model:value="formData.quotationProjectName"
  35. readonly
  36. placeholder="请输入报价项目(inquiry project)"
  37. allow-clear
  38. enter-button="Search"
  39. :disabled="notAllowEdit"
  40. @search="onSearchProject"
  41. />
  42. </a-form-item>
  43. </a-col>
  44. <a-col :span="12">
  45. <a-form-item
  46. label="报价客户(quotation customer)"
  47. v-bind="validateInfos.quotationCustomer"
  48. id="quotationFormForm-quotationCustomer"
  49. name="quotationCustomer"
  50. :labelCol="formItemLayout.labelCol1"
  51. :wrapperCol="formItemLayout.wrapperCol1"
  52. >
  53. <JSelectInput v-model:value="formData.quotationCustomer" placeholder="请选择" :options="customerOption" disabled />
  54. </a-form-item>
  55. </a-col>
  56. <a-col :span="12">
  57. <a-form-item
  58. label="报价有效期(quotation period)"
  59. v-bind="validateInfos.quotationPeriod"
  60. id="quotationFormForm-quotationPeriod"
  61. name="quotationPeriod"
  62. >
  63. <a-range-picker
  64. v-model:value="quotationPeriod"
  65. :format="['YYYY-MM-DD', 'YYYY-MM-DD']"
  66. @change="onChangequotationPeriod"
  67. style="width: 100%"
  68. />
  69. </a-form-item>
  70. </a-col>
  71. <a-col :span="12">
  72. <a-form-item label="优先级(priority)" v-bind="validateInfos.priority" id="quotationFormForm-priority" name="priority">
  73. <JDictSelectTag v-model:value="formData.priority" placeholder="请选择" dictCode="priority" />
  74. </a-form-item>
  75. </a-col>
  76. <a-col :span="12">
  77. <a-form-item
  78. label="产品分类(production class)"
  79. v-bind="validateInfos.productionClass"
  80. id="quotationFormForm-productionClass"
  81. name="productionClass"
  82. :labelCol="formItemLayout.labelCol1"
  83. :wrapperCol="formItemLayout.wrapperCol1"
  84. >
  85. <JDictSelectTag
  86. v-model:value="formData.productionClass"
  87. placeholder=""
  88. dictCode="base_product_class,name,id,del_flag=0 and parent_id is null"
  89. page="false"
  90. showSearch
  91. />
  92. </a-form-item>
  93. </a-col>
  94. <a-col :span="12">
  95. <a-form-item label="机型(model)" v-bind="validateInfos.model" id="quotationFormForm-model" name="model">
  96. <JSelectMultiple v-model:value="formData.model" placeholder="请选择" dictCode="model_typer" />
  97. </a-form-item>
  98. </a-col>
  99. <a-col :span="12">
  100. <a-form-item
  101. label="厂家(maker)"
  102. v-bind="validateInfos.maker"
  103. id="quotationFormForm-maker"
  104. name="maker"
  105. :labelCol="formItemLayout.labelCol1"
  106. :wrapperCol="formItemLayout.wrapperCol1"
  107. >
  108. <JDictSelectTag v-model:value="formData.maker" placeholder="请选择" dictCode="factory" />
  109. </a-form-item>
  110. </a-col>
  111. <a-col :span="12">
  112. <a-form-item
  113. label="币种(currency)"
  114. v-bind="validateInfos.currency"
  115. id="quotationFormForm-currency"
  116. name="currency"
  117. :labelCol="formItemLayout.labelCol1"
  118. :wrapperCol="formItemLayout.wrapperCol1"
  119. >
  120. <JDictSelectTag v-model:value="formData.currency" placeholder="请选择" dictCode="currency" @select="changeExchangeRate" />
  121. </a-form-item>
  122. </a-col>
  123. <a-col :span="12">
  124. <a-form-item label="汇率(exchangeRate)" v-bind="validateInfos.exchangeRate" id="quotationFormForm-exchangeRate" name="exchangeRate">
  125. <a-input-number
  126. v-model:value="formData.exchangeRate"
  127. placeholder="请输入"
  128. allow-clear
  129. AutoComplete="off"
  130. @change="changeDiscountOrExchangeRate"
  131. suffix="%"
  132. />
  133. </a-form-item>
  134. </a-col>
  135. <a-col :span="12">
  136. <a-form-item
  137. label="贸易方式(delivery terms)"
  138. v-bind="validateInfos.deliveryTerms"
  139. id="quotationFormForm-deliveryTerms"
  140. name="deliveryTerms"
  141. :labelCol="formItemLayout.labelCol1"
  142. :wrapperCol="formItemLayout.wrapperCol1"
  143. >
  144. <JDictSelectTag v-model:value="formData.deliveryTerms" placeholder="请选择" dictCode="delivery_terms" />
  145. </a-form-item>
  146. </a-col>
  147. <a-col :span="12">
  148. <a-form-item
  149. label="交期(delivery time)"
  150. v-bind="validateInfos.deliveryDayHead"
  151. id="quotationFormForm-deliveryDayHead"
  152. name="deliveryDayHead"
  153. >
  154. <a-input-number
  155. placeholder=""
  156. v-model:value="formData.deliveryDayHead"
  157. @change="changeDelivertTime"
  158. style="width: 100%"
  159. allow-clear
  160. />
  161. </a-form-item>
  162. </a-col>
  163. <a-col :span="12">
  164. <a-form-item
  165. label="付款条件(payment terms)"
  166. v-bind="validateInfos.paymentTerms"
  167. id="quotationFormForm-paymentTerms"
  168. name="paymentTerms"
  169. :labelCol="formItemLayout.labelCol1"
  170. :wrapperCol="formItemLayout.wrapperCol1"
  171. >
  172. <JDictSelectTag v-model:value="formData.paymentTerms" placeholder="请选择" dictCode="payment_terms" />
  173. </a-form-item>
  174. </a-col>
  175. <a-col :span="12">
  176. <a-form-item
  177. label="交货地点(place of delivery)"
  178. v-bind="validateInfos.placeDelivery"
  179. id="quotationFormForm-placeDelivery"
  180. name="placeDelivery"
  181. >
  182. <a-input v-model:value="formData.placeDelivery" placeholder="请输入交货地点(place of delivery)" allow-clear AutoComplete="off" />
  183. </a-form-item>
  184. </a-col>
  185. <a-col :span="12">
  186. <a-form-item
  187. label="客户折扣(custumer discount)"
  188. v-bind="validateInfos.custumerDiscount"
  189. id="quotationFormForm-custumerDiscount"
  190. name="custumerDiscount"
  191. :labelCol="formItemLayout.labelCol1"
  192. :wrapperCol="formItemLayout.wrapperCol1"
  193. >
  194. <a-input
  195. v-model:value="formData.custumerDiscount"
  196. placeholder="请输入客户折扣(custumer discount)"
  197. allow-clear
  198. AutoComplete="off"
  199. @change="changeDiscountOrExchangeRate"
  200. suffix="%"
  201. />
  202. </a-form-item>
  203. </a-col>
  204. <a-col :span="12">
  205. <a-form-item
  206. label="销售部门(sale department)"
  207. v-bind="validateInfos.saleDepartment"
  208. id="SaleInquiryFormForm-saleDepartment"
  209. name="saleDepartment"
  210. >
  211. <a-input v-model:value="formData.saleDepartmentName" placeholder="" allow-clear disabled />
  212. </a-form-item>
  213. </a-col>
  214. <a-col :span="12">
  215. <a-form-item
  216. label="包装方式(packaging method)"
  217. v-bind="validateInfos.packagingMethod"
  218. id="quotationFormForm-packagingMethod"
  219. name="packagingMethod"
  220. :labelCol="formItemLayout.labelCol1"
  221. :wrapperCol="formItemLayout.wrapperCol1"
  222. >
  223. <a-input v-model:value="formData.packagingMethod" placeholder="请输入包装方式(packaging method)" allow-clear AutoComplete="off" />
  224. </a-form-item>
  225. </a-col>
  226. <a-col :span="12">
  227. <a-form-item label="业务员(salesman)" v-bind="validateInfos.salesman" id="quotationFormForm-salesman" name="salesman">
  228. <a-input v-model:value="formData.salesmanName" placeholder="" allow-clear disabled />
  229. </a-form-item>
  230. </a-col>
  231. <a-col :span="12">
  232. <a-form-item
  233. label="报价备注(quotation notes)"
  234. v-bind="validateInfos.quotationNotes"
  235. id="quotationFormForm-quotationNotes"
  236. name="quotationNotes"
  237. :labelCol="formItemLayout.labelCol1"
  238. :wrapperCol="formItemLayout.wrapperCol1"
  239. >
  240. <a-input v-model:value="formData.quotationNotes" placeholder="请输入报价备注(quotation notes)" allow-clear AutoComplete="off" />
  241. </a-form-item>
  242. </a-col>
  243. <a-col :span="12">
  244. <a-form-item
  245. label="协议条款(agreement terms)"
  246. v-bind="validateInfos.agreementTerms"
  247. id="SaleOrderForm-agreementTerms"
  248. name="agreementTerms"
  249. :labelCol="formItemLayout.labelCol1"
  250. :wrapperCol="formItemLayout.wrapperCol1"
  251. >
  252. <JSelectMultiple v-model:value="formData.agreementTerms" placeholder="" dictCode="base_agreement_terms,name,name" page="false" showSearch/>
  253. </a-form-item>
  254. </a-col>
  255. <a-col :span="12">
  256. <a-form-item
  257. label="供应商技术资料(supplier quotation attachs)"
  258. v-bind="validateInfos.supplierAttachs"
  259. id="quotationFormForm-supplierAttachs"
  260. name="supplierAttachs"
  261. :labelCol="formItemLayout.labelCol1"
  262. :wrapperCol="formItemLayout.wrapperCol1"
  263. >
  264. <a :href="baseUrl + formData.supplierAttachs" v-if="formData.supplierAttachs">{{ formData.supplierAttachs }}</a>
  265. <a-input v-model:value="formData.supplierAttachs" disabled v-if="!formData.supplierAttachs" />
  266. </a-form-item>
  267. </a-col>
  268. <a-col :span="12">
  269. <a-form-item label="附件(attachs)" v-bind="validateInfos.attachs" id="quotationFormForm-attachs" name="attachs">
  270. <JUpload v-model:value="formData.attachs" />
  271. </a-form-item>
  272. </a-col>
  273. </a-row>
  274. </a-form>
  275. </template>
  276. </JFormContainer>
  277. <!-- 子表单区域 -->
  278. <a-tabs v-model:activeKey="activeKey" animated style="padding: 24px; padding-top: 0px">
  279. <a-tab-pane tab="销售报价单 - 产品明细(product details)" key="saleQuotationFormProduct" :forceRender="true">
  280. <a-button type="primary" @click="selectProducts" style="margin-right: 1%; margin-bottom: 1%"> 选择产品(select product)</a-button>
  281. <a-button type="primary" @click="chooseSupplier"> 选择供应商报价选定(select supplier quotation selection)</a-button>
  282. <a-button type="primary" @click="setSonList" style="margin-left: 1%; margin-bottom: 1%"> 配置毛利率(Configure gross margin)</a-button>
  283. <j-vxe-table
  284. :keep-source="true"
  285. resizable
  286. ref="saleQuotationFormProductTableRef"
  287. :loading="saleQuotationFormProductTable.loading"
  288. :columns="saleQuotationFormProductTable.columns"
  289. :dataSource="saleQuotationFormProductTable.dataSource"
  290. :height="340"
  291. :disabled="disabled"
  292. :rowNumber="true"
  293. :rowSelection="true"
  294. asyncRemove
  295. @value-change="changeValues"
  296. >
  297. <template #lastPrice="props">
  298. <a @click="viewHistory">{{ props.row.lastPrice }}</a>
  299. </template>
  300. <template #action="props">
  301. <a-popconfirm title="确定删除吗?" @confirm="handleDelete1(props)">
  302. <a>删除(delete)</a>
  303. </a-popconfirm>
  304. </template>
  305. </j-vxe-table>
  306. </a-tab-pane>
  307. <a-tab-pane tab="销售报价单 - 船明细(ship details)" key="saleQuotationFormShip" :forceRender="true">
  308. <a-button type="primary" @click="selectShip"> 选择船(select ship)</a-button>
  309. <j-vxe-table
  310. :keep-source="true"
  311. resizable
  312. ref="saleQuotationFormShipTableRef"
  313. :loading="saleQuotationFormShipTable.loading"
  314. :columns="saleQuotationFormShipTable.columns"
  315. :dataSource="saleQuotationFormShipTable.dataSource"
  316. :maxHeight="340"
  317. :disabled="disabled"
  318. :rowNumber="true"
  319. :rowSelection="true"
  320. >
  321. <template #action="props">
  322. <a @click="viewAccessory(props)">查看配件信息(view accessory information)</a>
  323. <a-divider type="vertical" />
  324. <a-popconfirm title="确定删除吗?" @confirm="handleDelete(props)">
  325. <a>删除(delete)</a>
  326. </a-popconfirm>
  327. </template>
  328. </j-vxe-table>
  329. </a-tab-pane>
  330. </a-tabs>
  331. <SelectShipSModal ref="SelectShipSModalRef" @select="addShip" />
  332. <BaseShipArchiveAccessoriesModal ref="BaseShipArchiveAccessoriesListRef" />
  333. <SelectPrpductModal ref="SelectPrpductModalRef" @select-product="addProduct" />
  334. <SelectProjectModal ref="SelectProjectModalRef" @select-project="addProject" />
  335. <ViewHistoryQuotationModal ref="ViewHistoryQuotationModalRef" />
  336. <SelectSupplierQuotation ref="SelectSupplierQuotationRef" @select-supplier-quatation-confirm="addProductFromSupplier" />
  337. <SetSonList ref="SetSonListRef" @success="setSonListFiled"></SetSonList>
  338. </a-spin>
  339. </template>
  340. <script lang="ts">
  341. import { defineComponent, ref, reactive, computed, toRaw, onMounted } from 'vue';
  342. import { defHttp } from '/@/utils/http/axios';
  343. import { useValidateAntFormAndTable } from '/@/hooks/system/useJvxeMethods';
  344. import {
  345. querysaleQuotationFormShipListByMainId,
  346. querysaleVersonFormShipListByMainId,
  347. querySaleQuotationFormProductListByMainId,
  348. querySaleVersonProductListByMainId,
  349. queryDataById,
  350. saveOrUpdate,
  351. HistoryQuotation,
  352. queryVersonHistoryById,
  353. queryRate,
  354. } from '../quotationForm.api';
  355. import { JVxeTable } from '/@/components/jeecg/JVxeTable';
  356. import { saleQuotationFormShipColumns, saleQuotationFormProductColumns } from '../quotationForm.data';
  357. import SelectShipSModal from '../../../publicComponents/SelectShipSModal.vue';
  358. import SetSonList from './SetSonList.vue';
  359. import BaseShipArchiveAccessoriesModal from '../../../publicComponents/BaseShipArchiveAccessoriesModal.vue';
  360. import SelectPrpductModal from '../../../publicComponents/SelectPrpductModal.vue';
  361. import SelectProjectModal from '../../../publicComponents/SelectProjectModal.vue';
  362. import SelectSupplierQuotation from '../../../publicComponents/SelectSupplierQuotation.vue';
  363. import ViewHistoryQuotationModal from './ViewHistoryQuotationModal.vue';
  364. import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
  365. import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
  366. import { JDictSelectTag, JSelectMultiple } from '/@/components/Form';
  367. import JSelectInput from '/@/components/Form/src/jeecg/components/JSelectInput.vue';
  368. import { Form, message } from 'ant-design-vue';
  369. import { useUserStore } from '/@/store/modules/user';
  370. import dayjs from 'dayjs';
  371. import { useGlobSetting } from '/@/hooks/setting';
  372. const { domainUrl } = useGlobSetting();
  373. const userStore = useUserStore();
  374. const useForm = Form.useForm;
  375. export default defineComponent({
  376. name: 'QuotationFormForm',
  377. components: {
  378. JVxeTable,
  379. JFormContainer,
  380. SelectShipSModal,
  381. BaseShipArchiveAccessoriesModal,
  382. SelectPrpductModal,
  383. JUpload,
  384. SelectProjectModal,
  385. SelectSupplierQuotation,
  386. ViewHistoryQuotationModal,
  387. JDictSelectTag,
  388. JSelectInput,
  389. JSelectMultiple,
  390. SetSonList
  391. },
  392. props: {
  393. formDisabled: {
  394. type: Boolean,
  395. default: false,
  396. },
  397. formData: { type: Object, default: () => {} },
  398. formBpm: { type: Boolean, default: true },
  399. },
  400. emits: ['success'],
  401. setup(props, { emit }) {
  402. const baseUrl = domainUrl + '/sys/common/static/';
  403. const loading = ref(false);
  404. const formRef = ref();
  405. var SetSonListRef = ref();
  406. var SelectPrpductModalRef = ref();
  407. var SelectProjectModalRef = ref();
  408. var ViewHistoryQuotationModalRef = ref();
  409. var SelectSupplierQuotationRef = ref();
  410. var quotationPeriod = ref([]);
  411. const saleQuotationFormShipTableRef = ref();
  412. const saleQuotationFormShipTable = reactive<Record<string, any>>({
  413. loading: false,
  414. columns: saleQuotationFormShipColumns,
  415. dataSource: [],
  416. });
  417. const saleQuotationFormProductTableRef = ref();
  418. const saleQuotationFormProductTable = reactive<Record<string, any>>({
  419. loading: false,
  420. columns: saleQuotationFormProductColumns,
  421. dataSource: [],
  422. });
  423. var SelectShipSModalRef = ref();
  424. var BaseShipArchiveAccessoriesListRef = ref();
  425. const activeKey = ref('saleQuotationFormProduct');
  426. var notAllowEdit = ref(false);
  427. var classOption = ref([]);
  428. var customerOption = ref([]);
  429. const formData = reactive<Record<string, any>>({
  430. id: '',
  431. status: undefined,
  432. delFlag: undefined,
  433. otherStatus: '',
  434. billDate: dayjs(new Date()).format('YYYY-MM-DD'),
  435. billCode: '',
  436. quotationProject: '',
  437. quotationProjectName: '',
  438. quotationCustomer: '',
  439. quotationCustomerName: '',
  440. quotationPeriodBegin: '',
  441. quotationPeriodEnd: '',
  442. busynessType: '',
  443. priority: '',
  444. productionClass: '',
  445. model: '',
  446. maker: '',
  447. currency: '',
  448. deliveryTerms: '',
  449. deliveryDayHead: '',
  450. paymentTerms: '',
  451. placeDelivery: '',
  452. custumerDiscount: '',
  453. saleDepartment: '',
  454. saleDepartmentName: '',
  455. packagingMethod: '',
  456. salesman: '',
  457. salesmanName: '',
  458. quotationNotes: '',
  459. attachs: '',
  460. supplierAttachs: '',
  461. sourceCode: '',
  462. exchangeRate: '',
  463. agreementTerms: '',
  464. });
  465. //表单验证
  466. const validatorRules = reactive({
  467. quotationProjectName: [{ required: true, message: '请选择报价项目(select project)' }],
  468. quotationCustomer: [{ required: true, message: '请选择报价客户(select customer)' }],
  469. currency: [{ required: true, message: '请选择币种(select currency)' }],
  470. });
  471. const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
  472. const dbData = {};
  473. const formItemLayout = {
  474. labelCol: { xs: { span: 24 }, sm: { span: 8 } },
  475. wrapperCol: { xs: { span: 24 }, sm: { span: 13 } },
  476. labelCol1: { xs: { span: 24 }, sm: { span: 8 } },
  477. wrapperCol1: { xs: { span: 24 }, sm: { span: 13 } },
  478. };
  479. // 表单禁用
  480. const disabled = computed(() => {
  481. if (props.formBpm === true) {
  482. if (props.formData.disabled === false) {
  483. return false;
  484. } else {
  485. return true;
  486. }
  487. }
  488. return props.formDisabled;
  489. });
  490. //新增方法
  491. function add() {
  492. resetFields();
  493. saleQuotationFormShipTable.dataSource = [];
  494. saleQuotationFormProductTable.dataSource = [];
  495. activeKey.value = 'saleQuotationFormProduct';
  496. getOptiom();
  497. getCustomerOptions();
  498. quotationPeriod.value = [];
  499. formData.salesman = userStore.getUserInfo.username;
  500. formData.salesmanName = userStore.getUserInfo.realname;
  501. formData.saleDepartment = userStore.getUserInfo.orgCode;
  502. formData.saleDepartmentName = userStore.getUserInfo.orgName;
  503. notAllowEdit.value = false;
  504. }
  505. async function changeExchangeRate() {
  506. if (formData.currency !== '美元') {
  507. var param = {
  508. month: dayjs(new Date()).month() + 1,
  509. year: dayjs(new Date()).year(),
  510. currency: formData.currency,
  511. };
  512. var info = await queryRate(param);
  513. formData.exchangeRate = info;
  514. } else {
  515. formData.exchangeRate = 1;
  516. }
  517. changeDiscountOrExchangeRate();
  518. }
  519. //编辑方法
  520. async function edit(row) {
  521. //主表数据
  522. await queryMainData(row.id);
  523. //子表数据
  524. const saleQuotationFormShipDataList = await querysaleQuotationFormShipListByMainId(row['id']);
  525. saleQuotationFormShipTable.dataSource = [...saleQuotationFormShipDataList];
  526. const saleQuotationFormProductDataList = await querySaleQuotationFormProductListByMainId(row['id']);
  527. saleQuotationFormProductTable.dataSource = [...saleQuotationFormProductDataList];
  528. getOptiom();
  529. getCustomerOptions();
  530. quotationPeriod.value[0] = formData.quotationPeriodBegin ? dayjs(formData.quotationPeriodBegin,'YYYY/MM/DD') : '';
  531. quotationPeriod.value[1] = formData.quotationPeriodEnd ? dayjs(formData.quotationPeriodEnd,'YYYY/MM/DD') : '';
  532. notAllowEdit.value = true;
  533. }
  534. //获取主表
  535. async function queryMainData(id) {
  536. const row = await queryDataById(id);
  537. resetFields();
  538. const tmpData = {};
  539. Object.keys(formData).forEach((key) => {
  540. if (row.hasOwnProperty(key)) {
  541. tmpData[key] = row[key];
  542. }
  543. });
  544. //赋值
  545. Object.assign(formData, tmpData);
  546. }
  547. const { getSubFormAndTableData, transformData } = useValidateAntFormAndTable(activeKey, {
  548. saleQuotationShip: saleQuotationFormShipTableRef,
  549. saleQuotationProduct: saleQuotationFormProductTableRef,
  550. });
  551. //获取表单信息
  552. async function getFormData() {
  553. try {
  554. // 触发表单验证
  555. await validate();
  556. } catch ({ errorFields }) {
  557. if (errorFields) {
  558. const firstField = errorFields[0];
  559. if (firstField) {
  560. formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
  561. }
  562. }
  563. return Promise.reject(errorFields);
  564. }
  565. return transformData(toRaw(formData));
  566. }
  567. //保存
  568. async function submitForm() {
  569. if (formData.sourceCode == '') {
  570. message.warning('请添加供应商报价选定');
  571. } else {
  572. saleQuotationFormProductTableRef.value!.validateTable().then(async (errMap) => {
  573. if (errMap) {
  574. console.log('表单验证未通过:', { errMap });
  575. } else {
  576. const mainData = await getFormData();
  577. const subData = await getSubFormAndTableData();
  578. const values = Object.assign({}, dbData, mainData, subData);
  579. console.log('表单提交数据', values);
  580. const isUpdate = values.id ? true : false;
  581. const isRevise = values.status == '1' ? true : false;
  582. await saveOrUpdate(values, isUpdate, isRevise);
  583. //关闭弹窗
  584. emit('success');
  585. }
  586. });
  587. }
  588. }
  589. function setFieldsValue(values) {
  590. if (values) {
  591. Object.keys(values).map((k) => {
  592. formData[k] = values[k];
  593. });
  594. }
  595. }
  596. /**
  597. * 值改变事件触发-树控件回调
  598. * @param key
  599. * @param value
  600. */
  601. function handleFormChange(key, value) {
  602. formData[key] = value;
  603. }
  604. //传明细-删除行
  605. async function handleDelete(prop) {
  606. var xTable = saleQuotationFormShipTableRef.value!.getXTable();
  607. var newArray = [...xTable.data];
  608. newArray.splice(prop.rowIndex, 1);
  609. saleQuotationFormShipTable.dataSource = newArray;
  610. }
  611. //产品明细-删除行
  612. async function handleDelete1(prop) {
  613. var xTable = saleQuotationFormProductTableRef.value!.getXTable();
  614. var newArray = [...xTable.data];
  615. newArray.splice(prop.rowIndex, 1);
  616. saleQuotationFormProductTable.dataSource = newArray;
  617. if (saleQuotationFormProductTable.dataSource.length !== 0) {
  618. var arr = [];
  619. saleQuotationFormProductTable.dataSource.map((item) => {
  620. if (item.sourceId) {
  621. arr.push(item.sourceId);
  622. }
  623. });
  624. if (arr.length == 0) {
  625. formData.sourceCode = '';
  626. notAllowEdit.value = false;
  627. }
  628. } else {
  629. formData.sourceCode = '';
  630. notAllowEdit.value = false;
  631. add();
  632. }
  633. }
  634. //查询船
  635. function selectShip() {
  636. SelectShipSModalRef.value.getTable();
  637. }
  638. //增行-船明细
  639. function addShip(data) {
  640. data.map((item) => {
  641. item.shipowner = item.relateCustomer;
  642. item.shipId = item.id;
  643. item.id=undefined;
  644. });
  645. var xTable = saleQuotationFormShipTableRef.value!.getXTable();
  646. var arr = xTable.data.concat(data);
  647. saleQuotationFormShipTable.dataSource = arr;
  648. }
  649. //增行-产品明细
  650. async function addProduct(data) {
  651. for (const item of data) {
  652. item.productClass = item.classId_dictText;
  653. item.productCode = item.code;
  654. // item.unit = item.measurementUnit
  655. item.deliveryDayChild = formData.deliveryDayHead;
  656. item.productId = item.id;
  657. var obj = await getRowRate(item);
  658. item.taxRate = obj.rateNumber;
  659. item.grossMargin = obj.grossMargin;
  660. item.discount = formData.custumerDiscount;
  661. item.id = undefined;
  662. }
  663. var xTable = saleQuotationFormProductTableRef.value!.getXTable();
  664. var arrProduct = xTable.data.concat(data);
  665. saleQuotationFormProductTable.dataSource = arrProduct;
  666. }
  667. //选择项目
  668. function addProject(data) {
  669. if (data.length == 0) {
  670. formData.quotationProject = formData.quotationProjectName = '';
  671. } else {
  672. formData.quotationProject = data[0].id;
  673. formData.quotationProjectName = data[0].code;
  674. formData.quotationCustomer = data[0].customerId;
  675. formData.quotationCustomerName = data[0].customerId_dictText;
  676. formData.custumerDiscount == data[0].discount;
  677. formData.currency = '美元';
  678. formData.exchangeRate = '1';
  679. customerOption.value.map((item) => {
  680. if (item.value == data[0].customerId) {
  681. formData.priority = item.priority;
  682. formData.custumerDiscount = item.discount;
  683. formData.paymentTerms = item.paymentTerms;
  684. formData.currency = item.currency;
  685. }
  686. });
  687. if (saleQuotationFormProductTable.dataSource.length > 0) {
  688. var newArr = [...saleQuotationFormProductTable.dataSource];
  689. newArr.map((item) => {
  690. item.discount = formData.custumerDiscount;
  691. });
  692. saleQuotationFormProductTable.dataSource = newArr;
  693. }
  694. }
  695. }
  696. //获取客户列表
  697. function getCustomerOptions() {
  698. let params = { pageSize: '-1', status: 1 };
  699. defHttp.get({ url: '/cuspCode/cuspCustomerProfile/list', params }, { isTransformResponse: false }).then((res) => {
  700. if (res) {
  701. customerOption.value = [];
  702. res.result.records.forEach((item) => {
  703. customerOption.value.push({
  704. label: item.name,
  705. value: item.id,
  706. priority: item.priority,
  707. intermediatorCommission: item.intermediatorCommission,
  708. commission: item.commission,
  709. discount: item.discount,
  710. paymentTerms: item.paymentTerms,
  711. currency: item.currency,
  712. });
  713. });
  714. }
  715. });
  716. }
  717. //查看配件信息
  718. function viewAccessory(prop) {
  719. BaseShipArchiveAccessoriesListRef.value.getTable(prop.row);
  720. }
  721. //选择产品
  722. function selectProducts() {
  723. SelectPrpductModalRef.value.getTable();
  724. }
  725. //选择供应商报价单
  726. function chooseSupplier() {
  727. SelectSupplierQuotationRef.value.getTable(formData);
  728. }
  729. //选择项目
  730. function onSearchProject() {
  731. SelectProjectModalRef.value.getTable();
  732. }
  733. //获取产品分类下拉框
  734. function getOptiom() {
  735. defHttp
  736. .get({ url: 'baseCode/baseProductClass/list' }, { isTransformResponse: false })
  737. .then((res) => {
  738. if (res.success) {
  739. classOption.value = [];
  740. res.result.records.forEach((element) => {
  741. var obj = {
  742. label: element.name ? element.name : '无名称请维护',
  743. value: element.id ? element.id : '',
  744. taxRate: element.taxRate ? element.taxRate : 0,
  745. grossMargin: element.grossMargin ? element.grossMargin : 0,
  746. };
  747. classOption.value.push(obj);
  748. });
  749. }
  750. })
  751. .finally(() => {
  752. // loading.value = false;
  753. });
  754. }
  755. //修改报价有效期
  756. function onChangequotationPeriod(data) {
  757. quotationPeriod.value = data;
  758. formData.quotationPeriodBegin = data[0].format('YYYY-MM-DD');
  759. formData.quotationPeriodEnd = data[1].format('YYYY-MM-DD');
  760. }
  761. //修改主表交期
  762. function changeDelivertTime() {
  763. if (saleQuotationFormProductTable.dataSource.length > 0) {
  764. var xTable = saleQuotationFormProductTableRef.value!.getXTable();
  765. var newArr = [...xTable.data];
  766. newArr.map((item) => {
  767. item.deliveryDayChild = formData.deliveryDayHead;
  768. });
  769. saleQuotationFormProductTable.dataSource = newArr;
  770. }
  771. }
  772. //查看上次报价
  773. function viewHistory() {
  774. ViewHistoryQuotationModalRef.value.getTable();
  775. }
  776. //查看版本详情
  777. async function VersionDetail(record) {
  778. //主表数据
  779. await queryVersonHistoryData(record.id);
  780. //子表数据
  781. const saleQuotationFormShipDataList = await querysaleVersonFormShipListByMainId(record.id);
  782. saleQuotationFormShipTable.dataSource = [...saleQuotationFormShipDataList];
  783. const saleQuotationFormProductDataList = await querySaleVersonProductListByMainId(record.id);
  784. saleQuotationFormProductTable.dataSource = [...saleQuotationFormProductDataList];
  785. getOptiom();
  786. getCustomerOptions();
  787. quotationPeriod.value[0] = formData.quotationPeriodBegin ? dayjs(formData.quotationPeriodBegin,'YYYY/MM/DD') : '';
  788. quotationPeriod.value[1] = formData.quotationPeriodEnd ? dayjs(formData.quotationPeriodEnd,'YYYY/MM/DD') : '';
  789. }
  790. async function queryVersonHistoryData(id) {
  791. const row = await queryVersonHistoryById(id);
  792. resetFields();
  793. const tmpData = {};
  794. Object.keys(formData).forEach((key) => {
  795. if (row.hasOwnProperty(key)) {
  796. tmpData[key] = row[key];
  797. }
  798. });
  799. //赋值
  800. Object.assign(formData, tmpData);
  801. }
  802. //新增行-产品明细-选择供应商报价单
  803. async function addProductFromSupplier(data) {
  804. //查询客户名称
  805. var obj = await SelectProjectModalRef.value.getCustom(data[0].inquiryProject);
  806. formData.quotationCustomer = obj.length == 0 ? '' : obj[0].customerId;
  807. formData.quotationCustomerName = obj.length == 0 ? '' : obj[0].customerId_dictText;
  808. for (const item of data) {
  809. var obj = await getRowRate(item);
  810. item.taxRate = obj.rateNumber;
  811. item.grossMargin = obj.grossMargin;
  812. item.productClass = item.productClass;
  813. item.productCode = item.productCode;
  814. item.sourceId = item.childId;
  815. item.id = undefined
  816. item.fatherModel = item.model;
  817. item.model = item.childModel;
  818. item.deliveryTime = formData.deliveryTime;
  819. item.supplierCurrency = item.currency;
  820. item.supplierId = item.selectionSupplier;
  821. item.supplierName = item.selectionSupplier_dictText;
  822. item.purchasePrice = item.taxPriceUsd;
  823. item.taxAmount = 0;
  824. item.currencyGys = item.currency;
  825. item.exchangeRateGys = item.exchangeRateUsd;
  826. item.taxPriceGys = item.taxPrice;
  827. item.notes=item.childNotes
  828. item.purchaseAmount=(Number(item.quantity) * Number(item.purchasePrice)).toFixed(2)
  829. }
  830. var xTable = saleQuotationFormProductTableRef.value!.getXTable();
  831. var arrProduct = xTable.data.concat(data);
  832. arrProduct.map((item) => {
  833. customerOption.value.map((event) => {
  834. if (event.value == formData.quotationCustomer) {
  835. (item.intermediatorCommission = event.intermediatorCommission), (item.customerCommision = event.commission);
  836. formData.custumerDiscount = event.discoun;
  837. item.discount = event.discount;
  838. formData.paymentTerms = event.paymentTerms;
  839. formData.currency = event.currency;
  840. }
  841. });
  842. });
  843. saleQuotationFormProductTable.dataSource = arrProduct;
  844. notAllowEdit.value = true;
  845. formData.quotationProject = data[0].inquiryProject;
  846. formData.quotationProjectName = data[0].projectName;
  847. formData.sourceCode = data[0].billCode;
  848. formData.priority = data[0].priority;
  849. formData.model = data[0].fatherModel;
  850. formData.maker = data[0].maker;
  851. formData.productionClass = data[0].productionClass;
  852. formData.deliveryDayHead = data[0].deliveryDayChild;
  853. formData.currency = '美元';
  854. formData.exchangeRate = '1';
  855. await getShipList(data[0].headId);
  856. // await changeDiscountOrExchangeRate()
  857. }
  858. function getShipList(id) {
  859. let params = { id: id };
  860. defHttp.get({ url: '/saleCode/saleInquiryForm/querySaleInquiryFormShipByMainId', params }, { isTransformResponse: false }).then((res) => {
  861. if (res) {
  862. saleQuotationFormShipTable.dataSource = res.result;
  863. }
  864. });
  865. }
  866. async function getRowRate(row) {
  867. var obj = {
  868. rateNumber: 0,
  869. grossMargin: 0,
  870. };
  871. let params = { pageSize: '-1', status: 1, code: row.productCode };
  872. await defHttp.get({ url: '/baseCode/baseProductArchive/list', params }, { isTransformResponse: false }).then((res) => {
  873. if (res) {
  874. if (res.result.records[0].taxRate && res.result.records[0].taxRate !== '') {
  875. obj.rateNumber = res.result.records[0].taxRate;
  876. } else {
  877. classOption.value.map((event) => {
  878. if (event.label == row.productClass) {
  879. obj.rateNumber = event.taxRate;
  880. }
  881. });
  882. }
  883. classOption.value.map((event) => {
  884. if (event.label == row.productClass) {
  885. obj.grossMargin = event.grossMargin;
  886. }
  887. });
  888. }
  889. });
  890. return obj;
  891. }
  892. function changeValues(prop) {
  893. //设置 默认值
  894. formData.exchangeRate = formData.exchangeRate == '' || formData.exchangeRate === null ? 1 : formData.exchangeRate;
  895. prop.row.customerCommision = prop.row.customerCommision == '' || prop.row.customerCommision === null || !prop.row.customerCommision ? 0 : prop.row.customerCommision;
  896. prop.row.discount = prop.row.discount == '' || prop.row.discount === null || !prop.row.discount ? 0 : prop.row.discount;
  897. prop.row.tariff = prop.row.tariff == '' || prop.row.tariff === null || !prop.row.tariff ? 0 : prop.row.tariff;
  898. prop.row.intermediatorCommission =prop.row.intermediatorCommission == '' || prop.row.intermediatorCommission === null || !prop.row.intermediatorCommission? 0: prop.row.intermediatorCommission;
  899. //计算销售单价
  900. if (prop.col.key == 'purchasePrice' || prop.col.key == 'taxRate' || prop.col.key == 'tariff' || prop.col.key == 'discount' || prop.col.key == 'grossMargin' || prop.col.key == 'customerCommision' || prop.col.key == 'intermediatorCommission') {
  901. var num =((prop.row.purchasePrice / Number(formData.exchangeRate)) *(1 + prop.row.taxRate / 100) *(1 + prop.row.tariff / 100) *(1 - prop.row.discount / 100)) /(1 - prop.row.grossMargin / 100 - prop.row.customerCommision / 100 - prop.row.intermediatorCommission / 100);
  902. prop.row.salePrice = !isNaN(num) ? num.toFixed(2) : '';
  903. if (prop.row.quantity) {
  904. prop.row.taxAmount = (prop.row.salePrice * prop.row.quantity).toFixed(2); //计算金额
  905. prop.row.purchaseAmount = (prop.row.purchasePrice * prop.row.quantity).toFixed(2); //计算采购金额
  906. }
  907. }
  908. //计算金额
  909. if (prop.col.key == 'quantity'&& prop.row.salePrice && prop.row.quantity) {
  910. prop.row.taxAmount = (prop.row.salePrice * prop.row.quantity).toFixed(2);
  911. }
  912. //计算采购金额
  913. if (prop.col.key == 'quantity' && prop.row.quantity&& prop.row.purchasePrice) {
  914. prop.row.purchaseAmount = (prop.row.purchasePrice * prop.row.quantity).toFixed(2);
  915. }
  916. //计算毛利率/金额
  917. if (prop.col.key == 'salePrice') {
  918. var num =1 -(((prop.row.purchasePrice / Number(formData.exchangeRate)) *(1 + prop.row.taxRate / 100) *(1 + prop.row.tariff / 100) *(1 - prop.row.discount / 100)) /prop.row.salePrice +(prop.row.customerCommision / 100 - prop.row.intermediatorCommission / 100));
  919. num = (Number(num) * 100).toFixed(2);
  920. prop.row.grossMargin = !isNaN(num) ? num : '';
  921. if (prop.row.quantity) {
  922. prop.row.taxAmount = (prop.row.salePrice * prop.row.quantity).toFixed(2);
  923. }
  924. }
  925. }
  926. function changeDiscountOrExchangeRate() {
  927. if (saleQuotationFormProductTable.dataSource.length > 0) {
  928. var xTable = saleQuotationFormProductTableRef.value!.getXTable();
  929. var newArr = [...xTable.data];
  930. formData.exchangeRate = formData.exchangeRate == '' || formData.exchangeRate === null || !formData.exchangeRate ? 1 : formData.exchangeRate;
  931. newArr.map((item) => {
  932. item.discount = formData.custumerDiscount == '' || formData.custumerDiscount === null || !formData.custumerDiscount ? 0 : formData.custumerDiscount;
  933. item.tariff = item.tariff == '' || item.tariff === null || !item.tariff ? 0 : item.tariff;
  934. item.customerCommision = item.customerCommision == '' || item.customerCommision === null || !item.customerCommision ? 0 : item.customerCommision;
  935. item.intermediatorCommission =
  936. item.intermediatorCommission == '' || item.intermediatorCommission === null || !item.intermediatorCommission
  937. ? 0
  938. : item.intermediatorCommission;
  939. //汇率默认为1
  940. var num =
  941. ((item.purchasePrice / Number(formData.exchangeRate)) *
  942. (1 + item.taxRate / 100) *
  943. (1 + item.tariff / 100) *
  944. (1 - item.discount / 100)) /
  945. (1 - item.grossMargin / 100 - item.customerCommision / 100 - item.intermediatorCommission / 100);
  946. item.salePrice = !isNaN(num) ? num.toFixed(2) : '';
  947. if (item.quantity) {
  948. item.taxAmount = (item.salePrice * item.quantity).toFixed(2);
  949. }
  950. // }
  951. });
  952. saleQuotationFormProductTable.dataSource = newArr;
  953. }
  954. }
  955. function setSonList(){
  956. SetSonListRef.value.getTable()
  957. }
  958. function setSonListFiled(value){
  959. var xTable = (saleQuotationFormProductTableRef.value!.getXTable()).data
  960. if(xTable.length>0){
  961. xTable.map(item=>{
  962. item.grossMargin = value.numericalValue
  963. })
  964. }
  965. saleQuotationFormProductTable.dataSource =[...xTable]
  966. changeDiscountOrExchangeRate()
  967. }
  968. return {
  969. saleQuotationFormShipTableRef,
  970. saleQuotationFormShipTable,
  971. saleQuotationFormProductTableRef,
  972. saleQuotationFormProductTable,
  973. validatorRules,
  974. validateInfos,
  975. activeKey,
  976. loading,
  977. formData,
  978. setFieldsValue,
  979. handleFormChange,
  980. formItemLayout,
  981. disabled,
  982. getFormData,
  983. submitForm,
  984. SelectShipSModalRef,
  985. add,
  986. edit,
  987. formRef,
  988. selectShip,
  989. addShip,
  990. addProduct,
  991. BaseShipArchiveAccessoriesListRef,
  992. viewAccessory,
  993. handleDelete,
  994. handleDelete1,
  995. selectProducts,
  996. SelectPrpductModalRef,
  997. SelectProjectModalRef,
  998. ViewHistoryQuotationModalRef,
  999. SelectSupplierQuotationRef,
  1000. onSearchProject,
  1001. addProject,
  1002. getOptiom,
  1003. classOption,
  1004. getCustomerOptions,
  1005. customerOption,
  1006. quotationPeriod,
  1007. onChangequotationPeriod,
  1008. chooseSupplier,
  1009. changeDelivertTime,
  1010. viewHistory,
  1011. baseUrl,
  1012. VersionDetail,
  1013. queryVersonHistoryData,
  1014. addProductFromSupplier,
  1015. notAllowEdit,
  1016. changeValues,
  1017. getRowRate,
  1018. changeDiscountOrExchangeRate,
  1019. changeExchangeRate,
  1020. setSonList,
  1021. SetSonListRef,
  1022. setSonListFiled
  1023. };
  1024. },
  1025. });
  1026. </script>
  1027. <style lang="less" scoped>
  1028. /** 时间和数字输入框样式 */
  1029. :deep(.ant-input-number) {
  1030. width: 100%;
  1031. }
  1032. :deep(.ant-calendar-picker) {
  1033. width: 100%;
  1034. }
  1035. // /deep/.vxe-table--body-wrapper{
  1036. // height: 100% !important;
  1037. // }
  1038. /deep/.ant-modal-body {
  1039. padding: 24px !important;
  1040. }
  1041. /deep/.ant-form-item {
  1042. margin-bottom: 8px !important;
  1043. }
  1044. /deep/.vxe-cell--valid-error-msg {
  1045. color: white !important;
  1046. background-color: white !important;
  1047. }
  1048. </style>