SemiFinishedProtuctsEntry.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  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 class="gui-flex1 gui-text-center gui-color-white">半成品入库【入库人:{{ scanPersonName }}】</text>
  10. <!-- 此处加一个右侧展位元素与左侧同宽,实现标题居中 -->
  11. <!-- 实际宽度请根据自己情况设置 -->
  12. <view style="width:40px;">
  13. <uni-easyinput v-model="batchNumber" type="text" class="hidden-focus" ref="scanRefs" focus @confirm="handleConfirmText" />
  14. </view>
  15. <!-- 如果右侧有其他内容可以利用条件编译和定位来实现-->
  16. </view>
  17. </template>
  18. <template #gBody>
  19. <view class="list-content">
  20. <div class="operation-header">
  21. <view class="operation-header-item">
  22. <text>条码号</text>
  23. <text>{{ formData.batchNumber }}</text>
  24. </view>
  25. <view class="operation-header-item">
  26. <text>产品名称</text>
  27. <text>{{ formData.productName }}</text>
  28. </view>
  29. <view class="operation-header-item">
  30. <text>条码数/已扫入总数</text>
  31. <text>{{ computedSumQty }}</text>
  32. </view>
  33. <view v-if="!scanPersonId" class="operation-header-item-tips">
  34. <text><text class="font-icons">&#xe6d6;</text>请扫描入库人员厂牌完成入库</text>
  35. </view>
  36. <view v-else class="operation-header-item-tips-success">
  37. <text><text class="font-icons">&#xe6d6;</text>已扫描员工码,可进行入库</text>
  38. </view>
  39. </div>
  40. <view class="collapsed-panel">
  41. <div class="collapsed-title">
  42. <text><text class="font-icons">&#xe6da;</text>入库列表</text>
  43. </div>
  44. <view v-if="cardList.length > 0">
  45. <view v-for="item in cardList" :key="item.id" @click="handleShowDetail(item)">
  46. <uni-swipe-action>
  47. <!-- 基础用法 -->
  48. <uni-swipe-action-item :right-options="options" @click="handleRemoveDetail(item)">
  49. <template #left>
  50. <view />
  51. </template>
  52. <div class="collapsed-item">
  53. <text>{{ item.batchNumber }}/ {{ item.productName }}/ {{ item.boxQty }}
  54. PCS</text>
  55. <text class="font-icons"
  56. :style="{ color: item.signStatus? '#479e5e': '#b7b7b7'}">&#xe844;</text>
  57. </div>
  58. </uni-swipe-action-item>
  59. </uni-swipe-action>
  60. </view>
  61. </view>
  62. <view v-else>
  63. <view class="bg-image">
  64. <image src="@/static/empty.png" mode="heightFix" />
  65. <text>这里什么都没有...</text>
  66. </view>
  67. </view>
  68. </view>
  69. </view>
  70. <uni-popup ref="errorTip" type="dialog">
  71. <uni-popup-dialog type="error" cancel-text="关闭" confirm-text="确认" title="提示" :content="errorTipMessage"
  72. @confirm="handleCloseErrorTipsModal" @close="handleCloseErrorTipsModal" />
  73. </uni-popup>
  74. </template>
  75. </gui-page>
  76. </template>
  77. <script>
  78. import {
  79. onMounted,
  80. computed,
  81. reactive,
  82. defineComponent,
  83. onBeforeMount,
  84. toRefs,
  85. ref
  86. } from 'vue'
  87. import tsc from '@/unit/CHITEN_SDK_APP/tsc.js'
  88. export default defineComponent({
  89. setup(options) {
  90. const errorState = ref(0)
  91. const errorTip = ref('')
  92. const errorTipMessage = ref('')
  93. const formData = ref({
  94. batchNumber: null,
  95. productName: null,
  96. boxQty: 0,
  97. sumQty: 0
  98. })
  99. const cardList = ref([])
  100. // 隐藏输入框
  101. const scanRefs = ref()
  102. const queryParams = reactive({
  103. batchNumber: '',
  104. scanPersonId: null,
  105. scanPersonName: '未绑定',
  106. })
  107. // 条码数/总数
  108. const computedSumQty = computed(() => {
  109. return formData.value.boxQty + '/' + formData.value.sumQty + ' PCS'
  110. })
  111. onMounted(() => {
  112. // 每3s自动定位到扫码框
  113. setInterval(() => {
  114. if (scanRefs.value.focusShow) {
  115. // #ifdef APP-PLUS
  116. setTimeout(() => {
  117. uni.hideKeyboard()
  118. }, 100)
  119. // #endif
  120. } else {
  121. scanRefs.value.onBlur()
  122. scanRefs.value.onFocus()
  123. }
  124. }, 1000)
  125. })
  126. // 获取入库列表
  127. const search = function() {
  128. uni.$reqGet('getProductMiddleDetailPage', {
  129. scanPersonId: queryParams.scanPersonId,
  130. })
  131. .then(async ({
  132. code,
  133. data,
  134. msg
  135. }) => {
  136. if (code === 0) {
  137. cardList.value = data?.list ?? [];
  138. } else {
  139. // #ifdef APP-PLUS
  140. plus.device.beep(2)
  141. // #endif
  142. errorTipMessage.value = msg
  143. errorTip.value.open()
  144. errorState.value = 0
  145. }
  146. })
  147. }
  148. // 详情
  149. const handleShowDetail = function(ret) {
  150. Object.assign(formData.value, ret)
  151. }
  152. const handleRemoveDetail = function(ret) {
  153. uni.$reqDelete("deleteProductMiddleDetail", {
  154. id: ret?.id
  155. })
  156. .then(async ({
  157. code,
  158. data,
  159. msg
  160. }) => {
  161. if (code === 0) {
  162. // 重新获取列表数据
  163. search()
  164. } else {
  165. // #ifdef APP-PLUS
  166. plus.device.beep(2)
  167. // #endif
  168. errorTipMessage.value = msg
  169. errorTip.value.open()
  170. errorState.value = -1
  171. }
  172. })
  173. }
  174. const goBack = function() {
  175. uni.$goBack('/pages/workbranch/warehouse/SemiFinishedProducts/indexPage')
  176. }
  177. // 扫码入库
  178. const handleScanProductMiddle = function() {
  179. uni.$reqPost("scanProductMiddleDetailEntry", {
  180. batchNumber: queryParams.batchNumber,
  181. scanPersonId: queryParams.scanPersonId,
  182. scanPersonName: queryParams.scanPersonName
  183. })
  184. .then(async ({
  185. code,
  186. data,
  187. msg
  188. }) => {
  189. if (code === 0) {
  190. search()
  191. setInputFocus()
  192. } else {
  193. // #ifdef APP-PLUS
  194. plus.device.beep(2)
  195. // #endif
  196. errorTipMessage.value = msg
  197. errorTip.value.open()
  198. errorState.value = -1
  199. }
  200. })
  201. }
  202. const handleConfirmText = function(e) {
  203. // 扫码入库
  204. if (queryParams.scanPersonId && queryParams.scanPersonName) {
  205. // 存在员工码,扫码入库
  206. handleScanProductMiddle(e)
  207. } else {
  208. uni.$reqGet("getEmployeeMaster", {
  209. id: e
  210. })
  211. .then(async ({
  212. code,
  213. data,
  214. msg
  215. }) => {
  216. if (code === 0) {
  217. // 绑定员工
  218. if (!!data) {
  219. queryParams.scanPersonId = data.id
  220. queryParams.scanPersonName = data.employeeName
  221. search()
  222. setInputFocus()
  223. }
  224. } else {
  225. // #ifdef APP-PLUS
  226. plus.device.beep(2)
  227. // #endif
  228. errorTipMessage.value = '员工码不正确,请检查!'
  229. errorTip.value.open()
  230. errorState.value = -1
  231. }
  232. })
  233. }
  234. }
  235. // 禁用软键盘
  236. // const handleInputFocus = function() {
  237. // // #ifdef APP-PLUS
  238. // setTimeout(() => {
  239. // uni.hideKeyboard()
  240. // }, 100)
  241. // // #endif
  242. // }
  243. const setInputFocus = function() {
  244. queryParams.batchNumber = ''
  245. scanRefs.value.onBlur()
  246. scanRefs.value.onFocus()
  247. }
  248. // 关闭错误信息弹窗
  249. const handleCloseErrorTipsModal = async function() {
  250. errorTip.value.close()
  251. if (errorState.value === 0) {
  252. await setInputFocus()
  253. }
  254. }
  255. return {
  256. options: [{
  257. text: '删除',
  258. style: {
  259. backgroundColor: '#dd524d'
  260. }
  261. }],
  262. scanRefs,
  263. ...toRefs(queryParams),
  264. formData,
  265. cardList,
  266. goBack,
  267. errorTip,
  268. errorTipMessage,
  269. computedSumQty,
  270. handleShowDetail,
  271. handleConfirmText,
  272. handleRemoveDetail,
  273. handleCloseErrorTipsModal,
  274. }
  275. }
  276. })
  277. </script>
  278. <style lang="scss" scoped>
  279. .gui-header-leader-btns {
  280. color: black;
  281. margin-left: 24rpx;
  282. font-size: 24px !important;
  283. }
  284. .list-content {
  285. margin-top: 68px;
  286. min-height: calc(100vh - 68px);
  287. position: relative;
  288. background-color: #edeeee;
  289. }
  290. .input-200 {
  291. width: 200px;
  292. padding-left: 10px;
  293. }
  294. .icon-scan {
  295. font-size: 20px;
  296. text-align: right;
  297. }
  298. .scan {
  299. height: 45px;
  300. width: calc(100% - 48px);
  301. margin: 12px;
  302. padding: 0 12px;
  303. display: flex;
  304. justify-content: space-between;
  305. align-items: center;
  306. border-radius: 6px;
  307. background-color: white;
  308. .scan-card {
  309. width: 100%;
  310. display: grid;
  311. grid-template-rows: 1fr;
  312. grid-template-columns: 7fr 2fr;
  313. align-items: center;
  314. input {
  315. height: 35px;
  316. line-height: 35px;
  317. }
  318. text {
  319. width: 100%;
  320. text-align: right;
  321. }
  322. }
  323. }
  324. span,
  325. text {
  326. font-size: 12px;
  327. }
  328. .collapsed-panel {
  329. // height: calc(100vh - 190px);
  330. width: calc(100vw - 24px);
  331. min-height: 230px;
  332. position: absolute;
  333. top: 105px;
  334. // bottom: 70px;
  335. bottom: 0px;
  336. padding: 0 12px;
  337. border-radius: 15px 15px 0 0;
  338. background-color: white;
  339. overflow-y: scroll;
  340. .collapsed-title {
  341. font-size: 14px;
  342. font-weight: bold;
  343. padding: 8px;
  344. position: sticky;
  345. top: 0;
  346. left: 0;
  347. width: calc(100% - 12px);
  348. z-index: 1;
  349. background-color: white;
  350. }
  351. .collapsed-item {
  352. display: flex;
  353. justify-content: space-between;
  354. align-items: center;
  355. padding: 8px;
  356. margin: 4px 0;
  357. border-radius: 4px;
  358. background-color: #f3f3f3;
  359. .font-icons {
  360. font-size: 14px;
  361. }
  362. }
  363. .collapsed-title+uni-view:nth-of-type(1) {
  364. margin-top: 8px;
  365. }
  366. }
  367. .operation-panel {
  368. padding: 12px 0;
  369. position: fixed;
  370. bottom: 0;
  371. width: 100%;
  372. display: grid;
  373. grid-template-columns: 1fr;
  374. grid-template-rows: 1fr;
  375. background-color: white;
  376. .operation-title {
  377. height: 40px;
  378. line-height: 40px;
  379. padding: 0 14px;
  380. font-size: 16px;
  381. font-weight: bold;
  382. }
  383. }
  384. .hidden-focus {
  385. position: fixed;
  386. top: 0;
  387. left: 0;
  388. z-index: -1;
  389. opacity: 0;
  390. }
  391. .operation-header {
  392. height: 130px;
  393. background-color: #4badf4;
  394. .operation-header-item {
  395. display: flex;
  396. flex-direction: row;
  397. justify-content: space-between;
  398. align-items: center;
  399. padding: 4px 12px;
  400. font-size: 12px;
  401. color: white;
  402. }
  403. .operation-header-item-tips {
  404. display: flex;
  405. flex-direction: row;
  406. justify-content: center;
  407. align-items: center;
  408. padding: 2px 12px;
  409. font-size: 14px;
  410. font-weight: bold;
  411. color: gold;
  412. }
  413. .operation-header-item-tips-success {
  414. display: flex;
  415. flex-direction: row;
  416. justify-content: center;
  417. align-items: center;
  418. padding: 2px 12px;
  419. font-size: 14px;
  420. font-weight: bold;
  421. color: lightgreen;
  422. }
  423. }
  424. </style>