index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. <template>
  2. <view class="uni-column" style="padding: 24rpx">
  3. <view v-if="allData.length>0" style="margin-bottom: 20rpx;">
  4. <view>
  5. <view class="item-info uni-row" style="height: 80rpx;">
  6. <view style="flex: 2;">
  7. <button :class="[ checkAll ? 'active' : 'select' ]" @click="handleAll"
  8. style="margin-left: 0px;display: flex; align-items: center; justify-content: center;">全选</button>
  9. </view>
  10. <button @click="handleSearch" style="margin-right: 20rpx ;">搜索</button>
  11. <uni-data-select v-model="workshopId" :localdata="workshopList" @change="handleChangeWorkshop"
  12. :clear="false" class="label right"
  13. style=" margin-right: 20rpx; outline: 2rpx solid #999999;border-radius: 10rpx;flex: 1;"></uni-data-select>
  14. </view>
  15. </view>
  16. </view>
  17. <view v-if="allData.length>0" style="overflow: auto; padding-bottom: 100rpx">
  18. <view v-for="(item, index) in listData" :key="index" :class="{'list-item':true,'selected':isSelected(item)}"
  19. @click="handleSelection(item)">
  20. <view class="title-container uni-row">
  21. <view class="title uni-row"><text class="label">{{item.lotCode}}</text></view>
  22. <view><button class="start-batch-btn uni-row"
  23. style="height: 70rpx; display: flex; align-items: center; justify-content: center;"
  24. type=primary @click.stop='handleChangeCarrier(item)'>换箱</button>
  25. </view>
  26. </view>
  27. <view class="item-info uni-row">
  28. <text class="label">产品描述</text>
  29. <text class="label right">{{item['productDescription']}}</text>
  30. </view>
  31. <view class="item-info uni-row">
  32. <text class="label">关联箱号</text>
  33. <text class="label right">{{item['carrierName']}}</text>
  34. </view>
  35. <!-- <view class="item-info uni-row">
  36. <text class="label">下序</text>
  37. <text class="label right">{{item['process']}}</text>
  38. </view> -->
  39. <view class="item-info uni-row">
  40. <text class="label">当前序</text>
  41. <text class="label right">{{item['process'].processAlias}}</text>
  42. </view>
  43. <view class="item-info uni-row">
  44. <text class="label">下序</text>
  45. <text class="label right">{{item['nextProcess'].processAlias}}</text>
  46. </view>
  47. <view class="item-info uni-row">
  48. <text class="label">下序工段</text>
  49. <text class="label right">{{item.quickInfo.deptName}}</text>
  50. </view>
  51. </view>
  52. </view>
  53. <view v-if="allData.length==0" style="color: #999;">
  54. <image style="width: 420rpx; height: 420rpx; padding-top: 30% ; margin: auto;"
  55. src="../../static/images/fastProductionPlan.png" />
  56. </view>
  57. <view v-if="allData.length==0" class='bottom-btn-container'>
  58. <text style="margin: auto; padding-bottom: 10%;">扫箱码开始快速报工</text>
  59. <button class="start-batch-btn uni-row" type=primary @click='handleAdd'>扫码开始报工</button>
  60. </view>
  61. <view v-if="allData.length>0" class='btn uni-row'>
  62. <button class='bottom-btn left-btn' type="warn" @click="handleEnd">结束报工</button>
  63. <button class='bottom-btn right-btn' type="primary" @click="handleContinue">继续扫码</button>
  64. </view>
  65. <dialog-lotReporting ref="lotReporting" :getList="init" @scan="handleAdd"></dialog-lotReporting>
  66. <dialog-Search ref="searchRef" @search="refreshSearch"></dialog-Search>
  67. <QrScanner v-if="showQrCodeReader" @decode="onDecodeHandler" @close="qrReaderClose" />
  68. </view>
  69. <view
  70. style="background-color: #99999999; z-index: 5; position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px;"
  71. v-if="loading">
  72. </view>
  73. </template>
  74. <script setup>
  75. import {
  76. getPlanDetailsList
  77. } from '@/api/business/planDetails.js'
  78. import {
  79. store
  80. } from '@/store/index.js'
  81. import {
  82. onShow
  83. } from '@dcloudio/uni-app'
  84. import {
  85. getDayWorkList,
  86. showDaywork,
  87. showDayworkSave,
  88. turnoverDelete
  89. } from '@/api/business/dayWork.js'
  90. import QrScanner from '../vueQrCode/index.vue'
  91. import {
  92. getQuickDayworkList,
  93. finishQuick,
  94. getDayworkByCarrierId,
  95. getDayworkByCarrierCode,
  96. reportDaywork
  97. } from '@/api/business/quickDaywork'
  98. import {
  99. isTakeStock
  100. } from '@/api/business/taksStackLot.js'
  101. import {
  102. ref
  103. } from 'vue'
  104. import path from '@/api/base/path.js'
  105. const lotReporting = ref(null)
  106. const workshopId = ref(null);
  107. const searchRef = ref(null);
  108. const keyword = ref('')
  109. const loading = ref(false)
  110. const showQrCodeReader = ref(false);
  111. const form = ref([]); //表单数据true
  112. const checkAll = ref(false); //是否全选
  113. // 创建一个引用来存储最后一次请求的时间戳
  114. const lastRequestTimestamp = ref(0);
  115. const listData = ref([]);
  116. const allData = ref([])
  117. const selection = ref([]); //选中数据
  118. const workshopList = ref([]); //车间数据
  119. onShow(() => {
  120. init()
  121. })
  122. //初始化
  123. function init() {
  124. // console.log(store.curDeptDetails)
  125. uni.showLoading({
  126. title: '加载中'
  127. });
  128. checkAll.value = false
  129. getQuickDayworkList({
  130. deptId: store.curDeptDetails.deptId,
  131. }).then(res => {
  132. // console.log(res)
  133. if (res.code == 200) {
  134. allData.value = res.rows
  135. if (allData.value.length == 0) {
  136. listData.value = []
  137. }
  138. uni.hideLoading();
  139. }
  140. if (res.other.workShops != null) {
  141. workshopList.value = res.other.workShops.map(v => ({
  142. value: v.id,
  143. text: v.name,
  144. depts: v.depts
  145. }))
  146. if ((workshopId.value == null || !workshopList.value.some(e => e.value === workshopId.value)) &&
  147. workshopList.value.length > 0) {
  148. workshopId.value = workshopList.value[0].value
  149. handleChangeWorkshop(workshopId.value)
  150. } else {
  151. handleChangeWorkshop(workshopId.value)
  152. }
  153. } else {
  154. workshopList.value = []
  155. }
  156. uni.hideLoading();
  157. loading.value = false
  158. })
  159. }
  160. // 搜索按钮操作
  161. function handleSearch() {
  162. searchRef.value.open();
  163. }
  164. function refreshSearch(input) {
  165. // console.log(input)
  166. keyword.value = input
  167. handleChangeWorkshop(workshopId.value)
  168. }
  169. /* 【原有代码】
  170. function handleAdd() {
  171. const mpaasScanModule = uni.requireNativePlugin("Mpaas-Scan-Module");
  172. if (mpaasScanModule) {
  173. // 调用插件的 mpaasScan 方法
  174. mpaasScanModule.mpaasScan({
  175. // 扫码识别类型,参数可多选,qrCode、barCode,
  176. // 如不设置,默认识别所有扫码类型,可能有些许影响识别效率
  177. scanType: ["qrCode", "barCode"],
  178. // 是否隐藏相册,默认false不隐藏
  179. hideAlbum: false,
  180. },
  181. (ret) => {
  182. let vehicleObj = JSON.parse(ret.resp_result);
  183. if (!vehicleObj.carrierId || vehicleObj.carrierId == "") {
  184. uni.showToast({
  185. icon: "none",
  186. title: "请扫载具码",
  187. duration: 1000
  188. })
  189. return;
  190. }
  191. getDayworkByCarrierId({
  192. carrierId: vehicleObj.carrierId,
  193. deptId: store.curDeptDetails.deptId,
  194. status: 7
  195. }).then(response => {
  196. if (response.code == 200) {
  197. // console.log(response.data.items.length)
  198. // console.log(response.data)
  199. // if (response.data.items[0].deptId !== store.curDeptDetails.deptId) {
  200. // uni.showToast({
  201. // icon: 'none',
  202. // title: '该批次不在当前工段',
  203. // duration: 2000
  204. // })
  205. // return
  206. // }
  207. if (response.data.items.length > 0) {
  208. lotReporting.value.open(response.data);
  209. } else {
  210. uni.showToast({
  211. icon: 'none',
  212. title: '该批次不在此计划单内, 或不在当前工段',
  213. duration: 2000
  214. })
  215. }
  216. } else {
  217. uni.showToast({
  218. icon: 'none',
  219. title: response.msg,
  220. duration: 2000
  221. })
  222. }
  223. })
  224. }
  225. );
  226. } else {
  227. // 测试时用
  228. getDayworkByCarrierId({
  229. carrierId: '1747500987688890381',
  230. status: 7,
  231. deptId: store.curDeptDetails.deptId,
  232. }).then(response => {
  233. console.log(response)
  234. if (response.code == 200) {
  235. //
  236. // if (response.data.items[0].deptId !== store.curDeptDetails.deptId) {
  237. // uni.showToast({
  238. // icon: 'none',
  239. // title: '该批次不在当前工段',
  240. // duration: 2000
  241. // })
  242. // return
  243. // }
  244. if (response.data.items.length > 0) {
  245. // console.log(response.data)
  246. lotReporting.value.open(response.data);
  247. } else {
  248. uni.showToast({
  249. icon: 'none',
  250. title: '该批次不在此计划单内, 或不在当前工段',
  251. duration: 2000
  252. })
  253. }
  254. } else {
  255. uni.showToast({
  256. icon: 'none',
  257. title: response.msg,
  258. duration: 2000
  259. })
  260. }
  261. })
  262. }
  263. // lotReporting.value.open(data);
  264. }
  265. */
  266. //H5扫码器回调
  267. function onDecodeHandler(data) {
  268. showQrCodeReader.value = false;
  269. let vehicleObj = {
  270. carrierCode: data
  271. };
  272. if (!vehicleObj.carrierCode || vehicleObj.carrierCode == "") {
  273. uni.showToast({
  274. icon: "none",
  275. title: "请扫载具码",
  276. duration: 1000
  277. })
  278. return;
  279. }
  280. getDayworkByCarrierCode({
  281. carrierCode: vehicleObj.carrierCode,
  282. deptId: store.curDeptDetails.deptId,
  283. status: 7
  284. }).then(response => {
  285. if (response.code == 200) {
  286. if (response.data.items.length > 0) {
  287. lotReporting.value.open(response.data);
  288. } else {
  289. uni.showToast({
  290. icon: 'none',
  291. title: '该批次不在此计划单内, 或不在当前工段',
  292. duration: 2000
  293. })
  294. }
  295. } else {
  296. uni.showToast({
  297. icon: 'none',
  298. title: response.msg,
  299. duration: 2000
  300. })
  301. }
  302. })
  303. }
  304. //H5扫码器关闭
  305. function qrReaderClose() {
  306. showQrCodeReader.value = false;
  307. }
  308. function handleAdd() {
  309. showQrCodeReader.value = true;
  310. // const mpaasScanModule = uni.requireNativePlugin("Mpaas-Scan-Module");
  311. // if (mpaasScanModule) {
  312. // // 调用插件的 mpaasScan 方法
  313. // mpaasScanModule.mpaasScan({
  314. // // 扫码识别类型,参数可多选,qrCode、barCode,
  315. // // 如不设置,默认识别所有扫码类型,可能有些许影响识别效率
  316. // scanType: ["qrCode", "barCode"],
  317. // // 是否隐藏相册,默认false不隐藏
  318. // hideAlbum: false,
  319. // },
  320. // (ret) => {
  321. // let vehicleObj = {
  322. // carrierCode: ret.resp_result
  323. // };
  324. // if (!vehicleObj.carrierCode || vehicleObj.carrierCode == "") {
  325. // uni.showToast({
  326. // icon: "none",
  327. // title: "请扫载具码",
  328. // duration: 1000
  329. // })
  330. // return;
  331. // }
  332. // getDayworkByCarrierCode({
  333. // carrierCode: vehicleObj.carrierCode,
  334. // deptId: store.curDeptDetails.deptId,
  335. // status: 7
  336. // }).then(response => {
  337. // if (response.code == 200) {
  338. // if (response.data.items.length > 0) {
  339. // lotReporting.value.open(response.data);
  340. // } else {
  341. // uni.showToast({
  342. // icon: 'none',
  343. // title: '该批次不在此计划单内, 或不在当前工段',
  344. // duration: 2000
  345. // })
  346. // }
  347. // } else {
  348. // uni.showToast({
  349. // icon: 'none',
  350. // title: response.msg,
  351. // duration: 2000
  352. // })
  353. // }
  354. // })
  355. // }
  356. // );
  357. // } else {
  358. // // 测试时用
  359. // getDayworkByCarrierCode({
  360. // carrierCode: '900005',
  361. // status: 7,
  362. // deptId: store.curDeptDetails.deptId,
  363. // }).then(response => {
  364. // console.log(response)
  365. // if (response.code == 200) {
  366. // //
  367. // // if (response.data.items[0].deptId !== store.curDeptDetails.deptId) {
  368. // // uni.showToast({
  369. // // icon: 'none',
  370. // // title: '该批次不在当前工段',
  371. // // duration: 2000
  372. // // })
  373. // // return
  374. // // }
  375. // if (response.data.items.length > 0) {
  376. // // console.log(response.data)
  377. // lotReporting.value.open(response.data);
  378. // } else {
  379. // uni.showToast({
  380. // icon: 'none',
  381. // title: '该批次不在此计划单内, 或不在当前工段',
  382. // duration: 2000
  383. // })
  384. // }
  385. // } else {
  386. // uni.showToast({
  387. // icon: 'none',
  388. // title: response.msg,
  389. // duration: 2000
  390. // })
  391. // }
  392. // })
  393. // }
  394. // lotReporting.value.open(data);
  395. }
  396. function handleContinue() {
  397. // lotReporting.value.open('test')
  398. handleAdd()
  399. }
  400. // 全选按钮操作
  401. function handleAll() {
  402. //清空选中数据
  403. selection.value.length = 0;
  404. if (checkAll.value) {
  405. //变更选中状态
  406. checkAll.value = false;
  407. } else {
  408. checkAll.value = true;
  409. listData.value.findIndex(item => handleSelection(item))
  410. }
  411. }
  412. function handleChangeWorkshop(arg) {
  413. const workshop = workshopList.value.find(v => v.value === arg)
  414. // console.log(allData.value)
  415. // console.log(workshop)
  416. // console.log()
  417. listData.value = allData.value.filter(v => workshop.depts.some(e => e.deptId === v.quickInfo.deptId) && (v.lotCode
  418. .includes(keyword.value) || v.productDescription.includes(keyword.value) || v.carrierName.includes(
  419. keyword.value)))
  420. selection.value = []
  421. }
  422. function isSelected(item) {
  423. return selection.value.includes(item);
  424. }
  425. //
  426. function handleSelection(item) {
  427. const buttonIndex = selection.value.findIndex(selectedItem => selectedItem === item);
  428. if (buttonIndex > -1) {
  429. selection.value.splice(buttonIndex, 1); // 取消选中
  430. } else {
  431. selection.value.push(item); // 选中
  432. }
  433. if (selection.value.length == listData.value.length) {
  434. checkAll.value = true;
  435. } else {
  436. checkAll.value = false;
  437. }
  438. }
  439. function handleChangeCarrier(item) {
  440. uni.$once('refreshQuickReport', () => {
  441. init()
  442. })
  443. store.dayworkInfo = null
  444. uni.navigateTo({
  445. url: "/pages/changeBox/index",
  446. success: function(res) {
  447. // 通过eventChannel向被打开页面传送数据
  448. res.eventChannel.emit('acceptDataFromOpenerPage', {
  449. data: item
  450. })
  451. }
  452. })
  453. }
  454. function handleEnd() {
  455. if (selection.value.length === 0) {
  456. uni.showToast({
  457. icon: 'none',
  458. title: '请选择完成报工批次'
  459. })
  460. return
  461. }
  462. const currentTime = Date.now();
  463. // 检查是否已经过去了 2 秒
  464. if (currentTime - lastRequestTimestamp.value < 2000) {
  465. // 如果在 2 秒 内已经有请求发出,那么不执行
  466. uni.showToast({
  467. icon: 'none',
  468. title: `请勿重复点击`,
  469. duration: 2000
  470. })
  471. return;
  472. }
  473. lastRequestTimestamp.value = currentTime;
  474. // 更新请求时间戳
  475. isTakeStock().then(response => {
  476. if (response.data) {
  477. uni.showToast({
  478. icon: 'none',
  479. title: '正在盘点,不能结束报工',
  480. duration: 2000
  481. })
  482. } else {
  483. loading.value = true
  484. uni.showLoading({
  485. title: '加载中'
  486. });
  487. lastRequestTimestamp.value = currentTime;
  488. selection.value.forEach(item => {
  489. item.tenantId = !store.tenantId ? store.userInfo.tenantId : store.tenantId
  490. })
  491. finishQuick(selection.value).then(res => {
  492. // console.log(res)
  493. if (res.code === 200) {
  494. init()
  495. } else {
  496. // loading.value = false
  497. // uni.hideLoading()
  498. uni.showToast({
  499. icon: 'none',
  500. title: res.msg,
  501. duration: 2000
  502. });
  503. setTimeout(() => {
  504. init()
  505. }, 1500);
  506. }
  507. })
  508. }
  509. })
  510. }
  511. // init();
  512. </script>
  513. <style lang="scss">
  514. $nav-height: 60rpx;
  515. .bottom-btn-container {
  516. position: fixed;
  517. top: 80%;
  518. right: 20rpx;
  519. left: 20rpx;
  520. .start-batch-btn {
  521. margin-bottom: 24rpx;
  522. border-radius: 8rpx;
  523. background-color: #00e2a6;
  524. width: 80%;
  525. }
  526. }
  527. .active {
  528. flex: 1;
  529. height: 40rpx;
  530. background-color: #5e6eff;
  531. border: 1px solid #5e6eff;
  532. color: #000000;
  533. }
  534. .select {
  535. flex: 1;
  536. height: 40rpx;
  537. // font-size: 20rpx;
  538. background-color: #5e6eff;
  539. border: 1px solid #5e6eff;
  540. color: #ffffff;
  541. }
  542. .btn {
  543. position: fixed;
  544. right: 0;
  545. bottom: 0;
  546. left: 0;
  547. height: 100rpx;
  548. padding: 16rpx 24rpx;
  549. align-items: center;
  550. background-color: #FFFFFF;
  551. justify-content: space-between;
  552. .bottom-btn {
  553. flex: 1;
  554. font-size: 28rpx;
  555. color: #FFFFFF;
  556. &.left-btn {
  557. // background-color: #a4adb3;
  558. }
  559. &.right-btn {
  560. background-color: #1684fc;
  561. margin-left: 24rpx;
  562. }
  563. }
  564. }
  565. .box-bg {
  566. width: 100%;
  567. background-color: #F5F5F5;
  568. padding: 5rpx 0;
  569. justify-content: space-around;
  570. align-items: center;
  571. .input-view {
  572. width: 100%;
  573. flex: 4;
  574. background-color: #f8f8f8;
  575. height: $nav-height;
  576. border: 1rpx solid #999;
  577. border-radius: 15rpx;
  578. padding: 0 15rpx;
  579. flex-wrap: nowrap;
  580. margin: 0 10rpx 20rpx;
  581. line-height: $nav-height;
  582. .input-uni-icon {
  583. line-height: $nav-height;
  584. }
  585. .nav-bar-input {
  586. width: 80%;
  587. height: $nav-height;
  588. line-height: $nav-height;
  589. padding: 0 5rpx;
  590. background-color: #f8f8f8;
  591. }
  592. }
  593. .search {
  594. width: 20%;
  595. text-align: center;
  596. color: #808080;
  597. margin-top: -20rpx;
  598. }
  599. }
  600. .list-item {
  601. background-color: #fff;
  602. position: relative;
  603. padding: 16rpx;
  604. padding-bottom: 24rpx;
  605. border-radius: 24rpx;
  606. margin-bottom: 24rpx;
  607. .title-container {
  608. justify-content: space-between;
  609. margin-top: 8rpx;
  610. margin-bottom: 16rpx;
  611. .title {
  612. height: 48rpx;
  613. align-items: center;
  614. .label {
  615. font-size: 32rpx;
  616. font-weight: bold;
  617. &.code {
  618. margin-left: 8rpx;
  619. }
  620. }
  621. }
  622. .tag {
  623. border: 1px solid #1ce5b0;
  624. background-color: #f6fffd;
  625. padding: 8rpx;
  626. border-radius: 8rpx;
  627. .label {
  628. color: #1ce5b0;
  629. font-size: 24rpx;
  630. }
  631. &.not-start {
  632. border: 1px solid #bbbbbb;
  633. background-color: #f5f5f5;
  634. .label {
  635. color: #bbbbbb;
  636. }
  637. }
  638. }
  639. }
  640. .item-info {
  641. margin-bottom: 8rpx;
  642. .label {
  643. font-size: 28rpx;
  644. width: 150rpx;
  645. color: #808080;
  646. &.right {
  647. flex: 1;
  648. color: #000000;
  649. }
  650. }
  651. }
  652. }
  653. .selected {
  654. border: 1rpx solid #c0c4fc;
  655. background-color: #c0c4fc;
  656. /* 选中之后样式 */
  657. }
  658. </style>