index.vue 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908
  1. <template>
  2. <div>
  3. <Modal
  4. :width="1400"
  5. class-name="vertical-center-modal"
  6. title="新增产品"
  7. :mask-closable="false"
  8. v-model="showAddProduct"
  9. >
  10. <div style="max-height: 800px; overflow: hidden; overflow-y: auto">
  11. <Tabs
  12. ref="tabsRef"
  13. @on-click="handleTabsPaneChange"
  14. type="card"
  15. closable
  16. @on-tab-remove="handleTabRemove"
  17. >
  18. <Button
  19. @click="handleAddProductCopy"
  20. size="small"
  21. type="primary"
  22. style="margin-right: 5px"
  23. slot="extra"
  24. >复制产品</Button
  25. >
  26. <Button
  27. @click="handleAddProductAdd"
  28. size="small"
  29. type="warning"
  30. style="margin-right: 5px"
  31. slot="extra"
  32. >添加</Button
  33. >
  34. <!-- <Button
  35. @click="handleAddProductDele"
  36. size="small"
  37. type="primary"
  38. slot="extra"
  39. >删除</Button
  40. > -->
  41. <TabPane
  42. :label="
  43. (addProductArray[index].position
  44. ? addProductArray[index].position
  45. : '位置') +
  46. '-' +
  47. item.type_name
  48. "
  49. v-for="(item, index) in addProductArray"
  50. :key="item.id"
  51. :name="item.index + ''"
  52. >
  53. </TabPane>
  54. </Tabs>
  55. <div class="modal_product_info">
  56. <div class="modal_product_info_title">产品信息</div>
  57. <div class="modal_product_info_content modal_product">
  58. <Form :model="currencyProduct" :label-width="100">
  59. <FormItem label="选择产品:">
  60. <Tooltip style="width: 120px" transfer>
  61. <span slot="content">
  62. <span
  63. v-for="_item in productList"
  64. :key="_item.id"
  65. v-show="_item.id == currencyProduct.product_id"
  66. >{{ _item.title }}</span
  67. >
  68. </span>
  69. <Select
  70. filterable
  71. clearable
  72. filter-by-label
  73. transfer
  74. label-in-value
  75. size="small"
  76. v-model="currencyProduct.product_id"
  77. @on-change="handleAddProductSelect($event)"
  78. style="width: 120px"
  79. >
  80. <Option
  81. v-for="item of productList"
  82. :tag="item.img_url"
  83. :key="item.id"
  84. :label="item.title"
  85. :value="item.id"
  86. ></Option>
  87. </Select>
  88. </Tooltip>
  89. </FormItem>
  90. <FormItem label="位置:">
  91. <Tooltip style="width: 120px" transfer>
  92. <span slot="content">
  93. {{ currencyProduct.position }}
  94. </span>
  95. <Input
  96. size="small"
  97. v-model="currencyProduct.position"
  98. style="width: 120px"
  99. placeholder="请输入位置"
  100. />
  101. </Tooltip>
  102. </FormItem>
  103. <FormItem label="计量单位:">
  104. <Input
  105. size="small"
  106. disabled
  107. style="width: 120px"
  108. v-model="currencyProduct.unit"
  109. placeholder="自动带出"
  110. />
  111. </FormItem>
  112. <!-- 工艺属性 -->
  113. <div v-for="(ele, idx) in currencyProduct.process" :key="idx">
  114. <FormItem
  115. v-for="(_process, _idx) in process_list"
  116. :key="_idx"
  117. :label="_process.title + ':'"
  118. v-show="ele.key == _process.id"
  119. >
  120. <Tooltip style="width: 120px" transfer>
  121. <span slot="content">
  122. <span
  123. v-for="_item in ele.cld"
  124. :key="_item.id"
  125. v-show="_item.id == ele.value"
  126. >{{ _item.title }}</span
  127. >
  128. </span>
  129. <Select
  130. style="width: 120px"
  131. filterable
  132. clearable
  133. filter-by-label
  134. transfer
  135. label-in-value
  136. @on-open-change="
  137. (e) =>
  138. handleGetProductMeasure(e, idx, currencyProduct, ele)
  139. "
  140. @on-change="
  141. (e) =>
  142. handleProductProcessChange(
  143. e,
  144. idx,
  145. currencyProduct,
  146. ele
  147. )
  148. "
  149. v-model="ele.value"
  150. size="small"
  151. >
  152. <Option
  153. v-for="option of ele.cld"
  154. :key="option.id"
  155. :disabled="option.isDisabled"
  156. :label="option.title"
  157. :value="option.id"
  158. ></Option>
  159. </Select>
  160. </Tooltip>
  161. </FormItem>
  162. </div>
  163. <!-- 测量字段 -->
  164. <FormItem
  165. v-for="ele in currencyProduct.measure"
  166. :key="ele.id"
  167. :label="ele.title + ':'"
  168. >
  169. <Input
  170. size="small"
  171. type="text"
  172. clearable
  173. :placeholder="ele.e_title"
  174. v-model="ele.value"
  175. @on-blur="
  176. (e) => handleProductMeasureBlur(e, currencyProduct, ele)
  177. "
  178. style="width: 120px"
  179. />
  180. </FormItem>
  181. <FormItem label="数量:">
  182. <Input
  183. size="small"
  184. @on-change="(e) => handleProductNumChange(e, currencyProduct)"
  185. v-model="currencyProduct.total_num"
  186. style="width: 120px"
  187. placeholder="请输入产品数量"
  188. />
  189. </FormItem>
  190. <FormItem label="核算数量:">
  191. <Input
  192. size="small"
  193. v-model="currencyProduct.num"
  194. disabled
  195. style="width: 120px"
  196. placeholder="自动带出"
  197. />
  198. </FormItem>
  199. <FormItem label="单价:">
  200. <Input
  201. size="small"
  202. v-model="currencyProduct.unit_price"
  203. @on-change="
  204. (e) => handleProductUnit_priceChange(e, currencyProduct)
  205. "
  206. style="width: 120px"
  207. placeholder="自动带出"
  208. />
  209. </FormItem>
  210. <FormItem label="附加金额:">
  211. <Input
  212. size="small"
  213. v-model="currencyProduct.ext_price"
  214. @on-change="
  215. (e) => handleProductExt_priceChange(e, currencyProduct)
  216. "
  217. style="width: 120px"
  218. placeholder="自动带出"
  219. />
  220. </FormItem>
  221. <FormItem label="超标金额:">
  222. <Input
  223. size="small"
  224. @on-change="
  225. (e) => handleProductOver_priceChange(e, currencyProduct)
  226. "
  227. v-model="currencyProduct.over_price"
  228. style="width: 120px"
  229. placeholder="自动带出"
  230. />
  231. </FormItem>
  232. <FormItem label="金额:">
  233. <Input
  234. size="small"
  235. v-model="currencyProduct.price"
  236. style="width: 120px"
  237. placeholder="自动带出"
  238. />
  239. </FormItem>
  240. <FormItem label="图号:">
  241. <Input
  242. size="small"
  243. v-model="currencyProduct.url_number"
  244. style="width: 120px"
  245. placeholder="自动带出"
  246. />
  247. </FormItem>
  248. <FormItem
  249. v-for="(_customize, customize_key) in currencyProduct.customize"
  250. :label="_customize.style + ':'"
  251. :key="customize_key + 99"
  252. >
  253. <Input
  254. v-show="_customize.type == 1"
  255. size="small"
  256. type="text"
  257. v-model="_customize.value"
  258. style="width: 120px"
  259. placeholder="请输入"
  260. />
  261. <Select
  262. v-show="_customize.type == 2"
  263. style="width: 120px"
  264. filterable
  265. clearable
  266. v-model="_customize.value"
  267. size="small"
  268. >
  269. <Option
  270. v-for="option of _customize.explain"
  271. :key="option.value"
  272. :label="option.value"
  273. :value="option.value"
  274. ></Option>
  275. </Select>
  276. </FormItem>
  277. <FormItem
  278. v-for="(outh, outh_key) in currencyProduct.outh"
  279. :label="outh.title"
  280. :key="outh_key + 21"
  281. >
  282. <img
  283. v-if="outh.key == 'img' || outh.key == 'url'"
  284. @click="showPreview(currencyProduct, outh.key)"
  285. style="
  286. max-width: 30px;
  287. max-height: 30px;
  288. top: 5px;
  289. position: relative;
  290. cursor: pointer;
  291. "
  292. :src="$store.state.ip + outh.value"
  293. />
  294. <Input
  295. v-if="
  296. outh.key != 'img' && outh.key != 'url' && outh.key != 'lock'
  297. "
  298. disabled
  299. placeholder="自动生成"
  300. style="width: 120px"
  301. size="small"
  302. v-model="outh.value"
  303. />
  304. <Select
  305. label-in-value
  306. @on-change="changeLock($event, currencyProduct, index)"
  307. size="small"
  308. clearable
  309. style="width: 120px"
  310. v-if="outh.key == 'lock'"
  311. v-model="currencyProduct[outh.key]"
  312. >
  313. <Option
  314. v-for="luck of lock_list"
  315. :key="luck.id"
  316. :tag="luck.price"
  317. :value="luck.id"
  318. :label="luck.title"
  319. ></Option>
  320. <Option :value="0" label="无"></Option>
  321. </Select>
  322. </FormItem>
  323. <FormItem label="备注:">
  324. <Select
  325. size="small"
  326. clearable
  327. filterable
  328. allow-create
  329. @on-create="handleRemarkCreate"
  330. style="width: 120px"
  331. v-model="currencyProduct.remark"
  332. >
  333. <Option
  334. v-for="_remark of support_remark"
  335. :key="_remark"
  336. :value="_remark"
  337. :label="_remark"
  338. ></Option>
  339. </Select>
  340. <!-- <Input
  341. size="small"
  342. type="textarea"
  343. v-model="item.remark"
  344. style="width: 120px"
  345. placeholder="请输入备注"
  346. /> -->
  347. </FormItem>
  348. <FormItem label="产品图:">
  349. <!-- v-show="modalData.url && modalData.url.length > 0" -->
  350. <div class="product-img">
  351. <div class="product-add">
  352. <div
  353. class="items"
  354. v-for="(item, index) of currencyProduct.url"
  355. :key="index"
  356. >
  357. <img
  358. @click="looks(item)"
  359. :src="$store.state.ip + item"
  360. alt=""
  361. />
  362. </div>
  363. </div>
  364. </div>
  365. </FormItem>
  366. </Form>
  367. </div>
  368. </div>
  369. <div class="modal_product_info">
  370. <div class="modal_product_info_title">部件信息</div>
  371. <div class="modal_product_info_content modal_parts">
  372. <Form
  373. :model="element"
  374. v-for="(element, idx) in currencyProduct.part"
  375. :key="element.id + '111' + idx"
  376. :label-width="50"
  377. >
  378. <FormItem
  379. :label-width="element.isBP ? 1 : 50"
  380. v-show="!element.is_metal"
  381. >
  382. <Radio
  383. v-show="element.isBP"
  384. @click.native.prevent="handleRadioClick(element)"
  385. v-model="element.isChoosed"
  386. ></Radio>
  387. <!-- <span v-show="element.isBP">{{ element.part_title }} </span> -->
  388. </FormItem>
  389. <FormItem label="部件:" v-show="!element.is_metal">
  390. <Select
  391. filterable
  392. clearable
  393. transfer
  394. label-in-value
  395. size="small"
  396. @on-change="
  397. handlePartChange(
  398. $event,
  399. element,
  400. currencyProduct.measure,
  401. currencyProduct.total_num
  402. )
  403. "
  404. v-model="element.change_id"
  405. style="width: 180px"
  406. >
  407. <Option
  408. v-for="item of element.change"
  409. :key="item.id"
  410. :label="item.part_title"
  411. :value="item.id"
  412. ></Option>
  413. </Select>
  414. </FormItem>
  415. <FormItem
  416. label="高:"
  417. v-show="
  418. !element.is_metal &&
  419. element.hide_measure &&
  420. !element.hide_measure.filter((v) => v == 'H').length > 0
  421. "
  422. >
  423. <Input
  424. size="small"
  425. clearable
  426. v-model="element.long"
  427. style="width: 50px"
  428. placeholder="请输入厚"
  429. />
  430. </FormItem>
  431. <FormItem
  432. label="宽:"
  433. v-show="
  434. !element.is_metal &&
  435. element.hide_measure &&
  436. !element.hide_measure.filter((v) => v == 'W').length > 0
  437. "
  438. >
  439. <Input
  440. size="small"
  441. clearable
  442. v-model="element.wide"
  443. style="width: 50px"
  444. placeholder="请输入宽"
  445. />
  446. </FormItem>
  447. <FormItem
  448. label="厚:"
  449. v-show="
  450. !element.is_metal &&
  451. element.hide_measure &&
  452. !element.hide_measure.filter((v) => v == 'T').length > 0
  453. "
  454. >
  455. <Input
  456. size="small"
  457. clearable
  458. v-model="element.high"
  459. style="width: 50px"
  460. placeholder="请输入高"
  461. />
  462. </FormItem>
  463. <FormItem
  464. v-for="(process_detail, idx) in element.process"
  465. :key="process_detail.name + '222' + element.part_id"
  466. :label="process_detail.name + ':'"
  467. v-show="
  468. !element.is_metal &&
  469. element.hide_process &&
  470. !element.hide_process.filter(
  471. (v) => v == process_detail.process_id
  472. ).length > 0
  473. "
  474. >
  475. <Tooltip style="width: 120px" transfer>
  476. <span slot="content">
  477. <span
  478. v-for="_item in process_detail.cld"
  479. :key="_item.id"
  480. v-show="_item.id == process_detail.value"
  481. >{{ _item.title }}</span
  482. >
  483. </span>
  484. <Select
  485. style="width: 120px"
  486. filterable
  487. clearable
  488. transfer
  489. label-in-value
  490. @on-change="
  491. (e) =>
  492. handlePartProcessChange(e, idx, element, process_detail)
  493. "
  494. v-model="process_detail.value"
  495. size="small"
  496. >
  497. <Option
  498. v-for="option of process_detail.cld"
  499. :key="option.id"
  500. :label="option.title"
  501. :value="option.id"
  502. ></Option>
  503. </Select>
  504. </Tooltip>
  505. </FormItem>
  506. <FormItem v-show="!element.is_metal">
  507. <Button
  508. @click="handlePartsApart(element, idx, currencyProduct.part)"
  509. type="primary"
  510. v-if="element.isBP"
  511. style="margin-right: 5px"
  512. size="small"
  513. >拆分</Button
  514. >
  515. <Button
  516. @click="handlePartsDele(element, idx, currencyProduct.part)"
  517. type="primary"
  518. v-else
  519. style="margin-right: 5px"
  520. size="small"
  521. >删除</Button
  522. >
  523. <Button
  524. @click="handlePartDetailEdit(element, idx)"
  525. type="primary"
  526. style="margin-right: 5px"
  527. size="small"
  528. >{{
  529. element.isShowPartDetail ? "收起" : "修改原材料"
  530. }}</Button
  531. >
  532. </FormItem>
  533. <div
  534. :class="[
  535. 'part_detail_form',
  536. element.isShowPartDetail ? '' : 'hide_part_detail',
  537. ]"
  538. :data-index="idx"
  539. >
  540. <FormItem>
  541. <div v-for="ele in element.part_detail" :key="ele.id">
  542. <Form :model="ele">
  543. <FormItem>
  544. <div style="width: 200px">
  545. {{ ele.title || ele.part_detail_title }}
  546. </div>
  547. </FormItem>
  548. <!-- 原材料 -->
  549. <Form>
  550. <FormItem>
  551. <div style="width: 200px">
  552. {{ ele.material_detail_title || "请选择" }}
  553. </div>
  554. </FormItem>
  555. <FormItem label="高" :label-width="40">
  556. <Select
  557. style="width: 80px"
  558. filterable
  559. clearable
  560. transfer
  561. v-model="ele.material_detail_id"
  562. @on-change="(e) => handleMaterialChange(e, ele)"
  563. placeholder="请选择高"
  564. size="small"
  565. >
  566. <Option
  567. v-for="option of ele.material_detail_list"
  568. :key="option.material_detail_id"
  569. :label="option.long"
  570. :value="option.material_detail_id"
  571. ></Option>
  572. </Select>
  573. </FormItem>
  574. <FormItem label="宽" :label-width="40">
  575. <Select
  576. style="width: 80px"
  577. filterable
  578. clearable
  579. transfer
  580. v-model="ele.material_detail_id"
  581. placeholder="请选择宽"
  582. size="small"
  583. >
  584. <Option
  585. v-for="option of ele.material_detail_list"
  586. :key="option.material_detail_id"
  587. :label="option.wide"
  588. :value="option.material_detail_id"
  589. ></Option>
  590. </Select>
  591. </FormItem>
  592. <FormItem label="厚" :label-width="40">
  593. <Select
  594. style="width: 80px"
  595. filterable
  596. clearable
  597. transfer
  598. v-model="ele.material_detail_id"
  599. placeholder="请选择厚"
  600. size="small"
  601. >
  602. <Option
  603. v-for="option of ele.material_detail_list"
  604. :key="option.material_detail_id"
  605. :label="option.high"
  606. :value="option.material_detail_id"
  607. ></Option>
  608. </Select>
  609. </FormItem>
  610. <FormItem label="数量" :label-width="40">
  611. <Input
  612. size="small"
  613. v-model="ele.material_detail_num"
  614. style="width: 80px"
  615. placeholder="请输入数量"
  616. />
  617. </FormItem>
  618. </Form>
  619. </Form>
  620. </div>
  621. </FormItem>
  622. </div>
  623. </Form>
  624. </div>
  625. </div>
  626. <div class="modal_product_info">
  627. <div class="modal_product_info_title">
  628. 附加信息
  629. <Button
  630. @click="handleExtraAdd(currencyProduct.extArray, 2)"
  631. type="primary"
  632. size="small"
  633. >新增附加项目</Button
  634. >
  635. </div>
  636. <div class="modal_product_info_content modal_extra">
  637. <Form
  638. :model="element"
  639. v-for="(element, idx) in currencyProduct.extArray"
  640. :key="element.id"
  641. :label-width="80"
  642. >
  643. <FormItem label="附加项目:">
  644. <Select
  645. filterable
  646. clearable
  647. transfer
  648. label-in-value
  649. size="small"
  650. v-model="element.id"
  651. @on-change="
  652. (e) => handleExtChange(element, e, currencyProduct)
  653. "
  654. style="width: 100px"
  655. >
  656. <Option
  657. v-for="item of extList"
  658. :key="item.id"
  659. :label="item.title"
  660. :value="item.id"
  661. ></Option>
  662. </Select>
  663. </FormItem>
  664. <FormItem label="数量:">
  665. <Input
  666. size="small"
  667. v-model="element.num"
  668. @on-change="handleTotalPriceCalc(element, currencyProduct)"
  669. style="width: 100px"
  670. placeholder="请输入数量"
  671. />
  672. </FormItem>
  673. <FormItem label="单价:">
  674. <Input
  675. size="small"
  676. v-model="element.price"
  677. @on-change="handleTotalPriceCalc(element, currencyProduct)"
  678. style="width: 100px"
  679. placeholder="请输入单价"
  680. />
  681. </FormItem>
  682. <FormItem label="金额:">
  683. <Input
  684. size="small"
  685. @on-change="handleTotalPriceChange(element, currencyProduct)"
  686. v-model="element.total_price"
  687. style="width: 100px"
  688. placeholder="请输入金额"
  689. />
  690. </FormItem>
  691. <FormItem label="备注:">
  692. <Input
  693. size="small"
  694. v-model="element.remark"
  695. style="width: 100px"
  696. placeholder="请输入备注"
  697. />
  698. </FormItem>
  699. <FormItem>
  700. <a
  701. style="color: red"
  702. @click="
  703. handleExtraDele(
  704. currencyProduct.extArray,
  705. element,
  706. idx,
  707. currencyProduct
  708. )
  709. "
  710. >删除</a
  711. >
  712. </FormItem>
  713. </Form>
  714. </div>
  715. </div>
  716. </div>
  717. <div slot="footer">
  718. <Button @click="cancel">取消</Button>
  719. <Button @click="then" type="primary">确定</Button>
  720. </div>
  721. </Modal>
  722. </div>
  723. </template>
  724. <script>
  725. // 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
  726. // 例如:import 《组件名称》 from '《组件路径》';
  727. export default {
  728. name: "",
  729. components: {},
  730. props: {},
  731. // import引入的组件需要注入到对象中才能使用
  732. data() {
  733. // 这里存放数据
  734. return {
  735. showAddProduct: false,
  736. subAddProductData: [],
  737. addProductArray: [
  738. {
  739. type_name: "产品1",
  740. num: 1,
  741. position: "位置",
  742. index: "0",
  743. extArray: [],
  744. },
  745. ], //新增产品列表
  746. pre_bp_id: "", //产品分类ID,添加多个产品时判断是否与前一个产品分类一致
  747. process_match_list: [], //当前产品所有工艺组合
  748. support_remark: [], //备注列表
  749. bpp_list: [], //工艺属性列表
  750. // route_id_at_copy: "", //复制产品的工艺路线ID
  751. pre_process_obj: {}, //产品工艺属性,添加多个产品时判断是否与前一个工艺属性一致
  752. currentTabIndex: "0", //当前分页面
  753. productList: [], //产品列表
  754. metalList: [], //五金列表
  755. extList: [], //五金列表
  756. currencyProduct: {}, //当前展示数据
  757. process_list: [], //所有工艺属性
  758. tempExtArray: [], //临时附加信息,更换产品是否保留用
  759. isAdd: false, //判断产品是否为添加
  760. };
  761. },
  762. // 生命周期 - 创建完成(可以访问当前this实例)
  763. created() {
  764. // 获取工艺属性
  765. this.axios({
  766. method: "get",
  767. url: "/api/bpp_list",
  768. }).then((res) => {
  769. if (res.code == 200) {
  770. this.bpp_list = res.data;
  771. }
  772. });
  773. // 获取产品列表
  774. this.axios("/api/product").then(
  775. (res) => (this.productList = res.data.data)
  776. );
  777. // 获取五金列表
  778. this.axios
  779. .get("/api/material", { params: { sub_type_id: 5 } })
  780. .then((res) => {
  781. if (res.code == 200) {
  782. this.metalList = res.data.data;
  783. }
  784. });
  785. // 获取附加列表
  786. this.axios.get("/api/project_ext_list").then((res) => {
  787. if (res.code == 200) {
  788. this.extList = res.data.data;
  789. }
  790. });
  791. },
  792. // 生命周期 - 挂载完成(可以访问DOM元素)
  793. mounted() {
  794. this.currencyProduct = this.addProductArray[0];
  795. },
  796. methods: {
  797. handleAddProductCopy() {
  798. // this.addProductArray[this.currentTabIndex] = this.currencyProduct;
  799. let idx = this.$refs.tabsRef.activeKey;
  800. let obj = this.deepClone(this.addProductArray[idx]);
  801. obj.index = this.addProductArray.length;
  802. obj.position = "";
  803. this.addProductArray.push(obj);
  804. },
  805. handleAddProductDele() {
  806. let idx = this.$refs.tabsRef.activeKey;
  807. this.addProductArray.splice(idx, 1);
  808. },
  809. handleTabRemove(name) {
  810. this.addProductArray[name].isdeleted = true;
  811. this.currencyProduct = this.addProductArray[name - 1];
  812. // this["tab" + name] = false;
  813. },
  814. handleAddProductAdd() {
  815. this.isAdd = true;
  816. let index = this.addProductArray.length;
  817. this.addProductArray.push({
  818. type_name: "产品" + (this.addProductArray.length + 1),
  819. position: "",
  820. index,
  821. extArray: [],
  822. });
  823. },
  824. handleAddProductSelect(row) {
  825. if (row) {
  826. let product_id = row.value;
  827. this.currencyProduct.type_name = row.label;
  828. this.currencyProduct.title = row.label;
  829. this.axios("/api/order_get_product_detail_new", {
  830. params: { product_id, custom_id: this.custom_id },
  831. }).then((res) => {
  832. if (res.code == 200) {
  833. if (this.process_list.length == 0) {
  834. this.process_list = res.data.process_list;
  835. }
  836. if (this.addProductArray.length == 1) {
  837. let _temp_obj = {};
  838. if (res.data.process.list.length > 1) {
  839. for (const key in res.data.process.list[0].detail) {
  840. res.data.process.list.reduce((pre, cur) => {
  841. if (_temp_obj[key] == "") {
  842. return pre;
  843. } else {
  844. if (pre.detail[key] == cur.detail[key]) {
  845. _temp_obj[key] = pre.detail[key];
  846. return pre;
  847. } else {
  848. _temp_obj[key] = "";
  849. return pre;
  850. }
  851. }
  852. });
  853. }
  854. } else {
  855. _temp_obj = res.data.process.list[0].detail;
  856. }
  857. this.pre_process_obj = this.deepClone(_temp_obj);
  858. }
  859. // this.process_match_list = res.data.process.list;
  860. this.support_remark = Array.from(
  861. new Set([...res.data.support_remark, ...this.support_remark])
  862. );
  863. let modalData = this.currencyProduct;
  864. modalData.url = res.data.url;
  865. modalData.total_num = res.data.total_num || 1;
  866. modalData.ext_price = res.data.ext_price || 0;
  867. modalData.unit_price = res.data.price || 0;
  868. modalData.num = res.data.num || 1;
  869. modalData.num_temp_save = modalData.num;
  870. modalData.over_price = res.data.over_price || 0;
  871. modalData.unit = res.data.unit || "";
  872. modalData.remark = res.data.remark || "";
  873. modalData.url_number = res.data.url_number || "";
  874. modalData.overdraft = res.data.overdraft;
  875. modalData.num_formula = res.data.num_formula;
  876. modalData.bp_id = res.data.bp_id;
  877. // 金额=(产品单价)*核算数量 +附加金额 + 超标金额
  878. modalData.price =
  879. (modalData.unit_price * 1 || 0) * (modalData.num * 1 || 1) +
  880. (modalData.over_price * 1 || 0) +
  881. (modalData.ext_price * 1 || 0);
  882. modalData.price = modalData.price.toFixed(2);
  883. modalData.selected_ids = [];
  884. modalData.part = res.data.part;
  885. modalData.part.forEach((element) => {
  886. // 选择不是附加项目的,
  887. if (!element.is_metal) {
  888. // 选择不是线条、或者基础档案中要默认为空的部件
  889. element.isBP = true;
  890. element.isChoosed = true;
  891. if (element.is_null == 1) {
  892. element.change_id = "";
  893. element.part_title = "";
  894. element.title = "";
  895. } else {
  896. element.change_id = element.change[0].id;
  897. }
  898. element.part_detail = element.sub_part;
  899. //展示非拆分部件
  900. // 默认替换部件
  901. //存计算公式
  902. element.long ? "" : (element.long = 0);
  903. element.wide ? "" : (element.wide = 0);
  904. element.high ? "" : (element.high = 0);
  905. element.longCalc = element.long;
  906. element.wideCalc = element.wide;
  907. element.highCalc = element.high;
  908. element.part_detail.forEach((elem) => {
  909. elem.org_num = elem.num;
  910. elem.material_detail_id = 0;
  911. elem.material_detail_title =
  912. elem.material_detail_list[0].title;
  913. elem.material_detail_id =
  914. elem.material_detail_list[0].material_detail_id;
  915. elem.material_detail_num = elem.num || 0;
  916. elem.material_detail_org_num = elem.num || 0;
  917. elem.long ? "" : (elem.long = 0);
  918. elem.wide ? "" : (elem.wide = 0);
  919. elem.high ? "" : (elem.high = 0);
  920. elem.longCalc = elem.long || "";
  921. elem.wideCalc = elem.wide || "";
  922. elem.highCalc = elem.high || "";
  923. elem.material_detail_list.forEach((el) => {
  924. el.long = el.long || "0";
  925. el.wide = el.wide || "0";
  926. el.high = el.high || "0";
  927. });
  928. });
  929. element.part_detail.map((_part_detail) => {
  930. _part_detail.material_detail_org_num = _part_detail.num || 0;
  931. _part_detail.part_detail_option = [];
  932. _part_detail.material_detail_list.map((v) => {
  933. _part_detail.part_detail_option.push({
  934. label: `${v.long}*${v.wide}*${v.high}`,
  935. value: v.material_detail_id,
  936. });
  937. });
  938. });
  939. }
  940. });
  941. //测量字段
  942. modalData.measure = res.data.measure;
  943. modalData.measure.forEach((element) => {
  944. element.value = "";
  945. element.measureCalc = element.e_title;
  946. });
  947. //工艺属性
  948. modalData.process = [];
  949. this.bpp_list.map((element) => {
  950. for (const key in res.data.process.title) {
  951. const ele = res.data.process.title[key];
  952. if (element.name == ele) {
  953. if (this.isAdd) {
  954. modalData.process.push({
  955. key: key,
  956. id: key,
  957. title: ele,
  958. value: "",
  959. cld: element.cld,
  960. });
  961. } else {
  962. const compare = res.data.process.list.filter(
  963. (item) => item.detail[key] == this.pre_process_obj[key]
  964. );
  965. if (compare.length > 0) {
  966. modalData.procedure_properties = {};
  967. modalData.procedure_properties[key] =
  968. this.pre_process_obj[key] * 1;
  969. modalData.process.push({
  970. key: key,
  971. id: key,
  972. title: ele,
  973. value: this.pre_process_obj[key] * 1,
  974. cld: element.cld,
  975. });
  976. } else {
  977. modalData.procedure_properties = {};
  978. modalData.procedure_properties[key] = "";
  979. modalData.process.push({
  980. key: key,
  981. id: key,
  982. title: ele,
  983. value: "",
  984. cld: element.cld,
  985. });
  986. }
  987. }
  988. }
  989. }
  990. });
  991. modalData.part.forEach((element) => {
  992. if (!element.is_metal) {
  993. //赋值默认工艺属性
  994. element.process = this.deepClone(this.bpp_list);
  995. element.process.forEach((elem, index) => {
  996. for (const key in res.data.process.title) {
  997. const ele = res.data.process.title[key];
  998. if (elem.name == ele) {
  999. elem.value = this.pre_process_obj[key] * 1;
  1000. elem.process_id = key;
  1001. if (!element.procedure_properties) {
  1002. element.procedure_properties = {};
  1003. }
  1004. element.procedure_properties[key] =
  1005. this.pre_process_obj[key] * 1;
  1006. }
  1007. }
  1008. });
  1009. }
  1010. });
  1011. if (res.data.bp_id == this.pre_bp_id) {
  1012. modalData.extArray = this.deepClone(this.tempExtArray);
  1013. if (modalData.extArray.length == 1) {
  1014. modalData.ext_price =
  1015. modalData.extArray[0].num * 1 * modalData.extArray[0].price;
  1016. } else {
  1017. modalData.ext_price = modalData.extArray.reduce(
  1018. (pre, pur) => pre.total_price * 1 + pur.num * pur.price * 1
  1019. );
  1020. }
  1021. modalData.price =
  1022. (modalData.unit_price * 1 || 0) * (modalData.num * 1 || 1) +
  1023. (modalData.over_price * 1 || 0) +
  1024. (modalData.ext_price * 1 || 0);
  1025. modalData.price = modalData.price.toFixed(2);
  1026. } else {
  1027. modalData.extArray = [];
  1028. }
  1029. }
  1030. });
  1031. }
  1032. },
  1033. handleGetProductMeasure(val, index, product, ele) {
  1034. if (val) {
  1035. let change = [];
  1036. if (product.part.filter((v) => !v.change_id).length > 0) {
  1037. ele.cld = [];
  1038. this.$forceUpdate();
  1039. return this.$Message.warning("请先选择部件!");
  1040. }
  1041. product.part.map((item) => {
  1042. change.push({
  1043. old_id: item.org_part_id || item.part_id,
  1044. new_id: item.change.filter((v) => v.id == item.change_id)[0]
  1045. .part_id,
  1046. });
  1047. });
  1048. let list = product.process.map((item) => {
  1049. return { type_id: item.key || item.id, value: item.value || "" };
  1050. });
  1051. ele.cld = [];
  1052. this.axios({
  1053. method: "post",
  1054. url: "/api/order_get_product_process",
  1055. data: {
  1056. product_id: product.product_id,
  1057. type_id: ele.key,
  1058. list,
  1059. change,
  1060. },
  1061. }).then((res) => {
  1062. if (res.code == 200) {
  1063. ele.cld = res.data;
  1064. } else {
  1065. ele.cld = [];
  1066. }
  1067. this.$forceUpdate();
  1068. });
  1069. }
  1070. },
  1071. //修改材质/颜色/工艺的 disabled
  1072. handleProductProcessChange(e, n, modelData, ele) {
  1073. if (e) {
  1074. this.pre_process_obj[ele.id] = e.value;
  1075. if (!modelData.procedure_properties_str) {
  1076. modelData.procedure_properties_str = [];
  1077. }
  1078. modelData.procedure_properties_str[ele.id - 1] = e.label;
  1079. if (!modelData.procedure_properties) {
  1080. modelData.procedure_properties = {};
  1081. }
  1082. modelData.procedure_properties[ele.id] = e.value;
  1083. let isStart = true;
  1084. modelData.process.forEach((element) => {
  1085. if (element.value == "") {
  1086. isStart = false;
  1087. }
  1088. });
  1089. //匹配工艺路线
  1090. if (isStart) {
  1091. let _target = [];
  1092. let _sorce = this.deepClone(this.process_match_list);
  1093. modelData.process.forEach((element) => {
  1094. _target.push(element.value);
  1095. });
  1096. _sorce.forEach((element) => {
  1097. let _str = [];
  1098. for (const key in element.detail) {
  1099. const item = element.detail[key];
  1100. _str.push(item);
  1101. }
  1102. element.new_detail = _str.join(",");
  1103. });
  1104. let target = _target.join(",");
  1105. _sorce.forEach((element) => {
  1106. if (element.new_detail == target) {
  1107. modelData.route_id = element.id;
  1108. }
  1109. });
  1110. }
  1111. // 产品 - 部件 工艺属性联动
  1112. modelData.part.forEach((element) => {
  1113. // 此处有错误,产品选择完工艺路线之后部件的展示跟着改了但是procedure_properties没有
  1114. if (!element.is_metal) {
  1115. element.process.forEach((elem) => {
  1116. if (elem.name == ele.title) {
  1117. elem.value = e.value;
  1118. if (!element.procedure_properties) {
  1119. element.procedure_properties = {};
  1120. }
  1121. if (!element.procedure_properties_str) {
  1122. element.procedure_properties_str = [];
  1123. }
  1124. element.procedure_properties[ele.id] = e.value;
  1125. element.procedure_properties_str[n] = e.label;
  1126. }
  1127. });
  1128. }
  1129. });
  1130. } else {
  1131. modelData.route_id = "";
  1132. if (typeof modelData.procedure_properties == "string") {
  1133. modelData.procedure_properties = modelData.procedure_properties.split(
  1134. ","
  1135. );
  1136. }
  1137. // modelData.procedure_properties = [];
  1138. modelData.procedure_properties[ele.id] = "";
  1139. }
  1140. this.$forceUpdate();
  1141. },
  1142. handlePartProcessChange(val, n, row, process_detail) {
  1143. if (!row.procedure_properties) {
  1144. row.procedure_properties = {};
  1145. }
  1146. if (!row.procedure_properties_str) {
  1147. row.procedure_properties_str = [];
  1148. }
  1149. if (val) {
  1150. row.procedure_properties[process_detail.id] = val.value;
  1151. row.procedure_properties_str[n] = val.label;
  1152. } else {
  1153. row.procedure_properties[process_detail.id] = "";
  1154. row.procedure_properties_str[n] = "";
  1155. }
  1156. this.$forceUpdate();
  1157. },
  1158. handlePartsDele(element, index, array) {
  1159. array.splice(index, 1);
  1160. this.$forceUpdate();
  1161. },
  1162. handlePartDetailEdit(element, index) {
  1163. element.isShowPartDetail = !element.isShowPartDetail;
  1164. this.$forceUpdate();
  1165. },
  1166. handlePartsApart(element, index, array) {
  1167. let obj = this.deepClone(element);
  1168. obj.isBP = false;
  1169. array.splice(index + 1, 0, obj);
  1170. this.$forceUpdate();
  1171. },
  1172. handleExtraDele(array, row, index, modalData) {
  1173. array.splice(index, 1);
  1174. this.handleTotalPriceCalc(row, modalData);
  1175. this.$forceUpdate();
  1176. },
  1177. handlePartChange($event, row, measure, product_num) {
  1178. if ($event) {
  1179. let cur = row.change.filter((item) => item.id == row.change_id);
  1180. console.log("cur :>> ", cur);
  1181. row.part_title = cur[0].part_title;
  1182. row.org_part_id = row.part_id;
  1183. row.part_id = cur[0].part_id;
  1184. row.high = cur[0].high || 0;
  1185. row.highCalc = row.high;
  1186. row.long = cur[0].long || 0;
  1187. row.longCalc = row.long;
  1188. row.wide = cur[0].wide || 0;
  1189. row.wideCalc = row.wide;
  1190. row.part_detail = cur[0].sub_part;
  1191. row.part_detail.forEach((elem) => {
  1192. elem.longCalc = elem.long;
  1193. elem.wideCalc = elem.wide;
  1194. elem.highCalc = elem.high;
  1195. elem.org_num = elem.num;
  1196. elem.material_detail_org_num = elem.num || 0;
  1197. elem.num =
  1198. ((elem.material_detail_org_num || elem.num) * product_num) | 0;
  1199. elem.material_detail_num = elem.material_detail_org_num * product_num;
  1200. });
  1201. console.log("row :>> ", row);
  1202. measure.forEach((element) => {
  1203. if ((row.long + "").indexOf(element.measureCalc) != -1) {
  1204. if (typeof (element.value * 1) == "number") {
  1205. row.long = row.long.replace(
  1206. new RegExp(element.measureCalc, "g"),
  1207. element.value | ""
  1208. );
  1209. row.long = eval(row.long);
  1210. row.long += "";
  1211. } else {
  1212. row.long = "";
  1213. }
  1214. }
  1215. if ((row.wide + "").indexOf(element.measureCalc) != -1) {
  1216. if (typeof (element.value * 1) == "number") {
  1217. row.wide = row.wide.replace(
  1218. new RegExp(element.measureCalc, "g"),
  1219. element.value | ""
  1220. );
  1221. row.wide = eval(row.wide);
  1222. row.wide += "";
  1223. } else {
  1224. row.wide = "";
  1225. }
  1226. }
  1227. if ((row.high + "").indexOf(element.measureCalc) != -1) {
  1228. if (typeof (element.value * 1) == "number") {
  1229. row.high = row.high.replace(
  1230. new RegExp(element.measureCalc, "g"),
  1231. element.value | ""
  1232. );
  1233. row.high = eval(row.high);
  1234. row.high += "";
  1235. } else {
  1236. row.high = "";
  1237. }
  1238. }
  1239. row.part_detail.forEach((item) => {
  1240. item.num =
  1241. row.material_detail_org_num || item.material_detail_org_num;
  1242. if ((item.long || "").indexOf(element.measureCalc) != -1) {
  1243. if (typeof (element.value * 1) == "number") {
  1244. item.long = item.long.replace(
  1245. new RegExp(element.measureCalc, "g"),
  1246. element.value
  1247. );
  1248. try {
  1249. item.long = eval(item.long);
  1250. item.long += "";
  1251. } catch (error) {
  1252. item.long = "";
  1253. }
  1254. }
  1255. }
  1256. if ((item.wide || "").indexOf(element.measureCalc) != -1) {
  1257. if (typeof (element.value * 1) == "number") {
  1258. item.wide = item.wide.replace(
  1259. new RegExp(element.measureCalc, "g"),
  1260. element.value
  1261. );
  1262. try {
  1263. item.wide = eval(item.wide);
  1264. item.wide += "";
  1265. } catch (error) {
  1266. item.wide = "";
  1267. }
  1268. }
  1269. }
  1270. if ((item.high || "").indexOf(element.measureCalc) != -1) {
  1271. if (typeof (element.value * 1) == "number") {
  1272. item.high = item.high.replace(
  1273. new RegExp(element.measureCalc, "g"),
  1274. element.value
  1275. );
  1276. try {
  1277. item.high = eval(item.high);
  1278. item.high += "";
  1279. } catch (error) {
  1280. item.high = "";
  1281. }
  1282. }
  1283. }
  1284. item.material_detail_list.forEach((it) => {
  1285. it.long = it.long || "0";
  1286. it.wide = it.wide || "0";
  1287. it.high = it.high || "0";
  1288. });
  1289. item.long = item.long || "0";
  1290. item.wide = item.wide || "0";
  1291. item.high = item.high || "0";
  1292. item.material_detail_title = item.material_detail_list[0].title;
  1293. item.material_detail_id =
  1294. item.material_detail_list[0].material_detail_id;
  1295. item.material_detail_org_num = item.num || 0;
  1296. });
  1297. });
  1298. } else {
  1299. row.change_id = "";
  1300. }
  1301. this.$forceUpdate();
  1302. },
  1303. handleExtraAdd(array, type) {
  1304. array.push({
  1305. num: 0,
  1306. price: 0,
  1307. total_price: 0,
  1308. type,
  1309. remark: "",
  1310. title: "",
  1311. id: "",
  1312. is_metal: true,
  1313. });
  1314. this.$forceUpdate();
  1315. },
  1316. handleRemarkCreate(val) {
  1317. this.support_remark.push(val);
  1318. },
  1319. handleProductMeasureChange(e, product, measure_detail) {
  1320. if (e.target.value) {
  1321. let cur_measure = measure_detail.measureCalc;
  1322. let cur_value = measure_detail.value;
  1323. product.over_price = 0;
  1324. //当前测量字段 L W H 修改部件测量字段
  1325. product.part.forEach((element) => {
  1326. console.log("element :>> ", element);
  1327. if (!element.is_metal) {
  1328. element.highCalc = element.highCalc + "";
  1329. element.longCalc = element.longCalc + "";
  1330. element.wideCalc = element.wideCalc + "";
  1331. //处理公式
  1332. if (element.highCalc.indexOf(cur_measure) != -1) {
  1333. element.high = element.highCalc.replace(
  1334. new RegExp(cur_measure, "g"),
  1335. cur_value || ""
  1336. );
  1337. }
  1338. if (element.longCalc.indexOf(cur_measure) != -1) {
  1339. element.long = element.longCalc.replace(
  1340. new RegExp(cur_measure, "g"),
  1341. cur_value || ""
  1342. );
  1343. }
  1344. if (element.wideCalc.indexOf(cur_measure) != -1) {
  1345. element.wide = element.wideCalc.replace(
  1346. new RegExp(cur_measure, "g"),
  1347. cur_value || ""
  1348. );
  1349. }
  1350. //判断测量字段公式中是否还含有字母
  1351. let flag_high = false;
  1352. let flag_long = false;
  1353. let flag_wide = false;
  1354. for (let index = 0; index < product.measure.length; index++) {
  1355. const item = product.measure[index];
  1356. if (element.high.indexOf(item.measureCalc) != -1) {
  1357. flag_high = true;
  1358. }
  1359. if (element.long.indexOf(item.measureCalc) != -1) {
  1360. flag_long = true;
  1361. }
  1362. if (element.wide.indexOf(item.measureCalc) != -1) {
  1363. flag_wide = true;
  1364. }
  1365. }
  1366. if (flag_high) {
  1367. } else {
  1368. element.high = eval(element.high);
  1369. element.high += "";
  1370. }
  1371. if (flag_long) {
  1372. } else {
  1373. element.long = eval(element.long);
  1374. element.long += "";
  1375. }
  1376. if (flag_wide) {
  1377. } else {
  1378. element.wide = eval(element.wide);
  1379. element.wide += "";
  1380. }
  1381. element.part_detail.forEach((elem) => {
  1382. if (!elem.high) {
  1383. } else if (elem.highCalc.indexOf(cur_measure) != -1) {
  1384. elem.high = elem.highCalc.replace(
  1385. new RegExp(cur_measure, "g"),
  1386. cur_value || ""
  1387. );
  1388. }
  1389. if (!elem.long) {
  1390. } else if (elem.longCalc.indexOf(cur_measure) != -1) {
  1391. elem.long = elem.longCalc.replace(
  1392. new RegExp(cur_measure, "g"),
  1393. cur_value || ""
  1394. );
  1395. }
  1396. if (!elem.wide) {
  1397. } else if (elem.wideCalc.indexOf(cur_measure) != -1) {
  1398. elem.wide = elem.wideCalc.replace(
  1399. new RegExp(cur_measure, "g"),
  1400. cur_value || ""
  1401. );
  1402. }
  1403. //判断测量字段公式中是否还含有字母
  1404. let _flag_high = false;
  1405. let _flag_long = false;
  1406. let _flag_wide = false;
  1407. // Number类型无法使用indexOf
  1408. elem.high += "";
  1409. elem.long += "";
  1410. elem.wide += "";
  1411. for (let index = 0; index < product.measure.length; index++) {
  1412. const item = product.measure[index];
  1413. if (!elem.high) {
  1414. } else if (elem.high.indexOf(item.measureCalc) != -1) {
  1415. _flag_high = true;
  1416. }
  1417. if (!elem.long) {
  1418. } else if (elem.long.indexOf(item.measureCalc) != -1) {
  1419. _flag_long = true;
  1420. }
  1421. if (!elem.wide) {
  1422. } else if (elem.wide.indexOf(item.measureCalc) != -1) {
  1423. _flag_wide = true;
  1424. }
  1425. }
  1426. if (_flag_high) {
  1427. } else {
  1428. elem.high = eval(elem.high);
  1429. elem.high += "";
  1430. elem.high == "null" && (elem.high = 0);
  1431. }
  1432. if (_flag_long) {
  1433. } else {
  1434. elem.long = eval(elem.long);
  1435. elem.long += "";
  1436. elem.long == "null" && (elem.long = 0);
  1437. }
  1438. if (_flag_wide) {
  1439. } else {
  1440. elem.wide = eval(elem.wide);
  1441. elem.wide += "";
  1442. elem.wide == "null" && (elem.wide = 0);
  1443. }
  1444. });
  1445. }
  1446. });
  1447. product.part.map((item) => {
  1448. const cur_part = product.overdraft.filter(
  1449. (v) => v.part_id == item.part_id
  1450. );
  1451. cur_part.length > 0 &&
  1452. cur_part.map((element) => {
  1453. // 1 高 2 宽 3 厚
  1454. if (
  1455. element.type == 1 &&
  1456. item.long >= element.min &&
  1457. item.long < element.max
  1458. ) {
  1459. item.formula_temp = element.formula;
  1460. item.formula_temp = item.formula_temp.replace(/H/g, item.long);
  1461. item.formula_temp = item.formula_temp.replace(/W/g, item.wide);
  1462. item.formula_temp = item.formula_temp.replace(/T/g, item.high);
  1463. item.formula_value = eval(item.formula_temp);
  1464. product.over_price += item.formula_value * 1 || 0;
  1465. product.over_price = product.over_price.toFixed(2);
  1466. }
  1467. if (
  1468. element.type == 2 &&
  1469. item.wide >= element.min &&
  1470. item.wide < element.max
  1471. ) {
  1472. item.formula_temp = element.formula;
  1473. item.formula_temp = item.formula_temp.replace(/H/g, item.long);
  1474. item.formula_temp = item.formula_temp.replace(/W/g, item.wide);
  1475. item.formula_temp = item.formula_temp.replace(/T/g, item.high);
  1476. item.formula_value = eval(item.formula_temp);
  1477. product.over_price += item.formula_value * 1 || 0;
  1478. product.over_price = product.over_price.toFixed(2);
  1479. }
  1480. if (
  1481. element.type == 3 &&
  1482. item.high >= element.min &&
  1483. item.high < element.max
  1484. ) {
  1485. item.formula_temp = element.formula;
  1486. item.formula_temp = item.formula_temp.replace(/H/g, item.long);
  1487. item.formula_temp = item.formula_temp.replace(/W/g, item.wide);
  1488. item.formula_temp = item.formula_temp.replace(/T/g, item.high);
  1489. item.formula_value = eval(item.formula_temp);
  1490. product.over_price += item.formula_value * 1 || 0;
  1491. product.over_price = product.over_price.toFixed(2);
  1492. }
  1493. });
  1494. });
  1495. //修改核算数量
  1496. // 如果没有核算数量公式,核算数量取产品数量
  1497. if (product.num_formula == "") {
  1498. product.total_num = product.num;
  1499. } else {
  1500. product.num_formula_temp = product.num_formula;
  1501. product.measure.forEach((element) => {
  1502. if (product.num_formula.indexOf(element.e_title) != -1) {
  1503. product.num_formula_temp = product.num_formula_temp.replace(
  1504. new RegExp(element.e_title, "g"),
  1505. element.value || 0
  1506. );
  1507. }
  1508. });
  1509. product.num = eval(product.num_formula_temp);
  1510. product.num = product.num.toFixed(2);
  1511. product.over_price = product.over_price.toFixed(2);
  1512. product.num_temp_save = product.num;
  1513. product.price =
  1514. (product.unit_price * 1 || 0) * (product.num * 1 || 1) +
  1515. (product.over_price * 1 || 0) +
  1516. (product.ext_price * 1 || 0);
  1517. product.price = product.price.toFixed(2);
  1518. }
  1519. product = this.deepClone(product);
  1520. this.$forceUpdate();
  1521. }
  1522. },
  1523. handleProductMeasureBlur(e, product, measure_detail) {
  1524. this.handleProductMeasureChange(e, product, measure_detail);
  1525. try {
  1526. measure_detail.value = eval(e.target.value);
  1527. } catch (error) {
  1528. console.log("error :>> ", error);
  1529. }
  1530. product.part.map((part) => {
  1531. part.part_detail &&
  1532. part.part_detail.length > 0 &&
  1533. part.part_detail.map((part_detail) => {
  1534. part_detail._longCalc = this.handleCalcPartDetailLong(
  1535. part_detail,
  1536. product
  1537. );
  1538. if (part_detail.material_detail_list.length > 1) {
  1539. try {
  1540. part_detail.longCalcFinal = eval(part_detail._longCalc);
  1541. part_detail.material_detail_id = this.handleFindNearest(
  1542. part_detail.material_detail_list,
  1543. part_detail.longCalcFinal
  1544. );
  1545. } catch (error) {
  1546. console.log("error :>> ", error);
  1547. }
  1548. }
  1549. });
  1550. });
  1551. console.log('product.process :>> ', product.process);
  1552. const process_ids = product.process.map((v) => {
  1553. return v.value;
  1554. });
  1555. this.axios
  1556. .post("/api/process_part_for_product", {
  1557. product_id: product.product_id,
  1558. process_ids,
  1559. })
  1560. .then((res) => {
  1561. for (const key in res.data) {
  1562. const element = res.data[key];
  1563. // 找到部件
  1564. const part_arr = product.part.filter((v) => v.part_id == key);
  1565. if (part_arr.length > 0) {
  1566. for (const k in element) {
  1567. const elem = element[k];
  1568. // 找到零部件
  1569. const part_detail_arr = part_arr[part_arr.length - 1].filter(
  1570. (v) => v.part_detail_id == k
  1571. );
  1572. elem.map((match_item) => {
  1573. const matched_part_detail = part_detail_arr[
  1574. part_detail_arr.length - 1
  1575. ].material_detail_list.filter(
  1576. (v) => v.material_detail_id == match_item.material_detail_id
  1577. );
  1578. if (
  1579. match_item.max > product[match_item.e_title] &&
  1580. match_item.min <= product[match_item.e_title]
  1581. ) {
  1582. part_detail_arr[
  1583. part_detail_arr.length - 1
  1584. ].material_detail_id =
  1585. matched_part_detail[
  1586. matched_part_detail.length - 1
  1587. ].material_detail_id;
  1588. }
  1589. });
  1590. }
  1591. }
  1592. }
  1593. console.log(res);
  1594. });
  1595. this.$forceUpdate();
  1596. },
  1597. handleMaterialChange(val, row) {
  1598. if (val) {
  1599. let tempRow = row.material_detail_list.filter(
  1600. (item) => item.material_detail_id == val
  1601. );
  1602. row.material_detail_title = tempRow[0].title;
  1603. this.$forceUpdate();
  1604. }
  1605. },
  1606. handleProductExt_priceChange(e, product) {
  1607. product.ext_price = e.target.value * 1;
  1608. product.price =
  1609. (product.unit_price * 1 || 0) * (product.num * 1 || 1) +
  1610. (product.over_price * 1 || 0) +
  1611. (product.ext_price * 1 || 0);
  1612. product.price = product.price.toFixed(2);
  1613. this.$forceUpdate();
  1614. },
  1615. handleProductOver_priceChange(e, product) {
  1616. product.over_price = e.target.value;
  1617. product.price =
  1618. (product.unit_price * 1 || 0) * (product.num * 1 || 1) +
  1619. (product.over_price * 1 || 0) +
  1620. (product.ext_price * 1 || 0);
  1621. product.price = product.price.toFixed(2);
  1622. this.$forceUpdate();
  1623. },
  1624. handleRadioClick(row) {
  1625. row.isChoosed = !row.isChoosed;
  1626. this.$forceUpdate();
  1627. },
  1628. handleProductUnit_priceChange(e, product) {
  1629. product.unit_price = e.target.value * 1;
  1630. product.price =
  1631. (product.unit_price * 1 || 0) * (product.num * 1 || 1) +
  1632. (product.over_price * 1 || 0) +
  1633. (product.ext_price * 1 || 0);
  1634. product.price = product.price.toFixed(2);
  1635. this.$forceUpdate();
  1636. },
  1637. handleProductNumChange(e, product) {
  1638. product.part.map((element) => {
  1639. element.part_detail.map((elem) => {
  1640. elem.material_detail_num =
  1641. e.target.value * elem.material_detail_org_num;
  1642. });
  1643. });
  1644. product.total_num = e.target.value;
  1645. product.num = (product.total_num * product.num_temp_save).toFixed(2);
  1646. product.price =
  1647. (product.unit_price * 1 || 0) * (product.num * 1 || 1) +
  1648. (product.over_price * 1 || 0) +
  1649. (product.ext_price * 1 || 0);
  1650. product.price = product.price.toFixed(2);
  1651. this.$forceUpdate();
  1652. },
  1653. handleCalcPartDetailLong(part_detail, product) {
  1654. for (const key in product.measure) {
  1655. const element = product.measure[key];
  1656. if (element.value) {
  1657. part_detail._longCalc = part_detail.longCalc.replace(
  1658. new RegExp(element.e_title, "g"),
  1659. element.value || ""
  1660. );
  1661. }
  1662. }
  1663. try {
  1664. eval(part_detail._longCalc);
  1665. } catch (error) {
  1666. for (const key in product.measure) {
  1667. const element = product.measure[key];
  1668. part_detail._longCalc = part_detail._longCalc.replace(
  1669. new RegExp(element.e_title, "g"),
  1670. element.value || ""
  1671. );
  1672. }
  1673. }
  1674. return part_detail._longCalc;
  1675. },
  1676. handleFindNearest(array, value) {
  1677. const temp = this.deepClone(array);
  1678. temp.sort((a, b) => {
  1679. return Math.abs(a.long - value) - Math.abs(b.long - value);
  1680. });
  1681. return temp[0].material_detail_id;
  1682. },
  1683. handleMetalChange(e, row, n, arr) {
  1684. arr[n].ext_id = e.value;
  1685. arr[n].title = e.label;
  1686. },
  1687. looks(img) {
  1688. const array = [{ img_url: img }];
  1689. this.$previewImg({
  1690. list: array,
  1691. baseUrl: this.$store.state.ip,
  1692. baseImgField: "img_url",
  1693. baseTitleField: "",
  1694. });
  1695. },
  1696. handleExtChange(row, { value, label }, item) {
  1697. row.ext_id = value;
  1698. row.title = label;
  1699. const element = this.extList.filter((item) => item.id == value);
  1700. row.num = element[0].num;
  1701. row.price = element[0].price;
  1702. row.total_price = (row.num * row.price).toFixed(2);
  1703. this.handleTotalPriceCalc(row, item);
  1704. },
  1705. handleTotalPriceCalc(row, item) {
  1706. row.total_price = ((row.price || 0) * (row.num || 0)).toFixed(2);
  1707. let sum2 = 0;
  1708. item.extArray &&
  1709. item.extArray.length > 0 &&
  1710. item.extArray.forEach((element) => {
  1711. sum2 += element.total_price * 1 || 0;
  1712. });
  1713. item.ext_price = sum2 * 1;
  1714. item.price =
  1715. (item.unit_price * 1 || 0) * (item.num * 1 || 1) +
  1716. (item.over_price * 1 || 0) +
  1717. (item.ext_price * 1 || 0);
  1718. item.price = item.price.toFixed(2);
  1719. this.$forceUpdate();
  1720. },
  1721. handleTabsPaneChange(name) {
  1722. this.tempExtArray = this.deepClone(
  1723. this.addProductArray[this.currentTabIndex].extArray
  1724. );
  1725. this.pre_bp_id = this.addProductArray[this.currentTabIndex].bp_id;
  1726. this.currentTabIndex = this.$refs.tabsRef.activeKey;
  1727. this.currencyProduct = this.addProductArray[this.currentTabIndex];
  1728. },
  1729. handleTotalPriceChange(row, item) {
  1730. row.price = (row.total_price / (row.num == 0 ? 1 : row.num)).toFixed(2);
  1731. let sum = 0;
  1732. item.extArray.map((v) => {
  1733. return (sum += v.total_price * 1);
  1734. });
  1735. item.ext_price = sum;
  1736. item.price =
  1737. (item.unit_price * 1 || 0) * (item.num * 1 || 1) +
  1738. (item.over_price * 1 || 0) +
  1739. (item.ext_price * 1 || 0);
  1740. item.price = item.price.toFixed(2);
  1741. this.$forceUpdate();
  1742. },
  1743. then() {
  1744. this.addProductArray[this.currentTabIndex] = this.currencyProduct;
  1745. this.subAddProductData = this.addProductArray.filter((v) => {
  1746. return !v.isdeleted;
  1747. });
  1748. this.$emit("then");
  1749. },
  1750. cancel() {
  1751. this.$emit("cancel");
  1752. },
  1753. deepClone(obj) {
  1754. //定义对象来判断当前的参数是数组还是对象
  1755. let objClone = Array.isArray(obj) ? [] : {};
  1756. //如果obj存在并且为对象
  1757. if (obj && typeof obj == "object") {
  1758. for (let key in obj) {
  1759. if (Object.hasOwnProperty.call(obj, key)) {
  1760. //如果obj的子元素为对象,那么递归(层级遍历)
  1761. if (obj[key] && typeof obj[key] == "object") {
  1762. objClone[key] = this.deepClone(obj[key]);
  1763. } else {
  1764. //如果不是,直接赋值
  1765. objClone[key] = obj[key];
  1766. }
  1767. }
  1768. }
  1769. }
  1770. return objClone;
  1771. },
  1772. },
  1773. // 监听属性 类似于data概念
  1774. computed: {},
  1775. // 监控data中的数据变化
  1776. watch: {},
  1777. beforeCreate() {}, // 生命周期 - 创建之前
  1778. beforeMount() {}, // 生命周期 - 挂载之前
  1779. beforeUpdate() {}, // 生命周期 - 更新之前
  1780. updated() {}, // 生命周期 - 更新之后
  1781. beforeDestroy() {}, // 生命周期 - 销毁之前
  1782. destroyed() {}, // 生命周期 - 销毁完成
  1783. activated() {}, // 如果页面有keep-alive缓存功能,这个函数会触发
  1784. };
  1785. </script>
  1786. <style lang="scss" scoped>
  1787. .modal_product_info {
  1788. background-color: #f5f5f5;
  1789. border-radius: 10px;
  1790. padding: 10px;
  1791. margin-bottom: 10px;
  1792. .modal_product_info_title {
  1793. font-size: 20px;
  1794. font-weight: 700;
  1795. margin-bottom: 10px;
  1796. }
  1797. .modal_product_info_content {
  1798. .part_detail_form {
  1799. /deep/.ivu-form {
  1800. display: flex;
  1801. justify-content: flex-start;
  1802. flex-wrap: wrap;
  1803. }
  1804. /deep/ .ivu-form-item {
  1805. display: inline-block;
  1806. min-width: 150px;
  1807. }
  1808. }
  1809. }
  1810. .hide_part_detail {
  1811. display: none;
  1812. }
  1813. .modal_product {
  1814. /deep/.ivu-form {
  1815. display: flex;
  1816. justify-content: flex-start;
  1817. flex-wrap: wrap;
  1818. }
  1819. /deep/ .ivu-form-item {
  1820. display: inline-block;
  1821. min-width: 200px;
  1822. }
  1823. }
  1824. .modal_parts {
  1825. /deep/.ivu-form {
  1826. display: flex;
  1827. justify-content: flex-start;
  1828. flex-wrap: wrap;
  1829. }
  1830. /deep/ .ivu-form-item {
  1831. display: inline-block;
  1832. min-width: 30px;
  1833. }
  1834. }
  1835. .modal_extra {
  1836. /deep/.ivu-form {
  1837. display: flex;
  1838. justify-content: flex-start;
  1839. flex-wrap: wrap;
  1840. }
  1841. /deep/ .ivu-form-item {
  1842. display: inline-block;
  1843. min-width: 100px;
  1844. }
  1845. }
  1846. }
  1847. .product-img {
  1848. padding-top: 10px;
  1849. }
  1850. .product-add {
  1851. padding: 10px 0;
  1852. display: flex;
  1853. flex-wrap: wrap;
  1854. .ipt {
  1855. position: absolute;
  1856. width: 100%;
  1857. height: 100%;
  1858. opacity: 0;
  1859. cursor: pointer;
  1860. outline: none;
  1861. top: 0;
  1862. left: 0;
  1863. }
  1864. .add-items {
  1865. width: 80px;
  1866. height: 80px;
  1867. border: 1px dotted #e7e7e7;
  1868. border-radius: 5px;
  1869. display: flex;
  1870. justify-content: center;
  1871. align-items: center;
  1872. overflow: hidden;
  1873. position: relative;
  1874. flex-direction: column;
  1875. background: #f4f5f7;
  1876. .item {
  1877. width: 46px;
  1878. height: 46px;
  1879. background: #3764ff;
  1880. opacity: 0.6;
  1881. display: flex;
  1882. justify-content: center;
  1883. align-items: center;
  1884. border-radius: 50%;
  1885. color: #fff;
  1886. }
  1887. }
  1888. .items {
  1889. width: 80px;
  1890. height: 80px;
  1891. margin-bottom: 10px;
  1892. display: flex;
  1893. justify-content: center;
  1894. align-items: center;
  1895. background: #e7e7e7;
  1896. margin-right: 10px;
  1897. border-radius: 5px;
  1898. position: relative;
  1899. img {
  1900. max-width: 70px;
  1901. max-height: 70px;
  1902. }
  1903. }
  1904. }
  1905. </style>