You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4879 lines
164 KiB

1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
9 months ago
1 year ago
9 months ago
1 year ago
1 year ago
1 year ago
11 months ago
1 year ago
1 year ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
11 months ago
1 year ago
8 months ago
1 year ago
1 year ago
1 year ago
1 year ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
11 months ago
11 months ago
11 months ago
11 months ago
7 months ago
11 months ago
11 months ago
11 months ago
10 months ago
11 months ago
1 year ago
1 year ago
7 months ago
7 months ago
7 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
8 months ago
1 year ago
1 year ago
1 year ago
1 year ago
7 months ago
1 year ago
1 year ago
1 year ago
10 months ago
7 months ago
1 year ago
1 year ago
9 months ago
1 year ago
8 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
7 months ago
1 year ago
10 months ago
1 year ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
8 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
11 months ago
1 year ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
7 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
7 months ago
1 year ago
1 year ago
1 year ago
8 months ago
1 year ago
1 year ago
1 year ago
11 months ago
7 months ago
1 year ago
9 months ago
9 months ago
9 months ago
9 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
8 months ago
9 months ago
9 months ago
1 year ago
10 months ago
8 months ago
9 months ago
9 months ago
9 months ago
1 year ago
1 year ago
9 months ago
9 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
9 months ago
9 months ago
9 months ago
9 months ago
1 year ago
1 year ago
1 year ago
10 months ago
1 year ago
11 months ago
1 year ago
1 year ago
1 year ago
11 months ago
11 months ago
11 months ago
1 year ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
11 months ago
11 months ago
11 months ago
1 year ago
11 months ago
1 year ago
11 months ago
1 year ago
11 months ago
1 year ago
11 months ago
1 year ago
11 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
1 year ago
1 year ago
1 year ago
7 months ago
11 months ago
7 months ago
11 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
1 year ago
1 year ago
1 year ago
9 months ago
1 year ago
10 months ago
1 year ago
11 months ago
7 months ago
1 year ago
  1. <template>
  2. <div class="mod-config">
  3. <el-form :inline="true" label-position="top" label-width="100px" style="margin-top: 0px;">
  4. <el-form-item :label="'BU:'">
  5. <el-select v-model="searchData.buNo" placeholder="请选择" >
  6. <el-option label="全部" value=""></el-option>
  7. <el-option
  8. v-for = "i in buList"
  9. :key = "i.buNo"
  10. :label = "i.buDesc"
  11. :value = "i.buNo">
  12. </el-option>
  13. </el-select>
  14. </el-form-item>
  15. <el-form-item :label="'发货通知单:'">
  16. <el-input v-model="searchData.delNo" clearable style="width: 120px"></el-input>
  17. </el-form-item>
  18. <el-form-item :label="'CMC Invoice:'">
  19. <el-input v-model="searchData.cmcInvoice" clearable style="width: 120px"></el-input>
  20. </el-form-item>
  21. <el-form-item :label="'通知单状态:'">
  22. <el-select filterable v-model="searchData.notifyStatus" style="width: 120px">
  23. <el-option label="全部" value=""></el-option>
  24. <el-option label="已下达" value="已下达"></el-option>
  25. <el-option label="仓库已确认" value="仓库已确认"></el-option>
  26. <el-option label="已报关" value="已报关"></el-option>
  27. <el-option label="订单取消" value="订单取消"></el-option>
  28. </el-select>
  29. </el-form-item>
  30. <el-form-item :label="'ReadyDate'" >
  31. <el-date-picker
  32. style="width: 120px"
  33. v-model="searchData.startDate"
  34. type="date"
  35. format="yyyy-MM-dd"
  36. value-format="yyyy-MM-dd"
  37. placeholder="选择日期">
  38. </el-date-picker>
  39. </el-form-item>
  40. <el-form-item :label="'To'" >
  41. <el-date-picker
  42. style="width: 120px"
  43. v-model="searchData.endDate"
  44. type="date"
  45. format="yyyy-MM-dd"
  46. value-format="yyyy-MM-dd"
  47. placeholder="选择日期">
  48. </el-date-picker>
  49. </el-form-item>
  50. <el-form-item :label="'是否导出:'">
  51. <el-select v-model="searchData.exportFlag" style="width: 120px">
  52. <el-option label="全部" value=""></el-option>
  53. <el-option label="已导出" value="Y"></el-option>
  54. <el-option label="未导出" value="N"></el-option>
  55. </el-select>
  56. </el-form-item>
  57. <el-form-item label="改单">
  58. <el-checkbox v-model="searchData.modifyData" true-label="true" false-label="false" @change="searchTable()"></el-checkbox>
  59. </el-form-item>
  60. <el-form-item label="FSC">
  61. <el-checkbox v-model="searchData.fscFlag" true-label="true" false-label="false" @change="searchTable()"></el-checkbox>
  62. </el-form-item>
  63. <el-form-item label="沃尔玛订单">
  64. <el-checkbox v-model="searchData.walMartOrderFlag" true-label="true" false-label="false" @change="searchTable()"></el-checkbox>
  65. </el-form-item>
  66. <el-form-item label="维护箱尺寸">
  67. <el-checkbox v-model="searchData.boxSizeFlag" true-label="true" false-label="false" @change="searchTable()"></el-checkbox>
  68. </el-form-item>
  69. <el-form-item :label="' '" >
  70. <el-button @click="searchTable()" type="primary" style="margin-left: 2px;margin-top: 0px">{{'查询'}}</el-button>
  71. </el-form-item>
  72. </el-form>
  73. <el-table
  74. @row-click="changeData"
  75. highlight-current-row
  76. :height="height"
  77. :data="dataList"
  78. ref="mainTable"
  79. border :cell-style="cellStyle"
  80. :row-class-name="tableRowClassName"
  81. v-loading="dataListLoading"
  82. style="width: 100%;">
  83. <el-table-column
  84. header-align="center"
  85. align="center"
  86. width="100"
  87. fixed="left"
  88. label="操作">
  89. <template slot-scope="scope">
  90. <a type="text" size="small" v-if="scope.row.notifyStatus==='已报关'" @click="updateModelOpen(scope.row)">修改</a>
  91. <a type="text" size="small" v-if="scope.row.notifyStatus==='已下达'" @click="confirmModelOpen(scope.row)">仓库确认</a>
  92. <a type="text" size="small" v-if="scope.row.notifyStatus==='仓库已确认'" @click="cancerConfirm(scope.row)">取消确认</a>
  93. </template>
  94. </el-table-column>
  95. <el-table-column
  96. v-for="(item,index) in columnList1" :key="index"
  97. :sortable="item.columnSortable"
  98. :prop="item.columnProp"
  99. :header-align="item.headerAlign"
  100. :show-overflow-tooltip="item.showOverflowTooltip"
  101. :align="item.align"
  102. :fixed="item.fixed==''?false:item.fixed"
  103. :min-width="item.columnWidth"
  104. :label="item.columnLabel">
  105. <template slot-scope="scope">
  106. <el-tooltip
  107. v-if="!item.columnHidden && showDelayWarningTooltip(scope.row, item.columnProp)"
  108. :content="getDelayWarningTooltip(scope.row)"
  109. placement="top">
  110. <span>{{scope.row[item.columnProp]}}</span>
  111. </el-tooltip>
  112. <span v-else-if="!item.columnHidden"> {{scope.row[item.columnProp]}}</span>
  113. <span v-if="item.columnImage"><img :src="scope.row[item.columnProp]"
  114. style="width: 100px; height: 80px"/></span>
  115. </template>
  116. </el-table-column>
  117. </el-table>
  118. <el-pagination
  119. @size-change="sizeChangeHandle"
  120. @current-change="currentChangeHandle"
  121. :current-page="pageIndex"
  122. :page-sizes="[20, 50, 100, 1000]"
  123. :page-size="pageSize"
  124. :total="totalPage"
  125. layout="total, sizes, prev, pager, next, jumper">
  126. </el-pagination>
  127. <el-tabs style="font-size: 12px;min-height: 200px" class="customer-tab" v-model="activeName" type="border-card" @tab-click="tabClick" >
  128. <el-tab-pane :label="currentRow.cmcInvoice+'明细'" name="detail">
  129. <el-table
  130. :height="height" ref="cloDetailTable"
  131. :data="dataList2" show-summary :summary-method="getDetailSummaries"
  132. border :cell-style="cellStyleDetail"
  133. style="width: 100%;">
  134. <el-table-column
  135. v-for="(item,index) in columnList2" :key="index"
  136. :sortable="item.columnSortable"
  137. :prop="item.columnProp"
  138. :header-align="item.headerAlign"
  139. :show-overflow-tooltip="item.showOverflowTooltip"
  140. :align="item.align"
  141. :fixed="item.fixed==''?false:item.fixed"
  142. :min-width="item.columnWidth"
  143. :label="item.columnLabel">
  144. <template slot-scope="scope">
  145. <!-- 金额字段特殊处理 -->
  146. <span v-if="item.columnProp === 'ttlAmount' || item.columnProp === 'sumPrice'">
  147. {{!!scope.row[item.columnProp]?scope.row[item.columnProp].toFixed(2):''}}
  148. </span>
  149. <!-- PN字段特殊处理添加提示信息 -->
  150. <template v-else-if="item.columnProp === 'pn'">
  151. <el-tooltip
  152. v-if="isPnDataIncomplete(scope.row)"
  153. :content="getPnIncompleteTooltip(scope.row)"
  154. placement="top">
  155. <span
  156. v-if="!item.columnHidden"
  157. class="clickable-pn"
  158. @click="navigateToPartHsCode(scope.row.pn)">
  159. {{ scope.row[item.columnProp] }}
  160. </span>
  161. </el-tooltip>
  162. <span v-else-if="!item.columnHidden">{{ scope.row[item.columnProp] }}</span>
  163. </template>
  164. <!-- 其他字段正常处理 -->
  165. <template v-else>
  166. <span v-if="!item.columnHidden">{{ scope.row[item.columnProp] }}</span>
  167. <span v-if="item.columnImage"><img :src="scope.row[item.columnProp]" style="width: 100px; height: 80px"/></span>
  168. </template>
  169. </template>
  170. </el-table-column>
  171. </el-table>
  172. </el-tab-pane>
  173. <el-tab-pane label="手工装箱" name="box">
  174. <!-- <el-button @click="oneClickPacking()" type="primary" style="margin-left: 2px;margin-top: 0px">{{'一键装箱'}}</el-button>
  175. <el-button @click="newPalletModel()" type="primary" style="margin-left: 2px;margin-top: 0px">{{'装箱'}}</el-button>-->
  176. <el-button @click="openMergeBoxDialog()" type="primary" style="margin-left: 2px;margin-top: 0px">{{'装箱'}}</el-button>
  177. <el-button @click="palletMaintenance()" type="primary" style="margin-left: 2px;margin-top: 0px">{{'栈板维护'}}</el-button>
  178. <el-button @click="exportExcel()" type="primary" style="margin-left: 2px;margin-top: 0px">{{'导出装箱数据'}}</el-button>
  179. <el-button @click="upLoadPallet()" type="success" style="margin-left: 2px;margin-top: 0px">{{'导入装箱单'}}</el-button>
  180. <el-table ref="detailTable"
  181. :data="dataList4"
  182. :height="height"
  183. border show-summary :summary-method="getSummaries"
  184. v-loading="dataListLoading"
  185. style="width: 100%; ">
  186. <el-table-column
  187. header-align="center"
  188. align="center"
  189. width="150"
  190. fixed="left"
  191. label="操作">
  192. <template slot-scope="scope">
  193. <a type="text" size="small" @click="updatePalletModel(scope.row)">修改</a>
  194. <a type="text" size="small" @click="deletePallet(scope.row)">删除</a>
  195. </template>
  196. </el-table-column>
  197. <el-table-column
  198. v-for="(item,index) in columnList4" :key="index"
  199. :sortable="item.columnSortable"
  200. :prop="item.columnProp"
  201. :header-align="item.headerAlign"
  202. :show-overflow-tooltip="item.showOverflowTooltip"
  203. :align="item.align"
  204. :fixed="item.fixed==''?false:item.fixed"
  205. :min-width="item.columnWidth"
  206. :label="item.columnLabel">
  207. <template slot-scope="scope">
  208. <span v-if="!item.columnHidden"> {{ scope.row[item.columnProp] }}</span>
  209. <span v-if="item.columnImage"><img :src="scope.row[item.columnProp]"
  210. style="width: 100px; height: 80px"/></span>
  211. </template>
  212. </el-table-column>
  213. </el-table>
  214. </el-tab-pane>
  215. <el-tab-pane label="装箱明细" name="pallet">
  216. <packing-detail-tab
  217. ref="packingDetailTab"
  218. :current-row="currentRow"
  219. :height="height"
  220. :show-actions="true"
  221. @refresh="searchTable">
  222. </packing-detail-tab>
  223. </el-tab-pane>
  224. <el-tab-pane label="相关文档" name="codelnotifyConfirmDocument">
  225. <oss-components label="申请单号" style="margin-top: 5px" height="44vh" :columns="ossColumns"
  226. :order-ref1="currentRow.site" :order-ref2="currentRow.delNo" :codelnotifyFlag="'2'"
  227. :rfq-no="currentRow.delNo">
  228. </oss-components>
  229. </el-tab-pane>
  230. </el-tabs>
  231. <el-dialog title="仓库确认" :close-on-click-modal="false" v-drag :visible.sync="confirmModelFlag" width="400px">
  232. <el-form label-position="top" style="margin-left: 7px;margin-top: -5px;">
  233. <el-row :gutter="20">
  234. <el-col :span="12">
  235. <el-form-item :label="'CMC Invoice'" >
  236. <el-input v-model="confirmModel.cmcInvoice" disabled ></el-input>
  237. </el-form-item>
  238. </el-col>
  239. <el-col :span="12">
  240. <el-form-item :label="'ReadyDate'" >
  241. <el-input v-model="confirmModel.readyDate" disabled ></el-input>
  242. </el-form-item>
  243. </el-col>
  244. <el-col :span="12">
  245. <el-form-item :label="'实际发货日期'" >
  246. <el-date-picker
  247. style="width: 100%"
  248. v-model="confirmModel.actualNotifyDate"
  249. type="date"
  250. format="yyyy-MM-dd"
  251. value-format="yyyy-MM-dd"
  252. placeholder="选择日期">
  253. </el-date-picker>
  254. </el-form-item>
  255. </el-col>
  256. </el-row>
  257. </el-form>
  258. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  259. <el-button type="primary" @click="confirmDo()">保存</el-button>
  260. <el-button type="primary" @click="confirmModelFlag=false">关闭</el-button>
  261. </el-footer>
  262. </el-dialog>
  263. <el-dialog title="修改" :close-on-click-modal="false" v-drag :visible.sync="updateModelFlag" width="350px">
  264. <el-form label-position="top" style="margin-left: 7px;margin-top: -5px;">
  265. <el-row :gutter="20">
  266. <el-col :span="12">
  267. <el-form-item :label="'ReadyDate'" >
  268. <el-date-picker
  269. style="width: 100%"
  270. v-model="confirmModel.readyDate"
  271. type="date"
  272. format="yyyy-MM-dd"
  273. value-format="yyyy-MM-dd"
  274. placeholder="选择日期">
  275. </el-date-picker>
  276. </el-form-item>
  277. </el-col>
  278. <el-col :span="12">
  279. <el-form-item :label="'实际发货日期'" >
  280. <el-date-picker
  281. style="width: 100%"
  282. v-model="confirmModel.actualNotifyDate"
  283. type="date"
  284. format="yyyy-MM-dd"
  285. value-format="yyyy-MM-dd"
  286. placeholder="选择日期">
  287. </el-date-picker>
  288. </el-form-item>
  289. </el-col>
  290. </el-row>
  291. </el-form>
  292. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  293. <el-button type="primary" @click="updateDo()">保存</el-button>
  294. <el-button type="primary" @click="updateModelFlag=false">关闭</el-button>
  295. </el-footer>
  296. </el-dialog>
  297. <el-dialog title="维护箱" :close-on-click-modal="false" v-drag :visible.sync="boxModelFlag" width="500px">
  298. <el-form label-position="top" style="margin-left: 7px;margin-top: -5px;">
  299. <el-row :gutter="20">
  300. <el-col :span="12">
  301. <el-form-item :label="boxModelData.type===1?'物料编码':''">
  302. <span v-if="boxModelData.type===0" slot="label" @click="openPartDialog()"><a herf="#">物料编码</a></span>
  303. <el-input v-model="boxModelData.pn" :disabled="boxModelData.type===1" ></el-input>
  304. </el-form-item>
  305. </el-col>
  306. <el-col :span="12">
  307. <el-form-item :label="'数量'" >
  308. <el-input v-model="boxModelData.qty" type="number" ></el-input>
  309. </el-form-item>
  310. </el-col>
  311. <el-col :span="12" v-if="boxModelData.type===0">
  312. <el-form-item :label="'PO'" >
  313. <el-input v-model="boxModelData.poNo" ></el-input>
  314. </el-form-item>
  315. </el-col>
  316. <el-col :span="12">
  317. <el-form-item :label="'箱数'" >
  318. <el-input v-model="boxModelData.boxQty"></el-input>
  319. </el-form-item>
  320. </el-col>
  321. <el-col :span="12">
  322. <el-form-item :label="'ROLLS'" >
  323. <el-input v-model="boxModelData.rolls" ></el-input>
  324. </el-form-item>
  325. </el-col>
  326. <el-col :span="12">
  327. <el-form-item :label="'毛重'" >
  328. <el-input v-model="boxModelData.grossWeight"></el-input>
  329. </el-form-item>
  330. </el-col>
  331. <el-col :span="12">
  332. <el-form-item :label="'净重'" >
  333. <el-input v-model="boxModelData.netWeight" ></el-input>
  334. </el-form-item>
  335. </el-col>
  336. </el-row>
  337. </el-form>
  338. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  339. <el-button type="primary" @click="saveBoxHeader()">保存</el-button>
  340. <el-button type="primary" @click="boxModelFlag=false">关闭</el-button>
  341. </el-footer>
  342. </el-dialog>
  343. <!-- 装箱新增/修改栈板 -->
  344. <el-dialog
  345. :title="palletModelData.addFlag===1 ? '修改栈板' : '手工装箱'"
  346. :close-on-click-modal="false"
  347. v-drag
  348. :visible.sync="palletModelFlag"
  349. width="780px"
  350. class="pallet-dialog">
  351. <!-- 区域 1箱信息 -->
  352. <div class="section section-header">
  353. <h4 class="section-title">箱信息</h4>
  354. <el-divider></el-divider>
  355. <el-form label-position="top" class="box-info-form">
  356. <el-row :gutter="20">
  357. <el-col :span="6">
  358. <el-form-item label="箱数">
  359. <el-input v-model="palletModelData.boxQty" type="number" placeholder="请输入箱数" @input="calculateWeightsByBoxQty"></el-input>
  360. </el-form-item>
  361. </el-col>
  362. <el-col :span="6">
  363. <el-form-item label="毛重">
  364. <el-input v-model="palletModelData.grossWeight" type="number" placeholder="自动计算" @input="onPalletGrossWeightChange"></el-input>
  365. </el-form-item>
  366. </el-col>
  367. <el-col :span="6">
  368. <el-form-item label="净重">
  369. <el-input v-model="palletModelData.netWeight" type="number" placeholder="自动计算" @input="onPalletNetWeightChange"></el-input>
  370. </el-form-item>
  371. </el-col>
  372. <el-col :span="6">
  373. <el-form-item label="总Rolls(箱明细无rolls才可修改)">
  374. <el-input
  375. v-model="palletModelData.rolls"
  376. type="number"
  377. placeholder="箱明细无rolls才可修改"
  378. :disabled="isTotalRollsDisabled"
  379. ></el-input>
  380. </el-form-item>
  381. </el-col>
  382. </el-row>
  383. </el-form>
  384. </div>
  385. <!-- 区域 2箱明细 -->
  386. <div class="section section-detail">
  387. <h4 class="section-title">箱明细</h4>
  388. <el-divider></el-divider>
  389. <div class="table-wrapper">
  390. <el-table
  391. ref="partTableRef"
  392. :data="dataList8"
  393. height="100%"
  394. stripe
  395. border
  396. class="zxClass"
  397. style="width: 100%;">
  398. <el-table-column prop="pn" label="PN" min-width="120"></el-table-column>
  399. <el-table-column prop="partDescription" label="Description" min-width="220"></el-table-column>
  400. <el-table-column prop="qty" label="原数量" align="right" width="70"></el-table-column>
  401. <el-table-column prop="surplusQty" label="可装箱数量" align="right" width="80"></el-table-column>
  402. <el-table-column label="装箱数量" align="center" width="80">
  403. <template slot-scope="scope">
  404. <el-input v-model.number="scope.row.useQty" type="number" :min="0" :max="999999" size="mini" @input="calculateRolls(scope.row)"></el-input>
  405. </template>
  406. </el-table-column>
  407. <el-table-column label="Rolls" align="center" width="80">
  408. <template slot-scope="scope">
  409. <el-input v-model="scope.row.rolls" type="number" :min="0" :max="999999" size="mini" placeholder="自动计算" @input="delayCalculateTotalRolls"></el-input>
  410. </template>
  411. </el-table-column>
  412. <el-table-column label="操作" align="center" width="70">
  413. <template slot-scope="scope">
  414. <a type="text" size="small" @click="fillUseQty(scope.row)">全数装箱</a>
  415. </template>
  416. </el-table-column>
  417. </el-table>
  418. </div>
  419. </div>
  420. <!-- 底部操作按钮 -->
  421. <div slot="footer" class="dialog-footer">
  422. <el-button type="primary" @click="savePalletHeader(0)">保存</el-button>
  423. <el-button type="primary" @click="savePalletHeader(1)">保存并关闭</el-button>
  424. <el-button @click="palletModelFlag=false">关闭</el-button>
  425. </div>
  426. </el-dialog>
  427. <el-dialog
  428. :title=" '修改栈板'"
  429. :close-on-click-modal="false"
  430. v-drag
  431. :visible.sync="palletEditFlag"
  432. width="240px"
  433. class="pallet-dialog">
  434. <div class="section section-header">
  435. <el-divider></el-divider>
  436. <el-form label-position="top" class="box-info-form">
  437. <el-row :gutter="20">
  438. <el-col :span="24">
  439. <el-form-item label="栈板高度(M)">
  440. <el-input v-model="palletModelData.height" type="number" placeholder="请输入栈板高度(M)"></el-input>
  441. </el-form-item>
  442. </el-col>
  443. <el-col :span="24">
  444. <el-form-item label="托数">
  445. <el-input v-model="palletModelData.palletQty" type="number" placeholder="请输入托数"></el-input>
  446. </el-form-item>
  447. </el-col>
  448. </el-row>
  449. </el-form>
  450. </div>
  451. <!-- 底部操作按钮 -->
  452. <div slot="footer" class="dialog-footer">
  453. <el-button type="primary" @click="updateCodelPalletHeaderPalletQty">保存</el-button>
  454. <el-button @click="palletEditFlag=false">关闭</el-button>
  455. </div>
  456. </el-dialog>
  457. <el-dialog title="一键装箱" :close-on-click-modal="false" v-drag :visible.sync="oneClickPackingModelFlag" width="170px">
  458. <el-form label-position="top" style="margin-left: 7px;margin-top: 10px;">
  459. <el-row :gutter="20">
  460. <el-col :span="12">
  461. <el-form-item :label="''" >
  462. <el-checkbox v-model="oneClickPackingModelData.boxRemnant">是否显示零数箱</el-checkbox>
  463. </el-form-item>
  464. </el-col>
  465. </el-row>
  466. </el-form>
  467. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  468. <el-button type="primary" @click="saveOneClickPacking()">保存</el-button>
  469. <el-button type="primary" @click="oneClickPackingModelFlag=false">关闭</el-button>
  470. </el-footer>
  471. </el-dialog>
  472. <!-- 合箱批量编辑弹出框 -->
  473. <el-dialog
  474. title="合箱批量编辑"
  475. :visible.sync="mergeBoxDialogVisible"
  476. width="60%"
  477. top="5vh"
  478. custom-class="batch-edit-dialog"
  479. :close-on-click-modal="false"
  480. @open="loadMergeBoxData">
  481. <div class="batch-edit-container" v-loading="mergeBoxLoading">
  482. <!-- 操作工具栏 -->
  483. <div class="merge-box-toolbar">
  484. <el-button
  485. type="primary"
  486. size="small"
  487. icon="el-icon-connection"
  488. :disabled="mergeBoxSelection.length < 2"
  489. @click="doMergeBoxes">
  490. 合并选中的箱 ({{ mergeBoxSelection.length }})
  491. </el-button>
  492. <el-button
  493. type="warning"
  494. size="small"
  495. icon="el-icon-refresh-left"
  496. :disabled="mergeBoxSelection.length === 0"
  497. @click="doUnmergeSelectedBoxes">
  498. 取消合并
  499. </el-button>
  500. <div class="merge-stats">
  501. <el-tag type="success" size="small">总箱数: {{ getUniqueBoxCount() }}</el-tag>
  502. <span v-if="mergeBoxModifiedCount > 0" class="modified-count">
  503. 已修改 <b>{{ mergeBoxModifiedCount }}</b>
  504. </span>
  505. </div>
  506. </div>
  507. <!-- 操作提示 -->
  508. <div class="batch-edit-tips">
  509. <el-alert
  510. type="info"
  511. :closable="false"
  512. show-icon>
  513. <template slot="title">
  514. <span>直接在表格中编辑数据选择多个箱点击"合并"按钮可以合箱选择已合并的箱点击"取消合并"可以拆分修改后点击"保存所有修改"按钮提交</span>
  515. </template>
  516. </el-alert>
  517. </div>
  518. <!-- 行合并表格 -->
  519. <el-table
  520. ref="mergeBoxTable"
  521. :data="mergeBoxTableData"
  522. :span-method="mergeBoxSpanMethod"
  523. border class="zxClass"
  524. size="small"
  525. height="50vh"
  526. style="width: 100%"
  527. @selection-change="handleMergeBoxSelectionChange"
  528. :row-class-name="getMergeBoxRowClassName"
  529. :header-cell-style="{background:'#f5f7fa', color:'#606266', fontWeight:'600'}">
  530. <!-- 复选框列 - 只在第一行显示 -->
  531. <el-table-column
  532. type="selection"
  533. width="55"
  534. align="center"
  535. :selectable="row => row._isFirstRowOfBox">
  536. </el-table-column>
  537. <!-- Box信息列会合并 -->
  538. <el-table-column label="序号" prop="item_no" width="60" align="center">
  539. <template slot-scope="scope">
  540. <span class="box-info-cell">{{ scope.row.item_no }}</span>
  541. </template>
  542. </el-table-column>
  543. <el-table-column label="箱数" prop="box_qty" width="80" align="center">
  544. <template slot-scope="scope">
  545. <el-input
  546. v-model="scope.row.box_qty"
  547. size="mini"
  548. type="number"
  549. :class="{'modified-input': isBoxFieldModified(scope.row, 'box_qty')}"
  550. @input="onMergeBoxQtyInput(scope.row)"
  551. @change="onMergeBoxFieldChange(scope.row, 'box_qty')">
  552. </el-input>
  553. </template>
  554. </el-table-column>
  555. <el-table-column label="毛重" prop="grossWeight" width="100" align="center">
  556. <template slot-scope="scope">
  557. <el-input
  558. v-model="scope.row.grossWeight"
  559. size="mini"
  560. type="number"
  561. :class="{'modified-input': isBoxFieldModified(scope.row, 'grossWeight')}"
  562. @input="onMergeGrossWeightInput(scope.row)"
  563. @change="onMergeBoxFieldChange(scope.row, 'grossWeight')">
  564. </el-input>
  565. </template>
  566. </el-table-column>
  567. <el-table-column label="净重" prop="netWeight" width="100" align="center">
  568. <template slot-scope="scope">
  569. <el-input
  570. v-model="scope.row.netWeight"
  571. size="mini"
  572. type="number"
  573. :class="{'modified-input': isBoxFieldModified(scope.row, 'netWeight')}"
  574. @input="onMergeNetWeightInput(scope.row)"
  575. @change="onMergeBoxFieldChange(scope.row, 'netWeight')">
  576. </el-input>
  577. </template>
  578. </el-table-column>
  579. <el-table-column label="总Rolls" prop="rolls" width="100" align="center">
  580. <template slot-scope="scope">
  581. <el-input
  582. v-model="scope.row.rolls"
  583. size="mini"
  584. type="number"
  585. :disabled="hasDetailRolls(scope.row)"
  586. :placeholder="hasDetailRolls(scope.row) ? '自动计算' : '请输入'"
  587. :class="{'modified-input': isBoxFieldModified(scope.row, 'rolls')}"
  588. @change="onMergeBoxFieldChange(scope.row, 'rolls')">
  589. </el-input>
  590. </template>
  591. </el-table-column>
  592. <!-- 明细信息列不合并 -->
  593. <el-table-column label="PO" prop="poNo" min-width="120" align="center">
  594. <template slot-scope="scope">
  595. <span>{{ scope.row.poNo || '-' }}</span>
  596. </template>
  597. </el-table-column>
  598. <el-table-column label="PN" prop="pn" min-width="120" align="center">
  599. <template slot-scope="scope">
  600. <span>{{ scope.row.pn || '-' }}</span>
  601. </template>
  602. </el-table-column>
  603. <el-table-column label="数量" prop="qty" width="100" align="center">
  604. <template slot-scope="scope">
  605. <el-input
  606. v-model="scope.row.qty"
  607. size="mini"
  608. type="number"
  609. :class="{'modified-input': isDetailFieldModified(scope.row, 'qty')}"
  610. @input="onDetailQtyChange(scope.row)"
  611. @change="onMergeDetailFieldChange(scope.row, 'qty')">
  612. </el-input>
  613. </template>
  614. </el-table-column>
  615. <el-table-column label="Rolls" prop="detailRolls" width="80" align="center">
  616. <template slot-scope="scope">
  617. <el-input
  618. v-model="scope.row.detailRolls"
  619. size="mini"
  620. type="number"
  621. :class="{'modified-input': isDetailFieldModified(scope.row, 'detailRolls')}"
  622. @input="onDetailRollsInput(scope.row)"
  623. @change="onMergeDetailFieldChange(scope.row, 'detailRolls')">
  624. </el-input>
  625. </template>
  626. </el-table-column>
  627. </el-table>
  628. </div>
  629. <div slot="footer" class="dialog-footer">
  630. <el-button @click="mergeBoxDialogVisible = false">取消</el-button>
  631. <el-button
  632. type="primary"
  633. :loading="mergeBoxSaving"
  634. :disabled="getUniqueBoxCount() === 0"
  635. @click="saveMergeBoxEdit">
  636. 保存所有修改 ({{ getUniqueBoxCount() }} / {{ mergeBoxModifiedCount }}处修改)
  637. </el-button>
  638. </div>
  639. </el-dialog>
  640. <el-dialog :close-on-click-modal="false" v-drag :visible.sync="palletMaintenanceModelFlag" width="450px">
  641. <div slot="title" class="dialog-title">
  642. <span>栈板维护</span>
  643. <el-tooltip effect="dark" placement="top">
  644. <div slot="content">
  645. <div>栈板维护功能说明</div>
  646. <div> 系统会自动加载当前BU下的所有栈板</div>
  647. <div> 栈板高度单位为米(M)请输入准确数值</div>
  648. <div> 只有托数大于0的栈板记录才会被保存</div>
  649. </div>
  650. <i class="el-icon-question" style="color: #17b3a3; margin-left: 8px; cursor: pointer; font-size: 16px;"></i>
  651. </el-tooltip>
  652. </div>
  653. <!-- 栈板记录列表 -->
  654. <div style="margin: 15px 0;">
  655. <el-table :data="palletMaintenanceRecords" border style="width: 100%; margin-bottom: 15px;" class="zxClass"
  656. max-height="200" v-if="palletMaintenanceRecords.length > 0">
  657. <el-table-column label="栈板类型" min-width="100">
  658. <template slot-scope="scope">
  659. <el-input v-model="scope.row.palletType" disabled style="width: 100%;"></el-input>
  660. </template>
  661. </el-table-column>
  662. <el-table-column width="120">
  663. <template slot="header">
  664. <span>栈板高度(M)</span>
  665. </template>
  666. <template slot-scope="scope">
  667. <el-input v-model="scope.row.height" type="text" placeholder="请输入高度" style="width: 100%;"></el-input>
  668. </template>
  669. </el-table-column>
  670. <el-table-column width="100">
  671. <template slot="header">
  672. <span>托数</span>
  673. </template>
  674. <template slot-scope="scope">
  675. <el-input v-model="scope.row.palletQty" type="text" placeholder="请输入托数" style="width: 100%;"></el-input>
  676. </template>
  677. </el-table-column>
  678. </el-table>
  679. <div v-if="palletMaintenanceRecords.length === 0" style="text-align: center; color: #999; padding: 20px; border: 1px dashed #ddd;">
  680. 正在加载栈板记录...
  681. </div>
  682. <!-- 操作提示 -->
  683. <div v-if="palletMaintenanceRecords.length > 0" style="margin-top: 10px; padding: 8px 12px; background: #f0f9ff; border: 1px solid #b3d8ff; border-radius: 4px; font-size: 12px; color: #409EFF;">
  684. <i class="el-icon-info" style="margin-right: 4px;"></i>
  685. <span>提示托数大于0的记录才会被保存</span>
  686. </div>
  687. </div>
  688. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  689. <el-button type="primary" :loading="saveLoading" :disabled="saveLoading" @click="savePalletMaintenance()">确定</el-button>
  690. <el-button type="primary" @click="palletMaintenanceModelFlag=false">关闭</el-button>
  691. </el-footer>
  692. </el-dialog>
  693. <el-dialog title="物料信息" @close="closePartDialog" @open="openPartDialog" :visible.sync="partFlag" width="559px" v-drag>
  694. <el-form inline="inline" label-position="top" :model="partData" style="margin-left: 7px;margin-top: -5px;">
  695. </el-form>
  696. <el-table
  697. :height="height + 110"
  698. :data="partList"
  699. stripe
  700. highlight-current-row
  701. border
  702. @row-dblclick="partRowDblclick"
  703. style="width: 100%;">
  704. <el-table-column
  705. prop="pn"
  706. header-align="center"
  707. align="center"
  708. label="物料编码">
  709. </el-table-column>
  710. <el-table-column
  711. prop="part_desc"
  712. header-align="center"
  713. align="center"
  714. label="物料名称">
  715. </el-table-column>
  716. </el-table>
  717. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  718. <el-button @click="partFlag = false">关闭</el-button>
  719. </el-footer>
  720. </el-dialog>
  721. <el-dialog title="栈板" @close="closePalletDialog" @open="openPalletDialog" :visible.sync="palletFlag" width="559px" v-drag>
  722. <el-form inline="inline" label-position="top" :model="palletData" style="margin-left: 7px;margin-top: -5px;">
  723. <el-form-item label="栈板类型">
  724. <el-input v-model="palletData.palletType" clearable style="width: 110px"></el-input>
  725. </el-form-item>
  726. <el-form-item label=" ">
  727. <el-button type="primary" style="padding: 3px 12px" @click="searchPalletList()">查询</el-button>
  728. </el-form-item>
  729. </el-form>
  730. <el-table
  731. :height="height + 110"
  732. :data="palletList"
  733. stripe
  734. highlight-current-row
  735. border
  736. @row-dblclick="palletRowDblclick"
  737. style="width: 100%;">
  738. <el-table-column
  739. prop="palletNo"
  740. header-align="center"
  741. align="center"
  742. width="120"
  743. label="栈板编码">
  744. </el-table-column>
  745. <el-table-column
  746. prop="palletType"
  747. header-align="center"
  748. align="center"
  749. label="栈板类型">
  750. </el-table-column>
  751. <el-table-column
  752. prop="applicationArea"
  753. header-align="center"
  754. align="center"
  755. label="应用环境">
  756. </el-table-column>
  757. <el-table-column
  758. prop="length"
  759. header-align="center"
  760. align="center"
  761. label="长(M)">
  762. </el-table-column>
  763. <el-table-column
  764. prop="width"
  765. header-align="center"
  766. align="center"
  767. label="宽(M)">
  768. </el-table-column>
  769. <el-table-column
  770. prop="height"
  771. header-align="center"
  772. align="center"
  773. label="栈板高(M)">
  774. </el-table-column>
  775. </el-table>
  776. <el-footer style="height:40px;margin-top: 10px;text-align:center">
  777. <el-button @click="palletFlag = false">关闭</el-button>
  778. </el-footer>
  779. </el-dialog>
  780. <!-- 导入 -->
  781. <pallet-upload-excel ref="palletUploadExcel" @refreshTable="searchPalletTable" v-drag></pallet-upload-excel>
  782. <!--列表的组件-->
  783. <Chooselist ref="baseList" @getBaseData="getBaseData"></Chooselist>
  784. </div>
  785. </template>
  786. <script>
  787. import Chooselist from '@/views/modules/common/Chooselist_eam'
  788. import {} from "@/api/sysLanguage.js"
  789. import palletUploadExcel from "./pallet_upload_excel.vue";
  790. import PackingDetailTab from "./components/PackingDetailTab.vue";
  791. import OssComponents from '../oss/ossComponents.vue'
  792. import {
  793. searchEcssCoDelNotifyHeaderForCK,
  794. searchEcssCoDelNotifyDetail,
  795. confirmEcssDel,
  796. updateEcssDel,
  797. cancerConfirmEcssDel,
  798. searchCoDelPalletDataNew,
  799. selectBoxList,
  800. searchEcssCoDelPalletHeaderData,
  801. searchEcssCoDelPalletDetailData,
  802. savePalletHeader,
  803. deletePalletHeader,
  804. savePalletDetail,
  805. deletePalletDetail,
  806. saveOneClickPacking,
  807. savePalletMaintenance,
  808. getNotifyPartDetail,
  809. searchPalletList,
  810. updateExportFlag,
  811. updateCodelPalletHeaderPalletQty,
  812. getPartPackageProperties,
  813. mergeBox
  814. }from "@/api/ecss/ecss.js"
  815. import {getBuList}from '@/api/factory/site.js'
  816. import excel from "@/utils/excel-util.js";
  817. import excelOpts from '@/utils/export-options.js'
  818. import ExportUtil from "@/utils/export";
  819. import { getTableUserListLanguage} from "@/api/table.js"
  820. import {getTableDefaultListLanguage} from "../../../api/table";
  821. export default {
  822. name: "null",
  823. components:{
  824. OssComponents,
  825. palletUploadExcel,
  826. Chooselist,
  827. PackingDetailTab,
  828. },
  829. data() {
  830. return {
  831. multipleSelection: [],
  832. palletFlag:false,
  833. palletList:[],
  834. palletData:{},
  835. partFlag:false,
  836. partData:{},
  837. partList:[],
  838. pageIndex: 1,
  839. pageSize: 100,
  840. totalPage: 0,
  841. // 选中行持久化相关
  842. selectedRowKey: null, // 当前选中行的唯一标识
  843. height: 200,
  844. buList:[],
  845. dataList:[],
  846. dataList2:[],
  847. dataList3:[],
  848. dataList4:[],
  849. dataList5:[],
  850. dataList8:[],
  851. notifyDetailMap: new Map(),
  852. boxDetailData:{
  853. site:'',
  854. buNo:'',
  855. delNo:'',
  856. seqNo:'',
  857. },
  858. dataListLoading: false,
  859. boxDetailModelFlag: false,
  860. searchData: {
  861. page: 1,
  862. limit: 100,
  863. buNo:'',
  864. delNo:'',
  865. cmcInvoice:'',
  866. notifyStatus:'',
  867. startDate:'',
  868. endDate:'',
  869. exportFlag:'',
  870. username:this.$store.state.user.name,
  871. },
  872. oneClickPackingModelFlag:false,
  873. oneClickPackingModelData:{
  874. boxRemnant: false,
  875. },
  876. // 合箱批量编辑相关
  877. mergeBoxDialogVisible: false,
  878. mergeBoxLoading: false,
  879. mergeBoxSaving: false,
  880. mergeBoxTableData: [], // 扁平化的表格数据
  881. mergeBoxSelection: [], // 已选择的箱(用于合箱)
  882. mergeBoxOriginalData: {}, // 原始数据快照(用于对比是否修改)
  883. mergeBoxModifiedBoxes: {}, // 修改过的Box记录
  884. mergeBoxMergeHistory: [], // 合并历史记录(用于取消合并)
  885. mergeBoxModifiedDetails: {}, // 修改过的明细记录
  886. nextItemNo: 1, // 下一个序号
  887. // 栈板维护相关
  888. palletMaintenanceModelFlag: false,
  889. saveLoading: false,
  890. palletMaintenanceRecords: [],
  891. palletModelFlag:false,
  892. palletEditFlag:false,
  893. palletModelData:{
  894. addFlag:0,
  895. site:'',
  896. buNo:'',
  897. delNo:'',
  898. seqNo:'',
  899. palletNo:'',
  900. palletQty:'',
  901. length:'',
  902. width:'',
  903. height:'',
  904. boxQty:'',
  905. grossWeight:'',
  906. netWeight:'',
  907. palletRemark:'',
  908. rolls:'',
  909. },
  910. boxModelFlag:false,
  911. boxModelData:{
  912. addFlag:0,
  913. site:'',
  914. buNo:'',
  915. delNo:'',
  916. seqNo:'',
  917. itemNo:'',
  918. partNo:'',
  919. pn:'',
  920. qty:'',
  921. poNo:'',
  922. boxQty:'',
  923. rolls:'',
  924. },
  925. buttons:{
  926. search:'查询',
  927. },
  928. confirmModelFlag:false,
  929. updateModelFlag:false,
  930. confirmModel:{
  931. site:'',
  932. buDesc:'',
  933. cmcInvoice:'',
  934. delNo:'',
  935. readyDate:'',
  936. shippingMode:'',
  937. destination:'',
  938. notifyDate:'',
  939. actualNotifyDate:'',
  940. remark:'',
  941. },
  942. activeName:'detail',
  943. columnList1: [
  944. {
  945. userId: this.$store.state.user.name,
  946. functionId: 801002,
  947. serialNumber: '801002Table1BuDesc',
  948. tableId: "801002Table1",
  949. tableName: "关务系统发货通知单",
  950. columnProp: "buDesc",
  951. headerAlign: "center",
  952. align: "left",
  953. columnLabel: "BU",
  954. columnHidden: false,
  955. columnImage: false,
  956. columnSortable: false,
  957. sortLv: 0,
  958. status: true,
  959. fixed: '',
  960. columnWidth: 60
  961. },
  962. {
  963. userId: this.$store.state.user.name,
  964. functionId: 801002,
  965. serialNumber: '801002Table1CmcInvoice',
  966. tableId: "801002Table1",
  967. tableName: "关务系统发货通知单",
  968. columnProp: "cmcInvoice",
  969. headerAlign: "center",
  970. align: "left",
  971. columnLabel: "CMC Invoice",
  972. columnHidden: false,
  973. columnImage: false,
  974. columnSortable: false,
  975. sortLv: 0,
  976. status: true,
  977. fixed: '',
  978. columnWidth: 100
  979. },
  980. {
  981. userId: this.$store.state.user.name,
  982. functionId: 801002,
  983. serialNumber: '801002Table1DelNo',
  984. tableId: "801002Table1",
  985. tableName: "关务系统发货通知单",
  986. columnProp: "delNo",
  987. headerAlign: "center",
  988. align: "center",
  989. columnLabel: "发货通知单号",
  990. columnHidden: false,
  991. columnImage: false,
  992. columnSortable: false,
  993. sortLv: 0,
  994. status: true,
  995. fixed: '',
  996. columnWidth: 110
  997. },
  998. {
  999. userId: this.$store.state.user.name,
  1000. functionId: 801002,
  1001. serialNumber: '801002Table1ReadyDate',
  1002. tableId: "801002Table1",
  1003. tableName: "关务系统发货通知单",
  1004. columnProp: "readyDate",
  1005. headerAlign: "center",
  1006. align: "center",
  1007. columnLabel: "ReadyDate",
  1008. columnHidden: false,
  1009. columnImage: false,
  1010. columnSortable: false,
  1011. sortLv: 0,
  1012. status: true,
  1013. fixed: '',
  1014. columnWidth: 100
  1015. },
  1016. {
  1017. userId: this.$store.state.user.name,
  1018. functionId: 801002,
  1019. serialNumber: '801002Table1CustomerName',
  1020. tableId: "801002Table1",
  1021. tableName: "关务系统发货通知单",
  1022. columnProp: "customerName",
  1023. headerAlign: "center",
  1024. align: "left",
  1025. columnLabel: "客户名称",
  1026. columnHidden: false,
  1027. columnImage: false,
  1028. columnSortable: false,
  1029. sortLv: 0,
  1030. status: true,
  1031. fixed: '',
  1032. columnWidth: 220
  1033. },
  1034. {
  1035. userId: this.$store.state.user.name,
  1036. functionId: 801002,
  1037. serialNumber: '801002Table1ShippingMode',
  1038. tableId: "801002Table1",
  1039. tableName: "关务系统发货通知单",
  1040. columnProp: "shippingMode",
  1041. headerAlign: "center",
  1042. align: "left",
  1043. columnLabel: "ShippingMode",
  1044. columnHidden: false,
  1045. columnImage: false,
  1046. columnSortable: false,
  1047. sortLv: 0,
  1048. status: true,
  1049. fixed: '',
  1050. columnWidth: 100
  1051. },
  1052. {
  1053. userId: this.$store.state.user.name,
  1054. functionId: 801002,
  1055. serialNumber: '801002Table1Destination',
  1056. tableId: "801002Table1",
  1057. tableName: "关务系统发货通知单",
  1058. columnProp: "destination",
  1059. headerAlign: "center",
  1060. align: "left",
  1061. columnLabel: "Destination",
  1062. columnHidden: false,
  1063. columnImage: false,
  1064. columnSortable: false,
  1065. sortLv: 0,
  1066. status: true,
  1067. fixed: '',
  1068. columnWidth: 100
  1069. },
  1070. {
  1071. userId: this.$store.state.user.name,
  1072. functionId: 801002,
  1073. serialNumber: '801002Table1NotifyStatus',
  1074. tableId: "801002Table1",
  1075. tableName: "关务系统发货通知单",
  1076. columnProp: "notifyStatus",
  1077. headerAlign: "center",
  1078. align: "left",
  1079. columnLabel: "通知单状态",
  1080. columnHidden: false,
  1081. columnImage: false,
  1082. columnSortable: false,
  1083. sortLv: 0,
  1084. status: true,
  1085. fixed: '',
  1086. columnWidth: 100
  1087. },
  1088. {
  1089. userId: this.$store.state.user.name,
  1090. functionId: 801001,
  1091. serialNumber: '801001Table1NotifyStatus',
  1092. tableId: "801001Table1",
  1093. tableName: "关务系统发货通知单",
  1094. columnProp: "modifyLabel",
  1095. headerAlign: "center",
  1096. align: "left",
  1097. columnLabel: "改单",
  1098. columnHidden: false,
  1099. columnImage: false,
  1100. columnSortable: false,
  1101. sortLv: 0,
  1102. status: true,
  1103. fixed: '',
  1104. columnWidth: 60
  1105. },
  1106. {
  1107. userId: this.$store.state.user.name,
  1108. functionId: 801002,
  1109. serialNumber: '801002Table1ExportFlag',
  1110. tableId: "801002Table1",
  1111. tableName: "关务系统发货通知单",
  1112. columnProp: "exportFlag",
  1113. headerAlign: "center",
  1114. align: "center",
  1115. columnLabel: "是否导出",
  1116. columnHidden: false,
  1117. columnImage: false,
  1118. columnSortable: false,
  1119. sortLv: 0,
  1120. status: true,
  1121. fixed: '',
  1122. columnWidth: 80
  1123. },
  1124. {
  1125. userId: this.$store.state.user.name,
  1126. functionId: 801002,
  1127. serialNumber: '801002Table1NotifyDate',
  1128. tableId: "801002Table1",
  1129. tableName: "关务系统发货通知单",
  1130. columnProp: "notifyDate",
  1131. headerAlign: "center",
  1132. align: "center",
  1133. columnLabel: "预计发货日期",
  1134. columnHidden: false,
  1135. columnImage: false,
  1136. columnSortable: false,
  1137. sortLv: 0,
  1138. status: true,
  1139. fixed: '',
  1140. columnWidth: 120
  1141. },
  1142. {
  1143. userId: this.$store.state.user.name,
  1144. functionId: 801002,
  1145. serialNumber: '801002Table1ActualNotifyDate',
  1146. tableId: "801002Table1",
  1147. tableName: "关务系统发货通知单",
  1148. columnProp: "actualNotifyDate",
  1149. headerAlign: "center",
  1150. align: "center",
  1151. columnLabel: "实际发货日期",
  1152. columnHidden: false,
  1153. columnImage: false,
  1154. columnSortable: false,
  1155. sortLv: 0,
  1156. status: true,
  1157. fixed: '',
  1158. columnWidth: 120
  1159. },
  1160. {
  1161. userId: this.$store.state.user.name,
  1162. functionId: 801002,
  1163. serialNumber: '801002Table1ErpDelNo',
  1164. tableId: "801002Table1",
  1165. tableName: "关务系统发货通知单",
  1166. columnProp: "walMartOrderFlag",
  1167. headerAlign: "center",
  1168. align: "left",
  1169. columnLabel: "沃尔玛订单",
  1170. columnHidden: false,
  1171. columnImage: false,
  1172. columnSortable: false,
  1173. sortLv: 0,
  1174. status: true,
  1175. fixed: '',
  1176. columnWidth: 100
  1177. },
  1178. {
  1179. userId: this.$store.state.user.name,
  1180. functionId: 801002,
  1181. serialNumber: '801002Table1BoxSizeFlag',
  1182. tableId: "801002Table1",
  1183. tableName: "关务系统发货通知单",
  1184. columnProp: "boxSizeFlag",
  1185. headerAlign: "center",
  1186. align: "left",
  1187. columnLabel: "维护箱尺寸",
  1188. columnHidden: false,
  1189. columnImage: false,
  1190. columnSortable: false,
  1191. sortLv: 0,
  1192. status: true,
  1193. fixed: '',
  1194. columnWidth: 100
  1195. },
  1196. {
  1197. userId: this.$store.state.user.name,
  1198. functionId: 801002,
  1199. serialNumber: '801002Table1CreateBy',
  1200. tableId: "801002Table1",
  1201. tableName: "关务系统发货通知单",
  1202. columnProp: "createBy",
  1203. headerAlign: "center",
  1204. align: "left",
  1205. columnLabel: "创建人",
  1206. columnHidden: false,
  1207. columnImage: false,
  1208. columnSortable: false,
  1209. sortLv: 0,
  1210. status: true,
  1211. fixed: '',
  1212. columnWidth: 80
  1213. },
  1214. {
  1215. userId: this.$store.state.user.name,
  1216. functionId: 801002,
  1217. serialNumber: '801002Table1CreateDate',
  1218. tableId: "801002Table1",
  1219. tableName: "关务系统发货通知单",
  1220. columnProp: "createDate",
  1221. headerAlign: "center",
  1222. align: "center",
  1223. columnLabel: "创建时间",
  1224. columnHidden: false,
  1225. columnImage: false,
  1226. columnSortable: false,
  1227. sortLv: 0,
  1228. status: true,
  1229. fixed: '',
  1230. columnWidth: 130
  1231. },
  1232. {
  1233. userId: this.$store.state.user.name,
  1234. functionId: 801002,
  1235. serialNumber: '801002Table1UpdateBy',
  1236. tableId: "801002Table1",
  1237. tableName: "关务系统发货通知单",
  1238. columnProp: "updateBy",
  1239. headerAlign: "center",
  1240. align: "left",
  1241. columnLabel: "修改人",
  1242. columnHidden: false,
  1243. columnImage: false,
  1244. columnSortable: false,
  1245. sortLv: 0,
  1246. status: true,
  1247. fixed: '',
  1248. columnWidth: 80
  1249. },
  1250. {
  1251. userId: this.$store.state.user.name,
  1252. functionId: 801002,
  1253. serialNumber: '801002Table1UpdateDate',
  1254. tableId: "801002Table1",
  1255. tableName: "关务系统发货通知单",
  1256. columnProp: "updateDate",
  1257. headerAlign: "center",
  1258. align: "center",
  1259. columnLabel: "修改时间",
  1260. columnHidden: false,
  1261. columnImage: false,
  1262. columnSortable: false,
  1263. sortLv: 0,
  1264. status: true,
  1265. fixed: '',
  1266. columnWidth: 130
  1267. },
  1268. {
  1269. userId: this.$store.state.user.name,
  1270. functionId: 801002,
  1271. serialNumber: '801002Table1Remark',
  1272. tableId: "801002Table1",
  1273. tableName: "关务系统发货通知单",
  1274. columnProp: "remark",
  1275. headerAlign: "center",
  1276. align: "left",
  1277. columnLabel: "Remark",
  1278. columnHidden: false,
  1279. columnImage: false,
  1280. columnSortable: false,
  1281. sortLv: 0,
  1282. status: true,
  1283. fixed: '',
  1284. columnWidth: 300
  1285. },
  1286. ],
  1287. columnList2: [
  1288. {
  1289. userId: this.$store.state.user.name,
  1290. functionId: 801002,
  1291. serialNumber: '801002Table2ItemNo',
  1292. tableId: "801002Table2",
  1293. tableName: "关务系统发货通知单明细",
  1294. columnProp: "itemNo",
  1295. headerAlign: "center",
  1296. align: "left",
  1297. columnLabel: "行号",
  1298. columnHidden: false,
  1299. columnImage: false,
  1300. columnSortable: false,
  1301. sortLv: 0,
  1302. status: true,
  1303. fixed: '',
  1304. columnWidth: 80
  1305. },
  1306. {
  1307. userId: this.$store.state.user.name,
  1308. functionId: 801002,
  1309. serialNumber: '801002Table2PartNo',
  1310. tableId: "801002Table2",
  1311. tableName: "关务系统发货通知单明细",
  1312. columnProp: "pn",
  1313. headerAlign: "center",
  1314. align: "left",
  1315. columnLabel: "PN",
  1316. columnHidden: false,
  1317. columnImage: false,
  1318. columnSortable: false,
  1319. sortLv: 0,
  1320. status: true,
  1321. fixed: '',
  1322. columnWidth: 100
  1323. },
  1324. {
  1325. userId: this.$store.state.user.name,
  1326. functionId: 801002,
  1327. serialNumber: '801002Table2PartDescription',
  1328. tableId: "801002Table2",
  1329. tableName: "关务系统发货通知单明细",
  1330. columnProp: "partDescription",
  1331. headerAlign: "center",
  1332. align: "left",
  1333. columnLabel: "Description",
  1334. columnHidden: false,
  1335. columnImage: false,
  1336. columnSortable: false,
  1337. sortLv: 0,
  1338. status: true,
  1339. fixed: '',
  1340. columnWidth: 300
  1341. },
  1342. {
  1343. userId: this.$store.state.user.name,
  1344. functionId: 801002,
  1345. serialNumber: '801002Table2Qty',
  1346. tableId: "801002Table2",
  1347. tableName: "关务系统发货通知单明细",
  1348. columnProp: "qty",
  1349. headerAlign: "center",
  1350. align: "right",
  1351. columnLabel: "Qty (pcs)",
  1352. columnHidden: false,
  1353. columnImage: false,
  1354. columnSortable: false,
  1355. sortLv: 0,
  1356. status: true,
  1357. fixed: '',
  1358. columnWidth: 100
  1359. },
  1360. {
  1361. userId: this.$store.state.user.name,
  1362. functionId: 801002,
  1363. serialNumber: '801002Table2SalesOrder',
  1364. tableId: "801002Table2",
  1365. tableName: "关务系统发货通知单明细",
  1366. columnProp: "salesOrder",
  1367. headerAlign: "center",
  1368. align: "left",
  1369. columnLabel: "销售订单号",
  1370. columnHidden: false,
  1371. columnImage: false,
  1372. columnSortable: false,
  1373. sortLv: 0,
  1374. status: true,
  1375. fixed: '',
  1376. columnWidth: 100
  1377. },
  1378. {
  1379. userId: this.$store.state.user.name,
  1380. functionId: 801002,
  1381. serialNumber: '801002Table2CustomerPO',
  1382. tableId: "801002Table2",
  1383. tableName: "关务系统发货通知单明细",
  1384. columnProp: "customerPO",
  1385. headerAlign: "center",
  1386. align: "left",
  1387. columnLabel: "客户采购单号",
  1388. columnHidden: false,
  1389. columnImage: false,
  1390. columnSortable: false,
  1391. sortLv: 0,
  1392. status: true,
  1393. fixed: '',
  1394. columnWidth: 100
  1395. },
  1396. {
  1397. userId: this.$store.state.user.name,
  1398. functionId: 801002,
  1399. serialNumber: '801002Table2Version',
  1400. tableId: "801002Table2",
  1401. tableName: "关务系统发货通知单明细",
  1402. columnProp: "version",
  1403. headerAlign: "center",
  1404. align: "left",
  1405. columnLabel: "Version",
  1406. columnHidden: false,
  1407. columnImage: false,
  1408. columnSortable: false,
  1409. sortLv: 0,
  1410. status: true,
  1411. fixed: '',
  1412. columnWidth: 100
  1413. },
  1414. {
  1415. userId: this.$store.state.user.name,
  1416. functionId: 801002,
  1417. serialNumber: '801002Table2Status',
  1418. tableId: "801002Table2",
  1419. tableName: "关务系统发货通知单明细",
  1420. columnProp: "status",
  1421. headerAlign: "center",
  1422. align: "left",
  1423. columnLabel: "Status",
  1424. columnHidden: false,
  1425. columnImage: false,
  1426. columnSortable: false,
  1427. sortLv: 0,
  1428. status: true,
  1429. fixed: '',
  1430. columnWidth: 100
  1431. },
  1432. {
  1433. userId: this.$store.state.user.name,
  1434. functionId: 801002,
  1435. serialNumber: '801002Table2Family',
  1436. tableId: "801002Table2",
  1437. tableName: "关务系统发货通知单明细",
  1438. columnProp: "family",
  1439. headerAlign: "center",
  1440. align: "left",
  1441. columnLabel: "Family",
  1442. columnHidden: false,
  1443. columnImage: false,
  1444. columnSortable: false,
  1445. sortLv: 0,
  1446. status: true,
  1447. fixed: '',
  1448. columnWidth: 100
  1449. },
  1450. {
  1451. userId: this.$store.state.user.name,
  1452. functionId: 801002,
  1453. serialNumber: '801002Table2Lt',
  1454. tableId: "801002Table2",
  1455. tableName: "关务系统发货通知单明细",
  1456. columnProp: "lt",
  1457. headerAlign: "center",
  1458. align: "right",
  1459. columnLabel: "LT (wks)",
  1460. columnHidden: false,
  1461. columnImage: false,
  1462. columnSortable: false,
  1463. sortLv: 0,
  1464. status: true,
  1465. fixed: '',
  1466. columnWidth: 100
  1467. },
  1468. {
  1469. userId: this.$store.state.user.name,
  1470. functionId: 801002,
  1471. serialNumber: '801002Table2CmcComment',
  1472. tableId: "801002Table2",
  1473. tableName: "关务系统发货通知单明细",
  1474. columnProp: "cmcComment",
  1475. headerAlign: "center",
  1476. align: "left",
  1477. columnLabel: "CMC Comment",
  1478. columnHidden: false,
  1479. columnImage: false,
  1480. columnSortable: false,
  1481. sortLv: 0,
  1482. status: true,
  1483. fixed: '',
  1484. columnWidth: 100
  1485. },
  1486. {
  1487. userId: this.$store.state.user.name,
  1488. functionId: 801002,
  1489. serialNumber: '801002Table2SaleType',
  1490. tableId: "801002Table2",
  1491. tableName: "关务系统发货通知单明细",
  1492. columnProp: "saleType",
  1493. headerAlign: "center",
  1494. align: "left",
  1495. columnLabel: "内外销方式",
  1496. columnHidden: false,
  1497. columnImage: false,
  1498. columnSortable: false,
  1499. sortLv: 0,
  1500. status: true,
  1501. fixed: '',
  1502. columnWidth: 100
  1503. },
  1504. {
  1505. userId: this.$store.state.user.name,
  1506. functionId: 801002,
  1507. serialNumber: '801002Table2AwbBl',
  1508. tableId: "801002Table2",
  1509. tableName: "关务系统发货通知单明细",
  1510. columnProp: "awbBl",
  1511. headerAlign: "center",
  1512. align: "left",
  1513. columnLabel: "AWB/ BL#",
  1514. columnHidden: false,
  1515. columnImage: false,
  1516. columnSortable: false,
  1517. sortLv: 0,
  1518. status: true,
  1519. fixed: '',
  1520. columnWidth: 100
  1521. },
  1522. {
  1523. userId: this.$store.state.user.name,
  1524. functionId: 801002,
  1525. serialNumber: '801002Table2ShippingNumber',
  1526. tableId: "801002Table2",
  1527. tableName: "关务系统发货通知单明细",
  1528. columnProp: "shippingNumber",
  1529. headerAlign: "center",
  1530. align: "left",
  1531. columnLabel: "ShippingNumber",
  1532. columnHidden: false,
  1533. columnImage: false,
  1534. columnSortable: false,
  1535. sortLv: 0,
  1536. status: true,
  1537. fixed: '',
  1538. columnWidth: 100
  1539. },
  1540. {
  1541. userId: this.$store.state.user.name,
  1542. functionId: 801002,
  1543. serialNumber: '801002Table2ForwarderInfo',
  1544. tableId: "801002Table2",
  1545. tableName: "关务系统发货通知单明细",
  1546. columnProp: "forwarderInfo",
  1547. headerAlign: "center",
  1548. align: "left",
  1549. columnLabel: "Forwarder Info",
  1550. columnHidden: false,
  1551. columnImage: false,
  1552. columnSortable: false,
  1553. sortLv: 0,
  1554. status: true,
  1555. fixed: '',
  1556. columnWidth: 100
  1557. },
  1558. {
  1559. userId: this.$store.state.user.name,
  1560. functionId: 801002,
  1561. serialNumber: '801002Table2Currency',
  1562. tableId: "801002Table2",
  1563. tableName: "关务系统发货通知单明细",
  1564. columnProp: "currency",
  1565. headerAlign: "center",
  1566. align: "left",
  1567. columnLabel: "Currency",
  1568. columnHidden: false,
  1569. columnImage: false,
  1570. columnSortable: false,
  1571. sortLv: 0,
  1572. status: true,
  1573. fixed: '',
  1574. columnWidth: 100
  1575. },
  1576. {
  1577. userId: this.$store.state.user.name,
  1578. functionId: 801002,
  1579. serialNumber: '801002Table2Tp',
  1580. tableId: "801002Table2",
  1581. tableName: "关务系统发货通知单明细",
  1582. columnProp: "tp",
  1583. headerAlign: "center",
  1584. align: "right",
  1585. columnLabel: "TP",
  1586. columnHidden: false,
  1587. columnImage: false,
  1588. columnSortable: false,
  1589. sortLv: 0,
  1590. status: true,
  1591. fixed: '',
  1592. columnWidth: 80
  1593. },
  1594. {
  1595. userId: this.$store.state.user.name,
  1596. functionId: 801002,
  1597. serialNumber: '801002Table2TtlAmount',
  1598. tableId: "801002Table2",
  1599. tableName: "关务系统发货通知单明细",
  1600. columnProp: "ttlAmount",
  1601. headerAlign: "center",
  1602. align: "right",
  1603. columnLabel: "TTL Amount",
  1604. columnHidden: false,
  1605. columnImage: false,
  1606. columnSortable: false,
  1607. sortLv: 0,
  1608. status: true,
  1609. fixed: '',
  1610. columnWidth: 80
  1611. },
  1612. {
  1613. userId: this.$store.state.user.name,
  1614. functionId: 801001,
  1615. serialNumber: '801001Table2Remark',
  1616. tableId: "801001Table2",
  1617. tableName: "关务系统发货通知单明细",
  1618. columnProp: "vat",
  1619. headerAlign: "center",
  1620. align: "right",
  1621. columnLabel: "VAT",
  1622. columnHidden: false,
  1623. columnImage: false,
  1624. columnSortable: false,
  1625. sortLv: 0,
  1626. status: true,
  1627. fixed: '',
  1628. columnWidth: 100
  1629. },
  1630. {
  1631. userId: this.$store.state.user.name,
  1632. functionId: 801002,
  1633. serialNumber: '801002Table2SumPrice',
  1634. tableId: "801002Table2",
  1635. tableName: "关务系统发货通知单明细",
  1636. columnProp: "sumPrice",
  1637. headerAlign: "center",
  1638. align: "right",
  1639. columnLabel: "价税合计",
  1640. columnHidden: false,
  1641. columnImage: false,
  1642. columnSortable: false,
  1643. sortLv: 0,
  1644. status: true,
  1645. fixed: '',
  1646. columnWidth: 80
  1647. },
  1648. {
  1649. userId: this.$store.state.user.name,
  1650. functionId: 801002,
  1651. serialNumber: '801002Table2So',
  1652. tableId: "801002Table2",
  1653. tableName: "关务系统发货通知单明细",
  1654. columnProp: "so",
  1655. headerAlign: "center",
  1656. align: "left",
  1657. columnLabel: "SO",
  1658. columnHidden: false,
  1659. columnImage: false,
  1660. columnSortable: false,
  1661. sortLv: 0,
  1662. status: true,
  1663. fixed: '',
  1664. columnWidth: 100
  1665. },
  1666. {
  1667. userId: this.$store.state.user.name,
  1668. functionId: 801002,
  1669. serialNumber: '801002Table2Upc',
  1670. tableId: "801002Table2",
  1671. tableName: "关务系统发货通知单明细",
  1672. columnProp: "upc",
  1673. headerAlign: "center",
  1674. align: "left",
  1675. columnLabel: "UPC",
  1676. columnHidden: false,
  1677. columnImage: false,
  1678. columnSortable: false,
  1679. sortLv: 0,
  1680. status: true,
  1681. fixed: '',
  1682. columnWidth: 100
  1683. },
  1684. {
  1685. userId: this.$store.state.user.name,
  1686. functionId: 801002,
  1687. serialNumber: '801002Table2Remark',
  1688. tableId: "801002Table2",
  1689. tableName: "关务系统发货通知单明细",
  1690. columnProp: "remark",
  1691. headerAlign: "center",
  1692. align: "left",
  1693. columnLabel: "Remark",
  1694. columnHidden: false,
  1695. columnImage: false,
  1696. columnSortable: false,
  1697. sortLv: 0,
  1698. status: true,
  1699. fixed: '',
  1700. columnWidth: 300
  1701. },
  1702. {
  1703. userId: this.$store.state.user.name,
  1704. functionId: 801001,
  1705. serialNumber: '801001Table2Remark',
  1706. tableId: "801001Table2",
  1707. tableName: "关务系统发货通知单明细",
  1708. columnProp: "roll",
  1709. headerAlign: "center",
  1710. align: "right",
  1711. columnLabel: "Roll",
  1712. columnHidden: false,
  1713. columnImage: false,
  1714. columnSortable: false,
  1715. sortLv: 0,
  1716. status: true,
  1717. fixed: '',
  1718. columnWidth: 100
  1719. },
  1720. {
  1721. userId: this.$store.state.user.name,
  1722. functionId: 801001,
  1723. serialNumber: '801001Table2Remark',
  1724. tableId: "801001Table2",
  1725. tableName: "关务系统发货通知单明细",
  1726. columnProp: "carton",
  1727. headerAlign: "center",
  1728. align: "right",
  1729. columnLabel: "Carton",
  1730. columnHidden: false,
  1731. columnImage: false,
  1732. columnSortable: false,
  1733. sortLv: 0,
  1734. status: true,
  1735. fixed: '',
  1736. columnWidth: 100
  1737. },
  1738. {
  1739. userId: this.$store.state.user.name,
  1740. functionId: 801001,
  1741. serialNumber: '801001Table2Remark',
  1742. tableId: "801001Table2",
  1743. tableName: "关务系统发货通知单明细",
  1744. columnProp: "qtyRoll",
  1745. headerAlign: "center",
  1746. align: "right",
  1747. columnLabel: "qty/roll",
  1748. columnHidden: false,
  1749. columnImage: false,
  1750. columnSortable: false,
  1751. sortLv: 0,
  1752. status: true,
  1753. fixed: '',
  1754. columnWidth: 100
  1755. },
  1756. {
  1757. userId: this.$store.state.user.name,
  1758. functionId: 801001,
  1759. serialNumber: '801001Table2Remark',
  1760. tableId: "801001Table2",
  1761. tableName: "关务系统发货通知单明细",
  1762. columnProp: "qtyBox",
  1763. headerAlign: "center",
  1764. align: "right",
  1765. columnLabel: "qty/box",
  1766. columnHidden: false,
  1767. columnImage: false,
  1768. columnSortable: false,
  1769. sortLv: 0,
  1770. status: true,
  1771. fixed: '',
  1772. columnWidth: 100
  1773. },
  1774. ],
  1775. columnList3:[
  1776. {
  1777. userId: this.$store.state.user.name,
  1778. functionId: 801002,
  1779. serialNumber: '801002Table3ItemNo',
  1780. tableId: "801002Table3",
  1781. tableName: "装箱明细",
  1782. columnProp: "itemNo",
  1783. headerAlign: "center",
  1784. align: "right",
  1785. columnLabel: "序号",
  1786. columnHidden: false,
  1787. columnImage: false,
  1788. columnSortable: false,
  1789. sortLv: 0,
  1790. status: true,
  1791. fixed: '',
  1792. columnWidth: 40
  1793. },
  1794. {
  1795. userId: this.$store.state.user.name,
  1796. functionId: 801002,
  1797. serialNumber: '801002Table3PoNo',
  1798. tableId: "801002Table3",
  1799. tableName: "装箱明细",
  1800. columnProp: "poNo",
  1801. headerAlign: "center",
  1802. align: "left",
  1803. columnLabel: "PO",
  1804. columnHidden: false,
  1805. columnImage: false,
  1806. columnSortable: false,
  1807. sortLv: 0,
  1808. status: true,
  1809. fixed: '',
  1810. columnWidth: 100
  1811. },
  1812. {
  1813. userId: this.$store.state.user.name,
  1814. functionId: 801002,
  1815. serialNumber: '801002Table3PN',
  1816. tableId: "801002Table3",
  1817. tableName: "装箱明细",
  1818. columnProp: "pn",
  1819. headerAlign: "center",
  1820. align: "left",
  1821. columnLabel: "PN",
  1822. columnHidden: false,
  1823. columnImage: false,
  1824. columnSortable: false,
  1825. sortLv: 0,
  1826. status: true,
  1827. fixed: '',
  1828. columnWidth: 100
  1829. },
  1830. {
  1831. userId: this.$store.state.user.name,
  1832. functionId: 801002,
  1833. serialNumber: '801002Table3Qty',
  1834. tableId: "801002Table3",
  1835. tableName: "装箱明细",
  1836. columnProp: "qty",
  1837. headerAlign: "center",
  1838. align: "right",
  1839. columnLabel: "数量",
  1840. columnHidden: false,
  1841. columnImage: false,
  1842. columnSortable: false,
  1843. sortLv: 0,
  1844. status: true,
  1845. fixed: '',
  1846. columnWidth: 50
  1847. },
  1848. {
  1849. userId: this.$store.state.user.name,
  1850. functionId: 801002,
  1851. serialNumber: '801002Table3Rolls',
  1852. tableId: "801002Table3",
  1853. tableName: "装箱明细",
  1854. columnProp: "rolls",
  1855. headerAlign: "center",
  1856. align: "right",
  1857. columnLabel: "Rolls",
  1858. columnHidden: false,
  1859. columnImage: false,
  1860. columnSortable: false,
  1861. sortLv: 0,
  1862. status: true,
  1863. fixed: '',
  1864. columnWidth: 50
  1865. },
  1866. ],
  1867. columnList4:[
  1868. {
  1869. userId: this.$store.state.user.name,
  1870. functionId: 801002,
  1871. serialNumber: '801002Table4SeqNo',
  1872. tableId: "801002Table4",
  1873. tableName: "装箱栈板主表",
  1874. columnProp: "seqNo",
  1875. headerAlign: "center",
  1876. align: "right",
  1877. columnLabel: "序号",
  1878. columnHidden: false,
  1879. columnImage: false,
  1880. columnSortable: false,
  1881. sortLv: 0,
  1882. status: true,
  1883. fixed: '',
  1884. columnWidth: 40
  1885. },
  1886. {
  1887. userId: this.$store.state.user.name,
  1888. functionId: 801002,
  1889. serialNumber: '801002Table4PalletRemark',
  1890. tableId: "801002Table4",
  1891. tableName: "装箱栈板主表",
  1892. columnProp: "palletRemark",
  1893. headerAlign: "center",
  1894. align: "left",
  1895. columnLabel: "栈板码",
  1896. columnHidden: false,
  1897. columnImage: false,
  1898. columnSortable: false,
  1899. sortLv: 0,
  1900. status: true,
  1901. fixed: '',
  1902. columnWidth: 60
  1903. },
  1904. {
  1905. userId: this.$store.state.user.name,
  1906. functionId: 801002,
  1907. serialNumber: '801002Table4PalletQty',
  1908. tableId: "801002Table4",
  1909. tableName: "装箱栈板主表",
  1910. columnProp: "palletQty",
  1911. headerAlign: "center",
  1912. align: "right",
  1913. columnLabel: "数量",
  1914. columnHidden: false,
  1915. columnImage: false,
  1916. columnSortable: false,
  1917. sortLv: 0,
  1918. status: true,
  1919. fixed: '',
  1920. columnWidth: 50
  1921. },
  1922. {
  1923. userId: this.$store.state.user.name,
  1924. functionId: 801002,
  1925. serialNumber: '801002Table4PalletQty',
  1926. tableId: "801002Table4",
  1927. tableName: "装箱栈板主表",
  1928. columnProp: "weight",
  1929. headerAlign: "center",
  1930. align: "right",
  1931. columnLabel: "重量(KG)",
  1932. columnHidden: false,
  1933. columnImage: false,
  1934. columnSortable: false,
  1935. sortLv: 0,
  1936. status: true,
  1937. fixed: '',
  1938. columnWidth: 50
  1939. },
  1940. {
  1941. userId: this.$store.state.user.name,
  1942. functionId: 801002,
  1943. serialNumber: '801002Table4Length',
  1944. tableId: "801002Table4",
  1945. tableName: "装箱栈板主表",
  1946. columnProp: "length",
  1947. headerAlign: "center",
  1948. align: "right",
  1949. columnLabel: "长(M)",
  1950. columnHidden: false,
  1951. columnImage: false,
  1952. columnSortable: false,
  1953. sortLv: 0,
  1954. status: true,
  1955. fixed: '',
  1956. columnWidth: 50
  1957. },
  1958. {
  1959. userId: this.$store.state.user.name,
  1960. functionId: 801002,
  1961. serialNumber: '801002Table4Width',
  1962. tableId: "801002Table4",
  1963. tableName: "装箱栈板主表",
  1964. columnProp: "width",
  1965. headerAlign: "center",
  1966. align: "right",
  1967. columnLabel: "宽(M)",
  1968. columnHidden: false,
  1969. columnImage: false,
  1970. columnSortable: false,
  1971. sortLv: 0,
  1972. status: true,
  1973. fixed: '',
  1974. columnWidth: 50
  1975. },
  1976. {
  1977. userId: this.$store.state.user.name,
  1978. functionId: 801002,
  1979. serialNumber: '801002Table4Height',
  1980. tableId: "801002Table4",
  1981. tableName: "装箱栈板主表",
  1982. columnProp: "height",
  1983. headerAlign: "center",
  1984. align: "right",
  1985. columnLabel: "高(M)",
  1986. columnHidden: false,
  1987. columnImage: false,
  1988. columnSortable: false,
  1989. sortLv: 0,
  1990. status: true,
  1991. fixed: '',
  1992. columnWidth: 50
  1993. },
  1994. ],
  1995. columnList5:[
  1996. {
  1997. userId: this.$store.state.user.name,
  1998. functionId: 801002,
  1999. serialNumber: '801002Table5PartNo',
  2000. tableId: "801002Table5",
  2001. tableName: "栈板装箱明细",
  2002. columnProp: "pn",
  2003. headerAlign: "center",
  2004. align: "left",
  2005. columnLabel: "物料编码",
  2006. columnHidden: false,
  2007. columnImage: false,
  2008. columnSortable: false,
  2009. sortLv: 0,
  2010. status: true,
  2011. fixed: '',
  2012. columnWidth: 70
  2013. },
  2014. {
  2015. userId: this.$store.state.user.name,
  2016. functionId: 801002,
  2017. serialNumber: '801002Table5Qty',
  2018. tableId: "801002Table5",
  2019. tableName: "栈板装箱明细",
  2020. columnProp: "qty",
  2021. headerAlign: "center",
  2022. align: "right",
  2023. columnLabel: "数量",
  2024. columnHidden: false,
  2025. columnImage: false,
  2026. columnSortable: false,
  2027. sortLv: 0,
  2028. status: true,
  2029. fixed: '',
  2030. columnWidth: 80
  2031. },
  2032. {
  2033. userId: this.$store.state.user.name,
  2034. functionId: 801002,
  2035. serialNumber: '801002Table5BoxQty',
  2036. tableId: "801002Table5",
  2037. tableName: "栈板装箱明细",
  2038. columnProp: "boxQty",
  2039. headerAlign: "center",
  2040. align: "right",
  2041. columnLabel: "箱数",
  2042. columnHidden: false,
  2043. columnImage: false,
  2044. columnSortable: false,
  2045. sortLv: 0,
  2046. status: true,
  2047. fixed: '',
  2048. columnWidth: 70
  2049. },
  2050. {
  2051. userId: this.$store.state.user.name,
  2052. functionId: 801002,
  2053. serialNumber: '801002Table5Rolls',
  2054. tableId: "801002Table5",
  2055. tableName: "栈板装箱明细",
  2056. columnProp: "rolls",
  2057. headerAlign: "center",
  2058. align: "right",
  2059. columnLabel: "Rolls",
  2060. columnHidden: false,
  2061. columnImage: false,
  2062. columnSortable: false,
  2063. sortLv: 0,
  2064. status: true,
  2065. fixed: '',
  2066. columnWidth: 70
  2067. },
  2068. ],
  2069. ossColumns:[
  2070. {
  2071. userId: this.$store.state.user.name,
  2072. functionId: 103001,
  2073. serialNumber: '103001Table2FileName',
  2074. tableId: '103001Table2',
  2075. tableName: '文件信息表',
  2076. columnProp: 'fileName',
  2077. headerAlign: 'center',
  2078. align: 'center',
  2079. columnLabel: '文件名称',
  2080. columnHidden: false,
  2081. columnImage: false,
  2082. columnSortable: false,
  2083. sortLv: 0,
  2084. status: true,
  2085. fixed: '',
  2086. columnWidth: 140
  2087. },
  2088. {
  2089. userId: this.$store.state.user.name,
  2090. functionId: 103001,
  2091. serialNumber: '103001Table2FileRemark',
  2092. tableId: '103001Table2',
  2093. tableName: '文件信息表',
  2094. columnProp: 'fileRemark',
  2095. headerAlign: 'center',
  2096. align: 'center',
  2097. columnLabel: '备注',
  2098. columnHidden: false,
  2099. columnImage: false,
  2100. columnSortable: false,
  2101. sortLv: 0,
  2102. status: true,
  2103. fixed: '',
  2104. columnWidth: 240
  2105. },
  2106. {
  2107. userId: this.$store.state.user.name,
  2108. functionId: 103001,
  2109. serialNumber: '103001Table2CreateDate',
  2110. tableId: '103001Table2',
  2111. tableName: '文件信息表',
  2112. columnProp: 'createDate',
  2113. headerAlign: 'center',
  2114. align: 'center',
  2115. columnLabel: '上传时间',
  2116. columnHidden: false,
  2117. columnImage: false,
  2118. columnSortable: false,
  2119. sortLv: 0,
  2120. status: true,
  2121. fixed: '',
  2122. columnWidth: 140
  2123. },
  2124. {
  2125. userId: this.$store.state.user.name,
  2126. functionId: 103001,
  2127. serialNumber: '103001Table2CreatedBy',
  2128. tableId: '103001Table2',
  2129. tableName: '文件信息表',
  2130. columnProp: 'createdBy',
  2131. headerAlign: 'center',
  2132. align: 'center',
  2133. columnLabel: '上传人',
  2134. columnHidden: false,
  2135. columnImage: false,
  2136. columnSortable: false,
  2137. sortLv: 0,
  2138. status: true,
  2139. fixed: '',
  2140. columnWidth: 140
  2141. }
  2142. ],
  2143. currentRow:{},
  2144. }
  2145. },
  2146. mounted() {
  2147. this.$nextTick(() => {
  2148. this.height = (window.innerHeight - 260)/2;
  2149. })
  2150. },
  2151. computed: {
  2152. /**
  2153. * 判断是否禁用总Rolls输入框
  2154. * 逻辑只有当所有明细的rolls都是空或0时才允许修改总rolls
  2155. * @returns {boolean} true=禁用false=启用
  2156. */
  2157. isTotalRollsDisabled() {
  2158. // 检查是否有任何明细的 rolls 不为空且大于 0
  2159. const hasValidRolls = this.dataList8.some(item => {
  2160. const rollsValue = parseFloat(item.rolls);
  2161. return !isNaN(rollsValue) && rollsValue > 0;
  2162. });
  2163. // 如果有任何明细有有效的rolls值,则禁用总rolls输入框
  2164. return hasValidRolls;
  2165. },
  2166. /**
  2167. * 合箱批量编辑修改数量
  2168. */
  2169. mergeBoxModifiedCount() {
  2170. return Object.keys(this.mergeBoxModifiedBoxes).length +
  2171. Object.keys(this.mergeBoxModifiedDetails).length;
  2172. }
  2173. },
  2174. methods: {
  2175. ensureActualNotifyDateColumn(columns) {
  2176. const sourceColumns = Array.isArray(columns) ? columns : [];
  2177. const hasActualNotifyDate = sourceColumns.some(item => item.columnProp === 'actualNotifyDate');
  2178. if (hasActualNotifyDate) {
  2179. return sourceColumns;
  2180. }
  2181. const referenceColumn = sourceColumns.find(item => item && item.tableId) || {};
  2182. const actualNotifyDateColumn = {
  2183. userId: this.$store.state.user.name,
  2184. functionId: this.$route.meta.menuId,
  2185. serialNumber: this.$route.meta.menuId + 'Table1ActualNotifyDate',
  2186. tableId: referenceColumn.tableId || (this.$route.meta.menuId + 'Table1'),
  2187. tableName: "关务系统发货通知单",
  2188. columnProp: "actualNotifyDate",
  2189. headerAlign: "center",
  2190. align: "center",
  2191. columnLabel: "实际发货日期",
  2192. columnHidden: false,
  2193. columnImage: false,
  2194. columnSortable: false,
  2195. sortLv: 0,
  2196. status: true,
  2197. fixed: '',
  2198. columnWidth: 120
  2199. };
  2200. const targetColumns = sourceColumns.slice();
  2201. const notifyDateIndex = targetColumns.findIndex(item => item.columnProp === 'notifyDate');
  2202. if (notifyDateIndex > -1) {
  2203. targetColumns.splice(notifyDateIndex + 1, 0, actualNotifyDateColumn);
  2204. } else {
  2205. targetColumns.push(actualNotifyDateColumn);
  2206. }
  2207. return targetColumns;
  2208. },
  2209. parseDateValue(dateValue) {
  2210. if (!dateValue) {
  2211. return null;
  2212. }
  2213. if (dateValue instanceof Date) {
  2214. if (isNaN(dateValue.getTime())) {
  2215. return null;
  2216. }
  2217. const date = new Date(dateValue.getTime());
  2218. date.setHours(0, 0, 0, 0);
  2219. return date;
  2220. }
  2221. if (typeof dateValue === 'string') {
  2222. const value = dateValue.trim();
  2223. if (!value) {
  2224. return null;
  2225. }
  2226. const datePart = value.split(' ')[0];
  2227. const parts = datePart.split('-');
  2228. if (parts.length === 3) {
  2229. const year = Number(parts[0]);
  2230. const month = Number(parts[1]);
  2231. const day = Number(parts[2]);
  2232. if (!Number.isNaN(year) && !Number.isNaN(month) && !Number.isNaN(day)) {
  2233. const date = new Date(year, month - 1, day);
  2234. date.setHours(0, 0, 0, 0);
  2235. return date;
  2236. }
  2237. }
  2238. const date = new Date(value);
  2239. if (!isNaN(date.getTime())) {
  2240. date.setHours(0, 0, 0, 0);
  2241. return date;
  2242. }
  2243. }
  2244. return null;
  2245. },
  2246. isActualNotifyDateEmpty(actualNotifyDate) {
  2247. return actualNotifyDate === null || actualNotifyDate === undefined || actualNotifyDate === '';
  2248. },
  2249. isDelayWarningRow(row) {
  2250. if (!row || !this.isActualNotifyDateEmpty(row.actualNotifyDate)) {
  2251. return false;
  2252. }
  2253. const notifyDate = this.parseDateValue(row.notifyDate);
  2254. if (!notifyDate) {
  2255. return false;
  2256. }
  2257. const deadline = new Date(notifyDate.getTime());
  2258. deadline.setDate(deadline.getDate() + 3);
  2259. const today = new Date();
  2260. today.setHours(0, 0, 0, 0);
  2261. return today.getTime() > deadline.getTime();
  2262. },
  2263. showDelayWarningTooltip(row, columnProp) {
  2264. return this.isDelayWarningRow(row) && (columnProp === 'cmcInvoice' || columnProp === 'notifyDate');
  2265. },
  2266. getDelayWarningTooltip(row) {
  2267. const notifyDate = row && row.notifyDate ? row.notifyDate : '预计发货日期';
  2268. return `预计发货日期${notifyDate}已超3天,且实际发货日期未维护,请及时补充。`;
  2269. },
  2270. // 动态列开始 获取 用户保存的 格式列
  2271. async getTableUserColumn (tableId, columnId) {
  2272. let queryTableUser = {
  2273. userId: this.$store.state.user.name,
  2274. functionId: this.$route.meta.menuId,
  2275. tableId: tableId,
  2276. status: true,
  2277. languageCode: this.$i18n.locale
  2278. }
  2279. await getTableUserListLanguage(queryTableUser).then(({data}) => {
  2280. if (data.rows.length > 0) {
  2281. //this.columnList1 = []
  2282. switch (columnId) {
  2283. case 1:
  2284. this.columnList1 = this.ensureActualNotifyDateColumn(data.rows)
  2285. break;
  2286. // case 2:
  2287. // this.columnDetailList = data.rows
  2288. // break;
  2289. // case 3:
  2290. // this.columnList2 = data.rows
  2291. // break;
  2292. // case 4:
  2293. // this.columnList3 = data.rows
  2294. // break;
  2295. }
  2296. } else {
  2297. this.getColumnList(tableId, columnId)
  2298. }
  2299. })
  2300. },
  2301. // 获取 tableDefault 列
  2302. async getColumnList (tableId, columnId) {
  2303. let queryTable = {
  2304. functionId: this.$route.meta.menuId,
  2305. tableId: tableId,
  2306. languageCode: this.$i18n.locale
  2307. }
  2308. await getTableDefaultListLanguage(queryTable).then(({data}) => {
  2309. if (!data.rows.length == 0) {
  2310. switch (columnId) {
  2311. case 1:
  2312. this.columnList1 = this.ensureActualNotifyDateColumn(data.rows)
  2313. break;
  2314. // case 2:
  2315. // this.columnDetailList = data.rows
  2316. // break;
  2317. // case 3:
  2318. // this.columnList2 = data.rows
  2319. // break;
  2320. // case 4:
  2321. // this.columnList3 = data.rows
  2322. // break;
  2323. }
  2324. } else {
  2325. // this.showDefault = true.
  2326. }
  2327. })
  2328. },
  2329. isPnDataIncomplete(row) {
  2330. const hasBoxrolls = row.boxrolls !== null && row.boxrolls !== undefined && row.boxrolls !== '';
  2331. const hasRollqty = row.rollqty !== null && row.rollqty !== undefined && row.rollqty !== '';
  2332. const hasBoxweight = row.boxweight !== null && row.boxweight !== undefined && row.boxweight !== '';
  2333. const packageNo = row.packageNo !== null && row.packageNo !== undefined && row.packageNo !== '';
  2334. return !hasBoxrolls || !hasRollqty || !hasBoxweight || !packageNo;
  2335. },
  2336. // 获取PN数据缺失的具体字段提示信息
  2337. getPnIncompleteTooltip(row) {
  2338. const missingFields = [];
  2339. // 检查每个字段是否缺失
  2340. if (!(row.rollqty !== null && row.rollqty !== undefined && row.rollqty !== '')) {
  2341. missingFields.push('每卷数量');
  2342. }
  2343. if (!(row.boxrolls !== null && row.boxrolls !== undefined && row.boxrolls !== '')) {
  2344. missingFields.push('每箱卷数');
  2345. }
  2346. if (!(row.boxweight !== null && row.boxweight !== undefined && row.boxweight !== '')) {
  2347. missingFields.push('箱重量');
  2348. }
  2349. if (!(row.packageNo !== null && row.packageNo !== undefined && row.packageNo !== '')) {
  2350. missingFields.push('箱类型');
  2351. }
  2352. // 根据缺失字段生成提示信息
  2353. if (missingFields.length > 0) {
  2354. return `基本信息(${missingFields.join('、')})未维护,点击跳转到维护页面`;
  2355. }
  2356. return '';
  2357. },
  2358. // 跳转到PN维护页面
  2359. navigateToPartHsCode(pn) {
  2360. if (!pn) {
  2361. this.$message.warning('PN不能为空');
  2362. return;
  2363. }
  2364. this.$router.push({
  2365. path: '/ecss-partHsCode',
  2366. query: {
  2367. sku: pn
  2368. }
  2369. });
  2370. },
  2371. openPartDialog () {
  2372. this.searchPartList();
  2373. this.partFlag = true
  2374. },
  2375. closePartDialog () {
  2376. this.partList = []
  2377. this.partFlag = false
  2378. },
  2379. searchPartList () {
  2380. this.partData.site = this.currentRow.site
  2381. this.partData.delNo = this.currentRow.delNo
  2382. getNotifyPartDetail(this.partData).then(({data}) => {
  2383. if (data && data.code === 0){
  2384. this.partList = data.rows;
  2385. }
  2386. })
  2387. },
  2388. partRowDblclick (row) {
  2389. this.boxModelData.partNo = row.partNo
  2390. this.boxModelData.pn = row.pn
  2391. this.partFlag = false
  2392. },
  2393. // 获取基础数据列表S
  2394. getBaseList(val, type) {
  2395. this.tagNo = val
  2396. this.$nextTick(() => {
  2397. let strVal = ''
  2398. if (val === 507) {
  2399. strVal = this.boxModelData.partNo
  2400. }
  2401. this.$refs.baseList.init(val, strVal)
  2402. })
  2403. },
  2404. /* 列表方法的回调 */
  2405. getBaseData(val) {
  2406. if (this.tagNo === 507) {
  2407. this.boxModelData.partNo = val.part_no
  2408. }
  2409. },
  2410. // 每页数
  2411. sizeChangeHandle (val) {
  2412. this.pageSize = val
  2413. this.pageIndex = 1
  2414. this.searchTable()
  2415. },
  2416. // 当前页
  2417. currentChangeHandle (val) {
  2418. this.pageIndex = val
  2419. this.searchTable()
  2420. },
  2421. searchTable(){
  2422. this.searchData.limit = this.pageSize
  2423. this.searchData.page = this.pageIndex
  2424. searchEcssCoDelNotifyHeaderForCK(this.searchData).then(({data}) => {
  2425. //区分请求成功和失败的状况
  2426. if (data && data.code == 0) {
  2427. this.dataList = data.page.list
  2428. this.pageIndex = data.page.currPage
  2429. this.pageSize = data.page.pageSize
  2430. this.totalPage = data.page.totalCount
  2431. if(this.dataList.length>0){
  2432. this.dataList.forEach(o => {
  2433. if (o.notifyStatus==='仓库已确认'&&!o.notifyDate) {
  2434. o.notifyDate='预计发货日期不确定'
  2435. }
  2436. // 显示改单次数,如:改单(1)、改单(2)
  2437. o.modifyLabel = !!o.modifyFlag ? (o.modifyCount ? '改单(' + o.modifyCount + ')' : '改单(1)') : '';
  2438. });
  2439. // 使用 $nextTick 确保 DOM 渲染完成后再设置选中行
  2440. this.$nextTick(() => {
  2441. try {
  2442. // 检查表格引用是否存在
  2443. if (!this.$refs.mainTable) {
  2444. console.warn('[确认页面行选择持久化] 表格引用不存在,跳过设置选中行');
  2445. return;
  2446. }
  2447. // 尝试恢复之前选中的行
  2448. const restoredRow = this.restoreSelectedRow();
  2449. if (restoredRow) {
  2450. this.$refs.mainTable.setCurrentRow(restoredRow);
  2451. this.changeData(restoredRow);
  2452. } else {
  2453. // 如果没有之前选中的行,默认选中第一行
  2454. this.$refs.mainTable.setCurrentRow(this.dataList[0]);
  2455. this.changeData(this.dataList[0]);
  2456. }
  2457. } catch (error) {
  2458. console.error('[确认页面行选择持久化] 设置选中行失败:', error);
  2459. // 降级处理:只调用 changeData,不设置表格选中状态
  2460. const restoredRow = this.restoreSelectedRow();
  2461. this.changeData(restoredRow || this.dataList[0]);
  2462. }
  2463. });
  2464. }else {
  2465. this.changeData(null)
  2466. }
  2467. } else {
  2468. this.dataList = [];
  2469. }
  2470. });
  2471. },
  2472. tableRowClassName({row}) {
  2473. if (row.notifyStatus==='订单取消') {
  2474. return 'warning-row';
  2475. }
  2476. },
  2477. cellStyle({row, column }) {
  2478. if (this.isDelayWarningRow(row) && (column.property === 'notifyDate' || column.property === 'cmcInvoice')) {
  2479. return { color: '#fa0303', fontWeight: '700' };
  2480. }
  2481. if (column.property === 'notifyDate' && row.notifyDate==='预计发货日期不确定') { // 根据列属性判断
  2482. return { color: '#ff5d03' };
  2483. }
  2484. // 改单列显示橙色:只要modifyFlag为true就显示橙色
  2485. if (column.property === 'modifyLabel' && row.modifyFlag===true) {
  2486. return { color: '#ff5d03' };
  2487. }
  2488. return {};
  2489. },
  2490. cellStyleDetail({row, column }) {
  2491. // 只有数量列且 modifyQtyFlag=true 时才变色
  2492. if (column.property === 'qty' && row.modifyQtyFlag===true) {
  2493. return { color: '#ff5d03' };
  2494. }
  2495. // PN列保持原有的 modifyFlag 判断
  2496. if (column.property === 'pn' && row.modifyFlag===true) {
  2497. return { color: '#ff5d03' };
  2498. }
  2499. // 检查 pn 列,当 boxrolls、rollqty、boxweight 其中任意一个没有值时,将 pn 颜色改成橙色
  2500. if (column.property === 'pn') {
  2501. const hasBoxrolls = row.boxrolls !== null && row.boxrolls !== undefined && row.boxrolls !== '';
  2502. const hasRollqty = row.rollqty !== null && row.rollqty !== undefined && row.rollqty !== '';
  2503. const hasBoxweight = row.boxweight !== null && row.boxweight !== undefined && row.boxweight !== '';
  2504. const packageNo = row.packageNo !== null && row.packageNo !== undefined && row.packageNo !== '';
  2505. if (!hasBoxrolls || !hasRollqty || !hasBoxweight || !packageNo) {
  2506. return { color: '#ff8c00' }; // 橙色
  2507. }
  2508. }
  2509. return {};
  2510. },
  2511. changeData(row){
  2512. this.currentRow = JSON.parse(JSON.stringify(row));
  2513. if (this.currentRow&&this.currentRow.notifyDate==='预计发货日期不确定') {
  2514. this.currentRow.notifyDate=''
  2515. }
  2516. this.headerData=row;
  2517. // 保存选中行的唯一标识到本地存储
  2518. if (row && row.delNo) {
  2519. this.selectedRowKey = row.delNo;
  2520. this.saveSelectedRowToStorage();
  2521. }
  2522. this.refreshCurrentTabTable ();
  2523. },
  2524. refreshCurrentTabTable(){
  2525. if(this.currentRow===''||this.currentRow===null){
  2526. this.currentRow={site:'',delNo:'',notifyStatus:''}
  2527. }
  2528. if(this.activeName==='detail'){
  2529. searchEcssCoDelNotifyDetail(this.currentRow).then(({data}) => {
  2530. //区分请求成功和失败的状况
  2531. if (data && data.code == 0) {
  2532. this.dataList2 = data.rows
  2533. } else {
  2534. this.dataList2 = [];
  2535. }
  2536. });
  2537. }
  2538. if(this.activeName==='pallet'){
  2539. // 刷新装箱明细组件
  2540. if (this.$refs.packingDetailTab) {
  2541. this.$refs.packingDetailTab.refresh();
  2542. }
  2543. }
  2544. if(this.activeName==='box'){
  2545. searchEcssCoDelPalletHeaderData(this.currentRow).then(({data}) => {
  2546. //区分请求成功和失败的状况
  2547. if (data && data.code == 0) {
  2548. this.dataList4 = data.rows
  2549. } else {
  2550. this.dataList4 = [];
  2551. }
  2552. });
  2553. }
  2554. },
  2555. tabClick (tab, event) {
  2556. // 刷新列表数据
  2557. this.refreshCurrentTabTable()
  2558. },
  2559. confirmDo(){
  2560. confirmEcssDel(this.confirmModel).then(({data}) => {
  2561. if (data && data.code === 0) {
  2562. // 保存当前选中行的标识,以便刷新后恢复
  2563. const currentSelectedKey = this.confirmModel ? this.confirmModel.delNo : null;
  2564. if (currentSelectedKey) {
  2565. this.selectedRowKey = currentSelectedKey;
  2566. this.saveSelectedRowToStorage();
  2567. }
  2568. this.searchTable()
  2569. this.confirmModelFlag=false
  2570. this.$message({
  2571. message: '操作成功',
  2572. type: 'success',
  2573. duration: 1500,
  2574. onClose: () => {}
  2575. })
  2576. } else {
  2577. this.$alert(data.msg, '错误', {
  2578. confirmButtonText: '确定'
  2579. })
  2580. }
  2581. })
  2582. },
  2583. cancerConfirm(row){
  2584. let indata=JSON.parse(JSON.stringify(row));
  2585. if (row.notifyDate==='预计发货日期不确定') {
  2586. indata.notifyDate=''
  2587. }
  2588. this.$confirm('取消确认这条发货通知单?', '提示').then(() => {
  2589. cancerConfirmEcssDel(indata).then(({data}) => {
  2590. if (data && data.code === 0) {
  2591. // 保存当前选中行的标识,以便刷新后恢复
  2592. const currentSelectedKey = row ? row.delNo : null;
  2593. if (currentSelectedKey) {
  2594. this.selectedRowKey = currentSelectedKey;
  2595. this.saveSelectedRowToStorage();
  2596. }
  2597. this.searchTable()
  2598. this.$message({
  2599. message: '操作成功',
  2600. type: 'success',
  2601. duration: 1500,
  2602. onClose: () => {}
  2603. })
  2604. } else {
  2605. this.$alert(data.msg, '错误', {
  2606. confirmButtonText: '确定'
  2607. })
  2608. }
  2609. })
  2610. })
  2611. },
  2612. getBu () {
  2613. let tempData = {
  2614. username: this.$store.state.user.name,
  2615. }
  2616. getBuList(tempData).then(({data}) => {
  2617. if (data.code === 0) {
  2618. this.buList = data.row2
  2619. if (this.buList.length===1) {
  2620. this.searchData.buNo = this.buList[0].buNo;
  2621. }
  2622. }
  2623. })
  2624. },
  2625. confirmModelOpen(row){
  2626. this.confirmModel=JSON.parse(JSON.stringify(row));
  2627. this.confirmModelFlag=true
  2628. },
  2629. updateModelOpen(row){
  2630. this.confirmModel=JSON.parse(JSON.stringify(row));
  2631. if (this.confirmModel.notifyDate==='预计发货日期不确定') {
  2632. this.confirmModel.notifyDate=''
  2633. }
  2634. this.updateModelFlag=true
  2635. },
  2636. updateDo(){
  2637. if (!this.confirmModel.readyDate) {
  2638. this.$alert('请选择ReadyDate!', '错误', {
  2639. confirmButtonText: '确定'
  2640. })
  2641. return false
  2642. }
  2643. // 添加更新人信息
  2644. this.confirmModel.updateBy = this.$store.state.user.name
  2645. updateEcssDel(this.confirmModel).then(({data}) => {
  2646. if (data && data.code === 0) {
  2647. // 保存当前选中行的标识,以便刷新后恢复
  2648. const currentSelectedKey = this.confirmModel ? this.confirmModel.delNo : null;
  2649. if (currentSelectedKey) {
  2650. this.selectedRowKey = currentSelectedKey;
  2651. this.saveSelectedRowToStorage();
  2652. }
  2653. this.searchTable()
  2654. this.updateModelFlag=false
  2655. this.$message({
  2656. message: '操作成功',
  2657. type: 'success',
  2658. duration: 1500,
  2659. onClose: () => {}
  2660. })
  2661. } else {
  2662. this.$alert(data.msg, '错误', {
  2663. confirmButtonText: '确定'
  2664. })
  2665. }
  2666. })
  2667. },
  2668. upLoadPallet(){
  2669. if(this.currentRow.site===''||this.currentRow.site==null){
  2670. this.$alert('请先选择发货通知单!', '错误', {
  2671. confirmButtonText: '确定'
  2672. })
  2673. return false
  2674. }
  2675. let inData={
  2676. site:this.currentRow.site,
  2677. buNo:this.currentRow.buNo,
  2678. delNo:this.currentRow.delNo,
  2679. cmcInvoice:this.currentRow.cmcInvoice,
  2680. shippingMode: this.currentRow.shippingMode,
  2681. destination : this.currentRow.destination,
  2682. walMartOrderFlag:this.currentRow.walMartOrderFlag
  2683. }
  2684. this.$nextTick(() => {
  2685. this.$refs.palletUploadExcel.init(inData)
  2686. })
  2687. },
  2688. async exportExcel() {
  2689. if(this.currentRow.site===''||this.currentRow.site==null){
  2690. this.$alert('请先选择发货通知单!', '错误', {
  2691. confirmButtonText: '确定'
  2692. })
  2693. return false
  2694. }
  2695. let exportParam = {
  2696. site: this.currentRow.site,
  2697. buNo: this.currentRow.buNo,
  2698. delNo: this.currentRow.delNo,
  2699. cmcInvoice: this.currentRow.cmcInvoice,
  2700. shippingMode: this.currentRow.shippingMode,
  2701. destination : this.currentRow.destination,
  2702. readyDate: this.currentRow.readyDate, // 增加ReadyDate列
  2703. remark: this.currentRow.remark, // 增加备注列
  2704. createBy: this.$store.state.user.name,
  2705. }
  2706. try {
  2707. // 使用后台Excel模版导出
  2708. ExportUtil.export(
  2709. "/ecss/coDel/exportPackingTemplate",
  2710. exportParam,
  2711. this.currentRow.cmcInvoice + "装箱数据.xlsx"
  2712. );
  2713. // 导出成功后更新export_flag字段
  2714. let updateData = {
  2715. site: this.currentRow.site,
  2716. buNo: this.currentRow.buNo,
  2717. delNo: this.currentRow.delNo,
  2718. exportFlag: 'Y',
  2719. updateBy: this.$store.state.user.name
  2720. }
  2721. updateExportFlag(updateData).then(({data}) => {
  2722. if (data.code === 0) {
  2723. // 刷新当前行的导出状态
  2724. this.currentRow.exportFlag = 'Y';
  2725. // 刷新表格数据
  2726. this.searchTable();
  2727. this.$message({
  2728. message: '导出成功',
  2729. type: 'success',
  2730. duration: 1500
  2731. });
  2732. } else {
  2733. this.$message.warning('导出成功,但更新导出状态失败:' + data.msg);
  2734. }
  2735. }).catch(error => {
  2736. this.$message.warning('导出成功,但更新导出状态失败');
  2737. console.error('更新导出状态失败:', error);
  2738. });
  2739. } catch (error) {
  2740. this.$message.error('导出失败');
  2741. console.error('导出失败:', error);
  2742. }
  2743. },
  2744. searchPalletTable(){
  2745. this.refreshCurrentTabTable();
  2746. },
  2747. boxDetailModel(row){
  2748. this.boxDetailData=row
  2749. searchEcssCoDelPalletDetailData(row).then(({data}) => {
  2750. if (data.code === 0) {
  2751. this.dataList5 = data.rows
  2752. }
  2753. })
  2754. this.boxDetailModelFlag=true
  2755. },
  2756. updatePalletModel(row){
  2757. this.palletModelData=JSON.parse(JSON.stringify(row))
  2758. this.palletModelData.palletRemark=row.palletRemark
  2759. this.palletModelData.addFlag=1
  2760. this.palletEditFlag=true
  2761. },
  2762. newPalletModel(){
  2763. if(this.currentRow.site===''||this.currentRow.site==null){
  2764. this.$alert('请先选择发货通知单!', '错误', {
  2765. confirmButtonText: '确定'
  2766. })
  2767. return false
  2768. }
  2769. this.palletModelData={
  2770. addFlag:0,
  2771. site:this.currentRow.site,
  2772. buNo:this.currentRow.buNo,
  2773. delNo:this.currentRow.delNo,
  2774. grossWeight:'',
  2775. netWeight:'',
  2776. boxQty:'',
  2777. }
  2778. searchEcssCoDelNotifyDetail(this.currentRow).then(({data}) => {
  2779. if (data && data.code == 0) {
  2780. this.dataList8 = data.rows
  2781. } else {
  2782. this.dataList8 = [];
  2783. }
  2784. });
  2785. this.palletModelFlag=true
  2786. },
  2787. fillUseQty(row) {
  2788. row.useQty = row.surplusQty || 0;
  2789. // 全数装箱后也需要计算rolls
  2790. this.calculateRolls(row);
  2791. },
  2792. /**
  2793. * 根据装箱数量自动计算Rolls卷数
  2794. * 计算公式Rolls = 装箱数量 / 每卷数量
  2795. * @param row 当前行数据
  2796. */
  2797. calculateRolls(row) {
  2798. // 如果装箱数量为空或为0,清空rolls
  2799. if (!row.useQty || row.useQty <= 0) {
  2800. this.$set(row, 'rolls', null);
  2801. // 装箱数量变化后,重新计算总箱数和重量
  2802. this.calculateTotalBoxQtyAndWeights();
  2803. return;
  2804. }
  2805. // 如果已经有缓存的每卷数量,直接计算
  2806. if (row.rollQtyCache && row.rollQtyCache > 0) {
  2807. const rolls = row.useQty / row.rollQtyCache;
  2808. this.$set(row, 'rolls', parseFloat(rolls.toFixed(4)));
  2809. // 装箱数量变化后,重新计算总箱数和重量
  2810. this.calculateTotalBoxQtyAndWeights();
  2811. return;
  2812. }
  2813. // 调用后端API获取每卷数量
  2814. const params = {
  2815. site: this.currentRow.site,
  2816. buNo: this.currentRow.buNo,
  2817. partNo: row.partNo
  2818. };
  2819. getPartPackageProperties(params).then(({data}) => {
  2820. if (data && data.code === 0 && data.data) {
  2821. const rollQty = data.data.rollQty;
  2822. if (rollQty && rollQty > 0) {
  2823. // 缓存每卷数量到row中,避免重复请求
  2824. this.$set(row, 'rollQtyCache', rollQty);
  2825. this.$set(row, 'boxRollsCache', data.data.boxRolls);
  2826. this.$set(row, 'boxWeightCache', data.data.boxWeight);
  2827. // 计算rolls:装箱数量 / 每卷数量
  2828. const rolls = row.useQty / rollQty;
  2829. this.$set(row, 'rolls', parseFloat(rolls.toFixed(4)));
  2830. // 装箱数量变化后,重新计算总箱数和重量
  2831. this.calculateTotalBoxQtyAndWeights();
  2832. } else {
  2833. this.$message.warning(`物料 ${row.partNo} 未配置每卷数量(ROLLQTY)属性,无法自动计算Rolls`);
  2834. this.$set(row, 'rolls', null);
  2835. }
  2836. } else {
  2837. console.error('获取物料包装属性失败:', data ? data.msg : '未知错误');
  2838. // 失败时不阻断用户操作,允许手动输入
  2839. this.$set(row, 'rolls', null);
  2840. }
  2841. }).catch(error => {
  2842. console.error('获取物料包装属性异常:', error);
  2843. // 异常时不阻断用户操作,允许手动输入
  2844. this.$set(row, 'rolls', null);
  2845. });
  2846. },
  2847. /**
  2848. * 根据物料装箱数量自动计算总箱数毛重净重和总Rolls
  2849. */
  2850. calculateTotalBoxQtyAndWeights() {
  2851. // 获取有装箱数量的物料列表
  2852. const selectedRows = this.dataList8.filter(item => item.useQty && item.useQty > 0);
  2853. // 先计算总Rolls(不管是否有缓存属性,都可以汇总)
  2854. this.calculateTotalRolls();
  2855. if (selectedRows.length === 0) {
  2856. // 没有装箱数量时,清空
  2857. this.palletModelData.boxQty = null;
  2858. this.palletModelData.grossWeight = null;
  2859. this.palletModelData.netWeight = null;
  2860. return;
  2861. }
  2862. // 检查是否所有物料都已缓存包装属性
  2863. const allHaveCache = selectedRows.every(row =>
  2864. row.rollQtyCache && row.boxRollsCache && row.boxWeightCache
  2865. );
  2866. if (!allHaveCache) {
  2867. // 如果有物料未缓存属性,不自动计算(避免数据不完整)
  2868. return;
  2869. }
  2870. // 计算总箱数和总重量
  2871. let totalBoxQty = 0;
  2872. let totalGrossWeight = 0;
  2873. selectedRows.forEach(row => {
  2874. // 每箱EA = 每卷数量 × 每箱卷数
  2875. const eaPerBox = row.rollQtyCache * row.boxRollsCache;
  2876. // 该物料的箱数(向上取整)
  2877. const partBoxQty = Math.ceil(row.useQty / eaPerBox);
  2878. // 该物料的毛重 = 箱数 × 箱重量
  2879. const partGrossWeight = partBoxQty * row.boxWeightCache;
  2880. totalBoxQty += partBoxQty;
  2881. totalGrossWeight += partGrossWeight;
  2882. });
  2883. // 净重 = 毛重 - (箱数 / 2)
  2884. const totalNetWeight = totalGrossWeight - (totalBoxQty / 2);
  2885. // 自动填入箱数、毛重、净重
  2886. this.palletModelData.boxQty = totalBoxQty;
  2887. this.palletModelData.grossWeight = parseFloat(totalGrossWeight.toFixed(2));
  2888. this.palletModelData.netWeight = parseFloat(totalNetWeight.toFixed(2));
  2889. },
  2890. /**
  2891. * 汇总明细的Rolls总和
  2892. */
  2893. calculateTotalRolls() {
  2894. let totalRolls = 0;
  2895. this.dataList8.forEach(row => {
  2896. const rollsValue = parseFloat(row.rolls);
  2897. if (!isNaN(rollsValue) && rollsValue > 0) {
  2898. totalRolls += rollsValue;
  2899. }
  2900. });
  2901. // 自动填入总Rolls(取整)
  2902. this.$set(this.palletModelData, 'rolls', totalRolls > 0 ? Math.round(totalRolls) : null);
  2903. },
  2904. /**
  2905. * 延迟计算总Rolls等待v-model更新完成
  2906. */
  2907. delayCalculateTotalRolls() {
  2908. this.$nextTick(() => {
  2909. this.calculateTotalRolls();
  2910. });
  2911. },
  2912. /**
  2913. * 根据箱数自动计算毛重和净重
  2914. * 计算公式来自后端代码2991-2992
  2915. * 毛重 = 箱数 × 箱重量
  2916. * 净重 = 毛重 - (箱数 / 2)
  2917. */
  2918. calculateWeightsByBoxQty() {
  2919. // 如果箱数为空或为0,清空毛重和净重
  2920. if (!this.palletModelData.boxQty || this.palletModelData.boxQty <= 0) {
  2921. this.palletModelData.grossWeight = null;
  2922. this.palletModelData.netWeight = null;
  2923. return;
  2924. }
  2925. // 获取有装箱数量的物料列表
  2926. const selectedRows = this.dataList8.filter(item => item.useQty && item.useQty > 0);
  2927. if (selectedRows.length === 0) {
  2928. // 没有选择物料时,不自动计算,允许用户手动输入
  2929. return;
  2930. }
  2931. // 检查是否所有物料都已缓存箱重量
  2932. const needFetchProperties = selectedRows.filter(row => !row.boxWeightCache);
  2933. if (needFetchProperties.length === 0) {
  2934. // 所有物料都有缓存,直接计算
  2935. this.calculateWeightsWithCache(selectedRows);
  2936. } else {
  2937. // 需要获取部分物料的属性
  2938. this.fetchBoxWeightsAndCalculate(selectedRows, needFetchProperties);
  2939. }
  2940. },
  2941. /**
  2942. * 使用缓存的箱重量计算毛重和净重
  2943. */
  2944. calculateWeightsWithCache(selectedRows) {
  2945. // 根据装箱数量计算加权平均箱重量
  2946. let totalWeight = 0;
  2947. let totalQty = 0;
  2948. selectedRows.forEach(row => {
  2949. if (row.boxWeightCache && row.boxWeightCache > 0 && row.rollQtyCache && row.rollQtyCache > 0 && row.boxRollsCache && row.boxRollsCache > 0) {
  2950. // 每箱EA = 每卷数量 × 每箱卷数
  2951. const eaPerBox = row.rollQtyCache * row.boxRollsCache;
  2952. // 该物料的箱数
  2953. const partBoxQty = Math.ceil(row.useQty / eaPerBox);
  2954. // 累计重量和箱数
  2955. totalWeight += partBoxQty * row.boxWeightCache;
  2956. totalQty += partBoxQty;
  2957. }
  2958. });
  2959. if (totalQty > 0) {
  2960. // 计算平均箱重量
  2961. const avgBoxWeight = totalWeight / totalQty;
  2962. this.calculateFinalWeights(avgBoxWeight);
  2963. } else {
  2964. // 如果无法计算平均重量,使用第一个物料的箱重量
  2965. const firstRow = selectedRows.find(row => row.boxWeightCache && row.boxWeightCache > 0);
  2966. if (firstRow) {
  2967. this.calculateFinalWeights(firstRow.boxWeightCache);
  2968. }
  2969. }
  2970. },
  2971. /**
  2972. * 获取物料箱重量并计算毛重净重
  2973. */
  2974. fetchBoxWeightsAndCalculate(selectedRows, needFetchProperties) {
  2975. // 批量获取物料属性
  2976. const promises = needFetchProperties.map(row => {
  2977. const params = {
  2978. site: this.currentRow.site,
  2979. buNo: this.currentRow.buNo,
  2980. partNo: row.partNo
  2981. };
  2982. return getPartPackageProperties(params).then(({data}) => {
  2983. if (data && data.code === 0 && data.data) {
  2984. // 缓存物料属性
  2985. this.$set(row, 'rollQtyCache', data.data.rollQty);
  2986. this.$set(row, 'boxRollsCache', data.data.boxRolls);
  2987. this.$set(row, 'boxWeightCache', data.data.boxWeight);
  2988. return true;
  2989. }
  2990. return false;
  2991. }).catch(error => {
  2992. console.error(`获取物料 ${row.partNo} 属性失败:`, error);
  2993. return false;
  2994. });
  2995. });
  2996. Promise.all(promises).then(() => {
  2997. // 所有属性获取完成后,重新计算
  2998. this.calculateWeightsWithCache(selectedRows);
  2999. });
  3000. },
  3001. /**
  3002. * 计算最终的毛重和净重
  3003. * @param avgBoxWeight 平均箱重量
  3004. */
  3005. calculateFinalWeights(avgBoxWeight) {
  3006. const boxQty = parseFloat(this.palletModelData.boxQty);
  3007. // 毛重 = 箱数 × 箱重量
  3008. const grossWeight = boxQty * avgBoxWeight;
  3009. // 净重 = 毛重 - (箱数 / 2)
  3010. const netWeight = grossWeight - (boxQty / 2);
  3011. // 保留2位小数
  3012. this.palletModelData.grossWeight = parseFloat(grossWeight.toFixed(2));
  3013. this.palletModelData.netWeight = parseFloat(netWeight.toFixed(2));
  3014. },
  3015. /**
  3016. * 毛重改变时自动计算净重
  3017. * 计算公式净重 = 毛重 - (箱数 / 2)
  3018. */
  3019. onPalletGrossWeightChange(value) {
  3020. // 防止循环触发,使用标志位
  3021. if (this._isPalletWeightCalculating) {
  3022. return;
  3023. }
  3024. this._isPalletWeightCalculating = true;
  3025. try {
  3026. const grossWeight = parseFloat(value) || 0;
  3027. const boxQty = parseFloat(this.palletModelData.boxQty) || 0;
  3028. if (grossWeight <= 0) {
  3029. this.palletModelData.netWeight = '';
  3030. return;
  3031. }
  3032. // 计算净重:净重 = 毛重 - (箱数 / 2)
  3033. const netWeight = grossWeight - (boxQty / 2);
  3034. // 保留2位小数
  3035. this.palletModelData.netWeight = parseFloat(netWeight.toFixed(2));
  3036. } finally {
  3037. this._isPalletWeightCalculating = false;
  3038. }
  3039. },
  3040. /**
  3041. * 净重改变时自动计算毛重
  3042. * 反向计算公式毛重 = 净重 + (箱数 / 2)
  3043. */
  3044. onPalletNetWeightChange(value) {
  3045. // 防止循环触发,使用标志位
  3046. if (this._isPalletWeightCalculating) {
  3047. return;
  3048. }
  3049. this._isPalletWeightCalculating = true;
  3050. try {
  3051. const netWeight = parseFloat(value) || 0;
  3052. const boxQty = parseFloat(this.palletModelData.boxQty) || 0;
  3053. if (netWeight <= 0) {
  3054. this.palletModelData.grossWeight = '';
  3055. return;
  3056. }
  3057. // 反向计算毛重:毛重 = 净重 + (箱数 / 2)
  3058. const grossWeight = netWeight + (boxQty / 2);
  3059. // 保留2位小数
  3060. this.palletModelData.grossWeight = parseFloat(grossWeight.toFixed(2));
  3061. } finally {
  3062. this._isPalletWeightCalculating = false;
  3063. }
  3064. },
  3065. savePalletHeader(type) {
  3066. // 过滤出 useQty > 0 的行
  3067. const selectedRows = this.dataList8.filter(item => item.useQty && item.useQty > 0);
  3068. if (this.palletModelData.addFlag === 0 && selectedRows.length === 0) {
  3069. this.$alert('请至少输入一行装箱数量!', '错误', {
  3070. confirmButtonText: '确定'
  3071. });
  3072. return false;
  3073. }
  3074. if (this.palletModelData.grossWeight<=0||this.palletModelData.grossWeight==null) {
  3075. this.$alert('请输入毛重!', '错误', {
  3076. confirmButtonText: '确定'
  3077. });
  3078. return false;
  3079. }
  3080. if (this.palletModelData.netWeight<=0||this.palletModelData.netWeight==null) {
  3081. this.$alert('请输入净重!', '错误', {
  3082. confirmButtonText: '确定'
  3083. });
  3084. return false;
  3085. }
  3086. if (this.palletModelData.boxQty<=0||this.palletModelData.boxQty==null) {
  3087. this.$alert('请输入箱数!', '错误', {
  3088. confirmButtonText: '确定'
  3089. });
  3090. return false;
  3091. }
  3092. // 校验:装箱数量不能大于可装箱数量 (item.qty)
  3093. const invalidRow = selectedRows.find(item => item.useQty > item.surplusQty);
  3094. if (invalidRow) {
  3095. this.$alert(`PN ${invalidRow.pn} 的装箱数量不能大于可装箱数量(${invalidRow.surplusQty})!`, '错误', {
  3096. confirmButtonText: '确定'
  3097. });
  3098. return false;
  3099. }
  3100. this.palletModelData.walMartOrderFlag = this.currentRow.walMartOrderFlag;
  3101. this.palletModelData.notifyDetailList = selectedRows;
  3102. savePalletHeader(this.palletModelData).then(({ data }) => {
  3103. if (data && data.code === 0) {
  3104. if (type===0) {
  3105. this.palletModelData={
  3106. addFlag:0,
  3107. site:this.currentRow.site,
  3108. buNo:this.currentRow.buNo,
  3109. delNo:this.currentRow.delNo,
  3110. grossWeight:'',
  3111. netWeight:'',
  3112. boxQty:'',
  3113. }
  3114. searchEcssCoDelNotifyDetail(this.currentRow).then(({data}) => {
  3115. if (data && data.code == 0) {
  3116. this.dataList8 = data.rows
  3117. } else {
  3118. this.dataList8 = [];
  3119. }
  3120. });
  3121. } else {
  3122. this.refreshCurrentTabTable()
  3123. this.palletModelFlag=false;
  3124. }
  3125. this.$message({
  3126. message: '操作成功',
  3127. type: 'success',
  3128. duration: 1500
  3129. });
  3130. } else {
  3131. this.$alert(data.msg, '错误', {
  3132. confirmButtonText: '确定'
  3133. });
  3134. }
  3135. });
  3136. },
  3137. updateCodelPalletHeaderPalletQty(row){
  3138. // 显示页面loading
  3139. const loading = this.$loading({
  3140. lock: true,
  3141. text: '保存中...',
  3142. spinner: 'el-icon-loading',
  3143. background: 'rgba(0, 0, 0, 0.3)'
  3144. });
  3145. updateCodelPalletHeaderPalletQty(this.palletModelData).then(({data}) => {
  3146. loading.close();
  3147. if (data && data.code === 0) {
  3148. this.palletEditFlag = false
  3149. // 刷新当前tab表格
  3150. this.refreshCurrentTabTable()
  3151. // 刷新上方的发货通知单列表
  3152. this.searchTable()
  3153. this.$message({
  3154. message: '操作成功',
  3155. type: 'success',
  3156. duration: 1500,
  3157. onClose: () => {}
  3158. })
  3159. } else {
  3160. this.$alert(data.msg, '错误', {
  3161. confirmButtonText: '确定'
  3162. })
  3163. }
  3164. }).catch(error => {
  3165. loading.close();
  3166. this.$message.error('保存失败: ' + (error.message || '未知错误'))
  3167. })
  3168. },
  3169. deletePallet(row){
  3170. this.$confirm('确认删除此明细?', '提示').then(() => {
  3171. // 显示页面loading
  3172. const loading = this.$loading({
  3173. lock: true,
  3174. text: '删除中...',
  3175. spinner: 'el-icon-loading',
  3176. background: 'rgba(0, 0, 0, 0.3)'
  3177. });
  3178. deletePalletHeader(row).then(({data}) => {
  3179. loading.close();
  3180. if (data && data.code === 0) {
  3181. this.refreshCurrentTabTable()
  3182. // 刷新上方的发货通知单列表
  3183. this.searchTable()
  3184. this.$message({
  3185. message: '操作成功',
  3186. type: 'success',
  3187. duration: 1500,
  3188. onClose: () => {}
  3189. })
  3190. } else {
  3191. this.$alert(data.msg, '错误', {
  3192. confirmButtonText: '确定'
  3193. })
  3194. }
  3195. }).catch(error => {
  3196. loading.close();
  3197. this.$message.error('删除失败: ' + (error.message || '未知错误'))
  3198. })
  3199. })
  3200. },
  3201. updateBoxModel(row,type){
  3202. this.boxModelData=JSON.parse(JSON.stringify(row))
  3203. this.boxModelData.addFlag=1
  3204. this.boxModelData.type=type
  3205. this.boxModelFlag=true
  3206. },
  3207. newBoxModel(){
  3208. this.boxModelData={
  3209. addFlag:0,
  3210. site:this.boxDetailData.site,
  3211. buNo:this.boxDetailData.buNo,
  3212. delNo:this.boxDetailData.delNo,
  3213. seqNo:this.boxDetailData.seqNo,
  3214. itemNo:'',
  3215. partNo:'',
  3216. pn:'',
  3217. qty:'',
  3218. poNo:'',
  3219. boxQty:'',
  3220. rolls:'',
  3221. type:0
  3222. }
  3223. this.boxModelFlag=true
  3224. },
  3225. saveBoxHeader(){
  3226. if(this.boxModelData.partNo===''||this.boxModelData.partNo==null){
  3227. this.$alert('请输入物料!', '错误', {
  3228. confirmButtonText: '确定'
  3229. })
  3230. return false
  3231. }
  3232. if(this.boxModelData.qty<=0||this.boxModelData.qty==null){
  3233. this.$alert('请输入数量!', '错误', {
  3234. confirmButtonText: '确定'
  3235. })
  3236. return false
  3237. }
  3238. savePalletDetail(this.boxModelData).then(({data}) => {
  3239. if (data && data.code === 0) {
  3240. searchEcssCoDelPalletDetailData(this.boxDetailData).then(({data}) => {
  3241. if (data.code === 0) {
  3242. this.dataList5 = data.rows
  3243. }
  3244. })
  3245. searchCoDelPalletDataNew(this.currentRow).then(({data}) => {
  3246. if (data && data.code == 0) {
  3247. this.dataList3 = data.rows
  3248. } else {
  3249. this.dataList3 = [];
  3250. }
  3251. });
  3252. this.boxModelFlag=false;
  3253. this.$message({
  3254. message: '操作成功',
  3255. type: 'success',
  3256. duration: 1500,
  3257. onClose: () => {}
  3258. })
  3259. } else {
  3260. this.$alert(data.msg, '错误', {
  3261. confirmButtonText: '确定'
  3262. })
  3263. }
  3264. })
  3265. },
  3266. oneClickPacking(){
  3267. if(this.currentRow.site===''||this.currentRow.site==null){
  3268. this.$alert('请先选择发货通知单!', '错误', {
  3269. confirmButtonText: '确定'
  3270. })
  3271. return false
  3272. }
  3273. this.oneClickPackingModelData={
  3274. boxRemnant: false,
  3275. }
  3276. this.oneClickPackingModelFlag=true
  3277. },
  3278. saveOneClickPacking(){
  3279. let saveData = {
  3280. site: this.currentRow.site,
  3281. buNo: this.currentRow.buNo,
  3282. delNo: this.currentRow.delNo,
  3283. boxRemnant: this.oneClickPackingModelData.boxRemnant,
  3284. }
  3285. // 显示页面loading
  3286. const loading = this.$loading({
  3287. lock: true,
  3288. text: '一键装箱计算中...',
  3289. spinner: 'el-icon-loading',
  3290. background: 'rgba(0, 0, 0, 0.3)'
  3291. });
  3292. saveOneClickPacking(saveData).then(({data}) => {
  3293. loading.close();
  3294. if (data && data.code === 0) {
  3295. this.oneClickPackingModelFlag=false;
  3296. // 刷新当前tab表格
  3297. this.refreshCurrentTabTable()
  3298. // 刷新上方的发货通知单列表
  3299. this.searchTable()
  3300. this.$message({
  3301. message: '操作成功',
  3302. type: 'success',
  3303. duration: 1500,
  3304. onClose: () => {}
  3305. })
  3306. } else {
  3307. this.$alert(data.msg, '错误', {
  3308. confirmButtonText: '确定'
  3309. })
  3310. }
  3311. }).catch(error => {
  3312. loading.close();
  3313. this.$message.error('一键装箱失败: ' + (error.message || '未知错误'))
  3314. })
  3315. },
  3316. // ========== 合箱批量编辑相关方法 ==========
  3317. /**
  3318. * 打开合箱批量编辑弹出框
  3319. */
  3320. openMergeBoxDialog() {
  3321. if(this.currentRow.site===''||this.currentRow.site==null){
  3322. this.$alert('请先选择发货通知单!', '错误', {
  3323. confirmButtonText: '确定'
  3324. })
  3325. return false
  3326. }
  3327. this.mergeBoxDialogVisible = true
  3328. },
  3329. /**
  3330. * 加载合箱批量编辑数据
  3331. * 将发货通知单明细扁平化为表格数据每条明细默认是一个箱子
  3332. */
  3333. async loadMergeBoxData() {
  3334. this.mergeBoxLoading = true
  3335. this.mergeBoxTableData = []
  3336. this.mergeBoxSelection = []
  3337. this.mergeBoxOriginalData = {}
  3338. this.mergeBoxModifiedBoxes = {}
  3339. this.mergeBoxModifiedDetails = {}
  3340. this.mergeBoxMergeHistory = []
  3341. this.nextItemNo = 1
  3342. try {
  3343. // 每次都重新查询最新的发货通知单明细数据
  3344. const detailResponse = await searchEcssCoDelNotifyDetail(this.currentRow)
  3345. const detailList = (detailResponse.data && detailResponse.data.code === 0)
  3346. ? detailResponse.data.rows || []
  3347. : []
  3348. if (detailList.length === 0) {
  3349. this.$message.warning('当前发货通知单没有明细数据')
  3350. this.mergeBoxLoading = false
  3351. return
  3352. }
  3353. // 处理明细数据 - 每条明细作为一个单独的箱
  3354. const tableData = []
  3355. let itemNo = 1
  3356. // 只处理剩余数量(surplus_qty)大于0的明细
  3357. const detailsToProcess = []
  3358. detailList.forEach(detail => {
  3359. const surplusQty = Number(detail.surplusQty) || 0
  3360. // 只处理剩余数量大于0的明细
  3361. if (surplusQty > 0) {
  3362. detailsToProcess.push({
  3363. detail: detail,
  3364. unpackedQty: surplusQty // 使用剩余数量
  3365. })
  3366. }
  3367. })
  3368. if (detailsToProcess.length === 0) {
  3369. this.$message.warning('所有明细都已装箱完毕')
  3370. this.mergeBoxLoading = false
  3371. return
  3372. }
  3373. // 创建表格数据
  3374. // searchEcssCoDelNotifyDetail已经返回了rollqty、boxrolls、boxweight,直接使用
  3375. detailsToProcess.forEach(({detail, unpackedQty}) => {
  3376. const boxKey = `box_${itemNo}`
  3377. // 直接从detail中读取包装属性(小写字段名)
  3378. const rollQty = Number(detail.rollqty) || 0
  3379. const boxRolls = Number(detail.boxrolls) || 0
  3380. const boxWeight = Number(detail.boxweight) || 0
  3381. // 计算默认值
  3382. let detailRolls = 0
  3383. let box_qty = 1
  3384. let grossWeight = 0
  3385. let netWeight = 0
  3386. let rolls = 0
  3387. // 1. 根据数量计算明细rolls(与calculateRolls保持一致)
  3388. if (rollQty > 0) {
  3389. detailRolls = parseFloat((unpackedQty / rollQty).toFixed(4))
  3390. // 总rolls = 明细rolls四舍五入取整(初始时每箱只有一条明细)
  3391. rolls = Math.round(detailRolls)
  3392. }
  3393. // 2. 根据数量计算箱数(向上取整,不允许小数箱)
  3394. if (rollQty > 0 && boxRolls > 0) {
  3395. const eaPerBox = rollQty * boxRolls
  3396. box_qty = Math.ceil(unpackedQty / eaPerBox)
  3397. }
  3398. // 3. 根据箱数计算毛重
  3399. if (boxWeight > 0) {
  3400. grossWeight = parseFloat((box_qty * boxWeight).toFixed(3))
  3401. }
  3402. // 4. 根据毛重计算净重(与装箱按钮保持一致)
  3403. netWeight = parseFloat((grossWeight - (box_qty / 2)).toFixed(3))
  3404. // 创建一行数据(Box和明细合并在一起)
  3405. const rowData = {
  3406. // Box信息
  3407. _boxKey: boxKey,
  3408. _isFirstRowOfBox: true,
  3409. _rowSpan: 1,
  3410. item_no: itemNo,
  3411. box_qty: box_qty,
  3412. grossWeight: grossWeight,
  3413. netWeight: netWeight,
  3414. rolls: rolls,
  3415. // 明细信息
  3416. _detailKey: `${detail.itemNo}_${detail.customerPO}_${detail.pn}`,
  3417. _hasDetail: true,
  3418. itemNo: detail.itemNo,
  3419. poNo: detail.customerPO,
  3420. pn: detail.pn,
  3421. qty: unpackedQty,
  3422. detailRolls: detailRolls,
  3423. readyDate: detail.readyDate,
  3424. partDesc: detail.partDesc,
  3425. cinvcname: detail.cinvcname,
  3426. // 缓存物料属性(用于后续自动计算)
  3427. rollQtyCache: rollQty,
  3428. boxRollsCache: boxRolls,
  3429. boxWeightCache: boxWeight
  3430. }
  3431. tableData.push(rowData)
  3432. // 保存Box原始数据
  3433. this.mergeBoxOriginalData[boxKey] = {
  3434. box_qty: box_qty,
  3435. grossWeight: grossWeight,
  3436. netWeight: netWeight,
  3437. rolls: rolls,
  3438. boxWeight: boxWeight
  3439. }
  3440. // 保存明细原始数据
  3441. this.mergeBoxOriginalData[rowData._detailKey] = {
  3442. qty: unpackedQty,
  3443. detailRolls: detailRolls
  3444. }
  3445. itemNo++
  3446. })
  3447. this.mergeBoxTableData = tableData
  3448. this.nextItemNo = itemNo
  3449. } catch (error) {
  3450. console.error('加载合箱数据失败:', error)
  3451. this.$message.error('加载数据失败')
  3452. } finally {
  3453. this.mergeBoxLoading = false
  3454. }
  3455. },
  3456. /**
  3457. * 选择变化事件处理
  3458. */
  3459. handleMergeBoxSelectionChange(selection) {
  3460. this.mergeBoxSelection = selection
  3461. },
  3462. /**
  3463. * 合并选中的箱
  3464. */
  3465. doMergeBoxes() {
  3466. if (this.mergeBoxSelection.length < 2) {
  3467. this.$message.warning('请至少选择2个箱进行合并')
  3468. return
  3469. }
  3470. // 获取选中箱的所有行数据
  3471. const selectedBoxKeys = this.mergeBoxSelection.map(row => row._boxKey)
  3472. const rowsToMerge = this.mergeBoxTableData.filter(row =>
  3473. selectedBoxKeys.includes(row._boxKey)
  3474. )
  3475. // 保存合并前的状态(用于取消合并)
  3476. const mergeHistoryItem = {
  3477. timestamp: Date.now(),
  3478. boxes: []
  3479. }
  3480. // 记录每个被合并的箱的原始状态
  3481. selectedBoxKeys.forEach(boxKey => {
  3482. const boxRows = this.mergeBoxTableData.filter(row => row._boxKey === boxKey)
  3483. if (boxRows.length > 0) {
  3484. mergeHistoryItem.boxes.push({
  3485. boxKey: boxKey,
  3486. item_no: boxRows[0].item_no,
  3487. box_qty: boxRows[0].box_qty,
  3488. grossWeight: boxRows[0].grossWeight,
  3489. netWeight: boxRows[0].netWeight,
  3490. rolls: boxRows[0].rolls,
  3491. rowCount: boxRows.length,
  3492. details: boxRows.map(r => ({
  3493. _detailKey: r._detailKey,
  3494. itemNo: r.itemNo,
  3495. poNo: r.poNo,
  3496. pn: r.pn,
  3497. qty: r.qty,
  3498. detailRolls: r.detailRolls
  3499. }))
  3500. })
  3501. }
  3502. })
  3503. this.mergeBoxMergeHistory.push(mergeHistoryItem)
  3504. // 使用第一个箱的序号作为合并后的序号
  3505. const targetItemNo = this.mergeBoxSelection[0].item_no
  3506. const targetBoxKey = this.mergeBoxSelection[0]._boxKey
  3507. // 计算合并后的累加值
  3508. let totalBoxQty = 0
  3509. let totalGrossWeight = 0
  3510. let totalNetWeight = 0
  3511. let totalRolls = 0
  3512. // 按箱Key分组,计算每个箱的值
  3513. const boxMap = new Map()
  3514. rowsToMerge.forEach(row => {
  3515. if (!boxMap.has(row._boxKey)) {
  3516. boxMap.set(row._boxKey, {
  3517. box_qty: parseFloat(row.box_qty) || 0,
  3518. grossWeight: parseFloat(row.grossWeight) || 0,
  3519. netWeight: parseFloat(row.netWeight) || 0,
  3520. rolls: parseFloat(row.rolls) || 0
  3521. })
  3522. }
  3523. })
  3524. // 累加所有箱的值
  3525. boxMap.forEach(boxData => {
  3526. totalBoxQty += boxData.box_qty
  3527. totalGrossWeight += boxData.grossWeight
  3528. totalNetWeight += boxData.netWeight
  3529. })
  3530. // 累加所有明细的rolls
  3531. rowsToMerge.forEach(row => {
  3532. if (row.detailRolls && row.detailRolls > 0) {
  3533. totalRolls += parseFloat(row.detailRolls)
  3534. }
  3535. })
  3536. // 四舍五入取整(与装箱按钮保持一致)
  3537. const finalRolls = Math.round(totalRolls)
  3538. // 更新所有被合并的行
  3539. rowsToMerge.forEach((row, index) => {
  3540. row.item_no = targetItemNo
  3541. row._boxKey = targetBoxKey
  3542. row._isFirstRowOfBox = index === 0
  3543. row._rowSpan = index === 0 ? rowsToMerge.length : 0
  3544. // 所有行使用累加后的值
  3545. row.box_qty = totalBoxQty
  3546. row.grossWeight = parseFloat(totalGrossWeight.toFixed(3))
  3547. row.netWeight = parseFloat(totalNetWeight.toFixed(3))
  3548. row.rolls = finalRolls
  3549. })
  3550. // 合并后重新编号所有箱
  3551. this.renumberBoxes()
  3552. // 按序号重新排序表格数据
  3553. this.sortTableDataByItemNo()
  3554. // 清空选择
  3555. this.$refs.mergeBoxTable.clearSelection()
  3556. this.mergeBoxSelection = []
  3557. this.$message.success(`已合并 ${selectedBoxKeys.length} 个箱(箱数: ${totalBoxQty}, 毛重: ${totalGrossWeight.toFixed(3)}, 净重: ${totalNetWeight.toFixed(3)}),当前共 ${this.getUniqueBoxCount()} 个箱`)
  3558. },
  3559. /**
  3560. * 取消选中箱的合并
  3561. */
  3562. doUnmergeSelectedBoxes() {
  3563. if (this.mergeBoxSelection.length === 0) {
  3564. this.$message.warning('请先选择要取消合并的箱')
  3565. return
  3566. }
  3567. const selectedBoxKeys = this.mergeBoxSelection.map(row => row._boxKey)
  3568. // 找到选中箱的所有明细
  3569. const rowsToUnmerge = this.mergeBoxTableData.filter(row =>
  3570. selectedBoxKeys.includes(row._boxKey) && row._hasDetail
  3571. )
  3572. if (rowsToUnmerge.length === 0) {
  3573. this.$message.warning('所选箱没有明细数据')
  3574. return
  3575. }
  3576. // 获取原箱的序号,用于为新箱分配临时序号
  3577. const originalItemNo = rowsToUnmerge[0].item_no
  3578. // 为每条明细创建独立的箱,恢复成初始化时的原始数据
  3579. const newRows = []
  3580. rowsToUnmerge.forEach((row, index) => {
  3581. const newBoxKey = `box_${Date.now()}_${index}`
  3582. // 从mergeBoxOriginalData恢复该明细的原始数据
  3583. const detailOriginalData = this.mergeBoxOriginalData[row._detailKey]
  3584. let box_qty, grossWeight, netWeight, rolls, detailRolls
  3585. // 始终使用缓存的包装属性重新计算(确保恢复到初始值)
  3586. const rollQty = row.rollQtyCache || 0
  3587. const boxRolls = row.boxRollsCache || 0
  3588. const boxWeight = row.boxWeightCache || 0
  3589. const qty = row.qty || 0
  3590. // 恢复明细rolls
  3591. if (detailOriginalData && detailOriginalData.detailRolls !== undefined) {
  3592. detailRolls = detailOriginalData.detailRolls
  3593. } else if (rollQty > 0) {
  3594. detailRolls = parseFloat((qty / rollQty).toFixed(4))
  3595. } else {
  3596. detailRolls = 0
  3597. }
  3598. // 计算总rolls(初始时每箱只有一条明细)
  3599. rolls = Math.round(detailRolls)
  3600. // 计算箱数(向上取整,不允许小数箱)
  3601. if (rollQty > 0 && boxRolls > 0) {
  3602. const eaPerBox = rollQty * boxRolls
  3603. box_qty = Math.ceil(qty / eaPerBox)
  3604. } else {
  3605. box_qty = 1
  3606. }
  3607. // 计算毛重
  3608. if (boxWeight > 0) {
  3609. grossWeight = parseFloat((box_qty * boxWeight).toFixed(3))
  3610. } else {
  3611. grossWeight = 0
  3612. }
  3613. // 计算净重
  3614. netWeight = parseFloat((grossWeight - (box_qty / 2)).toFixed(3))
  3615. const newRow = {
  3616. ...row,
  3617. _boxKey: newBoxKey,
  3618. _isFirstRowOfBox: true,
  3619. _rowSpan: 1,
  3620. item_no: originalItemNo + index * 0.001, // 使用原序号加小数,保持顺序
  3621. box_qty: box_qty,
  3622. grossWeight: grossWeight,
  3623. netWeight: netWeight,
  3624. rolls: rolls,
  3625. detailRolls: detailRolls // 恢复明细rolls
  3626. }
  3627. newRows.push(newRow)
  3628. // 为新箱保存原始数据(用于后续编辑)
  3629. this.mergeBoxOriginalData[newBoxKey] = {
  3630. box_qty: box_qty,
  3631. grossWeight: grossWeight,
  3632. netWeight: netWeight,
  3633. rolls: rolls,
  3634. boxWeight: boxWeight
  3635. }
  3636. })
  3637. // 删除旧的行
  3638. selectedBoxKeys.forEach(boxKey => {
  3639. for (let i = this.mergeBoxTableData.length - 1; i >= 0; i--) {
  3640. if (this.mergeBoxTableData[i]._boxKey === boxKey) {
  3641. this.mergeBoxTableData.splice(i, 1)
  3642. }
  3643. }
  3644. })
  3645. // 添加新的行
  3646. this.mergeBoxTableData.push(...newRows)
  3647. // 重新编号
  3648. this.renumberBoxes()
  3649. // 按序号重新排序表格数据
  3650. this.sortTableDataByItemNo()
  3651. // 清空选择
  3652. this.$refs.mergeBoxTable.clearSelection()
  3653. this.mergeBoxSelection = []
  3654. this.$message.success(`已取消合并,拆分为 ${newRows.length} 个独立的箱,当前共 ${this.getUniqueBoxCount()} 个箱`)
  3655. },
  3656. /**
  3657. * 重新编号所有箱
  3658. */
  3659. renumberBoxes() {
  3660. // 获取所有唯一的箱,并记录每个箱在表格中第一次出现的位置
  3661. const boxKeysWithIndex = []
  3662. const seenBoxKeys = new Set()
  3663. this.mergeBoxTableData.forEach((row, index) => {
  3664. if (!seenBoxKeys.has(row._boxKey)) {
  3665. seenBoxKeys.add(row._boxKey)
  3666. boxKeysWithIndex.push({
  3667. boxKey: row._boxKey,
  3668. item_no: row.item_no,
  3669. firstIndex: index // 在表格中第一次出现的位置
  3670. })
  3671. }
  3672. })
  3673. // 按当前序号排序,如果序号相同则按在表格中出现的位置排序
  3674. const sortedBoxKeys = boxKeysWithIndex.sort((a, b) => {
  3675. if (a.item_no !== b.item_no) {
  3676. return a.item_no - b.item_no
  3677. }
  3678. // 序号相同时,按在表格中的位置排序
  3679. return a.firstIndex - b.firstIndex
  3680. })
  3681. // 重新分配序号
  3682. sortedBoxKeys.forEach((boxInfo, index) => {
  3683. const newItemNo = index + 1
  3684. this.mergeBoxTableData.forEach(row => {
  3685. if (row._boxKey === boxInfo.boxKey) {
  3686. row.item_no = newItemNo
  3687. }
  3688. })
  3689. })
  3690. // 更新下一个序号
  3691. this.nextItemNo = sortedBoxKeys.length + 1
  3692. },
  3693. /**
  3694. * 按序号对表格数据重新排序
  3695. */
  3696. sortTableDataByItemNo() {
  3697. this.mergeBoxTableData.sort((a, b) => {
  3698. // 先按序号排序
  3699. if (a.item_no !== b.item_no) {
  3700. return a.item_no - b.item_no
  3701. }
  3702. // 序号相同时,保持原有顺序(同一箱内的明细)
  3703. return 0
  3704. })
  3705. },
  3706. /**
  3707. * 获取唯一箱数量
  3708. */
  3709. getUniqueBoxCount() {
  3710. const boxKeys = new Set(this.mergeBoxTableData.map(row => row._boxKey))
  3711. return boxKeys.size
  3712. },
  3713. /**
  3714. * 表格行合并方法
  3715. */
  3716. mergeBoxSpanMethod({ row, column, rowIndex, columnIndex }) {
  3717. // Box信息列(前6列:复选框、序号、箱数、毛重、净重、总Rolls)需要合并
  3718. if (columnIndex < 6) {
  3719. if (row._isFirstRowOfBox) {
  3720. return {
  3721. rowspan: row._rowSpan,
  3722. colspan: 1
  3723. };
  3724. } else {
  3725. return {
  3726. rowspan: 0,
  3727. colspan: 0
  3728. };
  3729. }
  3730. }
  3731. return {
  3732. rowspan: 1,
  3733. colspan: 1
  3734. };
  3735. },
  3736. /**
  3737. * 获取行样式类名
  3738. */
  3739. getMergeBoxRowClassName({ row }) {
  3740. const classes = [];
  3741. // 检查该行是否有Box修改
  3742. if (this.mergeBoxModifiedBoxes[row._boxKey]) {
  3743. classes.push('box-modified-row');
  3744. }
  3745. // 检查该行是否有明细修改
  3746. if (row._hasDetail && this.mergeBoxModifiedDetails[row._detailKey]) {
  3747. classes.push('detail-modified-row');
  3748. }
  3749. return classes.join(' ');
  3750. },
  3751. /**
  3752. * 检查Box字段是否被修改
  3753. */
  3754. isBoxFieldModified(row, field) {
  3755. const boxKey = row._boxKey;
  3756. return this.mergeBoxModifiedBoxes[boxKey] &&
  3757. this.mergeBoxModifiedBoxes[boxKey][field] !== undefined;
  3758. },
  3759. /**
  3760. * 检查明细字段是否被修改
  3761. */
  3762. isDetailFieldModified(row, field) {
  3763. if (!row._hasDetail) return false;
  3764. const detailKey = row._detailKey;
  3765. return this.mergeBoxModifiedDetails[detailKey] &&
  3766. this.mergeBoxModifiedDetails[detailKey][field] !== undefined;
  3767. },
  3768. /**
  3769. * 箱数输入时联动计算毛重和净重
  3770. */
  3771. onMergeBoxQtyInput(row) {
  3772. if (this._isMergeCalculating) return;
  3773. this._isMergeCalculating = true;
  3774. try {
  3775. const boxKey = row._boxKey;
  3776. const newBoxQty = Math.ceil(parseFloat(row.box_qty) || 0);
  3777. row.box_qty = newBoxQty;
  3778. // 先从原始数据获取,如果没有则从row缓存获取
  3779. let boxWeight = 0;
  3780. const originalData = this.mergeBoxOriginalData[boxKey];
  3781. if (originalData && originalData.boxWeight) {
  3782. boxWeight = parseFloat(originalData.boxWeight);
  3783. } else if (row.boxWeightCache) {
  3784. boxWeight = parseFloat(row.boxWeightCache);
  3785. }
  3786. if (boxWeight > 0 && newBoxQty > 0) {
  3787. const newGrossWeight = boxWeight * newBoxQty;
  3788. const newNetWeight = newGrossWeight - (newBoxQty / 2);
  3789. row.grossWeight = parseFloat(newGrossWeight.toFixed(3));
  3790. row.netWeight = parseFloat(newNetWeight.toFixed(3));
  3791. // 同步更新所有同Box的行
  3792. this.mergeBoxTableData.forEach(r => {
  3793. if (r._boxKey === boxKey) {
  3794. r.box_qty = newBoxQty;
  3795. r.grossWeight = row.grossWeight;
  3796. r.netWeight = row.netWeight;
  3797. }
  3798. });
  3799. this.onMergeBoxFieldChange(row, 'grossWeight');
  3800. this.onMergeBoxFieldChange(row, 'netWeight');
  3801. }
  3802. } finally {
  3803. this._isMergeCalculating = false;
  3804. }
  3805. },
  3806. /**
  3807. * 毛重输入时联动计算净重
  3808. */
  3809. onMergeGrossWeightInput(row) {
  3810. if (this._isMergeCalculating) return;
  3811. this._isMergeCalculating = true;
  3812. try {
  3813. const grossWeight = parseFloat(row.grossWeight) || 0;
  3814. const boxQty = parseFloat(row.box_qty) || 0;
  3815. const netWeight = grossWeight - (boxQty / 2);
  3816. row.netWeight = netWeight.toFixed(2);
  3817. // 同步更新所有同Box的行
  3818. const boxKey = row._boxKey;
  3819. this.mergeBoxTableData.forEach(r => {
  3820. if (r._boxKey === boxKey) {
  3821. r.grossWeight = row.grossWeight;
  3822. r.netWeight = row.netWeight;
  3823. }
  3824. });
  3825. this.onMergeBoxFieldChange(row, 'netWeight');
  3826. } finally {
  3827. this._isMergeCalculating = false;
  3828. }
  3829. },
  3830. /**
  3831. * 净重输入时联动计算毛重
  3832. */
  3833. onMergeNetWeightInput(row) {
  3834. if (this._isMergeCalculating) return;
  3835. this._isMergeCalculating = true;
  3836. try {
  3837. const netWeight = parseFloat(row.netWeight) || 0;
  3838. const boxQty = parseFloat(row.box_qty) || 0;
  3839. const grossWeight = netWeight + (boxQty / 2);
  3840. row.grossWeight = grossWeight.toFixed(2);
  3841. // 同步更新所有同Box的行
  3842. const boxKey = row._boxKey;
  3843. this.mergeBoxTableData.forEach(r => {
  3844. if (r._boxKey === boxKey) {
  3845. r.netWeight = row.netWeight;
  3846. r.grossWeight = row.grossWeight;
  3847. }
  3848. });
  3849. this.onMergeBoxFieldChange(row, 'grossWeight');
  3850. } finally {
  3851. this._isMergeCalculating = false;
  3852. }
  3853. },
  3854. /**
  3855. * Box字段变化处理
  3856. */
  3857. onMergeBoxFieldChange(row, field) {
  3858. const boxKey = row._boxKey;
  3859. const original = this.mergeBoxOriginalData[boxKey];
  3860. if (!original) return;
  3861. const currentValue = String(row[field]);
  3862. const originalValue = String(original[field]);
  3863. if (currentValue !== originalValue) {
  3864. if (!this.mergeBoxModifiedBoxes[boxKey]) {
  3865. this.$set(this.mergeBoxModifiedBoxes, boxKey, {});
  3866. }
  3867. this.$set(this.mergeBoxModifiedBoxes[boxKey], field, {
  3868. oldValue: original[field],
  3869. newValue: row[field]
  3870. });
  3871. // 同步更新所有同Box的行
  3872. this.mergeBoxTableData.forEach(r => {
  3873. if (r._boxKey === boxKey) {
  3874. r[field] = row[field];
  3875. }
  3876. });
  3877. } else {
  3878. if (this.mergeBoxModifiedBoxes[boxKey]) {
  3879. this.$delete(this.mergeBoxModifiedBoxes[boxKey], field);
  3880. if (Object.keys(this.mergeBoxModifiedBoxes[boxKey]).length === 0) {
  3881. this.$delete(this.mergeBoxModifiedBoxes, boxKey);
  3882. }
  3883. }
  3884. }
  3885. },
  3886. /**
  3887. * 明细字段变化处理
  3888. */
  3889. onMergeDetailFieldChange(row, field) {
  3890. if (!row._hasDetail) return;
  3891. const detailKey = row._detailKey;
  3892. const original = this.mergeBoxOriginalData[detailKey];
  3893. if (!original) return;
  3894. const currentValue = String(row[field]);
  3895. const originalValue = String(original[field]);
  3896. if (currentValue !== originalValue) {
  3897. if (!this.mergeBoxModifiedDetails[detailKey]) {
  3898. this.$set(this.mergeBoxModifiedDetails, detailKey, {
  3899. row: row
  3900. });
  3901. }
  3902. this.$set(this.mergeBoxModifiedDetails[detailKey], field, {
  3903. oldValue: original[field],
  3904. newValue: row[field]
  3905. });
  3906. } else {
  3907. if (this.mergeBoxModifiedDetails[detailKey]) {
  3908. this.$delete(this.mergeBoxModifiedDetails[detailKey], field);
  3909. const remainingFields = Object.keys(this.mergeBoxModifiedDetails[detailKey])
  3910. .filter(k => k !== 'row');
  3911. if (remainingFields.length === 0) {
  3912. this.$delete(this.mergeBoxModifiedDetails, detailKey);
  3913. }
  3914. }
  3915. }
  3916. },
  3917. /**
  3918. * 明细Rolls输入事件处理 - 自动计算总Rolls
  3919. */
  3920. onDetailRollsInput(row) {
  3921. this.$nextTick(() => {
  3922. this.calculateBoxTotalRolls(row);
  3923. });
  3924. },
  3925. /**
  3926. * 计算同一Box下所有明细Rolls的总和
  3927. * 计算规则总Rolls = Sum(所有明细rolls)然后四舍五入取整
  3928. */
  3929. calculateBoxTotalRolls(row) {
  3930. const boxKey = row._boxKey;
  3931. const boxRows = this.mergeBoxTableData.filter(r => r._boxKey === boxKey && r._hasDetail);
  3932. let totalDetailRolls = 0;
  3933. let hasDetailRolls = false;
  3934. boxRows.forEach(r => {
  3935. const rollsValue = parseFloat(r.detailRolls);
  3936. if (!isNaN(rollsValue) && rollsValue > 0) {
  3937. totalDetailRolls += rollsValue;
  3938. hasDetailRolls = true;
  3939. }
  3940. });
  3941. // 四舍五入取整(与装箱按钮保持一致)
  3942. const newRolls = hasDetailRolls ? Math.round(totalDetailRolls) : 0;
  3943. this.mergeBoxTableData.forEach(r => {
  3944. if (r._boxKey === boxKey) {
  3945. this.$set(r, 'rolls', newRolls);
  3946. }
  3947. });
  3948. this.onMergeBoxFieldChange(row, 'rolls');
  3949. },
  3950. /**
  3951. * 检查Box是否有明细Rolls值
  3952. */
  3953. hasDetailRolls(row) {
  3954. const boxKey = row._boxKey;
  3955. const boxRows = this.mergeBoxTableData.filter(r => r._boxKey === boxKey && r._hasDetail);
  3956. return boxRows.some(r => {
  3957. const rollsValue = parseFloat(r.detailRolls);
  3958. return !isNaN(rollsValue) && rollsValue > 0;
  3959. });
  3960. },
  3961. /**
  3962. * 明细数量变化时重新计算rolls
  3963. */
  3964. onDetailQtyChange(row) {
  3965. // 如果有缓存的每卷数量,重新计算rolls
  3966. if (row.rollQtyCache && row.rollQtyCache > 0 && row.qty > 0) {
  3967. const newRolls = parseFloat((row.qty / row.rollQtyCache).toFixed(4))
  3968. this.$set(row, 'detailRolls', newRolls)
  3969. // 更新总Rolls
  3970. this.$nextTick(() => {
  3971. this.calculateBoxTotalRolls(row)
  3972. })
  3973. }
  3974. },
  3975. /**
  3976. * 获取非整箱箱数据按明细数量与每箱EA关系判断
  3977. */
  3978. getNonWholeBoxDetails() {
  3979. const nonWholeBoxMap = new Map()
  3980. const checkedDetailKeys = new Set()
  3981. this.mergeBoxTableData.forEach(row => {
  3982. if (!row._hasDetail || !row._detailKey || checkedDetailKeys.has(row._detailKey)) {
  3983. return
  3984. }
  3985. checkedDetailKeys.add(row._detailKey)
  3986. const qty = Number(row.qty)
  3987. const rollQty = Number(row.rollQtyCache)
  3988. const boxRolls = Number(row.boxRollsCache)
  3989. if (!(qty > 0) || !(rollQty > 0) || !(boxRolls > 0)) {
  3990. return
  3991. }
  3992. const eaPerBox = rollQty * boxRolls
  3993. if (!(eaPerBox > 0)) {
  3994. return
  3995. }
  3996. const boxRatio = qty / eaPerBox
  3997. const isWholeBox = Math.abs(boxRatio - Math.round(boxRatio)) < 0.000001
  3998. if (!isWholeBox) {
  3999. const boxKey = row._boxKey || `${row.item_no}_${row.pn || row._detailKey}`
  4000. if (!nonWholeBoxMap.has(boxKey)) {
  4001. nonWholeBoxMap.set(boxKey, {
  4002. itemNo: row.item_no,
  4003. pn: row.pn,
  4004. boxQty: parseFloat(boxRatio.toFixed(4))
  4005. })
  4006. }
  4007. }
  4008. })
  4009. return Array.from(nonWholeBoxMap.values())
  4010. },
  4011. /**
  4012. * 获取非整卷明细数据按明细Rolls是否为整数判断
  4013. */
  4014. getNonWholeRollDetails() {
  4015. const nonWholeRollMap = new Map()
  4016. const checkedDetailKeys = new Set()
  4017. this.mergeBoxTableData.forEach(row => {
  4018. if (!row._hasDetail || !row._detailKey || checkedDetailKeys.has(row._detailKey)) {
  4019. return
  4020. }
  4021. checkedDetailKeys.add(row._detailKey)
  4022. const cinvcname = (row.cinvcname || '').toString().trim().toUpperCase()
  4023. if (cinvcname !== 'WET') {
  4024. return
  4025. }
  4026. const detailRolls = Number(row.detailRolls)
  4027. if (!(detailRolls > 0)) {
  4028. return
  4029. }
  4030. const isWholeRoll = Math.abs(detailRolls - Math.round(detailRolls)) < 0.000001
  4031. if (!isWholeRoll) {
  4032. const detailKey = row._detailKey
  4033. if (!nonWholeRollMap.has(detailKey)) {
  4034. nonWholeRollMap.set(detailKey, {
  4035. itemNo: row.item_no,
  4036. pn: row.pn,
  4037. detailRolls: parseFloat(detailRolls.toFixed(4))
  4038. })
  4039. }
  4040. }
  4041. })
  4042. return Array.from(nonWholeRollMap.values())
  4043. },
  4044. /**
  4045. * 保存合箱批量编辑
  4046. */
  4047. async saveMergeBoxEdit() {
  4048. // 允许直接保存,即使没有修改
  4049. this.mergeBoxSaving = true
  4050. try {
  4051. // 构造提交数据 - 按箱分组
  4052. const boxMap = new Map()
  4053. // 遍历表格数据,按箱分组
  4054. this.mergeBoxTableData.forEach(row => {
  4055. const boxKey = row._boxKey
  4056. if (!boxMap.has(boxKey)) {
  4057. boxMap.set(boxKey, {
  4058. item_no: row.item_no,
  4059. box_qty: Math.ceil(Number(row.box_qty) || 0),
  4060. grossWeight: row.grossWeight,
  4061. netWeight: row.netWeight,
  4062. rolls: row.rolls,
  4063. details: []
  4064. })
  4065. }
  4066. // 添加明细
  4067. if (row._hasDetail) {
  4068. boxMap.get(boxKey).details.push({
  4069. itemNo: row.itemNo,
  4070. poNo: row.poNo,
  4071. pn: row.pn,
  4072. qty: row.qty,
  4073. detailRolls: row.detailRolls,
  4074. readyDate: row.readyDate
  4075. })
  4076. }
  4077. })
  4078. // 转换为数组
  4079. const boxList = Array.from(boxMap.values())
  4080. if (boxList.length === 0) {
  4081. this.$message.warning('没有可保存的箱数据')
  4082. this.mergeBoxSaving = false
  4083. return
  4084. }
  4085. const nonWholeDetails = this.getNonWholeBoxDetails()
  4086. const nonWholeRollDetails = this.getNonWholeRollDetails()
  4087. if (nonWholeDetails.length > 0 || nonWholeRollDetails.length > 0) {
  4088. const escapeHtml = (value) => String(value)
  4089. .replace(/&/g, '&amp;')
  4090. .replace(/</g, '&lt;')
  4091. .replace(/>/g, '&gt;')
  4092. .replace(/"/g, '&quot;')
  4093. .replace(/'/g, '&#39;')
  4094. const warningSections = []
  4095. if (nonWholeDetails.length > 0) {
  4096. const boxPreviewLines = nonWholeDetails
  4097. .map(detail => `${escapeHtml(detail.itemNo)} / PN:${escapeHtml(detail.pn || '-')} / 箱数:${escapeHtml(detail.boxQty)}`)
  4098. .join('<br/>')
  4099. warningSections.push(
  4100. `<div style="padding: 8px 10px; border: 1px solid #ebeef5; border-radius: 4px; margin-bottom: 8px;">
  4101. <div style="font-weight: 600; color: #e6a23c; margin-bottom: 4px;">非整箱数据${nonWholeDetails.length}</div>
  4102. <div>${boxPreviewLines}</div>
  4103. </div>`
  4104. )
  4105. }
  4106. if (nonWholeRollDetails.length > 0) {
  4107. const rollPreviewLines = nonWholeRollDetails
  4108. .map(detail => `${escapeHtml(detail.itemNo)} / PN:${escapeHtml(detail.pn || '-')} / Rolls:${escapeHtml(detail.detailRolls)}`)
  4109. .join('<br/>')
  4110. warningSections.push(
  4111. `<div style="padding: 8px 10px; border: 1px solid #ebeef5; border-radius: 4px; margin-bottom: 8px;">
  4112. <div style="font-weight: 600; color: #e6a23c; margin-bottom: 4px;">WET产品非整卷数据${nonWholeRollDetails.length}</div>
  4113. <div>${rollPreviewLines}</div>
  4114. </div>`
  4115. )
  4116. }
  4117. const confirmMessage = `检测到需要确认的装箱数据:<br/>${warningSections.join('')}<div style="margin-top: 4px;">请确认是否继续装箱。</div>`
  4118. try {
  4119. await this.$confirm(
  4120. confirmMessage,
  4121. '装箱确认',
  4122. {
  4123. confirmButtonText: '确认继续',
  4124. cancelButtonText: '取消',
  4125. type: 'warning',
  4126. dangerouslyUseHTMLString: true
  4127. }
  4128. )
  4129. } catch (confirmError) {
  4130. return
  4131. }
  4132. }
  4133. const mergeData = {
  4134. site: this.currentRow.site,
  4135. buNo: this.currentRow.buNo,
  4136. delNo: this.currentRow.delNo,
  4137. createBy: this.$store.state.user.name,
  4138. boxList: boxList
  4139. }
  4140. // 调用合箱API
  4141. const response = await mergeBox(mergeData)
  4142. if (response.data && response.data.code === 0) {
  4143. this.$message.success(`成功保存 ${boxList.length} 个箱的数据`)
  4144. this.mergeBoxDialogVisible = false
  4145. // 刷新当前tab表格
  4146. this.refreshCurrentTabTable()
  4147. // 刷新上方的发货通知单列表
  4148. this.searchTable()
  4149. } else {
  4150. this.$alert(response.data.msg || '保存失败', '错误', {
  4151. confirmButtonText: '确定'
  4152. })
  4153. }
  4154. } catch (error) {
  4155. console.error('保存失败:', error)
  4156. this.$message.error('保存失败: ' + (error.message || '未知错误'))
  4157. } finally {
  4158. this.mergeBoxSaving = false
  4159. }
  4160. },
  4161. openPalletDialog () {
  4162. //请求
  4163. this.searchPalletList();
  4164. },
  4165. closePalletDialog () {
  4166. this.palletList = []
  4167. this.palletFlag = false
  4168. },
  4169. searchPalletList () {
  4170. this.palletData.buNo = this.palletModelData.buNo
  4171. searchPalletList(this.palletData).then(({data}) => {
  4172. if (data && data.code === 0){
  4173. this.palletList = data.rows;
  4174. }
  4175. })
  4176. },
  4177. palletRowDblclick (row) {
  4178. this.palletModelData.pallet = row.palletNo
  4179. this.palletFlag = false
  4180. },
  4181. // 栈板维护相关方法
  4182. palletMaintenance() {
  4183. if(this.currentRow.site===''||this.currentRow.site==null){
  4184. this.$alert('请先选择发货通知单!', '错误', {
  4185. confirmButtonText: '确定'
  4186. })
  4187. return false
  4188. }
  4189. // 重置栈板记录
  4190. this.palletMaintenanceRecords = []
  4191. // 默认根据buNo获取全部栈板
  4192. this.loadAllPalletsForMaintenance()
  4193. this.palletMaintenanceModelFlag = true
  4194. },
  4195. // 根据buNo加载全部栈板用于维护
  4196. loadAllPalletsForMaintenance() {
  4197. let searchData = {
  4198. palletType: '', // 不限制栈板类型,获取全部
  4199. buNo: this.currentRow.buNo
  4200. }
  4201. searchPalletList(searchData).then(({data}) => {
  4202. if (data.code === 0) {
  4203. const pallets = data.rows || []
  4204. // 为每个栈板创建一条记录
  4205. this.palletMaintenanceRecords = pallets.map(pallet => ({
  4206. pallet: pallet.palletNo,
  4207. palletType: pallet.palletType,
  4208. palletQty: '', // 默认为空,用户需要输入
  4209. height: '' // 使用栈板的默认高度
  4210. }))
  4211. }
  4212. }).catch(error => {
  4213. console.error('加载栈板列表失败:', error)
  4214. // 如果加载失败,至少添加一行空记录
  4215. this.palletMaintenanceRecords = [{
  4216. pallet: '',
  4217. palletType: '',
  4218. palletQty: '',
  4219. height: ''
  4220. }]
  4221. })
  4222. },
  4223. savePalletMaintenance() {
  4224. // 过滤出托数大于0的栈板记录
  4225. const validPalletRecords = this.palletMaintenanceRecords.filter(record => {
  4226. return record.palletQty && parseFloat(record.palletQty) > 0
  4227. })
  4228. if (validPalletRecords.length === 0) {
  4229. this.$alert('请至少输入一条有效的栈板记录!', '错误', {
  4230. confirmButtonText: '确定'
  4231. })
  4232. return false
  4233. }
  4234. // 验证有效的栈板记录
  4235. for (let i = 0; i < validPalletRecords.length; i++) {
  4236. const record = validPalletRecords[i]
  4237. if (!record.pallet) {
  4238. this.$alert(`栈板不能为空!`, '错误', {
  4239. confirmButtonText: '确定'
  4240. })
  4241. return false
  4242. }
  4243. if (!record.height || record.height <= 0) {
  4244. this.$alert(`栈板高度必须大于0!`, '错误', {
  4245. confirmButtonText: '确定'
  4246. })
  4247. return false
  4248. }
  4249. }
  4250. this.saveLoading = true
  4251. // 这里只新增栈板记录,不做其他事情
  4252. let saveData = {
  4253. site: this.currentRow.site,
  4254. buNo: this.currentRow.buNo,
  4255. delNo: this.currentRow.delNo,
  4256. palletRecords: JSON.stringify(validPalletRecords),
  4257. }
  4258. // 使用相同的API,但传递maintenanceOnly标识
  4259. savePalletMaintenance(saveData).then(({data}) => {
  4260. if (data && data.code === 0) {
  4261. this.searchTable()
  4262. this.refreshCurrentTabTable()
  4263. this.palletMaintenanceModelFlag = false;
  4264. this.$message({
  4265. message: '栈板记录新增成功',
  4266. type: 'success',
  4267. duration: 1500,
  4268. onClose: () => {}
  4269. })
  4270. this.saveLoading = false
  4271. } else {
  4272. this.$alert(data.msg, '错误', {
  4273. confirmButtonText: '确定'
  4274. })
  4275. this.saveLoading = false
  4276. }
  4277. }).catch((error) => {
  4278. console.error('保存失败:', error)
  4279. this.$message.error('保存失败,请重试')
  4280. }).finally(() => {
  4281. this.saveLoading = false
  4282. })
  4283. },
  4284. getSummaries(param) {
  4285. const { columns } = param;
  4286. const sums = [];
  4287. columns.forEach((column, index) => {
  4288. if (index === 0) {
  4289. sums[index] = '合计';
  4290. return;
  4291. }
  4292. let sumDataList = this.dataList4.filter(item => item.palletQty>0);
  4293. const values = sumDataList.map(item => Number(item[column.property]));
  4294. if (!values.every(value => isNaN(value))) {
  4295. switch(column.property) {
  4296. case 'palletQty':
  4297. sums[index] = `${values.reduce((a, b) => a + b, 0)}`;
  4298. break;
  4299. case 'weight':
  4300. sums[index] = `${values.reduce((a, b) => a + b, 0)}`;
  4301. break;
  4302. default:
  4303. sums[index] = '';
  4304. }
  4305. } else {
  4306. sums[index] = '';
  4307. }
  4308. });
  4309. this.$nextTick(() => this.$refs.detailTable.doLayout());// 强制刷新布局, 否则会被表格覆盖
  4310. return sums;
  4311. },
  4312. getDetailSummaries(param) {
  4313. const { columns } = param;
  4314. const sums = [];
  4315. columns.forEach((column, index) => {
  4316. if (index === 0) {
  4317. sums[index] = '合计';
  4318. return;
  4319. }
  4320. let sumDataList = this.dataList2.filter(item => item.qty>0);
  4321. const values = sumDataList.map(item => Number(item[column.property]));
  4322. if (!values.every(value => isNaN(value))) {
  4323. switch(column.property) {
  4324. case 'qty':
  4325. sums[index] = `${values.reduce((a, b) => a + b, 0)}`;
  4326. break;
  4327. case 'ttlAmount':
  4328. sums[index] = `${values.reduce((a, b) => a + b, 0).toFixed(2)}`;
  4329. break;
  4330. case 'sumPrice':
  4331. sums[index] = `${values.reduce((a, b) => a + b, 0).toFixed(2)}`;
  4332. break;
  4333. default:
  4334. sums[index] = '';
  4335. }
  4336. } else {
  4337. sums[index] = '';
  4338. }
  4339. });
  4340. this.$nextTick(() => this.$refs.cloDetailTable.doLayout());// 强制刷新布局, 否则会被表格覆盖
  4341. return sums;
  4342. },
  4343. /**
  4344. * 保存选中行到本地存储
  4345. * 使用页面路径和用户名作为存储键的一部分确保不同页面和用户的选择互不影响
  4346. */
  4347. saveSelectedRowToStorage() {
  4348. try {
  4349. const storageKey = `codelnotifyConfirm_selected_row_${this.$store.state.user.name}`;
  4350. localStorage.setItem(storageKey, this.selectedRowKey);
  4351. console.log(`[确认页面行选择持久化] 已保存选中行: ${this.selectedRowKey}`);
  4352. } catch (error) {
  4353. console.warn('保存选中行状态失败:', error);
  4354. }
  4355. },
  4356. /**
  4357. * 从本地存储恢复选中行
  4358. * @returns {Object|null} 返回匹配的行数据如果没有找到则返回null
  4359. */
  4360. restoreSelectedRow() {
  4361. try {
  4362. const storageKey = `codelnotifyConfirm_selected_row_${this.$store.state.user.name}`;
  4363. const savedRowKey = localStorage.getItem(storageKey);
  4364. // 检查必要的条件
  4365. if (!savedRowKey) {
  4366. console.log('[确认页面行选择持久化] 没有保存的选中行');
  4367. return null;
  4368. }
  4369. if (!this.dataList || this.dataList.length === 0) {
  4370. console.log('[确认页面行选择持久化] 数据列表为空,无法恢复选中行');
  4371. return null;
  4372. }
  4373. // 在当前数据列表中查找匹配的行
  4374. const matchedRow = this.dataList.find(row => row && row.delNo === savedRowKey);
  4375. if (matchedRow) {
  4376. this.selectedRowKey = savedRowKey;
  4377. console.log(`[确认页面行选择持久化] 已恢复选中行: ${savedRowKey}`);
  4378. return matchedRow;
  4379. } else {
  4380. console.log(`[确认页面行选择持久化] 未找到匹配的行: ${savedRowKey},当前数据列表长度: ${this.dataList.length}`);
  4381. }
  4382. return null;
  4383. } catch (error) {
  4384. console.warn('恢复选中行状态失败:', error);
  4385. return null;
  4386. }
  4387. },
  4388. /**
  4389. * 清除本地存储的选中行状态
  4390. */
  4391. clearSelectedRowStorage() {
  4392. try {
  4393. const storageKey = `codelnotifyConfirm_selected_row_${this.$store.state.user.name}`;
  4394. localStorage.removeItem(storageKey);
  4395. this.selectedRowKey = null;
  4396. } catch (error) {
  4397. console.warn('清除选中行状态失败:', error);
  4398. }
  4399. },
  4400. },
  4401. activated() {
  4402. this.searchTable()
  4403. },
  4404. created() {
  4405. this.getBu ()
  4406. // 动态列
  4407. this.getTableUserColumn(this.$route.meta.menuId+'table1',1)
  4408. // 初始化时从本地存储加载选中行状态
  4409. try {
  4410. const storageKey = `codelnotifyConfirm_selected_row_${this.$store.state.user.name}`;
  4411. const savedRowKey = localStorage.getItem(storageKey);
  4412. if (savedRowKey) {
  4413. this.selectedRowKey = savedRowKey;
  4414. }
  4415. } catch (error) {
  4416. console.warn('初始化选中行状态失败:', error);
  4417. }
  4418. }
  4419. }
  4420. </script>
  4421. <style lang="scss">
  4422. .warning-row td{
  4423. color: darkred !important;
  4424. }
  4425. .zxClass .cell {
  4426. line-height: 24px;
  4427. font-size: 12px;
  4428. height: 24px;
  4429. }
  4430. /* 可点击的PN样式 */
  4431. .clickable-pn {
  4432. cursor: pointer;
  4433. text-decoration: underline;
  4434. }
  4435. .clickable-pn:hover {
  4436. opacity: 0.8;
  4437. }
  4438. /* 对话框标题样式 */
  4439. .dialog-title {
  4440. display: flex;
  4441. align-items: center;
  4442. font-size: 16px;
  4443. font-weight: 500;
  4444. }
  4445. .dialog-title .el-icon-question:hover {
  4446. color: #66b1ff;
  4447. transform: scale(1.1);
  4448. transition: all 0.3s ease;
  4449. }
  4450. /* 表格头部提示图标样式 */
  4451. /deep/ .el-table th .el-icon-question:hover {
  4452. color: #409EFF;
  4453. transform: scale(1.1);
  4454. transition: all 0.2s ease;
  4455. }
  4456. /* 提示框内容样式 */
  4457. /deep/ .el-tooltip__popper {
  4458. max-width: 300px;
  4459. }
  4460. /deep/ .el-tooltip__popper .el-tooltip__content {
  4461. line-height: 1.6;
  4462. }
  4463. /deep/ .el-tooltip__popper .el-tooltip__content div {
  4464. margin-bottom: 4px;
  4465. }
  4466. /deep/ .el-tooltip__popper .el-tooltip__content div:first-child {
  4467. font-weight: bold;
  4468. margin-bottom: 8px;
  4469. color: #409EFF;
  4470. }
  4471. .pallet-dialog .section {
  4472. margin: 10px 7px;
  4473. }
  4474. .section-title {
  4475. font-size: 14px;
  4476. font-weight: bold;
  4477. color: #333;
  4478. margin-bottom: 8px;
  4479. }
  4480. .table-wrapper {
  4481. height: 300px; /* 让表格部分固定高度并滚动 */
  4482. overflow-y: auto;
  4483. }
  4484. /* ========== 合箱批量编辑弹出框样式 ========== */
  4485. /* 修复表格滚动条右侧的颜色问题 - 强制设置gutter背景色为白色 */
  4486. .el-dialog__wrapper .batch-edit-dialog .el-table th.gutter {
  4487. background-color: #f5f7fa !important;
  4488. }
  4489. /* 工具栏样式 */
  4490. .merge-box-toolbar {
  4491. display: flex;
  4492. align-items: center;
  4493. margin-bottom: 15px;
  4494. padding: 10px;
  4495. background: #f5f7fa;
  4496. border-radius: 4px;
  4497. }
  4498. .merge-box-toolbar .merge-stats {
  4499. margin-left: auto;
  4500. display: flex;
  4501. align-items: center;
  4502. }
  4503. .merge-box-toolbar .modified-count {
  4504. color: #e6a23c;
  4505. margin-left: 10px;
  4506. }
  4507. .merge-box-toolbar .modified-count b {
  4508. color: #f56c6c;
  4509. font-size: 16px;
  4510. }
  4511. /* Box信息单元格样式 */
  4512. .box-info-cell {
  4513. font-weight: 600;
  4514. color: #409eff;
  4515. font-size: 13px;
  4516. }
  4517. /* 修改过的输入框样式 */
  4518. /deep/ .batch-edit-container .modified-input .el-input__inner {
  4519. background-color: #fff7e6;
  4520. border-color: #e6a23c;
  4521. color: #e6a23c;
  4522. }
  4523. /* 修改过的行样式 */
  4524. /deep/ .batch-edit-container .box-modified-row td:nth-child(-n+6) {
  4525. background-color: #fdf6ec !important;
  4526. }
  4527. /deep/ .batch-edit-container .detail-modified-row td:nth-child(n+7) {
  4528. background-color: #fff7e6 !important;
  4529. }
  4530. /* 输入框样式 */
  4531. /deep/ .batch-edit-container .el-input--mini .el-input__inner {
  4532. text-align: center;
  4533. padding: 0 8px;
  4534. border-color: #dcdfe6;
  4535. }
  4536. /deep/ .batch-edit-container .el-input--mini .el-input__inner:focus {
  4537. border-color: #409eff;
  4538. }
  4539. /* 表格单元格内边距 */
  4540. /deep/ .batch-edit-container .el-table td {
  4541. padding: 6px 0;
  4542. }
  4543. /deep/ .batch-edit-container .el-table .cell {
  4544. padding: 0 8px;
  4545. }
  4546. /* 数字输入框隐藏上下箭头 */
  4547. /deep/ .batch-edit-container input[type="number"]::-webkit-inner-spin-button,
  4548. /deep/ .batch-edit-container input[type="number"]::-webkit-outer-spin-button {
  4549. -webkit-appearance: none;
  4550. margin: 0;
  4551. }
  4552. /deep/ .batch-edit-container input[type="number"] {
  4553. -moz-appearance: textfield;
  4554. }
  4555. /* 合并单元格的垂直居中 */
  4556. /deep/ .batch-edit-container .el-table__body td[rowspan] {
  4557. vertical-align: middle;
  4558. }
  4559. /deep/ .batch-edit-container .el-table__body td[rowspan] .cell {
  4560. display: flex;
  4561. align-items: center;
  4562. justify-content: center;
  4563. height: 100%;
  4564. }
  4565. /* 文字样式 */
  4566. /deep/ .batch-edit-container .el-table .cell span {
  4567. font-size: 13px;
  4568. color: #606266;
  4569. }
  4570. </style>