| | |
| | | "version": "0.1.0", |
| | | "private": true, |
| | | "scripts": { |
| | | "server": "vue-cli-service serve", |
| | | "serve": "vue-cli-service serve", |
| | | "build": "vue-cli-service build", |
| | | "test:unit": "vue-cli-service test:unit", |
| | | "lint": "vue-cli-service lint" |
| | |
| | | |
| | | //æ¤jsæä»¶æ¯ç¨æ¥èªå®ä¹æ©å±ä¸å¡ä»£ç ï¼å¯ä»¥æ©å±ä¸äºèªå®ä¹é¡µé¢æè
éæ°é
ç½®çæç代ç |
| | | |
| | | import http from '@/api/http.js' |
| | | import { h,createVNode, render,reactive,ref } from 'vue'; |
| | | import { ElDialog , ElForm, ElFormItem, ElInput, ElButton, ElMessage ,ElSelect ,ElOption } from 'element-plus'; // å¼å
¥ElMessageï¼è§£å³æç¤ºæ ååº |
| | | import gridBody from './extend/allocateOrderDetail.vue' |
| | | let extension = { |
| | | components: { |
| | | //æ¥è¯¢ç颿©å±ç»ä»¶ |
| | | gridHeader: '', |
| | | gridBody: '', |
| | | gridBody: gridBody, |
| | | gridFooter: '', |
| | | //æ°å»ºãç¼è¾å¼¹åºæ¡æ©å±ç»ä»¶ |
| | | modelHeader: '', |
| | |
| | | modelFooter: '' |
| | | }, |
| | | tableAction: '', //æå®æå¼ 表çæé(è¿éå¡«å表å,é»è®¤ä¸ç¨å¡«å) |
| | | buttons: { view: [], box: [], detail: [] }, //æ©å±çæé® |
| | | buttons: { view: [ |
| | | { |
| | | name: 'ç»ç', |
| | | type: 'primary', |
| | | value: 'ç»ç', |
| | | onClick: function () { // ä¿®å¤1ï¼ç§»é¤æ ç¨rowåæ°ï¼å æ¥å¿è°è¯ |
| | | console.log('ç»çæé®è¢«ç¹å»ï¼å¼å§æ ¡éª'); |
| | | const selectedRows = this.$refs.table.getSelected(); |
| | | |
| | | // æ ¡éª1ï¼æ¯å¦éä¸è¡ |
| | | if (selectedRows.length === 0) { |
| | | console.log('æ ¡éªä¸éè¿ï¼æªéä¸ä»»ä½åæ®'); |
| | | ElMessage.warning('è¯·éæ©ä¸æ¡åæ®'); |
| | | return; |
| | | } |
| | | // æ ¡éª2ï¼æ¯å¦éä¸åè¡ |
| | | if (selectedRows.length > 1) { |
| | | console.log('æ ¡éªä¸éè¿ï¼éä¸å¤è¡åæ®'); |
| | | ElMessage.warning('åªè½éæ©ä¸æ¡åæ®'); |
| | | return; |
| | | } |
| | | |
| | | const targetRow = selectedRows[0]; |
| | | |
| | | this.$emit('openPalletDialog', targetRow.orderNo); |
| | | } |
| | | }, |
| | | { |
| | | name: 'æ¤éç»ç', |
| | | type: 'primary', |
| | | value: 'æ¤éç»ç', |
| | | onClick: function () { |
| | | console.log('æ¤éç»çæé®è¢«ç¹å»'); |
| | | const mountNode = document.createElement('div'); |
| | | document.body.appendChild(mountNode); |
| | | |
| | | // ååºå¼è¡¨åæ°æ®ï¼æçå·ï¼å¿
å¡«ï¼ |
| | | const formData = reactive({ |
| | | palletCode: '' // æçå·è¾å
¥æ¡ |
| | | }); |
| | | |
| | | // æäº¤è¡¨åçç»ä¸é»è¾ |
| | | const submitForm = async () => { |
| | | const formRef = vnode.component.refs.cancelPalletForm; |
| | | try { |
| | | // æ§è¡è¡¨åæ ¡éªï¼æçå·å¿
å¡«ï¼ |
| | | await formRef.validate(); |
| | | } catch (err) { |
| | | ElMessage.warning('请è¾å
¥ææçæçå·'); |
| | | return; |
| | | } |
| | | |
| | | // åèµ·æ¤éç»çè¯·æ± |
| | | try { |
| | | //console.log('åèµ·æ¤éç»ç请æ±ï¼æçå·ï¼', formData.palletCode.trim()); |
| | | const response = await http.post('/api/InboundOrder/CancelPalletGroup', { |
| | | palletCode: formData.palletCode.trim() |
| | | }); |
| | | |
| | | const { status, message, data } = response; |
| | | if (status) { |
| | | ElMessage.success(`æ¤éç»çæåï¼æçå·ï¼${formData.palletCode.trim()}`); |
| | | this.refresh(); // æååå·æ°å表 |
| | | // å
³éå¯¹è¯æ¡ |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | } else { |
| | | console.log('æ¤éç»ç失败ï¼å端æç¤ºï¼', message); |
| | | ElMessage.error(message || data?.message || 'æ¤éç»ç失败'); |
| | | selectPalletCodeInput(); // éä¸è¾å
¥æ¡æ¹ä¾¿éæ°è¾å
¥ |
| | | } |
| | | } catch (error) { |
| | | console.error('æ¤éç»ç请æ±å¼å¸¸ï¼', error); |
| | | ElMessage.error('ç½ç»å¼å¸¸ææ¥å£é误ï¼è¯·ç¨åéè¯'); |
| | | selectPalletCodeInput(); |
| | | } |
| | | }; |
| | | |
| | | // éä¸è¾å
¥æ¡ææ¬ï¼æ¹ä¾¿éæ°è¾å
¥ï¼ |
| | | const selectPalletCodeInput = () => { |
| | | setTimeout(() => { |
| | | const inputRef = vnode.component.refs.palletCodeInput; |
| | | if (inputRef) { |
| | | const targetInput = inputRef.$el?.querySelector('input') || inputRef; |
| | | targetInput?.focus(); |
| | | targetInput?.select(); |
| | | } |
| | | }, 100); |
| | | }; |
| | | |
| | | // åå»ºå¯¹è¯æ¡VNode |
| | | const vnode = createVNode(ElDialog, { |
| | | title: 'æ¤éç»ç', |
| | | width: '400px', |
| | | modelValue: true, |
| | | appendToBody: true, |
| | | onOpened: () => { |
| | | // å¯¹è¯æ¡æå¼åèªå¨èç¦è¾å
¥æ¡ |
| | | setTimeout(() => { |
| | | const inputRef = vnode.component.refs.palletCodeInput; |
| | | inputRef?.focus(); |
| | | }, 100); |
| | | }, |
| | | 'onUpdate:modelValue': (isVisible) => { |
| | | if (!isVisible) { |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | } |
| | | } |
| | | }, { |
| | | default: () => h(ElForm, { |
| | | model: formData, |
| | | rules: { |
| | | palletCode: [ |
| | | { required: true, message: '请è¾å
¥æçå·', trigger: ['blur', 'enter'] }, |
| | | { min: 1, max: 50, message: 'æçå·é¿åº¦ä¸è½è¶
è¿50个å符', trigger: ['blur', 'input'] } |
| | | ] |
| | | }, |
| | | ref: 'cancelPalletForm' |
| | | }, [ |
| | | // æçå·è¾å
¥é¡¹ |
| | | h(ElFormItem, { label: 'æçå·', prop: 'palletCode', required: true }, [ |
| | | h(ElInput, { |
| | | type: 'text', |
| | | modelValue: formData.palletCode, |
| | | 'onUpdate:modelValue': (val) => { |
| | | formData.palletCode = val; |
| | | }, |
| | | ref: 'palletCodeInput', |
| | | placeholder: 'æ«ç è¾å
¥ææå¨è¾å
¥æçå·', |
| | | maxLength: 50, |
| | | // çå¬å车äºä»¶ï¼æ«ç æªé»è®¤ä¼åéåè½¦ï¼ |
| | | onKeydown: (e) => { |
| | | if (e.key === 'Enter') { |
| | | e.preventDefault(); |
| | | submitForm(); |
| | | } |
| | | } |
| | | }) |
| | | ]), |
| | | // åºé¨æé®åº |
| | | h('div', { style: { textAlign: 'right', marginTop: '16px' } }, [ |
| | | h(ElButton, { |
| | | type: 'text', |
| | | onClick: () => { |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | ElMessage.info('åæ¶æ¤éç»ç'); |
| | | } |
| | | }, 'åæ¶'), |
| | | h(ElButton, { |
| | | type: 'primary', |
| | | onClick: submitForm.bind(this) // ç»å®thisä¸ä¸æ |
| | | }, '确认æ¤é') |
| | | ]) |
| | | ]) |
| | | }); |
| | | |
| | | vnode.appContext = this.$.appContext; |
| | | render(vnode, mountNode); |
| | | } |
| | | }, |
| | | { |
| | | name: 'åæ¹å
¥åº', |
| | | type: 'primary', |
| | | value: 'åæ¹å
¥åº', |
| | | onClick: async function () { |
| | | console.log('åæ¹å
¥åºæé®è¢«ç¹å»ï¼å¼å§æ ¡éª'); |
| | | const selectedRows = this.$refs.table.getSelected(); |
| | | |
| | | // æ ¡éª1ï¼æ¯å¦éä¸è¡ï¼è³å°éæ©ä¸æ¡ï¼ |
| | | if (selectedRows.length === 0) { |
| | | console.log('æ ¡éªä¸éè¿ï¼æªéä¸ä»»ä½åæ®'); |
| | | ElMessage.warning('è¯·éæ©è³å°ä¸æ¡åæ®'); |
| | | return; |
| | | } |
| | | |
| | | // æ¶éææéä¸åæ®çç¼å·ï¼è¿æ»¤æ åæ®å·çå¼å¸¸è¡ï¼ |
| | | const inboundOrderNos = selectedRows |
| | | .filter(row => row.inboundOrderNo) |
| | | .map(row => row.inboundOrderNo); |
| | | |
| | | // æ ¡éª2ï¼æ¯å¦æææåæ®å· |
| | | if (inboundOrderNos.length === 0) { |
| | | console.log('æ ¡éªä¸éè¿ï¼éä¸åæ®æ ææç¼å·'); |
| | | ElMessage.warning('éä¸ç忮䏿 ææç¼å·ï¼è¯·éæ°éæ©'); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | console.log('åèµ·åæ¹å
¥åºè¯·æ±ï¼åæ°ï¼', { inboundOrderNos}); |
| | | const response = await http.post('/api/InboundOrder/BatchOrderFeedbackToMes', { |
| | | orderNos: inboundOrderNos, |
| | | inout:1 |
| | | }); |
| | | |
| | | const { status, message, data } = response; |
| | | if (status) { |
| | | console.log('åæ¹å
¥åºæåï¼å端è¿åï¼', data); |
| | | ElMessage.success(`åæ¹å
¥åºæåï¼å
±å¤ç${inboundOrderNos.length}æ¡åæ®`); |
| | | this.refresh(); // å
¥åºæååå·æ°å表ï¼å¤ç¨åæé»è¾ï¼ |
| | | } else { |
| | | console.log('åæ¹å
¥åºå¤±è´¥ï¼å端æç¤ºï¼', message); |
| | | ElMessage.error(message || data?.message || 'åæ¹å
¥åºå¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | console.error('åæ¹å
¥åºè¯·æ±å¼å¸¸ï¼', error); |
| | | ElMessage.error('ç½ç»å¼å¸¸ææ¥å£é误ï¼è¯·ç¨åéè¯'); |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | name: '空æçå
¥åº', |
| | | type: 'primary', |
| | | value: '空æçå
¥åº', |
| | | |
| | | onClick: function () { |
| | | const mountNode = document.createElement('div'); |
| | | document.body.appendChild(mountNode); |
| | | |
| | | // ååºå¼è¡¨åæ°æ®ï¼æç®±ç ï¼å¿
å¡«ï¼æ«ç æª/æå¨è¾å
¥ï¼ |
| | | const formData = reactive({ |
| | | boxCode: '', |
| | | warehouseCode:'' |
| | | }); |
| | | |
| | | const warehouses = ref([]); |
| | | const isLoadingWarehouses = ref(false); |
| | | |
| | | const getWarehouseList = async () => { |
| | | isLoadingWarehouses.value = true; |
| | | try { |
| | | const { data, status } = await http.post('/api/LocationInfo/GetLocationTypes'); |
| | | if (status && Array.isArray(data)) { |
| | | // æ ¼å¼åä»åºé项ï¼éé
ElSelectçlabel-valueæ ¼å¼ |
| | | warehouses.value = data.map(item => ({ |
| | | label: item.locationTypeDesc, |
| | | value: item.locationType |
| | | })); |
| | | } else { |
| | | ElMessage.error('è·ååºåå表失败'); |
| | | warehouses.value = []; |
| | | } |
| | | } catch (err) { |
| | | ElMessage.error('åºåæ°æ®è¯·æ±å¼å¸¸ï¼è¯·ç¨åéè¯'); |
| | | warehouses.value = []; |
| | | } finally { |
| | | isLoadingWarehouses.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨åçç»ä¸é»è¾ï¼ä¾å车触ååæé®ç¹å»å
±ç¨ï¼ |
| | | const submitForm = async () => { |
| | | const formRef = vnode.component.refs.batchInForm; |
| | | try { |
| | | // æ§è¡è¡¨åæ ¡éªï¼æç®±ç å¿
å¡«ï¼ |
| | | await formRef.validate(); |
| | | } catch (err) { |
| | | ElMessage.warning('请è¾å
¥ææçæç®±ç '); |
| | | return; |
| | | } |
| | | |
| | | |
| | | http.post('/api/InboundOrder/EmptyMaterielGroup', { |
| | | palletCode: formData.boxCode.trim(), |
| | | warehouseCode:formData.warehouseCode |
| | | }).then(({ data, status, message }) => { |
| | | if (status) { |
| | | ElMessage.success(`å
¥åºæåï¼æç®±ç ï¼${formData.boxCode.trim()}`); |
| | | this.refresh(); |
| | | formData.boxCode = ''; |
| | | |
| | | setTimeout(() => { |
| | | const inputRef = vnode.component.refs.boxCodeInput; |
| | | inputRef?.focus(); |
| | | }, 100); |
| | | } else { |
| | | ElMessage.error(message || data?.message || 'å
¥åºå¤±è´¥'); |
| | | selectBoxCodeInput(); |
| | | } |
| | | }).catch(() => { |
| | | ElMessage.error('请æ±å¤±è´¥ï¼è¯·ç¨åéè¯'); |
| | | selectBoxCodeInput(); |
| | | }); |
| | | }; |
| | | |
| | | const selectBoxCodeInput = () => { |
| | | setTimeout(() => { |
| | | const inputRef = vnode.component.refs.boxCodeInput; |
| | | if (inputRef) { |
| | | const targetInput = inputRef.$el?.querySelector('input') || inputRef; |
| | | targetInput?.focus(); |
| | | targetInput?.select(); |
| | | } |
| | | }, 100); |
| | | } |
| | | const vnode = createVNode(ElDialog, { |
| | | title: '空æçå
¥åº', |
| | | width: '400px', |
| | | modelValue: true, |
| | | appendToBody: true, |
| | | |
| | | onOpened: async () => { |
| | | await getWarehouseList(); |
| | | const inputRef = vnode.component.refs.boxCodeInput; |
| | | inputRef?.focus(); |
| | | }, |
| | | 'onUpdate:modelValue': (isVisible) => { |
| | | if (!isVisible) { |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | } |
| | | } |
| | | }, { |
| | | default: () => h(ElForm, { |
| | | model: formData, |
| | | rules: { |
| | | boxCode: [ |
| | | { required: true, message: '请è¾å
¥æç®±ç ', trigger: ['blur', 'enter'] } |
| | | ], |
| | | warehouseCode:[ |
| | | { required: true, message: 'è¯·éæ©åºå', trigger: ['change', 'blur'] } |
| | | ] |
| | | }, |
| | | ref: 'batchInForm' |
| | | }, [ |
| | | //ä»åºæ°æ® |
| | | h(ElFormItem, { label: 'åºå', prop: 'warehouseCode', required: true }, [ |
| | | h(ElSelect, { |
| | | modelValue: formData.warehouseCode, |
| | | 'onUpdate:modelValue': (val) => { |
| | | formData.warehouseCode = val; |
| | | }, |
| | | placeholder: 'è¯·éæ©å
¥åºåºå', |
| | | filterable: true, // æ¯ææç´¢ä»åº |
| | | loading: isLoadingWarehouses.value, // å è½½ç¶æ |
| | | style: { width: '100%' } |
| | | }, [ |
| | | // 渲æä»åºä¸æé项 |
| | | warehouses.value.map(item => h(ElOption, { |
| | | label: item.label, |
| | | value: item.value |
| | | })) |
| | | ]) |
| | | ]), |
| | | // æç®±ç è¾å
¥é¡¹ï¼æ¯æèç¦ãå车æäº¤ï¼ |
| | | h(ElFormItem, { label: 'æç®±ç ', prop: 'boxCode', required: true }, [ |
| | | h(ElInput, { |
| | | type: 'text', |
| | | modelValue: formData.boxCode, |
| | | 'onUpdate:modelValue': (val) => { |
| | | formData.boxCode = val; |
| | | }, |
| | | ref: 'boxCodeInput', |
| | | placeholder: 'æ«ç è¾å
¥ææå¨è¾å
¥æç®±ç ', |
| | | // çå¬å车äºä»¶ï¼æ«ç æªé»è®¤ä¼åéåè½¦ï¼ |
| | | onKeydown: (e) => { |
| | | if (e.key === 'Enter') { |
| | | e.preventDefault(); |
| | | submitForm(); |
| | | } |
| | | } |
| | | }) |
| | | ]), |
| | | // åºé¨æé®åº |
| | | h('div', { style: { textAlign: 'right', marginTop: '16px' } }, [ |
| | | h(ElButton, { |
| | | type: 'text', |
| | | onClick: () => { |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | ElMessage.info('åæ¶å
¥åºä»»å¡'); |
| | | } |
| | | }, 'åæ¶'), |
| | | h(ElButton, { |
| | | type: 'primary', |
| | | onClick: submitForm |
| | | }, 'ç¡®å®') |
| | | ]) |
| | | ]) |
| | | }); |
| | | |
| | | vnode.appContext = this.$.appContext; |
| | | render(vnode, mountNode); |
| | | } |
| | | } |
| | | ], box: [], detail: [] }, |
| | | methods: { |
| | | //ä¸é¢è¿äºæ¹æ³å¯ä»¥ä¿çä¹å¯ä»¥å é¤ |
| | | onInit() { |
| | | this.columns.push({ |
| | | field: 'æä½', |
| | | title: 'æä½', |
| | | width: 90, |
| | | fixed: 'right', |
| | | align: 'center', |
| | | formatter: (row) => { |
| | | return ( |
| | | '<i style="cursor: pointer;color: #2d8cf0;"class="el-icon-view">æ¥çæç»</i>' |
| | | ); |
| | | }, |
| | | click: (row) => { |
| | | this.$refs.gridBody.open(row); |
| | | } |
| | | }); |
| | | }, |
| | | onInited() { |
| | | |
| | | //æ¡æ¶åå§åé
ç½®å |
| | | //妿è¦é
ç½®æç»è¡¨,卿¤æ¹æ³æä½ |
| | | //this.detailOptions.columns.forEach(column=>{ }); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <vol-box |
| | | v-model="groupPalletVisible" |
| | | :title="'ç»çæä½ - åæ®å·ï¼' + currentDocNo" |
| | | :height="1000" |
| | | :width="1100" |
| | | :padding="20" |
| | | :modal="true" |
| | | |
| | | @open="handleDialogOpen" |
| | | @close="handleDialogClose" |
| | | > |
| | | <div class="barcode-scanner-container"> |
| | | |
| | | <!-- ä»åºéæ© - ç´§åå¸å± --> |
| | | <div class="location-section compact"> |
| | | <el-form :model="form" :rules="rules" ref="locationForm" class="compact-form"> |
| | | <el-form-item label="ä»åº" prop="warehouseType" class="location-select compact-item"> |
| | | <el-select |
| | | v-model="form.warehouseType" |
| | | placeholder="è¯·éæ©ä»åº" |
| | | clearable |
| | | filterable |
| | | @change="handleWarehouseChange" |
| | | style="width: 100%" |
| | | :loading="warehouseLoading" |
| | | size="medium" |
| | | > |
| | | <el-option |
| | | v-for="item in warehouseTypes" |
| | | :key="item.warehouseType" |
| | | :label="item.warehouseTypeDesc" |
| | | :value="item.warehouseType" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <!-- ä»åºåºåéæ© - ç´§åå¸å± --> |
| | | <div class="location-section compact"> |
| | | <el-form :model="form" :rules="rules" ref="locationForm" class="compact-form"> |
| | | <el-form-item label="ä»åºåºå" prop="locationType" class="location-select compact-item"> |
| | | <el-select |
| | | v-model="form.locationType" |
| | | placeholder="请å
éæ©ä»åº" |
| | | clearable |
| | | filterable |
| | | @change="handleLocationChange" |
| | | style="width: 100%" |
| | | :loading="locationLoading" |
| | | size="medium" |
| | | > |
| | | <el-option |
| | | v-for="item in locationTypes" |
| | | :key="item.locationType" |
| | | :label="item.locationTypeDesc" |
| | | :value="item.locationType" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <!-- æçä¿¡æ¯æ¾ç¤º - ç´§åå¸å± --> |
| | | <div class="tray-info compact" v-if="trayBarcode"> |
| | | <i class="el-icon-s-management"></i> å½åæç®±: {{ trayBarcode }} |
| | | <span class="location-info" v-if="form.warehouseType"> |
| | | | ä»åº: {{ currentWarehouseName }} |
| | | </span> |
| | | <span class="location-info" v-if="form.locationType"> |
| | | | ä»åºåºå: {{ currentLocationDesc }} |
| | | </span> |
| | | </div> |
| | | |
| | | <!-- æ«ç åºå - ç´§åå¸å± --> |
| | | <div class="input-section compact"> |
| | | <el-card shadow="hover" class="compact-card"> |
| | | <div slot="header" class="compact-header"> |
| | | <span><i class="el-icon-scanner"></i> æ«ç åºå</span> |
| | | <span class="scan-status"> |
| | | <span class="scan-indicator"></span> |
| | | {{ form.locationType && form.warehouseType ? 'æ«ç 就绪' : '请å
éæ©ä»åºåä»åºåºå' }} |
| | | </span> |
| | | </div> |
| | | |
| | | <!-- æçæ¡ç è¾å
¥ --> |
| | | <div class="input-wrapper custom-input-group compact-input"> |
| | | <div class="input-label">æç®±ç </div> |
| | | <el-input |
| | | ref="trayInput" |
| | | v-model="trayBarcode" |
| | | placeholder="è¯·æ«ææè¾å
¥æç®±ç åæå车é®" |
| | | clearable |
| | | :disabled="!form.locationType || !form.warehouseType" |
| | | @keyup.enter.native="handleTraySubmit" |
| | | @clear="handleTrayClear" |
| | | @input="handleTrayInput" |
| | | class="custom-input" |
| | | size="medium" |
| | | > |
| | | <template slot="append"> |
| | | <el-button |
| | | @click="handleTraySubmit" |
| | | type="primary" |
| | | icon="el-icon-position" |
| | | :disabled="!form.locationType || !trayBarcode || !form.warehouseType" |
| | | size="medium" |
| | | > |
| | | 确认 |
| | | </el-button> |
| | | </template> |
| | | </el-input> |
| | | </div> |
| | | |
| | | <!-- ç©ææ¡ç è¾å
¥ --> |
| | | <div class="input-wrapper custom-input-group compact-input"> |
| | | <div class="input-label">ç©ææ¡ç </div> |
| | | <el-input |
| | | ref="barcodeInput" |
| | | v-model="barcode" |
| | | placeholder="è¯·æ«ææè¾å
¥ç©ææ¡ç åæå车é®" |
| | | clearable |
| | | :disabled="!form.locationType || !trayBarcode || !form.warehouseType" |
| | | @keyup.enter.native="handleBarcodeSubmit" |
| | | @clear="handleClear" |
| | | @input="handleBarcodeInput" |
| | | class="custom-input" |
| | | size="medium" |
| | | > |
| | | <template slot="append"> |
| | | <el-button |
| | | :loading="loading" |
| | | @click="handleBarcodeSubmit" |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | :disabled="!form.locationType || !trayBarcode || !barcode || !from.warehouseType" |
| | | size="medium" |
| | | > |
| | | {{ loading ? 'æ¥è¯¢ä¸...' : 'æ¥è¯¢' }} |
| | | </el-button> |
| | | </template> |
| | | </el-input> |
| | | </div> |
| | | |
| | | <div class="input-tips compact-tips"> |
| | | <p>æç¤ºï¼è¯·å
éæ©ä»åº â éæ©ä»åºåºå â è¾å
¥æç®±ç â è¾å
¥ç©ææ¡ç </p> |
| | | <p v-if="!form.warehouseType" class="warning-text">â ï¸ è¯·å
éæ©ä»åº</p> |
| | | <p v-if="!form.locationType && !form.warehouseType" class="warning-text">â ï¸ è¯·å
éæ©ä»åºåºå</p> |
| | | <p v-if="form.warehouseType && form.locationType && !trayBarcode" class="warning-text">â ï¸ è¯·å
è¾å
¥æç®±ç </p> |
| | | </div> |
| | | |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- å è½½ç¶æ --> |
| | | <div v-if="loading" class="loading compact"> |
| | | <el-progress :percentage="100" status="success" :show-text="false" /> |
| | | <p>æ£å¨æ¥è¯¢ç©æä¿¡æ¯...</p> |
| | | </div> |
| | | |
| | | <!-- é误æç¤º --> |
| | | <div v-if="error" class="error-message compact"> |
| | | <el-alert |
| | | :title="error" |
| | | type="error" |
| | | show-icon |
| | | closable |
| | | @close="error = ''" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- ç©æå表 - åºå®é«åº¦å¸¦æ»å¨æ¡ --> |
| | | <div class="material-list compact"> |
| | | <el-card shadow="hover" class="compact-card"> |
| | | <div slot="header" class="compact-header"> |
| | | <span><i class="el-icon-tickets"></i> ç»çæ°æ®</span> |
| | | <span class="list-actions"> |
| | | <el-tag type="primary" size="small">å
± {{ materials.length }} æ¡</el-tag> |
| | | <el-tag type="primary" size="small">æªç»ç {{ totalStockCount }}</el-tag> |
| | | <el-tag type="primary" size="small">æªå
¥åºæ°é {{ totalStockSum }}{{ uniqueUnit }}</el-tag> |
| | | <el-tag v-if="trayBarcode" type="success" size="small">æç: {{ trayBarcode }}</el-tag> |
| | | <el-tag v-if="form.warehouseType" type="info" size="small">ä»åº: {{ currentWarehouseName }}</el-tag> |
| | | <el-tag v-if="form.locationType" type="info" size="small">åºå: {{ currentLocationDesc }}</el-tag> |
| | | </span> |
| | | </div> |
| | | |
| | | <div v-if="materials.length === 0" class="empty-state compact"> |
| | | <i class="el-icon-document"></i> |
| | | <p v-if="!form.warehouseType">请å
éæ©ä»åº</p> |
| | | <p v-if="!form.locationType">请å
éæ©ä»åºåºå</p> |
| | | <p v-else-if="!trayBarcode">请å
è¾å
¥æç®±æ¡ç </p> |
| | | <p v-else>ææ ç©ææ°æ®ï¼è¯·æ«ææè¾å
¥ç©ææ¡ç </p> |
| | | </div> |
| | | |
| | | <div class="table-container" v-else> |
| | | <el-table |
| | | :data="materials" |
| | | stripe |
| | | style="width: 100%" |
| | | height="100%" |
| | | size="small" |
| | | > |
| | | <el-table-column type="index" label="åºå·" width="60" align="center"></el-table-column> |
| | | <el-table-column prop="barcode" label="æ¡ç " min-width="140" show-overflow-tooltip></el-table-column> |
| | | <el-table-column prop="materielCode" label="ç©æç¼ç " min-width="150" show-overflow-tooltip></el-table-column> |
| | | <el-table-column prop="batchNo" label="æ¹æ¬¡" min-width="150" show-overflow-tooltip></el-table-column> |
| | | <el-table-column prop="stockQuantity" label="æ°é" min-width="130" align="right"></el-table-column> |
| | | <el-table-column prop="unit" label="åä½" width="80" align="center"></el-table-column> |
| | | <el-table-column prop="supplyCode" label="ä¾åºå" min-width="130" show-overflow-tooltip></el-table-column> |
| | | <el-table-column prop="warehouseType" label="ä»åº" min-width="120" show-overflow-tooltip></el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="handleCancel">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleConfirm">确认</el-button> |
| | | </div> --> |
| | | </vol-box> |
| | | </template> |
| | | <script> |
| | | import http from '@/api/http.js'; |
| | | import VolBox from '@/components/basic/VolBox.vue'; |
| | | import VolForm from '@/components/basic/VolForm.vue'; |
| | | import VolTable from '@/components/basic/VolTable.vue'; |
| | | import { ElLoading, ElMessage,ElMessageBox } from 'element-plus'; |
| | | import { ref, onMounted, onUnmounted } from 'vue' |
| | | import InboundOrder from '../../../views/inbound/inboundOrder.vue'; |
| | | import { th } from 'element-plus/es/locales.mjs'; |
| | | |
| | | export default { |
| | | name: 'BarcodeScanner', |
| | | components: { VolBox, VolForm, VolTable }, |
| | | props: { |
| | | docNo: { type: String, required: true, default: '' }, |
| | | visible: { type: Boolean, required: true, default: false } |
| | | }, |
| | | |
| | | data() { |
| | | return { |
| | | palletVisible: this.visible, |
| | | trayBarcode: '', |
| | | barcode: '', |
| | | materials: [], |
| | | loading: false, |
| | | error: '', |
| | | debugMode: false, |
| | | currentFocus: 'warehouse', |
| | | |
| | | // æ«ç æªç¸å
³åé |
| | | scanCode: '', |
| | | lastKeyTime: null, |
| | | isManualInput: false, |
| | | isScanning: false, |
| | | scanTimer: null, |
| | | manualInputTimer: null, |
| | | scanTarget: 'tray', // å½åæ«ç ç®æ : tray æ material |
| | | |
| | | // åºåç»è®¡ç¸å
³åé |
| | | totalStockSum: 0, |
| | | totalStockCount: 0, |
| | | uniqueUnit: '', |
| | | sumLoading: false, |
| | | sumError: '', |
| | | // ä»åºç¸å
³åé |
| | | warehouseTypes: [], |
| | | warehouseLoading: false, |
| | | // ä»åºåºåç¸å
³åé |
| | | locationTypes: [], |
| | | locationLoading: false, |
| | | form: { |
| | | warehouseType: null, |
| | | locationType: null |
| | | }, |
| | | rules: { |
| | | locationType: [ |
| | | { |
| | | validator: this.validateLocationType, |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | warehouseType: [ |
| | | { |
| | | massage:'è¯·éæ©ä»åº', |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | groupPalletVisible: { |
| | | get() { return this.visible; }, |
| | | set(newVal) { this.$emit('update:visible', newVal); } |
| | | }, |
| | | currentDocNo() { return this.docNo; }, |
| | | // å½åéæ©çä»åºåç§° |
| | | currentWarehouseName() { |
| | | const warehouse = this.warehouseTypes.find(item => item.warehouseType === this.form.warehouseType); |
| | | return warehouse ? warehouse.warehouseTypeDesc : ''; |
| | | }, |
| | | // å½åéæ©çä»åºåºåæè¿° |
| | | currentLocationDesc() { |
| | | const location = this.locationTypes.find(item => item.locationType === this.form.locationType) |
| | | return location ? location.locationTypeDesc : '' |
| | | } |
| | | }, |
| | | watch: { |
| | | visible(newVal, oldVal) { |
| | | this.palletVisible = newVal; |
| | | |
| | | // å½ä» false å为 true æ¶ï¼è¡¨ç¤ºå¼¹æ¡æå¼ |
| | | if (newVal === true && oldVal === false) { |
| | | console.log('å¼¹æ¡æå¼ï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | // this.focusTrayInput(); |
| | | this.initwarehouseTypes(); // åå§åä»åº |
| | | this.initLocationTypes(); // åå§åä»åºåºå |
| | | this.fetchStockStatistics(); // å è½½ç»è®¡æ°æ® |
| | | }, 300); |
| | | }); |
| | | } |
| | | |
| | | // å½ä» true å为 false æ¶ï¼è¡¨ç¤ºå¼¹æ¡å
³é |
| | | if (newVal === false && oldVal === true) { |
| | | console.log('å¼¹æ¡å
³éï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | } |
| | | }, |
| | | palletVisible(newVal) { |
| | | this.$emit('update:visible', newVal); |
| | | }, |
| | | docNo(newVal) { |
| | | if (newVal) { |
| | | this.palletForm = { palletCode: '', barcode: '' }; |
| | | this.backData = []; |
| | | this.$refs.palletForm?.reset(); |
| | | this.fetchStockStatistics(); // åæ®å·åäºï¼å·æ°ç»è®¡ |
| | | } |
| | | } |
| | | }, |
| | | 'form.warehouseType'(newVal) { |
| | | if (newVal) { |
| | | this.form.locationType = null; |
| | | } else { |
| | | this.locationTypes = []; |
| | | } |
| | | }, |
| | | |
| | | mounted() { |
| | | |
| | | // æ·»å å
¨å±é®ççå¬ |
| | | document.addEventListener('keypress', this.handleKeyPress); |
| | | |
| | | // 使ç¨setTimeoutç¡®ä¿DOMå®å
¨æ¸²æååèç¦ |
| | | setTimeout(() => { |
| | | // this.focusTrayInput(); |
| | | this.focusLocationSelect(); |
| | | }, 300); |
| | | }, |
| | | beforeDestroy() { |
| | | // æ¸
çäºä»¶çå¬ |
| | | document.removeEventListener('keypress', this.handleKeyPress); |
| | | this.clearAllTimers(); |
| | | }, |
| | | methods: { |
| | | /** |
| | | * èªå®ä¹ä»åºåºåéªè¯ |
| | | * å
许å¼ä¸º0ï¼å 为0æ¯åæ³çlocationType |
| | | */ |
| | | validateLocationType(rule, value, callback) { |
| | | // æ£æ¥å¼æ¯å¦ä¸ºnullãundefinedæç©ºå符串ï¼ä½å
许æ°å0 |
| | | if (!this.form.warehouseType) { |
| | | callback(new Error('请å
éæ©ä»åº')); |
| | | } else if (value === null || value === undefined || value === '') { |
| | | callback(new Error('è¯·éæ©ä»åºåºå')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | /** |
| | | * åå§åä»åºåºåæ°æ® |
| | | */ |
| | | async initLocationTypes() { |
| | | this.locationLoading = true; |
| | | this.error = ''; |
| | | |
| | | try { |
| | | const response = await http.post('/api/LocationInfo/GetLocationTypes'); |
| | | |
| | | if (response.status && Array.isArray(response.data)) { |
| | | this.locationTypes = response.data; |
| | | if (this.locationTypes.length === 0) { |
| | | this.error = 'æªè·åå°ä»åºåºåæ°æ®'; |
| | | } else { |
| | | // 妿æé»è®¤åºåï¼å¯ä»¥å¨è¿é设置 |
| | | // this.form.locationType = this.locationTypes[0].locationType; |
| | | } |
| | | } else { |
| | | this.error = 'è·åä»åºåºåæ°æ®å¤±è´¥'; |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åä»åºåºå失败:', error); |
| | | this.error = `è·åä»åºåºå失败: ${error.message || 'ç½ç»é误'}`; |
| | | } finally { |
| | | this.locationLoading = false; |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * åå§åä»åºæ°æ® |
| | | */ |
| | | async initwarehouseTypes() { |
| | | this.warehouseLoading = true; |
| | | this.error = ''; |
| | | |
| | | try { |
| | | const response = await http.post('/api/Warehouse/GetwarehouseTypes'); |
| | | |
| | | if (response.status && Array.isArray(response.data)) { |
| | | this.warehouseTypes = response.data; |
| | | if (this.warehouseTypes.length === 0) { |
| | | this.error = 'æªè·åå°ä»åºæ°æ®'; |
| | | } else { |
| | | // 妿æé»è®¤åºåï¼å¯ä»¥å¨è¿é设置 |
| | | // this.form.locationType = this.locationTypes[0].locationType; |
| | | } |
| | | } else { |
| | | this.error = 'è·åä»åºæ°æ®å¤±è´¥'; |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åä»åºå¤±è´¥:', error); |
| | | this.error = `è·åä»åºå¤±è´¥: ${error.message || 'ç½ç»é误'}`; |
| | | } finally { |
| | | this.warehouseLoading = false; |
| | | } |
| | | }, |
| | | |
| | | |
| | | /** |
| | | * ä»åºåºååæ´å¤ç |
| | | */ |
| | | handleLocationChange(value) { |
| | | console.log('éæ©ä»åºåºå:', value, 'ç±»å:', typeof value, this.currentLocationDesc); |
| | | |
| | | // ç«å³æ¸
é¤éè¯¯ä¿¡æ¯ |
| | | this.error = ''; |
| | | |
| | | // æå¨è§¦å表åéªè¯æ´æ° |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | // æ¸
é¤è¯¥å段çéªè¯ç¶æï¼ç¶åéæ°éªè¯ |
| | | this.$refs.locationForm.clearValidate('locationType'); |
| | | |
| | | // çæå»¶è¿åéæ°éªè¯ï¼ç¡®ä¿DOMå·²æ´æ° |
| | | setTimeout(() => { |
| | | this.$refs.locationForm.validateField('locationType', (errorMsg) => { |
| | | if (!errorMsg && (value === 0 || value)) { |
| | | console.log('ä»åºåºåéªè¯éè¿:', value); |
| | | // åºåéæ©åï¼èªå¨èç¦å°æçè¾å
¥æ¡ |
| | | this.focusLocationSelect(); |
| | | } |
| | | }); |
| | | }, 100); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * ä»åºåæ´å¤ç |
| | | */ |
| | | handleWarehouseChange(value) { |
| | | console.log('éæ©ä»åº:', value, 'ç±»å:', typeof value, this.currentWarehouseName); |
| | | |
| | | // ç«å³æ¸
é¤éè¯¯ä¿¡æ¯ |
| | | this.error = ''; |
| | | |
| | | // æå¨è§¦å表åéªè¯æ´æ° |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | // æ¸
é¤è¯¥å段çéªè¯ç¶æï¼ç¶åéæ°éªè¯ |
| | | this.$refs.locationForm.clearValidate('warehouseType'); |
| | | |
| | | // çæå»¶è¿åéæ°éªè¯ï¼ç¡®ä¿DOMå·²æ´æ° |
| | | setTimeout(() => { |
| | | this.$refs.locationForm.validateField('warehouseType', (errorMsg) => { |
| | | if (!errorMsg && (value === 0 || value)) { |
| | | console.log('ä»åºéªè¯éè¿:', value); |
| | | this.focusLocationSelect(); |
| | | } |
| | | }); |
| | | }, 100); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | async fetchStockStatistics() { |
| | | // åæ®å·ä¸ºç©ºæ¶ä¸æ¥è¯¢ |
| | | if (!this.docNo) { |
| | | this.sumError = 'åæ®å·ä¸ºç©ºï¼æ æ³ç»è®¡'; |
| | | return; |
| | | } |
| | | |
| | | this.sumLoading = true; |
| | | this.sumError = ''; |
| | | try { |
| | | // è°ç¨å端ç»è®¡æ¥å£ï¼æ¿æ¢ä¸ºä½ çå®é
æ¥å£è·¯å¾ï¼ |
| | | const response = await http.post('/api/InboundOrder/UnPalletQuantity?orderNo='+this.docNo, { |
| | | |
| | | }); |
| | | |
| | | // ç»å®æ°æ®ï¼å¹é
PalletSumQuantityDTO ç»æï¼ |
| | | if (response.data) { |
| | | this.totalStockSum = response.data.stockSumQuantity || 0; // æ»åºåæ°é |
| | | this.totalStockCount = response.data.stockCount || 0; // æ»åºåè®°å½æ° |
| | | this.uniqueUnit = response.data.uniqueUnit || ''; // 计éåä½ |
| | | } |
| | | } catch (err) { |
| | | this.sumError = 'ç»è®¡å 载失败'; |
| | | this.totalStockSum = 0; |
| | | this.totalStockCount = 0; |
| | | console.error('åºåç»è®¡æ¥è¯¢å¼å¸¸ï¼', err); |
| | | } finally { |
| | | this.sumLoading = false; |
| | | } |
| | | }, |
| | | /** |
| | | * 表åéªè¯ |
| | | */ |
| | | async validateForm() { |
| | | return new Promise((resolve) => { |
| | | if (!this.$refs.locationForm) { |
| | | this.error = 'è¡¨åæªåå§å'; |
| | | this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | resolve(false); |
| | | return; |
| | | } |
| | | |
| | | this.$refs.locationForm.validate((valid) => { |
| | | if (valid) { |
| | | this.error = ''; |
| | | resolve(true); |
| | | } else { |
| | | // æå¨æ£æ¥locationTypeï¼æ£ç¡®å¤çå¼ä¸º0çæ
åµ |
| | | if(!this.from.warehouseType){ |
| | | this.error='请å
éæ©ä»åº'; |
| | | } |
| | | else if(this.form.locationType === null || this.form.locationType === undefined || this.form.locationType === '') { |
| | | this.error = '请å
éæ©ä»åºåºå'; |
| | | //this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | } else { |
| | | // 妿å¼åå¨ï¼å
æ¬0ï¼ï¼ä½éªè¯ä¸éè¿ï¼å¯è½æ¯å
¶ä»éªè¯é误 |
| | | this.error = 'è¯·æ£æ¥è¡¨å填忝妿£ç¡®'; |
| | | } |
| | | resolve(false); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | focusWarehouseSelect() { |
| | | if (this.$refs.locationForm) { |
| | | const selectEl = this.$el.querySelector('.location-select:first-child .el-input__inner'); |
| | | if (selectEl) { |
| | | selectEl.focus(); |
| | | this.currentFocus = 'warehouse'; |
| | | } |
| | | } |
| | | }, |
| | | // èç¦å°ä»åºåºåéæ© |
| | | focusLocationSelect() { |
| | | if (this.$refs.locationForm) { |
| | | const selectEl = this.$el.querySelector('.location-select:nth-child(2) .el-input__inner'); |
| | | if (selectEl) { |
| | | selectEl.focus(); |
| | | this.currentFocus = 'location'; |
| | | } |
| | | } |
| | | }, |
| | | // èç¦å°æçè¾å
¥æ¡ |
| | | focusTrayInput() { |
| | | if (this.$refs.trayInput && this.$refs.trayInput.$el) { |
| | | const inputEl = this.$refs.trayInput.$el.querySelector('input'); |
| | | if (inputEl) { |
| | | inputEl.focus(); |
| | | this.currentFocus = 'tray'; |
| | | this.scanTarget = 'tray'; |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // èç¦å°ç©æè¾å
¥æ¡ |
| | | focusBarcodeInput() { |
| | | if (this.$refs.barcodeInput && this.$refs.barcodeInput.$el) { |
| | | const inputEl = this.$refs.barcodeInput.$el.querySelector('input'); |
| | | if (inputEl) { |
| | | inputEl.focus(); |
| | | this.currentFocus = 'material'; |
| | | this.scanTarget = 'material'; |
| | | } |
| | | } |
| | | }, |
| | | // éç½®æææ°æ® |
| | | resetData() { |
| | | console.log('éç½®å¼¹æ¡æ°æ®'); |
| | | this.trayBarcode = ''; |
| | | this.barcode = ''; |
| | | this.materials = []; |
| | | this.loading = false; |
| | | this.error = ''; |
| | | this.scanCode = ''; |
| | | this.lastKeyTime = null; |
| | | this.isManualInput = false; |
| | | this.isScanning = false; |
| | | this.currentFocus = 'warehouse'; |
| | | this.scanTarget = 'tray'; |
| | | this.clearAllTimers(); |
| | | this.totalStockSum = 0; |
| | | this.totalStockCount = 0; |
| | | this.sumLoading = false; |
| | | this.sumError = ''; |
| | | this.form={ |
| | | warehouseType:null, |
| | | locationType:null |
| | | } |
| | | this.warehouseTypes=[]; |
| | | this.locationTypes=[]; |
| | | // æ¸
é¤è¡¨åéªè¯ç¶æ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.locationForm) { |
| | | this.$refs.locationForm.clearValidate(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
餿æè®¡æ¶å¨ |
| | | clearAllTimers() { |
| | | if (this.manualInputTimer) { |
| | | clearTimeout(this.manualInputTimer); |
| | | this.manualInputTimer = null; |
| | | } |
| | | if (this.scanTimer) { |
| | | clearTimeout(this.scanTimer); |
| | | this.scanTimer = null; |
| | | } |
| | | }, |
| | | |
| | | // å¼¹æ¡æå¼æ¶éç½®æ°æ® |
| | | handleDialogOpen() { |
| | | console.log('å¼¹æ¡æå¼ï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | // 使ç¨setTimeoutç¡®ä¿DOMå®å
¨æ¸²æååèç¦ |
| | | this.$nextTick(() => { |
| | | setTimeout(() => { |
| | | this.initwarehouseTypes(); |
| | | this.initLocationTypes(); // åå§åä»åºåºå |
| | | // ç¡®ä¿è¡¨åå¼ç¨åå¨ååèç¦ |
| | | if (this.$refs.locationForm) { |
| | | this.focusWarehouseSelect(); |
| | | } else { |
| | | // å¦æè¡¨åå¼ç¨è¿ä¸åå¨ï¼ç¨åéè¯ |
| | | setTimeout(() => { |
| | | this.focusWarehouseSelect(); |
| | | }, 500); |
| | | } |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | // å¼¹æ¡å
³éæ¶éç½®æ°æ® |
| | | handleDialogClose() { |
| | | console.log('å¼¹æ¡å
³éï¼éç½®æ°æ®'); |
| | | this.resetData(); |
| | | }, |
| | | |
| | | // åæ¶æé® |
| | | handleCancel() { |
| | | this.palletVisible = false; |
| | | }, |
| | | |
| | | // 确认æé® |
| | | async handleConfirm() { |
| | | if (!await this.validateForm()) return; |
| | | |
| | | if (this.materials.length === 0) { |
| | | this.$message.warning('请è³å°æ·»å ä¸ä¸ªç©æ'); |
| | | return; |
| | | } |
| | | |
| | | if (!this.trayBarcode) { |
| | | this.$message.warning('请è¾å
¥æçæ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | const result = { |
| | | warehouseType:this.form.warehouseType, |
| | | warehouseName:this.currentWarehouseName, |
| | | locationType: this.form.locationType, |
| | | locationDesc: this.currentLocationDesc, |
| | | trayBarcode: this.trayBarcode, |
| | | materials: this.materials, |
| | | docNo: this.docNo |
| | | }; |
| | | |
| | | // 触åç¶ç»ä»¶ç back-success äºä»¶ |
| | | this.$emit('back-success', result); |
| | | this.palletVisible = false; |
| | | }, |
| | | // å¤çæçè¾å
¥ |
| | | handleTrayInput() { |
| | | // æ 记为æå¨è¾å
¥æ¨¡å¼ |
| | | this.isManualInput = true; |
| | | this.isScanning = false; |
| | | |
| | | // æ¸
é¤ä¹åç计æ¶å¨ |
| | | if (this.manualInputTimer) { |
| | | clearTimeout(this.manualInputTimer); |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åé置为æ«ç æ¨¡å¼ |
| | | this.manualInputTimer = setTimeout(() => { |
| | | this.isManualInput = false; |
| | | }, 1000); |
| | | }, |
| | | |
| | | // å¤çç©æè¾å
¥ |
| | | handleBarcodeInput() { |
| | | // æ 记为æå¨è¾å
¥æ¨¡å¼ |
| | | this.isManualInput = true; |
| | | this.isScanning = false; |
| | | |
| | | // æ¸
é¤ä¹åç计æ¶å¨ |
| | | if (this.manualInputTimer) { |
| | | clearTimeout(this.manualInputTimer); |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åé置为æ«ç æ¨¡å¼ |
| | | this.manualInputTimer = setTimeout(() => { |
| | | this.isManualInput = false; |
| | | }, 1000); |
| | | }, |
| | | |
| | | // å¤çæçæ¡ç æäº¤ |
| | | async handleTraySubmit() { |
| | | // å
ç´æ¥æ£æ¥locationTypeï¼é¿å
表åéªè¯ç弿¥é®é¢ |
| | | if (!this.form.warehouseType) { |
| | | this.error = '请å
éæ©ä»åº'; |
| | | return; |
| | | } |
| | | if (!this.form.locationType) { |
| | | this.error = '请å
éæ©ä»åºåºå'; |
| | | //this.$message.warning('请å
éæ©ä»åºåºå'); |
| | | return; |
| | | } |
| | | |
| | | // ç¶ååè¿è¡å®æ´ç表åéªè¯ |
| | | if (!await this.validateForm()) return; |
| | | |
| | | const currentTrayBarcode = this.trayBarcode.trim(); |
| | | |
| | | if (!currentTrayBarcode) { |
| | | this.error = '请è¾å
¥ææ«ææçæ¡ç '; |
| | | return; |
| | | } |
| | | |
| | | this.error = ''; |
| | | |
| | | // 设置æçæ¡ç åï¼èªå¨èç¦å°ç©æè¾å
¥æ¡ |
| | | this.focusBarcodeInput(); |
| | | |
| | | this.$message({ |
| | | message: `æçæ¡ç 已设置: ${currentTrayBarcode}`, |
| | | type: 'success', |
| | | duration: 2000 |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
餿ç |
| | | clearTray() { |
| | | this.trayBarcode = ''; |
| | | this.materials = []; |
| | | this.focusTrayInput(); |
| | | this.$message({ |
| | | message: 'æçæ¡ç å·²æ¸
é¤', |
| | | type: 'info', |
| | | duration: 2000 |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
空æçè¾å
¥ |
| | | handleTrayClear() { |
| | | this.error = ''; |
| | | }, |
| | | |
| | | // æ¸
空è¾å
¥ |
| | | handleClear() { |
| | | this.error = ''; |
| | | this.scanCode = ''; |
| | | this.isManualInput = false; |
| | | this.isScanning = false; |
| | | }, |
| | | |
| | | // å¤çç©ææ¡ç æäº¤ |
| | | async handleBarcodeSubmit() { |
| | | if (!await this.validateForm()) return; |
| | | const currentBarcode = this.barcode.trim(); |
| | | |
| | | if (!this.trayBarcode) { |
| | | this.error = '请å
è¾å
¥æçæ¡ç '; |
| | | this.focusTrayInput(); |
| | | return; |
| | | } |
| | | |
| | | if (!currentBarcode) { |
| | | this.error = '请è¾å
¥ææ«æç©ææ¡ç '; |
| | | return; |
| | | } |
| | | |
| | | this.error = ''; |
| | | this.loading = true; |
| | | |
| | | try { |
| | | // è°ç¨APIæ¥è¯¢ç©æä¿¡æ¯ |
| | | const materialData = await this.fetchMaterialData(currentBarcode); |
| | | if (!materialData || materialData.length === 0) { |
| | | |
| | | |
| | | return; |
| | | } |
| | | // æ£æ¥æ¯å¦å·²åå¨ç¸åç©æç¼ç çè®°å½ |
| | | const exists = this.materials.some(item => |
| | | item.barcode === this.trayBarcode |
| | | ); |
| | | console.log('API:',materialData) |
| | | if (exists) { |
| | | this.$message({ |
| | | message: '该æ¡ç å·²åå¨å½åæççå表ä¸', |
| | | type: 'warning', |
| | | duration: 2000 |
| | | }); |
| | | } else { |
| | | |
| | | materialData.forEach(item => { |
| | | |
| | | // 妿ä¸åå¨ï¼æ·»å æ°ç©æ |
| | | this.materials.push({ |
| | | ...item, |
| | | trayCode: this.trayBarcode, |
| | | locationType: this.form.locationType, |
| | | locationDesc: this.currentLocationDesc, |
| | | scanTime: this.formatTime(new Date()) |
| | | }); |
| | | }); |
| | | |
| | | |
| | | |
| | | |
| | | this.$message({ |
| | | message: `æåæ·»å æ¡ç : ${currentBarcode}`, |
| | | type: 'success', |
| | | duration: 2000 |
| | | }); |
| | | |
| | | this.fetchStockStatistics(); |
| | | // æ¸
ç©ºç©æè¾å
¥æ¡å¹¶ä¿æèç¦ |
| | | this.barcode = ''; |
| | | this.scanCode = ''; // æ¸
空æ«ç ç¼å |
| | | this.isScanning = false; |
| | | |
| | | setTimeout(() => { |
| | | this.focusBarcodeInput(); |
| | | }, 100); |
| | | } |
| | | } catch (err) { |
| | | this.error = err.message || 'æ¥è¯¢æ¡ç ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯'; |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // APIè¯·æ± - æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | async fetchMaterialData(barcode) { |
| | | try { |
| | | const response = await http.post('/api/InboundOrder/BarcodeMaterielGroup', |
| | | { |
| | | palletCode: this.trayBarcode, |
| | | orderNo: this.docNo, |
| | | barcodes: barcode, |
| | | locationTypeDesc: this.currentLocationDesc, |
| | | locationType: this.form.locationType, // æ·»å ä»åºåºåä¿¡æ¯ |
| | | warehouseType:this.form.warehouseType |
| | | } |
| | | ); |
| | | |
| | | |
| | | let materialData; |
| | | |
| | | if (typeof response.data === 'string') { |
| | | |
| | | try { |
| | | materialData = JSON.parse(response.data); |
| | | } catch (e) { |
| | | |
| | | } |
| | | } else { |
| | | // 妿è¿åçæ¯JSON对象ï¼ç´æ¥ä½¿ç¨ |
| | | materialData = response.data; |
| | | } |
| | | if(!response.status){ |
| | | this.error = response.message || 'æ¥è¯¢æ¡ç ä¿¡æ¯å¤±è´¥ï¼è¯·éè¯'; |
| | | } |
| | | |
| | | return materialData; |
| | | |
| | | } catch (error) { |
| | | console.error('APIè°ç¨å¤±è´¥:', error); |
| | | |
| | | |
| | | } |
| | | }, |
| | | |
| | | // å¤çæ«ç æªè¾å
¥ |
| | | handleKeyPress(event) { |
| | | // å¦ææ¯æå¨è¾å
¥æ¨¡å¼ï¼ä¸å¤çæ«ç æªé»è¾ |
| | | if (this.isManualInput) { |
| | | return; |
| | | } |
| | | |
| | | const key = event.key; |
| | | const currentTime = new Date().getTime(); |
| | | |
| | | // 忽ç¥ç´æ¥æä¸çå车é®ï¼ç±handleBarcodeSubmitå¤çï¼ |
| | | if (key === 'Enter') { |
| | | if (this.scanCode.length > 0) { |
| | | // 黿¢é»è®¤å车è¡ä¸ºï¼é¿å
表åæäº¤ |
| | | event.preventDefault(); |
| | | |
| | | // æ«ç 宿ï¼èªå¨è§¦åæ¥è¯¢ |
| | | this.isScanning = false; |
| | | |
| | | // æ ¹æ®å½åæ«ç ç®æ 设置ç¸åºçè¾å
¥æ¡å¼ |
| | | if (this.scanTarget === 'tray') { |
| | | this.trayBarcode = this.scanCode; |
| | | this.handleTraySubmit(); |
| | | } else if (this.scanTarget === 'material') { |
| | | this.barcode = this.scanCode; |
| | | this.handleBarcodeSubmit(); |
| | | } |
| | | } |
| | | this.scanCode = ''; |
| | | this.lastKeyTime = null; |
| | | return; |
| | | } |
| | | |
| | | // æå»ºæ«ç å
容ï¼å¿«éè¿ç»è¾å
¥è§ä¸ºæ«ç ï¼ |
| | | if (this.lastKeyTime && currentTime - this.lastKeyTime < 50) { |
| | | this.scanCode += key; |
| | | this.isScanning = true; |
| | | } else { |
| | | this.scanCode = key; |
| | | this.isScanning = true; |
| | | } |
| | | |
| | | // 设置计æ¶å¨ï¼å¦æä¸æ®µæ¶é´å
没æè¾å
¥ï¼åéç½®æ«æç¶æ |
| | | if (this.scanTimer) { |
| | | clearTimeout(this.scanTimer); |
| | | } |
| | | this.scanTimer = setTimeout(() => { |
| | | this.isScanning = false; |
| | | }, 100); |
| | | |
| | | this.lastKeyTime = currentTime; |
| | | }, |
| | | |
| | | // å é¤ç©æ |
| | | removeMaterial(index) { |
| | | this.$confirm('ç¡®å®è¦å é¤è¿æ¡ç©æè®°å½å?', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.materials.splice(index, 1); |
| | | this.$message({ |
| | | type: 'success', |
| | | message: 'å 餿å!' |
| | | }); |
| | | this.fetchStockStatistics(); |
| | | |
| | | }).catch(() => { |
| | | // åæ¶å é¤ |
| | | }); |
| | | }, |
| | | |
| | | // æ¸
空ææç©æ |
| | | clearAllMaterials() { |
| | | if (this.materials.length === 0) return; |
| | | |
| | | this.$confirm('ç¡®å®è¦æ¸
空ææç©æè®°å½å?', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.materials = []; |
| | | this.$message({ |
| | | type: 'success', |
| | | message: 'å·²æ¸
空ææè®°å½!' |
| | | }); |
| | | }).catch(() => { |
| | | // åæ¶æ¸
空 |
| | | }); |
| | | }, |
| | | |
| | | // æ ¼å¼åæ¶é´ |
| | | formatTime(date) { |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(date.getDate()).padStart(2, '0'); |
| | | const hours = String(date.getHours()).padStart(2, '0'); |
| | | const minutes = String(date.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(date.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .barcode-scanner-container { |
| | | max-width: 1200px; |
| | | margin: 0 auto; |
| | | padding: 10px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | gap: 8px; |
| | | } |
| | | |
| | | /* ç´§åå¸å±æ ·å¼ */ |
| | | .compact { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .compact-form { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .compact-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .compact-card { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .compact-card >>> .el-card__body { |
| | | padding: 12px; |
| | | } |
| | | |
| | | .compact-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | .compact-header >>> .el-card__header { |
| | | padding: 8px 12px; |
| | | } |
| | | |
| | | .compact-input { |
| | | margin: 8px 0; |
| | | } |
| | | |
| | | .compact-tips { |
| | | margin-top: 8px; |
| | | font-size: 11px; |
| | | } |
| | | |
| | | /* ä»åºåºåéæ© - ç´§å */ |
| | | .location-section.compact { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .location-section.compact >>> .el-form-item { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | /* æçä¿¡æ¯ - ç´§å */ |
| | | .tray-info.compact { |
| | | padding: 6px 10px; |
| | | margin-bottom: 8px; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* æ«ç åºå - ç´§å */ |
| | | .input-section.compact { |
| | | margin-bottom: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | /* ç©æå表 - åºå®é«åº¦å¸¦æ»å¨ */ |
| | | .material-list.compact { |
| | | flex: 1; |
| | | min-height: 0; /* éè¦ï¼å
许flexå项æ¶ç¼© */ |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .material-list.compact >>> .el-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | } |
| | | |
| | | .material-list.compact >>> .el-card__body { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 0; |
| | | min-height: 0; |
| | | } |
| | | |
| | | .table-container { |
| | | flex: 1; |
| | | min-height: 0; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .material-list.compact >>> .el-table { |
| | | flex: 1; |
| | | } |
| | | |
| | | .material-list.compact >>> .el-table__body-wrapper { |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | /* ç´§åçç©ºç¶æ */ |
| | | .empty-state.compact { |
| | | padding: 20px 0; |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .empty-state.compact i { |
| | | font-size: 36px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .empty-state.compact p { |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* å
¶ä»åææ ·å¼è°æ´ */ |
| | | .page-title { |
| | | text-align: center; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .scan-status { |
| | | font-size: 12px; |
| | | color: #67C23A; |
| | | } |
| | | |
| | | .scan-indicator { |
| | | display: inline-block; |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 50%; |
| | | background-color: #67C23A; |
| | | margin-right: 5px; |
| | | animation: pulse 1.5s infinite; |
| | | } |
| | | |
| | | @keyframes pulse { |
| | | 0% { opacity: 1; } |
| | | 50% { opacity: 0.4; } |
| | | 100% { opacity: 1; } |
| | | } |
| | | |
| | | .input-wrapper { |
| | | position: relative; |
| | | } |
| | | |
| | | .input-tips { |
| | | margin-top: 6px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .warning-text { |
| | | color: #E6A23C; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .loading.compact { |
| | | text-align: center; |
| | | margin: 10px 0; |
| | | padding: 5px; |
| | | } |
| | | |
| | | .loading.compact p { |
| | | margin-top: 5px; |
| | | color: #409EFF; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .error-message.compact { |
| | | margin: 5px 0; |
| | | } |
| | | |
| | | .error-message.compact >>> .el-alert { |
| | | padding: 6px 12px; |
| | | } |
| | | |
| | | .list-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | } |
| | | |
| | | .list-actions >>> .el-tag { |
| | | height: 24px; |
| | | line-height: 22px; |
| | | padding: 0 6px; |
| | | } |
| | | |
| | | .clear-all-btn { |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .material-code { |
| | | font-family: 'Courier New', monospace; |
| | | font-weight: bold; |
| | | color: #409EFF; |
| | | } |
| | | |
| | | .location-info { |
| | | color: #606266; |
| | | font-weight: normal; |
| | | } |
| | | |
| | | .debug-info { |
| | | background: #f5f7fa; |
| | | padding: 8px; |
| | | border-radius: 4px; |
| | | margin-top: 8px; |
| | | font-size: 11px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .small-button { |
| | | padding: 6px 8px; |
| | | font-size: 11px; |
| | | } |
| | | |
| | | /* è¾å
¥æ¡ç»æ ·å¼è°æ´ */ |
| | | .custom-input-group { |
| | | display: flex; |
| | | align-items: center; |
| | | width: 100%; |
| | | margin: 8px 0; |
| | | border: 1px solid #DCDFE6; |
| | | border-radius: 4px; |
| | | overflow: hidden; |
| | | background: #fff; |
| | | } |
| | | |
| | | .input-label { |
| | | padding: 0 12px; |
| | | background: #F5F7FA; |
| | | border-right: 1px solid #DCDFE6; |
| | | color: #606266; |
| | | font-size: 13px; |
| | | white-space: nowrap; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | flex-shrink: 0; |
| | | min-width: 70px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .input-container { |
| | | display: flex; |
| | | flex: 1; |
| | | align-items: center; |
| | | } |
| | | |
| | | .custom-input { |
| | | flex: 1; |
| | | } |
| | | |
| | | .custom-input >>> .el-input__inner { |
| | | border: none; |
| | | border-radius: 0; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | /* ååºå¼è°æ´ */ |
| | | @media (max-width: 768px) { |
| | | .barcode-scanner-container { |
| | | padding: 5px; |
| | | } |
| | | |
| | | .custom-input-group { |
| | | flex-direction: column; |
| | | border: none; |
| | | } |
| | | |
| | | .input-label { |
| | | width: 100%; |
| | | border-right: none; |
| | | border-bottom: 1px solid #DCDFE6; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .input-container { |
| | | width: 100%; |
| | | border: 1px solid #DCDFE6; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <vol-box |
| | | v-model="showDetialBox" |
| | | :lazy="true" |
| | | width="75%" |
| | | :padding="15" |
| | | title="åºåºè¯¦æ
" |
| | | > |
| | | <div class="box-head"> |
| | | <el-alert :closable="false" style="width: 100%"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <span class="less-style">ç©æåç§°ï¼ {{ row.materielName }} </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span class="less-style">ç©æç¼å·ï¼ {{ row.materielCode }} </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span class="less-style" |
| | | >éæ±æ°éï¼ {{ row.orderQuantity }} |
| | | </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span class="less-style" |
| | | >å·²åé
æ°éï¼ {{ row.lockQuantity }} |
| | | </span> |
| | | </el-col> |
| | | </el-row> |
| | | </el-alert> |
| | | </div> |
| | | <div class="box-table" style="margin-top: 1%"> |
| | | <el-table |
| | | ref="singleTable" |
| | | :data="tableData" |
| | | style="width: 100%; height: 100%" |
| | | highlight-current-row |
| | | height="500px" |
| | | > |
| | | > |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | fixed="left" |
| | | width="55" |
| | | align="center" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | v-for="(item, index) in tableColumns.filter((x) => !x.hidden)" |
| | | :key="index" |
| | | :prop="item.prop" |
| | | :label="item.title" |
| | | :width="item.width" |
| | | align="center" |
| | | > |
| | | <template #default="scoped" v-if="item.type == 'icon'"> |
| | | <el-tooltip |
| | | class="item" |
| | | effect="dark" |
| | | :content="item.title" |
| | | placement="bottom" |
| | | ><el-button |
| | | type="text" |
| | | @click="tableButtonClick(scoped.row, item)" |
| | | ><i :class="item.icon" style="font-size: 22px"></i></el-button |
| | | ></el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <template #footer> |
| | | <!-- <el-button type="primary" size="small" @click="submit">确认</el-button> --> |
| | | <el-button type="danger" size="small" @click="showDetialBox = false" |
| | | >å
³é</el-button |
| | | > |
| | | </template> |
| | | </vol-box> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import VolBox from "@/components/basic/VolBox.vue"; |
| | | export default { |
| | | components: { VolBox }, |
| | | data() { |
| | | return { |
| | | row: null, |
| | | showDetialBox: false, |
| | | tableData: [], |
| | | tableColumns: [ |
| | | { |
| | | prop: "id", |
| | | title: "主é®", |
| | | type: "string", |
| | | width: 150, |
| | | hidden: true, |
| | | }, |
| | | { |
| | | prop: "orderNo", |
| | | title: "åæ®ç¼å·", |
| | | type: "string", |
| | | width: 150, |
| | | }, |
| | | { |
| | | prop: "orderDetailId", |
| | | title: "åæ®æç»ä¸»é®", |
| | | type: "string", |
| | | width: 150, |
| | | hidden: true, |
| | | }, |
| | | { |
| | | prop: "orderType", |
| | | title: "åæ®ç±»å", |
| | | type: "string", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "batchNo", |
| | | title: "æ¹æ¬¡å·", |
| | | type: "string", |
| | | width: 120, |
| | | }, |
| | | { |
| | | prop: "materielCode", |
| | | title: "ç©æç¼å·", |
| | | type: "string", |
| | | width: 150, |
| | | }, |
| | | { |
| | | prop: "materielName", |
| | | title: "ç©æåç§°", |
| | | type: "string", |
| | | width: 150, |
| | | }, |
| | | { |
| | | prop: "stockId", |
| | | title: "åºå主é®", |
| | | type: "string", |
| | | width: 150, |
| | | hidden: true, |
| | | }, |
| | | { |
| | | prop: "originalQuantity", |
| | | title: "åå§åºåé", |
| | | type: "string", |
| | | width: 100, |
| | | }, |
| | | { |
| | | prop: "assignQuantity", |
| | | title: "åé
åºåºé", |
| | | type: "string", |
| | | width: 100, |
| | | }, |
| | | { |
| | | prop: "palletCode", |
| | | title: "æçç¼å·", |
| | | type: "string", |
| | | width: 150, |
| | | }, |
| | | { |
| | | prop: "locationCode", |
| | | title: "è´§ä½ç¼å·", |
| | | type: "string", |
| | | width: 180, |
| | | }, |
| | | { |
| | | prop: "status", |
| | | title: "ç¶æ", |
| | | type: "string", |
| | | }, |
| | | ], |
| | | }; |
| | | }, |
| | | methods: { |
| | | open(row) { |
| | | this.row = row; |
| | | this.showDetialBox = true; |
| | | this.getData(); |
| | | }, |
| | | getData() { |
| | | this.http |
| | | .post( |
| | | "api/OutStockLockInfo/GetByOrderDetailId?orderDetailId=" + |
| | | this.row.id, |
| | | null, |
| | | "æ¥è¯¢ä¸" |
| | | ) |
| | | .then((x) => { |
| | | |
| | | var label=[ |
| | | { label: 'å·²åé
', value: 0 }, |
| | | { label: 'åºåºä¸', value: 1 }, |
| | | { label: 'åºåºå®æ', value: 2 }, |
| | | { label: 'æ£é宿', value: 3 }, |
| | | { label: 'æ¤é', value: 99 } |
| | | ] |
| | | this.tableData=x.map((i) => ({ |
| | | ...i, |
| | | status:label.find((j) => j.value === i.status).label |
| | | })) |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | <style scoped> |
| | | .less-style { |
| | | color: black; |
| | | } |
| | | .equle-style { |
| | | color: green; |
| | | } |
| | | .more-style { |
| | | color: red; |
| | | } |
| | | </style> |
| | | |
| | | <style> |
| | | .text-button:hover { |
| | | background-color: #f0f9eb !important; |
| | | } |
| | | .el-table .warning-row { |
| | | background: oldlace; |
| | | } |
| | | .box-table .el-table tbody tr:hover > td { |
| | | background-color: #d8e0d4 !important; |
| | | /* color: #ffffff; */ |
| | | } |
| | | |
| | | .box-table .el-table tbody tr.current-row > td { |
| | | background-color: #f0f9eb !important; |
| | | /* color: #ffffff; */ |
| | | } |
| | | |
| | | .el-table .success-row { |
| | | background: #f0f9eb; |
| | | } |
| | | |
| | | .box-table .el-table { |
| | | border: 1px solid #ebeef5; |
| | | } |
| | | .box-head .el-alert__content { |
| | | width: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <vol-box |
| | | v-model="showDetialBox" |
| | | :lazy="true" |
| | | width="60%" |
| | | :padding="15" |
| | | title="æå®åºå" |
| | | > |
| | | <div class="box-head"> |
| | | <el-alert :closable="false" style="width: 100%"> |
| | | <el-row> |
| | | <el-col :span="16"> |
| | | <span class="less-style">ç©æåç§°ï¼ {{ row.materielName }} </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span class="less-style">ç©æç¼å·ï¼ {{ row.materielCode }} </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span class="less-style">éæ±æ°éï¼ {{ row.orderQuantity }} </span> |
| | | <el-divider direction="vertical"></el-divider> |
| | | <span :class="selectionClass">已鿰éï¼ {{ selectionSum }} </span> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="getData" |
| | | >å·æ°</el-link |
| | | > |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="openOutboundDialog" |
| | | >ç´æ¥åºåº</el-link |
| | | > |
| | | </el-col> |
| | | </el-row> |
| | | </el-alert> |
| | | </div> |
| | | <div class="box-table" style="margin-top: 1%"> |
| | | <el-table |
| | | ref="singleTable" |
| | | :data="tableData" |
| | | style="width: 100%; height: 100%" |
| | | highlight-current-row |
| | | @row-click="handleRowClick" |
| | | height="500px" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55"> </el-table-column> |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | fixed="left" |
| | | width="55" |
| | | align="center" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | v-for="(item, index) in tableColumns.filter((x) => !x.hidden)" |
| | | :key="index" |
| | | :prop="item.prop" |
| | | :label="item.title" |
| | | :width="item.width" |
| | | align="center" |
| | | > |
| | | <template #default="scoped" v-if="item.type == 'icon'"> |
| | | <el-tooltip |
| | | class="item" |
| | | effect="dark" |
| | | :content="item.title" |
| | | placement="bottom" |
| | | ><el-button |
| | | type="text" |
| | | @click="tableButtonClick(scoped.row, item)" |
| | | ><i :class="item.icon" style="font-size: 22px"></i></el-button |
| | | ></el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <template #footer> |
| | | <el-button type="danger" size="small" @click="showDetialBox = false" |
| | | >å
³é</el-button |
| | | > |
| | | </template> |
| | | </vol-box> |
| | | |
| | | <!-- åºåºç«å°éæ©å¼¹çªï¼éææ¨¡æ¿å®ç°ï¼ --> |
| | | <el-dialog |
| | | v-model="showOutboundDialog" |
| | | title="åºåºæä½ - éæ©åºåºç«å°" |
| | | width="500px" |
| | | :append-to-body="true" |
| | | > |
| | | <el-form |
| | | :model="outboundForm" |
| | | :rules="outboundRules" |
| | | ref="outboundFormRef" |
| | | label-width="100px" |
| | | style="padding: 0 20px" |
| | | > |
| | | <el-form-item label="åºåºç«å°" prop="selectedPlatform" style="margin-bottom: 24px"> |
| | | <el-select |
| | | v-model="outboundForm.selectedPlatform" |
| | | placeholder="è¯·éæ©åºåºç«å°ï¼3-12ï¼" |
| | | style="width: 100%; height: 40px" |
| | | > |
| | | <el-option |
| | | v-for="platform in platformOptions" |
| | | :key="platform.value" |
| | | :label="platform.label" |
| | | :value="platform.value" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="showOutboundDialog = false" style="margin-right: 8px">åæ¶</el-button> |
| | | <el-button type="primary" @click="confirmOutbound">ç¡®å®åºåº</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import VolBox from "@/components/basic/VolBox.vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | | export default { |
| | | components: { VolBox }, |
| | | data() { |
| | | return { |
| | | row: null, |
| | | showDetialBox: false, |
| | | tableData: [], |
| | | tableColumns: [ |
| | | { prop: "materielCode", title: "ç©æç¼å·", type: "string", width: 150 }, |
| | | { prop: "materielName", title: "ç©æåç§°", type: "string", width: 150 }, |
| | | { prop: "palletCode", title: "æçç¼å·", type: "string", width: 150 }, |
| | | { prop: "locationCode", title: "è´§ä½ç¼å·", type: "string", width: 180 }, |
| | | { prop: "useableQuantity", title: "å¯ç¨æ°é", type: "string" }, |
| | | ], |
| | | selection: [], |
| | | selectionSum: 0, |
| | | selectionClass: "less-style", |
| | | originalQuantity: 0, |
| | | |
| | | // åºåºå¼¹çªç¸å
³æ°æ® |
| | | showOutboundDialog: false, |
| | | outboundForm: { selectedPlatform: "" }, // 表åç»å®æ°æ® |
| | | outboundRules: { |
| | | selectedPlatform: [ |
| | | { required: true, message: "è¯·éæ©åºåºç«å°", trigger: "change" }, |
| | | ], |
| | | }, |
| | | platformOptions: [ |
| | | { label: "ç«å°2", value: "2-1" }, |
| | | { label: "ç«å°3", value: "3-1" }, |
| | | ], |
| | | }; |
| | | }, |
| | | methods: { |
| | | open(row) { |
| | | this.row = row; |
| | | this.showDetialBox = true; |
| | | this.getData(); |
| | | this.updateSelectionClass(); // åå§åå·²éæ°éæ ·å¼ |
| | | }, |
| | | |
| | | lockStock() { |
| | | this.http |
| | | .post( |
| | | "api/OutboundOrderDetail/LockOutboundStock?id=" + this.row.id, |
| | | this.selection, |
| | | "æ°æ®å¤çä¸" |
| | | ) |
| | | .then((x) => { |
| | | if (!x.status) return ElMessage.error(x.message); |
| | | ElMessage.success("æä½æå"); |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | // æå¼åºåºå¼¹çª |
| | | openOutboundDialog() { |
| | | if (this.selection.length === 0) { |
| | | return ElMessage.error("è¯·éæ©åæ®æç»"); |
| | | } |
| | | // é置表åé¿å
æ®çå¼ |
| | | this.outboundForm.selectedPlatform = ""; |
| | | this.showOutboundDialog = true; |
| | | }, |
| | | |
| | | // 确认åºåºæä½ |
| | | confirmOutbound() { |
| | | this.$refs.outboundFormRef.validate((valid) => { |
| | | if (!valid) return; |
| | | |
| | | |
| | | // æé 请æ±åæ° |
| | | const keys = this.selection.map((item) => item.id); |
| | | const requestParams = { |
| | | taskIds: keys, |
| | | outboundPlatform: this.outboundForm.selectedPlatform, |
| | | }; |
| | | console.log(this.selection) |
| | | // è°ç¨åºåºæ¥å£ |
| | | this.http |
| | | .post("api/Task/GenerateOutboundTasks", requestParams, "æ°æ®å¤çä¸") |
| | | .then((x) => { |
| | | if (!x.status) return ElMessage.error(x.message); |
| | | |
| | | ElMessage.success("æä½æå"); |
| | | this.showOutboundDialog = false; |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }) |
| | | .catch((error) => { |
| | | console.error("åºåºè¯·æ±å¤±è´¥:", error); |
| | | ElMessage.error("请æ±å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | // åºå®æ¥è¯¢ç«åºåºå |
| | | getData() { |
| | | const url = "api/StockInfo/GetStockSelectViews?materielCode="; |
| | | this.http |
| | | .post( |
| | | url + this.row.materielCode + "&orderId=" + this.row.orderId, |
| | | null, |
| | | "æ¥è¯¢ä¸" |
| | | ) |
| | | .then((x) => { |
| | | this.tableData = x; |
| | | // å·æ°åæ¸
空ä¹åçéæ©åè®¡æ° |
| | | this.clearSelection(); |
| | | this.selectionSum = 0; |
| | | this.originalQuantity = 0; |
| | | this.updateSelectionClass(); |
| | | }); |
| | | }, |
| | | |
| | | revokeAssign() { |
| | | this.http |
| | | .post( |
| | | "api/OutboundOrderDetail/RevokeLockOutboundStock?id=" + this.row.id, |
| | | null, |
| | | "æ°æ®å¤çä¸" |
| | | ) |
| | | .then((x) => { |
| | | if (!x.status) return ElMessage.error(x.message); |
| | | ElMessage.success("æä½æå"); |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | handleSelectionChange(val) { |
| | | this.selection = val; |
| | | // 计ç®å·²éæ°éï¼è½¬æ°åé¿å
åç¬¦ä¸²æ¼æ¥ï¼ |
| | | this.selectionSum = val.reduce( |
| | | (acc, curr) => acc + Number(curr.useableQuantity || 0), |
| | | 0 |
| | | ) + this.originalQuantity; |
| | | this.updateSelectionClass(); |
| | | }, |
| | | |
| | | // æ´æ°å·²éæ°éæ ·å¼ |
| | | updateSelectionClass() { |
| | | if (!this.row) return; |
| | | if (this.selectionSum === this.row.orderQuantity) { |
| | | this.selectionClass = "equle-style"; |
| | | } else if (this.selectionSum < this.row.orderQuantity) { |
| | | this.selectionClass = "less-style"; |
| | | } else { |
| | | this.selectionClass = "more-style"; |
| | | } |
| | | }, |
| | | |
| | | toggleSelection(rows) { |
| | | rows ? rows.forEach((row) => this.$refs.singleTable.toggleRowSelection(row)) : this.clearSelection(); |
| | | }, |
| | | |
| | | clearSelection() { |
| | | if (this.$refs.singleTable) { |
| | | this.$refs.singleTable.clearSelection(); |
| | | } |
| | | }, |
| | | |
| | | handleRowClick(row) { |
| | | this.$refs.singleTable.toggleRowSelection(row); |
| | | }, |
| | | |
| | | // 徿 æé®ç¹å»å 使¹æ³ï¼å¯æ ¹æ®éæ±æ©å±ï¼ |
| | | tableButtonClick(row, item) { |
| | | console.log("徿 æé®ç¹å»ï¼", item.title, row); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .less-style { |
| | | color: black; |
| | | } |
| | | |
| | | .equle-style { |
| | | color: green; |
| | | } |
| | | |
| | | .more-style { |
| | | color: red; |
| | | } |
| | | </style> |
| | | |
| | | <style> |
| | | .text-button:hover { |
| | | background-color: #f0f9eb !important; |
| | | } |
| | | |
| | | .el-table .warning-row { |
| | | background: oldlace; |
| | | } |
| | | |
| | | .box-table .el-table tbody tr:hover > td { |
| | | background-color: #d8e0d4 !important; |
| | | } |
| | | |
| | | .box-table .el-table tbody tr.current-row > td { |
| | | background-color: #f0f9eb !important; |
| | | } |
| | | |
| | | .el-table .success-row { |
| | | background: #f0f9eb; |
| | | } |
| | | |
| | | .box-table .el-table { |
| | | border: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .box-head .el-alert__content { |
| | | width: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <vol-box |
| | | v-model="showDetialBox" |
| | | :lazy="true" |
| | | width="75%" |
| | | title="åæ®æç»ä¿¡æ¯" |
| | | > |
| | | <div class="box-head"> |
| | | <el-alert :closable="false" style="width: 100%"> |
| | | <el-row> |
| | | <el-col :span="16"> |
| | | <span>å·²éä¸ {{ selection.length }} 项</span> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <!-- <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px" |
| | | @click="lockstocks" |
| | | >éå®åºå</el-link> --> |
| | | |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px" |
| | | @click="handleOpenPicking" |
| | | >æ£é</el-link> |
| | | |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="outbound" |
| | | >ç´æ¥åºåº</el-link |
| | | > |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px; margin-right: 10px" |
| | | @click="getData" |
| | | >å·æ°</el-link |
| | | ></el-col |
| | | > |
| | | </el-row> |
| | | </el-alert> |
| | | </div> |
| | | <div class="box-table" style="margin-top: 1%"> |
| | | <el-table |
| | | ref="singleTable" |
| | | :data="tableData" |
| | | style="width: 100%; height: 100%" |
| | | highlight-current-row |
| | | @current-change="handleCurrentChange" |
| | | height="500px" |
| | | @row-click="handleRowClick" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55"> </el-table-column> |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | fixed="left" |
| | | width="55" |
| | | align="center" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | v-for="(item, index) in tableColumns.filter((x) => !x.hidden)" |
| | | :key="index" |
| | | :prop="item.prop" |
| | | :label="item.title" |
| | | :width="item.width" |
| | | align="center" |
| | | > |
| | | <template #default="scoped"> |
| | | <div v-if="item.type == 'icon'"> |
| | | <el-tooltip |
| | | class="item" |
| | | effect="dark" |
| | | :content="item.title" |
| | | placement="bottom" |
| | | ><el-link |
| | | type="primary" |
| | | :disabled="getButtonEnable(item.prop, scoped.row)" |
| | | @click="tableButtonClick(scoped.row, item)" |
| | | ><i :class="item.icon" style="font-size: 22px"></i></el-link |
| | | ></el-tooltip> |
| | | </div> |
| | | |
| | | <div v-else-if="item.type == 'tag'"> |
| | | <el-tag size="small"> |
| | | {{ getDictionary(scoped.row, item) }} |
| | | </el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </vol-box> |
| | | <stock-select ref="child" @parentCall="parentCall"></stock-select> |
| | | <selected-stock |
| | | ref="selectedStock" |
| | | @parentCall="parentCall" |
| | | ></selected-stock> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import VolBox from "@/components/basic/VolBox.vue"; |
| | | import VolForm from "@/components/basic/VolForm.vue"; |
| | | import StockSelect from "./StockSelect.vue"; |
| | | import SelectedStock from "./SelectedStock.vue"; |
| | | import { h,createVNode, render,reactive } from 'vue'; |
| | | import { ElDialog , ElForm, ElFormItem, ElSelect,ElOption, ElButton, ElMessage } from 'element-plus'; |
| | | export default { |
| | | components: { VolBox, VolForm, StockSelect, SelectedStock }, |
| | | data() { |
| | | return { |
| | | row: null, |
| | | showDetialBox: false, |
| | | flag: false, |
| | | currentRow: null, |
| | | selection: [], |
| | | tableData: [], |
| | | tableColumns: [ |
| | | { |
| | | prop: "id", |
| | | title: "Id", |
| | | type: "int", |
| | | width: 90, |
| | | hidden: true, |
| | | }, |
| | | { |
| | | prop: "orderId", |
| | | title: "åºåºå主é®", |
| | | type: "string", |
| | | width: 90, |
| | | hidden: true, |
| | | }, |
| | | { |
| | | prop: "materielCode", |
| | | title: "ç©æç¼å·", |
| | | type: "string", |
| | | width: 150, |
| | | }, |
| | | { |
| | | prop: "materielName", |
| | | title: "ç©æåç§°", |
| | | type: "string", |
| | | width: 150, |
| | | }, |
| | | { |
| | | prop: "batchNo", |
| | | title: "æ¹æ¬¡å·", |
| | | type: "string", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "supplyCode", |
| | | title: "ä¾åºåç¼å·", |
| | | type: "string", |
| | | width: 150, |
| | | }, |
| | | { |
| | | prop: "orderQuantity", |
| | | title: "åæ®æ°é", |
| | | type: "string", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "lockQuantity", |
| | | title: "é宿°é", |
| | | type: "int", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "overOutQuantity", |
| | | title: "å·²åºæ°é", |
| | | type: "string", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "unit", |
| | | title: "åä½", |
| | | type: "string", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "orderDetailStatus", |
| | | title: "订åæç»ç¶æ", |
| | | type: "tag", |
| | | width: 180, |
| | | bindKey: "orderDetailStatusEnum", |
| | | }, |
| | | { |
| | | prop: "assignStock", |
| | | title: "æå®åºå", |
| | | type: "icon", |
| | | width: 90, |
| | | icon: "el-icon-s-grid", |
| | | }, |
| | | { |
| | | prop: "viewDetail", |
| | | title: "åºåºè¯¦ç»", |
| | | type: "icon", |
| | | width: 90, |
| | | icon: "el-icon-s-operation", |
| | | }, |
| | | { |
| | | prop: "creater", |
| | | title: "å建人", |
| | | type: "string", |
| | | width: 90, |
| | | }, |
| | | { |
| | | prop: "createDate", |
| | | title: "å建æ¶é´", |
| | | type: "datetime", |
| | | width: 160, |
| | | }, |
| | | { |
| | | prop: "modifier", |
| | | title: "ä¿®æ¹äºº", |
| | | type: "string", |
| | | width: 100, |
| | | }, |
| | | { |
| | | prop: "modifyDate", |
| | | title: "ä¿®æ¹æ¶é´", |
| | | type: "datetime", |
| | | width: 160, |
| | | }, |
| | | { |
| | | prop: "remark", |
| | | title: "夿³¨", |
| | | type: "string", |
| | | }, |
| | | ], |
| | | paginations: { |
| | | sort: "id", |
| | | order: "desc", |
| | | Foots: "", |
| | | total: 0, |
| | | // 2020.08.29å¢å èªå®ä¹å页æ¡å¤§å° |
| | | sizes: [30, 60, 100, 120], |
| | | size: 30, // é»è®¤åé¡µå¤§å° |
| | | Wheres: [], |
| | | page: 1, |
| | | rows: 30, |
| | | }, |
| | | searchFormOptions: [ |
| | | [ |
| | | { |
| | | title: "åæ®ç¼å·", |
| | | field: "allocation_code", |
| | | type: "like", |
| | | }, |
| | | { |
| | | title: "åæ®ç±»å", |
| | | field: "allocation_type", |
| | | type: "select", |
| | | dataKey: "OrderType", |
| | | data: [], |
| | | }, |
| | | { |
| | | title: "åæ®ç¶æ", |
| | | field: "allocation_state", |
| | | type: "select", |
| | | dataKey: "OrderState", |
| | | data: [], |
| | | }, |
| | | ], |
| | | ], |
| | | searchFormFields: { |
| | | allocation_code: "", |
| | | allocation_type: "", |
| | | allocation_state: "", |
| | | }, |
| | | dictionaryList: null, |
| | | }; |
| | | }, |
| | | methods: { |
| | | open(row) { |
| | | this.row = row; |
| | | this.showDetialBox = true; |
| | | this.getDictionaryData(); |
| | | this.getData(); |
| | | }, |
| | | getData() { |
| | | var wheres = [{ name: "orderId", value: this.row.id }]; |
| | | var param = { |
| | | page: this.paginations.page, |
| | | rows: this.paginations.rows, |
| | | sort: this.paginations.sort, |
| | | order: this.paginations.order, |
| | | wheres: JSON.stringify(wheres), // æ¥è¯¢æ¡ä»¶ï¼æ ¼å¼ä¸º[{ name: "åæ®µ", value: "xx" }] |
| | | }; |
| | | this.http |
| | | .post("api/AllocateOrderDetail/GetPageData", param, "æ¥è¯¢ä¸") |
| | | .then((x) => { |
| | | this.tableData = x.rows; |
| | | }); |
| | | }, |
| | | tableButtonClick(row, column) { |
| | | if (column.prop == "assignStock") { |
| | | this.$refs.child.open(row); |
| | | } else { |
| | | //ç¹å»æå¼åºåºè¯¦æ
|
| | | this.$refs.selectedStock.open(row); |
| | | } |
| | | }, |
| | | lockstocks() { |
| | | if (this.selection.length === 0) { |
| | | return this.$message.error("è¯·éæ©åæ®æç»"); |
| | | } |
| | | var keys = this.selection.map((item) => item.id); // è·åéä¸è¡çid |
| | | this.http |
| | | .post("api/AllocateOrderDetail/LockOutboundStocks", keys, "æ°æ®å¤çä¸") |
| | | .then((x) => { |
| | | if (!x.status) return this.$message.error(x.message); |
| | | this.$message.success("æä½æå"); |
| | | this.showDetialBox = false; |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); |
| | | }); |
| | | }); |
| | | }, |
| | | // æå¼æ£éé¡µé¢ |
| | | handleOpenPicking() { |
| | | this.$router.push({ |
| | | path: '/outbound/picking', |
| | | query: { orderId: this.row.id ,orderNo:this.row.orderNo} |
| | | }) |
| | | }, |
| | | outbound() { |
| | | if (this.selection.length === 0) { |
| | | return this.$message.error("è¯·éæ©åæ®æç»"); |
| | | } |
| | | const platformOptions = [{label:'ç«å°2',value:'2-1'},{label:'ç«å°3',value:'3-1'}]; |
| | | const mountNode = document.createElement('div'); |
| | | document.body.appendChild(mountNode); |
| | | |
| | | // 2. è¡¨åæ°æ®ï¼é»è®¤éä¸ç«å°3ï¼ |
| | | const formData = reactive({ |
| | | selectedPlatform: platformOptions[0].value // é»è®¤ç»å®ãç«å°3ãçvalue |
| | | }); |
| | | |
| | | // 3. 卿å建弹çªç»ä»¶ |
| | | const vnode = createVNode(ElDialog, { |
| | | title: 'åºåºæä½ - éæ©åºåºç«å°', |
| | | width: '500px', |
| | | modelValue: true, |
| | | appendToBody: true, |
| | | 'onUpdate:modelValue': (isVisible) => { |
| | | if (!isVisible) { |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | } |
| | | }, |
| | | style: { |
| | | padding: '20px 0', |
| | | borderRadius: '8px' |
| | | } |
| | | }, { |
| | | default: () => h(ElForm, { |
| | | model: formData, |
| | | rules: { |
| | | selectedPlatform: [ |
| | | { required: true, message: 'è¯·éæ©åºåºç«å°', trigger: 'change' } |
| | | ] |
| | | }, |
| | | ref: 'outboundForm', |
| | | labelWidth: '100px', |
| | | style: { |
| | | padding: '0 30px' |
| | | } |
| | | }, [ |
| | | // åºåºç«å°éæ©é¡¹ï¼æ ¸å¿è¡¨åé¡¹ï¼ |
| | | h(ElFormItem, { |
| | | label: 'åºåºç«å°', |
| | | prop: 'selectedPlatform', |
| | | style: { |
| | | marginBottom: '24px' |
| | | } |
| | | }, [ |
| | | h(ElSelect, { |
| | | placeholder: 'è¯·éæ©åºåºç«å°ï¼3-12ï¼', |
| | | modelValue: formData.selectedPlatform, |
| | | 'onUpdate:modelValue': (val) => { |
| | | formData.selectedPlatform = val; |
| | | }, |
| | | style: { |
| | | width: '100%', |
| | | height: '40px', |
| | | borderRadius: '4px', |
| | | borderColor: '#dcdfe6' |
| | | } |
| | | }, platformOptions.map(platform => |
| | | h(ElOption, { label: platform.label, value: platform.value }) |
| | | )) |
| | | ]), |
| | | // åºé¨æé®åº |
| | | h('div', { |
| | | style: { |
| | | textAlign: 'right', |
| | | marginTop: '8px', |
| | | paddingRight: '4px' |
| | | } |
| | | }, [ |
| | | h(ElButton, { |
| | | type: 'text', |
| | | onClick: () => { |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | ElMessage.info('åæ¶åºåºæä½'); |
| | | }, |
| | | style: { |
| | | marginRight: '8px', |
| | | color: '#606266' |
| | | } |
| | | }, 'åæ¶'), |
| | | h(ElButton, { |
| | | type: 'primary', |
| | | onClick: async () => { |
| | | const formRef = vnode.component.refs.outboundForm; |
| | | try { |
| | | // è¡¨åæ ¡éª |
| | | await formRef.validate(); |
| | | } catch (err) { |
| | | return; |
| | | } |
| | | |
| | | // 4. æé 请æ±åæ°ï¼éä¸åæ®ID + éæ©çåºåºç«å°ï¼ |
| | | const keys = this.selection.map((item) => item.id); |
| | | const requestParams = { |
| | | taskIds: keys, |
| | | outboundPlatform: formData.selectedPlatform // åºåºç«å° |
| | | }; |
| | | |
| | | // 5. è°ç¨åºåºæ¥å£ |
| | | this.http |
| | | .post("api/Task/GenerateOutboundTasks", requestParams, "æ°æ®å¤çä¸") |
| | | .then((x) => { |
| | | if (!x.status) return ElMessage.error(x.message); |
| | | |
| | | ElMessage.success("æä½æå"); |
| | | this.showDetialBox = false; // å
³é详æ
æ¡ |
| | | this.$emit("parentCall", ($vue) => { |
| | | $vue.getData(); // éç¥ç¶ç»ä»¶å·æ° |
| | | }); |
| | | // å
³éå¼¹çª |
| | | render(null, mountNode); |
| | | document.body.removeChild(mountNode); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error('请æ±å¤±è´¥ï¼è¯·ç¨åéè¯'); |
| | | }); |
| | | }, |
| | | style: { |
| | | borderRadius: '4px', |
| | | padding: '8px 20px' |
| | | } |
| | | }, 'ç¡®å®åºåº') |
| | | ]) |
| | | ]) |
| | | }); |
| | | |
| | | // ç»å®appä¸ä¸æï¼ç¡®ä¿Elç»ä»¶æ£å¸¸å·¥ä½ |
| | | vnode.appContext = this.$.appContext; |
| | | render(vnode, mountNode); |
| | | }, |
| | | setCurrent(row) { |
| | | this.$refs.singleTable.setCurrentRow(row); |
| | | }, |
| | | handleCurrentChange(val) { |
| | | this.currentRow = val; |
| | | }, |
| | | getButtonEnable(propName, row) { |
| | | if (propName == "assignStock") { |
| | | if ( |
| | | row.orderDetailStatus !== 0 && |
| | | row.orderDetailStatus !== 60 && |
| | | row.orderDetailStatus !== 70 && |
| | | row.orderDetailStatus !== 80 |
| | | ) { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | return false; |
| | | }, |
| | | parentCall(fun) { |
| | | if (typeof fun != "function") { |
| | | return console.log("æ©å±ç»ä»¶éè¦ä¼ å
¥ä¸ä¸ªåè°æ¹æ³æè½è·åç¶çº§Vue对象"); |
| | | } |
| | | fun(this); |
| | | }, |
| | | handleRowClick(row) { |
| | | this.$refs.singleTable.toggleRowSelection(row); |
| | | }, |
| | | handleSelectionChange(val) { |
| | | this.selection = val; |
| | | }, |
| | | getDictionaryData() { |
| | | if (this.dictionaryList) { |
| | | return; |
| | | } |
| | | var param = []; |
| | | this.tableColumns.forEach((x) => { |
| | | if (x.type == "tag" && x.bindKey != "") { |
| | | param.push(x.bindKey); |
| | | } |
| | | }); |
| | | this.http |
| | | .post("api/Sys_Dictionary/GetVueDictionary", param, "æ¥è¯¢ä¸") |
| | | .then((x) => { |
| | | if (x.length > 0) { |
| | | this.dictionaryList = x; |
| | | } |
| | | }); |
| | | }, |
| | | getDictionary(row, column) { |
| | | if (this.dictionaryList) { |
| | | var item = this.dictionaryList.find((x) => x.dicNo == column.bindKey); |
| | | if (item) { |
| | | var dicItem = item.data.find((x) => x.key == row[column.prop]); |
| | | console.log(dicItem); |
| | | if (dicItem) { |
| | | return dicItem.value; |
| | | } else { |
| | | return row[column.prop]; |
| | | } |
| | | } else { |
| | | return row[column.prop]; |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | <style scoped> |
| | | .text-button { |
| | | border: 0px; |
| | | } |
| | | </style> |
| | | |
| | | <style> |
| | | .text-button:hover { |
| | | background-color: #f0f9eb !important; |
| | | } |
| | | |
| | | .el-table .warning-row { |
| | | background: oldlace; |
| | | } |
| | | |
| | | .box-table .el-table tbody tr:hover > td { |
| | | background-color: #d8e0d4 !important; |
| | | /* color: #ffffff; */ |
| | | } |
| | | |
| | | .box-table .el-table tbody tr.current-row > td { |
| | | background-color: #f0f9eb !important; |
| | | /* color: #ffffff; */ |
| | | } |
| | | |
| | | .el-table .success-row { |
| | | background: #f0f9eb; |
| | | } |
| | | |
| | | .box-table .el-table { |
| | | border: 1px solid #ebeef5; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view-grid |
| | | ref="gridRef" |
| | | ref="grid" |
| | | @openPalletDialog="handleOpenPalletDialog" |
| | | :columns="columns" |
| | | :detail="detail" |
| | | :editFormFields="editFormFields" |
| | |
| | | :extend="extend" |
| | | > |
| | | </view-grid> |
| | | </template> |
| | | <!-- 2. ç»çå¼¹çªï¼ç¡®ä¿propsåäºä»¶ç»å®æ£ç¡® --> |
| | | <PalletDialog |
| | | v-model:visible="palletVisible" |
| | | :docNo="currentPalletDocNo" |
| | | @back-success="handlePalletBackSuccess" |
| | | ></PalletDialog> |
| | | |
| | | </template> |
| | | <script> |
| | | import extend from "@/extension/inbound/Dt_AllocateOrder.js"; |
| | | import ViewGrid from '@/components/basic/ViewGrid/ViewGrid.vue'; |
| | | import { ref, defineComponent } from "vue"; |
| | | |
| | | import PalletDialog from "@/extension/inbound/extend/AllocatedPallet.vue"; |
| | | export default defineComponent({ |
| | | components: { |
| | | viewGrid: ViewGrid, |
| | | PalletDialog |
| | | // å
³é®ä¿®å¤2ï¼ç»ä»¶æ³¨åå䏿¨¡æ¿æ ç¾åéé
ï¼kebab-case对åºview-gridï¼ |
| | | viewGrid: ViewGrid, // 注å为kebab-caseï¼æ¨¡æ¿ç¨<view-grid> |
| | | PalletDialog // 注åç»çå¼¹çª |
| | | |
| | | }, |
| | | setup() { |
| | | const table = ref({ |
| | | key: "id", |
| | | footer: "Foots", |
| | | cnName: "è°æ¨å", |
| | | name: "allocateOrder", |
| | | url: "/allocateOrder/", |
| | | name: "Dt_AllocateOrder", |
| | | url: "/AllocateOrder/", |
| | | sortName: "id", |
| | | }); |
| | | |
| | |
| | | key: "id", |
| | | }); |
| | | |
| | | // 6. ç»çå¼¹çªèå¨ï¼ææåéå¿
é¡»è¿åï¼ |
| | | const palletVisible = ref(false); |
| | | const currentPalletDocNo = ref(""); |
| | | |
| | | const handleOpenPalletDialog = (docNo) => { |
| | | console.log('主ç»ä»¶æ¶å°ç»çäºä»¶ï¼åæ®å·ï¼', docNo); |
| | | currentPalletDocNo.value = docNo; |
| | | palletVisible.value = true; |
| | | }; |
| | | |
| | | const handlePalletBackSuccess = () => { |
| | | console.log('ç»çåä¼ æåï¼å·æ°è¡¨æ ¼'); |
| | | grid.value?.refresh(); // æ¤æ¶gridRefå·²æè½½ï¼å¯è°ç¨æ¹æ³ |
| | | }; |
| | | |
| | | return { |
| | | table, |
| | | extend, |
| | |
| | | searchFormOptions, |
| | | columns, |
| | | detail, |
| | | // ç»çå¼¹çªç¸å
³ |
| | | PalletDialog, // å¼¹çªç»ä»¶ï¼æ éè¿åï¼æ³¨åå³å¯ï¼ä½åééè¿åï¼ |
| | | palletVisible, |
| | | currentPalletDocNo, |
| | | handleOpenPalletDialog, |
| | | handlePalletBackSuccess, |
| | | gridRef |
| | | handlePalletBackSuccess |
| | | }; |
| | | }, |
| | | }); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_Core.Helper; |
| | | using WIDESEA_IAllocateService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_AllocateService |
| | | { |
| | | public class AllocateDetailService : ServiceBase<Dt_AllocateOrderDetail, IRepository<Dt_AllocateOrderDetail>>, IAllocateDetailService |
| | | { |
| | | public AllocateDetailService(IRepository<Dt_AllocateOrderDetail> BaseDal) : base(BaseDal) |
| | | { |
| | | } |
| | | |
| | | IRepository<Dt_AllocateOrderDetail> IAllocateDetailService.Repository => BaseDal; |
| | | |
| | | public override PageGridData<Dt_AllocateOrderDetail> GetPageData(PageDataOptions options) |
| | | { |
| | | |
| | | ISugarQueryable<Dt_AllocateOrderDetail> sugarQueryable1 = BaseDal.Db.Queryable<Dt_AllocateOrderDetail>(); |
| | | if (!string.IsNullOrEmpty(options.Wheres)) |
| | | { |
| | | |
| | | List<SearchParameters> searchParametersList = options.Wheres.DeserializeObject<List<SearchParameters>>(); |
| | | int totalCount = 0; |
| | | if (searchParametersList.Count > 0) |
| | | { |
| | | { |
| | | SearchParameters? searchParameters = searchParametersList.FirstOrDefault(x => x.Name == nameof(Dt_AllocateOrderDetail.OrderId).FirstLetterToLower()); |
| | | if (searchParameters != null) |
| | | { |
| | | sugarQueryable1 = sugarQueryable1.Where(x => x.OrderId == searchParameters.Value.ObjToInt()); |
| | | var dataList = sugarQueryable1.ToPageList(options.Page, options.Rows, ref totalCount); |
| | | return new PageGridData<Dt_AllocateOrderDetail>(totalCount, dataList); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | | return new PageGridData<Dt_AllocateOrderDetail>(); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_IAllocateService |
| | | { |
| | | public interface IAllocateDetailService : IService<Dt_AllocateOrderDetail> |
| | | { |
| | | IRepository<Dt_AllocateOrderDetail> Repository { get; } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using WIDESEA_Core.BaseController; |
| | | using WIDESEA_IAllocateService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers.Allocate |
| | | { |
| | | /// <summary> |
| | | /// è°æ¨åæç» |
| | | /// </summary> |
| | | [Route("api/AllocateOrderDetail")] |
| | | [ApiController] |
| | | public class AllocateOrderDetailController : ApiBaseController<IAllocateDetailService, Dt_AllocateOrderDetail> |
| | | { |
| | | public AllocateOrderDetailController(IAllocateDetailService service) : base(service) |
| | | { |
| | | } |
| | | } |
| | | } |