index.vue 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  1. <template>
  2. <div class="tenant">
  3. <!-- <Banner /> -->
  4. <div class="content">
  5. <byTable
  6. :source="sourceList.data"
  7. :pagination="sourceList.pagination"
  8. :config="config"
  9. :loading="loading"
  10. highlight-current-row
  11. :selectConfig="selectConfig"
  12. :table-events="{
  13. //element talbe事件都能传
  14. select: selectRow,
  15. 'select-all': selectRow,
  16. }"
  17. :action-list="[
  18. {
  19. text: '出货',
  20. disabled: selectData.length === 0,
  21. action: () => openModalOne(),
  22. },
  23. {
  24. text: '产品装箱',
  25. action: () => openModal(),
  26. },
  27. ]"
  28. @get-list="getList"
  29. >
  30. <template #code="{ item }">
  31. <div>
  32. <div
  33. v-for="(item, index) in getData(item.codeAPName, 'code')"
  34. :key="index"
  35. >
  36. {{ item }}
  37. </div>
  38. </div>
  39. </template>
  40. <template #productName="{ item }">
  41. <div>
  42. <div
  43. v-for="(item, index) in getData(item.codeAPName, 'productName')"
  44. :key="index"
  45. >
  46. {{ item }}
  47. </div>
  48. </div>
  49. </template>
  50. <template #netWeight="{ item }">
  51. <div>
  52. <div v-for="(i, index) in item.dataJsonListCopy" :key="index">
  53. {{ i.netWeight + " kg" }}
  54. </div>
  55. </div>
  56. </template>
  57. <template #roughWeight="{ item }">
  58. <div>
  59. <div v-for="(i, index) in item.dataJsonListCopy" :key="index">
  60. {{ i.roughWeight + " kg" }}
  61. </div>
  62. </div>
  63. </template>
  64. <template #boxLong="{ item }">
  65. <div>
  66. <div v-for="(i, index) in item.dataJsonListCopy" :key="index">
  67. {{ i.boxLong + " cm" }}
  68. </div>
  69. </div>
  70. </template>
  71. <template #boxWide="{ item }">
  72. <div>
  73. <div v-for="(i, index) in item.dataJsonListCopy" :key="index">
  74. {{ i.boxWide + " cm" }}
  75. </div>
  76. </div>
  77. </template>
  78. <template #boxHigh="{ item }">
  79. <div>
  80. <div v-for="(i, index) in item.dataJsonListCopy" :key="index">
  81. {{ i.boxHigh + " cm" }}
  82. </div>
  83. </div>
  84. </template>
  85. <template #bomVolume="{ item }">
  86. <div>
  87. <div v-for="(i, index) in item.dataJsonListCopy" :key="index">
  88. {{ i.bomVolume + " m³" }}
  89. </div>
  90. </div>
  91. </template>
  92. </byTable>
  93. </div>
  94. <el-dialog
  95. title="产品装箱"
  96. v-model="dtlModalType"
  97. width="80%"
  98. v-loading="loading"
  99. >
  100. <el-row :gutter="10">
  101. <el-col :span="8">
  102. <div class="common-title">箱规</div>
  103. <el-form
  104. :model="boxFormData"
  105. :rules="rules"
  106. ref="formDom"
  107. label-position="top"
  108. >
  109. <el-form-item label="尺寸(cm³)" required>
  110. <el-col :span="7">
  111. <el-form-item label="" :prop="'boxLong'" :rules="rules.boxLong">
  112. <el-input-number
  113. v-model="boxFormData.boxLong"
  114. placeholder="长"
  115. :precision="2"
  116. :controls="false"
  117. :min="0"
  118. @change="computeBomVolume"
  119. onmousewheel="return false;"
  120. ></el-input-number>
  121. </el-form-item>
  122. </el-col>
  123. <el-col :span="1" style="text-align: center"> * </el-col>
  124. <el-col :span="7">
  125. <el-form-item label="" :prop="'boxWide'" :rules="rules.boxWide">
  126. <el-input-number
  127. v-model="boxFormData.boxWide"
  128. placeholder="宽"
  129. :precision="2"
  130. :controls="false"
  131. :min="0"
  132. @change="computeBomVolume"
  133. onmousewheel="return false;"
  134. ></el-input-number>
  135. </el-form-item>
  136. </el-col>
  137. <el-col :span="1" style="text-align: center"> * </el-col>
  138. <el-col :span="7">
  139. <el-form-item label="" :prop="'boxHigh'" :rules="rules.boxHigh">
  140. <el-input-number
  141. v-model="boxFormData.boxHigh"
  142. placeholder="高"
  143. :precision="2"
  144. :controls="false"
  145. :min="0"
  146. @change="computeBomVolume"
  147. onmousewheel="return false;"
  148. ></el-input-number>
  149. </el-form-item>
  150. </el-col>
  151. </el-form-item>
  152. <el-form-item label="体积" required>
  153. <el-input-number
  154. :model-value="boxFormData.bomVolume"
  155. placeholder="请输入"
  156. :precision="4"
  157. :controls="false"
  158. :min="0"
  159. disabled
  160. onmousewheel="return false;"
  161. ></el-input-number>
  162. </el-form-item>
  163. <el-form-item
  164. label="净重(kg)"
  165. :prop="'netWeight'"
  166. :rules="rules.netWeight"
  167. >
  168. <el-input-number
  169. v-model="boxFormData.netWeight"
  170. :precision="2"
  171. :controls="false"
  172. :min="0"
  173. placeholder="请输入"
  174. onmousewheel="return false;"
  175. ></el-input-number>
  176. </el-form-item>
  177. <el-form-item
  178. label="毛重(kg)"
  179. :prop="'roughWeight'"
  180. :rules="rules.roughWeight"
  181. >
  182. <el-input-number
  183. v-model="boxFormData.roughWeight"
  184. :precision="2"
  185. :controls="false"
  186. :min="0"
  187. placeholder="请输入"
  188. onmousewheel="return false;"
  189. ></el-input-number>
  190. </el-form-item>
  191. <el-form-item
  192. label="总箱数"
  193. :prop="'packQuantity'"
  194. :rules="rules.packQuantity"
  195. >
  196. <el-input-number
  197. v-model="boxFormData.packQuantity"
  198. :precision="0"
  199. :controls="false"
  200. :min="1"
  201. placeholder="请输入"
  202. onmousewheel="return false;"
  203. ></el-input-number>
  204. </el-form-item>
  205. </el-form>
  206. </el-col>
  207. <el-col :span="16">
  208. <!-- 添加行 -->
  209. <div class="add-box" style="margin-bottom: 20px">
  210. <el-button
  211. type="primary"
  212. @click="packDetailProductListPush(boxIndex)"
  213. >
  214. 添加行
  215. </el-button>
  216. <el-button
  217. type="primary"
  218. @click="openCustom('2')"
  219. v-if="encasementType == '1'"
  220. >
  221. 自定义装箱
  222. </el-button>
  223. <el-button
  224. type="primary"
  225. @click="openCustom('1')"
  226. v-if="encasementType == '2'"
  227. >
  228. 标准装箱
  229. </el-button>
  230. </div>
  231. <el-table
  232. :data="boxFormData.packDetailGoodsList"
  233. ref="tableDom2"
  234. v-if="encasementType == '2'"
  235. >
  236. <el-table-column prop="remark" label="货品描述" min-width="180">
  237. <template #default="{ row, $index }">
  238. <el-form-item prop="remark" :inline-message="true">
  239. <el-input
  240. v-model="boxFormData.packDetailGoodsList[$index].remark"
  241. onmousewheel="return false;"
  242. />
  243. </el-form-item>
  244. </template>
  245. </el-table-column>
  246. <el-table-column prop="unit" label="单位" min-width="180">
  247. <template #default="{ row, $index }">
  248. <el-form-item prop="unit" :inline-message="true">
  249. <el-input
  250. v-model="boxFormData.packDetailGoodsList[$index].unit"
  251. onmousewheel="return false;"
  252. />
  253. </el-form-item>
  254. </template>
  255. </el-table-column>
  256. <el-table-column prop="quantity" label="入箱数" min-width="180">
  257. <template #default="{ row, $index }">
  258. <el-form-item prop="quantity" :inline-message="true">
  259. <el-input-number
  260. v-model="boxFormData.packDetailGoodsList[$index].quantity"
  261. :precision="4"
  262. :controls="false"
  263. :min="0"
  264. onmousewheel="return false;"
  265. />
  266. </el-form-item>
  267. </template>
  268. </el-table-column>
  269. <el-table-column prop="quantity" label="操作" width="100">
  270. <template #default="{ row, $index }">
  271. <el-button type="danger" @click="boxFormData.packDetailGoodsList.splice($index,1)"> 删除 </el-button>
  272. </template>
  273. </el-table-column>
  274. </el-table>
  275. <el-table
  276. v-else
  277. :data="boxFormData.packDetailProductList"
  278. @select="handleSelectProduct"
  279. @select-all="handleSelectProduct"
  280. ref="tableDom"
  281. >
  282. <el-table-column
  283. prop="productName"
  284. label="产品名称"
  285. min-width="180"
  286. >
  287. <template #default="{ row, $index }">
  288. <!-- 选择产品 -->
  289. <el-form-item
  290. prop="mathId"
  291. style="margin-bottom: 0px"
  292. :inline-message="true"
  293. >
  294. <el-select
  295. :model-value="
  296. boxFormData.packDetailProductList[$index].mathId
  297. "
  298. placeholder="请选择"
  299. @change="(e) => selectProduct(e, $index)"
  300. filterable
  301. style="width: 100%"
  302. >
  303. <el-option
  304. v-for="item in formData.data.contractProductData"
  305. :disabled="item.disabled"
  306. :label="item.productName"
  307. :value="item.mathId"
  308. >
  309. </el-option>
  310. </el-select>
  311. </el-form-item>
  312. </template>
  313. </el-table-column>
  314. <el-table-column
  315. prop="productSpec"
  316. label="规格型号"
  317. min-width="100"
  318. />
  319. <el-table-column prop="cpQuantity" label="合同数量" width="100" />
  320. <el-table-column
  321. prop="waitQuantity"
  322. label="待装箱数量"
  323. width="100"
  324. />
  325. <el-table-column prop="quantity" label="装箱数量" width="100">
  326. <template #default="{ row, $index }">
  327. <el-form-item prop="quantity" :inline-message="true">
  328. <el-input-number
  329. :max="row.waitQuantity"
  330. v-model="boxFormData.packDetailProductList[$index].quantity"
  331. :precision="4"
  332. :controls="false"
  333. :min="0"
  334. onmousewheel="return false;"
  335. />
  336. </el-form-item>
  337. </template>
  338. </el-table-column>
  339. <!-- 删除按钮 -->
  340. <el-table-column prop="quantity" label="操作" width="100">
  341. <template #default="{ row, $index }">
  342. <el-button
  343. type="danger"
  344. @click="boxFormData.packDetailProductList.splice($index, 1)"
  345. >
  346. 删除
  347. </el-button>
  348. </template>
  349. </el-table-column>
  350. </el-table>
  351. </el-col>
  352. </el-row>
  353. <template #footer>
  354. <el-button
  355. type="primary"
  356. @click="submitBox()"
  357. size="large"
  358. :loading="submitLoading"
  359. >
  360. 确 定
  361. </el-button>
  362. </template>
  363. </el-dialog>
  364. <el-dialog
  365. title="产品装箱"
  366. v-model="dialogVisible"
  367. width="600"
  368. v-loading="loading"
  369. >
  370. <el-form
  371. :model="formData.data"
  372. :rules="rules"
  373. ref="formDom"
  374. label-position="top"
  375. >
  376. <el-row :gutter="10">
  377. <el-col :span="8">
  378. <el-form-item label="客户名称" prop="customerId">
  379. <el-select
  380. v-model="formData.data.customerId"
  381. placeholder="请选择"
  382. @change="handleChangeCustomer"
  383. filterable
  384. style="width: 100%"
  385. >
  386. <el-option
  387. v-for="item in customerList"
  388. :label="item.name"
  389. :value="item.id"
  390. >
  391. </el-option>
  392. </el-select>
  393. </el-form-item>
  394. </el-col>
  395. </el-row>
  396. <el-form-item label="选择合同" prop="contractIds">
  397. <el-select
  398. v-model="formData.data.contractIds"
  399. placeholder="请选择"
  400. @change="handleChangeContract"
  401. filterable
  402. style="width: 100%"
  403. multiple
  404. >
  405. <el-option
  406. v-for="item in contractData"
  407. :label="item.code"
  408. :value="item.id"
  409. >
  410. </el-option>
  411. </el-select>
  412. </el-form-item>
  413. <div class="box-icon-warp">
  414. <div
  415. class="box-content"
  416. v-for="(i, index) in formData.data.packDetailList"
  417. :key="i.id"
  418. @click="openDtlUpdata(index)"
  419. >
  420. <div class="box-icon">
  421. <i class="iconfont icon-iconm_daick"></i>
  422. </div>
  423. <div class="box-text">* {{ i.packQuantity }}</div>
  424. </div>
  425. <div class="add-box">
  426. <i class="iconfont icon-iconm_tianjia1" @click="openDtlModal"></i>
  427. </div>
  428. </div>
  429. </el-form>
  430. <template #footer>
  431. <el-button @click="handleClose" size="large">取 消</el-button>
  432. <el-button
  433. type="primary"
  434. @click="submitForm()"
  435. size="large"
  436. :loading="submitLoading"
  437. >
  438. 确 定
  439. </el-button>
  440. </template>
  441. </el-dialog>
  442. <el-dialog
  443. title="合并出货"
  444. v-model="dialogVisibleOne"
  445. width="400"
  446. v-loading="loadingOne"
  447. >
  448. <byForm
  449. :formConfig="formConfig"
  450. :formOption="formOption"
  451. v-model="formData.dataOne"
  452. :rules="rules"
  453. ref="byform"
  454. >
  455. </byForm>
  456. <template #footer>
  457. <el-button @click="dialogVisibleOne = false" size="large"
  458. >取 消</el-button
  459. >
  460. <el-button
  461. type="primary"
  462. @click="submitFormOne()"
  463. size="large"
  464. :loading="submitLoading"
  465. >
  466. 确 定
  467. </el-button>
  468. </template>
  469. </el-dialog>
  470. </div>
  471. </template>
  472. <script setup>
  473. /* eslint-disable vue/no-unused-components */
  474. import { ElMessage, ElMessageBox } from "element-plus";
  475. import byTable from "@/components/byTable/index";
  476. import byForm from "@/components/byForm/index";
  477. import FileUpload from "@/components/FileUpload/index";
  478. import { computed, defineComponent, ref } from "vue";
  479. import { getToken } from "@/utils/auth";
  480. const loading = ref(false);
  481. const loadingOne = ref(false);
  482. const dtlModalType = ref(false);
  483. const submitLoading = ref(false);
  484. const sourceList = ref({
  485. data: [],
  486. pagination: {
  487. total: 3,
  488. pageNum: 1,
  489. pageSize: 10,
  490. status: "",
  491. },
  492. });
  493. const computeBomVolume = () => {
  494. if (
  495. boxFormData.value.boxLong &&
  496. boxFormData.value.boxWide &&
  497. boxFormData.value.boxHigh
  498. ) {
  499. boxFormData.value.bomVolume =
  500. (boxFormData.value.boxLong *
  501. boxFormData.value.boxWide *
  502. boxFormData.value.boxHigh) /
  503. 1000000;
  504. }
  505. };
  506. const openDtlUpdata = (index) => {
  507. boxFormType = "updata";
  508. boxIndex.value = index;
  509. boxFormData.value = { ...formData.data.packDetailList[index] };
  510. formData.data.contractProductData.forEach((item) => {
  511. item.disabled = false;
  512. boxFormData.value.packDetailProductList.forEach((item1) => {
  513. if (item.mathId == item1.mathId) {
  514. item.disabled = true;
  515. }
  516. });
  517. });
  518. dtlModalType.value = true;
  519. };
  520. let boxFormData = ref({
  521. packQuantity: null,
  522. netWeight: null,
  523. roughWeight: null,
  524. boxLong: null,
  525. boxWide: null,
  526. boxHigh: null,
  527. packDetailGoodsList: [],
  528. packDetailProductList: [],
  529. bomVolume: null,
  530. //生成唯一id
  531. id: Math.random().toString(36).substr(2),
  532. });
  533. const openCustom = (type) => {
  534. if (type == "2" && boxFormData.value.packDetailGoodsList.length == 0) {
  535. for (let i = 0; i < boxFormData.value.packDetailProductList.length; i++) {
  536. const item = boxFormData.value.packDetailProductList[i];
  537. if (item.quantity == null) {
  538. ElMessage.error("请填写装箱数量");
  539. return;
  540. }
  541. if (item.productId == null) {
  542. ElMessage.error("请填写选择产品");
  543. return;
  544. }
  545. }
  546. boxFormData.value.packDetailGoodsList =
  547. boxFormData.value.packDetailProductList.map((item) => {
  548. return {
  549. remark: item.productName,
  550. unit: null,
  551. quantity: item.quantity,
  552. };
  553. });
  554. }
  555. encasementType.value = type;
  556. };
  557. const openDtlModal = () => {
  558. if (
  559. !formData.data.contractProductData ||
  560. formData.data.contractProductData.length == 0
  561. ) {
  562. ElMessage.error("请先选择合同");
  563. return;
  564. }
  565. boxFormData.value = {
  566. packQuantity: null,
  567. netWeight: null,
  568. roughWeight: null,
  569. boxLong: null,
  570. boxWide: null,
  571. boxHigh: null,
  572. packDetailGoodsList: [],
  573. packDetailProductList: [],
  574. bomVolume: null,
  575. //生成唯一id
  576. id: Math.random().toString(36).substr(2),
  577. };
  578. boxFormType = "add";
  579. boxIndex.value = formData.data.packDetailList.length;
  580. formData.data.contractProductData.forEach((item) => {
  581. item.disabled = false;
  582. boxFormData.value.packDetailProductList.forEach((item1) => {
  583. if (item.mathId == item1.mathId) {
  584. item.disabled = true;
  585. }
  586. });
  587. });
  588. dtlModalType.value = true;
  589. };
  590. const boxIndex = ref(0);
  591. const packDetailProductListPush = (index) => {
  592. if (encasementType.value == "2") {
  593. boxFormData.value.packDetailGoodsList.push({
  594. remark: null,
  595. unit: null,
  596. quantity: null,
  597. });
  598. } else {
  599. boxFormData.value.packDetailProductList.push({
  600. contractId: null,
  601. productName: null,
  602. contractProductId: null,
  603. quantity: null,
  604. productId: null,
  605. productModel: null,
  606. remark: null,
  607. });
  608. }
  609. };
  610. let boxFormType = "add";
  611. const submitBox = () => {
  612. formDom.value.validate((vaild) => {
  613. if (vaild) {
  614. if (boxFormData.value.packDetailProductList.length == 0) {
  615. ElMessage.error("请添加产品");
  616. return;
  617. }
  618. for (let i = 0; i < boxFormData.value.packDetailProductList.length; i++) {
  619. const item = boxFormData.value.packDetailProductList[i];
  620. if (item.quantity == null) {
  621. ElMessage.error("请填写装箱数量");
  622. return;
  623. } else {
  624. if (
  625. item.quantity * boxFormData.value.packQuantity >
  626. item.waitQuantity
  627. ) {
  628. return ElMessage({
  629. message: "装箱数量 * 总箱数不可大于待装箱数量",
  630. type: "info",
  631. });
  632. }
  633. }
  634. if (item.productId == null) {
  635. ElMessage.error("请填写选择产品");
  636. return;
  637. }
  638. }
  639. dtlModalType.value = false;
  640. if (boxFormType == "add") {
  641. formData.data.packDetailList.push({ ...boxFormData.value });
  642. } else {
  643. formData.data.packDetailList[boxIndex.value] = { ...boxFormData.value };
  644. }
  645. }
  646. });
  647. };
  648. const dtlformData = reactive({
  649. data: {
  650. customerId: null,
  651. contractIds: null,
  652. packQuantity: null,
  653. netWeight: null,
  654. roughWeight: null,
  655. boxLong: null,
  656. boxWide: null,
  657. boxHigh: null,
  658. remark: null,
  659. packDetailGoodsList: [],
  660. packDetailProductList: [],
  661. bomVolume: null,
  662. },
  663. });
  664. const selectProduct = (val, index) => {
  665. let msg = {
  666. ...formData.data.contractProductData.find((item) => item.mathId == val),
  667. };
  668. //根据val 禁用相应的下拉数据
  669. boxFormData.value.packDetailProductList[index] = {
  670. productId: msg.productId,
  671. productName: msg.productName,
  672. productSpec: msg.productSpec,
  673. contractCode: msg.contractCode,
  674. contractProductId: msg.id,
  675. cpQuantity: msg.cpQuantity,
  676. waitQuantity: msg.waitQuantity,
  677. quantity: null,
  678. mathId: msg.mathId,
  679. contractId: msg.contractId,
  680. contractProductId: msg.id,
  681. };
  682. formData.data.contractProductData.forEach((item) => {
  683. item.disabled = false;
  684. boxFormData.value.packDetailProductList.forEach((item1) => {
  685. if (item.mathId == item1.mathId) {
  686. item.disabled = true;
  687. }
  688. });
  689. });
  690. };
  691. let dialogVisible = ref(false);
  692. let dialogVisibleOne = ref(false);
  693. let modalType = ref("add");
  694. let fileList = ref([]);
  695. let rules = ref({
  696. contractIds: [{ required: true, message: "请选择合同", trigger: "change" }],
  697. packQuantity: [{ required: true, message: "请输入箱数", trigger: "blur" }],
  698. netWeight: [{ required: true, message: "请输入净重", trigger: "blur" }],
  699. roughWeight: [{ required: true, message: "请输入毛重", trigger: "blur" }],
  700. boxLong: [{ required: true, message: "请输入长", trigger: "blur" }],
  701. boxWide: [{ required: true, message: "请输入宽", trigger: "blur" }],
  702. boxHigh: [{ required: true, message: "请输入高", trigger: "blur" }],
  703. quantity: [{ required: true, message: "请输入装箱数量", trigger: "blur" }],
  704. quantityOne: [{ required: true, message: "请输入数量", trigger: "blur" }],
  705. unit: [{ required: true, message: "请输入单位", trigger: "blur" }],
  706. remark: [{ required: true, message: "请输入货物描述", trigger: "blur" }],
  707. productId: [{ required: true, message: "请选择产品", trigger: "change" }],
  708. contractId: [{ required: true, message: "请选择主合同", trigger: "change" }],
  709. mathId: [{ required: true, message: "请选择产品", trigger: "change" }],
  710. });
  711. const { proxy } = getCurrentInstance();
  712. const selectConfig = reactive([
  713. {
  714. label: "出货状态",
  715. prop: "shipmentStatus",
  716. data: [
  717. {
  718. label: "未出货",
  719. value: "0",
  720. },
  721. {
  722. label: "已出货",
  723. value: "1",
  724. },
  725. ],
  726. },
  727. ]);
  728. const config = computed(() => {
  729. return [
  730. {
  731. type: "selection",
  732. attrs: {
  733. checkAtt: "isCheck",
  734. },
  735. },
  736. {
  737. attrs: {
  738. label: "合同号",
  739. prop: "codeAPName",
  740. slot: "code",
  741. },
  742. },
  743. {
  744. attrs: {
  745. label: "产品名称",
  746. prop: "codeAPName",
  747. slot: "productName",
  748. },
  749. },
  750. {
  751. attrs: {
  752. label: "总箱数",
  753. prop: "packQuantity",
  754. width: 90,
  755. },
  756. },
  757. {
  758. attrs: {
  759. label: "净重",
  760. slot: "netWeight",
  761. width: 90,
  762. },
  763. },
  764. {
  765. attrs: {
  766. label: "毛重",
  767. slot: "roughWeight",
  768. width: 90,
  769. },
  770. },
  771. {
  772. attrs: {
  773. label: "长",
  774. slot: "boxLong",
  775. width: 90,
  776. },
  777. },
  778. {
  779. attrs: {
  780. label: "宽",
  781. slot: "boxWide",
  782. width: 90,
  783. },
  784. },
  785. {
  786. attrs: {
  787. label: "高",
  788. slot: "boxHigh",
  789. width: 90,
  790. },
  791. },
  792. {
  793. attrs: {
  794. label: "体积",
  795. slot: "bomVolume",
  796. width: 90,
  797. },
  798. },
  799. {
  800. attrs: {
  801. label: "总净重",
  802. prop: "netWeight",
  803. width: 120,
  804. },
  805. render(netWeight) {
  806. return netWeight + " kg";
  807. },
  808. },
  809. {
  810. attrs: {
  811. label: "总毛重",
  812. prop: "roughWeight",
  813. width: 120,
  814. },
  815. render(roughWeight) {
  816. return roughWeight + " kg";
  817. },
  818. },
  819. {
  820. attrs: {
  821. label: "总体积",
  822. prop: "bomVolume",
  823. width: 120,
  824. },
  825. render(bomVolume) {
  826. return bomVolume + " m³";
  827. },
  828. },
  829. {
  830. attrs: {
  831. label: "出货状态",
  832. prop: "shipmentStatus",
  833. width: 90,
  834. },
  835. render(status) {
  836. return status == 1 ? "已出货" : status == 0 ? "未出货" : "";
  837. },
  838. },
  839. {
  840. attrs: {
  841. label: "出货时间",
  842. prop: "shipmentTime",
  843. width: 155,
  844. },
  845. render(shipmentTime) {
  846. if (shipmentTime) {
  847. return shipmentTime.slice(5, 10);
  848. } else {
  849. return "";
  850. }
  851. },
  852. },
  853. {
  854. attrs: {
  855. label: "操作",
  856. width: "90",
  857. align: "center",
  858. },
  859. // 渲染 el-button,一般用在最后一列。
  860. renderHTML(row) {
  861. return [
  862. {
  863. attrs: {
  864. label: "删除",
  865. type: "primary",
  866. text: true,
  867. disabled: false,
  868. },
  869. el: "button",
  870. click() {
  871. ElMessageBox.confirm(
  872. "此操作将永久作废该数据, 是否继续?",
  873. "提示",
  874. {
  875. confirmButtonText: "确定",
  876. cancelButtonText: "取消",
  877. type: "warning",
  878. }
  879. ).then(() => {
  880. // 删除
  881. proxy
  882. .post("/pack/delete", {
  883. id: row.packId,
  884. })
  885. .then((res) => {
  886. ElMessage({
  887. message: "作废成功",
  888. type: "success",
  889. });
  890. getList();
  891. });
  892. });
  893. },
  894. },
  895. ];
  896. },
  897. },
  898. ];
  899. });
  900. const formDom = ref(null);
  901. let formData = reactive({
  902. data: {},
  903. dataOne: {},
  904. });
  905. const formOption = reactive({
  906. inline: true,
  907. labelWidth: 100,
  908. itemWidth: 100,
  909. rules: [],
  910. });
  911. const byform = ref(null);
  912. const treeData = ref([]);
  913. const formConfig = reactive([
  914. {
  915. type: "select",
  916. prop: "contractId",
  917. label: "主合同",
  918. required: true,
  919. data: [],
  920. },
  921. ]);
  922. const encasementType = ref("1");
  923. const getList = async (req) => {
  924. selectData.value = [];
  925. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  926. loading.value = true;
  927. proxy.post("/packDetail/page", sourceList.value.pagination).then((res) => {
  928. for (let i = 0; i < res.rows.length; i++) {
  929. const e = res.rows[i];
  930. e.isCheck = e.shipmentStatus == 1 ? false : true;
  931. let arr = [];
  932. let newArr = [];
  933. arr = e.dataJsonList.split("_");
  934. for (let j = 0; j < arr.length; j++) {
  935. const jele = arr[j];
  936. const jarr = jele.split(",");
  937. const obj = {
  938. bomVolume: jarr[0],
  939. boxLong: jarr[1],
  940. boxWide: jarr[2],
  941. boxHigh: jarr[3],
  942. roughWeight: jarr[4],
  943. netWeight: jarr[5],
  944. };
  945. let createArr = new Array(Number(jarr[6])).fill(obj);
  946. newArr = [...newArr, ...createArr];
  947. }
  948. e.dataJsonListCopy = newArr;
  949. }
  950. sourceList.value.data = res.rows;
  951. sourceList.value.pagination.total = res.total;
  952. loading.value = false;
  953. });
  954. };
  955. const openModal = () => {
  956. modalType.value = "add";
  957. formData.data = {
  958. packDetailList: [],
  959. contractIds: [],
  960. };
  961. dialogVisible.value = true;
  962. handleChangeCustomer("");
  963. };
  964. const openModalOne = () => {
  965. formData.dataOne = {
  966. ids: [],
  967. contractId: "",
  968. };
  969. let ids = []; //合同id
  970. let idsOne = []; //包装id
  971. const list = selectData.value;
  972. for (let i = 0; i < list.length; i++) {
  973. const e = list[i];
  974. ids = [...ids, ...e.contractIds.split(",")];
  975. idsOne = [...idsOne, ...e.ids.split(",")];
  976. }
  977. formData.dataOne.ids = idsOne;
  978. proxy.post(`/contract/getByIds`, ids).then((res) => {
  979. formConfig[0].data = res.map((x) => ({
  980. label: x.code,
  981. value: x.id,
  982. }));
  983. dialogVisibleOne.value = true;
  984. });
  985. };
  986. const packDetailProductListDom = ref(null);
  987. const submitForm = () => {
  988. formDom.value.validate((vaild) => {
  989. if (vaild) {
  990. if (!formData.data.packDetailList.length > 0) {
  991. return ElMessage({
  992. message: "请添加装箱明细!",
  993. type: "info",
  994. });
  995. }
  996. submitLoading.value = true;
  997. loadingOne.value = true;
  998. formData.data.contractIds = formData.data.contractIds.join(",");
  999. for (let i = 0; i < formData.data.packDetailList.length; i++) {
  1000. const e = formData.data.packDetailList[i];
  1001. e.bomVolume = (e.boxLong * e.boxWide * e.boxHigh) / 1000000;
  1002. e.contractIds = formData.data.contractIds;
  1003. e.customerId = formData.data.customerId;
  1004. }
  1005. formData.data.packDetailList.map((x) => {
  1006. return {
  1007. ...x,
  1008. customerId: formData.data.customerId,
  1009. contractIds: formData.data.contractIds,
  1010. };
  1011. });
  1012. let reqData = { ...formData.data };
  1013. //删除 reqData.packDetailList 里的id
  1014. reqData.packDetailList.forEach((item) => {
  1015. delete item.id;
  1016. });
  1017. proxy.post("/pack/" + modalType.value, reqData).then(
  1018. (res) => {
  1019. ElMessage({
  1020. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  1021. type: "success",
  1022. });
  1023. dialogVisible.value = false;
  1024. submitLoading.value = false;
  1025. loadingOne.value = false;
  1026. getList();
  1027. },
  1028. (err) => {
  1029. submitLoading.value = false;
  1030. loading.value = false;
  1031. }
  1032. );
  1033. }
  1034. });
  1035. };
  1036. const table = ref(null);
  1037. const submitFormOne = () => {
  1038. byform.value.handleSubmit((valid) => {
  1039. loading.value = true;
  1040. submitLoading.value = true;
  1041. proxy.post("/packDetail/shipment", formData.dataOne).then(
  1042. (res) => {
  1043. ElMessage({
  1044. message: "出货成功",
  1045. type: "success",
  1046. });
  1047. dialogVisibleOne.value = false;
  1048. submitLoading.value = false;
  1049. loading.value = false;
  1050. getList();
  1051. selectData.value = [];
  1052. },
  1053. (err) => {
  1054. submitLoading.value = false;
  1055. loading.value = false;
  1056. }
  1057. );
  1058. });
  1059. };
  1060. const selectData = ref([]);
  1061. const selectRow = (data) => {
  1062. selectData.value = data;
  1063. };
  1064. const selectProductData = ref([]);
  1065. const handleSelectProduct = (data) => {
  1066. selectProductData.value = data;
  1067. };
  1068. const tableDom = ref(null);
  1069. const handleClickPacking = () => {
  1070. if (selectProductData.value.length > 0) {
  1071. const list = selectProductData.value;
  1072. for (let i = 0; i < list.length; i++) {
  1073. const e = list[i];
  1074. if (!e.quantity) {
  1075. return ElMessage({
  1076. message: "请输入装箱数量",
  1077. type: "info",
  1078. });
  1079. }
  1080. }
  1081. for (let i = 0; i < list.length; i++) {
  1082. const e = list[i];
  1083. for (let j = 0; j < formData.data.contractProductData.length; j++) {
  1084. const jele = formData.data.contractProductData[j];
  1085. if (e.id === jele.id && e.quantity > Number(jele.waitQuantity)) {
  1086. return ElMessage({
  1087. message: "装箱数量不可大于袋装箱数量",
  1088. type: "info",
  1089. });
  1090. }
  1091. }
  1092. }
  1093. const packDetailProductList = list.map((x) => ({
  1094. contractCode: x.contractCode,
  1095. contractId: x.contractId,
  1096. contractProductId: x.id,
  1097. quantity: x.quantity,
  1098. productId: x.productId,
  1099. productName: x.productName,
  1100. }));
  1101. const customerId = formData.data.customerId ? formData.data.customerId : "";
  1102. const contractIds = formData.data.contractIds
  1103. ? formData.data.contractIds.join(",")
  1104. : "";
  1105. let item = {
  1106. customerId: customerId,
  1107. contractIds: contractIds,
  1108. packQuantity: 1,
  1109. netWeight: null,
  1110. roughWeight: null,
  1111. boxLong: null,
  1112. boxWide: null,
  1113. boxHigh: null,
  1114. bomVolume: "",
  1115. remark: "",
  1116. packDetailGoodsList: [],
  1117. packDetailProductList: packDetailProductList,
  1118. isShow: false,
  1119. };
  1120. formData.data.packDetailList.push(item);
  1121. handleChangePackQuantity(
  1122. item.packQuantity,
  1123. formData.data.packDetailList.length - 1
  1124. );
  1125. tableDom.value.clearSelection();
  1126. selectProductData.value = [];
  1127. table.value.clearSelection();
  1128. } else {
  1129. return ElMessage({
  1130. message: "请选择产品 !",
  1131. type: "info",
  1132. });
  1133. }
  1134. };
  1135. const handleChangePackQuantity = (val, index) => {
  1136. const obj = {};
  1137. for (let i = 0; i < formData.data.contractProductData.length; i++) {
  1138. const e = formData.data.contractProductData[i];
  1139. obj[e.contractId + "_" + e.productId + ""] = (
  1140. Number(e.cpQuantity) - Number(e.sumPackQuantity)
  1141. ).toFixed(2);
  1142. }
  1143. // 计算数量 即装箱数量 * 箱数 新增字段放在最外层
  1144. for (let i = 0; i < formData.data.packDetailList.length; i++) {
  1145. const ele = formData.data.packDetailList[i];
  1146. for (let j = 0; j < ele.packDetailProductList.length; j++) {
  1147. const jele = ele.packDetailProductList[j];
  1148. ele[jele.contractId + "_" + jele.productId + ""] = (
  1149. Number(ele.packQuantity) * jele.quantity
  1150. ).toFixed(2);
  1151. }
  1152. }
  1153. // 计算新的待装箱数量
  1154. for (let i = 0; i < formData.data.packDetailList.length; i++) {
  1155. const e = formData.data.packDetailList[i];
  1156. for (const key in obj) {
  1157. if (e.hasOwnProperty(key)) {
  1158. obj[key] = (obj[key] - e[key]).toFixed(2);
  1159. if (obj[key] < 0) {
  1160. e.packQuantity = null;
  1161. handleChangePackQuantity(null, index);
  1162. return ElMessage({
  1163. message: "装箱数量 * 箱数不可大于待装箱数量",
  1164. type: "info",
  1165. });
  1166. }
  1167. }
  1168. }
  1169. }
  1170. // 赋值
  1171. for (let i = 0; i < formData.data.contractProductData.length; i++) {
  1172. const e = formData.data.contractProductData[i];
  1173. for (const key in obj) {
  1174. if (e.contractId + "_" + e.productId + "" === key) {
  1175. e.waitQuantity = obj[key];
  1176. }
  1177. }
  1178. }
  1179. // }
  1180. };
  1181. const handleCustomPush = (index) => {
  1182. formData.data.packDetailList[index].packDetailGoodsList.push({
  1183. unit: "",
  1184. quantity: "",
  1185. remark: "",
  1186. });
  1187. };
  1188. const handleCustomRemove = (index, sonIndex) => {
  1189. formData.data.packDetailList[index].packDetailGoodsList.splice(sonIndex, 1);
  1190. };
  1191. const customerList = ref([]);
  1192. const getSelectData = () => {
  1193. proxy.post("/customer/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  1194. customerList.value = res.rows.map((item) => {
  1195. return {
  1196. ...item,
  1197. label: item.name,
  1198. value: item.id,
  1199. };
  1200. });
  1201. });
  1202. };
  1203. const contractData = ref([]);
  1204. const handleChangeCustomer = (val) => {
  1205. proxy
  1206. .get(`/contract/getNoPackContractByCustomerId?customerId=${val}`)
  1207. .then((res) => {
  1208. contractData.value = res.data;
  1209. formData.data.contractIds = [];
  1210. formData.data.packDetailList = [];
  1211. });
  1212. };
  1213. const handleChangeContract = (val) => {
  1214. const customerId = formData.data.customerId ? formData.data.customerId : "";
  1215. proxy
  1216. .get(
  1217. `/contractProduct/getNoPackContractProductById?customerId=${customerId}&contractIds=${val}`
  1218. )
  1219. .then((res) => {
  1220. formData.data.contractProductData = res.data.map((x) => ({
  1221. ...x,
  1222. waitQuantity: (
  1223. Number(x.cpQuantity) - Number(x.sumPackQuantity)
  1224. ).toFixed(2),
  1225. quantity: null,
  1226. mathId: Math.random().toString(36).substr(2),
  1227. disabled: false,
  1228. }));
  1229. handleChangePackQuantity();
  1230. });
  1231. };
  1232. const getData = (data, type) => {
  1233. if (!data) return [];
  1234. const arr = data.split(",");
  1235. if (arr && arr.length > 0) {
  1236. const arrOne = [];
  1237. for (let i = 0; i < arr.length; i++) {
  1238. const e = arr[i];
  1239. if (type === "code") {
  1240. arrOne.push(e.split("_")[0]);
  1241. } else if (type === "productName") {
  1242. arrOne.push(e.split("_")[1]);
  1243. }
  1244. }
  1245. return arrOne;
  1246. }
  1247. return [];
  1248. };
  1249. const handleClose = () => {
  1250. dialogVisible.value = false;
  1251. selectProductData.value = [];
  1252. };
  1253. getSelectData();
  1254. getList();
  1255. const clickDelete = (index) => {
  1256. formData.data.packDetailList.splice(index, 1);
  1257. handleChangePackQuantity();
  1258. };
  1259. </script>
  1260. <style lang="scss" scoped>
  1261. .tenant {
  1262. padding: 20px;
  1263. }
  1264. :deep(.el-collapse-item__header) {
  1265. background-color: #fde6c8;
  1266. border: none;
  1267. }
  1268. :deep(.el-collapse-item__wrap) {
  1269. background-color: #fde6c8;
  1270. border: none;
  1271. }
  1272. .box-icon-warp {
  1273. width: 100%;
  1274. display: flex;
  1275. .add-box {
  1276. width: 33.33%;
  1277. height: 100px;
  1278. border-radius: 50%;
  1279. display: flex;
  1280. justify-content: center;
  1281. i {
  1282. display: block;
  1283. width: 100px;
  1284. height: 100px;
  1285. border: 1px solid #dcdcdc;
  1286. text-align: center;
  1287. line-height: 100px;
  1288. cursor: pointer;
  1289. }
  1290. }
  1291. .box-content {
  1292. width: 33.33%;
  1293. height: 100px;
  1294. border-radius: 50%;
  1295. display: flex;
  1296. justify-content: center;
  1297. align-items: center;
  1298. .box-icon {
  1299. i {
  1300. font-size: 60px;
  1301. }
  1302. color: #f5a623;
  1303. }
  1304. .box-text {
  1305. font-size: 20px;
  1306. color: #f5a623;
  1307. }
  1308. }
  1309. }
  1310. .box {
  1311. padding: 15px;
  1312. background: #fde6c8;
  1313. border: 1px solid #7fb5e3;
  1314. margin-bottom: 10px;
  1315. width: 100%;
  1316. .flex-box {
  1317. width: 100%;
  1318. display: flex;
  1319. flex-wrap: wrap;
  1320. .item {
  1321. width: 50%;
  1322. margin-bottom: 10px;
  1323. div {
  1324. line-height: 22px;
  1325. }
  1326. }
  1327. }
  1328. .line {
  1329. width: 100%;
  1330. height: 1px;
  1331. background: #7fb5e3;
  1332. margin: 20px 0;
  1333. }
  1334. .bottom-arrow {
  1335. text-align: center;
  1336. cursor: pointer;
  1337. color: #0084ff;
  1338. }
  1339. }
  1340. </style>