info.vue 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833
  1. <template>
  2. <div class="component-edit-indent-info">
  3. <el-dialog
  4. v-model="show"
  5. class="custom-edit-indent-info-dialog"
  6. :title="visible === 1 ? '录入报价信息' : '录入报价信息'"
  7. :close-on-click-modal="false"
  8. :close-on-press-escape="false"
  9. :before-close="close"
  10. width="1300px"
  11. >
  12. <div style="color: #ef4135">* 为了报价单的内容,请填写英文信息</div>
  13. <div
  14. class="form-table"
  15. v-loading="loading"
  16. >
  17. <div class="flex items-stretch form-header">
  18. <div class="first-label"></div>
  19. <div class="second-label">操作</div>
  20. <div
  21. v-for="(item, index) in forms"
  22. :key="index"
  23. class="input-area flex justify-center items-center"
  24. >
  25. <el-button
  26. v-show="forms.length > 1"
  27. size="small"
  28. type="danger"
  29. link
  30. plain
  31. @click="deleteForm(index)"
  32. >
  33. {{ $t('btn_delete') }}
  34. </el-button>
  35. </div>
  36. </div>
  37. <div class="flex items-stretch">
  38. <div class="first-label flex justify-center items-center">
  39. {{ $t(prefix + 'label_supplier') }}
  40. </div>
  41. <div class="flex flex-col items-stretch">
  42. <div class="flex items-center">
  43. <div class="second-label required">
  44. {{ $t(prefix + 'label_company_name') }}
  45. </div>
  46. <el-form
  47. v-for="(item, index) in forms"
  48. :ref="($e) => getFormRef($e, `vendor_id_${index}`)"
  49. :key="index"
  50. :show-message="false"
  51. :model="item"
  52. >
  53. <div class="input-area">
  54. <el-form-item
  55. prop="vendor_id"
  56. :rules="{ required: true, validator: commonCheck }"
  57. >
  58. <div class="flex w-[100%] pr-3">
  59. <el-select
  60. v-model="item.vendor_id"
  61. :remote-method="($e: any) => queryVenderList($e, index)"
  62. filterable
  63. remote
  64. style="width: 100%"
  65. placeholder="请选择供应商"
  66. @change="($e) => changeVenderSelect($e, index)"
  67. >
  68. <!-- allow-create -->
  69. <el-option
  70. v-for="(option, subIndex) in vendorList[index]"
  71. :key="option.id || subIndex"
  72. :value="option.id"
  73. :label="option.name"
  74. ></el-option>
  75. </el-select>
  76. <el-button @click="copyValue(item.vendor_name, $event)">
  77. copy
  78. </el-button>
  79. </div>
  80. </el-form-item>
  81. <div
  82. v-if="index < forms.length - 1"
  83. class="btn-copy"
  84. @click.self="commonCopyFormItem(index, 'vendor_id')"
  85. >
  86. &gt;&gt;&gt;
  87. </div>
  88. </div>
  89. </el-form>
  90. </div>
  91. <div class="flex items-stretch">
  92. <div class="second-label">
  93. {{ $t(prefix + 'label_supplier_type') }}
  94. </div>
  95. <div
  96. v-for="(item, index) in forms"
  97. :key="index"
  98. class="input-area"
  99. >
  100. <el-input
  101. v-model="item.vendor_type"
  102. placeholder="请输入供应商类型"
  103. ></el-input>
  104. <div
  105. v-if="index < forms.length - 1"
  106. class="btn-copy"
  107. @click.self="commonCopyFormItem(index, 'vendor_type')"
  108. >
  109. &gt;&gt;&gt;
  110. </div>
  111. </div>
  112. </div>
  113. <div class="flex items-stretch">
  114. <div class="second-label">
  115. {{ $t(prefix + 'label_wangwang_year') }}
  116. </div>
  117. <div
  118. v-for="(item, index) in forms"
  119. :key="index"
  120. class="input-area"
  121. >
  122. <el-input
  123. v-model="item.vendor_wangwang_old"
  124. placeholder="请输入旺旺年份"
  125. ></el-input>
  126. <div
  127. v-if="index < forms.length - 1"
  128. class="btn-copy"
  129. @click.self="commonCopyFormItem(index, 'vendor_wangwang_old')"
  130. >
  131. &gt;&gt;&gt;
  132. </div>
  133. </div>
  134. </div>
  135. <div class="flex items-stretch">
  136. <div class="second-label">
  137. {{ $t(prefix + 'label_contact') }}
  138. </div>
  139. <div
  140. v-for="(item, index) in forms"
  141. :key="index"
  142. class="input-area"
  143. >
  144. <el-input
  145. v-model="item.vendor_contact"
  146. placeholder="请输入联系人"
  147. ></el-input>
  148. <div
  149. v-if="index < forms.length - 1"
  150. class="btn-copy"
  151. @click.self="commonCopyFormItem(index, 'vendor_contact')"
  152. >
  153. &gt;&gt;&gt;
  154. </div>
  155. </div>
  156. </div>
  157. <div class="flex items-stretch">
  158. <div class="second-label">
  159. {{ $t(prefix + 'label_phone') }}
  160. </div>
  161. <div
  162. v-for="(item, index) in forms"
  163. :key="index"
  164. class="input-area"
  165. >
  166. <el-input
  167. v-model="item.vendor_phone"
  168. placeholder="请输入电话"
  169. ></el-input>
  170. <div
  171. v-if="index < forms.length - 1"
  172. class="btn-copy"
  173. @click.self="commonCopyFormItem(index, 'vendor_phone')"
  174. >
  175. &gt;&gt;&gt;
  176. </div>
  177. </div>
  178. </div>
  179. <div class="flex items-stretch">
  180. <div class="second-label">
  181. {{ $t(prefix + 'label_cert') }}
  182. </div>
  183. <div
  184. v-for="(item, index) in forms"
  185. :key="index"
  186. class="input-area"
  187. >
  188. <el-input
  189. v-model="item.cert"
  190. placeholder="证书"
  191. ></el-input>
  192. <div
  193. v-if="index < forms.length - 1"
  194. class="btn-copy"
  195. @click.self="commonCopyFormItem(index, 'cert')"
  196. >
  197. &gt;&gt;&gt;
  198. </div>
  199. </div>
  200. </div>
  201. </div>
  202. </div>
  203. <div class="flex items-stretch">
  204. <div class="first-label flex justify-center items-center">
  205. {{ $t(prefix + 'label_product_info') }}
  206. </div>
  207. <div class="flex flex-col items-stretch">
  208. <div class="flex items-stretch">
  209. <div class="second-label required">
  210. {{ $t(prefix + 'label_product_name') }}
  211. </div>
  212. <el-form
  213. v-for="(item, index) in forms"
  214. :ref="($e) => getFormRef($e, `product_name_${index}`)"
  215. :key="index"
  216. :show-message="false"
  217. :model="item"
  218. >
  219. <div class="input-area">
  220. <el-form-item
  221. prop="product_name"
  222. :rules="{
  223. required: true,
  224. trigger: 'change',
  225. validator: commonCheck,
  226. }"
  227. >
  228. <el-input
  229. v-model="item.product_name"
  230. placeholder="请输入产品名称"
  231. @input="
  232. ($e) => inputFilter($e, forms[index], 'product_name')
  233. "
  234. ></el-input>
  235. </el-form-item>
  236. <div
  237. v-if="index < forms.length - 1"
  238. class="btn-copy"
  239. @click.self="commonCopyFormItem(index, 'product_name')"
  240. >
  241. &gt;&gt;&gt;
  242. </div>
  243. </div>
  244. </el-form>
  245. </div>
  246. <div class="flex items-stretch">
  247. <div class="second-label">
  248. {{ $t(prefix + 'label_product_url') }}
  249. </div>
  250. <div
  251. v-for="(item, index) in forms"
  252. :key="index"
  253. class="input-area"
  254. >
  255. <el-input
  256. v-model="item.product_url"
  257. placeholder="请输入产品链接"
  258. @input="($e) => inputFilter($e, forms[index], 'product_url')"
  259. ></el-input>
  260. <div
  261. v-if="index < forms.length - 1"
  262. class="btn-copy"
  263. @click.self="commonCopyFormItem(index, 'product_url')"
  264. >
  265. &gt;&gt;&gt;
  266. </div>
  267. </div>
  268. </div>
  269. <div class="flex items-stretch">
  270. <div class="second-label">
  271. {{ $t(prefix + 'label_product_image') }}
  272. </div>
  273. <div
  274. v-for="(item, index) in forms"
  275. :key="index"
  276. class="input-area"
  277. >
  278. <image-upload
  279. v-model:list="productImageList[index]"
  280. width="100px"
  281. height="100px"
  282. :disable-preview="false"
  283. ></image-upload>
  284. <div
  285. v-if="index < forms.length - 1"
  286. class="btn-copy"
  287. @click.self="commonCopyFormItem(index, 'productImageList')"
  288. >
  289. &gt;&gt;&gt;
  290. </div>
  291. </div>
  292. </div>
  293. <div class="flex items-stretch">
  294. <div class="second-label">
  295. {{ $t(prefix + 'label_size') }}
  296. </div>
  297. <div
  298. v-for="(item, index) in forms"
  299. :key="index"
  300. class="input-area"
  301. >
  302. <el-input
  303. v-model="item.product_size"
  304. placeholder="请输入尺寸"
  305. @input="($e) => inputFilter($e, forms[index], 'product_size')"
  306. ></el-input>
  307. <div
  308. v-if="index < forms.length - 1"
  309. class="btn-copy"
  310. @click.self="commonCopyFormItem(index, 'product_size')"
  311. >
  312. &gt;&gt;&gt;
  313. </div>
  314. </div>
  315. </div>
  316. <div class="flex items-stretch">
  317. <div class="second-label">
  318. {{ $t(prefix + 'label_product_hd') }}
  319. </div>
  320. <div
  321. v-for="(item, index) in forms"
  322. :key="index"
  323. class="input-area"
  324. >
  325. <el-input
  326. v-model="item.product_hd"
  327. placeholder="请输入厚度"
  328. @input="($e) => inputFilter($e, forms[index], 'product_hd')"
  329. ></el-input>
  330. <div
  331. v-if="index < forms.length - 1"
  332. class="btn-copy"
  333. @click.self="commonCopyFormItem(index, 'product_hd')"
  334. >
  335. &gt;&gt;&gt;
  336. </div>
  337. </div>
  338. </div>
  339. <div class="flex items-stretch">
  340. <div class="second-label">
  341. {{ $t(prefix + 'label_capacity') }}
  342. </div>
  343. <div
  344. v-for="(item, index) in forms"
  345. :key="index"
  346. class="input-area"
  347. >
  348. <el-input
  349. v-model="item.product_capacity"
  350. placeholder="请输入容量"
  351. @input="
  352. ($e) => inputFilter($e, forms[index], 'product_capacity')
  353. "
  354. ></el-input>
  355. <div
  356. v-if="index < forms.length - 1"
  357. class="btn-copy"
  358. @click.self="commonCopyFormItem(index, 'product_capacity')"
  359. >
  360. &gt;&gt;&gt;
  361. </div>
  362. </div>
  363. </div>
  364. <div class="flex items-stretch">
  365. <div class="second-label">
  366. {{ $t(prefix + 'label_material') }}
  367. </div>
  368. <div
  369. v-for="(item, index) in forms"
  370. :key="index"
  371. class="input-area"
  372. >
  373. <el-input
  374. v-model="item.product_material"
  375. placeholder="请输入材质"
  376. @input="
  377. ($e) => inputFilter($e, forms[index], 'product_material')
  378. "
  379. ></el-input>
  380. <div
  381. v-if="index < forms.length - 1"
  382. class="btn-copy"
  383. @click.self="commonCopyFormItem(index, 'product_material')"
  384. >
  385. &gt;&gt;&gt;
  386. </div>
  387. </div>
  388. </div>
  389. <div class="flex items-stretch">
  390. <div class="second-label">
  391. {{ $t(prefix + 'label_battery') }}
  392. </div>
  393. <div
  394. v-for="(item, index) in forms"
  395. :key="index"
  396. class="input-area"
  397. >
  398. <el-input
  399. v-model="item.product_battery"
  400. placeholder="是否带电池"
  401. @input="
  402. ($e) => inputFilter($e, forms[index], 'product_battery')
  403. "
  404. ></el-input>
  405. <div
  406. v-if="index < forms.length - 1"
  407. class="btn-copy"
  408. @click.self="commonCopyFormItem(index, 'product_battery')"
  409. >
  410. &gt;&gt;&gt;
  411. </div>
  412. </div>
  413. </div>
  414. <div class="flex items-stretch">
  415. <div class="second-label">
  416. {{ $t(prefix + 'label_print_require') }}
  417. </div>
  418. <div
  419. v-for="(item, index) in forms"
  420. :key="index"
  421. class="input-area"
  422. >
  423. <el-input
  424. v-model="item.product_require_print"
  425. placeholder="请输入要求"
  426. @input="
  427. ($e) =>
  428. inputFilter($e, forms[index], 'product_require_print')
  429. "
  430. ></el-input>
  431. <div
  432. v-if="index < forms.length - 1"
  433. class="btn-copy"
  434. @click.self="
  435. commonCopyFormItem(index, 'product_require_print')
  436. "
  437. >
  438. &gt;&gt;&gt;
  439. </div>
  440. </div>
  441. </div>
  442. <div class="flex items-stretch">
  443. <div class="second-label">
  444. {{ $t(prefix + 'label_color') }}
  445. </div>
  446. <div
  447. v-for="(item, index) in forms"
  448. :key="index"
  449. class="input-area"
  450. >
  451. <el-input
  452. v-model="item.product_color"
  453. placeholder="请输入颜色"
  454. @input="
  455. ($e) => inputFilter($e, forms[index], 'product_color')
  456. "
  457. ></el-input>
  458. <div
  459. v-if="index < forms.length - 1"
  460. class="btn-copy"
  461. @click.self="commonCopyFormItem(index, 'product_color')"
  462. >
  463. &gt;&gt;&gt;
  464. </div>
  465. </div>
  466. </div>
  467. <div class="flex items-stretch">
  468. <div class="second-label">
  469. {{ $t(prefix + 'label_color_require') }}
  470. </div>
  471. <div
  472. v-for="(item, index) in forms"
  473. :key="index"
  474. class="input-area"
  475. >
  476. <el-input
  477. v-model="item.product_require_color"
  478. placeholder="请输入颜色定制要求"
  479. @input="
  480. ($e) =>
  481. inputFilter($e, forms[index], 'product_require_color')
  482. "
  483. ></el-input>
  484. <div
  485. v-if="index < forms.length - 1"
  486. class="btn-copy"
  487. @click.self="
  488. commonCopyFormItem(index, 'product_require_color')
  489. "
  490. >
  491. &gt;&gt;&gt;
  492. </div>
  493. </div>
  494. </div>
  495. <div class="flex items-stretch">
  496. <div class="second-label">
  497. {{ $t(prefix + 'label_other') }}
  498. </div>
  499. <div
  500. v-for="(item, index) in forms"
  501. :key="index"
  502. class="input-area"
  503. >
  504. <el-input
  505. v-model="item.product_other"
  506. placeholder="其他信息"
  507. type="textarea"
  508. :rows="3"
  509. @input="
  510. ($e) => inputFilter($e, forms[index], 'product_other')
  511. "
  512. ></el-input>
  513. <div
  514. v-if="index < forms.length - 1"
  515. class="btn-copy"
  516. @click.self="commonCopyFormItem(index, 'product_other')"
  517. >
  518. &gt;&gt;&gt;
  519. </div>
  520. </div>
  521. </div>
  522. </div>
  523. </div>
  524. <div class="flex items-stretch">
  525. <div class="first-label flex justify-center items-center">
  526. {{ $t(prefix + 'label_factory_price') }}
  527. </div>
  528. <div class="flex flex-col items-stretch">
  529. <div class="flex items-stretch">
  530. <div class="second-label required">
  531. {{ $t(prefix + 'label_number_table') }}
  532. </div>
  533. <el-form
  534. v-for="(item, index) in forms"
  535. :ref="($e) => getFormRef($e, `number_${index}`)"
  536. :key="index"
  537. :show-message="false"
  538. :model="item"
  539. >
  540. <div class="input-area">
  541. <div class="sub-table">
  542. <div class="sub-table-head flex items-center">
  543. <div class="sub-table-number">数量</div>
  544. <div class="sub-table-price">单价(RMB)</div>
  545. <div class="sub-table-days">天数</div>
  546. </div>
  547. <div
  548. v-for="(i, subIndex) in item.number"
  549. :key="subIndex"
  550. class="sub-table-row flex items-center"
  551. >
  552. <div class="sub-table-number">
  553. <el-form-item
  554. :prop="'number.' + subIndex"
  555. :rules="{
  556. required: true,
  557. validator: commonCheck,
  558. }"
  559. >
  560. <el-input v-model="item.number[subIndex]"></el-input>
  561. </el-form-item>
  562. </div>
  563. <div class="sub-table-price">
  564. <el-form-item
  565. :prop="'price.' + subIndex"
  566. :rules="{
  567. required: true,
  568. validator: commonCheck,
  569. }"
  570. >
  571. <el-input v-model="item.price[subIndex]"></el-input>
  572. </el-form-item>
  573. </div>
  574. <div class="sub-table-days">
  575. <el-form-item
  576. :prop="'days.' + subIndex"
  577. :rules="{
  578. required: true,
  579. validator: commonCheck,
  580. }"
  581. >
  582. <el-input v-model="item.days[subIndex]"></el-input>
  583. </el-form-item>
  584. </div>
  585. <div class="sub-table-btn-delete">
  586. <div
  587. v-show="item.number.length > 1"
  588. @click="numberTableDeleteRow(index, subIndex)"
  589. >
  590. <el-icon size="18">
  591. <CircleCloseFilled></CircleCloseFilled>
  592. </el-icon>
  593. </div>
  594. </div>
  595. </div>
  596. </div>
  597. <div class="sub-table-btn-add">
  598. <el-button
  599. size="small"
  600. @click="numberTableAddRow(index)"
  601. >
  602. + 添加价格信息
  603. </el-button>
  604. </div>
  605. <div
  606. v-if="index < forms.length - 1"
  607. class="btn-copy"
  608. style="bottom: 4px; top: unset"
  609. @click.self="commonCopyFormItem(index, 'numberItem')"
  610. >
  611. &gt;&gt;&gt;
  612. </div>
  613. </div>
  614. </el-form>
  615. </div>
  616. <div class="flex items-stretch">
  617. <div class="second-label required">
  618. {{ $t(prefix + 'label_extra_fee') }}
  619. </div>
  620. <el-form
  621. v-for="(item, index) in forms"
  622. :ref="($e) => getFormRef($e, `cost_${index}`)"
  623. :key="index"
  624. :show-message="false"
  625. :model="item"
  626. >
  627. <div class="input-area">
  628. <div class="sub-table">
  629. <div class="sub-table-head flex items-center">
  630. <div class="sub-table-cost-name">项目</div>
  631. <div class="sub-table-cost-price">价格(RMB)</div>
  632. </div>
  633. <div
  634. v-for="(i, subIndex) in item.cost_name"
  635. :key="subIndex"
  636. class="sub-table-row flex items-center"
  637. >
  638. <div class="sub-table-cost-name">
  639. <el-form-item
  640. :prop="'cost_name.' + subIndex"
  641. :rules="{
  642. required: true,
  643. validator: commonCheck,
  644. }"
  645. >
  646. <el-select
  647. v-model="item.cost_name[subIndex]"
  648. size="small"
  649. >
  650. <el-option
  651. v-for="option in costOptions"
  652. :key="option.label"
  653. :label="option.label"
  654. :value="option.value"
  655. ></el-option>
  656. </el-select>
  657. </el-form-item>
  658. </div>
  659. <div class="sub-table-cost-price">
  660. <el-form-item
  661. :prop="'cost_price.' + subIndex"
  662. :rules="{
  663. required: true,
  664. validator: commonCheck,
  665. }"
  666. >
  667. <el-input
  668. v-model="item.cost_price[subIndex]"
  669. ></el-input>
  670. </el-form-item>
  671. </div>
  672. <div class="sub-table-btn-delete">
  673. <el-button
  674. :disabled="item.cost_name.length < 2"
  675. type="danger"
  676. size="small"
  677. plain
  678. @click="costTableDeleteRow(index, subIndex)"
  679. >
  680. {{ $t('btn_delete') }}
  681. </el-button>
  682. </div>
  683. </div>
  684. </div>
  685. <div class="sub-table-btn-add">
  686. <el-button
  687. size="small"
  688. @click="costTableAddRow(index)"
  689. >
  690. + 添加价格信息
  691. </el-button>
  692. </div>
  693. <div
  694. v-if="index < forms.length - 1"
  695. class="btn-copy"
  696. style="bottom: 4px; top: unset"
  697. @click.self="commonCopyFormItem(index, 'cost')"
  698. >
  699. &gt;&gt;&gt;
  700. </div>
  701. </div>
  702. </el-form>
  703. </div>
  704. </div>
  705. </div>
  706. <div class="flex items-stretch">
  707. <div class="first-label flex justify-center items-center">
  708. {{ $t(prefix + 'label_package_info') }}
  709. </div>
  710. <div class="flex flex-col items-stretch">
  711. <div class="flex items-stretch">
  712. <div class="second-label">
  713. {{ $t(prefix + 'label_package') }}
  714. </div>
  715. <div
  716. v-for="(item, index) in forms"
  717. :key="index"
  718. class="input-area"
  719. >
  720. <el-input
  721. v-model="item.package_info"
  722. placeholder="请输入产品包装信息"
  723. ></el-input>
  724. <div
  725. v-if="index < forms.length - 1"
  726. class="btn-copy"
  727. @click.self="commonCopyFormItem(index, 'package_info')"
  728. >
  729. &gt;&gt;&gt;
  730. </div>
  731. </div>
  732. </div>
  733. <div class="flex flex-col items-stretch">
  734. <div class="flex items-stretch">
  735. <div class="second-label required">
  736. {{ $t(prefix + 'label_gross_weight') }}(KG)
  737. </div>
  738. <el-form
  739. v-for="(item, index) in forms"
  740. :ref="($e) => getFormRef($e, `package_weight_${index}`)"
  741. :key="index"
  742. :show-message="false"
  743. :model="item"
  744. >
  745. <div class="input-area">
  746. <el-form-item
  747. prop="package_weight"
  748. :rules="{ required: true, validator: commonCheck }"
  749. >
  750. <el-input
  751. v-model="item.package_weight"
  752. placeholder="请输入每箱毛重"
  753. ></el-input>
  754. </el-form-item>
  755. <div
  756. v-if="index < forms.length - 1"
  757. class="btn-copy"
  758. @click.self="commonCopyFormItem(index, 'package_weight')"
  759. >
  760. &gt;&gt;&gt;
  761. </div>
  762. </div>
  763. </el-form>
  764. </div>
  765. <div class="flex items-stretch">
  766. <div class="second-label required">
  767. {{ $t(prefix + 'label_package_size') }}(CM)
  768. </div>
  769. <el-form
  770. v-for="(item, index) in forms"
  771. :ref="($e) => getFormRef($e, `package_size_${index}`)"
  772. :key="index"
  773. :show-message="false"
  774. :model="item"
  775. >
  776. <div class="input-area flex justify-center items-center">
  777. <el-form-item
  778. prop="package_size_length"
  779. :rules="{
  780. required: true,
  781. trigger: 'change',
  782. validator: commonCheck,
  783. }"
  784. >
  785. <el-input
  786. v-model="item.package_size_length"
  787. style="width: 74px"
  788. placeholder="长"
  789. ></el-input>
  790. </el-form-item>
  791. <el-icon size="18">
  792. <Close></Close>
  793. </el-icon>
  794. <el-form-item
  795. prop="package_size_width"
  796. :rules="{
  797. required: true,
  798. trigger: 'change',
  799. validator: commonCheck,
  800. }"
  801. >
  802. <el-input
  803. v-model="item.package_size_width"
  804. style="width: 74px"
  805. placeholder="宽"
  806. ></el-input>
  807. </el-form-item>
  808. <el-icon size="18">
  809. <Close></Close>
  810. </el-icon>
  811. <el-form-item
  812. prop="package_size_height"
  813. :rules="{
  814. required: true,
  815. trigger: 'change',
  816. validator: commonCheck,
  817. }"
  818. >
  819. <el-input
  820. v-model="item.package_size_height"
  821. style="width: 74px"
  822. placeholder="高"
  823. ></el-input>
  824. </el-form-item>
  825. <span>&nbsp;CM</span>
  826. <div
  827. v-if="index < forms.length - 1"
  828. class="btn-copy"
  829. @click.self="commonCopyFormItem(index, 'package_size')"
  830. >
  831. &gt;&gt;&gt;
  832. </div>
  833. </div>
  834. </el-form>
  835. </div>
  836. <div class="flex items-stretch">
  837. <div class="second-label required">
  838. {{ $t(prefix + 'label_pcs') }}(PCS)
  839. </div>
  840. <el-form
  841. v-for="(item, index) in forms"
  842. :ref="($e) => getFormRef($e, `in_package_${index}`)"
  843. :key="index"
  844. :show-message="false"
  845. :model="item"
  846. >
  847. <div class="input-area">
  848. <el-form-item
  849. prop="in_package"
  850. :rules="{
  851. required: true,
  852. trigger: 'change',
  853. validator: commonCheck,
  854. }"
  855. >
  856. <el-input
  857. v-model="item.in_package"
  858. placeholder="PCS"
  859. ></el-input>
  860. </el-form-item>
  861. <div
  862. v-if="index < forms.length - 1"
  863. class="btn-copy"
  864. @click.self="commonCopyFormItem(index, 'in_package')"
  865. >
  866. &gt;&gt;&gt;
  867. </div>
  868. </div>
  869. </el-form>
  870. </div>
  871. </div>
  872. </div>
  873. </div>
  874. <div class="flex items-stretch">
  875. <div class="first-label flex justify-center items-center">
  876. {{ $t(prefix + 'label_example') }}
  877. </div>
  878. <div class="flex flex-col items-stretch">
  879. <div class="flex items-stretch">
  880. <div class="second-label required">
  881. {{ $t(prefix + 'label_example_days') }}(Days)
  882. </div>
  883. <el-form
  884. v-for="(item, index) in forms"
  885. :ref="($e) => getFormRef($e, `demo_days_${index}`)"
  886. :key="index"
  887. :show-message="false"
  888. :model="item"
  889. >
  890. <div class="input-area">
  891. <el-form-item
  892. prop="demo_days"
  893. :rules="{
  894. required: true,
  895. trigger: 'change',
  896. validator: commonCheck,
  897. }"
  898. >
  899. <el-input
  900. v-model="item.demo_days"
  901. placeholder="天数"
  902. ></el-input>
  903. </el-form-item>
  904. <div
  905. v-if="index < forms.length - 1"
  906. class="btn-copy"
  907. @click.self="commonCopyFormItem(index, 'demo_days')"
  908. >
  909. &gt;&gt;&gt;
  910. </div>
  911. </div>
  912. </el-form>
  913. </div>
  914. <div class="flex items-stretch">
  915. <div class="second-label">
  916. {{ $t(prefix + 'label_example_cost') }}(¥)
  917. </div>
  918. <div
  919. v-for="(item, index) in forms"
  920. :key="index"
  921. class="input-area"
  922. >
  923. <el-input
  924. v-model="item.demo_cost"
  925. placeholder="请输入打样费用"
  926. ></el-input>
  927. <div
  928. v-if="index < forms.length - 1"
  929. class="btn-copy"
  930. @click.self="commonCopyFormItem(index, 'demo_cost')"
  931. >
  932. &gt;&gt;&gt;
  933. </div>
  934. </div>
  935. </div>
  936. <div class="flex items-stretch">
  937. <div class="second-label">
  938. {{ $t(prefix + 'label_can_refund') }}
  939. </div>
  940. <div
  941. v-for="(item, index) in forms"
  942. :key="index"
  943. class="input-area"
  944. >
  945. <el-input
  946. v-model="item.demo_return"
  947. placeholder="请输入退费信息"
  948. ></el-input>
  949. <div
  950. v-if="index < forms.length - 1"
  951. class="btn-copy"
  952. @click.self="commonCopyFormItem(index, 'demo_return')"
  953. >
  954. &gt;&gt;&gt;
  955. </div>
  956. </div>
  957. </div>
  958. </div>
  959. </div>
  960. <div class="flex items-stretch">
  961. <div class="first-label flex justify-center items-center"></div>
  962. <div class="flex flex-col items-stretch">
  963. <div class="flex items-stretch">
  964. <div class="second-label">
  965. {{ $t(prefix + 'label_comment') }}
  966. </div>
  967. <div
  968. v-for="(item, index) in forms"
  969. :key="index"
  970. class="input-area"
  971. >
  972. <el-input
  973. v-model="item.notes"
  974. placeholder="请输入内容"
  975. type="textarea"
  976. :rows="3"
  977. ></el-input>
  978. <div
  979. v-if="index < forms.length - 1"
  980. class="btn-copy"
  981. @click.self="commonCopyFormItem(index, 'notes')"
  982. >
  983. &gt;&gt;&gt;
  984. </div>
  985. </div>
  986. </div>
  987. </div>
  988. </div>
  989. </div>
  990. <div
  991. v-show="canAddForm"
  992. v-loading="loading"
  993. class="btn-add-indent-info flex justify-center flex-col items-center"
  994. @click="addFormColumn"
  995. >
  996. <el-icon
  997. size="42"
  998. class="el-icon-circle-plus-outline"
  999. >
  1000. <CirclePlus></CirclePlus>
  1001. </el-icon>
  1002. <div>
  1003. {{ $t(prefix + 'btn_add_info') }}
  1004. </div>
  1005. </div>
  1006. <template #footer>
  1007. <div class="flex justify-center items-center">
  1008. <!-- v-show="$showAuthBtn(429)" -->
  1009. <el-button
  1010. :loading="loading"
  1011. type="primary"
  1012. size="small"
  1013. @click="checkForm"
  1014. >
  1015. {{ $t('btn_save') }}
  1016. </el-button>
  1017. <el-button
  1018. :loading="loading"
  1019. size="small"
  1020. @click="close"
  1021. >
  1022. {{ $t('btn_close') }}
  1023. </el-button>
  1024. </div>
  1025. </template>
  1026. </el-dialog>
  1027. </div>
  1028. </template>
  1029. <script lang="ts" setup>
  1030. import { defineComponent, ref, watch, computed, nextTick, inject } from 'vue'
  1031. import {
  1032. ElButton,
  1033. ElForm,
  1034. ElFormItem,
  1035. ElInput,
  1036. ElSelect,
  1037. ElOption,
  1038. ElDialog,
  1039. ElNotification,
  1040. ElMessage,
  1041. ElIcon,
  1042. ElMessageBox,
  1043. } from 'element-plus'
  1044. import { CirclePlus, Close, CircleCloseFilled } from '@element-plus/icons-vue'
  1045. import debounce from 'lodash.debounce'
  1046. import cloneDeep from 'lodash.clonedeep'
  1047. import Clipboard from 'clipboard'
  1048. import { $t } from '@/i18n/index'
  1049. import imageUpload from '@/components/ImageUpload.vue'
  1050. // 用来对oss的图片、视频等媒体数据的url进行匹配替换
  1051. import { getVendorList, createQuote, deleteIndent } from '@/api/indent'
  1052. import userAPI from '@/api/user'
  1053. defineComponent({
  1054. name: 'EditInfo',
  1055. })
  1056. const $emit = defineEmits(['update:visible', 'create'])
  1057. const {
  1058. visible = 0,
  1059. alreadyHasIndentCount = 0,
  1060. parentId = 0,
  1061. dataForEdit = [],
  1062. defaultName = '',
  1063. defaultSku = {},
  1064. } = defineProps<{
  1065. visible: number
  1066. alreadyHasIndentCount?: number
  1067. parentId?: number | string
  1068. dataForEdit?: any[]
  1069. defaultName?: string
  1070. defaultSku?: { [x: string]: any }
  1071. }>()
  1072. const $mediaRegExp = inject('mediaRegExp') as RegExp
  1073. const prefix = 'order.indent_edit_info.'
  1074. const show = ref(false)
  1075. const costOptions = [
  1076. {
  1077. label: $t('text_please_select'),
  1078. value: '',
  1079. },
  1080. {
  1081. label: '样品费用',
  1082. value: '样品费用',
  1083. },
  1084. {
  1085. label: '印刷费用',
  1086. value: '印刷费用',
  1087. },
  1088. {
  1089. label: '模具费用',
  1090. value: '模具费用',
  1091. },
  1092. {
  1093. label: '制版费用',
  1094. value: '制版费用',
  1095. },
  1096. {
  1097. label: '染色费用',
  1098. value: '染色费用',
  1099. },
  1100. {
  1101. label: '其他费用',
  1102. value: '其他费用',
  1103. },
  1104. ]
  1105. const formDemo = {
  1106. // 供应商
  1107. vendor_name: '',
  1108. vendor_id: '',
  1109. vendor_type: '',
  1110. vendor_wangwang_old: '',
  1111. vendor_contact: '',
  1112. vendor_phone: '',
  1113. // 产品信息
  1114. product_name: '',
  1115. product_url: '',
  1116. product_image: '',
  1117. product_size: '',
  1118. product_hd: '',
  1119. product_capacity: '',
  1120. product_material: '',
  1121. product_battery: '',
  1122. product_require_print: '',
  1123. product_color: '',
  1124. product_require_color: '',
  1125. product_other: '',
  1126. // 出厂价
  1127. number: [''],
  1128. price: [''],
  1129. days: [''],
  1130. cost_name: ['制版费用'],
  1131. cost_price: ['0'],
  1132. // 包装信息
  1133. package_info: '',
  1134. package_size_length: '',
  1135. package_size_width: '',
  1136. package_size_height: '',
  1137. package_weight: '',
  1138. in_package: '', // 一箱个数
  1139. // 打样情况
  1140. demo_days: '',
  1141. demo_cost: '',
  1142. demo_return: '',
  1143. cert: '',
  1144. notes: '',
  1145. }
  1146. const forms = ref<any[]>([])
  1147. const canAddForm = computed(() => {
  1148. return 100 - alreadyHasIndentCount - forms.value.length > 0
  1149. })
  1150. const productImageList = ref([] as any[][])
  1151. const vendorList = ref([] as any[][])
  1152. const manualVendor = ref({} as any)
  1153. const commonCopyFormItem = function (index: number, key: string) {
  1154. if (['vendor_id', 'vendor_name', 'vendor_phone'].includes(key)) {
  1155. vendorList.value.splice(index + 1, 1, cloneDeep(vendorList.value[index]))
  1156. forms.value[index + 1].vendor_name = forms.value[index].vendor_name
  1157. forms.value[index + 1].vendor_phone = forms.value[index].vendor_phone
  1158. forms.value[index + 1].vendor_id = forms.value[index].vendor_id
  1159. } else if (key === 'productImageList') {
  1160. productImageList.value.splice(
  1161. index + 1,
  1162. 1,
  1163. cloneDeep(productImageList.value[index]),
  1164. )
  1165. } else if (key === 'cost') {
  1166. // 额外费用
  1167. forms.value[index + 1].cost_name = cloneDeep(forms.value[index].cost_name)
  1168. forms.value[index + 1].cost_price = cloneDeep(forms.value[index].cost_price)
  1169. } else if (key === 'numberItem') {
  1170. // 数量 单价
  1171. forms.value[index + 1].number = cloneDeep(forms.value[index].number)
  1172. forms.value[index + 1].price = cloneDeep(forms.value[index].price)
  1173. forms.value[index + 1].days = cloneDeep(forms.value[index].days)
  1174. } else if (key === 'package_size') {
  1175. // 外箱规格
  1176. forms.value[index + 1].package_size_length = cloneDeep(
  1177. forms.value[index].package_size_length,
  1178. )
  1179. forms.value[index + 1].package_size_width = cloneDeep(
  1180. forms.value[index].package_size_width,
  1181. )
  1182. forms.value[index + 1].package_size_height = cloneDeep(
  1183. forms.value[index].package_size_height,
  1184. )
  1185. } else {
  1186. forms.value[index + 1][key] = forms.value[index][key]
  1187. }
  1188. }
  1189. const costTableDeleteRow = function (index: number, subIndex: number) {
  1190. forms.value[index].cost_name.splice(subIndex, 1)
  1191. forms.value[index].cost_price.splice(subIndex, 1)
  1192. }
  1193. const costTableAddRow = function (index: number) {
  1194. forms.value[index].cost_name.push('制版费用')
  1195. forms.value[index].cost_price.push('0')
  1196. }
  1197. const numberTableDeleteRow = function (index: number, subIndex: number) {
  1198. forms.value[index].number.splice(subIndex, 1)
  1199. forms.value[index].price.splice(subIndex, 1)
  1200. forms.value[index].days.splice(subIndex, 1)
  1201. }
  1202. const numberTableAddRow = function (index: number) {
  1203. forms.value[index].number.push('')
  1204. forms.value[index].price.push('')
  1205. forms.value[index].days.push('')
  1206. }
  1207. // 20250630.在编辑询价界面进来也要显示所有报价信息, 即除了新建报价时(询价为空), 其实时候都需要遍历数据展示已有报价.
  1208. const initData = function (d: any, index: number) {
  1209. // 查询供应商候选列表, 不然下拉框无数据匹配, 下拉框界面上会显示成供应商的id
  1210. queryVenderList(d.vendor_name || '', index)
  1211. const temp = cloneDeep(d)
  1212. productImageList.value.push([])
  1213. if (Array.isArray(temp.product_image) && temp.product_image.length) {
  1214. nextTick(() => {
  1215. productImageList.value.splice(
  1216. index,
  1217. 1,
  1218. temp.product_image.map((img: string) => {
  1219. return {
  1220. url: $mediaRegExp.test(img)
  1221. ? img
  1222. : import.meta.env.VITE_APP_OSS_PREFIX + img,
  1223. }
  1224. }),
  1225. )
  1226. })
  1227. }
  1228. if (temp.cost_list && temp.cost_list.length > 2) {
  1229. const t = JSON.parse(temp.cost_list)
  1230. temp.cost_name = []
  1231. temp.cost_price = []
  1232. t.forEach((item: any) => {
  1233. temp.cost_name.push(item.cost_name)
  1234. temp.cost_price.push(item.cost_price)
  1235. })
  1236. } else {
  1237. // 如果cost_list字符串长度小于2, 说明该数组为空, 删除temp的对应字段, 避免覆盖掉formDemo的克隆值.
  1238. delete temp.cost_name
  1239. delete temp.cost_price
  1240. }
  1241. if (temp.price_list && temp.price_list.length > 2) {
  1242. const t = JSON.parse(temp.price_list)
  1243. temp.number = []
  1244. temp.price = []
  1245. temp.days = []
  1246. t.forEach((item: any) => {
  1247. temp.number.push(item.number)
  1248. temp.price.push(item.price)
  1249. temp.days.push(item.days)
  1250. })
  1251. } else {
  1252. // 如果 price_list 字符串长度小于2, 说明该数组为空, 删除temp的对应字段, 避免覆盖掉formDemo的克隆值.
  1253. delete temp.cost_name
  1254. delete temp.cost_price
  1255. }
  1256. temp.entity_id = temp.id
  1257. // 删除无用字段避免接口报错
  1258. delete temp.id
  1259. // delete temp.parent_id
  1260. delete temp.create_time
  1261. delete temp.update_time
  1262. delete temp.creator
  1263. delete temp.admin_id
  1264. forms.value.push(Object.assign({}, cloneDeep(formDemo), temp))
  1265. }
  1266. const deleteForm = function (index: number) {
  1267. let deleteItem = forms.value.splice(index, 1)
  1268. productImageList.value.splice(index, 1)
  1269. vendorList.value.splice(index, 1)
  1270. console.log(deleteItem, 'deleteItem')
  1271. if (!['0', 0].includes(parentId)) {
  1272. deleteIndent({
  1273. indent_ids: [],
  1274. quote_ids: deleteItem.map((i) => `${parentId}_${i.entity_id}`),
  1275. }).then((response: any) => {
  1276. if (response.code === 1) {
  1277. ElNotification({
  1278. title: '删除成功',
  1279. message: '删除成功',
  1280. duration: 3000,
  1281. })
  1282. }
  1283. })
  1284. }
  1285. }
  1286. const addFormColumn = function () {
  1287. if (loading.value) {
  1288. ElMessage.warning({
  1289. message: '正在提交中, 请勿重复提交',
  1290. duration: 2000,
  1291. })
  1292. return
  1293. }
  1294. if (canAddForm.value) {
  1295. forms.value.push(
  1296. Object.assign(cloneDeep(formDemo), {
  1297. parent_id: parentId,
  1298. product_name: visible === 1 ? defaultName : '',
  1299. in_package: visible === 1 ? defaultSku.Carton_Qty || '' : '',
  1300. package_weight: visible === 1 ? defaultSku.Carton_Weight_Kg || '' : '',
  1301. package_size_length: visible === 1 ? defaultSku.Length || '' : '',
  1302. package_size_width: visible === 1 ? defaultSku.Width || '' : '',
  1303. package_size_height:
  1304. visible === 1 ? defaultSku.Thickness_Height || '' : '',
  1305. }),
  1306. )
  1307. productImageList.value.push([])
  1308. vendorList.value.push([])
  1309. }
  1310. }
  1311. watch(
  1312. () => visible,
  1313. () => {
  1314. forms.value = []
  1315. productImageList.value = []
  1316. vendorList.value = []
  1317. if (visible > 1) {
  1318. dataForEdit.forEach((i, index) => {
  1319. vendorList.value.push([])
  1320. initData(i, index)
  1321. })
  1322. } else if (visible > 0) {
  1323. addFormColumn()
  1324. }
  1325. show.value = visible > 0
  1326. },
  1327. )
  1328. const queryVenderList = function (keyword: string, index: number) {
  1329. let keywords = keyword.trim()
  1330. if (!keywords.length) return
  1331. getVendorList({ keywords }).then((response: any) => {
  1332. const defaultCreateOption = {
  1333. name: keywords,
  1334. id: keywords,
  1335. }
  1336. if (Array.isArray(response.result)) {
  1337. const tempStr = keywords.replace(/\S_-/g, '').toLowerCase()
  1338. const tempList = response.result.map((i: any) =>
  1339. i.name.replace(/\S_-/g, '').toLowerCase(),
  1340. )
  1341. let result = []
  1342. if (response.result.length) {
  1343. if (tempList.includes(tempStr)) {
  1344. result = response.result
  1345. } else {
  1346. // 结果里面没找到输入的搜索字符串, 就把它加入到结果里面当成‘新增的’
  1347. result = [cloneDeep(defaultCreateOption)].concat(response.result)
  1348. }
  1349. } else if (keywords.length) {
  1350. result = [cloneDeep(defaultCreateOption)]
  1351. }
  1352. if (manualVendor.value.id) {
  1353. vendorList.value.splice(index, 1, [manualVendor.value].concat(result))
  1354. } else {
  1355. vendorList.value.splice(index, 1, result)
  1356. }
  1357. }
  1358. })
  1359. }
  1360. const changeVenderSelect = function (value: string | number, index: number) {
  1361. if (value) {
  1362. const temp = vendorList.value[index].filter((i) => i.id === value)
  1363. if (temp.length) {
  1364. forms.value[index].vendor_name = temp[0].name
  1365. forms.value[index].vendor_phone = temp[0].phone || temp[0].Phone || ''
  1366. forms.value[index].vendor_contact = temp[0].Primary_Contact_name || ''
  1367. manualVendor.value = {
  1368. name: '',
  1369. id: '',
  1370. }
  1371. if (temp[0].High_Risk_Supplier) {
  1372. ElMessageBox.alert(
  1373. '请注意该供应商在我们黑名单中。<br>Please note that this supplier is in our black list.',
  1374. 'Alert',
  1375. {
  1376. dangerouslyUseHTMLString: true,
  1377. },
  1378. )
  1379. }
  1380. } else {
  1381. // vendor_name === vendor_id 为新增
  1382. forms.value[index].vendor_name = value || ''
  1383. forms.value[index].vendor_phone = ''
  1384. forms.value[index].vendor_type = ''
  1385. forms.value[index].vendor_contact = ''
  1386. manualVendor.value = {
  1387. name: value || '',
  1388. id: value || '',
  1389. }
  1390. }
  1391. }
  1392. }
  1393. const auditUser = ref('')
  1394. const getCurrentAuditUser = () => {
  1395. userAPI.getAuditUser().then((res: any) => {
  1396. // console.log(res, 'res')
  1397. if (
  1398. res.code === 1 &&
  1399. Array.isArray(res.result.data) &&
  1400. res.result.data.length
  1401. ) {
  1402. const temp = res.result.data.filter((i: any) => i.type === 1)
  1403. // console.log(temp, 'temp')
  1404. if (temp.length) auditUser.value = temp[0].email
  1405. }
  1406. })
  1407. }
  1408. getCurrentAuditUser()
  1409. let loading = ref(false)
  1410. const createQuoteFunc = function () {
  1411. const params = {
  1412. file: '', // 疑似永远为空
  1413. } as any
  1414. if (parentId) {
  1415. params.parent_id = parentId
  1416. }
  1417. let notiList: string[] = []
  1418. let temp = cloneDeep(forms.value)
  1419. temp = temp.map((item, index) => {
  1420. const result = { ...item }
  1421. result.price_list = []
  1422. result.number.forEach((v: any, i: number) => {
  1423. result.price_list.push({
  1424. number: `${result.number[i]}`,
  1425. price: `${result.price[i]}`,
  1426. days: `${result.days[i]}`,
  1427. })
  1428. })
  1429. result.cost_list = []
  1430. result.cost_name.forEach((v: any, i: number) => {
  1431. result.cost_list.push({
  1432. cost_name: `${result.cost_name[i]}`,
  1433. cost_price: `${result.cost_price[i]}`,
  1434. })
  1435. })
  1436. result.product_image = productImageList.value[index]
  1437. .map((i) => {
  1438. return i.url.replace($mediaRegExp, '/')
  1439. })
  1440. .join(',')
  1441. // if (result.vendor_id && result.vendor_name === result.vendor_id) {
  1442. // notiList.push(result.vendor_name)
  1443. // }
  1444. return result
  1445. })
  1446. // 组装接口数据
  1447. Object.assign(params, { lists: temp })
  1448. // if (notiList.length) {
  1449. // ElMessageBox.alert(
  1450. // '您正在提交系统外供应商 ' +
  1451. // notiList.map((i) => `[${i}]`).join(', ') +
  1452. // '<br>本次操作已触发审核流程,审核人将会尽快处理,如有问题请联系:' +
  1453. // `<a href="mailto:${auditUser.value}">${auditUser.value}</a>`,
  1454. // '提示',
  1455. // {
  1456. // dangerouslyUseHTMLString: true,
  1457. // },
  1458. // )
  1459. // }
  1460. loading.value = true
  1461. createQuote(params)
  1462. .then((response: any) => {
  1463. if (response.code !== 1) return
  1464. ElNotification({
  1465. title: '成功',
  1466. message: '提交成功',
  1467. type: 'success',
  1468. duration: 3000,
  1469. })
  1470. $emit('create', response.result)
  1471. close()
  1472. })
  1473. .finally(() => {
  1474. loading.value = false
  1475. })
  1476. }
  1477. const inputFilter = (value: string, target: any, key: string) => {
  1478. target[key] = value
  1479. .split('')
  1480. .filter((i) => i.charCodeAt(0) > 0 && i.charCodeAt(0) < 255)
  1481. .join('')
  1482. }
  1483. // 用来动态绑定ref, 便于调用表单验证
  1484. const formRef = ref({} as any)
  1485. const getFormRef = (el: any, key: string) => {
  1486. formRef.value[`${key}`] = el
  1487. }
  1488. const checkForm = function () {
  1489. if (loading.value) {
  1490. ElMessage.warning({
  1491. message: '正在提交中, 请勿重复提交',
  1492. duration: 2000,
  1493. })
  1494. return
  1495. }
  1496. const key = [
  1497. 'vendor_id',
  1498. 'product_name',
  1499. 'number',
  1500. 'cost',
  1501. 'package_weight',
  1502. 'package_size',
  1503. 'in_package',
  1504. 'demo_days',
  1505. ]
  1506. let length = forms.value.length
  1507. const target = [] as any[]
  1508. do {
  1509. key.forEach((i) => {
  1510. target.push(`${i}_${length - 1}`)
  1511. })
  1512. length--
  1513. } while (length >= 1)
  1514. // 表单校验结果
  1515. let result = true
  1516. const promisePool: any[] = []
  1517. target.forEach((i: string) => {
  1518. const r: any = formRef.value[`${i}`]
  1519. if (typeof r.validate === 'function') {
  1520. r.clearValidate()
  1521. const p = new Promise((resolve) => {
  1522. r.validate((valid: boolean) => {
  1523. if (!valid) {
  1524. messageError('请检查表单必填项')
  1525. resolve(false)
  1526. } else {
  1527. resolve(true)
  1528. }
  1529. })
  1530. })
  1531. promisePool.push(p)
  1532. } else {
  1533. result = false
  1534. }
  1535. })
  1536. if (!result) {
  1537. // 一般不会到这里
  1538. messageError('表单异常. 请刷新页面再试或者全屏截图联系管理员')
  1539. return
  1540. }
  1541. Promise.all(promisePool).then((res) => {
  1542. const valid = res.every((a) => a === true)
  1543. if (valid) {
  1544. createQuoteFunc()
  1545. }
  1546. })
  1547. }
  1548. const messageError = debounce(function (info) {
  1549. ElMessage.error(info)
  1550. }, 100)
  1551. const commonCheck = (rule: any, value: any, cb: any) => {
  1552. if (typeof value === 'number') {
  1553. if (value >= 0) {
  1554. cb()
  1555. } else {
  1556. cb(new Error('数字校验出错'))
  1557. }
  1558. return
  1559. }
  1560. if (value && value.trim().length) {
  1561. cb()
  1562. } else {
  1563. cb(new Error('字符串校验出错'))
  1564. }
  1565. }
  1566. const close = (done = {} as any) => {
  1567. $emit('update:visible', 0)
  1568. if (typeof done === 'function') done()
  1569. }
  1570. const copyValue = (str: any, event: any) => {
  1571. console.log(str, 'str')
  1572. const clipboard = new Clipboard(event.target, {
  1573. text: () => str,
  1574. })
  1575. clipboard.on('success', () => {
  1576. ElMessage.success('复制成功!')
  1577. clipboard.destroy()
  1578. })
  1579. clipboard.on('error', () => {
  1580. ElMessage.error('复制失败,请手动复制')
  1581. clipboard.destroy()
  1582. })
  1583. // 触发实际复制
  1584. event.target.click()
  1585. }
  1586. </script>
  1587. <style lang="scss">
  1588. .component-edit-indent-info {
  1589. .custom-edit-indent-info-dialog {
  1590. margin-top: 0 !important;
  1591. margin-bottom: 0 !important;
  1592. height: 100vh;
  1593. .el-dialog__body {
  1594. max-height: 87vh;
  1595. overflow-y: scroll;
  1596. overflow-x: auto;
  1597. padding-top: 8px;
  1598. }
  1599. .el-dialog__header {
  1600. border-bottom: 1px solid #dcdfe6;
  1601. }
  1602. .el-dialog__footer {
  1603. padding-bottom: 10px;
  1604. }
  1605. }
  1606. }
  1607. </style>
  1608. <style lang="scss" scoped>
  1609. div {
  1610. box-sizing: border-box;
  1611. }
  1612. .form-table {
  1613. margin: 24px 0;
  1614. & > div {
  1615. &::after {
  1616. // 占位符. 让表格右侧在横向滚动的时候能再滚动20px
  1617. content: '.';
  1618. width: 20px;
  1619. padding-left: 20px;
  1620. height: 1px;
  1621. background-color: transparent;
  1622. color: transparent;
  1623. }
  1624. }
  1625. }
  1626. .first-label {
  1627. text-align: center;
  1628. width: 120px;
  1629. min-width: 120px;
  1630. border: 1px solid #dcdfe6;
  1631. border-top: none;
  1632. border-right: none;
  1633. }
  1634. .second-label {
  1635. width: 170px;
  1636. min-width: 170px;
  1637. line-height: 55px;
  1638. min-height: 55px;
  1639. text-align: left;
  1640. padding: 0 10px;
  1641. border: 1px solid #dcdfe6;
  1642. border-top: none;
  1643. &.required {
  1644. color: #ef4135;
  1645. &::before {
  1646. content: '*';
  1647. display: inline-block;
  1648. color: #ef4135;
  1649. font-size: 14px;
  1650. width: 8px;
  1651. height: 8px;
  1652. }
  1653. }
  1654. }
  1655. .input-area {
  1656. position: relative;
  1657. border: 1px solid #dcdfe6;
  1658. border-left: none;
  1659. border-top: none;
  1660. min-height: 55px;
  1661. height: 100%;
  1662. padding: 7px 8px;
  1663. width: 300px;
  1664. min-width: 300px;
  1665. &:hover .btn-copy {
  1666. display: block;
  1667. }
  1668. .btn-copy {
  1669. display: none;
  1670. cursor: pointer;
  1671. background-color: #fff;
  1672. line-height: 26px;
  1673. padding: 0 4px;
  1674. position: absolute;
  1675. z-index: 2;
  1676. top: calc((100% - 26px) / 2);
  1677. right: -16px;
  1678. }
  1679. .el-form-item {
  1680. margin-bottom: 0;
  1681. }
  1682. .sub-table {
  1683. border: 1px solid #dcdfe6;
  1684. border-left: none;
  1685. }
  1686. .sub-table-head {
  1687. text-align: center;
  1688. line-height: 24px;
  1689. height: 24px;
  1690. background-color: #efefef;
  1691. }
  1692. .sub-table-row {
  1693. border-top: 1px solid #dcdfe6;
  1694. }
  1695. .sub-table-head,
  1696. .sub-table-row {
  1697. position: relative;
  1698. & > div {
  1699. border-left: 1px solid #dcdfe6;
  1700. padding: 2px 4px;
  1701. }
  1702. &:hover .sub-table-btn-delete {
  1703. border-left: 0;
  1704. padding: 0;
  1705. display: block;
  1706. }
  1707. }
  1708. .sub-table-price {
  1709. width: 120px;
  1710. }
  1711. .sub-table-days {
  1712. width: 90px;
  1713. }
  1714. .sub-table-number {
  1715. width: 90px;
  1716. }
  1717. .sub-table-cost-name {
  1718. width: 140px;
  1719. }
  1720. .sub-table-cost-price {
  1721. width: 140px;
  1722. }
  1723. .sub-table-btn-delete {
  1724. display: none;
  1725. line-height: 1;
  1726. font-size: 20px;
  1727. color: #ef4135;
  1728. position: absolute;
  1729. right: -6px;
  1730. top: 0;
  1731. z-index: 2;
  1732. }
  1733. .sub-table-btn-add {
  1734. margin: 12px 0 8px;
  1735. }
  1736. }
  1737. .form-header {
  1738. .first-label,
  1739. .input-area,
  1740. .second-label {
  1741. border-top: 1px solid #dcdfe6;
  1742. min-height: auto;
  1743. height: 40px;
  1744. line-height: 40px;
  1745. }
  1746. .el-button {
  1747. color: #ef4135;
  1748. }
  1749. }
  1750. .btn-add-indent-info {
  1751. background-color: #fff;
  1752. z-index: 2;
  1753. width: 74px;
  1754. height: 84px;
  1755. border: 1px solid #009688;
  1756. position: absolute;
  1757. right: 40px;
  1758. bottom: 40px;
  1759. color: #666;
  1760. font-size: 14px;
  1761. cursor: pointer;
  1762. .el-icon-circle-plus-outline {
  1763. color: #009688;
  1764. }
  1765. &:hover {
  1766. color: #333;
  1767. font-weight: 500;
  1768. border-color: #00bb88;
  1769. .el-icon-circle-plus-outline {
  1770. color: #00bb88;
  1771. }
  1772. }
  1773. }
  1774. </style>