taskIndex.html 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <!-- import CSS -->
  6. <link rel="stylesheet" href="../../css/index.css">
  7. <!-- import Vue before Element -->
  8. <script src="../../js/vue.js"></script>
  9. <!-- import JavaScript -->
  10. <script src="../../js/index.js"></script>
  11. <script src="../../js/axios.js"></script>
  12. </head>
  13. <body>
  14. <div id="app" v-cloak>
  15. <div style="padding: 20px;">
  16. <div>
  17. <div class="commonCss">
  18. <el-form :inline="true" :model="formInline" class="demo-form-inline">
  19. <el-form-item label="盘点计划名称">
  20. <el-input v-model="formInline.taskCode" placeholder="入库单号"></el-input>
  21. </el-form-item>
  22. <el-form-item>
  23. <el-button type="primary" @click="queryClick()">查询</el-button>
  24. </el-form-item>
  25. </el-form>
  26. </div>
  27. <el-table ref="singleTable" :data="migrationResultList" v-loading="loading" :border=true
  28. tooltip-effect="dark"
  29. highlight-current-row max-height="500" style="width: 100%;overflow-x: auto;"
  30. :default-sort="{prop: 'createDate', order: 'descending'}">
  31. <el-table-column prop="taskCode" label="盘点任务编码" :show-overflow-tooltip="true"></el-table-column>
  32. <el-table-column prop="planType" label="盘点类型" :show-overflow-tooltip="true">
  33. <template slot-scope="{ row }">
  34. <el-tag >
  35. {{ getInOutTypeText(row.planType) }}
  36. </el-tag>
  37. </template>
  38. </el-table-column>
  39. <el-table-column prop="status" label="状态" :show-overflow-tooltip="true">
  40. <template slot-scope="{ row }">
  41. <el-tag >
  42. {{ getStatusText(row.status) }}
  43. </el-tag>
  44. </template>
  45. </el-table-column>
  46. <el-table-column prop="startTime" label="开始时间" :show-overflow-tooltip="true"></el-table-column>
  47. <el-table-column prop="endTime" label="结束时间" :show-overflow-tooltip="true"></el-table-column>
  48. <el-table-column prop="plan_user" label="盘点人" :show-overflow-tooltip="true"></el-table-column>
  49. <el-table-column label="操作" :show-overflow-tooltip="true" fixed="right" width="430px">
  50. <template #default="scope">
  51. <!-- 这里放置操作按钮 -->
  52. <div class="button-group">
  53. <el-button type="primary" @click="toDo(scope.row.id)" icon="el-icon-check" :disabled="scope.row.status === 2">执行</el-button>
  54. <el-button type="danger" @click="orderDelete(scope.row)" icon="el-icon-delete" >删除</el-button>
  55. </div>
  56. </template>
  57. </el-table-column>
  58. </el-table>
  59. <div class="pagination-block">
  60. <el-pagination :current-page="currentPage" :page-sizes="pageSizes" :total="total"
  61. :page-size="currentPageSize"
  62. layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  63. @current-change="handleCurrentChange"/>
  64. </div>
  65. <el-dialog
  66. title="盘点"
  67. :visible.sync="dialogVisibleTask"
  68. :before-close="handleCloseTask" width="80%">
  69. <el-form :inline="true" :model="formInline" class="demo-form-inline">
  70. <el-form-item label="入库口">
  71. <el-select v-model="entryPoint" placeholder="请选择">
  72. <el-option
  73. v-for="item in options"
  74. :key="item.value"
  75. :label="item.label"
  76. :value="item.value">
  77. </el-option>
  78. </el-select>
  79. </el-form-item>
  80. <el-form-item>
  81. <el-input type="text" v-model="palletCode" placeholder="托盘编码" style="width: 100px;" :disabled="true"></el-input>
  82. </el-form-item>
  83. <el-form-item>
  84. <el-input type="text" v-model="binCode" placeholder="料箱编码" style="width: 100px;" :disabled="true"></el-input>
  85. </el-form-item>
  86. <el-form-item>
  87. <el-input type="text" v-model="inputCode" placeholder="扫码 托盘编码" @change="handleScan()" style="width: 300px" ></el-input>
  88. </el-form-item>
  89. </el-form-item>
  90. </el-form>
  91. <div class="table-container" style="margin-bottom: 80px;margin-top: 20px;">
  92. <div class="table-wrapper">
  93. <div class="table-title">盘点托盘</div>
  94. <el-table ref="singleTable" :data="detailListTask" v-loading="loading" :border=true label="需求明细"
  95. tooltip-effect="dark"
  96. highlight-current-row max-height="500" style="width: 100%;margin-right:22px"
  97. :default-sort="{prop: 'createDate', order: 'descending'}" @row-click="rowClick"
  98. >
  99. <el-table-column prop="palletCode" label="托盘编码" :show-overflow-tooltip="true"></el-table-column>
  100. <el-table-column prop="storageLocationCode" label="库位编码" :show-overflow-tooltip="true"></el-table-column>
  101. <el-table-column prop="status" label="盘点状态" :show-overflow-tooltip="true">
  102. <template slot-scope="{ row }">
  103. <el-tag >
  104. {{ getPlanStatusText(row.status) }}
  105. </el-tag>
  106. </template>
  107. </el-table-column>
  108. <el-table-column label="操作" :show-overflow-tooltip="true">
  109. <template #default="scope">
  110. <!-- 这里放置操作按钮 -->
  111. <div class="button-group">
  112. <el-button type="primary" icon="el-icon-check" :disabled="scope.row.status===2" @click="getOutPalletCode(scope.row)">出库</el-button>
  113. </div>
  114. </template>
  115. </el-table-column>
  116. </el-table>
  117. </div>
  118. <div class="table-wrapper">
  119. <div class="table-title">托盘明细</div>
  120. <el-table ref="singleTable" :data="detailList" v-loading="loading" :border=true label="库存明细"
  121. tooltip-effect="dark"
  122. highlight-current-row max-height="500" style="width: 100%;"
  123. :default-sort="{prop: 'createDate', order: 'descending'}"
  124. >
  125. <el-table-column prop="materialCode" label="物料编码" :show-overflow-tooltip="true"></el-table-column>
  126. <el-table-column prop="storeAmount" label="库存数量" :show-overflow-tooltip="true"></el-table-column>
  127. <el-table-column prop="realAmount" label="盘点数量" :show-overflow-tooltip="true">
  128. <template slot-scope="scope">
  129. <el-input v-model="scope.row.realAmount" type="number" @input="handleInput(scope.row)" :disabled="inputDisabled"></el-input>
  130. </template>
  131. </el-table-column>
  132. <el-table-column prop="profitLossType" label="盘库状态" :show-overflow-tooltip="true">
  133. </el-table-column>
  134. <el-table-column prop="profitLossQuantity" label="盘库异常数量" :show-overflow-tooltip="true">
  135. </el-table-column>
  136. </el-table>
  137. </div>
  138. </div>
  139. <span slot="footer" class="dialog-footer">
  140. <el-button @click="handleCloseTask()">取 消</el-button>
  141. <el-button type="primary" @click="outSubmit()" :disabled="isViewMode">托盘回库</el-button>
  142. </span>
  143. </el-dialog>
  144. </div>
  145. </div>
  146. </div>
  147. </body>
  148. <style scoped>
  149. .table-container {
  150. display: flex;
  151. justify-content: space-between;
  152. width: 100%;
  153. }
  154. .table-wrapper {
  155. position: relative;
  156. width: 48%;
  157. }
  158. .table-title {
  159. position: absolute;
  160. top: -25px; /* Adjust based on your layout */
  161. left: 0;
  162. font-weight: bold;
  163. }
  164. </style>
  165. <script type="module">
  166. new Vue({
  167. el: '#app',
  168. data: function () {
  169. return {
  170. migrationResultList: [],
  171. detailList: [],
  172. detailListTask: [],
  173. detailListStore: [],
  174. detailListPallet: [],
  175. detailListOut: [],
  176. options: [],
  177. name: '',
  178. entryPoint: '',
  179. binCode: '',
  180. wPInventoryCountTaskId: '',
  181. createDate: '',
  182. currentPage: 1,
  183. total: 0,
  184. currentPageSize: 10,
  185. pageSizes: [10, 50, 100, 200, 300],
  186. loading: false,
  187. formInline: {
  188. taskCode: ''
  189. },
  190. detailType: '',
  191. palletCode: '',
  192. dialogVisible: false,
  193. dialogVisibleTask: false,
  194. inputDisabled: false,
  195. plan: this.initOrder(),
  196. rules: {
  197. planName: [
  198. {required: true, message: '必填', trigger: 'blur'},
  199. ],
  200. planType: [
  201. {required: true, message: '必填', trigger: 'blur'},
  202. ],
  203. planStrategy: [
  204. {required: true, message: '必填', trigger: 'blur'},
  205. ],
  206. planInput: [
  207. {required: true, message: '必填', trigger: 'blur'},
  208. ],
  209. },
  210. inputCode: '',
  211. selection: [],
  212. isViewMode: false,
  213. planId: '',
  214. wInventoryTransactionOrdersId: '',
  215. }
  216. },
  217. created() {
  218. console.log("初始化")
  219. this.queryClick();
  220. this.getDic();
  221. },
  222. methods: {
  223. handleSizeChange(pageSize, total) {
  224. this.currentPage = 1;
  225. this.currentPageSize = pageSize;
  226. this.queryClick();
  227. },
  228. initOrder() {
  229. return {
  230. planName: '',
  231. planStrategy: '',
  232. planInput: '',
  233. planTime: '',
  234. remarks: '',
  235. planType: ''
  236. }
  237. },
  238. handleCurrentChange(page) {
  239. this.currentPage = page;
  240. this.queryClick();
  241. },
  242. clear() {
  243. this.ylCard = '';
  244. this.master = '';
  245. }, getDic() {
  246. axios.post('/Dic/list', {
  247. 'dicCode': 'planType'
  248. })
  249. .then(response => {
  250. console.log(response)
  251. this.planTypeOptions = response.data;
  252. })
  253. .catch(error => {
  254. // 处理错误
  255. });
  256. axios.post('/Dic/list', {
  257. 'dicCode': 'planStrategy'
  258. })
  259. .then(response => {
  260. console.log(response)
  261. this.planStrategyOptions = response.data;
  262. })
  263. .catch(error => {
  264. // 处理错误
  265. });
  266. axios.post('/Dic/list', {
  267. 'dicCode': 'entryPoint'
  268. })
  269. .then(response => {
  270. console.log(response)
  271. this.options = response.data;
  272. })
  273. .catch(error => {
  274. // 处理错误
  275. });
  276. },
  277. queryClick() {
  278. this.loading = true;
  279. axios.get('/wPInventoryCountTask', {
  280. params: {
  281. page: this.currentPage,
  282. size: this.currentPageSize,
  283. taskCode: this.formInline.taskCode
  284. }
  285. })
  286. .then(response => {
  287. console.log(response)
  288. this.migrationResultList = response.data.list;
  289. this.total = response.data.total;
  290. // 处理响应
  291. this.loading = false;
  292. })
  293. .catch(error => {
  294. // 处理错误
  295. });
  296. }, getStatusText(status) {
  297. switch (status) {
  298. case 0:
  299. return '未开始'; // 第三种类型的文本
  300. case 1:
  301. return '进行中'; // 第四种类型的文本
  302. case 2:
  303. return '完成'; // 第四种类型的文本
  304. default:
  305. return ""
  306. }
  307. }, getPlanStatusText(status) {
  308. switch (status) {
  309. case 0:
  310. return '未开始'; // 第三种类型的文本
  311. case 1:
  312. return '进行中'; // 第四种类型的文本
  313. case 2:
  314. return '完成'; // 第四种类型的文本
  315. default:
  316. return '未开始'
  317. }
  318. }, getInOutTypeText(status) {
  319. switch (status) {
  320. case 1:
  321. return '物料'; // 第三种类型的文本
  322. case 2:
  323. return '库位'; // 第四种类型的文本
  324. case 3:
  325. return '货架'; // 第四种类型的文本
  326. case 4:
  327. return '库房'; // 第四种类型的文本
  328. default:
  329. return ""
  330. }
  331. }, getProfitLossTypeText(status) {
  332. /* if(status === null){
  333. let ag= row.realAmount - row.storeAmount;
  334. if(ag > 0){
  335. return '盘盈';
  336. }else if(ag = 0){
  337. return '正常';
  338. }else{
  339. return '盘亏';
  340. }
  341. }else{
  342. switch (status) {
  343. case 0:
  344. return '盘亏'; // 第三种类型的文本
  345. case 1:
  346. return '盘盈'; // 第四种类型的文本
  347. case 2:
  348. return '正常'; // 第四种类型的文本
  349. default:
  350. return ''
  351. }
  352. }
  353. */
  354. }, getPendingAmount(row) {
  355. return row.realAmount - row.storeAmount;
  356. }, handleSelectionChange(selection) {
  357. this.selection = selection
  358. }, toDo(id) {
  359. this.dialogVisibleTask = true;
  360. this.wPInventoryCountTaskId = id;
  361. axios.get('/wPInventoryCountPallet/getPalletList/' + id, {})
  362. .then(response => {
  363. console.log(response)
  364. if (response.data.success) {
  365. this.detailListTask = response.data.data;
  366. this.isViewMode = true;
  367. }
  368. })
  369. .catch(error => {
  370. // 处理错误
  371. });
  372. }, handleCloseTask() {
  373. this.dialogVisibleTask = false;
  374. this.detailListPallet = [];
  375. this.inputCode = '';
  376. this.palletCode = '';
  377. this.detailList = [];
  378. this.entryPoint = '';
  379. }, handleSelectChange(row) {
  380. console.log(row)
  381. row.inventoryManagementList.forEach(item => {
  382. if (row.outPalletCode === item.palletCode) {
  383. row.storageLocationCode = item.storageLocationCode;
  384. row.amount = item.amount;
  385. return
  386. }
  387. })
  388. },
  389. rowClick(row, column, event) {
  390. console.log(row)
  391. this.detailList = row.detailList;
  392. this.isViewMode = false;
  393. this.selection = row;
  394. this.inputDisabled = row.status === 2;
  395. }, orderDelete(row) {
  396. this.$confirm('确认删除?')
  397. .then(_ => {
  398. axios.delete('/wPInventoryCountTask', {
  399. params: {
  400. id: row.id
  401. }
  402. })
  403. .then(response => {
  404. console.log(response)
  405. if (response.data) {
  406. this.$message({
  407. message: '删除成功',
  408. type: "success"
  409. })
  410. this.queryClick();
  411. }
  412. })
  413. .catch(error => {
  414. // 处理错误
  415. });
  416. done();
  417. })
  418. .catch(_ => {
  419. });
  420. },
  421. handleInput(row) {
  422. console.log(row)
  423. let ag = row.realAmount - row.storeAmount;
  424. row.profitLossQuantity = ag
  425. if (ag > 0) {
  426. row.profitLossType = '盘盈';
  427. } else if (ag === 0) {
  428. row.profitLossType = '正常';
  429. } else {
  430. row.profitLossType = '盘亏';
  431. }
  432. }, handleScan() {
  433. console.log(this.inputCode)
  434. this.palletCode = this.inputCode;
  435. this.inputCode = '';
  436. /*axios.get('/order/verifyCode/'+this.inputCode, {
  437. })
  438. .then(response => {
  439. const verify=response.data.data;
  440. if(verify === null){
  441. this.$message.error('无法识别'+this.inputCode);
  442. this.inputCode='';
  443. return
  444. }
  445. if(verify === 0){
  446. const needFlag=this.detailListTask.some(vo=>{
  447. if(vo.materialCode === this.inputCode){
  448. return true;
  449. }
  450. return false;
  451. })
  452. if(!needFlag){
  453. this.$message.error('需求明细无法识别'+this.inputCode);
  454. this.inputCode='';
  455. return;
  456. }
  457. const flag =this.detailListPallet.some(vo=>{
  458. if(vo.materialCode === this.inputCode){
  459. const flag1=this.detailListOut.some(item =>{
  460. if(item.materialCode === this.inputCode){
  461. item.amount=parseInt(item.amount)+1;
  462. return true;
  463. }
  464. return false;
  465. })
  466. if(!flag1){
  467. const newRow = {
  468. "materialCode":this.inputCode,
  469. "materialName":vo.materialName,
  470. "amount":1
  471. }
  472. this.detailListOut.push(newRow);
  473. }
  474. return true;
  475. }
  476. return false;
  477. })
  478. if(!flag){
  479. this.$message.error('托盘明细中无法识别'+this.inputCode);
  480. }
  481. }else if(verify === 1){
  482. console.log(this.detailListTask)
  483. const allMaterials = this.detailListTask.reduce((accumulator, currentObject) => {
  484. return accumulator.concat(currentObject.inventoryManagementList);
  485. }, []);
  486. let locationCode1='';
  487. const hasMatchingCode = allMaterials.some(task => {
  488. if (task.palletCode === this.inputCode) {
  489. locationCode1 = task.storageLocationCode;
  490. return true;
  491. }
  492. return false;
  493. });
  494. if(!hasMatchingCode){
  495. this.$message.error("库存明细中无法识别到 " + this.inputCode);
  496. this.inputCode='';
  497. return;
  498. }
  499. axios.get('/wInventoryManagement/'+locationCode1, {
  500. })
  501. .then(response => {
  502. console.log(response)
  503. if(response.data.success){
  504. const res=response.data.data;
  505. this.detailListPallet=res;
  506. }
  507. })
  508. .catch(error => {
  509. // 处理错误
  510. });
  511. this.palletCode=this.inputCode;
  512. }
  513. this.inputCode='';
  514. })
  515. .catch(error => {
  516. // 处理错误
  517. });*/
  518. }, outSubmit() {
  519. console.log(this.selection)
  520. if (this.entryPoint === '') {
  521. this.$message({
  522. message: '入库口不能为空',
  523. type: "error"
  524. })
  525. return
  526. }
  527. if (this.selection.palletCode != this.palletCode) {
  528. this.$message({
  529. message: '选中托盘编码和扫描托盘编码不一致,请核对',
  530. type: "error"
  531. })
  532. return
  533. }
  534. if (this.selection.status === 2) {
  535. this.$message({
  536. message: '选中托盘已盘库完成',
  537. type: "error"
  538. })
  539. return
  540. }
  541. this.detailList.forEach(item => {
  542. if (item.realAmount === '' || item.realAmount <= 0) {
  543. this.$message({
  544. message: '盘点数量不能为空或小于等于0',
  545. type: "error"
  546. })
  547. return
  548. }
  549. })
  550. /*const remainingTasks = this.detailListTask.filter(task => !this.selection.includes(task));
  551. const allStatusTwo = remainingTasks.every(task => task.status === 2);*/
  552. axios.post('/wPInventoryCountPallet', {
  553. 'wPInventoryCountTaskId': this.wPInventoryCountTaskId,
  554. 'taskId': this.wPInventoryCountTaskId,
  555. 'entryPoint': this.entryPoint,
  556. 'palletCode': this.selection.palletCode,
  557. 'storageLocationCode': this.selection.storageLocationCode,
  558. 'status': 2,
  559. 'detailList': this.detailList
  560. })
  561. .then(response => {
  562. if (response.data.success) {
  563. this.$message({
  564. message: '操作成功',
  565. type: 'success'
  566. });
  567. this.entryPoint='';
  568. this.palletCode='';
  569. this.inputDisabled=true;
  570. this.toDo(this.wPInventoryCountTaskId);
  571. }
  572. })
  573. .catch(error => {
  574. // 处理错误
  575. });
  576. /* this.selection.forEach(item=>{
  577. if(item.amount === '' || item.amount <= 0){
  578. this.$message({
  579. message: '本次出库数量不能为空或小于等于0',
  580. type: "error"
  581. })
  582. return
  583. }
  584. })
  585. if(this.entryPoint ===''){
  586. this.$message({
  587. message: '入库口不能为空',
  588. type: "error"
  589. })
  590. return
  591. }
  592. axios.post('/wStorageLocationManagement', {
  593. 'startPosition':this.entryPoint,
  594. 'wInventoryTransactionOrdersId':this.wInventoryTransactionOrdersId,
  595. 'vectorCode':this.palletCode,
  596. 'status':0,
  597. 'taskType':2,//代表实际的出入库操作
  598. 'detailList':this.selection
  599. })
  600. .then(response => {
  601. if(response.data.success){
  602. const code=response.data.data;
  603. this.$message({
  604. message: '空托盘 '+code +' 已出库',
  605. type: 'success'
  606. });
  607. }else{
  608. this.$message.error(response.data.data);
  609. }
  610. })
  611. .catch(error => {
  612. // 处理错误
  613. });*/
  614. }, savePlanTask(row) {
  615. this.$confirm('确认生成盘点任务吗?')
  616. .then(_ => {
  617. axios.post('/wPInventoryCountTask', {
  618. id: row.id
  619. })
  620. .then(response => {
  621. if (response.data.success) {
  622. this.$message({
  623. message: '盘点任务生成成功',
  624. type: 'success'
  625. });
  626. }
  627. })
  628. .catch(error => {
  629. // 处理错误
  630. });
  631. done();
  632. })
  633. .catch(_ => {
  634. });
  635. }, getOutPalletCode(row) {
  636. //入库口 即空托盘出库的目的地
  637. const inCode = row.storageLocationCode;
  638. if (this.entryPoint === '') {
  639. this.$message({
  640. message: '请选择出入库口',
  641. type: 'error'
  642. });
  643. return
  644. }
  645. this.getPalletCodeCon(inCode, this.entryPoint)
  646. }, getPalletCodeCon(startPosition, endPosition) {
  647. axios.get('/wStorageLocationManagement/getPalletCode', {
  648. params: {
  649. startPosition: startPosition,
  650. endPosition: endPosition
  651. }
  652. })
  653. .then(response => {
  654. if (response.data.success) {
  655. const code = response.data.msg;
  656. this.$message({
  657. message: '托盘 ' + code + ' 已出库',
  658. type: 'success'
  659. });
  660. } else {
  661. this.$message.error(response.data.msg);
  662. }
  663. })
  664. .catch(error => {
  665. // 处理错误
  666. });
  667. }
  668. }
  669. })
  670. </script>
  671. </html>