Contract.vue 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945
  1. <template>
  2. <div style="width: 100%; padding: 0px 15px">
  3. <byForm
  4. :formConfig="formConfig"
  5. :formOption="formOption"
  6. v-model="formData.data"
  7. :rules="rules"
  8. ref="submit"
  9. >
  10. <template #seller>
  11. <div style="width: 100%">
  12. <el-form-item prop="sellCorporationId">
  13. <el-select
  14. v-model="formData.data.sellCorporationId"
  15. style="width: 100%"
  16. disabled
  17. >
  18. <el-option
  19. v-for="item in corporationList"
  20. :key="item.value"
  21. :label="item.label"
  22. :value="item.value"
  23. />
  24. </el-select>
  25. </el-form-item>
  26. <el-row style="margin-top: 20px; width: 100%">
  27. <el-col :span="8">
  28. <el-form-item label="地址" prop="sellCountryName">
  29. <el-input
  30. v-model="formData.data.sellCountryName"
  31. placeholder="请输入国家"
  32. />
  33. </el-form-item>
  34. </el-col>
  35. <el-col :span="1"></el-col>
  36. <el-col :span="7">
  37. <el-form-item label=" " prop="sellProvinceName">
  38. <el-input
  39. v-model="formData.data.sellProvinceName"
  40. placeholder="请输入省/州"
  41. />
  42. </el-form-item>
  43. </el-col>
  44. <el-col :span="1"></el-col>
  45. <el-col :span="7">
  46. <el-form-item label=" " prop="sellCityName">
  47. <el-input
  48. v-model="formData.data.sellCityName"
  49. placeholder="请输入城市"
  50. />
  51. </el-form-item>
  52. </el-col>
  53. </el-row>
  54. <el-row style="margin-top: 20px; width: 100%">
  55. <el-col :span="24">
  56. <el-form-item prop="sellAddress">
  57. <el-input v-model="formData.data.sellAddress" type="textarea">
  58. </el-input>
  59. </el-form-item>
  60. </el-col>
  61. </el-row>
  62. <el-row style="margin-top: 20px; width: 100%">
  63. <el-col :span="8">
  64. <el-form-item label="联系人" prop="sellContactName">
  65. <el-input
  66. v-model="formData.data.sellContactName"
  67. placeholder="请输入联系人"
  68. />
  69. </el-form-item>
  70. </el-col>
  71. <el-col :span="1"></el-col>
  72. <el-col :span="15">
  73. <el-form-item label=" " prop="sellContactNumber">
  74. <el-input
  75. v-model="formData.data.sellContactNumber"
  76. placeholder="请输入联系人电话"
  77. />
  78. </el-form-item>
  79. </el-col>
  80. </el-row>
  81. </div>
  82. </template>
  83. <template #buyer>
  84. <div style="width: 100%">
  85. <div style="width: 100%">
  86. <el-form-item prop="buyCorporationId">
  87. <el-select
  88. v-model="formData.data.buyCorporationId"
  89. filterable
  90. style="width: 100%"
  91. @change="changeCustomer"
  92. >
  93. <el-option
  94. v-for="item in customerList"
  95. :key="item.value"
  96. :label="item.label"
  97. :value="item.value"
  98. />
  99. </el-select>
  100. </el-form-item>
  101. <el-row style="margin-top: 20px; width: 100%">
  102. <el-col :span="6">
  103. <el-form-item label="地址" prop="countryId">
  104. <el-select
  105. v-model="formData.data.countryId"
  106. placeholder="国家"
  107. filterable
  108. @change="(val) => getCityData(val, '20', true)"
  109. >
  110. <el-option
  111. v-for="item in countryData"
  112. :label="
  113. formData.data.contractType == '2'
  114. ? item.chineseName
  115. : item.name
  116. "
  117. :value="item.id"
  118. >
  119. </el-option>
  120. </el-select>
  121. </el-form-item>
  122. </el-col>
  123. <el-col :span="1"></el-col>
  124. <el-col :span="5">
  125. <el-form-item label=" " prop="provinceName">
  126. <selectCity
  127. placeholder="省/洲"
  128. @change="(val) => getCityData(val, '30', true)"
  129. addressId="provinceId"
  130. addressName="provinceName"
  131. v-model="formData.data"
  132. :data="provinceData"
  133. >
  134. </selectCity>
  135. </el-form-item>
  136. </el-col>
  137. <el-col :span="1"></el-col>
  138. <el-col :span="5">
  139. <el-form-item label=" " prop="cityName">
  140. <selectCity
  141. placeholder="城市"
  142. addressId="cityId"
  143. addressName="cityName"
  144. v-model="formData.data"
  145. :data="cityData"
  146. >
  147. </selectCity>
  148. </el-form-item>
  149. </el-col>
  150. <el-col :span="1"></el-col>
  151. <el-col :span="5">
  152. <el-form-item label=" " prop="buyPostalCode">
  153. <el-input
  154. v-model="formData.data.buyPostalCode"
  155. placeholder="请输入邮编"
  156. />
  157. </el-form-item>
  158. </el-col>
  159. </el-row>
  160. <el-row style="margin-top: 20px; width: 100%">
  161. <el-col :span="24">
  162. <el-form-item prop="buyAddress">
  163. <el-input v-model="formData.data.buyAddress" type="textarea">
  164. </el-input>
  165. </el-form-item>
  166. </el-col>
  167. </el-row>
  168. <el-row style="margin-top: 20px; width: 100%">
  169. <el-col :span="8">
  170. <el-form-item label="联系人" prop="buyContactName">
  171. <el-autocomplete
  172. v-model="formData.data.buyContactName"
  173. :fetch-suggestions="querySearchPerson"
  174. clearable
  175. class="inline-input w-50"
  176. placeholder="请输入联系人"
  177. @select="handlePerson"
  178. >
  179. </el-autocomplete>
  180. </el-form-item>
  181. </el-col>
  182. <el-col :span="1"></el-col>
  183. <el-col :span="15">
  184. <el-form-item label=" " prop="buyContactNumber">
  185. <el-input
  186. v-model="formData.data.buyContactNumber"
  187. placeholder="请输入联系人电话"
  188. />
  189. </el-form-item>
  190. </el-col>
  191. </el-row>
  192. </div>
  193. </div>
  194. </template>
  195. <template #commodity>
  196. <div style="width: 100%">
  197. <el-button @click="openProduct = true">添加商品</el-button>
  198. <el-table
  199. :data="formData.data.contractProductList"
  200. style="width: 100%; margin-top: 16px"
  201. >
  202. <el-table-column label="商品图片" width="80">
  203. <template #default="{ row }">
  204. <div v-if="row.fileUrl">
  205. <img
  206. :src="row.fileUrl"
  207. class="pic"
  208. @click="onPicture(row.fileUrl)"
  209. />
  210. </div>
  211. <div v-else></div>
  212. </template>
  213. </el-table-column>
  214. <el-table-column prop="code" label="商品编码" width="120" />
  215. <el-table-column prop="name" label="商品中文名" width="160" />
  216. <el-table-column label="商品英文名" min-width="200">
  217. <template #default="{ row, $index }">
  218. <div style="width: 100%">
  219. <el-form-item
  220. :prop="'contractProductList.' + $index + '.productName'"
  221. :rules="rules.productName"
  222. :inline-message="true"
  223. >
  224. <el-input
  225. v-model="row.productName"
  226. placeholder="请输入商品英文名"
  227. />
  228. </el-form-item>
  229. </div>
  230. </template>
  231. </el-table-column>
  232. <el-table-column label="规格型号" width="180">
  233. <template #default="{ row, $index }">
  234. <div style="width: 100%">
  235. <el-form-item
  236. :prop="'contractProductList.' + $index + '.productModel'"
  237. :inline-message="true"
  238. >
  239. <el-input
  240. v-model="row.productModel"
  241. placeholder="请输入规格型号"
  242. />
  243. </el-form-item>
  244. </div>
  245. </template>
  246. </el-table-column>
  247. <el-table-column
  248. prop="unit"
  249. label="单位"
  250. width="100"
  251. :formatter="(row) => dictValueLabel(row.unit, productUnit)"
  252. />
  253. <el-table-column label="数量" width="160">
  254. <template #default="{ row, $index }">
  255. <div style="width: 100%">
  256. <el-form-item
  257. :prop="'contractProductList.' + $index + '.quantity'"
  258. :rules="rules.quantity"
  259. :inline-message="true"
  260. >
  261. <el-input-number
  262. onmousewheel="return false;"
  263. v-model="row.quantity"
  264. placeholder="请输入数量"
  265. style="width: 100%"
  266. :controls="false"
  267. :min="0"
  268. @change="
  269. () => {
  270. return calculationAmount(
  271. 'contractProductList',
  272. $index,
  273. 'quantity'
  274. );
  275. }
  276. "
  277. />
  278. </el-form-item>
  279. </div>
  280. </template>
  281. </el-table-column>
  282. <el-table-column label="单价" width="160">
  283. <template #default="{ row, $index }">
  284. <div style="width: 100%">
  285. <el-form-item
  286. :prop="'contractProductList.' + $index + '.price'"
  287. :rules="rules.price"
  288. :inline-message="true"
  289. >
  290. <el-input-number
  291. onmousewheel="return false;"
  292. v-model="row.price"
  293. placeholder="请输入单价"
  294. style="width: 100%"
  295. :controls="false"
  296. :min="0"
  297. @change="
  298. () => {
  299. return calculationAmount(
  300. 'contractProductList',
  301. $index,
  302. 'price'
  303. );
  304. }
  305. "
  306. />
  307. </el-form-item>
  308. </div>
  309. </template>
  310. </el-table-column>
  311. <el-table-column prop="amount" label="金额" width="100" />
  312. <el-table-column
  313. align="center"
  314. label="操作"
  315. width="120"
  316. fixed="right"
  317. >
  318. <template #default="{ row, $index }">
  319. <el-button
  320. type="primary"
  321. link
  322. @click="handleHandover(row, $index)"
  323. >交接单</el-button
  324. >
  325. <el-button
  326. type="primary"
  327. link
  328. @click="handleRemove($index, row)"
  329. >删除</el-button
  330. >
  331. </template>
  332. </el-table-column>
  333. </el-table>
  334. </div>
  335. </template>
  336. <template #otherCharge>
  337. <div style="width: 100%">
  338. <el-button type="primary" @click="clickAdd()">添加行</el-button>
  339. <el-table
  340. :data="formData.data.contractProjectList"
  341. style="width: 100%; margin-top: 16px"
  342. >
  343. <el-table-column label="收费项目" width="220">
  344. <template #default="{ row, $index }">
  345. <div style="width: 100%">
  346. <el-form-item
  347. :prop="'contractProjectList.' + $index + '.payName'"
  348. :rules="rules.payName"
  349. :inline-message="true"
  350. >
  351. <el-autocomplete
  352. v-model="row.payName"
  353. :fetch-suggestions="querySearch"
  354. clearable
  355. class="inline-input w-50"
  356. placeholder="请输入收费项目"
  357. />
  358. </el-form-item>
  359. </div>
  360. </template>
  361. </el-table-column>
  362. <el-table-column label="金额" width="180">
  363. <template #default="{ row, $index }">
  364. <div style="width: 100%">
  365. <el-form-item
  366. :prop="'contractProjectList.' + $index + '.amount'"
  367. :rules="rules.amount"
  368. :inline-message="true"
  369. >
  370. <el-input-number
  371. onmousewheel="return false;"
  372. v-model="row.amount"
  373. placeholder="请输入金额"
  374. style="width: 100%"
  375. :controls="false"
  376. :min="0"
  377. @change="
  378. () => {
  379. return totalAmount(
  380. 'contractProjectList',
  381. $index,
  382. 'amount'
  383. );
  384. }
  385. "
  386. />
  387. </el-form-item>
  388. </div>
  389. </template>
  390. </el-table-column>
  391. <el-table-column label="备注">
  392. <template #default="{ row, $index }">
  393. <div style="width: 100%">
  394. <el-form-item
  395. :prop="'contractProjectList.' + $index + '.remark'"
  396. >
  397. <el-input v-model="row.remark" placeholder="请输入备注" />
  398. </el-form-item>
  399. </div>
  400. </template>
  401. </el-table-column>
  402. <el-table-column
  403. align="center"
  404. label="操作"
  405. width="80"
  406. fixed="right"
  407. >
  408. <template #default="{ row, $index }">
  409. <el-button type="primary" link @click="handleDelete($index)"
  410. >删除</el-button
  411. >
  412. </template>
  413. </el-table-column>
  414. </el-table>
  415. </div>
  416. </template>
  417. <template #offerMoney>
  418. <div style="width: 100%">
  419. <el-row style="margin-top: 20px; width: 100%">
  420. <el-col :span="4">
  421. <el-form-item label="币种" prop="currency">
  422. <el-select
  423. v-model="formData.data.currency"
  424. placeholder="请选择币种"
  425. style="width: 100%"
  426. >
  427. <el-option
  428. v-for="item in accountCurrency"
  429. :key="item.value"
  430. :label="item.label"
  431. :value="item.value"
  432. />
  433. </el-select>
  434. </el-form-item>
  435. </el-col>
  436. <el-col :span="1"></el-col>
  437. <el-col :span="6">
  438. <el-form-item label="合同总金额" prop="amount">
  439. <el-input
  440. v-model="formData.data.amount"
  441. placeholder="合同总金额"
  442. disabled
  443. />
  444. </el-form-item>
  445. </el-col>
  446. </el-row>
  447. <el-row style="margin-top: 20px; width: 100%">
  448. <el-col :span="6">
  449. <el-form-item label="付款方式" prop="paymentMethod">
  450. <el-select
  451. v-model="formData.data.paymentMethod"
  452. placeholder="请选择付款方式"
  453. style="width: 100%"
  454. >
  455. <el-option
  456. v-for="item in fundsPaymentMethod"
  457. :key="item.value"
  458. :label="item.label"
  459. :value="item.value"
  460. />
  461. </el-select>
  462. </el-form-item>
  463. </el-col>
  464. <el-col :span="1"></el-col>
  465. <el-col :span="6">
  466. <el-form-item label="预付比例 (%)" prop="advanceRatio">
  467. <el-input-number
  468. onmousewheel="return false;"
  469. v-model="formData.data.advanceRatio"
  470. placeholder="请输入预付比例"
  471. style="width: 100%"
  472. :precision="2"
  473. :controls="false"
  474. :min="0"
  475. :max="100"
  476. />
  477. </el-form-item>
  478. </el-col>
  479. <el-col :span="1"></el-col>
  480. <el-col :span="6">
  481. <el-form-item label="收款账号" prop="shroffAccountId">
  482. <el-select
  483. v-model="formData.data.shroffAccountId"
  484. placeholder="请选择收款账号"
  485. style="width: 100%"
  486. @change="changeShroffAccount"
  487. >
  488. <el-option
  489. v-for="item in accountList"
  490. :key="item.value"
  491. :label="item.label"
  492. :value="item.value"
  493. />
  494. </el-select>
  495. </el-form-item>
  496. </el-col>
  497. <el-col :span="1"></el-col>
  498. <el-col :span="3">
  499. <el-form-item label=" ">
  500. <el-button type="primary" @click="changeActiveName" text>
  501. <span v-if="activeName == '1'">收起</span>
  502. <span v-else>展开</span>
  503. </el-button>
  504. </el-form-item>
  505. </el-col>
  506. </el-row>
  507. <div style="width: 100%; margin-top: 34px">
  508. <el-collapse v-model="activeName" class="hideCollapse" accordion>
  509. <el-collapse-item title="" name="1">
  510. <el-row style="width: 100%">
  511. <el-col :span="9">
  512. <el-form-item
  513. label="Beneficiary Name"
  514. prop="beneficiaryName"
  515. >
  516. <el-input
  517. v-model="formData.data.beneficiaryName"
  518. placeholder="请输入Beneficiary Name"
  519. />
  520. </el-form-item>
  521. <div style="height: 20px"></div>
  522. <el-form-item
  523. label="Beneficiary Bank"
  524. prop="beneficiaryBank"
  525. >
  526. <el-input
  527. v-model="formData.data.beneficiaryBank"
  528. placeholder="请输入Beneficiary Bank"
  529. />
  530. </el-form-item>
  531. <div style="height: 20px"></div>
  532. <el-form-item
  533. label="Beneficiary Bank Address"
  534. prop="beneficiaryBankAddress"
  535. >
  536. <el-input
  537. v-model="formData.data.beneficiaryBankAddress"
  538. placeholder="请输入Beneficiary Bank Address"
  539. />
  540. </el-form-item>
  541. </el-col>
  542. <el-col :span="9">
  543. <el-form-item
  544. label="Beneficiary Account Number"
  545. prop="beneficiaryAccountNumber"
  546. >
  547. <el-input
  548. v-model="formData.data.beneficiaryAccountNumber"
  549. placeholder="请输入Beneficiary Account Number"
  550. />
  551. </el-form-item>
  552. <div style="height: 20px"></div>
  553. <el-form-item label="Swift Code" prop="swiftCode">
  554. <el-input
  555. v-model="formData.data.swiftCode"
  556. placeholder="请输入Swift Code"
  557. />
  558. </el-form-item>
  559. <div style="height: 20px"></div>
  560. <el-form-item
  561. label="Beneficiary Address"
  562. prop="beneficiaryAddress"
  563. >
  564. <el-input
  565. v-model="formData.data.beneficiaryAddress"
  566. placeholder="请输入Beneficiary Address"
  567. />
  568. </el-form-item>
  569. </el-col>
  570. </el-row>
  571. </el-collapse-item>
  572. </el-collapse>
  573. </div>
  574. </div>
  575. </template>
  576. <template #delivery>
  577. <div style="width: 100%">
  578. <el-row style="margin-top: 20px; width: 100%">
  579. <el-col :span="7">
  580. <el-form-item label="贸易方式" prop="tradeMethods">
  581. <el-select
  582. v-model="formData.data.tradeMethods"
  583. placeholder="请选择贸易方式"
  584. style="width: 100%"
  585. >
  586. <el-option
  587. v-for="item in tradeMethods"
  588. :key="item.value"
  589. :label="item.label"
  590. :value="item.value"
  591. />
  592. </el-select>
  593. </el-form-item>
  594. </el-col>
  595. </el-row>
  596. <el-row style="margin-top: 20px; width: 100%">
  597. <el-col :span="7">
  598. <el-form-item label="运输方式" prop="transportMethod">
  599. <el-select
  600. v-model="formData.data.transportMethod"
  601. placeholder="请选择运输方式"
  602. style="width: 100%"
  603. >
  604. <el-option
  605. v-for="item in shippingMethod"
  606. :key="item.value"
  607. :label="item.label"
  608. :value="item.value"
  609. />
  610. </el-select>
  611. </el-form-item>
  612. </el-col>
  613. <el-col :span="1"></el-col>
  614. <el-col :span="7">
  615. <el-form-item label="运输说明" prop="transportRemark">
  616. <el-input
  617. v-model="formData.data.transportRemark"
  618. placeholder="请输入运输说明"
  619. />
  620. </el-form-item>
  621. </el-col>
  622. </el-row>
  623. <el-row style="margin-top: 20px; width: 100%">
  624. <el-col :span="15">
  625. <el-form-item label="付款条件" prop="remark">
  626. <el-input
  627. v-model="formData.data.remark"
  628. :rows="2"
  629. type="textarea"
  630. placeholder="请输入付款条件"
  631. />
  632. </el-form-item>
  633. </el-col>
  634. </el-row>
  635. <el-row style="margin-top: 20px; width: 100%">
  636. <el-col :span="7">
  637. <el-form-item label="交货期限 (天)" prop="deliveryTime">
  638. <el-input-number
  639. onmousewheel="return false;"
  640. v-model="formData.data.deliveryTime"
  641. placeholder="请输入交货期限"
  642. style="width: 100%"
  643. :precision="0"
  644. :controls="false"
  645. :min="0"
  646. />
  647. </el-form-item>
  648. </el-col>
  649. <el-col :span="1"></el-col>
  650. <el-col :span="7">
  651. <el-form-item label="质保期 (天)" prop="warranty">
  652. <el-input-number
  653. onmousewheel="return false;"
  654. v-model="formData.data.warranty"
  655. placeholder="请输入质保期"
  656. style="width: 100%"
  657. :precision="0"
  658. :controls="false"
  659. :min="0"
  660. />
  661. </el-form-item>
  662. </el-col>
  663. </el-row>
  664. </div>
  665. </template>
  666. <template #shipment>
  667. <div style="width: 100%">
  668. <el-table
  669. :data="formData.data.contractShipmentList"
  670. style="width: 100%; margin-top: 16px"
  671. >
  672. <el-table-column prop="code" label="商品编码" width="120" />
  673. <el-table-column prop="productName" label="商品名称" />
  674. <el-table-column label="出货日期" width="220">
  675. <template #default="{ row, $index }">
  676. <div style="width: 100%">
  677. <el-form-item
  678. :prop="'contractShipmentList.' + $index + '.shipmentTime'"
  679. :rules="rules.shipmentTime"
  680. :inline-message="true"
  681. >
  682. <el-date-picker
  683. v-model="row.shipmentTime"
  684. type="date"
  685. placeholder="请选择出货日期"
  686. value-format="YYYY-MM-DD HH:mm:ss"
  687. />
  688. </el-form-item>
  689. </div>
  690. </template>
  691. </el-table-column>
  692. <el-table-column label="数量" width="160">
  693. <template #default="{ row, $index }">
  694. <div style="width: 100%">
  695. <el-form-item
  696. :prop="'contractShipmentList.' + $index + '.quantity'"
  697. :inline-message="true"
  698. >
  699. <el-input-number
  700. onmousewheel="return false;"
  701. v-model="row.quantity"
  702. placeholder="请输入数量"
  703. style="width: 100%"
  704. :controls="false"
  705. :min="0"
  706. @change="
  707. () => {
  708. return calculationAmount(
  709. 'contractShipmentList',
  710. $index,
  711. 'quantity'
  712. );
  713. }
  714. "
  715. />
  716. </el-form-item>
  717. </div>
  718. </template>
  719. </el-table-column>
  720. <el-table-column
  721. align="center"
  722. label="操作"
  723. width="120"
  724. fixed="right"
  725. >
  726. <template #default="{ row, $index }">
  727. <el-button type="primary" link @click="clickSplit(row)"
  728. >拆分</el-button
  729. >
  730. <el-button type="primary" link @click="clickDelete($index)"
  731. >删除</el-button
  732. >
  733. </template>
  734. </el-table-column>
  735. </el-table>
  736. </div>
  737. </template>
  738. </byForm>
  739. <el-dialog
  740. v-if="openProduct"
  741. v-model="openProduct"
  742. title="选择商品"
  743. width="70%"
  744. append-to-body
  745. >
  746. <SelectGoods
  747. :selectList="acquireSelectList()"
  748. @cancel="openProduct = false"
  749. @pushGoods="pushGoods"
  750. ></SelectGoods>
  751. </el-dialog>
  752. <el-dialog
  753. title="交接单"
  754. v-if="openHandover"
  755. v-model="openHandover"
  756. width="800"
  757. >
  758. <byForm
  759. :formConfig="formHandoverConfig"
  760. :formOption="formOption"
  761. v-model="productRow.data"
  762. >
  763. <template #remark>
  764. <div style="width: 100%">
  765. <Editor
  766. :value="productRow.data.remark"
  767. @updateValue="updateContent"
  768. />
  769. </div>
  770. </template>
  771. <template #file>
  772. <div style="width: 100%">
  773. <el-upload
  774. v-model:fileList="fileList"
  775. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  776. :data="uploadData"
  777. multiple
  778. :before-upload="uploadFile"
  779. :on-success="handleSuccess"
  780. :on-preview="onPreviewFile"
  781. >
  782. <el-button>选择</el-button>
  783. </el-upload>
  784. </div>
  785. </template>
  786. </byForm>
  787. <template #footer>
  788. <el-button @click="openHandover = false" size="large">取 消</el-button>
  789. <el-button type="primary" @click="submitHandoverForm()" size="large"
  790. >确 定</el-button
  791. >
  792. </template>
  793. </el-dialog>
  794. </div>
  795. </template>
  796. <script setup>
  797. import byForm from "@/components/byForm/index";
  798. import SelectGoods from "@/components/product/SelectGoods";
  799. import { ElMessage } from "element-plus";
  800. import Editor from "@/components/Editor/index.vue";
  801. import selectCity from "@/components/selectCity/index.vue";
  802. import { useRoute } from "vue-router";
  803. const route = useRoute();
  804. // 接收父组件的传值
  805. const props = defineProps({
  806. queryData: String,
  807. });
  808. const { proxy } = getCurrentInstance();
  809. const contractType = ref([]);
  810. const accountCurrency = ref([]);
  811. const fundsPaymentMethod = ref([]);
  812. const tradeMethods = ref([]);
  813. const shippingMethod = ref([]);
  814. const templateList = ref([]);
  815. const corporationList = ref([]);
  816. const customerList = ref([]);
  817. const countryData = ref([]);
  818. const provinceData = ref([]);
  819. const cityData = ref([]);
  820. const customerUserList = ref([]);
  821. const accountList = ref([]);
  822. const productUnit = ref([]);
  823. const openProduct = ref(false);
  824. const activeName = ref("1");
  825. const formData = reactive({
  826. data: {
  827. contractType: "1",
  828. amount: undefined,
  829. contractProductList: [],
  830. contractProjectList: [],
  831. contractShipmentList: [],
  832. },
  833. });
  834. const submit = ref(null);
  835. const judgeStatus = () => {
  836. if (route.query.processType == 20 || route.query.processType == 10) {
  837. return true;
  838. }
  839. if (props.queryData.recordList && props.queryData.recordList.length > 0) {
  840. let data = props.queryData.recordList.filter(
  841. (item) => item.status === 2 && item.nodeType !== 1
  842. );
  843. if (data && data.length > 0) {
  844. return true;
  845. }
  846. }
  847. return false;
  848. };
  849. const formOption = reactive({
  850. inline: true,
  851. labelWidth: 100,
  852. itemWidth: 100,
  853. rules: [],
  854. disabled: false,
  855. });
  856. const formConfig = computed(() => {
  857. return [
  858. {
  859. type: "title",
  860. title: "合同模板",
  861. label: "",
  862. },
  863. {
  864. type: "select",
  865. label: "合同类型",
  866. prop: "contractType",
  867. data: contractType.value,
  868. itemWidth: 25,
  869. },
  870. {
  871. type: "select",
  872. label: "选择合同模板",
  873. prop: "contractTemplateId",
  874. data: templateList.value,
  875. fn: (val) => {
  876. changeTemplate(val);
  877. },
  878. itemWidth: 26,
  879. },
  880. {
  881. type: "slot",
  882. slotName: "seller",
  883. label: "卖方信息",
  884. itemWidth: 50,
  885. },
  886. {
  887. type: "slot",
  888. slotName: "buyer",
  889. label: "买方信息",
  890. itemWidth: 50,
  891. },
  892. {
  893. type: "slot",
  894. slotName: "commodity",
  895. label: "商品信息",
  896. },
  897. {
  898. type: "slot",
  899. slotName: "otherCharge",
  900. label: "其他收费项目",
  901. },
  902. {
  903. type: "slot",
  904. slotName: "offerMoney",
  905. label: "收款信息",
  906. },
  907. {
  908. type: "slot",
  909. slotName: "delivery",
  910. label: "交付信息",
  911. },
  912. {
  913. type: "slot",
  914. slotName: "shipment",
  915. label: "出货计划",
  916. },
  917. ];
  918. });
  919. const rules = ref({
  920. contractType: [
  921. { required: true, message: "请选择合同类型", trigger: "change" },
  922. ],
  923. contractTemplateId: [
  924. { required: true, message: "请选择合同模板", trigger: "change" },
  925. ],
  926. buyCorporationId: [
  927. { required: true, message: "请选择公司", trigger: "change" },
  928. ],
  929. countryId: [{ required: true, message: "请选择国家", trigger: "change" }],
  930. sellAddress: [{ required: true, message: "请输入详细地址", trigger: "blur" }],
  931. buyAddress: [{ required: true, message: "请输入详细地址", trigger: "blur" }],
  932. buyContactName: [
  933. { required: true, message: "请输入联系人", trigger: ["change", "blur"] },
  934. ],
  935. buyContactNumber: [
  936. { required: true, message: "请输入联系电话", trigger: "blur" },
  937. ],
  938. productName: [
  939. { required: true, message: "请输入商品英文名", trigger: "blur" },
  940. ],
  941. productModel: [
  942. { required: true, message: "请输入规格型号", trigger: "blur" },
  943. ],
  944. quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  945. price: [{ required: true, message: "请输入单价", trigger: "blur" }],
  946. amount: [{ required: true, message: "请输入金额", trigger: "blur" }],
  947. payName: [
  948. { required: true, message: "请输入收费项目", trigger: ["change", "blur"] },
  949. ],
  950. currency: [{ required: true, message: "请选择币种", trigger: "change" }],
  951. effective: [{ required: true, message: "请输入报价有效期", trigger: "blur" }],
  952. deliveryTime: [
  953. { required: true, message: "请选择交货期限", trigger: "blur" },
  954. ],
  955. paymentMethod: [
  956. { required: true, message: "请选择付款方式", trigger: "change" },
  957. ],
  958. advanceRatio: [
  959. { required: true, message: "请输入预付比例", trigger: "blur" },
  960. ],
  961. shroffAccountId: [
  962. { required: true, message: "请选择收款账号", trigger: "change" },
  963. ],
  964. tradeMethods: [
  965. { required: true, message: "请选择贸易方式", trigger: "change" },
  966. ],
  967. transportMethod: [
  968. { required: true, message: "请选择运输方式", trigger: "change" },
  969. ],
  970. transportRemark: [
  971. { required: true, message: "请输入运输说明", trigger: "blur" },
  972. ],
  973. remark: [{ required: true, message: "请输入付款条件", trigger: "blur" }],
  974. });
  975. const getDict = () => {
  976. proxy
  977. .getDictOne([
  978. "account_currency",
  979. "funds_payment_method",
  980. "trade_mode",
  981. "shipping_method",
  982. "contract_type",
  983. "unit",
  984. ])
  985. .then((res) => {
  986. accountCurrency.value = res["account_currency"].map((x) => ({
  987. label: x.dictValue,
  988. value: x.dictKey,
  989. }));
  990. fundsPaymentMethod.value = res["funds_payment_method"].map((x) => ({
  991. label: x.dictValue,
  992. value: x.dictKey,
  993. }));
  994. tradeMethods.value = res["trade_mode"].map((x) => ({
  995. label: x.dictValue,
  996. value: x.dictKey,
  997. }));
  998. shippingMethod.value = res["shipping_method"].map((x) => ({
  999. label: x.dictValue,
  1000. value: x.dictKey,
  1001. }));
  1002. contractType.value = res["contract_type"].map((x) => ({
  1003. label: x.dictValue,
  1004. value: x.dictKey,
  1005. }));
  1006. productUnit.value = res["unit"].map((x) => ({
  1007. label: x.dictValue,
  1008. value: x.dictKey,
  1009. }));
  1010. });
  1011. proxy
  1012. .post("/contractTemplate/page", { pageNum: 1, pageSize: 999 })
  1013. .then((res) => {
  1014. templateList.value = res.rows.map((item) => {
  1015. return {
  1016. ...item,
  1017. label: item.templateName,
  1018. value: item.id,
  1019. };
  1020. });
  1021. });
  1022. proxy.post("/corporation/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  1023. corporationList.value = res.rows.map((item) => {
  1024. return {
  1025. ...item,
  1026. label: item.name,
  1027. value: item.id,
  1028. };
  1029. });
  1030. });
  1031. proxy
  1032. .post("/accountManagement/page", { pageNum: 1, pageSize: 999 })
  1033. .then((res) => {
  1034. accountList.value = res.rows.map((item) => {
  1035. return {
  1036. ...item,
  1037. label: item.alias,
  1038. value: item.id,
  1039. };
  1040. });
  1041. });
  1042. };
  1043. getDict();
  1044. const changeTemplate = (val) => {
  1045. formData.data.sellCorporationId = "";
  1046. formData.data.sellContactName = "";
  1047. formData.data.sellContactNumber = "";
  1048. formData.data.sellCountryName = "";
  1049. formData.data.sellProvinceName = "";
  1050. formData.data.sellCityName = "";
  1051. formData.data.sellAddress = "";
  1052. if (val) {
  1053. proxy.post("/contractTemplate/detail", { id: val }).then((res) => {
  1054. formData.data.sellCorporationId = res.corporationId;
  1055. if (res.corporationId) {
  1056. proxy
  1057. .post("/corporation/detail", { id: res.corporationId })
  1058. .then((detailCorporation) => {
  1059. if (detailCorporation.countryEnStr) {
  1060. formData.data.sellCountryName = detailCorporation.countryEnStr;
  1061. }
  1062. if (detailCorporation.provinceEnStr) {
  1063. formData.data.sellProvinceName = detailCorporation.provinceEnStr;
  1064. }
  1065. if (detailCorporation.cityEnStr) {
  1066. formData.data.sellCityName = detailCorporation.cityEnStr;
  1067. }
  1068. if (detailCorporation.addressEn) {
  1069. formData.data.sellAddress = detailCorporation.addressEn;
  1070. }
  1071. // proxy.post("/customizeArea/list", { parentId: "0" }).then((resCountry) => {
  1072. // let sellCountryData = resCountry.filter((item) => item.id === detailCorporation.countryId);
  1073. // if (sellCountryData && sellCountryData.length > 0) {
  1074. // formData.data.sellCountryName = sellCountryData[0].chineseName;
  1075. // } else {
  1076. // formData.data.sellCountryName = "";
  1077. // }
  1078. // });
  1079. // if (detailCorporation.countryId) {
  1080. // proxy
  1081. // .post("/customizeArea/list", {
  1082. // parentId: detailCorporation.countryId,
  1083. // })
  1084. // .then((resProvince) => {
  1085. // let sellProvinceData = resProvince.filter((item) => item.id === detailCorporation.provinceId);
  1086. // if (sellProvinceData && sellProvinceData.length > 0) {
  1087. // formData.data.sellProvinceName = sellProvinceData[0].name;
  1088. // } else {
  1089. // formData.data.sellProvinceName = "";
  1090. // }
  1091. // });
  1092. // } else {
  1093. // formData.data.sellProvinceName = "";
  1094. // }
  1095. // if (detailCorporation.provinceId) {
  1096. // proxy
  1097. // .post("/customizeArea/list", {
  1098. // parentId: detailCorporation.provinceId,
  1099. // })
  1100. // .then((resCity) => {
  1101. // let sellCityData = resCity.filter((item) => item.id === detailCorporation.cityId);
  1102. // if (sellCityData && sellCityData.length > 0) {
  1103. // formData.data.sellCityName = sellCityData[0].name;
  1104. // } else {
  1105. // formData.data.sellCityName = "";
  1106. // }
  1107. // });
  1108. // } else {
  1109. // formData.data.sellCityName = "";
  1110. // }
  1111. // formData.data.sellAddress = detailCorporation.address;
  1112. });
  1113. }
  1114. formData.data.sellContactName = res.contactName;
  1115. formData.data.sellContactNumber = res.contactNumber;
  1116. });
  1117. }
  1118. };
  1119. const getCityData = (id, type, isChange) => {
  1120. proxy.post("/customizeArea/list", { parentId: id }).then((res) => {
  1121. if (type === "20") {
  1122. provinceData.value = res;
  1123. if (isChange) {
  1124. formData.data.provinceId = "";
  1125. formData.data.provinceName = "";
  1126. formData.data.cityId = "";
  1127. formData.data.cityName = "";
  1128. }
  1129. } else if (type === "30") {
  1130. cityData.value = res;
  1131. if (isChange) {
  1132. formData.data.cityId = "";
  1133. formData.data.cityName = "";
  1134. }
  1135. } else {
  1136. countryData.value = res;
  1137. }
  1138. });
  1139. };
  1140. getCityData("0");
  1141. const changeCustomer = (val) => {
  1142. formData.data.buyContactName = "";
  1143. formData.data.buyContactNumber = "";
  1144. if (val) {
  1145. proxy.post("/customer/detail", { id: val }).then(
  1146. (res) => {
  1147. if (res.customerUserList && res.customerUserList.length > 0) {
  1148. formData.data.buyContactName = res.customerUserList[0].name;
  1149. if (res.customerUserList[0].contactJson) {
  1150. let contactJson = JSON.parse(res.customerUserList[0].contactJson);
  1151. if (contactJson && contactJson.length > 0) {
  1152. formData.data.buyContactNumber = contactJson[0].contactNo;
  1153. }
  1154. }
  1155. customerUserList.value = res.customerUserList.map((item) => {
  1156. return {
  1157. ...item,
  1158. value: item.name,
  1159. };
  1160. });
  1161. }
  1162. formData.data.countryId = res.countryId;
  1163. formData.data.provinceId = res.provinceId;
  1164. formData.data.cityId = res.cityId;
  1165. formData.data.buyPostalCode = res.zipCode;
  1166. formData.data.buyAddress = res.address;
  1167. getCityData(formData.data.countryId, "20");
  1168. if (formData.data.provinceId) {
  1169. getCityData(formData.data.provinceId, "30");
  1170. }
  1171. },
  1172. (err) => {
  1173. console.log(err);
  1174. formData.data.countryId = "";
  1175. formData.data.provinceId = "";
  1176. formData.data.cityId = "";
  1177. formData.data.buyPostalCode = "";
  1178. formData.data.buyAddress = "";
  1179. }
  1180. );
  1181. } else {
  1182. formData.data.countryId = "";
  1183. formData.data.provinceId = "";
  1184. formData.data.cityId = "";
  1185. formData.data.buyPostalCode = "";
  1186. formData.data.buyAddress = "";
  1187. }
  1188. getDecisionAids();
  1189. };
  1190. let auxiliaryData = ref([
  1191. {
  1192. label: "最近合同",
  1193. data: [],
  1194. },
  1195. {
  1196. label: "产品价格",
  1197. data: [],
  1198. },
  1199. ]);
  1200. const emit = defineEmits(["auxiliaryChange"]);
  1201. const getDecisionAids = () => {
  1202. let data = {
  1203. buyCorporationId: formData.data.buyCorporationId,
  1204. productIdList: [],
  1205. };
  1206. if (
  1207. formData.data.contractProductList &&
  1208. formData.data.contractProductList.length > 0
  1209. ) {
  1210. data.productIdList = formData.data.contractProductList.map(
  1211. (item) => item.productId
  1212. );
  1213. }
  1214. proxy.post("/contract/decisionAid", data).then((res) => {
  1215. if (res.lastContractList && res.lastContractList.length > 0) {
  1216. auxiliaryData.value[0].data = res.lastContractList.map((item) => {
  1217. return [
  1218. {
  1219. label: "合同编号",
  1220. value: item.code,
  1221. style: {
  1222. color: "#0084FF",
  1223. },
  1224. id: item.id,
  1225. num: 1,
  1226. // fn: () => {},
  1227. },
  1228. {
  1229. label: "下单日期",
  1230. value: item.createTime,
  1231. id: item.id,
  1232. num: 1,
  1233. },
  1234. {
  1235. label: "合同金额",
  1236. value: item.currency + item.amount,
  1237. id: item.id,
  1238. num: 1,
  1239. },
  1240. ];
  1241. });
  1242. } else {
  1243. auxiliaryData.value[0].data = [];
  1244. }
  1245. if (res.productPriceList && res.productPriceList.length > 0) {
  1246. auxiliaryData.value[1].data = res.productPriceList.map((item) => {
  1247. return [
  1248. {
  1249. label: "产品名称",
  1250. value: item.name,
  1251. id: item.id,
  1252. num: 1,
  1253. },
  1254. {
  1255. label: "最近价格",
  1256. value: item.lastPrice,
  1257. id: item.id,
  1258. num: 1,
  1259. },
  1260. {
  1261. label: "历史最高",
  1262. value: item.maxPrice,
  1263. id: item.id,
  1264. num: 1,
  1265. },
  1266. {
  1267. label: "历史最低",
  1268. value: item.minPrice,
  1269. id: item.id,
  1270. num: 1,
  1271. },
  1272. ];
  1273. });
  1274. } else {
  1275. auxiliaryData.value[1].data = [];
  1276. }
  1277. emit("auxiliaryChange", auxiliaryData.value);
  1278. });
  1279. };
  1280. const createFilter = (queryString) => {
  1281. return (restaurant) => {
  1282. return (
  1283. restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
  1284. );
  1285. };
  1286. };
  1287. const querySearchPerson = (queryString, callback) => {
  1288. const results = queryString
  1289. ? customerUserList.value.filter(createFilter(queryString))
  1290. : customerUserList.value;
  1291. callback(results);
  1292. };
  1293. const handlePerson = (item) => {
  1294. if (item.contactJson) {
  1295. let contactJson = JSON.parse(item.contactJson);
  1296. if (contactJson && contactJson.length > 0) {
  1297. formData.data.buyContactNumber = contactJson[0].contactNo;
  1298. } else {
  1299. formData.data.buyContactNumber = "";
  1300. }
  1301. }
  1302. };
  1303. const pushGoods = (goods) => {
  1304. if (goods && goods.length > 0) {
  1305. let afterFiltering = [];
  1306. if (
  1307. formData.data.contractProductList &&
  1308. formData.data.contractProductList.length > 0
  1309. ) {
  1310. afterFiltering = goods.filter((item) => {
  1311. let data = formData.data.contractProductList.filter(
  1312. (itemProduct) => itemProduct.productId === item.id
  1313. );
  1314. if (data && data.length > 0) {
  1315. return false;
  1316. }
  1317. return true;
  1318. });
  1319. } else {
  1320. afterFiltering = goods;
  1321. }
  1322. formData.data.contractProductList =
  1323. formData.data.contractProductList.concat(
  1324. afterFiltering.map((item) => {
  1325. let fileUrl = "";
  1326. if (item.fileList && item.fileList.length > 0) {
  1327. fileUrl = item.fileList[0].fileUrl;
  1328. }
  1329. let name = item.name;
  1330. if (item.standardJson) {
  1331. let standardJson = JSON.parse(item.standardJson);
  1332. if (standardJson && standardJson.englishName) {
  1333. name = standardJson.englishName;
  1334. }
  1335. }
  1336. return {
  1337. fileUrl: fileUrl,
  1338. code: item.code,
  1339. productId: item.id,
  1340. name: item.name,
  1341. productName: name,
  1342. productModel: item.spec,
  1343. unit: item.unit,
  1344. quantity: undefined,
  1345. price: undefined,
  1346. amount: "",
  1347. remark: "",
  1348. fileList: [],
  1349. };
  1350. })
  1351. );
  1352. formData.data.contractShipmentList =
  1353. formData.data.contractShipmentList.concat(
  1354. afterFiltering.map((item) => {
  1355. return {
  1356. code: item.code,
  1357. productId: item.id,
  1358. productName: item.name,
  1359. shipmentTime: "",
  1360. quantity: undefined,
  1361. };
  1362. })
  1363. );
  1364. ElMessage({
  1365. message: "添加成功!",
  1366. type: "success",
  1367. });
  1368. openProduct.value = false;
  1369. getDecisionAids();
  1370. } else {
  1371. ElMessage("请选择至少一件商品");
  1372. }
  1373. };
  1374. const onPicture = (path) => {
  1375. window.open(path, "_blank");
  1376. };
  1377. const productRow = reactive({
  1378. data: {
  1379. productName: "",
  1380. productModel: "",
  1381. remark: "",
  1382. },
  1383. });
  1384. const productIndex = ref(0);
  1385. const openHandover = ref(false);
  1386. const fileList = ref([]);
  1387. const uploadData = ref({});
  1388. const formHandoverConfig = computed(() => {
  1389. return [
  1390. {
  1391. type: "title",
  1392. title: "产品信息",
  1393. label: "",
  1394. },
  1395. {
  1396. type: "input",
  1397. prop: "productName",
  1398. label: "产品名称",
  1399. itemType: "text",
  1400. disabled: true,
  1401. },
  1402. {
  1403. type: "input",
  1404. prop: "productModel",
  1405. label: "规格型号",
  1406. itemType: "text",
  1407. disabled: true,
  1408. },
  1409. {
  1410. type: "slot",
  1411. slotName: "remark",
  1412. label: "交接单",
  1413. },
  1414. {
  1415. type: "slot",
  1416. prop: "file",
  1417. slotName: "file",
  1418. label: "上传附件",
  1419. },
  1420. ];
  1421. });
  1422. const handleHandover = (row, index) => {
  1423. productRow.data = {
  1424. productName: row.productName,
  1425. productModel: row.productModel,
  1426. remark: row.remark,
  1427. };
  1428. if (row.fileList && row.fileList.length > 0) {
  1429. fileList.value = row.fileList.map((item) => {
  1430. return {
  1431. raw: item,
  1432. name: item.fileName,
  1433. url: item.fileUrl,
  1434. };
  1435. });
  1436. } else {
  1437. fileList.value = [];
  1438. }
  1439. productIndex.value = index;
  1440. openHandover.value = true;
  1441. };
  1442. const updateContent = (val) => {
  1443. productRow.data.remark = val;
  1444. };
  1445. const changeActiveName = () => {
  1446. if (activeName.value) {
  1447. activeName.value = "";
  1448. } else {
  1449. activeName.value = "1";
  1450. }
  1451. };
  1452. const uploadFile = async (file) => {
  1453. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  1454. uploadData.value = res.uploadBody;
  1455. file.id = res.id;
  1456. file.fileName = res.fileName;
  1457. file.fileUrl = res.fileUrl;
  1458. file.uploadState = true;
  1459. return true;
  1460. };
  1461. const handleSuccess = (any, UploadFile) => {
  1462. UploadFile.raw.uploadState = false;
  1463. };
  1464. const onPreviewFile = (file) => {
  1465. window.open(file.raw.fileUrl, "_blank");
  1466. };
  1467. const submitHandoverForm = () => {
  1468. if (fileList.value && fileList.value.length > 0) {
  1469. for (let i = 0; i < fileList.value.length; i++) {
  1470. if (fileList.value[i].raw.uploadState) {
  1471. ElMessage("文件上传中,请稍后提交");
  1472. return;
  1473. }
  1474. }
  1475. formData.data.contractProductList[productIndex.value].fileList =
  1476. fileList.value.map((item) => {
  1477. return {
  1478. id: item.raw.id,
  1479. fileName: item.raw.fileName,
  1480. fileUrl: item.raw.fileUrl,
  1481. uploadState: item.raw.uploadState,
  1482. };
  1483. });
  1484. } else {
  1485. formData.data.contractProductList[productIndex.value].fileList = [];
  1486. }
  1487. formData.data.contractProductList[productIndex.value].remark =
  1488. productRow.data.remark;
  1489. openHandover.value = false;
  1490. };
  1491. const handleRemove = async (index, row) => {
  1492. formData.data.contractShipmentList =
  1493. formData.data.contractShipmentList.filter(
  1494. (item) => item.productId !== row.productId
  1495. );
  1496. await formData.data.contractProductList.splice(index, 1);
  1497. totalAmount();
  1498. getDecisionAids();
  1499. };
  1500. const calculationAmount = (listLabel, index, label) => {
  1501. if (formData.data[listLabel][index][label]) {
  1502. formData.data[listLabel][index][label] = Number(
  1503. Math.round(Number(formData.data[listLabel][index][label]) * 10000) / 10000
  1504. );
  1505. }
  1506. nextTick(() => {
  1507. if (
  1508. formData.data.contractProductList &&
  1509. formData.data.contractProductList.length > 0
  1510. ) {
  1511. for (let i = 0; i < formData.data.contractProductList.length; i++) {
  1512. let money = 0;
  1513. if (
  1514. formData.data.contractProductList[i].quantity &&
  1515. formData.data.contractProductList[i].price
  1516. ) {
  1517. money = Number(
  1518. Math.round(
  1519. Number(formData.data.contractProductList[i].quantity) *
  1520. Number(formData.data.contractProductList[i].price) *
  1521. 10000
  1522. ) / 10000
  1523. );
  1524. }
  1525. formData.data.contractProductList[i].amount = money;
  1526. }
  1527. }
  1528. nextTick(() => {
  1529. totalAmount();
  1530. });
  1531. });
  1532. };
  1533. const totalAmount = (listLabel, index, label) => {
  1534. if (listLabel && formData.data[listLabel][index][label]) {
  1535. formData.data[listLabel][index][label] = Number(
  1536. Math.round(Number(formData.data[listLabel][index][label]) * 10000) / 10000
  1537. );
  1538. }
  1539. let money = 0;
  1540. if (
  1541. formData.data.contractProductList &&
  1542. formData.data.contractProductList.length > 0
  1543. ) {
  1544. for (let i = 0; i < formData.data.contractProductList.length; i++) {
  1545. if (formData.data.contractProductList[i].amount) {
  1546. money = Number(
  1547. Math.round(
  1548. (Number(money) +
  1549. Number(formData.data.contractProductList[i].amount)) *
  1550. 10000
  1551. ) / 10000
  1552. );
  1553. }
  1554. }
  1555. }
  1556. if (
  1557. formData.data.contractProjectList &&
  1558. formData.data.contractProjectList.length > 0
  1559. ) {
  1560. for (let i = 0; i < formData.data.contractProjectList.length; i++) {
  1561. if (formData.data.contractProjectList[i].amount) {
  1562. money = Number(
  1563. Math.round(
  1564. (Number(money) +
  1565. Number(formData.data.contractProjectList[i].amount)) *
  1566. 10000
  1567. ) / 10000
  1568. );
  1569. }
  1570. }
  1571. }
  1572. formData.data.amount = money;
  1573. };
  1574. const clickAdd = () => {
  1575. if (
  1576. formData.data.contractProjectList &&
  1577. formData.data.contractProjectList.length > 0
  1578. ) {
  1579. formData.data.contractProjectList.push({
  1580. payName: "",
  1581. amount: undefined,
  1582. remark: "",
  1583. });
  1584. } else {
  1585. formData.data.contractProjectList = [
  1586. { payName: "", amount: undefined, remark: "" },
  1587. ];
  1588. }
  1589. };
  1590. const handleDelete = async (index) => {
  1591. await formData.data.contractProjectList.splice(index, 1);
  1592. totalAmount();
  1593. };
  1594. const querySearch = (queryString, callback) => {
  1595. proxy.post("/quotationPay/page", { payName: queryString }).then((res) => {
  1596. if (res.rows && res.rows.length > 0) {
  1597. res.rows = res.rows.map((item) => {
  1598. return {
  1599. ...item,
  1600. value: item.payName,
  1601. };
  1602. });
  1603. callback(res.rows);
  1604. } else {
  1605. callback([]);
  1606. }
  1607. });
  1608. };
  1609. const clickSplit = (item) => {
  1610. formData.data.contractShipmentList.push({
  1611. code: item.code,
  1612. productId: item.productId,
  1613. productName: item.productName,
  1614. shipmentTime: "",
  1615. quantity: undefined,
  1616. });
  1617. };
  1618. const clickDelete = (index) => {
  1619. formData.data.contractShipmentList.splice(index, 1);
  1620. };
  1621. const handleSubmit = async () => {
  1622. let status = await submit.value.handleSubmit(() => {});
  1623. if (status) {
  1624. if (
  1625. !(
  1626. formData.data.contractProductList &&
  1627. formData.data.contractProductList.length > 0
  1628. )
  1629. ) {
  1630. ElMessage("请添加至少一件商品");
  1631. return false;
  1632. }
  1633. if (
  1634. formData.data.contractShipmentList &&
  1635. formData.data.contractShipmentList.length > 0
  1636. ) {
  1637. for (let i = 0; i < formData.data.contractProductList.length; i++) {
  1638. let data = formData.data.contractShipmentList.filter(
  1639. (item) =>
  1640. item.productId === formData.data.contractProductList[i].productId
  1641. );
  1642. if (data && data.length > 0) {
  1643. let quantity = 0;
  1644. for (let j = 0; j < data.length; j++) {
  1645. quantity = parseFloat(Number(quantity) + Number(data[j].quantity));
  1646. }
  1647. if (quantity > formData.data.contractProductList[i].quantity) {
  1648. ElMessage("出货数量不能大于商品数量");
  1649. return false;
  1650. }
  1651. }
  1652. }
  1653. }
  1654. return true;
  1655. } else {
  1656. setTimeout(() => {
  1657. const errorDiv = document.getElementsByClassName("is-error");
  1658. errorDiv[0].scrollIntoView();
  1659. }, 0);
  1660. }
  1661. return false;
  1662. };
  1663. const getFormData = () => {
  1664. return proxy.deepClone(formData.data);
  1665. };
  1666. // 向父组件暴露
  1667. defineExpose({
  1668. getFormData,
  1669. handleSubmit,
  1670. });
  1671. const changeShroffAccount = (val) => {
  1672. if (val) {
  1673. let data = accountList.value.filter((item) => item.value === val);
  1674. if (data && data.length > 0) {
  1675. formData.data.beneficiaryName = data[0].beneficiaryName;
  1676. formData.data.beneficiaryBank = data[0].beneficiaryBank;
  1677. formData.data.beneficiaryBankAddress = data[0].beneficiaryBankAddress;
  1678. formData.data.beneficiaryAccountNumber = data[0].beneficiaryAccountNumber;
  1679. formData.data.swiftCode = data[0].swiftCode;
  1680. formData.data.beneficiaryAddress = data[0].beneficiaryAddress;
  1681. }
  1682. }
  1683. };
  1684. watch(
  1685. props.queryData,
  1686. () => {
  1687. formOption.disabled = judgeStatus();
  1688. if (
  1689. props.queryData &&
  1690. ["10", "20", "30"].includes(route.query.processType)
  1691. ) {
  1692. for (var text in props.queryData) {
  1693. formData.data[text] = props.queryData[text];
  1694. }
  1695. if (formData.data.countryId) {
  1696. getCityData(formData.data.countryId, "20");
  1697. }
  1698. if (formData.data.provinceId) {
  1699. getCityData(formData.data.provinceId, "30");
  1700. }
  1701. getDecisionAids();
  1702. }
  1703. },
  1704. {
  1705. deep: true,
  1706. }
  1707. );
  1708. const acquireSelectList = () => {
  1709. let data = [];
  1710. if (
  1711. formData.data.contractProductList &&
  1712. formData.data.contractProductList.length > 0
  1713. ) {
  1714. data = formData.data.contractProductList.map((item) => {
  1715. return {
  1716. id: item.productId,
  1717. name: item.name,
  1718. };
  1719. });
  1720. }
  1721. return data;
  1722. };
  1723. onMounted(() => {
  1724. if (!route.query.processType || route.query.processType == 30) {
  1725. proxy
  1726. .post("/customer/privateSeaPage", { pageNum: 1, pageSize: 999 })
  1727. .then((res) => {
  1728. customerList.value = res.rows.map((item) => {
  1729. return {
  1730. ...item,
  1731. label: item.name,
  1732. value: item.id,
  1733. };
  1734. });
  1735. });
  1736. } else {
  1737. proxy.post("/customer/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  1738. customerList.value = res.rows.map((item) => {
  1739. return {
  1740. ...item,
  1741. label: item.name,
  1742. value: item.id,
  1743. };
  1744. });
  1745. });
  1746. }
  1747. // 报价单生成合同
  1748. if (props.queryData.priceSheetId) {
  1749. proxy
  1750. .post("/saleQuotation/detail", { id: props.queryData.priceSheetId })
  1751. .then((res) => {
  1752. res.countryId = res.buyCountryId;
  1753. res.provinceId = res.buyProvinceId;
  1754. res.cityId = res.buyCityId;
  1755. for (var text in res) {
  1756. formData.data[text] = res[text];
  1757. }
  1758. if (
  1759. formData.data.quotationProductList &&
  1760. formData.data.quotationProductList.length > 0
  1761. ) {
  1762. formData.data.contractProductList =
  1763. formData.data.quotationProductList.map((item) => {
  1764. delete item.id;
  1765. return {
  1766. ...item,
  1767. };
  1768. });
  1769. formData.data.contractShipmentList = proxy.deepClone(
  1770. formData.data.contractProductList.map((item) => {
  1771. return {
  1772. ...item,
  1773. quantity: undefined,
  1774. };
  1775. })
  1776. );
  1777. for (let i = 0; i < formData.data.contractProductList.length; i++) {
  1778. proxy
  1779. .post("/productInfo/detail", {
  1780. id: formData.data.contractProductList[i].productId,
  1781. })
  1782. .then((resProduct) => {
  1783. let name = resProduct.name;
  1784. if (resProduct.standardJson) {
  1785. let standardJson = JSON.parse(resProduct.standardJson);
  1786. if (standardJson && standardJson.englishName) {
  1787. name = standardJson.englishName;
  1788. }
  1789. }
  1790. formData.data.contractProductList[i].name = resProduct.name;
  1791. formData.data.contractProductList[i].productName = name;
  1792. formData.data.contractProductList[i].code = resProduct.code;
  1793. formData.data.contractProductList[i].unit = resProduct.unit;
  1794. formData.data.contractShipmentList[i].code = resProduct.code;
  1795. });
  1796. }
  1797. }
  1798. delete formData.data.id;
  1799. delete formData.data.code;
  1800. getCityData(formData.data.countryId, "20");
  1801. if (formData.data.provinceId) {
  1802. getCityData(formData.data.provinceId, "30");
  1803. }
  1804. if (
  1805. formData.data.quotationPayList &&
  1806. formData.data.quotationPayList.length > 0
  1807. ) {
  1808. formData.data.contractProjectList =
  1809. formData.data.quotationPayList.map((item) => {
  1810. delete item.id;
  1811. return {
  1812. ...item,
  1813. };
  1814. });
  1815. }
  1816. });
  1817. }
  1818. if (route.query && route.query.businessId) {
  1819. proxy
  1820. .post("/contract/detail", { id: route.query.businessId })
  1821. .then((res) => {
  1822. setTimeout(() => {
  1823. formData.data.id = res.id;
  1824. for (let i = 0; i < formData.data.contractProductList.length; i++) {
  1825. formData.data.contractProductList[i].id =
  1826. res.contractProductList[i].id;
  1827. }
  1828. for (let i = 0; i < formData.data.contractProjectList.length; i++) {
  1829. formData.data.contractProjectList[i].id =
  1830. res.contractProjectList[i].id;
  1831. }
  1832. for (let i = 0; i < formData.data.contractShipmentList.length; i++) {
  1833. formData.data.contractShipmentList[i].id =
  1834. res.contractShipmentList[i].id;
  1835. }
  1836. }, 2000);
  1837. });
  1838. }
  1839. // 暂存修改
  1840. if (!route.query.processType && route.query.contractId) {
  1841. proxy
  1842. .post("/contract/detail", { id: route.query.contractId })
  1843. .then((res) => {
  1844. if (res && res.dataJson) {
  1845. res = { ...res, ...JSON.parse(res.dataJson) };
  1846. }
  1847. res.countryId = res.buyCountryId;
  1848. res.provinceId = res.buyProvinceId;
  1849. res.cityId = res.buyCityId;
  1850. for (var text in res) {
  1851. if (text === "contractType") {
  1852. formData.data[text] = res[text] + "";
  1853. } else {
  1854. formData.data[text] = res[text];
  1855. }
  1856. }
  1857. getCityData(formData.data.countryId, "20");
  1858. if (formData.data.provinceId) {
  1859. getCityData(formData.data.provinceId, "30");
  1860. }
  1861. if (
  1862. formData.data.contractProductList &&
  1863. formData.data.contractProductList.length > 0
  1864. ) {
  1865. let productIds = formData.data.contractProductList.map(
  1866. (item) => item.productId
  1867. );
  1868. proxy
  1869. .post("/fileInfo/getList", { businessIdList: productIds })
  1870. .then((resFile) => {
  1871. for (
  1872. let i = 0;
  1873. i < formData.data.contractProductList.length;
  1874. i++
  1875. ) {
  1876. if (
  1877. resFile[formData.data.contractProductList[i].productId] &&
  1878. resFile[formData.data.contractProductList[i].productId]
  1879. .length > 0
  1880. ) {
  1881. formData.data.contractProductList[i].fileUrl =
  1882. resFile[
  1883. formData.data.contractProductList[i].productId
  1884. ][0].fileUrl;
  1885. }
  1886. }
  1887. });
  1888. let ids = formData.data.contractProductList.map((item) => item.id);
  1889. proxy
  1890. .post("/fileInfo/getList", { businessIdList: ids })
  1891. .then((resFile) => {
  1892. for (
  1893. let i = 0;
  1894. i < formData.data.contractProductList.length;
  1895. i++
  1896. ) {
  1897. if (
  1898. resFile[formData.data.contractProductList[i].id] &&
  1899. resFile[formData.data.contractProductList[i].id].length > 0
  1900. ) {
  1901. formData.data.contractProductList[i].fileList =
  1902. resFile[formData.data.contractProductList[i].id];
  1903. }
  1904. }
  1905. });
  1906. }
  1907. });
  1908. }
  1909. });
  1910. </script>
  1911. <style lang="scss" scoped>
  1912. ::v-deep(.el-input-number .el-input__inner) {
  1913. text-align: left;
  1914. }
  1915. .pic {
  1916. object-fit: contain;
  1917. width: 50px;
  1918. height: 50px;
  1919. cursor: pointer;
  1920. vertical-align: middle;
  1921. }
  1922. .shrinkPadding {
  1923. padding-right: 0 !important;
  1924. }
  1925. .hideCollapse {
  1926. margin-top: -62px;
  1927. border: 0 !important;
  1928. }
  1929. ::v-deep(.el-collapse-item__arrow) {
  1930. display: none !important;
  1931. }
  1932. ::v-deep(.el-collapse-item__wrap) {
  1933. border: 0 !important;
  1934. }
  1935. ::v-deep(.el-collapse-item__header) {
  1936. border: 0 !important;
  1937. }
  1938. </style>