index.vue 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900
  1. <template>
  2. <div class="compnent-price-calc">
  3. <exportQuota
  4. ref="compExportQuotaRef"
  5. :product-info="productInfo"
  6. :export-form="exportForm"
  7. :step3-form-list="step3FormList"
  8. :step2-form-list="formList"
  9. :creator-options="creatorOptions"
  10. :city2="formData.cal_city.local_city"
  11. :city="exportForm.pdf_city"
  12. ></exportQuota>
  13. <!-- :city="formData.cal_city.local_city" -->
  14. <el-dialog
  15. v-model="show"
  16. class="custom-calc-price-dialog"
  17. title="查看计价结果"
  18. :close-on-click-modal="false"
  19. :close-on-press-escape="false"
  20. :before-close="close"
  21. width="1800px"
  22. >
  23. <div
  24. v-loading="loading"
  25. class="flex items-start flex-wrap"
  26. >
  27. <step1
  28. :computed-box-number="computedBoxNumber"
  29. :computed-total-bulk="computedTotalBulk"
  30. :computed-total-weight="computedTotalWeight"
  31. :computed-total-weight-plus="computedTotalWeightPlus"
  32. :image-list="imageList"
  33. :product-info="productInfo"
  34. ></step1>
  35. <div class="step step-2">
  36. <common-title
  37. :title="$t(prefix + 'label_transport_info')"
  38. ></common-title>
  39. <p style="color: #ef4135; margin-bottom: 12px">
  40. 快速运输天数:2-3天 / 空+派运输天数:8天 /
  41. 海运运输天数:LCL30天、FCL25天
  42. </p>
  43. <div class="flex items-center">
  44. <el-select
  45. v-model="formData.cal_city.local_city"
  46. style="width: 120px; margin-right: 12px"
  47. size="small"
  48. @change="onCityChange"
  49. >
  50. <el-option
  51. v-for="city in cityList"
  52. :key="city"
  53. :label="city"
  54. :value="city"
  55. ></el-option>
  56. </el-select>
  57. <div class="flex items-center">
  58. <el-tooltip content="切换城市后点击">
  59. <el-button
  60. type="primary"
  61. size="small"
  62. @click="reGenerateFormAfterCityChange"
  63. >
  64. 生成运输信息
  65. </el-button>
  66. </el-tooltip>
  67. <el-button
  68. type="warning"
  69. size="small"
  70. @click="componentFreightVisible = true"
  71. >
  72. 设置运费参数
  73. </el-button>
  74. </div>
  75. </div>
  76. <div class="step2-form-area">
  77. <div
  78. v-for="(formItem, index) in formList"
  79. :key="index"
  80. class="step2-form-item"
  81. >
  82. <div class="qty-number">
  83. 采购数量:&nbsp;{{ formItem.number }} ({{ isHeavyGoods.label
  84. }}{{
  85. isHeavyGoodsPlus.flag !== isHeavyGoods.flag
  86. ? ` | ${isHeavyGoodsPlus.label}`
  87. : ''
  88. }})
  89. </div>
  90. <div class="flex items-center">
  91. <el-card
  92. v-for="v in 5"
  93. :key="v"
  94. class="form-item-card"
  95. :class="{
  96. on: formItem[`${v - 1}_${formItem.number}`] === 'on',
  97. }"
  98. >
  99. <template #header>
  100. <div
  101. @click.capture="
  102. ($e) => captureSwitchChange($e, formItem, v - 1)
  103. "
  104. >
  105. <!-- <el-tooltip
  106. placement="left"
  107. content="注意, 切换开关会导致右侧的成本数据 以(点过'保存按钮'后的 / 默认的)初始值 计算重置"
  108. > -->
  109. <el-switch
  110. v-model="formItem[`${v - 1}_${formItem.number}`]"
  111. size="small"
  112. active-color="#409eff"
  113. inactive-color="#ccc"
  114. active-value="on"
  115. inactive-value="off"
  116. @change="
  117. () => generateStep3Form({ y: v - 1, x: index })
  118. "
  119. />
  120. <!-- </el-tooltip> -->
  121. </div>
  122. </template>
  123. <div v-if="v === 1">
  124. <el-select
  125. v-model="formItem[`method_0_${formItem.number}`]"
  126. size="small"
  127. @change="
  128. reGenerateFormAfterMidwayTypeChange({
  129. x: index,
  130. y: 0,
  131. })
  132. "
  133. >
  134. <el-option
  135. v-for="option in airOption"
  136. :key="option.value"
  137. :label="option.label"
  138. :value="option.value"
  139. ></el-option>
  140. </el-select>
  141. <div class="price">
  142. $&nbsp;{{ Number(formItem.midway_price_0).toFixed(2) }}
  143. </div>
  144. </div>
  145. <div v-if="v === 2">
  146. <div>空+派</div>
  147. <div class="price">
  148. $&nbsp;{{ Number(formItem.midway_price_1).toFixed(2) }}
  149. </div>
  150. </div>
  151. <div v-if="v === 3">
  152. <el-select
  153. v-model="formItem[`method_2_${formItem.number}`]"
  154. size="small"
  155. @change="
  156. reGenerateFormAfterMidwayTypeChange({
  157. x: index,
  158. y: 2,
  159. })
  160. "
  161. >
  162. <el-option
  163. v-for="option in seaOption"
  164. :key="option.value"
  165. :label="option.label"
  166. :value="option.value"
  167. ></el-option>
  168. </el-select>
  169. <div class="price">
  170. $&nbsp;{{ Number(formItem.midway_price_2).toFixed(2) }}
  171. </div>
  172. </div>
  173. <div v-if="v === 4">
  174. <div>DTD</div>
  175. <div
  176. v-if="formItem.freight_cost_3"
  177. class="price cursor-pointer"
  178. @click="openDTDDialog(3, index)"
  179. >
  180. $&nbsp;{{ Number(formItem.freight_cost_3).toFixed(2) }}
  181. </div>
  182. <div
  183. v-else
  184. class="edit cursor-pointer"
  185. @click="openDTDDialog(3, index)"
  186. >
  187. {{ $t('btn_edit') }}
  188. </div>
  189. </div>
  190. <div v-if="v === 5">
  191. <div>LCL散货</div>
  192. <div
  193. v-if="formItem.freight_cost_4"
  194. class="price cursor-pointer"
  195. @click="openLCLDialog(4, index)"
  196. >
  197. $&nbsp;{{ Number(formItem.freight_cost_4).toFixed(2) }}
  198. </div>
  199. <div
  200. v-else
  201. class="edit cursor-pointer"
  202. @click="openLCLDialog(4, index)"
  203. >
  204. {{ $t('btn_edit') }}
  205. </div>
  206. </div>
  207. </el-card>
  208. </div>
  209. </div>
  210. </div>
  211. </div>
  212. <div class="step step-3">
  213. <div
  214. class="mb-4 border border-x-0 border-t-0 border-solid border-gray-200"
  215. >
  216. <el-check-tag
  217. v-for="(form, index) in step3FormList"
  218. :checked="index === currentTab"
  219. :key="index"
  220. class="border border-solid border-gray-200 bg-white"
  221. style="border-radius: 2px"
  222. @click="currentTab = index"
  223. >
  224. {{ form.tabLabel }}
  225. </el-check-tag>
  226. </div>
  227. <div
  228. data-desc="这层div没用的,只是移除原本的el-tab之后用来减少代码改动量,不然里面的内容全部要减少一个缩进单位了"
  229. >
  230. <div
  231. v-show="index === currentTab"
  232. v-for="(form, index) in step3FormList"
  233. :key="index"
  234. >
  235. <common-title
  236. :title="$t(prefix + 'label_cost_list')"
  237. ></common-title>
  238. <div class="horizontal-table">
  239. <div
  240. class="flex items-center tr"
  241. style="background-color: #ebeef5"
  242. >
  243. <div class="td">项目</div>
  244. <div class="td">总价</div>
  245. <div class="td">单价</div>
  246. </div>
  247. <div class="flex items-center tr">
  248. <div class="td column-label">产品成本(AUD)</div>
  249. <div class="td">
  250. {{ Number(form.product_cost).toFixed(2) }}
  251. </div>
  252. <div class="td">
  253. {{ (Number(form.product_cost) / form.number).toFixed(2) }}
  254. </div>
  255. </div>
  256. <div class="flex items-center tr">
  257. <div class="td column-label">制版及其它成本(AUD)</div>
  258. <div class="td">
  259. {{ Number(form.extend_cost).toFixed(2) }}
  260. </div>
  261. <div class="td">
  262. {{ (Number(form.extend_cost) / form.number).toFixed(2) }}
  263. </div>
  264. </div>
  265. <div class="flex items-center tr">
  266. <div class="td column-label">运费总成本(AUD)</div>
  267. <div class="td">
  268. {{ Number(form.freight_cost).toFixed(2) }}
  269. </div>
  270. <div class="td">
  271. {{ (Number(form.freight_cost) / form.number).toFixed(2) }}
  272. </div>
  273. </div>
  274. <div class="flex items-center tr">
  275. <div class="td column-label">税费(AUD)</div>
  276. <div class="td">
  277. {{ Number(form.tax_fee).toFixed(2) }}
  278. </div>
  279. <div class="td">
  280. {{ (Number(form.tax_fee) / form.number).toFixed(2) }}
  281. </div>
  282. </div>
  283. <div class="flex items-center tr">
  284. <div class="td column-label">入口报关费(AUD)</div>
  285. <div class="td">
  286. {{ Number(form.gatt_tax_fee).toFixed(2) }}
  287. </div>
  288. <div class="td">
  289. {{ (Number(form.gatt_tax_fee) / form.number).toFixed(2) }}
  290. </div>
  291. </div>
  292. <div class="flex items-center tr">
  293. <div class="td column-label">验货费(AUD)</div>
  294. <div class="td">
  295. {{ Number(form.review_cost).toFixed(2) }}
  296. </div>
  297. <div class="td">
  298. {{ (Number(form.review_cost) / form.number).toFixed(2) }}
  299. </div>
  300. </div>
  301. <div class="flex items-center tr">
  302. <div class="td column-label">总成本(AUD)</div>
  303. <div class="td">
  304. {{ Number(form.total_cost).toFixed(2) }}
  305. </div>
  306. <div class="td">
  307. {{ (Number(form.total_cost) / form.number).toFixed(2) }}
  308. </div>
  309. </div>
  310. </div>
  311. <el-form
  312. :model="form"
  313. label-width="105px"
  314. >
  315. <common-title
  316. :title="$t(prefix + 'label_other_cost')"
  317. ></common-title>
  318. <div class="">
  319. <el-form-item
  320. label="COO Certificate"
  321. label-width="120px"
  322. >
  323. <el-switch
  324. v-model="form.coo_certificate"
  325. active-color="#409eff"
  326. inactive-color="#ccc"
  327. active-text="是"
  328. inactive-text="否"
  329. active-value="on"
  330. inactive-value="off"
  331. size="small"
  332. @change="($e: any) => changeCOO(form, $e)"
  333. ></el-switch>
  334. </el-form-item>
  335. </div>
  336. <div class="flex justify-between flex-wrap items-center">
  337. <el-form-item label="税点">
  338. <el-input
  339. v-model="form.tax"
  340. :disabled="form.coo_certificate === 'on'"
  341. @input="() => onForm3ItemChange(form, 'tax')"
  342. >
  343. <template #append>%</template>
  344. </el-input>
  345. </el-form-item>
  346. <el-form-item label="税费">
  347. <el-input
  348. v-model="form.tax_fee"
  349. disabled
  350. >
  351. <template #append>AUD</template>
  352. </el-input>
  353. </el-form-item>
  354. <el-form-item label="入口报关费用">
  355. <el-input
  356. v-model="form.gatt_tax_fee"
  357. @input="() => onForm3ItemChange(form, 'gatt_tax_fee')"
  358. >
  359. <template #append>AUD</template>
  360. </el-input>
  361. </el-form-item>
  362. <el-form-item label="验货费">
  363. <el-input
  364. v-model="form.review_cost"
  365. @input="() => onForm3ItemChange(form, 'review_cost')"
  366. >
  367. <template #append>AUD</template>
  368. </el-input>
  369. </el-form-item>
  370. <el-form-item label="国内运费总价">
  371. <el-input
  372. v-model="form.cn_freight_cost"
  373. @input="() => onForm3ItemChange(form, 'cn_freight_cost')"
  374. >
  375. <template #append>RMB</template>
  376. </el-input>
  377. </el-form-item>
  378. <el-form-item label="国外本土运费">
  379. <el-input
  380. v-model="form.local_freight_cost"
  381. @input="
  382. () => onForm3ItemChange(form, 'local_freight_cost')
  383. "
  384. >
  385. <template #append>AUD</template>
  386. </el-input>
  387. </el-form-item>
  388. </div>
  389. <common-title
  390. :title="$t(prefix + 'label_charge')"
  391. ></common-title>
  392. <div class="flex justify-between flex-wrap items-center">
  393. <el-form-item label="Set Up Cost">
  394. <el-input
  395. v-model="form.setup_cost"
  396. @input="() => onForm3ItemChange(form, 'setup_cost')"
  397. >
  398. <template #append>AUD</template>
  399. </el-input>
  400. </el-form-item>
  401. <el-form-item label="本地收费">
  402. <el-input
  403. v-model="form.add_freight_cost"
  404. @input="() => onForm3ItemChange(form, 'add_freight_cost')"
  405. >
  406. <template #append>AUD</template>
  407. </el-input>
  408. </el-form-item>
  409. <el-form-item label="售卖单价">
  410. <el-input
  411. v-model="form.sold_unit"
  412. @input="() => onForm3ItemChange(form, 'sold_unit')"
  413. >
  414. <template #append>AUD</template>
  415. </el-input>
  416. </el-form-item>
  417. <el-form-item label="售卖总价">
  418. <el-input
  419. v-model="form.sold_price"
  420. disabled
  421. >
  422. <template #append>AUD</template>
  423. </el-input>
  424. </el-form-item>
  425. </div>
  426. <common-title
  427. :title="$t(prefix + 'label_analysis')"
  428. ></common-title>
  429. <div class="flex justify-between items-center">
  430. <el-form-item label="利润率">
  431. <el-input
  432. v-model="form.profit_margin"
  433. @input="() => onForm3ItemChange(form, 'profit_margin')"
  434. >
  435. <template #append>%</template>
  436. </el-input>
  437. </el-form-item>
  438. <el-form-item label="利润">
  439. <el-input
  440. v-model="form.profit"
  441. disabled
  442. >
  443. <template #append>AUD</template>
  444. </el-input>
  445. </el-form-item>
  446. </div>
  447. </el-form>
  448. <div class="flex justify-center items-center">
  449. <el-button
  450. type="primary"
  451. size="small"
  452. @click="
  453. () => {
  454. isExport = 0
  455. checkForm(1)
  456. }
  457. "
  458. >
  459. {{ $t('btn_save') }}
  460. </el-button>
  461. <el-button
  462. type="primary"
  463. size="small"
  464. plain
  465. @click="
  466. () => {
  467. isExport = 1
  468. checkForm(2)
  469. }
  470. "
  471. >
  472. 保存并导出
  473. </el-button>
  474. <!-- <el-button @click="generate">test</el-button> -->
  475. </div>
  476. </div>
  477. </div>
  478. </div>
  479. </div>
  480. <setDTD
  481. v-model:visible="dtdVisible"
  482. :form-data="dtdData"
  483. @save="dtdChange"
  484. ></setDTD>
  485. <setLCL
  486. v-model:visible="lclVisible"
  487. :form-data="lclData"
  488. @save="lclChange"
  489. ></setLCL>
  490. <freight
  491. v-model:visible="componentFreightVisible"
  492. @save="getCalcParam"
  493. ></freight>
  494. <CompExportForm
  495. v-model:visible="componentExportFormVisible"
  496. :step3-form-list="step3FormList"
  497. :creator-options="creatorOptions"
  498. :form-data="exportForm"
  499. :city-list="cityList"
  500. @save="onExportFormSave"
  501. ></CompExportForm>
  502. </el-dialog>
  503. </div>
  504. </template>
  505. <script lang="ts" setup>
  506. import { defineComponent, ref, watch, computed, nextTick, inject } from 'vue'
  507. import {
  508. ElButton,
  509. ElNotification,
  510. ElMessage,
  511. ElForm,
  512. ElFormItem,
  513. ElInput,
  514. ElSelect,
  515. ElDialog,
  516. ElOption,
  517. ElSwitch,
  518. ElCard,
  519. ElCheckTag,
  520. ElTooltip,
  521. } from 'element-plus'
  522. import cloneDeep from 'lodash.clonedeep'
  523. import commonTitle from './components/title.vue'
  524. import setDTD from './components/dialogDTD.vue'
  525. import setLCL from './components/dialogLCL.vue'
  526. import freight from '../freight.vue'
  527. import step1 from './components/step1.vue'
  528. import CompExportForm from '../exportForm.vue'
  529. import exportQuota from '../exportQuota2.vue'
  530. import mathjs, { savePrecision } from '@/utils/math.js'
  531. import Cookies from 'js-cookie'
  532. import { getCalcParams, saveCalcData } from '@/api/indent'
  533. import { $t } from '@/i18n/index'
  534. defineComponent({
  535. name: 'ComponentAaaa',
  536. })
  537. const {
  538. visible = false,
  539. dataForCalc = {} as any,
  540. creatorOptions = [],
  541. } = defineProps<{
  542. visible: boolean
  543. dataForCalc: object
  544. creatorOptions: any[]
  545. }>()
  546. const $emit = defineEmits([
  547. 'update:visible',
  548. 'save-price-calc',
  549. 'save-price-calc',
  550. ])
  551. const $mediaRegExp = inject('mediaRegExp') as RegExp
  552. const prefix = 'order.indent_calc.'
  553. const loading = ref(false)
  554. const componentFreightVisible = ref(false)
  555. const componentExportFormVisible = ref(false)
  556. const productInfo = ref({} as any)
  557. const setting = ref({} as any) // 运费设置数据
  558. // 用在step2界面上显示的表单
  559. const formList = ref([] as any[])
  560. // 用在step3界面上显示的表单
  561. const step3FormList = ref([] as any[])
  562. const currentTab = ref(0) // 当前显示的step3表单的tab索引
  563. // 提交的表单, 用来存真正提交的数据.
  564. const formData = ref({
  565. cal_city: {
  566. local_city: '',
  567. },
  568. cal_shipment_method: {},
  569. } as any)
  570. // 导出pdf那个表单
  571. let exportForm = ref({
  572. city: '', // 显示在导出pdf的城市地址, 不是step2的运费选择地址.
  573. exchange: '',
  574. days: '30',
  575. gst_name: '+GST',
  576. notes: '',
  577. other_notes: '',
  578. saleperson: '',
  579. } as any)
  580. const step3FormDemo = ref({
  581. coo_certificate: 'on', // coo 开关
  582. tax: 0, // 税点 coo打开则是0, 关闭默认是5
  583. tax_fee: 0, // 税费 coo打开则是0, 需要根据税点计算
  584. gatt_tax_fee: 60, // 入口报关费用
  585. review_cost: 0, // 验货费
  586. cn_freight_cost: 0, // 国内运费总价
  587. local_freight_cost: 0, // 国外本地运费
  588. add_freight_cost: 0, // 本地收费
  589. freight: 0, // 运费总成本
  590. setup_cost: 0, // Set Up Cost
  591. sold_unit: 0, // 售卖单价
  592. sold_price: 0, // 售卖总价
  593. profit_margin: 30, // mark up 利润率
  594. profit: 0, // 利润
  595. } as any)
  596. const imageList = ref([] as any[])
  597. const cityList = ref([] as any[])
  598. // 空运选项. 参考: https://www.tapd.cn/59388921/prong/stories/view/1159388921001001048
  599. const airOption = [
  600. { label: 'DHL', value: 'dhl' },
  601. { label: 'TNT', value: 'tnt' },
  602. { label: 'Fedex', value: 'fedex' },
  603. ]
  604. // 海运选项
  605. const seaOption = ref([
  606. { label: 'FCL', value: 'fcl' },
  607. { label: 'LCL', value: 'lcl' },
  608. ])
  609. const dtdData = ref({} as any)
  610. const lclData = ref({} as any)
  611. const dtdVisible = ref(false)
  612. const lclVisible = ref(false)
  613. const show = ref(false)
  614. watch(
  615. () => visible,
  616. () => {
  617. show.value = visible
  618. resetData()
  619. if (show.value) {
  620. getCalcParam()
  621. }
  622. },
  623. )
  624. let getCalcParam = () => {
  625. getCalcParams().then((response: any) => {
  626. const res = response.result
  627. if (response.code !== 1) return
  628. cityList.value = res.city_list
  629. if (cityList.value.length) {
  630. formData.value.cal_city.local_city = cityList.value[0]
  631. }
  632. setting.value = Object.assign({}, res.data)
  633. setting.value.dhl_airline = JSON.parse(setting.value.dhl_airline)
  634. if (!Array.isArray(setting.value.dhl_airline)) {
  635. setting.value.dhl_airline = []
  636. } else {
  637. setting.value.dhl_airline = setting.value.dhl_airline.map((i: any) => {
  638. const result: any = {}
  639. for (const key in i) {
  640. if (Object.prototype.hasOwnProperty.call(i, key)) {
  641. result[key] = Number(i[key])
  642. }
  643. }
  644. return result
  645. })
  646. }
  647. setting.value.tnt_airline = JSON.parse(setting.value.tnt_airline)
  648. if (!Array.isArray(setting.value.tnt_airline)) {
  649. setting.value.tnt_airline = []
  650. } else {
  651. setting.value.tnt_airline = setting.value.tnt_airline.map((i: any) => {
  652. const result: any = {}
  653. for (const key in i) {
  654. if (Object.prototype.hasOwnProperty.call(i, key)) {
  655. result[key] = Number(i[key])
  656. }
  657. }
  658. return result
  659. })
  660. }
  661. setting.value.fedex_airline = JSON.parse(setting.value.fedex_airline)
  662. if (!Array.isArray(setting.value.fedex_airline)) {
  663. setting.value.fedex_airline = []
  664. } else {
  665. setting.value.fedex_airline = setting.value.fedex_airline.map(
  666. (i: any) => {
  667. const result: any = {}
  668. for (const key in i) {
  669. if (Object.prototype.hasOwnProperty.call(i, key)) {
  670. result[key] = Number(i[key])
  671. }
  672. }
  673. return result
  674. },
  675. )
  676. }
  677. setting.value.airplus = JSON.parse(setting.value.airplus)
  678. if (!Array.isArray(setting.value.airplus)) {
  679. setting.value.airplus = []
  680. } else {
  681. setting.value.airplus = setting.value.airplus.map((i: any) => {
  682. const result: any = {}
  683. for (const key in i) {
  684. if (Object.prototype.hasOwnProperty.call(i, key)) {
  685. result[key] = Number(i[key])
  686. }
  687. }
  688. return result
  689. })
  690. }
  691. setting.value.cbm = JSON.parse(setting.value.cbm)
  692. if (!Array.isArray(setting.value.cbm)) {
  693. setting.value.cbm = []
  694. } else {
  695. setting.value.cbm = setting.value.cbm.map((i: any) => {
  696. const result: any = {}
  697. for (const key in i) {
  698. if (Object.prototype.hasOwnProperty.call(i, key)) {
  699. result[key] = Number(i[key])
  700. }
  701. }
  702. return result
  703. })
  704. }
  705. delete setting.value.admin_id
  706. delete setting.value.id
  707. delete setting.value.is_del
  708. delete setting.value.update_time
  709. delete setting.value.create_time
  710. delete setting.value.delete_time
  711. // 把浅层的几个属性全部转换成数字. 方便后续的计算
  712. for (const key in setting.value) {
  713. if (
  714. Object.prototype.hasOwnProperty.call(setting.value, key) &&
  715. typeof setting.value[key] === 'string'
  716. ) {
  717. setting.value[key] = Number(setting.value[key])
  718. }
  719. }
  720. initProductInfo()
  721. initForm([], true)
  722. })
  723. }
  724. let close = (done = {} as any) => {
  725. $emit('update:visible', false)
  726. imageList.value = []
  727. if (typeof done === 'function') done()
  728. }
  729. let resetData = () => {
  730. formData.value = {
  731. cal_city: {
  732. local_city: '',
  733. },
  734. cal_shipment_method: {},
  735. }
  736. exportForm.value = {
  737. pdf_city: '',
  738. cycle_name: '',
  739. exchange: '',
  740. days: '30',
  741. gst_name: '+GST',
  742. notes: '',
  743. other_notes: '',
  744. saleperson: '',
  745. }
  746. }
  747. // 总箱数. 购买数量/每箱数量.
  748. let computedBoxNumber = computed(() => {
  749. if (productInfo.value.number?.length) {
  750. return productInfo.value.number.map((i: any) =>
  751. mathjs.chain(i).divide(productInfo.value.in_package).done(),
  752. )
  753. } else {
  754. return []
  755. }
  756. })
  757. // 单箱体积. 立方厘米. 长*宽*高
  758. let computedBulk = computed(() => {
  759. return mathjs
  760. .chain(productInfo.value.package_size_length || 1)
  761. .multiply(productInfo.value.package_size_width || 1)
  762. .multiply(productInfo.value.package_size_height || 1)
  763. .done()
  764. })
  765. // 是否重货. 每箱毛重 大于等于 (每箱体积 / 5000) 则为重货.
  766. let isHeavyGoods = computed(() => {
  767. if (
  768. productInfo.value.package_weight >
  769. mathjs.chain(computedBulk.value).divide(5000).done()
  770. ) {
  771. return {
  772. flag: true,
  773. label: '重货',
  774. }
  775. } else {
  776. return {
  777. flag: false,
  778. label: '轻货',
  779. }
  780. }
  781. })
  782. // 是否重货. 空+派 配送方式专属的 轻重货计算逻辑, 与标准的计算区别在于一个除6000一个除5000
  783. let isHeavyGoodsPlus = computed(() => {
  784. if (
  785. productInfo.value.package_weight >
  786. mathjs.chain(computedBulk.value).divide(6000).done()
  787. ) {
  788. return {
  789. flag: true,
  790. label: '重货',
  791. }
  792. } else {
  793. return {
  794. flag: false,
  795. label: '轻货',
  796. }
  797. }
  798. })
  799. // 界面上写的是总重量, 实际上应该理解成负重系数, 即轻重货占不同体积, 货运得收不同费用维持利润.
  800. // 重货是货物重量本身, 即每箱毛重*箱数, 轻货则是每箱体积*箱数/5000
  801. let computedTotalWeight = computed(() => {
  802. if (!computedBoxNumber.value.length) return []
  803. if (isHeavyGoods.value.flag) {
  804. // 重货
  805. return computedBoxNumber.value.map((i: number) => {
  806. return mathjs
  807. .chain(
  808. // 重量浮动比. 在运费参数里面设置的.
  809. mathjs
  810. .chain(Number(setting.value.rate_weight || 0))
  811. .divide(100)
  812. .add(1)
  813. .done(),
  814. )
  815. .multiply(productInfo.value.package_weight)
  816. .multiply(i)
  817. .done()
  818. })
  819. } else {
  820. // 轻货
  821. return computedBoxNumber.value.map((i: number) => {
  822. return mathjs.chain(computedBulk.value).multiply(i).divide(5000).done()
  823. })
  824. }
  825. })
  826. // 空+派 方式的(总重量)负重系数.
  827. let computedTotalWeightPlus = computed(() => {
  828. if (!computedBoxNumber.value.length) return []
  829. if (isHeavyGoodsPlus.value.flag) {
  830. // 重货
  831. return computedBoxNumber.value.map((i: number) => {
  832. return mathjs
  833. .chain(
  834. // 重量浮动比. 在运费参数里面设置的.
  835. mathjs
  836. .chain(Number(setting.value.rate_weight || 0))
  837. .divide(100)
  838. .add(1)
  839. .done(),
  840. )
  841. .multiply(productInfo.value.package_weight)
  842. .multiply(i)
  843. .done()
  844. })
  845. } else {
  846. // 轻货
  847. return computedBoxNumber.value.map((i: number) => {
  848. return mathjs.chain(computedBulk.value).multiply(i).divide(6000).done()
  849. })
  850. }
  851. })
  852. // 总体积CBM. 单箱体积*箱数*浮动 / 一百万
  853. let computedTotalBulk = computed(() => {
  854. if (!computedBoxNumber.value.length) return []
  855. return computedBoxNumber.value.map((i: number) => {
  856. return mathjs
  857. .chain(
  858. // 体积浮动比. 在运费参数里面设置的.
  859. mathjs.chain(Number(setting.value.rate_bulk)).divide(100).add(1).done(),
  860. )
  861. .multiply(computedBulk.value)
  862. .multiply(i)
  863. .divide(1000000)
  864. .done()
  865. })
  866. })
  867. // 返回值会有两个子数组. 第一个是重货的, 第二个是轻货的,
  868. // 每个数组里有两项, 分别是计算公式的参数1和2.
  869. let computedCityFreightParams = computed(() => {
  870. if (formData.value.cal_city?.local_city) {
  871. return setting.value.city_list[formData.value.cal_city.local_city]
  872. }
  873. return []
  874. })
  875. // 国内运费
  876. // let computedLocalFreight = computed(() => {
  877. // if (isHeavyGoodsPlus.value.flag) {
  878. // return this.computedTotalWeight((i:number) => {
  879. // return mathjs.chain(setting.value.cn_price_heavy).multiply(i).done()
  880. // })
  881. // }
  882. // return computedTotalBulk.value.map((i:number) => {
  883. // return mathjs.chain(setting.value.cn_price).multiply(i).done()
  884. // })
  885. // })
  886. let initProductInfo = () => {
  887. const temp = cloneDeep(dataForCalc)
  888. if (Array.isArray(temp.product_image)) {
  889. imageList.value = temp.product_image.map((img: string) => {
  890. return $mediaRegExp.test(img)
  891. ? img
  892. : import.meta.env.VITE_APP_OSS_PREFIX + img
  893. })
  894. }
  895. temp.cost_name = []
  896. temp.cost_price = []
  897. if (temp.cost_list && temp.cost_list.length > 2) {
  898. const t = JSON.parse(temp.cost_list)
  899. t.forEach((item: any) => {
  900. temp.cost_name.push(item.cost_name)
  901. temp.cost_price.push(parseFloat(item.cost_price))
  902. })
  903. }
  904. temp.number = []
  905. temp.price = []
  906. temp.days = []
  907. if (temp.price_list && temp.price_list.length > 2) {
  908. const t = JSON.parse(temp.price_list)
  909. // temp.number 按数量从小到大排序
  910. t.sort(
  911. (a: any, b: any) => parseFloat(a.number) - parseFloat(b.number),
  912. ).forEach((item: any) => {
  913. temp.number.push(parseFloat(item.number))
  914. temp.price.push(parseFloat(item.price))
  915. temp.days.push(parseFloat(item.days))
  916. })
  917. }
  918. // 之前保存到数据库的计价信息
  919. if (typeof temp.save_cal === 'string' && temp.save_cal.length > 2) {
  920. temp.save_cal = JSON.parse(temp.save_cal)
  921. } else {
  922. temp.save_cal = {}
  923. }
  924. // 初始化之前选择的城市
  925. if (temp.save_cal.cal_city) {
  926. formData.value.cal_city.local_city = temp.save_cal.cal_city.local_city
  927. }
  928. productInfo.value = temp
  929. }
  930. /**
  931. * 根据 productInfo 生成表单, 包括step2的和部分step3的数据.
  932. */
  933. let initForm = (switchStatus = [] as any[], useOldFormData = true) => {
  934. formList.value = []
  935. step3FormList.value = []
  936. if (productInfo.value.number?.length) {
  937. // 保存的数据库里面的中途配送数据
  938. const oldMidWayData = productInfo.value.save_cal.cal_shipment_method || {}
  939. productInfo.value.number.forEach((item: any, index: number) => {
  940. const t: any = {}
  941. t[`method_0_${item}`] = 'dhl'
  942. t[`method_2_${item}`] = 'lcl'
  943. if (useOldFormData) {
  944. t[`method_0_${item}`] = oldMidWayData[`method_0_${item}`] || 'dhl'
  945. t[`method_2_${item}`] = oldMidWayData[`method_2_${item}`] || 'lcl'
  946. }
  947. t[`method_3_${item}`] = ''
  948. t[`method_4_${item}`] = ''
  949. // 这5个是开关
  950. t[`0_${item}`] = 'off'
  951. t[`1_${item}`] = 'off'
  952. t[`2_${item}`] = 'off'
  953. t[`3_${item}`] = 'off'
  954. t[`4_${item}`] = 'off'
  955. if (useOldFormData) {
  956. // 上一次编辑中, 保存到数据库的数据记录
  957. t[`0_${item}`] = oldMidWayData[`0_${item}`] || 'off'
  958. t[`1_${item}`] = oldMidWayData[`1_${item}`] || 'off'
  959. t[`2_${item}`] = oldMidWayData[`2_${item}`] || 'off'
  960. t[`3_${item}`] = oldMidWayData[`3_${item}`] || 'off'
  961. t[`4_${item}`] = oldMidWayData[`4_${item}`] || 'off'
  962. }
  963. if (switchStatus.length) {
  964. // 记录当前页面之前已经打开的开关状态, 用在切换城市后的重新初始化逻辑中.
  965. t[`0_${item}`] = switchStatus[index][`0_${item}`] || 'off'
  966. t[`1_${item}`] = switchStatus[index][`1_${item}`] || 'off'
  967. t[`2_${item}`] = switchStatus[index][`2_${item}`] || 'off'
  968. t[`3_${item}`] = switchStatus[index][`3_${item}`] || 'off'
  969. t[`4_${item}`] = switchStatus[index][`4_${item}`] || 'off'
  970. }
  971. // 目的城市运费
  972. t.city_price_0 = 0
  973. t.city_price_1 = 0
  974. t.city_price_2 = 0
  975. t.city_price_3 = 0
  976. t.city_price_4 = 0
  977. // 中途运费总额. 即海运和空运的.
  978. t.midway_price_0 = 0
  979. t.midway_price_1 = 0
  980. t.midway_price_2 = 0
  981. // 这两个是自行输入然后直接显示在step2的中途运费位置, 其他三个是计算出来的,
  982. // 同时也作为step3的运费总成本(AUD)
  983. t.freight_cost_3 = 0
  984. t.freight_cost_4 = 0
  985. // 国内本地运费
  986. t.cn_price_0 = 0
  987. t.cn_price_1 = 0
  988. t.cn_price_2 = 0
  989. // 成本清单
  990. t.product_cost = calcProductCost(index) // 产品成本(AUD)
  991. t.extend_cost = calcExtendCost() // 制版及其它成本(AUD)
  992. t.total_cost = 0 // 总成本(AUD)
  993. // 给html模版分辨是哪个表单的数据
  994. t.number = item
  995. // 计价步骤上貌似没有用到的数据, 但是保存到数据库, 并且该对话框界面回显.
  996. t.fclData = {}
  997. t.lclData = {}
  998. if (useOldFormData) {
  999. const oldData = productInfo.value.save_cal || {}
  1000. if (oldData[`cal_fcl_${item}`]) {
  1001. t.fclData = oldData[`cal_fcl_${item}`]
  1002. t.freight_cost_3 = oldData[`cal_fcl_${item}`].total_fcl
  1003. }
  1004. if (oldData[`cal_lcl_${item}`]) {
  1005. t.lclData = oldData[`cal_lcl_${item}`]
  1006. t.freight_cost_4 = oldData[`cal_lcl_${item}`].total_lcl
  1007. }
  1008. }
  1009. formList.value.push(t)
  1010. })
  1011. const indentUser = Cookies.get('indent-user')
  1012. let r = creatorOptions.filter((i) => i.label === indentUser)
  1013. exportForm.value = {
  1014. pdf_city: productInfo.value.save_cal.pdf_city || cityList.value[0],
  1015. exchange: productInfo.value.save_cal.exchange || '',
  1016. days: productInfo.value.save_cal.days || 30,
  1017. gst_name: productInfo.value.save_cal.gst_name || '+GST',
  1018. notes: productInfo.value.save_cal.notes || '',
  1019. other_notes: productInfo.value.save_cal.other_notes || '',
  1020. saleperson:
  1021. productInfo.value.save_cal.saleperson || (r.length ? r[0].value : ''),
  1022. }
  1023. }
  1024. console.log(formList.value, 'formList')
  1025. setFreight()
  1026. if (useOldFormData) {
  1027. // 仅页面初始化时会执行到这里
  1028. generateStep3Form({ withOldData: true })
  1029. }
  1030. }
  1031. const onCityChange = (str: string) => {
  1032. // 没保存计价之前, 切换城市会改变pdf_city. 保存之后, 再怎么切换也用保存的数据做默认数据, 除非手动更改pdf_city
  1033. exportForm.value.pdf_city =
  1034. productInfo.value.save_cal.pdf_city || str || cityList.value[0]
  1035. }
  1036. let reGenerateFormAfterCityChange = () => {
  1037. const temp: any[] = formList.value.map((i, index) => {
  1038. const result: any = {}
  1039. result[`0_${productInfo.value.number[index]}`] =
  1040. i[`0_${productInfo.value.number[index]}`]
  1041. result[`1_${productInfo.value.number[index]}`] =
  1042. i[`1_${productInfo.value.number[index]}`]
  1043. result[`2_${productInfo.value.number[index]}`] =
  1044. i[`2_${productInfo.value.number[index]}`]
  1045. result[`3_${productInfo.value.number[index]}`] =
  1046. i[`3_${productInfo.value.number[index]}`]
  1047. result[`4_${productInfo.value.number[index]}`] =
  1048. i[`4_${productInfo.value.number[index]}`]
  1049. result[`method_0_${productInfo.value.number[index]}`] =
  1050. i[`method_0_${productInfo.value.number[index]}`]
  1051. result[`method_2_${productInfo.value.number[index]}`] =
  1052. i[`method_2_${productInfo.value.number[index]}`]
  1053. return result
  1054. })
  1055. initForm(temp)
  1056. // 切换城市后, 理论上所有数据都应该重置
  1057. generateStep3Form({ withOldData: false })
  1058. }
  1059. /**
  1060. * 切换运送方式之后, 重新计算中途运费和生成step3的表单内容.
  1061. */
  1062. let reGenerateFormAfterMidwayTypeChange = (p: any) => {
  1063. setFreight()
  1064. generateStep3Form(p || {})
  1065. }
  1066. let generateStep3Form = (p = {}) => {
  1067. const config = Object.assign({}, { withOldData: true, x: -1, y: -1 }, p || {})
  1068. const withOldData = config.withOldData
  1069. const labelList = ['快递', '空+派', '海运', 'DTD', 'LCL散货']
  1070. const result: any[] = []
  1071. const oldData = productInfo.value.save_cal
  1072. formList.value.forEach((i: any, formRow) => {
  1073. // console.log(i, '表单行数据')
  1074. for (let n = 0; n < 5; n++) {
  1075. if (i[`${n}_${i.number}`] === 'on') {
  1076. // console.log(config, 'config')
  1077. let temp = Object.assign({}, step3FormDemo.value, {
  1078. tabLabel: `${i.number} ${labelList[n]}`,
  1079. number: i.number,
  1080. typeNumber: n,
  1081. cn_freight_cost: 0,
  1082. product_cost: i.product_cost,
  1083. extend_cost: i.extend_cost,
  1084. total_cost: i.total_cost,
  1085. })
  1086. if (n <= 2) {
  1087. console.log(i, 'i')
  1088. temp.cn_freight_cost = savePrecision(i[`cn_price_${n}`]) // 这个是人民币
  1089. temp.local_freight_cost = savePrecision(i[`city_price_${n}`]).toFixed(
  1090. 2,
  1091. )
  1092. temp.add_freight_cost = savePrecision(i[`city_price_${n}`]).toFixed(2)
  1093. // 记录中途运费, 用在step3表单项变更后的重复计算
  1094. temp.midway_price = i[`midway_price_${n}`]
  1095. temp.freight_cost = mathjs
  1096. .chain(i[`midway_price_${n}`])
  1097. .add(i[`city_price_${n}`])
  1098. .add(
  1099. mathjs
  1100. .chain(i[`cn_price_${n}`])
  1101. .divide(setting.value.rate_rmb_aud)
  1102. .done(),
  1103. )
  1104. .done()
  1105. .toFixed(2)
  1106. // 用demo默认值是重新计算的数据. 如果是初始化时需要用保存到数据库的数据覆盖掉这个.
  1107. temp.total_cost = mathjs
  1108. .chain(i.product_cost)
  1109. .add(i.extend_cost)
  1110. .add(temp.freight_cost)
  1111. .add(
  1112. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1113. ? oldData[`cal_quote_${n}_${i.number}`].tax_fee ||
  1114. step3FormDemo.value.tax_fee
  1115. : step3FormDemo.value.tax_fee,
  1116. )
  1117. .add(
  1118. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1119. ? oldData[`cal_quote_${n}_${i.number}`].gatt_tax_fee ||
  1120. step3FormDemo.value.gatt_tax_fee
  1121. : step3FormDemo.value.gatt_tax_fee,
  1122. )
  1123. .add(
  1124. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1125. ? oldData[`cal_quote_${n}_${i.number}`].review_cost ||
  1126. step3FormDemo.value.review_cost
  1127. : step3FormDemo.value.review_cost,
  1128. )
  1129. .done()
  1130. .toFixed(2)
  1131. } else if (n === 3) {
  1132. temp.local_freight_cost = 0
  1133. temp.add_freight_cost = 0
  1134. // 记录中途运费, 用在step3表单项变更后的重复计算
  1135. temp.midway_price = mathjs
  1136. .chain(i[`freight_cost_${n}`])
  1137. .add(i[`city_price_${n}`])
  1138. .done()
  1139. .toFixed(2)
  1140. temp.freight_cost = mathjs
  1141. .chain(temp.midway_price)
  1142. .add(
  1143. mathjs
  1144. .chain(temp.cn_freight_cost)
  1145. .divide(setting.value.rate_rmb_aud)
  1146. .done(),
  1147. )
  1148. .done()
  1149. .toFixed(2)
  1150. temp.total_cost = mathjs
  1151. .chain(i.product_cost)
  1152. .add(i.extend_cost)
  1153. .add(temp.freight_cost)
  1154. // .add(
  1155. // mathjs
  1156. // .chain(temp.cn_freight_cost)
  1157. // .divide(setting.value.rate_rmb_aud)
  1158. // .done(),
  1159. // )
  1160. .add(
  1161. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1162. ? oldData[`cal_quote_${n}_${i.number}`].tax_fee ||
  1163. step3FormDemo.value.tax_fee
  1164. : step3FormDemo.value.tax_fee,
  1165. )
  1166. .add(
  1167. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1168. ? oldData[`cal_quote_${n}_${i.number}`].gatt_tax_fee ||
  1169. step3FormDemo.value.gatt_tax_fee
  1170. : step3FormDemo.value.gatt_tax_fee,
  1171. )
  1172. .add(
  1173. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1174. ? oldData[`cal_quote_${n}_${i.number}`].review_cost ||
  1175. step3FormDemo.value.review_cost
  1176. : step3FormDemo.value.review_cost,
  1177. )
  1178. .done()
  1179. .toFixed(2)
  1180. temp[`cn_price_${n}`] = 0 // 国内运费. 后两种配送方式默认是0
  1181. } else if (n === 4) {
  1182. temp.local_freight_cost = 0
  1183. temp.add_freight_cost = 0
  1184. temp.local_freight_cost = 0
  1185. temp.add_freight_cost = 0
  1186. // 记录中途运费, 用在step3表单项变更后的重复计算
  1187. temp.midway_price = mathjs
  1188. .chain(i[`freight_cost_${n}`])
  1189. .add(i[`city_price_${n}`])
  1190. .done()
  1191. .toFixed(2)
  1192. temp.freight_cost = mathjs
  1193. .chain(temp.midway_price)
  1194. .add(
  1195. mathjs
  1196. .chain(temp.cn_freight_cost)
  1197. .divide(setting.value.rate_rmb_aud)
  1198. .done(),
  1199. )
  1200. .done()
  1201. .toFixed(2)
  1202. // total_lcl 运费总成本
  1203. // price 国内总运费
  1204. temp.total_cost = mathjs
  1205. .chain(i.product_cost)
  1206. .add(i.extend_cost)
  1207. .add(temp.freight_cost)
  1208. // .add(
  1209. // mathjs
  1210. // .chain(temp.cn_freight_cost)
  1211. // .divide(setting.value.rate_rmb_aud)
  1212. // .done(),
  1213. // )
  1214. .add(
  1215. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1216. ? oldData[`cal_quote_${n}_${i.number}`].tax_fee ||
  1217. step3FormDemo.value.tax_fee
  1218. : step3FormDemo.value.tax_fee,
  1219. )
  1220. .add(
  1221. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1222. ? oldData[`cal_quote_${n}_${i.number}`].gatt_tax_fee ||
  1223. step3FormDemo.value.gatt_tax_fee
  1224. : step3FormDemo.value.gatt_tax_fee,
  1225. )
  1226. .add(
  1227. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1228. ? oldData[`cal_quote_${n}_${i.number}`].review_cost ||
  1229. step3FormDemo.value.review_cost
  1230. : step3FormDemo.value.review_cost,
  1231. )
  1232. .done()
  1233. .toFixed(2)
  1234. temp[`cn_price_${n}`] = 0 // 国内运费. 后两种配送方式默认是0
  1235. }
  1236. temp.profit = savePrecision(
  1237. // 利润率是整数, 除100算出百分数.
  1238. mathjs
  1239. .chain(
  1240. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1241. ? oldData[`cal_quote_${n}_${i.number}`].profit_margin ||
  1242. step3FormDemo.value.profit_margin
  1243. : step3FormDemo.value.profit_margin,
  1244. )
  1245. .divide(100)
  1246. .multiply(temp.total_cost)
  1247. .done(),
  1248. ).toFixed(2)
  1249. temp.sold_price = savePrecision(
  1250. mathjs
  1251. .chain(temp.total_cost)
  1252. .multiply(
  1253. mathjs
  1254. .chain(
  1255. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1256. ? oldData[`cal_quote_${n}_${i.number}`].profit_margin ||
  1257. step3FormDemo.value.profit_margin
  1258. : step3FormDemo.value.profit_margin,
  1259. )
  1260. .add(100)
  1261. .divide(100)
  1262. .done(),
  1263. )
  1264. .done(),
  1265. ).toFixed(2)
  1266. temp.sold_unit = mathjs
  1267. .chain(
  1268. Math.ceil(
  1269. Number(
  1270. mathjs
  1271. .chain(temp.sold_price)
  1272. .subtract(temp.add_freight_cost)
  1273. .subtract(
  1274. withOldData && oldData[`cal_quote_${n}_${i.number}`]
  1275. ? oldData[`cal_quote_${n}_${i.number}`].setup_cost
  1276. : step3FormDemo.value.setup_cost,
  1277. )
  1278. .divide(i.number)
  1279. .multiply(100)
  1280. .done(),
  1281. ),
  1282. ),
  1283. )
  1284. .divide(100)
  1285. .done()
  1286. .toFixed(2)
  1287. // exportForm.value[`zdy_date_${n}_${i.number}`] = ''
  1288. // exportForm.value[`cycle_name_${n}_${i.number}`] = 'weeks'
  1289. // 行和列只要有一项不等, 就不是点开关的那个, 就应该用已保存数据覆盖
  1290. // if (withOldData && (config.y !== n || config.x !== formRow)) {
  1291. // 出了切换城市, 全部用已保存的数据覆盖
  1292. if (withOldData) {
  1293. if (oldData[`cal_quote_${n}_${i.number}`]) {
  1294. const cloneData = cloneDeep(oldData[`cal_quote_${n}_${i.number}`])
  1295. cloneData.freight_cost = cloneData.freight
  1296. delete cloneData.freight
  1297. temp = Object.assign(temp, cloneData)
  1298. calcTotalCost(temp) // 如果运费总成本被覆盖, 那总成本会产生误差, 最好是重算一遍.
  1299. }
  1300. exportForm.value[`zdy_date_${n}_${i.number}`] = oldData[
  1301. `zdy_date_${n}_${i.number}`
  1302. ]
  1303. ? oldData[`zdy_date_${n}_${i.number}`]
  1304. : ''
  1305. exportForm.value[`cycle_name_${n}_${i.number}`] = oldData[
  1306. `cycle_name_${n}_${i.number}`
  1307. ]
  1308. ? oldData[`cycle_name_${n}_${i.number}`]
  1309. : 'weeks'
  1310. console.log('覆盖: 行:', formRow + 1, '列:', n)
  1311. } else {
  1312. console.log('重算, 没有覆盖: 行:', config.x + 1, '列:', config.y)
  1313. }
  1314. // console.log(temp, 'temp')
  1315. result.push(temp)
  1316. }
  1317. }
  1318. })
  1319. step3FormList.value = result
  1320. }
  1321. // 设置 中途运费 及 国外当地运费
  1322. let setFreight = () => {
  1323. productInfo.value.number.forEach((item: any, index: number) => {
  1324. // 早起的需求限制3个, 现在暂定放开了. 限制的话, 超过3个的货物数量的运费直接就跳过不计算了.
  1325. // if (index > 2) {
  1326. // return
  1327. // }
  1328. const cityPrice = calcCityPrice(
  1329. computedTotalWeight.value[index],
  1330. computedTotalBulk.value[index],
  1331. )
  1332. // 国外本地运费, dtd 和 lcl散货默认是0, 所以这里只给前三个填充了值.
  1333. formList.value[index].city_price_0 = cityPrice
  1334. formList.value[index].city_price_1 = cityPrice
  1335. formList.value[index].city_price_2 = cityPrice
  1336. // 航空:总重量*空运费单价(AUD) * (1+燃油附加)
  1337. formList.value[index].midway_price_0 = mathjs
  1338. .chain(
  1339. getCurrentPrice(
  1340. formList.value[index][`method_0_${item}`],
  1341. computedTotalWeight.value[index],
  1342. ),
  1343. )
  1344. .multiply(computedTotalWeight.value[index])
  1345. .multiply(mathjs.chain(setting.value.rate_fuel).divide(100).add(1).done())
  1346. .done()
  1347. // 空+派 与航空的计算方式基本一致。
  1348. // 差异点为,重轻货判断及负重系数计算时,除以6000, 燃油附加是另外的字段.
  1349. formList.value[index].midway_price_1 = mathjs
  1350. .chain(getCurrentPricePlus(computedTotalWeightPlus.value[index]))
  1351. .multiply(computedTotalWeightPlus.value[index])
  1352. .multiply(
  1353. mathjs.chain(setting.value.rate_fuelplus).divide(100).add(1).done(),
  1354. )
  1355. .done()
  1356. // 海运 CBM * 基础参数里面的海运费. 旧后台这一项的计算有误差, cbm用了约进两位数之后的值来计算.
  1357. formList.value[index].midway_price_2 = mathjs
  1358. .chain(computedTotalBulk.value[index])
  1359. .multiply(setting.value.sea_fee)
  1360. .done()
  1361. const cn_price = calcLocalPrice(index)
  1362. // 国内运费
  1363. formList.value[index].cn_price_0 = cn_price
  1364. formList.value[index].cn_price_1 = cn_price
  1365. formList.value[index].cn_price_2 = cn_price
  1366. })
  1367. }
  1368. // 目标城市的快递费用计算. 这个判断轻重货时不用区分 空+派 的 /6000
  1369. let calcCityPrice = (heavy: number, bulk: number) => {
  1370. const p = computedCityFreightParams.value
  1371. if (!p.length) return 0
  1372. if (isHeavyGoods.value.flag) {
  1373. return p[0][0] + (p[0][1] / 50) * heavy
  1374. } else {
  1375. return p[1][0] + p[1][1] * bulk
  1376. }
  1377. }
  1378. // 目标城市的快递费用计算. 空+派方式的, 这种方式轻重货判断计算公式不一样
  1379. // let calcCityPricePlus = (heavy: number, bulk: number) => {
  1380. // const p = computedCityFreightParams.value
  1381. // if (!p.length) return 0
  1382. // if (isHeavyGoodsPlus.value.flag) {
  1383. // return p[0][0] + (p[0][1] / 50) * heavy
  1384. // } else {
  1385. // return p[1][0] + p[1][1] * bulk
  1386. // }
  1387. // }
  1388. // 国内运费. 轻重货计算公式不同
  1389. let calcLocalPrice = (index: number) => {
  1390. if (isHeavyGoods.value.flag) {
  1391. return mathjs
  1392. .chain(setting.value.cn_price_heavy)
  1393. .multiply(computedTotalWeight.value[index])
  1394. .done()
  1395. } else {
  1396. return mathjs
  1397. .chain(setting.value.cn_price)
  1398. .multiply(computedTotalBulk.value[index])
  1399. .done()
  1400. }
  1401. }
  1402. // 打样费用 和 额外费用(报价信息里面的出厂价-额外费用), 再除以汇率
  1403. let calcExtendCost = () => {
  1404. const reduceCost = productInfo.value.cost_price.reduce(
  1405. (total: number, i: number) => {
  1406. total = total + i
  1407. return total
  1408. },
  1409. 0,
  1410. )
  1411. const extendCost = mathjs
  1412. .chain(reduceCost)
  1413. .add(Number(productInfo.value.demo_cost) || 0)
  1414. .divide(setting.value.rate_rmb_aud)
  1415. .done()
  1416. return extendCost
  1417. }
  1418. // 产品成本 = 单价 * 数量 / 汇率
  1419. let calcProductCost = (index: number) => {
  1420. return mathjs
  1421. .chain(productInfo.value.number[index])
  1422. .multiply(productInfo.value.price[index])
  1423. .divide(setting.value.rate_rmb_aud)
  1424. .done()
  1425. }
  1426. // 获取 当前重量的 运费单价
  1427. let getCurrentPrice = (key: string | number, heavy: number) => {
  1428. const target = setting.value[`${key}_airline`]
  1429. let result = 0
  1430. if (Array.isArray(target) && target.length) {
  1431. result = target.findIndex((i: any) => i.min <= heavy && i.max > heavy)
  1432. }
  1433. return target[result].price
  1434. }
  1435. // 空+ 派
  1436. let getCurrentPricePlus = (heavy: number) => {
  1437. const target = setting.value.airplus
  1438. let result = 0
  1439. if (Array.isArray(target) && target.length) {
  1440. result = target.findIndex((i: any) => i.min <= heavy && i.max > heavy)
  1441. }
  1442. return target[result].price
  1443. }
  1444. // 开关切换前的点击捕获, 检查前提数据是否已输入, 没有的话不允许打开开关. 旧后台的交互.
  1445. let captureSwitchChange = (e: any, obj: any, n: number) => {
  1446. if (n === 3) {
  1447. if (typeof obj.freight_cost_3 !== 'number' || obj.freight_cost_3 <= 0) {
  1448. ElMessage.warning('请先点击编辑, 填写相关数据, 再打开开关')
  1449. e.preventDefault()
  1450. e.stopPropagation()
  1451. }
  1452. } else if (n === 4) {
  1453. if (typeof obj.freight_cost_4 !== 'number' || obj.freight_cost_4 <= 0) {
  1454. ElMessage.warning('请先点击编辑, 填写相关数据, 再打开开关')
  1455. e.preventDefault()
  1456. e.stopPropagation()
  1457. }
  1458. }
  1459. }
  1460. let changeCOO = (form: any, value: any) => {
  1461. // 因为设置了active value, value变量不再是布尔值
  1462. if (value === 'on') {
  1463. form.tax = 0
  1464. onForm3ItemChange(form, 'tax')
  1465. } else {
  1466. form.tax = 5
  1467. onForm3ItemChange(form, 'tax')
  1468. }
  1469. }
  1470. let calcTaxFee = (form: any) => {
  1471. form.tax_fee = savePrecision(
  1472. mathjs.chain(form.product_cost).multiply(form.tax).divide(100).done(),
  1473. ).toFixed(2)
  1474. }
  1475. // 利润 = 售卖总价 - 总成本
  1476. let calcProfit = (form: any) => {
  1477. form.profit = savePrecision(
  1478. mathjs
  1479. .chain(form.sold_price)
  1480. // .subtract(form.setup_cost)
  1481. // .subtract(form.add_freight_cost)
  1482. .subtract(form.total_cost)
  1483. .done(),
  1484. ).toFixed(2)
  1485. }
  1486. let calcProfitMargin = (form: any) => {
  1487. form.profit_margin = savePrecision(
  1488. mathjs.chain(form.profit).divide(form.total_cost).multiply(100).done(),
  1489. ).toFixed(2)
  1490. }
  1491. let calcTotalCost = (form: any) => {
  1492. form.total_cost = mathjs
  1493. .chain(form.product_cost)
  1494. .add(form.extend_cost)
  1495. .add(form.freight_cost)
  1496. // .add(
  1497. // mathjs
  1498. // .chain(form.cn_freight_cost)
  1499. // .divide(setting.value.rate_rmb_aud)
  1500. // .done(),
  1501. // )
  1502. .add(form.tax_fee)
  1503. .add(form.gatt_tax_fee)
  1504. .add(form.review_cost)
  1505. .done()
  1506. .toFixed(2)
  1507. }
  1508. /**
  1509. * 用利润率计算售价总价. 总成本 * (利润率 + 100) / 100
  1510. **/
  1511. let calcSoldPriceByProfitMargin = (form: any) => {
  1512. form.sold_price = savePrecision(
  1513. mathjs
  1514. .chain(form.total_cost)
  1515. .multiply(mathjs.chain(form.profit_margin).add(100).divide(100).done())
  1516. // .add(form.setup_cost)
  1517. // .add(form.add_freight_cost)
  1518. .done(),
  1519. ).toFixed(2)
  1520. }
  1521. /**
  1522. * 用单价计算售价总价. 单价*数量 + setup cost + add freight cost
  1523. **/
  1524. let calcSoldPriceBySoldUnit = (form: any) => {
  1525. form.sold_price = savePrecision(
  1526. mathjs
  1527. .chain(form.sold_unit)
  1528. .multiply(form.number)
  1529. .add(form.setup_cost)
  1530. .add(form.add_freight_cost)
  1531. .done(),
  1532. ).toFixed(2)
  1533. }
  1534. let onForm3ItemChange = (form: any, key: string) => {
  1535. let dotFlag = false
  1536. if (typeof form[key] === 'string' && /\.$/.test(form[key])) {
  1537. // 处理小数点
  1538. form[key] = form[key].replace(/\.$/, '')
  1539. dotFlag = true
  1540. }
  1541. // 各输入框之间的输入值变动会有联动.
  1542. // 注意, 各 case 里面的调用顺序有影响, 改动之前务必保证你理解当前在做什么.
  1543. switch (key) {
  1544. case 'tax':
  1545. // 影响 税费、总成本、利润率、利润值
  1546. calcTaxFee(form)
  1547. calcTotalCost(form)
  1548. calcProfit(form)
  1549. calcProfitMargin(form)
  1550. break
  1551. case 'review_cost':
  1552. // 影响 总成本、利润率、利润值
  1553. calcTotalCost(form)
  1554. calcProfit(form)
  1555. calcProfitMargin(form)
  1556. break
  1557. case 'cn_freight_cost':
  1558. // 影响 运费总成本、总成本、利润率、利润值
  1559. form.freight_cost = mathjs
  1560. .chain(form.local_freight_cost)
  1561. .add(form.midway_price)
  1562. .add(
  1563. mathjs
  1564. .chain(form.cn_freight_cost)
  1565. .divide(setting.value.rate_rmb_aud)
  1566. .done(),
  1567. )
  1568. .done()
  1569. .toFixed(2)
  1570. calcTotalCost(form)
  1571. calcProfit(form)
  1572. calcProfitMargin(form)
  1573. break
  1574. case 'local_freight_cost':
  1575. // 影响 运费总成本、总成本、售卖总价、利润率. 利润值(不影响)
  1576. form.add_freight_cost = form.local_freight_cost
  1577. form.freight_cost = mathjs
  1578. .chain(form.local_freight_cost)
  1579. .add(form.midway_price)
  1580. .add(
  1581. mathjs
  1582. .chain(form.cn_freight_cost)
  1583. .divide(setting.value.rate_rmb_aud)
  1584. .done(),
  1585. )
  1586. .done()
  1587. .toFixed(2)
  1588. calcTotalCost(form)
  1589. calcProfitMargin(form)
  1590. calcSoldPriceByProfitMargin(form)
  1591. break
  1592. case 'add_freight_cost':
  1593. // 影响 售卖总价、利润率、利润值
  1594. // fallthrough
  1595. case 'setup_cost':
  1596. // 影响 售卖总价、利润值、利润率
  1597. // fallthrough
  1598. case 'sold_unit':
  1599. // 直接乘算出售卖总价, 更新利润率、利润值
  1600. calcSoldPriceBySoldUnit(form)
  1601. calcProfit(form)
  1602. calcProfitMargin(form)
  1603. break
  1604. case 'profit_margin':
  1605. // 影响 利润值、售卖总价、售卖单价
  1606. calcSoldPriceByProfitMargin(form)
  1607. calcProfit(form)
  1608. form.sold_unit = mathjs
  1609. .chain(
  1610. Math.ceil(
  1611. Number(
  1612. mathjs
  1613. .chain(form.sold_price)
  1614. .subtract(form.add_freight_cost)
  1615. .subtract(form.setup_cost)
  1616. .divide(form.number)
  1617. .multiply(100)
  1618. .done(),
  1619. ),
  1620. ),
  1621. )
  1622. .divide(100)
  1623. .done()
  1624. .toFixed(2)
  1625. break
  1626. case 'gatt_tax_fee':
  1627. calcTotalCost(form)
  1628. calcProfit(form)
  1629. calcProfitMargin(form)
  1630. break
  1631. default:
  1632. // 默认不做任何处理
  1633. break
  1634. }
  1635. if (dotFlag) {
  1636. form[key] = form[key] + '.'
  1637. }
  1638. }
  1639. let openDTDDialog = (columnNum: number, rowNum: number) => {
  1640. let a = formList.value[rowNum].fclData.method_fcl
  1641. dtdData.value = {
  1642. rowNum,
  1643. columnNum,
  1644. freight_cost: formList.value[rowNum][`freight_cost_${columnNum}`] || '',
  1645. method_fcl: a !== undefined ? a : '空运',
  1646. }
  1647. dtdVisible.value = true
  1648. }
  1649. let dtdChange = (data: any) => {
  1650. formList.value[dtdData.value.rowNum][
  1651. `freight_cost_${dtdData.value.columnNum}`
  1652. ] = Number(data.freight_cost) || 0
  1653. formList.value[dtdData.value.rowNum].fclData.method_fcl =
  1654. data.method_fcl || ''
  1655. formList.value[dtdData.value.rowNum].fclData.total_fcl =
  1656. Number(data.freight_cost) || 0
  1657. generateStep3Form({ x: dtdData.value.rowNum, y: dtdData.value.columnNum })
  1658. }
  1659. let openLCLDialog = (columnNum: number, rowNum: number) => {
  1660. lclData.value = {
  1661. rowNum,
  1662. columnNum,
  1663. heavy: computedTotalWeight.value[rowNum],
  1664. freight_cost: formList.value[rowNum][`freight_cost_${columnNum}`] || '',
  1665. margin_lcl: formList.value[rowNum].lclData.margin_lcl || '',
  1666. unit_lcl: formList.value[rowNum].lclData.unit_lcl || '',
  1667. price: formList.value[rowNum].lclData.price || '',
  1668. }
  1669. lclVisible.value = true
  1670. }
  1671. let lclChange = (data: any) => {
  1672. // 这个是 运输总成本, 会添加到 step3form 里面用于计算
  1673. formList.value[lclData.value.rowNum][
  1674. `freight_cost_${lclData.value.columnNum}`
  1675. ] = Number(data.freight_cost) || 0
  1676. // 这四个保存到数据库的, total_lcl其实就是 运输总成本
  1677. formList.value[lclData.value.rowNum].lclData.unit_lcl =
  1678. Number(data.unit_lcl) || 0
  1679. formList.value[lclData.value.rowNum].lclData.price = Number(data.price) || 0
  1680. formList.value[lclData.value.rowNum].lclData.margin_lcl =
  1681. Number(data.margin_lcl) || 0
  1682. formList.value[lclData.value.rowNum].lclData.total_lcl =
  1683. Number(data.freight_cost) || 0
  1684. generateStep3Form({ x: lclData.value.rowNum, y: lclData.value.columnNum })
  1685. }
  1686. let isExport = ref(0)
  1687. let checkForm = (type = 1) => {
  1688. // 利用引用传值变更 formData 的内容
  1689. const method = formData.value.cal_shipment_method
  1690. formList.value.forEach((item) => {
  1691. for (let i = 0; i < 5; i++) {
  1692. if (item[`${i}_${item.number}`] === 'on') {
  1693. method[`${i}_${item.number}`] = 'on'
  1694. }
  1695. }
  1696. method[`method_0_${item.number}`] = item[`method_0_${item.number}`]
  1697. method[`method_2_${item.number}`] = item[`method_2_${item.number}`]
  1698. if (item.lclData && item.lclData.total_lcl) {
  1699. formData.value[`cal_lcl_${item.number}`] = cloneDeep(item.lclData)
  1700. }
  1701. if (item.fclData && item.fclData.total_fcl) {
  1702. formData.value[`cal_fcl_${item.number}`] = cloneDeep(item.fclData)
  1703. }
  1704. })
  1705. step3FormList.value.forEach((item) => {
  1706. formData.value[`cal_quote_${item.typeNumber}_${item.number}`] = {
  1707. coo_certificate: item.coo_certificate, // coo 开关
  1708. tax: item.tax, // 税点 coo打开则是0, 关闭默认是5
  1709. tax_fee: item.tax_fee, // 税费 coo打开则是0, 需要根据税点计算
  1710. gatt_tax_fee: item.gatt_tax_fee, // 入口报关费用
  1711. review_cost: item.review_cost, // 验货费
  1712. cn_freight_cost: item.cn_freight_cost, // 国内运费总价
  1713. local_freight_cost: item.local_freight_cost, // 国外本地运费
  1714. add_freight_cost: item.add_freight_cost, // 本地收费
  1715. freight: savePrecision(item.freight_cost), // 运费总成本
  1716. setup_cost: item.setup_cost, // Set Up Cost
  1717. sold_unit: item.sold_unit, // 售卖单价
  1718. sold_price: item.sold_price, // 售卖总价
  1719. profit_margin: item.profit_margin, // mark up 利润率
  1720. profit: item.profit, // 利润
  1721. }
  1722. })
  1723. const p = Object.assign(
  1724. {
  1725. id: dataForCalc.id || '',
  1726. },
  1727. cloneDeep(formData.value),
  1728. )
  1729. if (isExport.value === 1) p.is_export = 1 // 后端用来区分是否是点了导出
  1730. if (type === 1) {
  1731. saveCalc(Object.assign(p, exportForm.value))
  1732. } else if (type === 2) {
  1733. componentExportFormVisible.value = true
  1734. }
  1735. }
  1736. let saveCalc = (p: any) => {
  1737. loading.value = true
  1738. saveCalcData(p)
  1739. .then((res: any) => {
  1740. if (res.code !== 1) {
  1741. ElNotification({
  1742. type: 'error',
  1743. title: '保存出错了',
  1744. duration: 3000,
  1745. })
  1746. return
  1747. }
  1748. ElNotification({
  1749. type: 'success',
  1750. title: '保存成功',
  1751. duration: 3000,
  1752. })
  1753. $emit('save-price-calc')
  1754. })
  1755. .finally(() => {
  1756. setTimeout(() => {
  1757. loading.value = false
  1758. }, 300)
  1759. })
  1760. }
  1761. let onExportFormSave = (data: any) => {
  1762. exportForm.value = cloneDeep(data)
  1763. checkForm(1)
  1764. // 生成pdf涉及DOM操作, 故变更数据后需要等界面更新,
  1765. // 此处需要nextTick保证生成时数据已经更新到了界面上.
  1766. nextTick(() => {
  1767. generate()
  1768. })
  1769. }
  1770. const compExportQuotaRef = ref()
  1771. let generate = () => {
  1772. if (
  1773. compExportQuotaRef.value.generatePDF &&
  1774. typeof compExportQuotaRef.value.generatePDF === 'function'
  1775. ) {
  1776. compExportQuotaRef.value.generatePDF()
  1777. }
  1778. }
  1779. </script>
  1780. <style lang="scss">
  1781. .compnent-price-calc {
  1782. .custom-calc-price-dialog {
  1783. margin-top: 0 !important;
  1784. margin-bottom: 0 !important;
  1785. height: 100vh;
  1786. .el-dialog__body {
  1787. max-height: calc(100vh - 56px);
  1788. overflow-y: scroll;
  1789. overflow-x: auto;
  1790. padding: 4px 0 0;
  1791. }
  1792. }
  1793. .step-3 {
  1794. input[type='number'] {
  1795. -moz-appearance: textfield;
  1796. appearance: textfield;
  1797. &:hover {
  1798. -moz-appearance: textfield;
  1799. appearance: textfield;
  1800. &::-webkit-inner-spin-button,
  1801. &::-webkit-outer-spin-button {
  1802. -webkit-appearance: none;
  1803. margin: 0;
  1804. }
  1805. }
  1806. &::-webkit-inner-spin-button,
  1807. &::-webkit-outer-spin-button {
  1808. -webkit-appearance: none;
  1809. margin: 0;
  1810. }
  1811. }
  1812. }
  1813. }
  1814. </style>
  1815. <style lang="scss" scoped>
  1816. @use './styles/index.scss';
  1817. </style>