inventoryTable.vue 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460
  1. <template>
  2. <el-form ref="form" :model="form" :rules="rules">
  3. <ele-pro-table
  4. ref="table"
  5. :needPage="false"
  6. :columns="columns"
  7. :toolkit="[]"
  8. :datasource="form.datasource"
  9. cache-key="systemRoleTable17"
  10. class="time-form"
  11. max-height="300"
  12. >
  13. <!-- 表头工具栏 -->
  14. <template v-slot:toolbar>
  15. <div class="headbox">
  16. <div>
  17. <el-button
  18. size="small"
  19. type="primary"
  20. icon="el-icon-plus"
  21. class="ele-btn-icon"
  22. @click="handParent('', -1)"
  23. v-if="!isContractId"
  24. >
  25. 新增
  26. </el-button>
  27. <el-button
  28. size="small"
  29. type="primary"
  30. icon="el-icon-plus"
  31. class="ele-btn-icon"
  32. v-if="!isContractId && isTemporary"
  33. @click="handlAdd"
  34. >
  35. 新增临时产品
  36. </el-button>
  37. <el-button
  38. size="small"
  39. type="primary"
  40. class="ele-btn-icon"
  41. @click="save"
  42. v-if="!isContractId && isDrawer"
  43. >
  44. 保存
  45. </el-button>
  46. </div>
  47. <div class="pricebox">
  48. <span class="amount">总计:{{ allPrice }}元</span>
  49. <el-form-item
  50. style="width: 300px"
  51. v-if="isDiscountTotalPrice"
  52. label="优惠后总金额:"
  53. prop="discountTotalPrice"
  54. :rules="{
  55. required: true,
  56. message: '请输入优惠后总金额',
  57. trigger: 'change'
  58. }"
  59. >
  60. <el-input
  61. type="number"
  62. :min="0"
  63. :max="allPrice"
  64. :disabled="!allPrice"
  65. v-model="form.discountTotalPrice"
  66. style="width: 180px"
  67. placeholder="请输入"
  68. @input="discountInputByOrder(form.discountTotalPrice)"
  69. >
  70. <template slot="append">元</template>
  71. </el-input>
  72. </el-form-item>
  73. </div>
  74. </div>
  75. </template>
  76. <template v-slot:productName="{ row, $index }">
  77. <el-form-item
  78. style="margin-bottom: 20px"
  79. :prop="'datasource.' + $index + '.productName'"
  80. :rules="{
  81. required: true,
  82. message: '请输入',
  83. trigger: 'change'
  84. }"
  85. >
  86. <el-input
  87. :disabled="isContractId || !!row.productCode"
  88. v-model="row.productName"
  89. placeholder="请输入"
  90. style="width: 60%; margin-right: 10px"
  91. ></el-input>
  92. <el-button
  93. v-if="!isContractId"
  94. size="small"
  95. type="primary"
  96. @click.native="handParent(row, $index)"
  97. >选择
  98. </el-button>
  99. </el-form-item>
  100. </template>
  101. <template v-slot:entrustedEnterpriseId="scope">
  102. <el-form-item prop="entrustedEnterpriseId">
  103. <el-select
  104. v-model="scope.row['entrustedEnterpriseId']"
  105. clearable
  106. filterable
  107. >
  108. <el-option
  109. v-for="i in scope.row.entrustedEnterpriseIdList"
  110. :key="i.id"
  111. :value="i.id"
  112. :label="i.name"
  113. ></el-option>
  114. </el-select>
  115. </el-form-item>
  116. </template>
  117. <template v-slot:headerCustomerMark="{ column }">
  118. <span :class="isCustomerMark ? 'is-required' : ''">{{
  119. column.label
  120. }}</span>
  121. </template>
  122. <template v-slot:customerMark="{ row, $index }">
  123. <el-form-item
  124. :prop="'datasource.' + $index + '.customerMark'"
  125. :rules="{
  126. required: isCustomerMark ? true : false,
  127. message: '请输入',
  128. trigger: 'change'
  129. }"
  130. >
  131. <el-input v-model="row.customerMark" placeholder="请输入"></el-input>
  132. </el-form-item>
  133. </template>
  134. <!-- <template v-slot:headerSupplierMark="{ column }">
  135. <span :class="isSupplierMark ? 'is-required' : ''">{{
  136. column.label
  137. }}</span>
  138. </template>
  139. <template v-slot:supplierMark="{ row, $index }">
  140. <el-form-item
  141. :prop="'datasource.' + $index + '.supplierMark'"
  142. :rules="{
  143. required: isSupplierMark ? true : false,
  144. message: '请输入',
  145. trigger: 'change'
  146. }"
  147. >
  148. <el-input v-model="row.supplierMark" placeholder="请输入"></el-input>
  149. </el-form-item>
  150. </template> -->
  151. <template v-slot:headerProductName="{ column }">
  152. <span class="is-required">{{ column.label }}</span>
  153. </template>
  154. <template v-slot:productCode="scope">
  155. <el-form-item
  156. style="margin-bottom: 20px"
  157. :prop="'datasource.' + scope.$index + '.productCode'"
  158. >
  159. <el-input v-model="scope.row.productCode" :disabled="true"></el-input>
  160. </el-form-item>
  161. </template>
  162. <template v-slot:productCategoryName="scope">
  163. <el-form-item
  164. style="margin-bottom: 20px"
  165. :prop="'datasource.' + scope.$index + '.productCategoryName'"
  166. >
  167. <el-input v-model="scope.row.productCategoryName" disabled></el-input>
  168. </el-form-item>
  169. </template>
  170. <template v-slot:totalCount="scope">
  171. <el-form-item
  172. style="margin-bottom: 20px"
  173. :prop="'datasource.' + scope.$index + '.totalCount'"
  174. :rules="{
  175. required: isTotalCount ? true : false,
  176. message: '请输入单价',
  177. trigger: 'change'
  178. }"
  179. >
  180. <el-input
  181. :disabled="isContractId"
  182. v-model="scope.row.totalCount"
  183. type="number"
  184. placeholder="请输入"
  185. @input="changeCount(scope.row, scope.$index)"
  186. ></el-input>
  187. </el-form-item>
  188. </template>
  189. <template v-slot:headerTotalCount="{ column }">
  190. <span :class="{ 'is-required': isTotalCount }">{{ column.label }}</span>
  191. </template>
  192. <template v-slot:totalPrice="scope">
  193. <el-form-item
  194. style="margin-bottom: 20px"
  195. :prop="'datasource.' + scope.$index + '.totalPrice'"
  196. >
  197. {{ (Number(scope.row.totalPrice) || 0).toFixed(2) }}元
  198. </el-form-item>
  199. </template>
  200. <template v-slot:productBrand="scope">
  201. <el-form-item
  202. style="margin-bottom: 20px"
  203. :prop="'datasource.' + scope.$index + '.productBrand'"
  204. >
  205. <el-input
  206. v-model="scope.row.productBrand"
  207. :disabled="!!scope.row.productCode"
  208. ></el-input>
  209. </el-form-item>
  210. </template>
  211. <template v-slot:modelType="scope">
  212. <el-form-item
  213. style="margin-bottom: 20px"
  214. :prop="'datasource.' + scope.$index + '.modelType'"
  215. >
  216. <el-input
  217. v-model="scope.row.modelType"
  218. :disabled="!!scope.row.productCode"
  219. ></el-input>
  220. </el-form-item>
  221. </template>
  222. <template v-slot:specification="scope">
  223. <el-form-item
  224. style="margin-bottom: 20px"
  225. :prop="'datasource.' + scope.$index + '.specification'"
  226. >
  227. <el-input
  228. v-model="scope.row.specification"
  229. :disabled="!!scope.row.productCode"
  230. ></el-input>
  231. </el-form-item>
  232. </template>
  233. <template v-slot:headerGuaranteePeriod="{ column }">
  234. <span :class="{ 'is-required': contractBookType == 1 }">{{
  235. column.label
  236. }}</span>
  237. </template>
  238. <template v-slot:guaranteePeriod="scope">
  239. <div class="period">
  240. <div class="borderleftnone">
  241. <el-form-item
  242. style="margin-bottom: 20px"
  243. :prop="'datasource.' + scope.$index + '.guaranteePeriod'"
  244. :rules="{
  245. pattern: numberReg,
  246. message: '请输入质保期',
  247. trigger: 'blur'
  248. }"
  249. >
  250. <el-input
  251. :disabled="isContractId"
  252. v-model="scope.row.guaranteePeriod"
  253. @change="
  254. setDeliveryDays(scope.row, scope.$index, 'guaranteePeriod')
  255. "
  256. placeholder="请输入"
  257. ></el-input>
  258. </el-form-item>
  259. </div>
  260. <div class="borderrightnone">
  261. <DictSelection
  262. dictName="质保期单位"
  263. clearable
  264. v-model="scope.row.guaranteePeriodUnitCode"
  265. :disabled="isContractId"
  266. @change="
  267. setDeliveryDays(scope.row, scope.$index, 'guaranteePeriod')
  268. "
  269. >
  270. </DictSelection>
  271. </div>
  272. </div>
  273. </template>
  274. <template v-slot:measuringUnit="scope">
  275. <el-form-item
  276. style="margin-bottom: 20px"
  277. :prop="'datasource.' + scope.$index + '.measuringUnit'"
  278. >
  279. <el-input
  280. v-model="scope.row.measuringUnit"
  281. :disabled="!!scope.row.productCode"
  282. placeholder="请输入"
  283. ></el-input>
  284. </el-form-item>
  285. </template>
  286. <template v-slot:remark="scope">
  287. <el-form-item
  288. style="margin-bottom: 20px"
  289. :prop="'datasource.' + scope.$index + '.remark'"
  290. >
  291. <el-input
  292. :disabled="isContractId"
  293. v-model="scope.row.remark"
  294. type="textarea"
  295. placeholder="请输入"
  296. ></el-input>
  297. </el-form-item>
  298. </template>
  299. <template v-slot:singlePrice="scope">
  300. <el-form-item
  301. style="margin-bottom: 20px"
  302. :prop="'datasource.' + scope.$index + '.singlePrice'"
  303. :rules="{
  304. required: isSinglePrice ? true : false,
  305. message: '请输入单价',
  306. trigger: 'change'
  307. }"
  308. >
  309. <el-input
  310. :disabled="isContractId"
  311. v-model="scope.row.singlePrice"
  312. placeholder="请输入"
  313. type="number"
  314. @input="changeCount(scope.row, scope.$index)"
  315. >
  316. <template slot="append">元</template>
  317. </el-input>
  318. </el-form-item>
  319. </template>
  320. <template v-slot:taxRate="scope">
  321. <el-form-item
  322. style="margin-bottom: 20px"
  323. :prop="'datasource.' + scope.$index + '.taxRate'"
  324. >
  325. <el-input
  326. :disabled="isContractId"
  327. v-model="scope.row.taxRate"
  328. placeholder="请输入"
  329. type="number"
  330. >
  331. <template slot="append">%</template>
  332. </el-input>
  333. </el-form-item>
  334. </template>
  335. <template v-slot:headerSinglePrice="{ column }">
  336. <span :class="isSinglePrice ? 'is-required' : ''">{{
  337. column.label
  338. }}</span>
  339. </template>
  340. <template v-slot:headerCustomerExpectDeliveryDeadline="{ column }">
  341. <span class="is-required">{{ column.label }}</span>
  342. </template>
  343. <template v-slot:technicalAnswerName="{ row, $index }">
  344. <el-form-item
  345. style="margin-bottom: 20px"
  346. :prop="'datasource.' + $index + '.technicalAnswerName'"
  347. >
  348. <el-input
  349. v-model="row.technicalAnswerName"
  350. placeholder="请输入"
  351. :disabled="isContractId"
  352. @click.native="handHead(row, $index)"
  353. ></el-input>
  354. </el-form-item>
  355. </template>
  356. <template v-slot:technicalParams="scope">
  357. <el-form-item
  358. style="margin-bottom: 20px"
  359. :prop="'datasource.' + scope.$index + '.technicalParams'"
  360. >
  361. <el-input
  362. type="textarea"
  363. v-model="scope.row.technicalParams"
  364. :disabled="isContractId"
  365. placeholder="请输入"
  366. ></el-input>
  367. </el-form-item>
  368. </template>
  369. <template v-slot:technicalDrawings="scope">
  370. <el-form-item
  371. style="margin-bottom: 20px"
  372. :prop="'datasource.' + scope.$index + '.technicalDrawings'"
  373. >
  374. <fileMain
  375. v-model="scope.row.technicalDrawings"
  376. :type="isContractId ? 'view' : ''"
  377. ></fileMain>
  378. </el-form-item>
  379. </template>
  380. <template v-slot:customerReqFiles="scope">
  381. <el-form-item
  382. style="margin-bottom: 20px"
  383. :prop="'datasource.' + scope.$index + '.customerReqFiles'"
  384. >
  385. <fileMain
  386. v-model="scope.row.customerReqFiles"
  387. :type="isContractId ? 'view' : ''"
  388. ></fileMain>
  389. </el-form-item>
  390. </template>
  391. <template v-slot:industryArtFiles="scope">
  392. <el-form-item
  393. style="margin-bottom: 20px"
  394. :prop="'datasource.' + scope.$index + '.industryArtFiles'"
  395. :rules="{
  396. required: false,
  397. message: '请输入',
  398. trigger: 'change'
  399. }"
  400. >
  401. <fileMain
  402. v-model="scope.row.industryArtFiles"
  403. :type="isContractId ? 'view' : ''"
  404. ></fileMain>
  405. </el-form-item>
  406. </template>
  407. <template v-slot:otherFiles="scope">
  408. <el-form-item
  409. style="margin-bottom: 20px"
  410. :prop="'datasource.' + scope.$index + '. otherFiles'"
  411. >
  412. <fileMain
  413. v-model="scope.row.otherFiles"
  414. :type="isContractId ? 'view' : ''"
  415. ></fileMain>
  416. </el-form-item>
  417. </template>
  418. <template v-slot:headerProduceDeliveryDeadline="{ column }">
  419. <span :class="isProduceDeliveryDeadline ? 'is-required' : ''">{{
  420. column.label
  421. }}</span>
  422. </template>
  423. <template v-slot:produceDeliveryDeadline="scope">
  424. <el-form-item
  425. :prop="'datasource.' + scope.$index + '.produceDeliveryDeadline'"
  426. :rules="{
  427. required: isProduceDeliveryDeadline ? true : false,
  428. message: '选择生产交付交期',
  429. trigger: 'change'
  430. }"
  431. >
  432. <el-date-picker
  433. style="width: 140px"
  434. v-model="scope.row.produceDeliveryDeadline"
  435. @change="
  436. setDeliveryDays(scope.row, scope.$index, 'guaranteePeriod')
  437. "
  438. type="date"
  439. placeholder="选择日期"
  440. >
  441. </el-date-picker>
  442. </el-form-item>
  443. </template>
  444. <template v-slot:customerExpectDeliveryDeadline="scope">
  445. <el-form-item
  446. :rules="{
  447. required: true,
  448. message:
  449. contractBookType == 1 ? '请选择客户期望交期' : '请选择交付日期',
  450. trigger: 'change'
  451. }"
  452. :prop="
  453. 'datasource.' + scope.$index + '.customerExpectDeliveryDeadline'
  454. "
  455. >
  456. <el-date-picker
  457. style="width: 140px"
  458. :disabled="isContractId"
  459. v-model="scope.row.customerExpectDeliveryDeadline"
  460. @change="
  461. setDeliveryDays(scope.row, scope.$index, 'guaranteePeriod')
  462. "
  463. type="date"
  464. placeholder="选择日期"
  465. >
  466. </el-date-picker>
  467. </el-form-item>
  468. </template>
  469. <template v-slot:provenance="scope">
  470. <el-form-item :prop="'datasource.' + scope.$index + '.provenance'">
  471. <DictSelection
  472. dictName="产地"
  473. clearable
  474. :disabled="status == 'Detail'"
  475. v-model="scope.row.provenance"
  476. multiple
  477. >
  478. </DictSelection>
  479. </el-form-item>
  480. </template>
  481. <template v-slot:guaranteePeriodDeadline="scope">
  482. <el-form-item
  483. :prop="'datasource.' + scope.$index + '.guaranteePeriodDeadline'"
  484. >
  485. <el-date-picker
  486. style="width: 140px"
  487. :disabled="isContractId"
  488. v-model="scope.row.guaranteePeriodDeadline"
  489. type="date"
  490. placeholder="选择日期"
  491. >
  492. </el-date-picker>
  493. </el-form-item>
  494. </template>
  495. <template v-slot:singleWeight="scope">
  496. <el-form-item
  497. style="margin-bottom: 20px"
  498. :prop="'datasource.' + scope.$index + '.singleWeight'"
  499. >
  500. <el-input
  501. :disabled="isContractId"
  502. v-model="scope.row.singleWeight"
  503. @input="changeCount(scope.row, scope.$index)"
  504. placeholder="请输入"
  505. ></el-input>
  506. </el-form-item>
  507. </template>
  508. <template v-slot:technologyRouteName="scope">
  509. <el-form-item
  510. :prop="'datasource.' + scope.$index + '.technologyRouteName'"
  511. :rules="{
  512. required: false,
  513. message: '请选择',
  514. trigger: 'change'
  515. }"
  516. >
  517. <el-input
  518. v-model="scope.row.technologyRouteName"
  519. :disabled="isContractId"
  520. placeholder="请选择"
  521. @click.native="openVersion(scope.$index)"
  522. ></el-input>
  523. </el-form-item>
  524. </template>
  525. <template v-slot:pricingWay="scope">
  526. <el-form-item :prop="'datasource.' + scope.$index + '.pricingWay'">
  527. <el-select
  528. v-model="scope.row.pricingWay"
  529. placeholder="请选择"
  530. :rules="{
  531. required: true,
  532. message: '请选择计价方式',
  533. trigger: 'change'
  534. }"
  535. >
  536. <el-option
  537. v-for="item in pricingWayList"
  538. :key="item.id"
  539. :label="item.name"
  540. :value="item.id"
  541. @click.native="changeCount(scope.row, scope.$index)"
  542. >
  543. </el-option>
  544. </el-select>
  545. </el-form-item>
  546. </template>
  547. <template v-slot:headerPricingWay="{ column }">
  548. <span class="is-required">{{ column.label }}</span>
  549. </template>
  550. <!-- 操作列 -->
  551. <template v-slot:action="scope">
  552. <el-popconfirm
  553. v-if="!isContractId"
  554. class="ele-action"
  555. title="确定要删除吗?"
  556. @confirm="remove(scope.$index)"
  557. >
  558. <template v-slot:reference>
  559. <el-link type="danger" :underline="false" icon="el-icon-delete">
  560. 删除
  561. </el-link>
  562. </template>
  563. </el-popconfirm>
  564. </template>
  565. </ele-pro-table>
  566. <product-list
  567. ref="productListRef"
  568. classType="1"
  569. :is-get-inventory-total="true"
  570. @changeParent="changeParent"
  571. ></product-list>
  572. <head-list ref="headRef" @changeParent="changeAnswer"></head-list>
  573. <ProductionVersion
  574. ref="versionRefs"
  575. @changeProduct="changeProduct"
  576. ></ProductionVersion>
  577. </el-form>
  578. </template>
  579. <script>
  580. import { numberReg } from 'ele-admin';
  581. import productList from '@/BIZComponents/product-list.vue';
  582. import dictMixins from '@/mixins/dictMixins';
  583. import fileUpload from '@/components/upload/fileUpload';
  584. import headList from '@/BIZComponents/user-select/user-select.vue';
  585. import ProductionVersion from '@/components/ProductionVersion2/index.vue';
  586. import { getFile } from '@/api/system/file';
  587. import { getInventoryTotalAPI } from '@/api/wms';
  588. import { getByCode } from '@/api/system/dictionary-data';
  589. import fileMain from '@/components/addDoc/index.vue';
  590. import { pricingWayList } from '@/enum/dict.js';
  591. import { changeCount } from '@/BIZComponents/setProduct.js';
  592. import { contactQueryByCategoryIdsAPI } from '@/api/saleManage/contact';
  593. const dayjs = require('dayjs');
  594. export default {
  595. mixins: [dictMixins],
  596. components: {
  597. fileMain,
  598. productList,
  599. fileUpload,
  600. headList,
  601. ProductionVersion
  602. },
  603. props: {
  604. pageName: {
  605. default: '',
  606. type: String
  607. },
  608. isDiscountTotalPrice: {
  609. default: false,
  610. type: Boolean
  611. },
  612. isGuaranteePeriod: {
  613. default: true,
  614. type: Boolean
  615. },
  616. customerMark: {
  617. default: '',
  618. type: String
  619. },
  620. isContractId: {
  621. type: Boolean,
  622. default: false
  623. },
  624. isSinglePrice: {
  625. //单价必填
  626. type: Boolean,
  627. default: true
  628. },
  629. isTotalCount: {
  630. //数量必填
  631. type: Boolean,
  632. default: true
  633. },
  634. isCustomerMark: {
  635. //客户代号必填
  636. type: Boolean,
  637. default: false
  638. },
  639. isDiscount: {
  640. //折让
  641. type: Boolean,
  642. default: true
  643. },
  644. isProduceDeliveryDeadline: {
  645. //生产交付交期必填
  646. type: Boolean,
  647. default: false
  648. },
  649. isDrawer: {
  650. type: Boolean,
  651. default: false
  652. },
  653. isChangeCount: {
  654. //默认计算
  655. type: Boolean,
  656. default: true
  657. },
  658. contractBookType: {
  659. //合同类型 1销售 2采购
  660. type: [String, Number],
  661. default: 1
  662. },
  663. // isSupplierMark: {
  664. // //客户代号必填
  665. // type: Boolean,
  666. // default: false
  667. // },
  668. isTemporary: {
  669. //临时
  670. type: Boolean,
  671. default: false
  672. }
  673. },
  674. data() {
  675. const defaultForm = {
  676. key: null,
  677. endTime: '',
  678. isFirst: 0,
  679. name: '',
  680. startTime: '',
  681. workHour: '',
  682. guaranteePeriodUnitCode: '',
  683. technicalDrawings: []
  684. };
  685. return {
  686. allPrice: 0,
  687. numberReg,
  688. defaultForm,
  689. form: {
  690. datasource: [],
  691. discountTotalPrice: 0
  692. },
  693. pricingWayList,
  694. rules: {},
  695. dictList: {}
  696. };
  697. },
  698. computed: {
  699. canHandl() {
  700. return this.form.datasource.length;
  701. },
  702. columns() {
  703. console.log(this.contractBookType, 'this.contractBookType');
  704. return [
  705. {
  706. width: 45,
  707. type: 'index',
  708. columnKey: 'index',
  709. align: 'center',
  710. fixed: 'left'
  711. },
  712. {
  713. width: 280,
  714. prop: 'productName',
  715. label: '名称',
  716. slot: 'productName',
  717. headerSlot: 'headerProductName',
  718. align: 'center',
  719. fixed: 'left'
  720. },
  721. {
  722. width: 120,
  723. prop: 'productCode',
  724. label: '编码',
  725. slot: 'productCode',
  726. align: 'center'
  727. },
  728. {
  729. width: 200,
  730. prop: 'productCategoryName',
  731. label: '类型',
  732. slot: 'productCategoryName',
  733. align: 'center'
  734. },
  735. {
  736. width: 120,
  737. prop: 'specification',
  738. label: '规格',
  739. slot: 'specification',
  740. align: 'center'
  741. },
  742. {
  743. width: 200,
  744. prop: 'customerMark',
  745. label: this.contractBookType == 1 ? '客户代号' : '供应商代号',
  746. slot: 'customerMark',
  747. headerSlot: 'headerCustomerMark',
  748. align: 'center'
  749. },
  750. // {
  751. // width: 200,
  752. // prop: 'supplierMark',
  753. // label: '供应商代号',
  754. // slot: 'supplierMark',
  755. // headerSlot: 'headerSupplierMark',
  756. // align: 'center',
  757. // show: this.contractBookType == 2
  758. // },
  759. {
  760. minWidth: 120,
  761. prop: 'entrustedEnterpriseId',
  762. label: '受托企业',
  763. slot: 'entrustedEnterpriseId',
  764. show: this.isCustomerMark,
  765. align: 'center'
  766. },
  767. {
  768. width: 150,
  769. prop: 'totalCount',
  770. label: '数量',
  771. slot: 'totalCount',
  772. headerSlot: 'headerTotalCount',
  773. align: 'center'
  774. },
  775. {
  776. width: 160,
  777. prop: 'pricingWay',
  778. label: '计价方式',
  779. headerSlot: 'headerPricingWay',
  780. slot: 'pricingWay',
  781. align: 'center'
  782. },
  783. {
  784. width: 200,
  785. prop: 'singlePrice',
  786. label: '单价',
  787. slot: 'singlePrice',
  788. headerSlot: 'headerSinglePrice',
  789. align: 'center'
  790. },
  791. {
  792. width: 160,
  793. prop: 'taxRate',
  794. label: '税率',
  795. slot: 'taxRate',
  796. align: 'center'
  797. },
  798. {
  799. width: 160,
  800. prop: 'discountSinglePrice',
  801. label: '折让单价',
  802. align: 'center',
  803. show: this.isDiscount,
  804. formatter: (_row, _column, cellValue) => {
  805. return _row.discountSinglePrice
  806. ? Number(_row.discountSinglePrice).toFixed(2)
  807. : '';
  808. }
  809. },
  810. {
  811. width: 120,
  812. prop: 'totalPrice',
  813. label: '合计',
  814. slot: 'totalPrice',
  815. align: 'center'
  816. },
  817. {
  818. width: 160,
  819. prop: 'discountTotalPrice',
  820. label: '折让合计',
  821. align: 'center',
  822. show: this.isDiscount,
  823. formatter: (_row, _column, cellValue) => {
  824. return _row.discountTotalPrice
  825. ? Number(_row.discountTotalPrice).toFixed(2)
  826. : '';
  827. }
  828. },
  829. {
  830. width: 120,
  831. prop: 'availableCountBase',
  832. label: '库存数量',
  833. slot: 'availableCountBase',
  834. align: 'center'
  835. },
  836. {
  837. prop: 'provenance',
  838. label: '产地',
  839. slot: 'provenance',
  840. align: 'center',
  841. showOverflowTooltip: true,
  842. minWidth: 200
  843. // show:this.contractBookType==2
  844. },
  845. {
  846. width: 120,
  847. prop: 'measuringUnit',
  848. label: '计量单位',
  849. slot: 'measuringUnit',
  850. align: 'center'
  851. },
  852. {
  853. width: 120,
  854. prop: 'singleWeight',
  855. label: '单重',
  856. slot: 'singleWeight',
  857. headerSlot: 'headerSingleWeight',
  858. align: 'center'
  859. },
  860. {
  861. width: 120,
  862. prop: 'totalWeight',
  863. label: '总重',
  864. slot: 'totalWeight',
  865. align: 'center'
  866. },
  867. {
  868. width: 120,
  869. prop: 'weightUnit',
  870. label: '重量单位',
  871. slot: 'weightUnit',
  872. align: 'center'
  873. },
  874. {
  875. width: 160,
  876. prop: 'productBrand',
  877. label: '牌号',
  878. slot: 'productBrand',
  879. align: 'center'
  880. },
  881. {
  882. width: 120,
  883. prop: 'modelType',
  884. label: '型号',
  885. slot: 'modelType',
  886. align: 'center'
  887. },
  888. {
  889. width: 120,
  890. prop: 'produceType',
  891. align: 'center',
  892. label: '属性类型',
  893. showOverflowTooltip: true,
  894. formatter: (row, column) => {
  895. return row?.produceType
  896. ?.map((item) => {
  897. return this.getDictValue('生产类型', item);
  898. })
  899. ?.toString();
  900. }
  901. },
  902. {
  903. width: 120,
  904. prop: 'packingSpecification',
  905. align: 'center',
  906. label: '包装规格',
  907. showOverflowTooltip: true
  908. },
  909. {
  910. width: 160,
  911. prop: 'customerExpectDeliveryDeadline',
  912. label: this.contractBookType == 1 ? '客户期望交期' : '交付日期',
  913. slot: 'customerExpectDeliveryDeadline',
  914. headerSlot: 'headerCustomerExpectDeliveryDeadline',
  915. align: 'center'
  916. },
  917. {
  918. width: 160,
  919. prop: 'produceDeliveryDeadline',
  920. label: '生产交付交期',
  921. slot: 'produceDeliveryDeadline',
  922. headerSlot: 'headerProduceDeliveryDeadline',
  923. show: this.contractBookType == 1,
  924. align: 'center'
  925. },
  926. {
  927. width: 200,
  928. prop: 'guaranteePeriod',
  929. label: '质保期',
  930. slot: 'guaranteePeriod',
  931. // headerSlot: 'headerGuaranteePeriod',
  932. align: 'center'
  933. },
  934. {
  935. width: 200,
  936. prop: 'guaranteePeriodDeadline',
  937. label: '质保期截止日期',
  938. slot: 'guaranteePeriodDeadline',
  939. show: this.isGuaranteePeriod,
  940. align: 'center'
  941. },
  942. {
  943. width: 120,
  944. prop: 'imgCode',
  945. align: 'center',
  946. label: '图号/件号',
  947. showOverflowTooltip: true
  948. },
  949. // {
  950. // width: 120,
  951. // prop: 'approvalNumber',
  952. // align: 'center',
  953. // label: '批准文号',
  954. // showOverflowTooltip: true
  955. // },
  956. {
  957. width: 220,
  958. prop: 'customerReqFiles',
  959. label: '客户需求',
  960. slot: 'customerReqFiles',
  961. align: 'center'
  962. },
  963. {
  964. width: 130,
  965. prop: 'technicalAnswerName',
  966. label: '技术答疑人',
  967. slot: 'technicalAnswerName',
  968. align: 'center'
  969. },
  970. {
  971. width: 220,
  972. prop: 'technicalParams',
  973. label: '技术参数',
  974. slot: 'technicalParams',
  975. align: 'center'
  976. },
  977. {
  978. width: 240,
  979. prop: 'technicalDrawings',
  980. label: '技术图纸',
  981. slot: 'technicalDrawings',
  982. align: 'center'
  983. },
  984. {
  985. width: 240,
  986. prop: 'technologyRouteName',
  987. label: '工艺路线',
  988. slot: 'technologyRouteName',
  989. align: 'center'
  990. },
  991. {
  992. width: 240,
  993. prop: 'industryArtFiles',
  994. label: '工艺附件',
  995. slot: 'industryArtFiles',
  996. align: 'center'
  997. },
  998. {
  999. width: 240,
  1000. prop: 'otherFiles',
  1001. label: '其他附件',
  1002. slot: 'otherFiles',
  1003. align: 'center'
  1004. },
  1005. {
  1006. width: 220,
  1007. prop: 'remark',
  1008. label: '备注',
  1009. slot: 'remark',
  1010. align: 'center'
  1011. },
  1012. {
  1013. columnKey: 'action',
  1014. label: '操作',
  1015. width: 120,
  1016. align: 'center',
  1017. resizable: false,
  1018. slot: 'action',
  1019. fixed: 'right',
  1020. showOverflowTooltip: true
  1021. }
  1022. ];
  1023. }
  1024. },
  1025. created() {
  1026. this.requestDict('生产类型');
  1027. this.requestDict('保质期单位');
  1028. },
  1029. methods: {
  1030. openVersion(index) {
  1031. this.$refs.versionRefs.open(index);
  1032. },
  1033. //工艺路线
  1034. changeProduct(data, index) {
  1035. this.$set(
  1036. this.form.datasource[index],
  1037. 'technologyRouteName',
  1038. data.name
  1039. );
  1040. this.$set(this.form.datasource[index], 'technologyRouteId', data.id);
  1041. },
  1042. async getSupplierObj(productList, queryName) {
  1043. try {
  1044. let categoryIds = productList
  1045. .filter((item) => item.productId)
  1046. .map((item) => item.productId);
  1047. if (categoryIds.length > 0) {
  1048. return await contactQueryByCategoryIdsAPI({
  1049. categoryIds,
  1050. isQueryEE: 1
  1051. });
  1052. } else {
  1053. return Promise.resolve({});
  1054. }
  1055. } catch (e) {
  1056. return Promise.resolve({});
  1057. }
  1058. },
  1059. setDeliveryDays(row, index, type, isAll) {
  1060. if (isAll) {
  1061. this.form.datasource.forEach((item, i) => {
  1062. let guaranteePeriodUnitName = this.guaranteePeriodUnit(
  1063. item.guaranteePeriodUnitCode
  1064. );
  1065. this.$set(
  1066. this.form.datasource[i],
  1067. 'guaranteePeriodDeadline',
  1068. guaranteePeriodUnitName != 'second'
  1069. ? this.setDay(
  1070. item.guaranteePeriod,
  1071. guaranteePeriodUnitName,
  1072. item
  1073. )
  1074. : ''
  1075. );
  1076. // }
  1077. });
  1078. return;
  1079. }
  1080. if (type == 'guaranteePeriod') {
  1081. let guaranteePeriodUnitName = this.guaranteePeriodUnit(
  1082. row.guaranteePeriodUnitCode
  1083. );
  1084. this.$set(
  1085. this.form.datasource[index],
  1086. 'guaranteePeriodDeadline',
  1087. guaranteePeriodUnitName != 'second'
  1088. ? this.setDay(row.guaranteePeriod, guaranteePeriodUnitName, row)
  1089. : ''
  1090. );
  1091. }
  1092. },
  1093. guaranteePeriodUnit(code) {
  1094. return code == 3
  1095. ? 'day'
  1096. : code == 4
  1097. ? 'month'
  1098. : code == 5
  1099. ? 'year'
  1100. : 'second';
  1101. },
  1102. setDay(addDay, dateType = 'day', item) {
  1103. let tiem =
  1104. this.contractBookType == 1
  1105. ? item.produceDeliveryDeadline
  1106. : item.customerExpectDeliveryDeadline;
  1107. return dayjs(tiem || new Date())
  1108. .add(addDay, dateType)
  1109. .format('YYYY-MM-DD');
  1110. },
  1111. // 返回列表数据
  1112. getTableValue() {
  1113. let comitDatasource = this.form.datasource;
  1114. if (comitDatasource.length === 0) return [];
  1115. comitDatasource.forEach((v) => {
  1116. if (v.guaranteePeriodUnitCode) {
  1117. v.guaranteePeriodUnitName = this.getDictValue(
  1118. '保质期单位',
  1119. v.guaranteePeriodUnitCode
  1120. );
  1121. }
  1122. v.technicalDrawings = v.technicalDrawings ? v.technicalDrawings : [];
  1123. v.customerReqFiles = v.customerReqFiles || [];
  1124. v.industryArtFiles = v.industryArtFiles || [];
  1125. v.otherFiles = v.otherFiles || [];
  1126. });
  1127. return comitDatasource;
  1128. },
  1129. getPrice() {
  1130. return [this.allPrice, this.form.discountTotalPrice];
  1131. },
  1132. //改变数量
  1133. changeCount(row, index) {
  1134. const { allPrice, arr } = changeCount(row, index, this.form.datasource);
  1135. this.form.datasource = arr;
  1136. this.allPrice = allPrice || 0;
  1137. if (this.isDiscountTotalPrice) {
  1138. this.form.discountTotalPrice = allPrice;
  1139. this.$emit('setDiscountTotalPrice', allPrice);
  1140. }
  1141. this.$emit('setCountAmount', this.allPrice);
  1142. },
  1143. setCustomerMark(customerMark) {
  1144. this.form.datasource.forEach((item) => {
  1145. item['customerMark'] = customerMark;
  1146. this.$forceUpdate();
  1147. });
  1148. },
  1149. //设置优惠后总金额修改产品单价
  1150. discountInputByOrder(val) {
  1151. this.form.discountTotalPrice = val;
  1152. // //获取优惠金额和总计的差价
  1153. this.form.datasource.forEach((item, index) => {
  1154. //获取折让单价
  1155. this.$set(
  1156. this.form.datasource[index],
  1157. 'discountSinglePrice',
  1158. this.getDiscountSinglePrice(item)
  1159. );
  1160. this.$set(
  1161. this.form.datasource[index],
  1162. 'discountTotalPrice',
  1163. this.getDiscountTotalPrice(item)
  1164. );
  1165. });
  1166. this.$emit('setDiscountTotalPrice', val);
  1167. this.$forceUpdate();
  1168. this.$refs.table.reRenderTable();
  1169. },
  1170. //获取折让单价
  1171. getDiscountSinglePrice(row) {
  1172. let num =
  1173. (Number(this.form.discountTotalPrice) / Number(this.allPrice)) *
  1174. Number(row.singlePrice);
  1175. console.log(num, 'num');
  1176. return isNaN(num) ? '' : num;
  1177. },
  1178. //获取折让合计
  1179. getDiscountTotalPrice(row) {
  1180. let num = 0;
  1181. if (row.pricingWay == 1) {
  1182. num = Number(row.discountSinglePrice) * Number(row.totalCount);
  1183. }
  1184. if (row.pricingWay == 2) {
  1185. num =
  1186. Number(row.discountSinglePrice) *
  1187. Number(row.totalCount) *
  1188. Number(row.singleWeight);
  1189. }
  1190. return isNaN(num) ? '' : num.toFixed(2);
  1191. },
  1192. //修改回显
  1193. async putTableValue(data) {
  1194. let productList =
  1195. (data &&
  1196. (data.quoteProductList || data.productList || data.detailList)) ||
  1197. [];
  1198. if (productList) {
  1199. let supplierObj = await this.getSupplierObj(productList, 'productId');
  1200. productList.forEach((item) => {
  1201. item.pricingWay =
  1202. item.pricingWay ||
  1203. data.pricingWay ||
  1204. data?.contractVO?.pricingWay;
  1205. item.guaranteePeriodUnitCode = item.guaranteePeriodUnitCode
  1206. ? item.guaranteePeriodUnitCode + ''
  1207. : '';
  1208. let guaranteePeriodUnitName = this.guaranteePeriodUnit(
  1209. item.guaranteePeriodUnitCode
  1210. );
  1211. if (item.guaranteePeriod && item.guaranteePeriodUnitCode) {
  1212. item['guaranteePeriodDeadline'] =
  1213. item['guaranteePeriodDeadline'] ||
  1214. guaranteePeriodUnitName != 'second'
  1215. ? this.setDay(
  1216. item.guaranteePeriod,
  1217. guaranteePeriodUnitName,
  1218. item
  1219. )
  1220. : '';
  1221. }
  1222. item.entrustedEnterpriseIdList = supplierObj[item.productId];
  1223. if (supplierObj[item.productId]?.length === 1) {
  1224. item.entrustedEnterpriseId = supplierObj[item.productId][0].id;
  1225. }
  1226. item['customerMark'] = item.customerMark || this.customerMark;
  1227. });
  1228. this.form.datasource = productList;
  1229. if (this.isChangeCount) {
  1230. this.changeCount();
  1231. } else {
  1232. this.allPrice = data.totalAmount || data?.contractVO?.totalPrice;
  1233. }
  1234. if (this.isDiscountTotalPrice) {
  1235. this.form.discountTotalPrice =
  1236. data.payAmount || data?.contractVO?.discountTotalPrice;
  1237. }
  1238. let codeList = this.form.datasource
  1239. .filter((item) => item.productCode)
  1240. .map((item) => item.productCode);
  1241. //获取仓库库存
  1242. let inventoryTotalList = await getInventoryTotalAPI(codeList);
  1243. this.form.datasource
  1244. .filter((item) => item.productCode)
  1245. .forEach((item, index) => {
  1246. let find =
  1247. inventoryTotalList.find(
  1248. (key) => key.code == item.productCode
  1249. ) || {};
  1250. this.form.datasource;
  1251. this.$set(
  1252. this.form.datasource[index],
  1253. 'availableCountBase',
  1254. find.availableCountBase
  1255. );
  1256. });
  1257. this.$refs.table.reload();
  1258. }
  1259. },
  1260. //计算单重
  1261. //选择产品
  1262. handParent(row, index) {
  1263. let item = {
  1264. id: row.productCode
  1265. };
  1266. this.$refs.productListRef.open(item, index);
  1267. },
  1268. //选择技术人回调
  1269. changeAnswer(obj, idx) {
  1270. this.$set(this.form.datasource[idx], 'technicalAnswerId', obj.id);
  1271. this.$set(this.form.datasource[idx], 'technicalAnswerName', obj.name);
  1272. },
  1273. handHead(row, index) {
  1274. let item = {
  1275. id: row.technicalAnswerId
  1276. };
  1277. this.$refs.headRef.open(item, index);
  1278. },
  1279. //选择产品回调
  1280. changeParent(obj, idx) {
  1281. obj.forEach((item, index) => {
  1282. let i = idx == -1 ? index : idx;
  1283. let row = JSON.parse(JSON.stringify(this.defaultForm));
  1284. row.key = this.form.datasource.length + 1;
  1285. let parasm = idx == -1 ? row : this.form.datasource[i];
  1286. this.$set(parasm, 'productId', item.id);
  1287. this.$set(parasm, 'categoryName', item.name);
  1288. this.$set(parasm, 'productCategoryId', item.categoryLevelId);
  1289. this.$set(parasm, 'productBrand', item.brandNum);
  1290. this.$set(parasm, 'productCategoryName', item.categoryLevelPath);
  1291. this.$set(parasm, 'productCode', item.code);
  1292. this.$set(parasm, 'productName', item.name);
  1293. this.$set(parasm, 'modelType', item.modelType);
  1294. this.$set(parasm, 'availableCountBase', item.availableCountBase);
  1295. this.$set(parasm, 'measuringUnit', item.measuringUnit);
  1296. this.$set(parasm, 'specification', item.specification);
  1297. this.$set(parasm, 'weightUnit', item.weightUnit);
  1298. this.$set(parasm, 'singleWeight', item.roughWeight);
  1299. this.$set(parasm, 'pricingWay', item.pricingWay || 1);
  1300. this.$set(parasm, 'imgCode', item.imgCode);
  1301. this.$set(parasm, 'produceType', item.componentAttribute);
  1302. this.$set(parasm, 'approvalNumber', item.extField?.approvalNumber);
  1303. this.$set(
  1304. parasm,
  1305. 'packingSpecification',
  1306. item.extField.packingSpecification
  1307. );
  1308. this.$set(parasm, 'customerMark', this.customerMark);
  1309. if (item.purchaseOrigins?.length > 0) {
  1310. item.purchaseOrigins = item.purchaseOrigins.map((val) => val + '');
  1311. }
  1312. this.$set(parasm, 'provenance', item.purchaseOrigins || []);
  1313. if (idx == -1) {
  1314. this.form.datasource.push(row);
  1315. }
  1316. });
  1317. },
  1318. remove(index) {
  1319. this.form.datasource.splice(index, 1);
  1320. this.setSort();
  1321. this.changeCount();
  1322. },
  1323. // 清空表格
  1324. restTable() {
  1325. this.form.datasource = [];
  1326. this.changeCount();
  1327. },
  1328. // 重新排序
  1329. setSort() {
  1330. this.form.datasource.forEach((n, index) => {
  1331. n.key = index + 1;
  1332. });
  1333. },
  1334. // 添加
  1335. handlAdd() {
  1336. let item = JSON.parse(JSON.stringify(this.defaultForm));
  1337. item.key = this.form.datasource.length + 1;
  1338. item.customerMark = this.customerMark;
  1339. this.form.datasource.push(item);
  1340. },
  1341. validateForm(callback) {
  1342. let singleWeightData = {};
  1343. this.form.datasource.forEach((item) => {
  1344. if (item.pricingWay == 2 && !item.singleWeight) {
  1345. singleWeightData['name'] = item.productName;
  1346. console.log(singleWeightData, 'singleWeightData');
  1347. }
  1348. });
  1349. if (singleWeightData.name) {
  1350. this.$message.warning(
  1351. singleWeightData.name + '计价方式为按重量计费,单重不能为空'
  1352. );
  1353. callback(false);
  1354. }
  1355. //开始表单校验
  1356. this.$refs.form.validate((valid, obj) => {
  1357. if (obj) {
  1358. let messages = Object.keys(obj).map((key) => obj[key][0]);
  1359. if (messages.length > 0) {
  1360. this.$message.warning(messages[0].message);
  1361. }
  1362. }
  1363. callback(valid);
  1364. });
  1365. },
  1366. save() {
  1367. this.$emit('save');
  1368. }
  1369. }
  1370. };
  1371. </script>
  1372. <style lang="scss" scoped>
  1373. .headbox {
  1374. display: flex;
  1375. justify-content: space-between;
  1376. align-items: center;
  1377. .amount {
  1378. font-size: 14px;
  1379. font-weight: bold;
  1380. padding-right: 30px;
  1381. }
  1382. }
  1383. .time-form .el-form-item {
  1384. margin-bottom: 0 !important;
  1385. }
  1386. ::v-deep .period {
  1387. display: flex;
  1388. .borderleftnone {
  1389. .el-input--medium .el-input__inner {
  1390. border-top-right-radius: 0;
  1391. border-bottom-right-radius: 0;
  1392. }
  1393. }
  1394. .borderrightnone {
  1395. .el-input--medium .el-input__inner {
  1396. border-top-left-radius: 0;
  1397. border-bottom-left-radius: 0;
  1398. }
  1399. }
  1400. }
  1401. ::v-deep .time-form tbody > tr:hover > td {
  1402. background-color: transparent !important;
  1403. }
  1404. ::v-deep .time-form .el-table tr {
  1405. background-color: #ffffff;
  1406. }
  1407. .pricebox {
  1408. display: flex;
  1409. justify-content: flex-start;
  1410. align-items: center;
  1411. font-weight: bold;
  1412. }
  1413. </style>