Contract.vue 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961
  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 (flag) => {
  1622. if (flag) {
  1623. return true;
  1624. } else {
  1625. let status = await submit.value.handleSubmit(() => {});
  1626. if (status) {
  1627. if (
  1628. !(
  1629. formData.data.contractProductList &&
  1630. formData.data.contractProductList.length > 0
  1631. )
  1632. ) {
  1633. ElMessage("请添加至少一件商品");
  1634. return false;
  1635. }
  1636. if (
  1637. formData.data.contractShipmentList &&
  1638. formData.data.contractShipmentList.length > 0
  1639. ) {
  1640. for (let i = 0; i < formData.data.contractProductList.length; i++) {
  1641. let data = formData.data.contractShipmentList.filter(
  1642. (item) =>
  1643. item.productId === formData.data.contractProductList[i].productId
  1644. );
  1645. if (data && data.length > 0) {
  1646. let quantity = 0;
  1647. for (let j = 0; j < data.length; j++) {
  1648. quantity = parseFloat(
  1649. Number(quantity) + Number(data[j].quantity)
  1650. );
  1651. }
  1652. if (quantity > formData.data.contractProductList[i].quantity) {
  1653. ElMessage("出货数量不能大于商品数量");
  1654. return false;
  1655. }
  1656. }
  1657. }
  1658. }
  1659. return true;
  1660. } else {
  1661. setTimeout(() => {
  1662. const errorDiv = document.getElementsByClassName("is-error");
  1663. errorDiv[0].scrollIntoView();
  1664. }, 0);
  1665. }
  1666. return false;
  1667. }
  1668. };
  1669. const getFormData = () => {
  1670. return proxy.deepClone(formData.data);
  1671. };
  1672. // 向父组件暴露
  1673. defineExpose({
  1674. getFormData,
  1675. handleSubmit,
  1676. });
  1677. const changeShroffAccount = (val) => {
  1678. if (val) {
  1679. let data = accountList.value.filter((item) => item.value === val);
  1680. console.log(formData.data.contractType);
  1681. if (data && data.length > 0) {
  1682. if(formData.data.contractType == 2){
  1683. formData.data.beneficiaryName = data[0].name;
  1684. formData.data.beneficiaryBank = data[0].openingBank;
  1685. formData.data.beneficiaryAccountNumber = data[0].accountOpening;
  1686. formData.data.beneficiaryBankAddress = '';
  1687. formData.data.swiftCode = '';
  1688. formData.data.beneficiaryAddress = '';
  1689. }else{
  1690. formData.data.beneficiaryName = data[0].beneficiaryName;
  1691. formData.data.beneficiaryBank = data[0].beneficiaryBank;
  1692. formData.data.beneficiaryBankAddress = data[0].beneficiaryBankAddress;
  1693. formData.data.beneficiaryAccountNumber = data[0].beneficiaryAccountNumber;
  1694. formData.data.swiftCode = data[0].swiftCode;
  1695. formData.data.beneficiaryAddress = data[0].beneficiaryAddress;
  1696. }
  1697. }
  1698. }
  1699. };
  1700. watch(
  1701. props.queryData,
  1702. () => {
  1703. formOption.disabled = judgeStatus();
  1704. if (
  1705. props.queryData &&
  1706. ["10", "20", "30"].includes(route.query.processType)
  1707. ) {
  1708. for (var text in props.queryData) {
  1709. formData.data[text] = props.queryData[text];
  1710. }
  1711. if (formData.data.countryId) {
  1712. getCityData(formData.data.countryId, "20");
  1713. }
  1714. if (formData.data.provinceId) {
  1715. getCityData(formData.data.provinceId, "30");
  1716. }
  1717. getDecisionAids();
  1718. }
  1719. },
  1720. {
  1721. deep: true,
  1722. }
  1723. );
  1724. const acquireSelectList = () => {
  1725. let data = [];
  1726. if (
  1727. formData.data.contractProductList &&
  1728. formData.data.contractProductList.length > 0
  1729. ) {
  1730. data = formData.data.contractProductList.map((item) => {
  1731. return {
  1732. id: item.productId,
  1733. name: item.name,
  1734. };
  1735. });
  1736. }
  1737. return data;
  1738. };
  1739. onMounted(() => {
  1740. if (!route.query.processType || route.query.processType == 30) {
  1741. proxy
  1742. .post("/customer/privateSeaPage", { pageNum: 1, pageSize: 999 })
  1743. .then((res) => {
  1744. customerList.value = res.rows.map((item) => {
  1745. return {
  1746. ...item,
  1747. label: item.name,
  1748. value: item.id,
  1749. };
  1750. });
  1751. });
  1752. } else {
  1753. proxy.post("/customer/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  1754. customerList.value = res.rows.map((item) => {
  1755. return {
  1756. ...item,
  1757. label: item.name,
  1758. value: item.id,
  1759. };
  1760. });
  1761. });
  1762. }
  1763. // 报价单生成合同
  1764. if (props.queryData.priceSheetId) {
  1765. proxy
  1766. .post("/saleQuotation/detail", { id: props.queryData.priceSheetId })
  1767. .then((res) => {
  1768. res.countryId = res.buyCountryId;
  1769. res.provinceId = res.buyProvinceId;
  1770. res.cityId = res.buyCityId;
  1771. for (var text in res) {
  1772. formData.data[text] = res[text];
  1773. }
  1774. if (
  1775. formData.data.quotationProductList &&
  1776. formData.data.quotationProductList.length > 0
  1777. ) {
  1778. formData.data.contractProductList =
  1779. formData.data.quotationProductList.map((item) => {
  1780. delete item.id;
  1781. return {
  1782. ...item,
  1783. };
  1784. });
  1785. formData.data.contractShipmentList = proxy.deepClone(
  1786. formData.data.contractProductList.map((item) => {
  1787. return {
  1788. ...item,
  1789. quantity: undefined,
  1790. };
  1791. })
  1792. );
  1793. for (let i = 0; i < formData.data.contractProductList.length; i++) {
  1794. proxy
  1795. .post("/productInfo/detail", {
  1796. id: formData.data.contractProductList[i].productId,
  1797. })
  1798. .then((resProduct) => {
  1799. let name = resProduct.name;
  1800. if (resProduct.standardJson) {
  1801. let standardJson = JSON.parse(resProduct.standardJson);
  1802. if (standardJson && standardJson.englishName) {
  1803. name = standardJson.englishName;
  1804. }
  1805. }
  1806. formData.data.contractProductList[i].name = resProduct.name;
  1807. formData.data.contractProductList[i].productName = name;
  1808. formData.data.contractProductList[i].code = resProduct.code;
  1809. formData.data.contractProductList[i].unit = resProduct.unit;
  1810. formData.data.contractShipmentList[i].code = resProduct.code;
  1811. });
  1812. }
  1813. }
  1814. delete formData.data.id;
  1815. delete formData.data.code;
  1816. getCityData(formData.data.countryId, "20");
  1817. if (formData.data.provinceId) {
  1818. getCityData(formData.data.provinceId, "30");
  1819. }
  1820. if (
  1821. formData.data.quotationPayList &&
  1822. formData.data.quotationPayList.length > 0
  1823. ) {
  1824. formData.data.contractProjectList =
  1825. formData.data.quotationPayList.map((item) => {
  1826. delete item.id;
  1827. return {
  1828. ...item,
  1829. };
  1830. });
  1831. }
  1832. });
  1833. }
  1834. if (route.query && route.query.businessId) {
  1835. proxy
  1836. .post("/contract/detail", { id: route.query.businessId })
  1837. .then((res) => {
  1838. setTimeout(() => {
  1839. formData.data.id = res.id;
  1840. for (let i = 0; i < formData.data.contractProductList.length; i++) {
  1841. formData.data.contractProductList[i].id =
  1842. res.contractProductList[i].id;
  1843. }
  1844. for (let i = 0; i < formData.data.contractProjectList.length; i++) {
  1845. formData.data.contractProjectList[i].id =
  1846. res.contractProjectList[i].id;
  1847. }
  1848. for (let i = 0; i < formData.data.contractShipmentList.length; i++) {
  1849. formData.data.contractShipmentList[i].id =
  1850. res.contractShipmentList[i].id;
  1851. }
  1852. }, 2000);
  1853. });
  1854. }
  1855. // 暂存修改
  1856. if (!route.query.processType && route.query.contractId) {
  1857. proxy
  1858. .post("/contract/detail", { id: route.query.contractId })
  1859. .then((res) => {
  1860. if (res && res.dataJson) {
  1861. res = { ...res, ...JSON.parse(res.dataJson) };
  1862. }
  1863. res.countryId = res.buyCountryId;
  1864. res.provinceId = res.buyProvinceId;
  1865. res.cityId = res.buyCityId;
  1866. for (var text in res) {
  1867. if (text === "contractType") {
  1868. formData.data[text] = res[text] + "";
  1869. } else {
  1870. formData.data[text] = res[text];
  1871. }
  1872. }
  1873. getCityData(formData.data.countryId, "20");
  1874. if (formData.data.provinceId) {
  1875. getCityData(formData.data.provinceId, "30");
  1876. }
  1877. if (
  1878. formData.data.contractProductList &&
  1879. formData.data.contractProductList.length > 0
  1880. ) {
  1881. let productIds = formData.data.contractProductList.map(
  1882. (item) => item.productId
  1883. );
  1884. proxy
  1885. .post("/fileInfo/getList", { businessIdList: productIds })
  1886. .then((resFile) => {
  1887. for (
  1888. let i = 0;
  1889. i < formData.data.contractProductList.length;
  1890. i++
  1891. ) {
  1892. if (
  1893. resFile[formData.data.contractProductList[i].productId] &&
  1894. resFile[formData.data.contractProductList[i].productId]
  1895. .length > 0
  1896. ) {
  1897. formData.data.contractProductList[i].fileUrl =
  1898. resFile[
  1899. formData.data.contractProductList[i].productId
  1900. ][0].fileUrl;
  1901. }
  1902. }
  1903. });
  1904. let ids = formData.data.contractProductList.map((item) => item.id);
  1905. proxy
  1906. .post("/fileInfo/getList", { businessIdList: ids })
  1907. .then((resFile) => {
  1908. for (
  1909. let i = 0;
  1910. i < formData.data.contractProductList.length;
  1911. i++
  1912. ) {
  1913. if (
  1914. resFile[formData.data.contractProductList[i].id] &&
  1915. resFile[formData.data.contractProductList[i].id].length > 0
  1916. ) {
  1917. formData.data.contractProductList[i].fileList =
  1918. resFile[formData.data.contractProductList[i].id];
  1919. }
  1920. }
  1921. });
  1922. }
  1923. });
  1924. }
  1925. });
  1926. </script>
  1927. <style lang="scss" scoped>
  1928. ::v-deep(.el-input-number .el-input__inner) {
  1929. text-align: left;
  1930. }
  1931. .pic {
  1932. object-fit: contain;
  1933. width: 50px;
  1934. height: 50px;
  1935. cursor: pointer;
  1936. vertical-align: middle;
  1937. }
  1938. .shrinkPadding {
  1939. padding-right: 0 !important;
  1940. }
  1941. .hideCollapse {
  1942. margin-top: -62px;
  1943. border: 0 !important;
  1944. }
  1945. ::v-deep(.el-collapse-item__arrow) {
  1946. display: none !important;
  1947. }
  1948. ::v-deep(.el-collapse-item__wrap) {
  1949. border: 0 !important;
  1950. }
  1951. ::v-deep(.el-collapse-item__header) {
  1952. border: 0 !important;
  1953. }
  1954. </style>