materialScanRegister.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  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. tableName: scanParams.value.scanType
  192. })
  193. .then(({
  194. code,
  195. data,
  196. msg
  197. }) => {
  198. if (code === 0) {
  199. Object.assign(scanParams.value, data)
  200. setInputFocus2()
  201. } else {
  202. // #ifdef APP-PLUS
  203. plus.device.beep(2)
  204. // #endif
  205. errorTipMessage.value = msg
  206. errorTip.value.open()
  207. errorState.value = 0
  208. }
  209. })
  210. }
  211. })
  212. // #endif
  213. }
  214. // 扫描送货单输入框回车事件
  215. const confirmDeliverOrderNo = function(e) {
  216. uni.$reqGet('scanDeliveryOrderNo', {
  217. deliveryOrderNo: e,
  218. tableName: scanParams.value.scanType,
  219. })
  220. .then(({
  221. code,
  222. data,
  223. msg
  224. }) => {
  225. if (code === 0) {
  226. Object.assign(scanParams.value, data)
  227. setInputFocus2()
  228. } else {
  229. // #ifdef APP-PLUS
  230. plus.device.beep(2)
  231. // #endif
  232. errorTipMessage.value = msg
  233. errorTip.value.open()
  234. errorState.value = 0
  235. }
  236. })
  237. }
  238. const handleScanMaterial = function() {
  239. // #ifdef APP-PLUS
  240. const mpaasScanModule = uni.requireNativePlugin('Mpaas-Scan-Module')
  241. mpaasScanModule.mpaasScan({
  242. // 扫码识别类型,参数可多选,qrCode、barCode,不设置,默认识别所有
  243. 'scanType': ['qrCode', 'barCode'],
  244. // 是否隐藏相册,默认false不隐藏
  245. 'hideAlbum': false
  246. },
  247. (ret) => {
  248. if (ret.resp_code === 1000) {
  249. uni.$reqGet('scanRegisterMaterial', {
  250. batchNumber: ret.resp_result
  251. })
  252. .then(({
  253. code,
  254. data,
  255. msg
  256. }) => {
  257. scanParams.value.deliverBatch = data?.deliverBatch
  258. if (code === 0) {
  259. fdIndex.value = scanParams.value.detail.findIndex(item => item
  260. ?.deliverBatch ===
  261. data?.deliverBatch)
  262. if (fdIndex.value !== -1) {
  263. if (data?.ifExpired === 1) {
  264. // 物料超过保质期
  265. modalForm.value.open()
  266. } else {
  267. setInputFocus2()
  268. scanParams.value.detail[fdIndex.value].state = true
  269. }
  270. } else {
  271. // #ifdef APP-PLUS
  272. plus.device.beep(2)
  273. // #endif
  274. errorTipMessage.value = '请扫描正确的物料'
  275. errorTip.value.open()
  276. errorState.value = 1
  277. }
  278. } else {
  279. // #ifdef APP-PLUS
  280. plus.device.beep(2)
  281. // #endif
  282. errorTipMessage.value = msg
  283. errorTip.value.open()
  284. errorState.value = 1
  285. }
  286. })
  287. }
  288. })
  289. // #endif
  290. }
  291. // 扫描物料输入框回车事件
  292. const confirmMaterial = function(e) {
  293. uni.$reqGet('scanRegisterMaterial', {
  294. batchNumber: e
  295. })
  296. .then(({
  297. code,
  298. data,
  299. msg
  300. }) => {
  301. scanParams.value.deliverBatch = data?.deliverBatch
  302. if (code === 0) {
  303. fdIndex.value = scanParams.value.detail.findIndex(item => item
  304. ?.deliverBatch ===
  305. data?.deliverBatch)
  306. if (fdIndex.value !== -1) {
  307. if (data?.ifExpired === 1) {
  308. // 物料超过保质期
  309. modalForm.value.open()
  310. } else {
  311. setInputFocus2()
  312. scanParams.value.detail[fdIndex.value].state = true
  313. }
  314. } else {
  315. // #ifdef APP-PLUS
  316. plus.device.beep(2)
  317. // #endif
  318. errorTipMessage.value = '请扫描正确的物料'
  319. errorTip.value.open()
  320. errorState.value = 1
  321. }
  322. } else {
  323. // #ifdef APP-PLUS
  324. plus.device.beep(2)
  325. // #endif
  326. errorTipMessage.value = msg
  327. errorTip.value.open()
  328. errorState.value = 1
  329. }
  330. })
  331. }
  332. const handleNavigateToRegisterRecord = function() {
  333. uni.navigateTo({
  334. url: '/pages/workbranch/warehouse/materialRegister/Record/registerRecord'
  335. })
  336. }
  337. // 登记
  338. const handeleRegister = function() {
  339. let isTrue = false
  340. if (scanParams.value.detail.length === 0) {
  341. // #ifdef APP-PLUS
  342. plus.device.beep(2)
  343. // #endif
  344. errorTipMessage.value = '登记数据不能为空'
  345. errorTip.value.open()
  346. errorState.value = 0
  347. return
  348. }
  349. if (scanParams.value.validateFlag === 0) {
  350. isTrue = true
  351. } else {
  352. isTrue = scanParams.value.detail.every(item => item.state === true)
  353. }
  354. if (isTrue) {
  355. uni.showLoading({
  356. title: '数据请求中',
  357. duration: 20000,
  358. mask: true
  359. })
  360. uni.$reqPost('incomingReceiptMasterCreate', scanParams.value)
  361. .then(({
  362. code,
  363. data,
  364. msg
  365. }) => {
  366. scanParams.value = {
  367. deliveryOrderNo: '',
  368. supplierCode: '',
  369. supplierName: '',
  370. remark: '',
  371. scanType: '',
  372. deliverBatch: '',
  373. validateFlag: -1,
  374. detail: []
  375. }
  376. if (code === 0) {
  377. uni.showToast({
  378. title: '来料登记成功',
  379. icon: 'none',
  380. duration: 2000
  381. })
  382. } else {
  383. // #ifdef APP-PLUS
  384. plus.device.beep(2)
  385. // #endif
  386. errorTipMessage.value = msg
  387. errorTip.value.open()
  388. errorState.value = -1
  389. }
  390. })
  391. .finally(() => {
  392. uni.hideLoading()
  393. })
  394. } else {
  395. // #ifdef APP-PLUS
  396. plus.device.beep(2)
  397. // #endif
  398. errorTipMessage.value = '请填写完整需求清单'
  399. errorTip.value.open()
  400. errorState.value = 1
  401. }
  402. }
  403. const handleCompleteDialog = function() {
  404. setInputFocus2()
  405. scanParams.value.detail[fdIndex.value].state = true
  406. modalForm.value.close()
  407. }
  408. const handleCloseDialog = function() {
  409. setInputFocus2()
  410. modalForm.value.close()
  411. }
  412. const goBack = function() {
  413. uni.$goBack('/pages/workbranch/warehouse/materialRegister/registerType')
  414. }
  415. const setInputFocus = function() {
  416. scanParams.value.deliveryOrderNo = ''
  417. easyinput.value.onBlur()
  418. easyinput.value.onFocus()
  419. }
  420. const setInputFocus2 = function() {
  421. scanParams.value.deliverBatch = ''
  422. easyinput2.value.onBlur()
  423. easyinput2.value.onFocus()
  424. }
  425. // 关闭错误信息弹窗
  426. const handleCloseErrorTipsModal = async function() {
  427. errorTip.value.close()
  428. if (errorState.value === 0) {
  429. await setInputFocus()
  430. } else if (errorState.value === 1) {
  431. await setInputFocus2()
  432. }
  433. }
  434. // 禁用软键盘
  435. const handleInputFocus = function() {
  436. setTimeout(() => {
  437. uni.hideKeyboard()
  438. }, 100)
  439. }
  440. // 计算属性:获取扫码类型的中文标签
  441. const scanTypeLabel = computed(() => {
  442. if (!scanParams.value.scanType) return '未选择'
  443. const typeItem = scanTypeList.value.find(item => item.value === scanParams.value.scanType)
  444. return typeItem ? typeItem.text : scanParams.value.scanType
  445. })
  446. onMounted(() => {
  447. // 获取扫码类型字典数据
  448. uni.$reqGet('getDictDataPage', {
  449. dictType: 'srm_tablename_type', // 使用字典编码418
  450. pageNo: 1,
  451. pageSize: 100
  452. }).then(({ data }) => {
  453. scanTypeList.value = []
  454. const dataList = data?.list || [];
  455. for (var i = 0; i < dataList.length; i++) {
  456. scanTypeList.value.push({
  457. text: dataList[i].label,
  458. value: dataList[i].value,
  459. })
  460. }
  461. })
  462. })
  463. return {
  464. goBack,
  465. modalForm,
  466. easyinput,
  467. easyinput2,
  468. errorState,
  469. errorTip,
  470. errorTipMessage,
  471. scanParams,
  472. scanTypeList,
  473. scanTypeLabel,
  474. handleMapass,
  475. handleInputFocus,
  476. handleCompleteDialog,
  477. handleCloseDialog,
  478. handleScanMaterial,
  479. handeleRegister,
  480. confirmMaterial,
  481. confirmDeliverOrderNo,
  482. handleCloseErrorTipsModal,
  483. handleNavigateToRegisterRecord
  484. }
  485. }
  486. })
  487. </script>
  488. <style lang="scss" scoped>
  489. .gui-header-leader-btns {
  490. color: black;
  491. font-size: 24px !important;
  492. }
  493. .gui-sbody {
  494. background-color: rgba(234, 239, 242, 1);
  495. }
  496. .form {
  497. margin-top: 85px;
  498. font-size: 14px;
  499. }
  500. .row {
  501. height: 55px;
  502. display: flex;
  503. justify-content: center;
  504. padding-left: 20px;
  505. padding-right: 20px;
  506. margin: 10px 0;
  507. background-color: white;
  508. .row-card {
  509. display: flex;
  510. flex-direction: row;
  511. justify-content: space-between;
  512. align-items: center;
  513. width: calc(375px - 30px);
  514. }
  515. }
  516. .input-200 {
  517. width: 200px;
  518. padding-left: 10px;
  519. }
  520. .font-icons {
  521. width: 40px;
  522. font-size: 20px;
  523. text-align: right;
  524. }
  525. .card-list-flexbox {
  526. width: calc(100vw - 24px);
  527. height: 195px;
  528. margin: 0 12px;
  529. display: flex;
  530. justify-content: center;
  531. flex-direction: column;
  532. align-items: center;
  533. overflow-y: scroll;
  534. .card-list-title {
  535. width: 100%;
  536. height: 35px;
  537. line-height: 35px;
  538. margin: 0 4px 0 4px;
  539. border-radius: 4px 4px 0 0;
  540. text-align: center;
  541. color: white;
  542. background-color: rgba(0, 160, 233, 1.0);
  543. }
  544. .card-list-item,
  545. .card-list-item-operation {
  546. width: 100%;
  547. height: 35px;
  548. margin: 0 4px 3rpx 4px;
  549. border-radius: 4px;
  550. display: flex;
  551. flex-direction: row;
  552. align-items: center;
  553. justify-content: space-between;
  554. background-color: #fff;
  555. uni-text {
  556. font-size: 14px;
  557. height: 50rpx;
  558. text-align: left;
  559. padding: 0 8px;
  560. display: flex;
  561. flex-direction: row;
  562. align-items: center;
  563. }
  564. .text-1 {
  565. flex: 1;
  566. height: 35px;
  567. justify-content: flex-start;
  568. }
  569. .text-2 {
  570. flex: 3;
  571. height: 35px;
  572. justify-content: flex-end;
  573. margin-right: 4px;
  574. padding: 2px 6px;
  575. }
  576. }
  577. }
  578. .table-title {
  579. height: 40px;
  580. line-height: 40px;
  581. margin: 4px 0 -3px 0;
  582. padding: 0 12px;
  583. font-size: 16px;
  584. font-weight: bold;
  585. background-color: white;
  586. }
  587. .custom-table {
  588. height: calc(100vh - 405px);
  589. min-height: 230px;
  590. margin: 5px 0;
  591. overflow-y: scroll;
  592. }
  593. </style>