materialScanRegister.vue 18 KB

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