出入库申请申请页面数据交互逻辑
This commit is contained in:
parent
5632412229
commit
94d825fa2d
@ -8,16 +8,18 @@
|
|||||||
|
|
||||||
<a-form-item label="申请类型" name="applyType">
|
<a-form-item label="申请类型" name="applyType">
|
||||||
<a-radio-group v-model:value="formData.applyType" button-style="solid" style="width: 40%;">
|
<a-radio-group v-model:value="formData.applyType" button-style="solid" style="width: 40%;">
|
||||||
<a-radio-button value='1'>采购入库</a-radio-button>
|
<a-radio-button value='1' v-if="applyType === '1'">采购入库</a-radio-button>
|
||||||
<a-radio-button value='2'>归还入库</a-radio-button>
|
<a-radio-button value='2' v-if="applyType === '1'">归还入库</a-radio-button>
|
||||||
|
<a-radio-button value='3' v-if="applyType === '3'">出库外借</a-radio-button>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="申请日期" name="applyDate" style="width: 40%;">
|
<a-form-item label="申请日期" name="applyDate" style="width: 40%;">
|
||||||
<a-date-picker v-model:value="formData.applyDate" />
|
<a-date-picker v-model:value="formData.applyDate" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="入库物料" name="selected">
|
<a-form-item label="选择物料" name="selected">
|
||||||
<a-select v-model:value="formData.slectedList" mode="multiple" bordered placeholder="请选择入库物料" style="width: 40%;"
|
<a-select v-model:value="formData.slectedList" mode="multiple" bordered placeholder="请选择物料" style="width: 40%;"
|
||||||
showArrow :options="options" @deselect="removeEvent" @select="insertEvent"></a-select>
|
show-search :options="options" @deselect="removeEvent"
|
||||||
|
@select="insertEvent"></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
@ -25,8 +27,7 @@
|
|||||||
<!-- vxe-table -->
|
<!-- vxe-table -->
|
||||||
<div>
|
<div>
|
||||||
<vxe-table border show-overflow ref="tableRef" max-height="500" size="medium" v-model:data="tableData"
|
<vxe-table border show-overflow ref="tableRef" max-height="500" size="medium" v-model:data="tableData"
|
||||||
empty-text="请先选择入库物料" :edit-config="{ trigger: 'click', mode: 'cell', autoFocus: true }">
|
empty-text="请先选择物料" :edit-config="{ trigger: 'click', mode: 'cell', autoFocus: true }">
|
||||||
|
|
||||||
<vxe-column type="seq" title="序号" width="60" />
|
<vxe-column type="seq" title="序号" width="60" />
|
||||||
<vxe-column field="id" title="物料id" :visible="false" />
|
<vxe-column field="id" title="物料id" :visible="false" />
|
||||||
<vxe-column field="name" title="物料名称" />
|
<vxe-column field="name" title="物料名称" />
|
||||||
@ -57,13 +58,29 @@ import api from '@/api'
|
|||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import dayjs, { Dayjs } from 'dayjs';
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
// 和外层界面的数据交互
|
// 和外层界面的数据交互
|
||||||
|
const props = defineProps(
|
||||||
|
{
|
||||||
|
applyType: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
} // 申请类型 applyType页面传值的使用1和2,1: 采购入库 和 归还入库 2: 出库外借
|
||||||
|
)
|
||||||
const getTableData = () => {
|
const getTableData = () => {
|
||||||
const $table = tableRef.value
|
const $table = tableRef.value
|
||||||
return $table?.getTableData().fullData;
|
return $table?.getTableData().fullData;
|
||||||
}
|
}
|
||||||
|
const getApplyForm = () => {
|
||||||
defineExpose({ getTableData})
|
return {
|
||||||
|
type: formData.value.applyType,
|
||||||
|
applicant: formData.value.applicant,
|
||||||
|
applyDate: formData.value.applyDate.format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
isConfirm: true,
|
||||||
|
exceptionExplain: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ getTableData, getApplyForm })
|
||||||
|
|
||||||
interface FormData {
|
interface FormData {
|
||||||
applicant: string; // 申请人
|
applicant: string; // 申请人
|
||||||
@ -76,7 +93,7 @@ const userStore = useUserStore()
|
|||||||
const formData = ref<FormData>({
|
const formData = ref<FormData>({
|
||||||
applicant: userStore.userName,
|
applicant: userStore.userName,
|
||||||
applyDate: dayjs(),
|
applyDate: dayjs(),
|
||||||
applyType: '1', // 1: 采购入库 2: 归还入库 3: 出库外借
|
applyType: props.applyType, // 1: 采购入库 2: 归还入库 3: 出库外借
|
||||||
slectedList: []
|
slectedList: []
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -138,7 +155,7 @@ const insertEvent = (value: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 取消选中时,删除table中的行
|
// 取消选中时,删除table中的行
|
||||||
const removeEvent = (value: any) => {
|
const removeEvent = (value : any) => {
|
||||||
const $table = tableRef.value
|
const $table = tableRef.value
|
||||||
// 根据value找到对应的行
|
// 根据value找到对应的行
|
||||||
if ($table) {
|
if ($table) {
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- steps -->
|
<!-- steps -->
|
||||||
<div>
|
<div v-show="current != 3">
|
||||||
<a-steps v-model:current="current" :items="items"></a-steps>
|
<a-steps v-model:current="current" :items="items"></a-steps>
|
||||||
|
<a-divider style="height: 2px; background-color: #7cb305" />
|
||||||
</div>
|
</div>
|
||||||
<a-divider style="height: 2px; background-color: #7cb305" />
|
|
||||||
<!-- step1 -->
|
<!-- step1 -->
|
||||||
|
|
||||||
<div class="step-1" v-show="current === 0">
|
<div class="step-1" v-show="current === 0">
|
||||||
<apply-form ref="applyFormRef"></apply-form>
|
<apply-form :apply-type="applyType" ref="applyFormRef"></apply-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step-2" v-show="current === 1">
|
<div class="step-2" v-show="current === 1">
|
||||||
<scan-form :total-value="totalValue"></scan-form>
|
<scan-form :total-value="totalValue" ref="scanFormRef"></scan-form>
|
||||||
</div>
|
</div>
|
||||||
<div class="step-3" v-show="current === 2">
|
<div class="step-3" v-show="current === 2">
|
||||||
<apply-confirm></apply-confirm>
|
<apply-confirm :table-data="conformData" ref="applyConfirmRef"></apply-confirm>
|
||||||
|
</div>
|
||||||
|
<div class="step-4" v-show="current === 3">
|
||||||
|
<successResul></successResul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@ -22,7 +26,7 @@
|
|||||||
<a-space wrap class="fixed-button-container">
|
<a-space wrap class="fixed-button-container">
|
||||||
<a-button type="dashed" v-if="current != 0" @click="current--">上一步</a-button>
|
<a-button type="dashed" v-if="current != 0" @click="current--">上一步</a-button>
|
||||||
<a-button type="primary" v-if="current != 2" @click="nextStep">下一步</a-button>
|
<a-button type="primary" v-if="current != 2" @click="nextStep">下一步</a-button>
|
||||||
<a-button type="primary" v-if="current === 2">提交申请</a-button>
|
<a-button type="primary" :loading="loading" v-if="current === 2" @click="submit">提交申请</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -30,26 +34,92 @@
|
|||||||
import applyForm from '../component/applyForm.vue'
|
import applyForm from '../component/applyForm.vue'
|
||||||
import scanForm from '../component/scanForm.vue';
|
import scanForm from '../component/scanForm.vue';
|
||||||
import applyConfirm from '../component/applyConfirm.vue';
|
import applyConfirm from '../component/applyConfirm.vue';
|
||||||
|
import successResul from '../component/successResul.vue';
|
||||||
|
import api from '@/api'
|
||||||
|
|
||||||
|
// 和外层界面的数据交互
|
||||||
|
defineProps(
|
||||||
|
{
|
||||||
|
applyType: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
}
|
||||||
|
} // 申请类型 applyType页面传值的使用1和2,1: 采购入库 和 归还入库 2: 出库外借
|
||||||
|
)
|
||||||
// steps
|
// steps
|
||||||
const current = ref<number>(0) // 翻页的引用
|
const current = ref<number>(0) // 翻页的引用
|
||||||
const applyFormRef = ref(); // step1表单引用
|
const applyFormRef = ref(); // step1表单引用
|
||||||
const selectData = ref();
|
const scanFormRef = ref(); // step2表单引用
|
||||||
|
const applyConfirmRef = ref(); // step3表单引用
|
||||||
const totalValue = ref(199);
|
|
||||||
|
|
||||||
|
const selectData = ref(); // step1中用户申请选择的物料数据,存的原始数据
|
||||||
|
const scanData = ref(); // step2中用户扫码的物料数据
|
||||||
|
const totalValue = ref(0); // 传给扫码页面的合计数值
|
||||||
|
const conformData = ref<Array<object>>([]); // step3中的待确认数据
|
||||||
|
const loading = ref(false); // 提交按钮的loading状态
|
||||||
|
|
||||||
const items = [{ title: '录入申请' }, { title: '扫码点货' }, { title: '人工确认' }]
|
const items = [{ title: '录入申请' }, { title: '扫码点货' }, { title: '人工确认' }]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击下一步
|
||||||
|
*/
|
||||||
const nextStep = () => {
|
const nextStep = () => {
|
||||||
if (applyFormRef.value) {
|
|
||||||
|
if (applyFormRef.value && current.value === 0) { // 再step1中点击下一步的时候,就去获取step1中的表单数据
|
||||||
selectData.value = applyFormRef.value.getTableData();
|
selectData.value = applyFormRef.value.getTableData();
|
||||||
|
selectData.value.forEach((item) => {
|
||||||
|
if (item.assignRule === 1) {
|
||||||
|
totalValue.value += item.quantity
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
if (scanFormRef.value && current.value === 1) { // 再step2中点击下一步的时候,就去获取step2中的表单数据
|
||||||
|
const items = scanFormRef.value.getTableData();
|
||||||
|
const groupedSums = items.reduce((acc, item) => {
|
||||||
|
if (!acc[item.code]) {
|
||||||
|
acc[item.code] = 0;
|
||||||
|
}
|
||||||
|
acc[item.code]++;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
scanData.value = items
|
||||||
|
// 组装步骤三的原始数据
|
||||||
|
conformData.value = selectData.value.map(item => {
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
name: item.name,
|
||||||
|
code: item.code,
|
||||||
|
applyNum: item.quantity,
|
||||||
|
scan: item.assignRule,
|
||||||
|
scanNum: groupedSums[item.code] || 0,
|
||||||
|
remark: item.quantity != groupedSums[item.code] ? `实际扫码数量与申请数量不一致` : '',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 切换到下一步
|
||||||
current.value++
|
current.value++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交申请
|
||||||
|
*/
|
||||||
|
const submit = () => {
|
||||||
|
loading.value = true;
|
||||||
|
// 提交申请
|
||||||
|
console.log('提交申请')
|
||||||
|
// 获取用户最终确认的数据
|
||||||
|
const applyDetails = applyConfirmRef.value.getTableData(); // 申请明细数据
|
||||||
|
const applyForm = applyFormRef.value.getApplyForm(); // 申请表单数据
|
||||||
|
|
||||||
|
api.materialApi.apply.saveOrUpdateApply({ applyForm: applyForm, applyDetails: applyDetails }, () => {
|
||||||
|
console.log('申请成功')
|
||||||
|
// 清理缓存数据
|
||||||
|
loading.value = false;
|
||||||
|
current.value = 3;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
style="margin-top: 20px; margin-bottom: 20px;" />
|
style="margin-top: 20px; margin-bottom: 20px;" />
|
||||||
<a-row style="margin-bottom: 20px;">
|
<a-row style="margin-bottom: 20px;">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-statistic title="总共扫码数量" :value="totalValue" style="margin-right: 50px" />
|
<a-statistic title="扫码合计" :value="totalValue" style="margin-right: 50px" />
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<a-statistic title="待扫码数量" :value="remainderValue" />
|
<a-statistic title="已扫码" :value="remainderValue" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<!-- Esc键退出编辑功能 -->
|
<!-- Esc键退出编辑功能 -->
|
||||||
@ -19,7 +19,7 @@
|
|||||||
<vxe-column type="seq" title="序号" width="60"></vxe-column>
|
<vxe-column type="seq" title="序号" width="60"></vxe-column>
|
||||||
<vxe-column field="id" title="物料id" :visible="false"></vxe-column>
|
<vxe-column field="id" title="物料id" :visible="false"></vxe-column>
|
||||||
<vxe-column field="barcode" title="物料条码" :edit-render="{ name: 'input', autoFocus: true, immediate: true }" />
|
<vxe-column field="barcode" title="物料条码" :edit-render="{ name: 'input', autoFocus: true, immediate: true }" />
|
||||||
<vxe-column field="role" title="物料名称" />
|
<vxe-column field="name" title="物料名称" />
|
||||||
<vxe-column field="code" title="编码" />
|
<vxe-column field="code" title="编码" />
|
||||||
<vxe-column field="spec" title="规格" />
|
<vxe-column field="spec" title="规格" />
|
||||||
<vxe-column field="type" title="类型" />
|
<vxe-column field="type" title="类型" />
|
||||||
@ -36,15 +36,34 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { VxeTableInstance } from 'vxe-table'
|
import { VxeTableInstance } from 'vxe-table'
|
||||||
import { useTemplateRef } from 'vue'
|
import { useTemplateRef } from 'vue'
|
||||||
import api from '@/api/index';
|
import { api } from '@/api'
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
// 父组件数据交互
|
// 父组件数据交互
|
||||||
defineProps(
|
defineProps(
|
||||||
{ totalValue: Number }
|
{
|
||||||
|
totalValue: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
//获取扫码的集合
|
||||||
|
const getTableData = () => {
|
||||||
|
const $table = applyDetailTableRef.value
|
||||||
|
if ($table) {
|
||||||
|
return $table.getTableData().fullData.map(item => ({
|
||||||
|
sn: item.barcode,
|
||||||
|
code: item.code,
|
||||||
|
date: item.times
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ getTableData })
|
||||||
|
|
||||||
const remainderValue = ref(100) // 上一步传递过来
|
|
||||||
|
|
||||||
|
const remainderValue = ref(0)
|
||||||
|
|
||||||
//扫码的条形码字符串
|
//扫码的条形码字符串
|
||||||
const value = ref('')
|
const value = ref('')
|
||||||
@ -54,13 +73,16 @@ const snListCache = ref<string[]>([]) // 缓存扫码的条形码列表
|
|||||||
// 定义一个map缓存物料信息
|
// 定义一个map缓存物料信息
|
||||||
const materialMapCache = ref<Map<string, material.Material>>(new Map<string, material.Material>()) // 缓存物料信息,key是code
|
const materialMapCache = ref<Map<string, material.Material>>(new Map<string, material.Material>()) // 缓存物料信息,key是code
|
||||||
|
|
||||||
// 请求接口获取缓存数据
|
|
||||||
|
/**
|
||||||
|
* 请求接口获取缓存数据
|
||||||
|
*/
|
||||||
const getCache = () => {
|
const getCache = () => {
|
||||||
|
|
||||||
api.materialApi.material.all((data) => {
|
api.materialApi.material.all((data) => {
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
if (item.code) {
|
if (item.code) {
|
||||||
materialMapCache.value.set(item.code, item)
|
materialMapCache.value.set(item.code, item) // 物料编码定义为6位
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -68,6 +90,7 @@ const getCache = () => {
|
|||||||
getCache();
|
getCache();
|
||||||
|
|
||||||
interface TableRowVO {
|
interface TableRowVO {
|
||||||
|
id: number
|
||||||
barcode: string
|
barcode: string
|
||||||
name: string
|
name: string
|
||||||
code: string
|
code: string
|
||||||
@ -103,29 +126,42 @@ const autoInsertOneRow = async () => {
|
|||||||
* 3. 根据sn获取物料信息,并新增一行到表格中,需要缓存物料信息
|
* 3. 根据sn获取物料信息,并新增一行到表格中,需要缓存物料信息
|
||||||
* 4. 插入成功后缓存sn
|
* 4. 插入成功后缓存sn
|
||||||
*/
|
*/
|
||||||
if (sn.length === 0 || snListCache.value.includes(sn)) {
|
if (sn.length === 0) {
|
||||||
value.value = ''
|
value.value = ''
|
||||||
message.warning('【' + sn + '】条形码重复或为空,请重新扫码', 5)
|
message.warning('【' + sn + '】条形码为空,请重新扫码', 5)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (snListCache.value.includes(sn)) {
|
||||||
|
value.value = ''
|
||||||
|
message.warning('【' + sn + '】条形码重复,请重新扫码', 5)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 找到条形码对应的物料编码
|
||||||
|
const code = sn.slice(0, 6)
|
||||||
|
const materialInfo = materialMapCache.value.get(code)
|
||||||
|
if (!materialInfo) {
|
||||||
|
value.value = ''
|
||||||
|
message.warning('【' + sn + '】条形码不合法,请重新扫码', 5)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($table) {
|
if ($table) {
|
||||||
const row: TableRowVO = {
|
const row: TableRowVO = {
|
||||||
|
id: materialInfo?.id ?? 0,
|
||||||
barcode: sn,
|
barcode: sn,
|
||||||
name: '',
|
name: materialInfo?.name ?? '',
|
||||||
code: '',
|
code: materialInfo?.code ?? '',
|
||||||
spec: '',
|
spec: materialInfo?.spec ?? '',
|
||||||
type: '',
|
type: materialInfo?.type ?? '',
|
||||||
times: new Date().toLocaleString()
|
times: new Date().toLocaleString()
|
||||||
}
|
}
|
||||||
|
$table.insert(row)
|
||||||
|
|
||||||
$table.insertAt(row, null)
|
|
||||||
// 缓存sn
|
// 缓存sn
|
||||||
snListCache.value.push(sn)
|
snListCache.value.push(sn)
|
||||||
//待扫码数量减一
|
//已扫码数量+1
|
||||||
|
|
||||||
remainderValue.value = remainderValue.value - 1
|
remainderValue.value = remainderValue.value + 1
|
||||||
// 添加后就清空输入框
|
// 添加后就清空输入框
|
||||||
value.value = ''
|
value.value = ''
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<apply-modal></apply-modal>
|
<apply-modal apply-type='1'></apply-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<apply-page pageType='2'></apply-page>
|
<apply-modal apply-type='3'></apply-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import applyPage from '../component/apply-page.vue';
|
import applyModal from "@/views/stock/component/applyModal.vue";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user