出入库申请申请页面数据交互逻辑

This commit is contained in:
mayong 2024-12-05 17:59:23 +08:00
parent 5632412229
commit 94d825fa2d
5 changed files with 170 additions and 47 deletions

View File

@ -8,16 +8,18 @@
<a-form-item label="申请类型" name="applyType">
<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='2'>归还入库</a-radio-button>
<a-radio-button value='1' v-if="applyType === '1'">采购入库</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-form-item>
<a-form-item label="申请日期" name="applyDate" style="width: 40%;">
<a-date-picker v-model:value="formData.applyDate" />
</a-form-item>
<a-form-item label="入库物料" name="selected">
<a-select v-model:value="formData.slectedList" mode="multiple" bordered placeholder="请选择入库物料" style="width: 40%;"
showArrow :options="options" @deselect="removeEvent" @select="insertEvent"></a-select>
<a-form-item label="选择物料" name="selected">
<a-select v-model:value="formData.slectedList" mode="multiple" bordered placeholder="请选择物料" style="width: 40%;"
show-search :options="options" @deselect="removeEvent"
@select="insertEvent"></a-select>
</a-form-item>
</a-form>
</div>
@ -25,8 +27,7 @@
<!-- vxe-table -->
<div>
<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 field="id" title="物料id" :visible="false" />
<vxe-column field="name" title="物料名称" />
@ -57,13 +58,29 @@ import api from '@/api'
import { useUserStore } from '@/stores/user'
import dayjs, { Dayjs } from 'dayjs';
//
//
const props = defineProps(
{
applyType: {
type: String,
default: ''
}
} // applyType使121: 2:
)
const getTableData = () => {
const $table = tableRef.value
return $table?.getTableData().fullData;
}
defineExpose({ getTableData})
const getApplyForm = () => {
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 {
applicant: string; //
@ -76,7 +93,7 @@ const userStore = useUserStore()
const formData = ref<FormData>({
applicant: userStore.userName,
applyDate: dayjs(),
applyType: '1', // 1: 2: 3:
applyType: props.applyType, // 1: 2: 3:
slectedList: []
});
@ -138,7 +155,7 @@ const insertEvent = (value: any) => {
}
// table
const removeEvent = (value: any) => {
const removeEvent = (value : any) => {
const $table = tableRef.value
// value
if ($table) {

View File

@ -1,20 +1,24 @@
<template>
<!-- steps -->
<div>
<div v-show="current != 3">
<a-steps v-model:current="current" :items="items"></a-steps>
<a-divider style="height: 2px; background-color: #7cb305" />
</div>
<a-divider style="height: 2px; background-color: #7cb305" />
<!-- step1 -->
<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 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 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>
@ -22,7 +26,7 @@
<a-space wrap class="fixed-button-container">
<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">提交申请</a-button>
<a-button type="primary" :loading="loading" v-if="current === 2" @click="submit">提交申请</a-button>
</a-space>
</template>
@ -30,26 +34,92 @@
import applyForm from '../component/applyForm.vue'
import scanForm from '../component/scanForm.vue';
import applyConfirm from '../component/applyConfirm.vue';
import successResul from '../component/successResul.vue';
import api from '@/api'
//
defineProps(
{
applyType: {
type: String,
default: '',
}
} // applyType使121: 2:
)
// steps
const current = ref<number>(0) //
const applyFormRef = ref(); // step1
const selectData = ref();
const totalValue = ref(199);
const scanFormRef = ref(); // step2
const applyConfirmRef = ref(); // step3
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 nextStep = () => {
if (applyFormRef.value) {
if (applyFormRef.value && current.value === 0) { // step1step1
selectData.value = applyFormRef.value.getTableData();
selectData.value.forEach((item) => {
if (item.assignRule === 1) {
totalValue.value += item.quantity
}
})
}
if (scanFormRef.value && current.value === 1) { // step2step2
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++
}
/**
* 提交申请
*/
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>
<style scoped>

View File

@ -5,10 +5,10 @@
style="margin-top: 20px; margin-bottom: 20px;" />
<a-row style="margin-bottom: 20px;">
<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 :span="12">
<a-statistic title="待扫码数量" :value="remainderValue" />
<a-statistic title="已扫码" :value="remainderValue" />
</a-col>
</a-row>
<!-- Esc键退出编辑功能 -->
@ -19,7 +19,7 @@
<vxe-column type="seq" title="序号" width="60"></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="role" title="物料名称" />
<vxe-column field="name" title="物料名称" />
<vxe-column field="code" title="编码" />
<vxe-column field="spec" title="规格" />
<vxe-column field="type" title="类型" />
@ -36,15 +36,34 @@
<script lang="ts" setup>
import { VxeTableInstance } from 'vxe-table'
import { useTemplateRef } from 'vue'
import api from '@/api/index';
import { api } from '@/api'
import { message } from 'ant-design-vue';
//
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('')
@ -54,13 +73,16 @@ const snListCache = ref<string[]>([]) // 缓存扫码的条形码列表
// map
const materialMapCache = ref<Map<string, material.Material>>(new Map<string, material.Material>()) // ,keycode
//
/**
* 请求接口获取缓存数据
*/
const getCache = () => {
api.materialApi.material.all((data) => {
data.forEach(item => {
if (item.code) {
materialMapCache.value.set(item.code, item)
materialMapCache.value.set(item.code, item) // 6
}
})
})
@ -68,6 +90,7 @@ const getCache = () => {
getCache();
interface TableRowVO {
id: number
barcode: string
name: string
code: string
@ -103,29 +126,42 @@ const autoInsertOneRow = async () => {
* 3. 根据sn获取物料信息并新增一行到表格中,需要缓存物料信息
* 4. 插入成功后缓存sn
*/
if (sn.length === 0 || snListCache.value.includes(sn)) {
if (sn.length === 0) {
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;
}
if ($table) {
const row: TableRowVO = {
id: materialInfo?.id ?? 0,
barcode: sn,
name: '',
code: '',
spec: '',
type: '',
name: materialInfo?.name ?? '',
code: materialInfo?.code ?? '',
spec: materialInfo?.spec ?? '',
type: materialInfo?.type ?? '',
times: new Date().toLocaleString()
}
$table.insertAt(row, null)
$table.insert(row)
// sn
snListCache.value.push(sn)
//
//+1
remainderValue.value = remainderValue.value - 1
remainderValue.value = remainderValue.value + 1
//
value.value = ''
}

View File

@ -1,5 +1,5 @@
<template>
<apply-modal></apply-modal>
<apply-modal apply-type='1'></apply-modal>
</template>
<script setup lang="ts">

View File

@ -1,8 +1,8 @@
<template>
<apply-page pageType='2'></apply-page>
<apply-modal apply-type='3'></apply-modal>
</template>
<script setup lang="ts">
import applyPage from '../component/apply-page.vue';
import applyModal from "@/views/stock/component/applyModal.vue";
</script>
</script>