shipmentPackingDetails.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. <template>
  2. <gui-page :custom-header="true" :header-class="['gui-theme-background-color']">
  3. <template #gHeader>
  4. <view style="height:44px;" class="gui-flex gui-nowrap gui-rows gui-align-items-center">
  5. <!-- 使用组件实现返回按钮及返回首页按钮 -->
  6. <text style="font-size:44rpx;" class="gui-header-leader-btns gui-color-white font-icons"
  7. @tap="goBack">&#xe6c5;</text>
  8. <!-- 导航文本此处也可以是其他自定义内容 -->
  9. <text
  10. class="gui-h4 gui-blod gui-flex1 gui-text-center gui-ellipsis gui-color-white gui-primary-text">装箱明细</text>
  11. <!-- 此处加一个右侧展位元素与左侧同宽,实现标题居中 -->
  12. <!-- 实际宽度请根据自己情况设置 -->
  13. <view style="width:40px;" />
  14. <!-- 如果右侧有其他内容可以利用条件编译和定位来实现-->
  15. </view>
  16. </template>
  17. <template #gBody>
  18. <view class="list-content">
  19. <view class="collapsed-panel" v-if="cardList.length > 0">
  20. <div class="content" v-for="item in cardList" :key="item.id" @click="handleHighLightRow(item)">
  21. <div :class="['panel-row', highLightField?.id === item.id?'printer':'']">
  22. <span>内盘标批号</span>
  23. <span>{{ item.workpieceTrayLabel }}</span>
  24. </div>
  25. <div :class="['panel-row', highLightField?.id === item.id?'printer':'']">
  26. <span>数量</span>
  27. <span>{{ ~~item.qty }}</span>
  28. </div>
  29. </div>
  30. </view>
  31. <view v-else>
  32. <view class="bg-image">
  33. <image src="@/static/empty.png" mode="heightFix" />
  34. <text>这里什么都没有...</text>
  35. </view>
  36. </view>
  37. </view>
  38. <view class="operation-panel">
  39. <button type="primary" :disabled="!highLightField" style="width: calc(100% - 8px);margin: 0 4px;"
  40. @click="handleShipmentBoxPrinter">内盘/袋标签补打</button>
  41. </view>
  42. <uni-popup ref="errorTip" type="dialog">
  43. <uni-popup-dialog type="error" cancel-text="关闭" confirm-text="确认" title="提示" :content="errorTipMessage"
  44. @confirm="handleCloseErrorTipsModal" @close="handleCloseErrorTipsModal" />
  45. </uni-popup>
  46. </template>
  47. </gui-page>
  48. </template>
  49. <script>
  50. import {
  51. computed,
  52. defineComponent,
  53. onBeforeMount,
  54. ref
  55. } from 'vue'
  56. import tsc from '@/unit/CHITEN_SDK_APP/tsc.js'
  57. export default defineComponent({
  58. setup(options) {
  59. const easyinput = ref()
  60. const errorTip = ref('')
  61. const errorTipMessage = ref('')
  62. const cardList = ref([])
  63. const formData = ref()
  64. const parseData = JSON.parse(options?.params) ?? {}
  65. const highLightField = ref()
  66. const bluetooth = ref()
  67. const blueConfig = ref({
  68. loopBuffer: 0,
  69. currentTime: 1,
  70. lastData: 0,
  71. onBufferSize: 20,
  72. printerNum: 1,
  73. currentPrint: 1,
  74. isLabelSend: false
  75. })
  76. onBeforeMount(() => {
  77. // #ifdef APP-PLUS
  78. const bluetoothConfig = uni.getStorageSync('bluetoothConfig')
  79. if ([null, '', undefined].includes(bluetoothConfig)) {
  80. bluetooth.value = {
  81. 'isOpenBle': false,
  82. 'deviceId': '',
  83. 'serviceId': '',
  84. 'writeId': '',
  85. 'notifyId': ''
  86. }
  87. setTimeout(() => {
  88. // #ifdef APP-PLUS
  89. plus.device.beep(2)
  90. // #endif
  91. errorTipMessage.value = '蓝牙打印机未连接'
  92. errorState.value = -1
  93. errorTip.value.open()
  94. }, 800)
  95. } else {
  96. bluetooth.value = JSON.parse(bluetoothConfig)
  97. }
  98. // #endif
  99. formData.value = parseData
  100. cardList.value = parseData?.insideRespVOList ?? [];
  101. })
  102. const handleShipmentBoxPrinter = function() {
  103. // const filterBoxId = cardList.value?.filter(ret => ret.labelContent === highLightField
  104. // .value)[0]?.id
  105. // 打印内部标签
  106. uni.$reqGet("getShippingLabelPrintData", {
  107. id: highLightField.value.id
  108. })
  109. .then(async ({
  110. code,
  111. data,
  112. msg
  113. }) => {
  114. if (code === 0) {
  115. // 打印
  116. await labelInnerTest(data)
  117. blueConfig.value.currentPrint = 1
  118. blueConfig.value.printNum = 2
  119. const timer = setInterval(() => {
  120. if (blueConfig.value.isLabelSend === false &&
  121. blueConfig.value.currentPrint === 2) {
  122. blueConfig.value.currentPrint += 1
  123. labelExternalTest(data)
  124. }
  125. if (blueConfig.value.currentPrint === blueConfig
  126. .value.printNum) {
  127. clearInterval(timer);
  128. }
  129. }, 2000)
  130. } else {
  131. // #ifdef APP-PLUS
  132. plus.device.beep(2)
  133. // #endif
  134. errorTipMessage.value = msg
  135. errorTip.value.open()
  136. }
  137. })
  138. }
  139. const Send = function(buff) {
  140. var currentTime = blueConfig.value.currentTime
  141. var loopBuffer = blueConfig.value.loopBuffer
  142. var lastData = blueConfig.value.lastData
  143. var onBufferSize = blueConfig.value.onBufferSize
  144. var printNum = blueConfig.value.printerNum
  145. var currentPrint = blueConfig.value.currentPrint
  146. var buf
  147. var dataView
  148. if (currentTime < loopBuffer) {
  149. buf = new ArrayBuffer(onBufferSize)
  150. dataView = new DataView(buf)
  151. for (let i = 0; i < onBufferSize; ++i) {
  152. dataView.setUint8(i, buff[(currentTime - 1) * onBufferSize + i])
  153. }
  154. } else {
  155. buf = new ArrayBuffer(lastData)
  156. dataView = new DataView(buf)
  157. for (let i = 0; i < lastData; ++i) {
  158. dataView.setUint8(i, buff[(currentTime - 1) * onBufferSize + i])
  159. }
  160. }
  161. plus.bluetooth.writeBLECharacteristicValue({
  162. deviceId: bluetooth.value.deviceId,
  163. serviceId: bluetooth.value.serviceId,
  164. characteristicId: bluetooth.value.writeId,
  165. value: buf,
  166. success: function(res) {
  167. if (currentPrint <= printNum) {
  168. wx.showToast({
  169. title: '数据打印中',
  170. icon: 'loading'
  171. })
  172. }
  173. // 将complete中处理数据的代码挪过来,增加30ms延迟, 解决蓝牙打印数据传输10007问题
  174. setTimeout(() => {
  175. currentTime += 1
  176. if (currentTime <= loopBuffer) {
  177. blueConfig.value.isLabelSend = true
  178. blueConfig.value.currentTime = currentTime
  179. Send(buff)
  180. }
  181. // end
  182. if (currentTime === loopBuffer) {
  183. blueConfig.value.currentPrint += 1
  184. blueConfig.value.isLabelSend = false
  185. }
  186. }, 10)
  187. },
  188. fail: function(e) {
  189. wx.showToast({
  190. title: '打印第' + currentPrint + '张失败' + 'error: code ' + e
  191. ?.code + ', message ' + e?.message,
  192. icon: 'none',
  193. duration: 4000
  194. })
  195. },
  196. complete: function() {}
  197. })
  198. }
  199. const prepareSend = function(buff) {
  200. var time = blueConfig.value.onBufferSize
  201. var loopBuffer = parseInt(buff.length / time)
  202. var lastData = parseInt(buff.length % time)
  203. blueConfig.value.loopBuffer = loopBuffer + 1
  204. blueConfig.value.lastData = lastData
  205. blueConfig.value.currentTime = 1
  206. Send(buff)
  207. }
  208. const labelInnerTest = function(ret) {
  209. var command = tsc.dlabelPrinter.createNew()
  210. command.setBackFeed(4)
  211. command.setOffset(-2)
  212. // (480 * 200)dots
  213. command.setSize(60, 25)
  214. command.setCls()
  215. command.setGap(6, 2)
  216. command.setSpeed(1.5)
  217. // row1
  218. command.setText(4, 0, '1', 0, 1, 1, '(C)Customer P/N:')
  219. command.setText(172, 0, '1', 0, 1, 1, ret.c)
  220. command.setText(278, 0, '1', 0, 1, 1, '(D)QTY(EA):')
  221. command.setText(378, 0, '1', 0, 1, 1, ret.qty)
  222. // row2
  223. command.setText(4, 20, '1', 0, 1, 1, '(G)LOT NO:')
  224. const strList = ret.lotNo?.split('');
  225. let lotNo = ''
  226. let lotNo2 = ''
  227. if (strList.length > 16) {
  228. lotNo = ret.lotNo?.substring(0, 16)
  229. lotNo2 = ret.lotNo?.substring(16)
  230. command.setText(102, 20, '1', 0, 1, 1, lotNo)
  231. command.setText(102, 40, '1', 0, 1, 1, lotNo2)
  232. } else {
  233. command.setText(102, 20, '1', 0, 1, 1, ret.lotNo)
  234. }
  235. command.setText(270, 20, '1', 0, 1, 1, '(J)ExpDate:')
  236. const timeList = ret.expDate?.split('');
  237. let timeText = ''
  238. let timeText2 = ''
  239. if (timeList.length > 9) {
  240. timeText = ret.expDate?.substring(0, 9)
  241. timeText2 = ret.expDate?.substring(9)
  242. command.setText(380, 20, '1', 0, 1, 1, timeText)
  243. command.setText(380, 40, '1', 0, 1, 1, timeText2)
  244. } else {
  245. command.setText(380, 20, '1', 0, 1, 1, ret.expDate)
  246. }
  247. // row3
  248. command.setText(128, 60, '1', 0, 1, 1, '(E)Manuf:')
  249. command.setText(218, 60, '1', 0, 1, 1, ret.manuf)
  250. command.setText(128, 78, 'TSS24.BF2', 0, 1, 1, '存储条件:')
  251. // let strList2 = []
  252. // let strText = ''
  253. // if (ret.storageEnvironmentName) {
  254. // strList2 = ret.storageEnvironmentName?.split(' ')
  255. // strText = strList2[0] + ' ' + strList2[1]
  256. // } else {
  257. // strText = '';
  258. // }
  259. command.setText(208, 94, 'TSS24.BF2', 0, 1, 1, '温度 ' + ret.temperature)
  260. command.setText(208, 112, 'TSS24.BF2', 0, 1, 1, '湿度 ' + ret.humidity)
  261. // command.setText(208, 94, 'TSS24.BF2', 0, 1, 1, strText)
  262. // row4
  263. command.setQrcode(4, 64, 'H', 4, 'A', ret.lotNo2)
  264. command.setQrcode(318, 54, 'M', 3, 'A', ret.qrCode1)
  265. command.setText(128, 160, '1', 0, 1, 1, 'C.O.O.CN')
  266. command.setText(128, 178, '2', 0, 1, 1, 'ROHS 2.0 HF')
  267. command.setPagePrint()
  268. blueConfig.value.isLabelSend = true
  269. prepareSend(command.getData())
  270. }
  271. const labelExternalTest = function(ret) {
  272. var command = tsc.dlabelPrinter.createNew()
  273. command.setBackFeed(6)
  274. // (640 * 320)dots
  275. command.setSize(80, 40)
  276. command.setCls()
  277. command.setGap(6)
  278. command.setSpeed(1.5)
  279. // row1
  280. command.setText(4, 0, '1', 0, 1, 1, '(A)Cust PO:')
  281. command.setText(120, 0, '1', 0, 1, 1, ret.a)
  282. // row2
  283. command.setText(4, 15, '1', 0, 1, 1, '(C)Customer P/N:')
  284. command.setText(165, 15, '1', 0, 1, 1, ret.c)
  285. command.setText(280, 12, '1', 0, 1, 1, 'C.O.O.CN')
  286. // row3
  287. command.setText(4, 30, '1', 0, 1, 1, '(E)Manuf:')
  288. command.setText(100, 30, '1', 0, 1, 1, ret.manuf)
  289. // command.setText(300, 45, 'TSS24.BF2', 0, 1, 1, '量产模具生产')
  290. // row4
  291. command.setText(4, 45, '1', 0, 1, 1, '(H)Date Code:')
  292. command.setText(140, 45, '1', 0, 1, 1, ret.h)
  293. command.setText(280, 30, '2', 0, 1, 1, 'ROHS 2.0 HF')
  294. // row5
  295. command.setText(4, 60, '1', 0, 1, 1, '(J)ExpDate:')
  296. command.setText(120, 60, '1', 0, 1, 1, ret.expDate)
  297. command.setText(270, 60, '1', 0, 1, 1, '(B)Line NO:')
  298. command.setText(385, 60, '1', 0, 1, 1, ret.b)
  299. // row6
  300. command.setText(4, 75, '1', 0, 1, 1, '(G)LOT NO:')
  301. const strList = ret.lotNo?.split('');
  302. let lotNo = ''
  303. let lotNo2 = ''
  304. if (strList.length > 16) {
  305. lotNo = ret.lotNo?.substring(0, 16)
  306. lotNo2 = ret.lotNo?.substring(16)
  307. command.setText(102, 75, '1', 0, 1, 1, lotNo)
  308. command.setText(102, 90, '1', 0, 1, 1, lotNo2)
  309. } else {
  310. command.setText(102, 75, '1', 0, 1, 1, ret.lotNo)
  311. }
  312. command.setText(270, 75, '1', 0, 1, 1, '(D)QTY(EA):')
  313. command.setText(385, 75, '1', 0, 1, 1, ret.qty)
  314. // row3
  315. command.setText(90, 110, 'TSS24.BF2', 0, 1, 1, '存储条件:')
  316. // let strList2 = []
  317. // let strText = ''
  318. // if (ret.storageEnvironmentName) {
  319. // strList2 = ret.storageEnvironmentName?.split(' ')
  320. // strText = strList2[0] + ' ' + strList2[1]
  321. // } else {
  322. // strText = '';
  323. // }
  324. command.setText(90, 135, 'TSS24.BF2', 0, 1, 1, '温度 ' + ret.temperature)
  325. command.setText(90, 150, 'TSS24.BF2', 0, 1, 1, '湿度 ' + ret.humidity)
  326. // command.setText(90, 135, 'TSS24.BF2', 0, 1, 1, strText)
  327. command.setText(230, 110, '1', 0, 1, 1, '(F)MPN:')
  328. command.setText(315, 110, '1', 0, 1, 1, ret.f)
  329. command.setText(4, 195, '1', 0, 1, 1, '(K)ERP LOT:')
  330. // QR
  331. command.setQrcode(4, 100, 'Q', 3, 'A', ret.lotNo2)
  332. command.setQrcode(470, 0, 'Q', 3, 'A', ret.qrCode1)
  333. command.setBarCode(4, 210, '39', 50, 1, 0, 1, 2, ret.k)
  334. // row5
  335. command.setText(230, 125, '1', 0, 1, 1, '(I)ManufID:')
  336. command.setText(340, 125, '1', 0, 1, 1, ret.i)
  337. command.setText(230, 140, '1', 0, 1, 1, '(L)ADH:')
  338. command.setText(315, 140, '1', 0, 1, 1, ret.l)
  339. // row5
  340. command.setText(275, 190, 'TSS24.BF2', 0, 1, 1, '原胶LOT NO:')
  341. command.setText(410, 195, '2', 0, 1, 1, ret.rawIncomingReceiptMaterialLots)
  342. // row6
  343. command.setText(275, 230, '1', 0, 1, 1, 'ADHManufDate:')
  344. command.setText(410, 230, '1', 0, 1, 1, ret.rawProduceDate)
  345. command.setText(275, 250, '1', 0, 1, 1, 'ADHExpDate:')
  346. command.setText(400, 250, '1', 0, 1, 1, ret.rawExpirationDate)
  347. command.setPagePrint()
  348. blueConfig.value.isLabelSend = true
  349. prepareSend(command.getData())
  350. }
  351. // 高亮行点击事件
  352. const handleHighLightRow = function(ret) {
  353. highLightField.value = ret;
  354. }
  355. const goBack = function() {
  356. uni.$goBack(
  357. `/pages/workbranch/production/shipment/shipmentOrderInfoDetails?params=${JSON.stringify(parseData)}`
  358. )
  359. }
  360. // 关闭错误信息弹窗
  361. const handleCloseErrorTipsModal = async function() {
  362. errorTip.value.close()
  363. }
  364. return {
  365. formData,
  366. highLightField,
  367. goBack,
  368. easyinput,
  369. errorTip,
  370. errorTipMessage,
  371. cardList,
  372. handleHighLightRow,
  373. handleShipmentBoxPrinter,
  374. handleCloseErrorTipsModal
  375. }
  376. }
  377. })
  378. </script>
  379. <style lang="scss" scoped>
  380. .gui-header-leader-btns {
  381. color: black;
  382. margin-left: 24rpx;
  383. font-size: 24px !important;
  384. }
  385. .list-content {
  386. margin-top: 80px;
  387. min-height: calc(100vh - 80px);
  388. background-color: #edeeee;
  389. }
  390. .input-200 {
  391. width: 200px;
  392. padding-left: 10px;
  393. }
  394. .icon-scan {
  395. font-size: 20px;
  396. text-align: right;
  397. }
  398. .scan {
  399. height: 45px;
  400. width: calc(100% - 48px);
  401. margin: 12px;
  402. padding: 0 12px;
  403. display: flex;
  404. justify-content: space-between;
  405. align-items: center;
  406. border-radius: 6px;
  407. background-color: white;
  408. .scan-card {
  409. width: 100%;
  410. display: grid;
  411. grid-template-rows: 1fr;
  412. grid-template-columns: 7fr 2fr;
  413. align-items: center;
  414. input {
  415. height: 35px;
  416. line-height: 35px;
  417. }
  418. text {
  419. width: 100%;
  420. text-align: right;
  421. }
  422. }
  423. }
  424. span,
  425. text {
  426. font-size: 12px;
  427. }
  428. .collapsed-panel {
  429. // height: calc(100vh - 190px);
  430. // min-height: 230px;
  431. margin: 5px 0;
  432. padding: 0 8px;
  433. overflow-y: scroll;
  434. .content {
  435. position: relative;
  436. overflow-y: scroll;
  437. border-top: 2px dashed rgba(237, 238, 238, 1);
  438. .panel-row {
  439. // height: 32px;
  440. line-height: 32px;
  441. padding: 0 12px;
  442. display: flex;
  443. justify-content: space-between;
  444. background-color: #fbfbfb;
  445. span:nth-of-type(1) {
  446. min-width: 30%;
  447. }
  448. span:nth-of-type(2) {
  449. min-width: 30%;
  450. padding-right: 8px;
  451. text-align: right;
  452. word-wrap: break-word;
  453. overflow-y: scroll;
  454. }
  455. }
  456. .font-icons {
  457. position: absolute;
  458. right: 2px;
  459. top: 50%;
  460. transform: translate(0, -50%);
  461. z-index: 1;
  462. }
  463. }
  464. }
  465. .printer {
  466. color: white;
  467. background-color: #00a0e9 !important;
  468. }
  469. .operation-panel {
  470. padding: 12px 0;
  471. position: fixed;
  472. bottom: 0;
  473. width: 100%;
  474. display: grid;
  475. grid-template-columns: 1fr;
  476. grid-template-rows: 1fr;
  477. background-color: white;
  478. .operation-title {
  479. height: 40px;
  480. line-height: 40px;
  481. padding: 0 14px;
  482. font-size: 16px;
  483. font-weight: bold;
  484. }
  485. }
  486. </style>