index.vue 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534
  1. <template>
  2. <div class="w-[100vw] bg-white page-cargo-consolidation">
  3. <div
  4. v-loading="loading"
  5. class="pt-2 w-[100%] min-h-[100vh]"
  6. >
  7. <el-form
  8. style="width: 100%"
  9. inline
  10. :loading="loading"
  11. @submit.prevent="getList"
  12. >
  13. <el-form-item label="ETD Range">
  14. <el-date-picker
  15. v-model="dateRange"
  16. type="daterange"
  17. unlink-panels
  18. clearable
  19. start-placeholder="Start date"
  20. end-placeholder="End date"
  21. :shortcuts="dateShortcuts"
  22. />
  23. </el-form-item>
  24. <el-form-item>
  25. <el-tooltip content="时间范围最好不要选太大, 不然数据太多会卡">
  26. <el-button
  27. class="custom-button"
  28. @click="getList"
  29. >
  30. Search
  31. </el-button>
  32. </el-tooltip>
  33. </el-form-item>
  34. </el-form>
  35. <el-tabs v-model="currentTab">
  36. <el-tab-pane
  37. v-for="tab in finalTabs"
  38. :key="tab.value"
  39. :label="tab.label"
  40. :name="tab.value"
  41. ></el-tab-pane>
  42. </el-tabs>
  43. <el-table
  44. border
  45. :header-cell-style="{ backgroundColor: 'rgb(227, 241, 253)' }"
  46. :data="computedList"
  47. highlight-current-row
  48. style="width: 100%"
  49. max-height="330"
  50. @row-click="($e) => getSubList($e)"
  51. >
  52. <el-table-column
  53. prop="Name"
  54. label="船名&航次"
  55. min-width="500"
  56. />
  57. <el-table-column
  58. prop="Forwarder"
  59. label="货代"
  60. width="100"
  61. />
  62. <el-table-column
  63. prop="ETD"
  64. label="ETD"
  65. width="100"
  66. />
  67. <el-table-column
  68. prop="ATD"
  69. label="ATD"
  70. width="100"
  71. />
  72. <el-table-column
  73. prop="ETA"
  74. label="ETA"
  75. width="100"
  76. />
  77. <el-table-column
  78. prop="ATA"
  79. label="ATA"
  80. width="100"
  81. />
  82. <el-table-column
  83. prop="Cut_Off_Date"
  84. label="入仓时间"
  85. width="100"
  86. />
  87. <el-table-column
  88. prop="Status"
  89. label="状态"
  90. width="75"
  91. />
  92. <!-- <el-table-column
  93. label="修改时间"
  94. min-width="190"
  95. >
  96. <template #default="scope">
  97. {{ dayjs(scope.row.Modified_Time).format('YYYY-MM-DD HH:mm:ss') }}
  98. </template>
  99. </el-table-column> -->
  100. <el-table-column
  101. prop="GRN"
  102. label="入仓单号"
  103. min-width="200"
  104. />
  105. <el-table-column
  106. prop="Booking_Number"
  107. label="订舱号"
  108. min-width="120"
  109. />
  110. <el-table-column
  111. prop="Container_Number"
  112. label="柜号"
  113. min-width="125"
  114. />
  115. <el-table-column
  116. prop="Carrier"
  117. label="船东"
  118. min-width="100"
  119. />
  120. <el-table-column label="操作">
  121. <template #default="scope">
  122. <el-button
  123. size="small"
  124. type="warning"
  125. link
  126. :disabled="!scope.row.SubscriptionId"
  127. @click="openMapDrawer(scope.row)"
  128. >
  129. 查看轨迹
  130. </el-button>
  131. </template>
  132. </el-table-column>
  133. </el-table>
  134. <div
  135. v-show="currentRow.Name?.length"
  136. class="flex justify-between mt-8"
  137. >
  138. <div class="flex">
  139. <!-- <div class="flex items-center mr-2">
  140. <span class="min-w-[150px]">选中的船名&航次:&nbsp;</span>
  141. <div class="text-red-700 font-bold">
  142. {{ currentRow.Name }}
  143. </div>
  144. </div> -->
  145. <div class="flex flex-wrap min-w-[800px] mr-2">
  146. <!-- ['可用', '已截仓'].includes(currentRow.Status) && -->
  147. <el-input
  148. v-if="
  149. currentTab === 'Arrangement' &&
  150. [
  151. '4791186000259693001',
  152. '4791186000022965001',
  153. '4791186000052269001',
  154. ].includes(currentUser)
  155. "
  156. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  157. style="width: 200px; height: 24px; margin-right: 10px"
  158. size="small"
  159. v-model="bookingNumber"
  160. >
  161. <template #append>
  162. <el-button
  163. class="custom-button"
  164. size="small"
  165. style="padding-top: 0; padding-bottom: 0"
  166. @click="updateBookingNumber"
  167. >
  168. 更新订舱号
  169. </el-button>
  170. </template>
  171. </el-input>
  172. <!-- ['可用', '已截仓'].includes(currentRow.Status) && -->
  173. <el-input
  174. v-if="
  175. currentTab === 'Arrangement' &&
  176. [
  177. '4791186000259693001',
  178. '4791186000022965001',
  179. '4791186000052269001',
  180. ].includes(currentUser)
  181. "
  182. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  183. style="width: 200px; height: 24px; margin-right: 10px"
  184. size="small"
  185. v-model="containerNumber"
  186. >
  187. <template #append>
  188. <el-button
  189. class="custom-button"
  190. size="small"
  191. style="padding-top: 0; padding-bottom: 0"
  192. @click="updateContainerNumber"
  193. >
  194. 更新柜号
  195. </el-button>
  196. </template>
  197. </el-input>
  198. <el-button
  199. v-if="
  200. currentTab === 'Arrangement' &&
  201. ['可用', '已截仓'].includes(currentRow.Status) &&
  202. [
  203. '4791186000259693001',
  204. '4791186000022965001',
  205. '4791186000052269001',
  206. ].includes(currentUser)
  207. "
  208. size="small"
  209. type="danger"
  210. @click="ensure"
  211. >
  212. 确认集货
  213. </el-button>
  214. <el-button
  215. class="custom-button"
  216. v-if="
  217. ['Arrangement', 'my_request'].includes(currentTab) &&
  218. ['可用'].includes(currentRow.Status)
  219. "
  220. size="small"
  221. @click="addBulkProduct"
  222. >
  223. 提交大货集货申请
  224. </el-button>
  225. <el-button
  226. class="custom-button"
  227. v-if="
  228. ['Arrangement', 'my_request'].includes(currentTab) &&
  229. ['可用'].includes(currentRow.Status)
  230. "
  231. size="small"
  232. @click="addSample"
  233. >
  234. 提交样品集货申请
  235. </el-button>
  236. <el-button
  237. v-if="['Arrangement', 'my_request'].includes(currentTab)"
  238. :disabled="subList.length < 1"
  239. size="small"
  240. type="danger"
  241. @click="generateSubList"
  242. >
  243. 放弃下方表格改动
  244. </el-button>
  245. <el-button
  246. class="custom-button"
  247. size="small"
  248. :disabled="subList.length < 1"
  249. @click="exportSubTable"
  250. >
  251. 导出Excel文档
  252. </el-button>
  253. <el-button
  254. v-if="
  255. ['Arrangement'].includes(currentTab) ||
  256. (['可用'].includes(currentRow.Status) &&
  257. ['my_request'].includes(currentTab))
  258. "
  259. :disabled="subList.length < 1"
  260. size="small"
  261. type="primary"
  262. class="custom-button small"
  263. @click="commit"
  264. >
  265. 保存更改
  266. </el-button>
  267. </div>
  268. </div>
  269. <div class="flex justify-end min-w-[380px] gap-2">
  270. <div class="flex">总重量: {{ computedWeight }}</div>
  271. <div class="flex">总体积: {{ computedCube }}</div>
  272. <div class="flex">总离岸价: {{ computedTotalFOB }}</div>
  273. </div>
  274. </div>
  275. <el-table
  276. class="mt-4"
  277. size="small"
  278. :data="subList"
  279. style="width: 100%"
  280. :row-style="calcRowStyle"
  281. :header-cell-style="{ backgroundColor: 'rgb(227, 241, 253)' }"
  282. :empty-text="
  283. currentRow.Name?.length
  284. ? '暂无数据'
  285. : '请点击voyage表格其中一行以查询相应记录'
  286. "
  287. border
  288. >
  289. <el-table-column
  290. fixed
  291. type="index"
  292. width="50"
  293. ></el-table-column>
  294. <el-table-column
  295. fixed
  296. label="CRM批次记录"
  297. width="220"
  298. >
  299. <template #default="scope">
  300. <el-select
  301. v-model="scope.row.batchRecord"
  302. size="small"
  303. :remote-method="debounce(search, 1500)"
  304. remote
  305. style="width: 100%"
  306. :loading="loading2"
  307. filterable
  308. clearable
  309. :placeholder="scope.row.Sample ? 'Sample' : ''"
  310. :disabled="
  311. scope.row.Sample ||
  312. !['Arrangement', 'my_request'].includes(currentTab)
  313. "
  314. @change="($e) => onBatchRecordChange($e, scope.$index)"
  315. >
  316. <el-option
  317. v-for="option in computedOption as any[]"
  318. :disabled="!option.isSearch && scope.row.addFlag"
  319. :key="option.id"
  320. :value="option.id"
  321. :label="
  322. option.Name +
  323. (option.Reference ? ` - ${option.Reference}` : '')
  324. "
  325. ></el-option>
  326. </el-select>
  327. </template>
  328. </el-table-column>
  329. <el-table-column
  330. label="备注"
  331. width="110"
  332. fixed
  333. >
  334. <template #default="scope">
  335. <el-input
  336. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  337. v-model="scope.row.User_Notes"
  338. size="small"
  339. :rows="2"
  340. type="textarea"
  341. @change="scope.row.editFlag = true"
  342. ></el-input>
  343. </template>
  344. </el-table-column>
  345. <el-table-column
  346. label="箱数"
  347. width="80"
  348. >
  349. <template #default="scope">
  350. <el-input
  351. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  352. v-model="scope.row.Carton"
  353. size="small"
  354. @change="scope.row.editFlag = true"
  355. ></el-input>
  356. </template>
  357. </el-table-column>
  358. <el-table-column
  359. label="唛头"
  360. width="220"
  361. >
  362. <template #default="scope">
  363. <el-input
  364. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  365. v-model="scope.row.Marks_Nos"
  366. size="small"
  367. @change="scope.row.editFlag = true"
  368. ></el-input>
  369. </template>
  370. </el-table-column>
  371. <el-table-column
  372. label="货物名称"
  373. width="180"
  374. >
  375. <template #default="scope">
  376. <el-input
  377. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  378. v-model="scope.row.Description_of_Goods"
  379. size="small"
  380. @change="scope.row.editFlag = true"
  381. ></el-input>
  382. </template>
  383. </el-table-column>
  384. <el-table-column
  385. label="货物材质"
  386. width="220"
  387. >
  388. <template #default="scope">
  389. <el-select
  390. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  391. v-model="scope.row.Material_of_Goods"
  392. size="small"
  393. multiple
  394. @change="scope.row.editFlag = true"
  395. >
  396. <el-option
  397. v-for="i in goodMaterialOption"
  398. :key="i"
  399. :value="i"
  400. :label="i"
  401. ></el-option>
  402. </el-select>
  403. </template>
  404. </el-table-column>
  405. <el-table-column
  406. label="数量"
  407. width="100"
  408. >
  409. <template #default="scope">
  410. <el-input
  411. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  412. v-model="scope.row.Quantity"
  413. size="small"
  414. @change="changeTotal(scope.row)"
  415. ></el-input>
  416. </template>
  417. </el-table-column>
  418. <el-table-column
  419. label="单价(澳币/AUD)"
  420. width="120"
  421. >
  422. <template #default="scope">
  423. <el-input
  424. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  425. v-model="scope.row.Unit_Price"
  426. size="small"
  427. @change="changeTotal(scope.row)"
  428. ></el-input>
  429. </template>
  430. </el-table-column>
  431. <el-table-column
  432. label="负责人"
  433. fixed="right"
  434. width="120"
  435. >
  436. <template #default="scope">
  437. <el-input
  438. v-model="scope.row.Requester.name"
  439. size="small"
  440. disabled
  441. ></el-input>
  442. </template>
  443. </el-table-column>
  444. <el-table-column
  445. label="申请人"
  446. fixed="right"
  447. width="120"
  448. >
  449. <template #default="scope">
  450. <el-input
  451. v-model="scope.row.Sales_Person"
  452. size="small"
  453. disabled
  454. ></el-input>
  455. </template>
  456. </el-table-column>
  457. <!-- <el-table-column
  458. v-show="['Arrangement', 'my_request'].includes(currentTab)"
  459. fixed="right"
  460. label="更新时间"
  461. width="90"
  462. >
  463. <template #default="scope">
  464. <div v-if="scope.row.id">
  465. {{
  466. dayjs(scope.row.update_time || new Date()).format(
  467. 'YYYY-MM-DD HH:mm:ss',
  468. )
  469. }}
  470. </div>
  471. </template>
  472. </el-table-column> -->
  473. <el-table-column
  474. v-show="
  475. [
  476. '4791186000259693001',
  477. '4791186000022965001',
  478. '4791186000052269001',
  479. ].includes(currentUser)
  480. "
  481. fixed="right"
  482. label="操作"
  483. width="90"
  484. >
  485. <template #default="scope">
  486. <el-tooltip
  487. content="新增未commit的行会被直接移除; 已commit的行只会标记, 正式commit后才会删除"
  488. >
  489. <el-button
  490. v-if="['Arrangement', 'my_request'].includes(currentTab)"
  491. type="danger"
  492. size="small"
  493. link
  494. @click="() => onDeleteRow(scope.row, scope.$index)"
  495. >
  496. 删除
  497. </el-button>
  498. </el-tooltip>
  499. <el-button
  500. size="small"
  501. link
  502. type="primary"
  503. @click="print(scope.row)"
  504. >
  505. 打印
  506. </el-button>
  507. </template>
  508. </el-table-column>
  509. <el-table-column
  510. fixed="right"
  511. label="重量 (KG)"
  512. width="70"
  513. >
  514. <template #default="scope">
  515. <el-input
  516. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  517. v-model="scope.row.Weight"
  518. size="small"
  519. @change="scope.row.editFlag = true"
  520. ></el-input>
  521. </template>
  522. </el-table-column>
  523. <el-table-column
  524. fixed="right"
  525. label="体积 m&sup3;"
  526. width="70"
  527. >
  528. <template #default="scope">
  529. <el-button
  530. @click="openCubeDialog(scope)"
  531. :disabled="!['Arrangement', 'my_request'].includes(currentTab)"
  532. type="primary"
  533. size="small"
  534. text
  535. >
  536. {{ scope.row.Cube || '点击输入' }}
  537. </el-button>
  538. </template>
  539. </el-table-column>
  540. <el-table-column
  541. fixed="right"
  542. label="总离岸价 (澳币/AUD)"
  543. width="140"
  544. >
  545. <template #default="scope">
  546. <el-input
  547. v-model="scope.row.Total_FOB"
  548. size="small"
  549. disabled
  550. ></el-input>
  551. </template>
  552. </el-table-column>
  553. <el-table-column
  554. label="Reference"
  555. fixed="right"
  556. width="90"
  557. >
  558. <template #default="scope">
  559. <div class="">{{ scope.row.Reference || scope.row.PO_Number }}</div>
  560. </template>
  561. </el-table-column>
  562. </el-table>
  563. <el-drawer
  564. v-model:model-value="printDrawerVisible"
  565. :size="'1050px'"
  566. :title="'打印唛 (注意先写完唛内容和宽高最后再调页数, 不然可能会很卡)'"
  567. :close-on-click-modal="false"
  568. :close-on-press-escape="false"
  569. >
  570. <comp-print
  571. v-if="printDrawerVisible"
  572. :autoOpenQRCode="false"
  573. :content="[currentPrintRow.Marks_Nos || '']"
  574. :scene="'QC'"
  575. />
  576. </el-drawer>
  577. <el-drawer
  578. v-model:model-value="mapDrawerVisible"
  579. :size="'1050px'"
  580. :close-on-click-modal="false"
  581. :close-on-press-escape="false"
  582. :destroy-on-close="true"
  583. :with-header="false"
  584. header-class="mb-1"
  585. >
  586. <div class="relative h-[20px]">
  587. <span
  588. @click="closeMapDrawer"
  589. class="absolute top-[-16px] right-0 text-gray-600 text-sm cursor-pointer"
  590. >
  591. 关闭地图窗口
  592. </span>
  593. </div>
  594. <div
  595. id="mapDrawer"
  596. class="h-[100%]"
  597. ></div>
  598. </el-drawer>
  599. </div>
  600. <el-dialog
  601. style="margin-top: 35vh"
  602. title="体积输入(直接输入体积, 或输入长宽高自动计算)"
  603. :modelValue="cubeDialogVisible >= 0"
  604. @close="closeCubeDialog"
  605. width="400px"
  606. >
  607. <el-form>
  608. <el-form-item label="length (m)">
  609. <el-input v-model="cubeForm.l"></el-input>
  610. </el-form-item>
  611. <el-form-item label="width (m)">
  612. <el-input v-model="cubeForm.w"></el-input>
  613. </el-form-item>
  614. <el-form-item label="height (m)">
  615. <el-input v-model="cubeForm.h"></el-input>
  616. </el-form-item>
  617. <el-form-item label="cube (m³)">
  618. <el-input v-model="cubeForm2.c"></el-input>
  619. </el-form-item>
  620. <el-form-item>
  621. <div class="w-full flex justify-center">
  622. <el-button
  623. size="small"
  624. type="primary"
  625. @click="commitCube"
  626. >
  627. 确定
  628. </el-button>
  629. <el-button
  630. size="small"
  631. @click="closeCubeDialog"
  632. >
  633. 取消
  634. </el-button>
  635. </div>
  636. </el-form-item>
  637. </el-form>
  638. </el-dialog>
  639. </div>
  640. </template>
  641. <script lang="ts" setup>
  642. import { defineComponent, ref, watch, computed, nextTick } from 'vue'
  643. import {
  644. ElButton,
  645. ElForm,
  646. ElFormItem,
  647. ElInput,
  648. ElTabs,
  649. ElTabPane,
  650. ElTable,
  651. ElTableColumn,
  652. ElDatePicker,
  653. ElTooltip,
  654. ElSelect,
  655. ElOption,
  656. ElMessage,
  657. ElMessageBox,
  658. ElNotification,
  659. ElDrawer,
  660. ElDialog,
  661. } from 'element-plus'
  662. import cloneDeep from 'lodash.clonedeep'
  663. import dayjs from 'dayjs'
  664. import * as XLSX from 'xlsx'
  665. import debounce from 'lodash.debounce'
  666. import compPrint from '@/components/print.vue'
  667. import request from '@/utils/axios'
  668. defineComponent({
  669. name: 'ComponentCargoConsolidationRequest',
  670. })
  671. const currentUser = ref('')
  672. const currentUserName = ref('')
  673. const currentUserRawData = ref({} as any)
  674. let loading = ref(false)
  675. let list = ref([] as any[])
  676. let currentTab = ref('all')
  677. let tabs = [
  678. {
  679. label: 'All',
  680. value: 'all',
  681. },
  682. {
  683. label: 'Avaliable',
  684. value: 'avaliable',
  685. },
  686. {
  687. label: 'Closed Voyage',
  688. value: 'voyage_closed',
  689. },
  690. {
  691. label: 'My Request',
  692. value: 'my_request',
  693. },
  694. ]
  695. let finalTabs = ref([] as any[])
  696. finalTabs.value = cloneDeep(tabs)
  697. let computedList = computed(() => {
  698. return list.value.filter((i: any) => {
  699. let condition = true
  700. switch (currentTab.value) {
  701. case 'avaliable':
  702. condition = i.Status && i.Status === '可用'
  703. break
  704. case 'voyage_closed':
  705. condition = ['已截仓', '已确认', '已发出', '已到达'].includes(i.Status)
  706. break
  707. }
  708. return condition
  709. })
  710. })
  711. let dateRange = ref([] as any[])
  712. const generateDateRange = (days = 7) => {
  713. const today = new Date()
  714. const endDate = new Date()
  715. endDate.setDate(today.getDate() + days)
  716. return [today, endDate]
  717. }
  718. const dateShortcuts = ref([
  719. {
  720. text: 'Next 3 days',
  721. value: generateDateRange(3),
  722. },
  723. {
  724. text: 'Next week',
  725. value: generateDateRange(7),
  726. },
  727. {
  728. text: 'Next 14days',
  729. value: generateDateRange(14),
  730. },
  731. ] as any[])
  732. function getDefaultRange() {
  733. const today = dayjs()
  734. const lastMonthFirstDay = today
  735. .subtract(1, 'month')
  736. .startOf('month')
  737. .format('YYYY-MM-DD')
  738. const nextMonthLastDay = today
  739. .add(1, 'month')
  740. .endOf('month')
  741. .format('YYYY-MM-DD')
  742. return [lastMonthFirstDay, nextMonthLastDay]
  743. }
  744. dateRange.value = getDefaultRange()
  745. const clearSubList = () => {
  746. subList.value = []
  747. subListBackup = []
  748. currentRow.value = {}
  749. }
  750. let getList = () => {
  751. loading.value = true
  752. zoho.CRM.API.coql({
  753. select_query:
  754. 'select Container_Number,Name,Forwarder,ETD,ATD,ETA,ATA,Cut_Off_Date,Owner,Status,Modified_Time,SubscriptionId,Carrier,Booking_Number,GRN from Sea_Freight_Table' +
  755. " where ETD between '" +
  756. `${dateRange.value.map((i) => dayjs(i).format('YYYY-MM-DD')).join("' and '")}` +
  757. "'",
  758. })
  759. .then((res: any) => {
  760. if (Array.isArray(res.data) && res.data.length) {
  761. list.value = res.data.sort(
  762. (a: any, b: any) =>
  763. new Date(b.Cut_Off_Date).getTime() -
  764. new Date(a.Cut_Off_Date).getTime(),
  765. )
  766. } else if (res.status === 204) {
  767. ElNotification({
  768. type: 'warning',
  769. title: 'No Data Found',
  770. message: res.statusText || `zoho api return: ${res.status}`,
  771. duration: 3000,
  772. })
  773. list.value = []
  774. clearSubList()
  775. }
  776. })
  777. .finally(() => (loading.value = false))
  778. }
  779. let currentRow = ref({} as any)
  780. let subList = ref([] as any[])
  781. // 未经过滤的crm数据
  782. let subListBackup: any[] = []
  783. watch(currentTab, (value: string) => {
  784. // 切到可用tab, 但是当前行是不是 可用 状态
  785. let notAvaliable = value === 'avaliable' && currentRow.value.Status !== '可用'
  786. // 切到关闭tab, 但当前行不是‘关闭’状态
  787. let notClose =
  788. value === 'voyage_closed' &&
  789. !['已截仓', '已确认', '已发出'].includes(currentRow.value.Status)
  790. if (notAvaliable || notClose) {
  791. clearSubList()
  792. } else {
  793. generateSubList()
  794. }
  795. })
  796. const generateSubList = () => {
  797. // clonedeep 是因为数据里面有 object array, 担心浅复制到表单变量会影响到原始数据
  798. subList.value = cloneDeep(
  799. subListBackup
  800. .filter(
  801. (i: any) =>
  802. i.Parent_Id.id === currentRow.value.id &&
  803. (currentTab.value === 'my_request'
  804. ? i.Sales_Person === currentUserName.value
  805. : true),
  806. )
  807. .map((i: any) => ({
  808. ...i,
  809. Requester: i.Requester?.id
  810. ? {
  811. name: i.Requester.name || '',
  812. id: i.Requester.id,
  813. }
  814. : { name: '', id: '' },
  815. Sample: i.Sample || false,
  816. batchRecord: i.Batch_Record?.id || '',
  817. addFlag: false,
  818. editFlag: false,
  819. deleteFlag: false,
  820. })),
  821. )
  822. }
  823. const changeTotal = (row: any) => {
  824. row.editFlag = true
  825. row.Total_FOB = (Number(row.Unit_Price) * Number(row.Quantity)).toFixed(2)
  826. }
  827. /**
  828. * 用来增加新行的数据模版
  829. */
  830. const newLineTemplate = {
  831. addFlag: true,
  832. editFlag: true,
  833. deleteFlag: false,
  834. batchRecord: '',
  835. // 提交表单前删掉以上字段
  836. // id: '',
  837. Sample: false,
  838. Batch_Record: {
  839. name: '',
  840. id: '',
  841. } as any,
  842. Sales_Order: '',
  843. Purchase_Order: '',
  844. Reference: '',
  845. PO_Number: '',
  846. Parent_Id: {
  847. name: '',
  848. id: '',
  849. } as any,
  850. Carton: '',
  851. Marks_Nos: '',
  852. Description_of_Goods: '',
  853. Material_of_Goods: [],
  854. Quantity: '',
  855. Unit_Price: '',
  856. Weight: '',
  857. Cube: '',
  858. Total_FOB: '',
  859. Requester: { name: '', id: '' } as any,
  860. Sales_Person: '', // 申请人
  861. User_Notes: '',
  862. }
  863. // 用在弹窗里面给批次记录做候选项
  864. let batchListOption = computed(() =>
  865. subList.value
  866. .filter(
  867. (i) =>
  868. i.Batch_Record && i.Batch_Record.name && i.Batch_Record.name.length > 0,
  869. )
  870. .map((i) => {
  871. return {
  872. Name: i.Batch_Record.name || '',
  873. id: i.Batch_Record.id || '',
  874. isSearch: false, // 用来区分是搜索出来的还是原始数据
  875. }
  876. })
  877. // ai生成的去重逻辑.
  878. .filter(
  879. (item, index, self) =>
  880. index ===
  881. self.findIndex((t) => t.Name === item.Name && t.id === item.id),
  882. ),
  883. )
  884. let computedOption = computed(() => {
  885. return qcList.value.concat(batchListOption.value)
  886. })
  887. let getSubList = (e: any = {}) => {
  888. if (e.id) currentRow.value = e
  889. loading.value = true
  890. zoho.CRM.API.searchRecord({
  891. Entity: 'Sea_Freight_Details',
  892. Type: 'criteria',
  893. Query: `(Parent_Id:equals:${currentRow.value.id})`,
  894. delay: false,
  895. })
  896. .then((res: any) => {
  897. if (Array.isArray(res.data) && res.data.length) {
  898. subListBackup = cloneDeep(res.data)
  899. } else {
  900. subListBackup = []
  901. }
  902. generateSubList()
  903. newLineTemplate.Parent_Id = { id: currentRow.value.id }
  904. newLineTemplate.Sales_Person = currentUserName.value
  905. newLineTemplate.Requester = {
  906. id: currentUser.value,
  907. name: currentUserName.value,
  908. }
  909. })
  910. .finally(() => (loading.value = false))
  911. }
  912. // 货物材质候选数据
  913. const goodMaterialOption = ref([
  914. 'Cotton 棉',
  915. 'Iron 铁',
  916. 'Neoprene 潜水料',
  917. 'Paper 纸质',
  918. 'Plastic 塑料',
  919. 'Polyester Fibre 聚酯纤维',
  920. 'PU 聚氨酯',
  921. 'PVC 聚氯乙烯',
  922. 'Velvet 天鹅绒',
  923. 'Zinc alloy 锌合金',
  924. 'Aluminum alloy 铝合金',
  925. 'Glass 玻璃',
  926. 'Rubber 橡胶',
  927. 'Stainless Steel 不锈钢',
  928. ])
  929. // 动态获取货物材质候选数据
  930. let getGoodMaterialOption = () => {
  931. request
  932. .post('/common/getWebsiteSubform', { id: '4791186000359651051' })
  933. .then((resp: any) => {
  934. // console.log(resp, 'res')
  935. const res = resp.data.result || {}
  936. if (Array.isArray(res.data) && res.data.length) {
  937. // console.log(res.data, 'res.data')
  938. goodMaterialOption.value =
  939. res.data[0].Website_Subform.map(
  940. (i: any) => i.Website_Subform_Value,
  941. ) || []
  942. }
  943. })
  944. }
  945. getGoodMaterialOption()
  946. const addBulkProduct = () => {
  947. let temp = cloneDeep(newLineTemplate)
  948. temp.Sample = false
  949. subList.value.unshift(temp)
  950. }
  951. const addSample = () => {
  952. let temp = cloneDeep(newLineTemplate)
  953. temp.Sample = true
  954. subList.value.unshift(temp)
  955. }
  956. const onDeleteRow = (row: any, index: number = -1) => {
  957. if (row.addFlag) {
  958. subList.value.splice(index, 1)
  959. } else {
  960. row.deleteFlag = true
  961. ElNotification({
  962. type: 'warning',
  963. title: '已标记删除',
  964. duration: 3000,
  965. message: '点 提交 按钮后会正式删除. 误操作请点击 放弃改动.',
  966. })
  967. }
  968. }
  969. const onBatchRecordChange = ($e: string, line = -1) => {
  970. const temp = computedOption.value.filter((i) => i.id === $e)
  971. let result: any = {}
  972. if (temp.length) {
  973. result = cloneDeep(temp[0])
  974. }
  975. if (line > -1) {
  976. // 主页面数据编辑
  977. subList.value[line].editFlag = true
  978. subList.value[line].Batch_Record = { id: result.id, name: result.Name }
  979. if (result.Owner) {
  980. subList.value[line].Requester = {
  981. name: result.Owner.name,
  982. id: result.Owner.id,
  983. }
  984. }
  985. subList.value[line].Sales_Order = result.Sales_Order || ''
  986. subList.value[line].Purchase_Order = result.Purchase_Order || ''
  987. subList.value[line].Reference = result.Reference || ''
  988. subList.value[line].PO_Number = result.PO_Number || ''
  989. // 如果对应行的唛头为空, 则用批次记录的名称填充
  990. if (
  991. !subList.value[line].Marks_Nos ||
  992. subList.value[line].Marks_Nos.length < 1
  993. ) {
  994. subList.value[line].Marks_Nos = result.Name || ''
  995. }
  996. }
  997. }
  998. // 给子表格加红绿背景. 颜色用的tailwind的 red green
  999. const calcRowStyle = ($e: any) => {
  1000. const result = {} as any
  1001. if ($e.row.addFlag) result['background-color'] = 'rgb(187, 247, 208)'
  1002. if ($e.row.editFlag) result['background-color'] = 'rgb(187, 247, 208)'
  1003. if ($e.row.deleteFlag) result['background-color'] = 'rgb(254, 202, 202)'
  1004. return result
  1005. }
  1006. const commit = () => {
  1007. let temp = cloneDeep(subList.value)
  1008. let result = temp
  1009. .filter((i) => !i.deleteFlag)
  1010. .map((i) => {
  1011. return {
  1012. id: i.id,
  1013. Sample: i.Sample || false,
  1014. Batch_Record: i.batchRecord
  1015. ? {
  1016. name: i.Batch_Record.name,
  1017. id: i.Batch_Record.id,
  1018. }
  1019. : '',
  1020. Parent_Id: {
  1021. name: i.Parent_Id.name,
  1022. id: i.Parent_Id.id || '',
  1023. },
  1024. Material_of_Goods: i.Material_of_Goods,
  1025. Requester: i.Requester.name
  1026. ? {
  1027. name: i.Requester.name,
  1028. id: i.Requester.id || '',
  1029. }
  1030. : '',
  1031. Sales_Person: i.Sales_Person || '',
  1032. Carton: i.Carton || '',
  1033. Marks_Nos: i.Marks_Nos || '',
  1034. Description_of_Goods: i.Description_of_Goods || '',
  1035. Quantity: i.Quantity || '',
  1036. Unit_Price: i.Unit_Price || '',
  1037. Weight: i.Weight || '',
  1038. Cube: i.Cube || '',
  1039. Total_FOB: i.Total_FOB || '',
  1040. User_Notes: i.User_Notes || '',
  1041. Sales_Order: i.Sales_Order || '',
  1042. Purchase_Order: i.Purchase_Order || '',
  1043. Reference: i.Reference || '',
  1044. PO_Number: i.PO_Number || '',
  1045. }
  1046. }) as any[]
  1047. result = result.concat(
  1048. temp
  1049. .filter((i) => i.deleteFlag)
  1050. .map((i) => ({ id: i.id, _delete: null, Material_of_Goods: null })),
  1051. )
  1052. // const emptyBatchRecordList: number[] = []
  1053. const emptyUserNotesList: number[] = []
  1054. result.forEach((i, index) => {
  1055. // if (!i.Sample) {
  1056. // if (!i.Batch_Record) {
  1057. // emptyBatchRecordList.push(index)
  1058. // }
  1059. // }
  1060. if (!i.User_Notes) {
  1061. emptyUserNotesList.push(index)
  1062. }
  1063. })
  1064. // if (emptyBatchRecordList.length) {
  1065. // ElNotification({
  1066. // title: '请检查表单',
  1067. // message: `第 ${emptyBatchRecordList.map((i) => i + 1).join(', ')} 行的Batch Record数据`,
  1068. // duration: 5000,
  1069. // })
  1070. // return
  1071. // }
  1072. if (emptyUserNotesList.length) {
  1073. ElNotification({
  1074. title: '请检查表单, 备注是必填的',
  1075. message: `第 ${emptyUserNotesList
  1076. .map((i) => i + 1)
  1077. .join(', ')} 行的备注数据, 不能为空`,
  1078. duration: 5000,
  1079. })
  1080. return
  1081. }
  1082. console.log(result, 'submit result')
  1083. loading.value = true
  1084. request
  1085. .post('/sea_freight/updateSeaFreightDataV2', {
  1086. id: newLineTemplate.Parent_Id.id,
  1087. Sea_Freight_array: result,
  1088. Sales_Person: currentUserName.value,
  1089. Sales_Person_Obj: {
  1090. id: currentUser.value,
  1091. name: currentUserName.value,
  1092. },
  1093. })
  1094. .then((res) => {
  1095. if (res.data.code === 1) {
  1096. let result = res.data.result || { data: [] }
  1097. if (
  1098. Array.isArray(result.data) &&
  1099. result.data.length &&
  1100. result.data.every((i: any) => i.status === 'success')
  1101. ) {
  1102. ElNotification({
  1103. title: '保存成功',
  1104. message: '正在刷新数据',
  1105. duration: 3000,
  1106. })
  1107. } else {
  1108. ElNotification({
  1109. title: '部份内容保存失败',
  1110. message: '建议刷新再试或者联系管理员',
  1111. duration: 10000,
  1112. })
  1113. }
  1114. getSubList(currentRow.value)
  1115. } else {
  1116. ElMessage.error('保存出错')
  1117. loading.value = false
  1118. }
  1119. })
  1120. .catch((e) => {
  1121. console.log(e, 'commit error')
  1122. loading.value = false
  1123. })
  1124. }
  1125. let printDrawerVisible = ref(false)
  1126. let currentPrintRow = ref({} as any)
  1127. const print = (row: any) => {
  1128. currentPrintRow.value = row
  1129. printDrawerVisible.value = true
  1130. }
  1131. const exportSubTable = () => {
  1132. const headers = [
  1133. '箱数 Carton',
  1134. '唛头 Marks & Nos',
  1135. '货物名称 Description of Goods',
  1136. '货物材质 Material goods',
  1137. '数量 QTY',
  1138. '单价 澳币/AUD Unit Price',
  1139. '重量KG Weight',
  1140. '体积m³ Cube',
  1141. '总离岸价 澳币/AUD Total FOB',
  1142. '负责人 Owner',
  1143. 'Reference',
  1144. ]
  1145. const data: any[] = subList.value.map((i) => {
  1146. return {
  1147. '箱数 Carton': i.Carton || '',
  1148. '唛头 Marks & Nos': i.Marks_Nos || '',
  1149. '货物名称 Description of Goods': i.Description_of_Goods || '',
  1150. '货物材质 Material goods': i.Material_of_Goods,
  1151. '数量 QTY': i.Quantity || '',
  1152. '单价 澳币/AUD Unit Price': i.Unit_Price || '',
  1153. '重量KG Weight': i.Weight || '',
  1154. '体积m³ Cube': i.Cube || '',
  1155. '总离岸价 澳币/AUD Total FOB': i.Total_FOB || '',
  1156. '负责人 Owner': i.Requester.name || '',
  1157. Reference: i.Reference || i.PO_Number || '',
  1158. }
  1159. })
  1160. if (data.length === 0) {
  1161. throw new Error('Invalid data: Data array is empty.')
  1162. }
  1163. const worksheetData = []
  1164. worksheetData.push(['发票/装箱单/INVOICE/PACKING LIST'])
  1165. if (headers && headers.length > 0) {
  1166. worksheetData.push(headers)
  1167. } else {
  1168. worksheetData.push(Object.keys(data[0]))
  1169. }
  1170. data.forEach((row) => {
  1171. worksheetData.push(Object.values(row))
  1172. })
  1173. const wb = XLSX.utils.book_new()
  1174. let ws = XLSX.utils.aoa_to_sheet(worksheetData)
  1175. ws['!merges'] = [
  1176. { s: { r: 0, c: 0 }, e: { r: 0, c: 9 } }, // 合并列作为标题
  1177. ]
  1178. ws['!cols'] = [
  1179. { wpx: 80 },
  1180. { wpx: 200 },
  1181. { wpx: 180 },
  1182. { wpx: 120 },
  1183. { wpx: 90 },
  1184. { wpx: 120 },
  1185. { wpx: 100 },
  1186. { wpx: 100 },
  1187. { wpx: 120 },
  1188. { wpx: 120 },
  1189. { wpx: 100 },
  1190. ]
  1191. XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
  1192. XLSX.writeFile(
  1193. wb,
  1194. encodeURIComponent(currentRow.value.Name || 'test') + '.xlsx',
  1195. )
  1196. }
  1197. let qcList = ref([] as any[])
  1198. let loading2 = ref(false)
  1199. const search = (keyword: string) => {
  1200. if (keyword.length < 2) return
  1201. loading2.value = true
  1202. zoho.CRM.API.searchRecord({
  1203. Entity: 'QC_Record',
  1204. Type: 'criteria',
  1205. Query: `(Reference:in:${keyword})or(Reference:starts_with:${keyword})or(Purchase_Order.name:in:${keyword})or(Purchase_Order.name:starts_with:${keyword})`,
  1206. delay: false,
  1207. })
  1208. .then((res: any) => {
  1209. if (Array.isArray(res.data) && res.data.length) {
  1210. qcList.value = res.data.map((i: any) => {
  1211. return {
  1212. ...i,
  1213. isSearch: true,
  1214. }
  1215. })
  1216. } else {
  1217. qcList.value = []
  1218. ElMessage.warning('No Data Found')
  1219. }
  1220. })
  1221. .finally(() => (loading2.value = false))
  1222. }
  1223. const ensure = () => {
  1224. ElMessageBox.confirm('确定要把该记录状态更新为"已确认"吗?', {
  1225. confirmButtonText: '确定',
  1226. cancelButtonText: '取消',
  1227. type: 'warning',
  1228. }).then(() => {
  1229. loading.value = true
  1230. zoho.CRM.API.updateRecord({
  1231. Entity: 'Sea_Freight_Table',
  1232. Trigger: ['workflow'],
  1233. APIData: {
  1234. id: currentRow.value.id,
  1235. Status: '已确认',
  1236. },
  1237. }).then((res: any) => {
  1238. if (
  1239. Array.isArray(res.data) &&
  1240. res.data.length &&
  1241. res.data[0].code === 'SUCCESS'
  1242. ) {
  1243. ElMessage.success('操作成功, 正在刷新数据')
  1244. loading.value = false
  1245. getList()
  1246. clearSubList()
  1247. } else {
  1248. loading.value = false
  1249. ElMessage.error('操作失败, 请稍后再试或者联系管理员')
  1250. }
  1251. })
  1252. })
  1253. }
  1254. let bookingNumber = ref('')
  1255. const updateBookingNumber = () => {
  1256. bookingNumber.value = bookingNumber.value.trim()
  1257. if (!bookingNumber.value || !currentRow.value.id) {
  1258. ElMessage.error('请填写订舱号')
  1259. return
  1260. }
  1261. ElMessageBox.confirm(
  1262. `确定要把该记录的订舱号更新为"${bookingNumber.value}"吗?`,
  1263. {
  1264. confirmButtonText: '确定',
  1265. cancelButtonText: '取消',
  1266. type: 'warning',
  1267. },
  1268. ).then(() => {
  1269. loading.value = true
  1270. zoho.CRM.API.updateRecord({
  1271. Entity: 'Sea_Freight_Table',
  1272. Trigger: ['workflow'],
  1273. APIData: {
  1274. id: currentRow.value.id,
  1275. Booking_Number: bookingNumber.value,
  1276. },
  1277. }).then((res: any) => {
  1278. if (
  1279. Array.isArray(res.data) &&
  1280. res.data.length &&
  1281. res.data[0].code === 'SUCCESS'
  1282. ) {
  1283. ElMessage.success('操作成功, 正在刷新数据')
  1284. loading.value = false
  1285. bookingNumber.value = ''
  1286. getList()
  1287. clearSubList()
  1288. } else {
  1289. loading.value = false
  1290. ElMessage.error('操作失败, 请稍后再试或者联系管理员')
  1291. }
  1292. })
  1293. })
  1294. }
  1295. let containerNumber = ref('')
  1296. const updateContainerNumber = () => {
  1297. containerNumber.value = containerNumber.value.trim()
  1298. if (!containerNumber.value || !currentRow.value.id) {
  1299. ElMessage.error('请填写柜号')
  1300. return
  1301. }
  1302. ElMessageBox.confirm(
  1303. `确定要把该记录的柜号更新为"${containerNumber.value}"吗?`,
  1304. {
  1305. confirmButtonText: '确定',
  1306. cancelButtonText: '取消',
  1307. type: 'warning',
  1308. },
  1309. ).then(() => {
  1310. loading.value = true
  1311. zoho.CRM.API.updateRecord({
  1312. Entity: 'Sea_Freight_Table',
  1313. Trigger: ['workflow'],
  1314. APIData: {
  1315. id: currentRow.value.id,
  1316. Container_Number: containerNumber.value,
  1317. },
  1318. }).then((res: any) => {
  1319. if (
  1320. Array.isArray(res.data) &&
  1321. res.data.length &&
  1322. res.data[0].code === 'SUCCESS'
  1323. ) {
  1324. ElMessage.success('操作成功, 正在刷新数据')
  1325. loading.value = false
  1326. containerNumber.value = ''
  1327. getList()
  1328. clearSubList()
  1329. } else {
  1330. loading.value = false
  1331. ElMessage.error('操作失败, 请稍后再试或者联系管理员')
  1332. }
  1333. })
  1334. })
  1335. }
  1336. // @ts-ignore
  1337. const zoho = window.ZOHO
  1338. zoho.embeddedApp.on('PageLoad', function () {
  1339. zoho.CRM.CONFIG.getCurrentUser().then(function (data: any) {
  1340. if (Array.isArray(data.users) && data.users.length) {
  1341. const user = data.users[0]
  1342. // console.log(user, 'user')
  1343. currentUser.value = user.id
  1344. currentUserName.value = user.full_name || ''
  1345. currentUserRawData.value = cloneDeep(user)
  1346. getList()
  1347. }
  1348. })
  1349. })
  1350. zoho.embeddedApp.init()
  1351. watch(currentUserRawData, () => {
  1352. if (!currentUserRawData.value.role) return false
  1353. let result =
  1354. /(CEO|Logistics)/g.test(currentUserRawData.value.role.name) ||
  1355. ['4791186000022965001', '4791186000052269001'].includes(
  1356. currentUserRawData.value.role.id,
  1357. )
  1358. if (result) {
  1359. finalTabs.value = cloneDeep(tabs)
  1360. finalTabs.value.push({
  1361. label: 'Arrangement',
  1362. value: 'Arrangement',
  1363. })
  1364. }
  1365. })
  1366. let computedWeight = computed(() => {
  1367. return subList.value
  1368. .reduce((t, c) => {
  1369. t = t + Number(c.Weight)
  1370. return t
  1371. }, 0)
  1372. .toFixed(2)
  1373. })
  1374. let computedCube = computed(() => {
  1375. return subList.value
  1376. .reduce((t, c) => {
  1377. t = t + Number(c.Cube)
  1378. return t
  1379. }, 0)
  1380. .toFixed(2)
  1381. })
  1382. let computedTotalFOB = computed(() => {
  1383. return subList.value
  1384. .reduce((t, c) => {
  1385. t = t + Number(c.Total_FOB)
  1386. return t
  1387. }, 0)
  1388. .toFixed(2)
  1389. })
  1390. // 订单轨迹地图插件
  1391. let mapDrawerVisible = ref(false)
  1392. const openMapDrawer = (row: any) => {
  1393. mapDrawerVisible.value = true
  1394. // console.log(row.Carrier, 'row.value.Carrier')
  1395. // console.log(row.Booking_Number, 'row.value.Booking_Number')
  1396. if ((window as any).Sgld) {
  1397. nextTick(() => {
  1398. ;(window as any).Sgld.createContainerTrack({
  1399. id: 'mapDrawer',
  1400. carrierCode: row.Carrier, // 船公司代码
  1401. billNo: row.Booking_Number, // 提单号
  1402. })
  1403. })
  1404. }
  1405. }
  1406. const closeMapDrawer = () => {
  1407. mapDrawerVisible.value = false
  1408. }
  1409. let cubeDialogVisible = ref(-1)
  1410. let cubeForm = ref({
  1411. l: '',
  1412. w: '',
  1413. h: '',
  1414. })
  1415. let cubeForm2 = ref({
  1416. c: '' as string | number,
  1417. })
  1418. watch(
  1419. cubeForm,
  1420. () => {
  1421. cubeForm2.value.c =
  1422. Number(cubeForm.value.l) *
  1423. Number(cubeForm.value.w) *
  1424. Number(cubeForm.value.h)
  1425. },
  1426. {
  1427. immediate: true,
  1428. deep: true,
  1429. },
  1430. )
  1431. let openCubeDialog = (obj: any) => {
  1432. let index = obj.$index
  1433. if (index < 0 || index >= subList.value.length) return
  1434. const row = subList.value[index]
  1435. cubeForm2.value.c = row.Cube || ''
  1436. cubeDialogVisible.value = index
  1437. }
  1438. let commitCube = () => {
  1439. const row = subList.value[cubeDialogVisible.value]
  1440. row.Cube = Number(cubeForm2.value.c).toFixed(2) || ''
  1441. row.editFlag = true
  1442. closeCubeDialog()
  1443. }
  1444. let closeCubeDialog = () => {
  1445. cubeDialogVisible.value = -1
  1446. cubeForm.value.l = ''
  1447. cubeForm.value.w = ''
  1448. cubeForm.value.h = ''
  1449. cubeForm2.value.c = ''
  1450. }
  1451. </script>
  1452. <style lang="scss">
  1453. .page-cargo-consolidation {
  1454. .el-table__body tr.current-row > td.el-table__cell {
  1455. background-color: rgb(56, 163, 238);
  1456. color: #fff;
  1457. }
  1458. }
  1459. </style>
  1460. <style lang="scss" scoped>
  1461. .el-button.custom-button {
  1462. height: 24px;
  1463. line-height: 24px;
  1464. background-image: linear-gradient(
  1465. 171deg,
  1466. rgb(28, 74, 136) 49%,
  1467. rgb(0, 130, 193) 100%
  1468. );
  1469. background-color: rgb(97, 165, 245);
  1470. color: #fff;
  1471. font-size: 13px;
  1472. font-family: Zoho_Puvi_Bold sans-serif;
  1473. border-radius: 6px;
  1474. cursor: pointer;
  1475. &:hover,
  1476. &:active {
  1477. background-image: linear-gradient(
  1478. 171deg,
  1479. rgb(28, 74, 136) 49%,
  1480. rgb(22, 208, 239) 100%
  1481. );
  1482. color: #fff;
  1483. }
  1484. &.fb {
  1485. font-weight: 900;
  1486. }
  1487. &.small {
  1488. height: 24px;
  1489. line-height: 24px;
  1490. }
  1491. }
  1492. </style>