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.

4582 lines
153 KiB

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