materialScanRegister.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. <template>
  2. <gui-page :custom-header="true" :is-header-sized="false"
  3. :header-class="['gui-theme-background-color', isLandscapeScreen?'width: 100vmax;':'']"
  4. :style="[isLandscapeScreen?'width: 100vmax':'']">
  5. <template #gHeader>
  6. <view :style="[isLandscapeScreen?'height:44px;width: 100vmax':'height:44px;']"
  7. class="gui-flex gui-nowrap gui-rows gui-align-items-center">
  8. <!-- 使用组件实现返回按钮及返回首页按钮 -->
  9. <text style="font-size:44rpx;" class="gui-header-leader-btns gui-color-white font-icons"
  10. @tap="goBack">&#xe6c5;</text>
  11. <!-- 导航文本此处也可以是其他自定义内容 -->
  12. <text
  13. class="gui-h4 gui-blod gui-flex1 gui-text-center gui-color-white gui-ellipsis gui-primary-text">来料登记</text>
  14. <!-- 此处加一个右侧展位元素与左侧同宽,实现标题居中 -->
  15. <!-- 实际宽度请根据自己情况设置 -->
  16. <view style="width:40px;" />
  17. </view>
  18. </template>
  19. <template #gBody>
  20. <view class="form">
  21. <view class="card-list-flexbox">
  22. <text class="card-list-title" :style="[isPad?'font-size: 18px':'font-size: 14px']">单据信息</text>
  23. <view class="card-list-item">
  24. <text>送货单号</text>
  25. <text>{{ scanParams.deliveryOrderNo }}</text>
  26. </view>
  27. <view class="card-list-item">
  28. <text>供应商编码</text>
  29. <text>{{ scanParams.supplierCode }}</text>
  30. </view>
  31. <view class="card-list-item">
  32. <text>供应商名称</text>
  33. <text>{{ scanParams.supplierName }}</text>
  34. </view>
  35. <view class="card-list-item">
  36. <text>备注</text>
  37. <text>{{ scanParams.remark }}</text>
  38. </view>
  39. <view class="card-list-item">
  40. <text>扫码类型</text>
  41. <text>{{ scanTypeLabel }}</text>
  42. </view>
  43. </view>
  44. <view class="row">
  45. <view class="row-card">
  46. <uni-data-select v-model="scanParams.scanType" :localdata="scanTypeList" placeholder="请选择扫码类型" />
  47. </view>
  48. </view>
  49. <view class="row">
  50. <view class="row-card">
  51. <uni-easyinput ref="easyinput" v-model="scanParams.deliveryOrderNo" :input-border="false"
  52. :clearable="false" type="text" focus @focus="handleInputFocus" placeholder="扫描送货单条码"
  53. @confirm="confirmDeliverOrderNo" />
  54. <text class="font-icons" @click="handleMapass"></text>
  55. </view>
  56. </view>
  57. <view v-if="scanParams.deliveryOrderNo" class="row">
  58. <view class="row-card">
  59. <uni-easyinput ref="easyinput2" v-model="scanParams.deliverBatch" :input-border="false"
  60. :clearable="false" type="text" @focus="handleInputFocus" placeholder="扫描物料条码"
  61. @confirm="confirmMaterial" />
  62. <text class="font-icons" @click="handleScanMaterial"></text>
  63. </view>
  64. </view>
  65. <view class="table-title">
  66. <span>需求清单</span>
  67. </view>
  68. <view class="custom-table">
  69. <uni-table border stripe empty-text="暂无更多数据">
  70. <!-- 表头行 -->
  71. <uni-tr class="custom-table-head">
  72. <uni-th align="center" width="80px">数量</uni-th>
  73. <uni-th align="center" width="140px">采购单号</uni-th>
  74. <uni-th align="center" width="140px">物料编码</uni-th>
  75. <uni-th align="center" width="140px">送货批次</uni-th>
  76. <uni-th align="center" width="140px">生产日期</uni-th>
  77. </uni-tr>
  78. <!-- 表格数据行 -->
  79. <uni-tr v-for="(item, key) in scanParams.detail" :key="key">
  80. <uni-td align="center"
  81. :style="item.state? 'background-color: rgba(109, 205, 50, 1);color: white;': ''">{{ item.receiptQty }}</uni-td>
  82. <uni-td align="center"
  83. :style="item.state? 'background-color: rgba(109, 205, 50, 1);color: white;': ''">{{ item.purchaseOrderNo }}</uni-td>
  84. <uni-td align="center"
  85. :style="item.state? 'background-color: rgba(109, 205, 50, 1);color: white;': ''">{{ item.materialNo }}</uni-td>
  86. <uni-td align="center"
  87. :style="item.state? 'background-color: rgba(109, 205, 50, 1);color: white;': ''">{{ item.deliverBatch }}</uni-td>
  88. <uni-td align="center"
  89. :style="item.state? 'background-color: rgba(109, 205, 50, 1);color: white;': ''">{{ item.produceDate }}</uni-td>
  90. </uni-tr>
  91. </uni-table>
  92. </view>
  93. <gui-right-menus>
  94. <!-- 扩展按钮 -->
  95. <template #menus-more>
  96. <view hover-class="gui-tap"
  97. class="menu-items gui-bg-green gui-flex gui-columns gui-justify-content-center"
  98. @click="handeleRegister">
  99. <text class="menu-text gui-block gui-text-center gui-color-white">登记</text>
  100. </view>
  101. <view hover-class="gui-tap"
  102. class="menu-items gui-bg-blue gui-flex gui-columns gui-justify-content-center"
  103. @click="handleNavigateToRegisterRecord">
  104. <text class="menu-text gui-block gui-text-center gui-color-white">登记记录</text>
  105. </view>
  106. </template>
  107. <!-- 核心按钮 -->
  108. <template #menus-primary>
  109. <view class="menu-items gui-bg-primary gui-flex gui-columns gui-justify-content-center">
  110. <text class="menu-icon gui-color-white gui-block gui-text-center gui-icons"></text>
  111. <text class="menu-text gui-color-white gui-block gui-text-center">操作</text>
  112. </view>
  113. </template>
  114. </gui-right-menus>
  115. <uni-popup ref="modalForm" type="dialog">
  116. <uni-popup-dialog type="error" cancel-text="不使用" confirm-text="继续使用" title="提示" content="此物料已过保质期!"
  117. @confirm="handleCompleteDialog" @close="handleCloseDialog" />
  118. </uni-popup>
  119. <uni-popup ref="errorTip" type="dialog">
  120. <uni-popup-dialog type="error" cancel-text="关闭" confirm-text="确认" title="提示"
  121. :content="errorTipMessage" @confirm="handleCloseErrorTipsModal"
  122. @close="handleCloseErrorTipsModal" />
  123. </uni-popup>
  124. </view>
  125. </template>
  126. </gui-page>
  127. </template>
  128. <script>
  129. import {
  130. defineComponent,
  131. ref,
  132. computed,
  133. onMounted
  134. } from 'vue'
  135. export default defineComponent({
  136. setup() {
  137. const modalForm = ref('')
  138. const errorTip = ref('')
  139. const errorTipMessage = ref('')
  140. const easyinput = ref('')
  141. const easyinput2 = ref('')
  142. const errorState = ref(0)
  143. const fdIndex = ref(0)
  144. const scanParams = ref({
  145. deliveryOrderNo: '',
  146. supplierCode: '',
  147. supplierName: '',
  148. remark: '',
  149. scanType: '',
  150. deliverBatch: '',
  151. validateFlag: -1,
  152. detail: []
  153. })
  154. const scanTypeList = ref([])
  155. const handleMapass = function() {
  156. // uni.$reqGet("scanDeliveryOrderNo", {
  157. // deliveryOrderNo: "CGSH230907000007"
  158. // })
  159. // .then(({
  160. // code,
  161. // data,
  162. // msg
  163. // }) => {
  164. // if (code === 0) {
  165. // Object.assign(scanParams.value, data);
  166. // setInputFocus2();
  167. // } else {
  168. // // #ifdef APP-PLUS
  169. // plus.device.beep(2);
  170. // // #endif
  171. // errorTipMessage.value = msg;
  172. // errorTip.value.open();
  173. // errorState.value = 0;
  174. // }
  175. // })
  176. // #ifdef APP-PLUS
  177. const mpaasScanModule = uni.requireNativePlugin('Mpaas-Scan-Module')
  178. mpaasScanModule.mpaasScan({
  179. // 扫码识别类型,参数可多选,qrCode、barCode,不设置,默认识别所有
  180. 'scanType': ['qrCode', 'barCode'],
  181. // 是否隐藏相册,默认false不隐藏
  182. 'hideAlbum': false
  183. },
  184. (ret) => {
  185. // errorTipMessage.value = ret.resp_code + "-" + ret.resp_result;
  186. // errorTip.value.open();
  187. // errorState.value = -1;
  188. if (ret.resp_code === 1000) {
  189. uni.$reqGet('scanDeliveryOrderNo', {
  190. deliveryOrderNo: ret.resp_result
  191. })
  192. .then(({
  193. code,
  194. data,
  195. msg
  196. }) => {
  197. if (code === 0) {
  198. Object.assign(scanParams.value, data)
  199. setInputFocus2()
  200. } else {
  201. // #ifdef APP-PLUS
  202. plus.device.beep(2)
  203. // #endif
  204. errorTipMessage.value = msg
  205. errorTip.value.open()
  206. errorState.value = 0
  207. }
  208. })
  209. }
  210. })
  211. // #endif
  212. }
  213. // 扫描送货单输入框回车事件
  214. const confirmDeliverOrderNo = function(e) {
  215. uni.$reqGet('scanDeliveryOrderNo', {
  216. deliveryOrderNo: e,
  217. tableName: scanParams.value.scanType,
  218. })
  219. .then(({
  220. code,
  221. data,
  222. msg
  223. }) => {
  224. if (code === 0) {
  225. Object.assign(scanParams.value, data)
  226. setInputFocus2()
  227. } else {
  228. // #ifdef APP-PLUS
  229. plus.device.beep(2)
  230. // #endif
  231. errorTipMessage.value = msg
  232. errorTip.value.open()
  233. errorState.value = 0
  234. }
  235. })
  236. }
  237. const handleScanMaterial = function() {
  238. // #ifdef APP-PLUS
  239. const mpaasScanModule = uni.requireNativePlugin('Mpaas-Scan-Module')
  240. mpaasScanModule.mpaasScan({
  241. // 扫码识别类型,参数可多选,qrCode、barCode,不设置,默认识别所有
  242. 'scanType': ['qrCode', 'barCode'],
  243. // 是否隐藏相册,默认false不隐藏
  244. 'hideAlbum': false
  245. },
  246. (ret) => {
  247. if (ret.resp_code === 1000) {
  248. uni.$reqGet('scanRegisterMaterial', {
  249. batchNumber: ret.resp_result
  250. })
  251. .then(({
  252. code,
  253. data,
  254. msg
  255. }) => {
  256. scanParams.value.deliverBatch = data?.deliverBatch
  257. if (code === 0) {
  258. fdIndex.value = scanParams.value.detail.findIndex(item => item
  259. ?.deliverBatch ===
  260. data?.deliverBatch)
  261. if (fdIndex.value !== -1) {
  262. if (data?.ifExpired === 1) {
  263. // 物料超过保质期
  264. modalForm.value.open()
  265. } else {
  266. setInputFocus2()
  267. scanParams.value.detail[fdIndex.value].state = true
  268. }
  269. } else {
  270. // #ifdef APP-PLUS
  271. plus.device.beep(2)
  272. // #endif
  273. errorTipMessage.value = '请扫描正确的物料'
  274. errorTip.value.open()
  275. errorState.value = 1
  276. }
  277. } else {
  278. // #ifdef APP-PLUS
  279. plus.device.beep(2)
  280. // #endif
  281. errorTipMessage.value = msg
  282. errorTip.value.open()
  283. errorState.value = 1
  284. }
  285. })
  286. }
  287. })
  288. // #endif
  289. }
  290. // 扫描物料输入框回车事件
  291. const confirmMaterial = function(e) {
  292. uni.$reqGet('scanRegisterMaterial', {
  293. batchNumber: e
  294. })
  295. .then(({
  296. code,
  297. data,
  298. msg
  299. }) => {
  300. scanParams.value.deliverBatch = data?.deliverBatch
  301. if (code === 0) {
  302. fdIndex.value = scanParams.value.detail.findIndex(item => item
  303. ?.deliverBatch ===
  304. data?.deliverBatch)
  305. if (fdIndex.value !== -1) {
  306. if (data?.ifExpired === 1) {
  307. // 物料超过保质期
  308. modalForm.value.open()
  309. } else {
  310. setInputFocus2()
  311. scanParams.value.detail[fdIndex.value].state = true
  312. }
  313. } else {
  314. // #ifdef APP-PLUS
  315. plus.device.beep(2)
  316. // #endif
  317. errorTipMessage.value = '请扫描正确的物料'
  318. errorTip.value.open()
  319. errorState.value = 1
  320. }
  321. } else {
  322. // #ifdef APP-PLUS
  323. plus.device.beep(2)
  324. // #endif
  325. errorTipMessage.value = msg
  326. errorTip.value.open()
  327. errorState.value = 1
  328. }
  329. })
  330. }
  331. const handleNavigateToRegisterRecord = function() {
  332. uni.navigateTo({
  333. url: '/pages/workbranch/warehouse/materialRegister/Record/registerRecord'
  334. })
  335. }
  336. // 登记
  337. const handeleRegister = function() {
  338. let isTrue = false
  339. if (scanParams.value.detail.length === 0) {
  340. // #ifdef APP-PLUS
  341. plus.device.beep(2)
  342. // #endif
  343. errorTipMessage.value = '登记数据不能为空'
  344. errorTip.value.open()
  345. errorState.value = 0
  346. return
  347. }
  348. if (scanParams.value.validateFlag === 0) {
  349. isTrue = true
  350. } else {
  351. isTrue = scanParams.value.detail.every(item => item.state === true)
  352. }
  353. if (isTrue) {
  354. uni.showLoading({
  355. title: '数据请求中',
  356. duration: 20000,
  357. mask: true
  358. })
  359. uni.$reqPost('incomingReceiptMasterCreate', scanParams.value)
  360. .then(({
  361. code,
  362. data,
  363. msg
  364. }) => {
  365. scanParams.value = {
  366. deliveryOrderNo: '',
  367. supplierCode: '',
  368. supplierName: '',
  369. remark: '',
  370. scanType: '',
  371. deliverBatch: '',
  372. validateFlag: -1,
  373. detail: []
  374. }
  375. if (code === 0) {
  376. uni.showToast({
  377. title: '来料登记成功',
  378. icon: 'none',
  379. duration: 2000
  380. })
  381. } else {
  382. // #ifdef APP-PLUS
  383. plus.device.beep(2)
  384. // #endif
  385. errorTipMessage.value = msg
  386. errorTip.value.open()
  387. errorState.value = -1
  388. }
  389. })
  390. .finally(() => {
  391. uni.hideLoading()
  392. })
  393. } else {
  394. // #ifdef APP-PLUS
  395. plus.device.beep(2)
  396. // #endif
  397. errorTipMessage.value = '请填写完整需求清单'
  398. errorTip.value.open()
  399. errorState.value = 1
  400. }
  401. }
  402. const handleCompleteDialog = function() {
  403. setInputFocus2()
  404. scanParams.value.detail[fdIndex.value].state = true
  405. modalForm.value.close()
  406. }
  407. const handleCloseDialog = function() {
  408. setInputFocus2()
  409. modalForm.value.close()
  410. }
  411. const goBack = function() {
  412. uni.$goBack('/pages/workbranch/warehouse/materialRegister/registerType')
  413. }
  414. const setInputFocus = function() {
  415. scanParams.value.deliveryOrderNo = ''
  416. easyinput.value.onBlur()
  417. easyinput.value.onFocus()
  418. }
  419. const setInputFocus2 = function() {
  420. scanParams.value.deliverBatch = ''
  421. easyinput2.value.onBlur()
  422. easyinput2.value.onFocus()
  423. }
  424. // 关闭错误信息弹窗
  425. const handleCloseErrorTipsModal = async function() {
  426. errorTip.value.close()
  427. if (errorState.value === 0) {
  428. await setInputFocus()
  429. } else if (errorState.value === 1) {
  430. await setInputFocus2()
  431. }
  432. }
  433. // 禁用软键盘
  434. const handleInputFocus = function() {
  435. setTimeout(() => {
  436. uni.hideKeyboard()
  437. }, 100)
  438. }
  439. // 计算属性:获取扫码类型的中文标签
  440. const scanTypeLabel = computed(() => {
  441. if (!scanParams.value.scanType) return '未选择'
  442. const typeItem = scanTypeList.value.find(item => item.value === scanParams.value.scanType)
  443. return typeItem ? typeItem.text : scanParams.value.scanType
  444. })
  445. onMounted(() => {
  446. // 获取扫码类型字典数据
  447. uni.$reqGet('getDictDataPage', {
  448. dictType: 'srm_tablename_type', // 使用字典编码418
  449. pageNo: 1,
  450. pageSize: 100
  451. }).then(({ data }) => {
  452. scanTypeList.value = []
  453. const dataList = data?.list || [];
  454. for (var i = 0; i < dataList.length; i++) {
  455. scanTypeList.value.push({
  456. text: dataList[i].label,
  457. value: dataList[i].value,
  458. })
  459. }
  460. })
  461. })
  462. return {
  463. goBack,
  464. modalForm,
  465. easyinput,
  466. easyinput2,
  467. errorState,
  468. errorTip,
  469. errorTipMessage,
  470. scanParams,
  471. scanTypeList,
  472. scanTypeLabel,
  473. handleMapass,
  474. handleInputFocus,
  475. handleCompleteDialog,
  476. handleCloseDialog,
  477. handleScanMaterial,
  478. handeleRegister,
  479. confirmMaterial,
  480. confirmDeliverOrderNo,
  481. handleCloseErrorTipsModal,
  482. handleNavigateToRegisterRecord
  483. }
  484. }
  485. })
  486. </script>
  487. <style lang="scss" scoped>
  488. .gui-header-leader-btns {
  489. color: black;
  490. font-size: 24px !important;
  491. }
  492. .gui-sbody {
  493. background-color: rgba(234, 239, 242, 1);
  494. }
  495. .form {
  496. margin-top: 85px;
  497. font-size: 14px;
  498. }
  499. .row {
  500. height: 55px;
  501. display: flex;
  502. justify-content: center;
  503. padding-left: 20px;
  504. padding-right: 20px;
  505. margin: 10px 0;
  506. background-color: white;
  507. .row-card {
  508. display: flex;
  509. flex-direction: row;
  510. justify-content: space-between;
  511. align-items: center;
  512. width: calc(375px - 30px);
  513. }
  514. }
  515. .input-200 {
  516. width: 200px;
  517. padding-left: 10px;
  518. }
  519. .font-icons {
  520. width: 40px;
  521. font-size: 20px;
  522. text-align: right;
  523. }
  524. .card-list-flexbox {
  525. width: calc(100vw - 24px);
  526. height: 195px;
  527. margin: 0 12px;
  528. display: flex;
  529. justify-content: center;
  530. flex-direction: column;
  531. align-items: center;
  532. overflow-y: scroll;
  533. .card-list-title {
  534. width: 100%;
  535. height: 35px;
  536. line-height: 35px;
  537. margin: 0 4px 0 4px;
  538. border-radius: 4px 4px 0 0;
  539. text-align: center;
  540. color: white;
  541. background-color: rgba(0, 160, 233, 1.0);
  542. }
  543. .card-list-item,
  544. .card-list-item-operation {
  545. width: 100%;
  546. height: 35px;
  547. margin: 0 4px 3rpx 4px;
  548. border-radius: 4px;
  549. display: flex;
  550. flex-direction: row;
  551. align-items: center;
  552. justify-content: space-between;
  553. background-color: #fff;
  554. uni-text {
  555. font-size: 14px;
  556. height: 50rpx;
  557. text-align: left;
  558. padding: 0 8px;
  559. display: flex;
  560. flex-direction: row;
  561. align-items: center;
  562. }
  563. .text-1 {
  564. flex: 1;
  565. height: 35px;
  566. justify-content: flex-start;
  567. }
  568. .text-2 {
  569. flex: 3;
  570. height: 35px;
  571. justify-content: flex-end;
  572. margin-right: 4px;
  573. padding: 2px 6px;
  574. }
  575. }
  576. }
  577. .table-title {
  578. height: 40px;
  579. line-height: 40px;
  580. margin: 4px 0 -3px 0;
  581. padding: 0 12px;
  582. font-size: 16px;
  583. font-weight: bold;
  584. background-color: white;
  585. }
  586. .custom-table {
  587. height: calc(100vh - 405px);
  588. min-height: 230px;
  589. margin: 5px 0;
  590. overflow-y: scroll;
  591. }
  592. </style>