no message

main
HUOJIN\92525 2025-12-21 18:41:10 +08:00
parent d308c16400
commit bf33b23154
13 changed files with 485 additions and 365 deletions

View File

@ -5,6 +5,7 @@ const { createConfirm } = useMessage();
enum Api { enum Api {
list = '/base/area/list', list = '/base/area/list',
queryById='/base/area/queryById',
save = '/base/area/add', save = '/base/area/add',
edit = '/base/area/edit', edit = '/base/area/edit',
deleteOne = '/base/area/delete', deleteOne = '/base/area/delete',
@ -30,6 +31,11 @@ export const getImportUrl = Api.importExcel;
*/ */
export const list = (params) => defHttp.get({ url: Api.list, params }); export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* id
* @param params
*/
export const queryById = (params) => defHttp.get({ url: Api.queryById, params });
/** /**
* *
* @param params * @param params

View File

@ -1,4 +1,4 @@
<!-- 库区下拉选择--> <!-- 库区选择 -->
<template> <template>
<a-select <a-select
v-model:value="selectedValue" v-model:value="selectedValue"
@ -12,15 +12,14 @@
@change="handleChange" @change="handleChange"
@search="handleSearch" @search="handleSearch"
@focus="handleFocus" @focus="handleFocus"
@popupScroll="handlePopupScroll" @popup-scroll="handlePopupScroll"
:getPopupContainer="getParentContainer" :getPopupContainer="getParentContainer"
v-bind="attrs" v-bind="attrs"
> >
<template #notFoundContent> <template #notFoundContent>
<a-spin v-if="loading" size="small" />
<span v-else></span>
</template> </template>
<a-select-option v-for="option in areaOptions" :key="option.id" :value="getOptionValue(option)"> <a-select-option v-for="option in Options" :key="option.id" :value="getOptionValue(option)">
{{ getOptionLabel(option) }} {{ getOptionLabel(option) }}
</a-select-option> </a-select-option>
</a-select> </a-select>
@ -31,6 +30,7 @@
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { queryById } from '@/views/base/area/Area.api';
import { setPopContainer } from '/@/utils'; import { setPopContainer } from '/@/utils';
import { debounce } from 'lodash-es'; import { debounce } from 'lodash-es';
@ -63,7 +63,7 @@
// //
async: propTypes.bool.def(true), async: propTypes.bool.def(true),
// //
pageSize: propTypes.number.def(20), pageSize: propTypes.number.def(10),
// //
popContainer: propTypes.string, popContainer: propTypes.string,
// //
@ -77,10 +77,12 @@
returnValue: propTypes.string.def('id'), returnValue: propTypes.string.def('id'),
// //
izActive: propTypes.number.def(1), izActive: propTypes.number.def(1),
//
delFlag:propTypes.number.def(0)
}, },
emits: ['change', 'update:value', 'optionsLoaded'], emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) { setup(props, { emit }) {
const areaOptions = ref<Area[]>([]); const Options = ref<Area[]>([]);
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
const allAreas = ref<Area[]>([]); const allAreas = ref<Area[]>([]);
const attrs = useAttrs({ excludeDefaultKeys: false }); const attrs = useAttrs({ excludeDefaultKeys: false });
@ -96,7 +98,7 @@
// //
const notFoundContent = computed(() => { const notFoundContent = computed(() => {
return loading.value ? undefined : null; return loading.value ? undefined : '暂无数据';
}); });
/** /**
@ -141,46 +143,56 @@
return true; // return true; //
} }
/**
* 确保库区唯一性的辅助函数
*/
function ensureUnique(Areas: Area[], newArea: Area): Area[] {
// id
const filtered = Areas.filter(Area => Area.id !== newArea.id);
return [newArea, ...filtered];
}
/** /**
* 获取库区数据 * 获取库区数据
*/ */
const fetchAreas = async (page = 1, keyword = '', isSearch = false) => { const queryData = async (page = 1, keyword = '', isSearch = false) => {
try { try {
loading.value = true; loading.value = true;
const res = await defHttp.get<ResponseData>({ const res = await defHttp.get<ResponseData>({
url: '/base/area/list', url: '/base/Area/list',
params: { params: {
pageSize: props.pageSize, pageSize: props.pageSize,
pageNo: page, pageNo: page,
keyword: keyword, keyword: keyword,
izActive: props.izActive, izActive: props.izActive,
delFlag: props.delFlag
}, },
}); });
console.log('获取库区数据成功:', res);
const records = res.records || []; const records = res.records || [];
if (page === 1 || isSearch) { if (page === 1 || isSearch) {
// //
allAreas.value = records; allAreas.value = records;
areaOptions.value = records; Options.value = records;
} else { } else {
// //
allAreas.value = [...allAreas.value, ...records]; const newRecords = records.filter(record =>
areaOptions.value = [...areaOptions.value, ...records]; !allAreas.value.some(Area => Area.id === record.id)
);
allAreas.value = [...allAreas.value, ...newRecords];
Options.value = [...Options.value, ...newRecords];
} }
// //
isHasData.value = records.length >= props.pageSize; isHasData.value = records.length >= props.pageSize;
console.log('是否还有更多数据:', records.length);
emit('optionsLoaded', allAreas.value); emit('optionsLoaded', allAreas.value);
} catch (error) { } catch (error) {
console.error('获取库区数据失败:', error);
if (page === 1) { if (page === 1) {
allAreas.value = []; allAreas.value = [];
areaOptions.value = []; Options.value = [];
} }
} finally { } finally {
loading.value = false; loading.value = false;
@ -188,14 +200,33 @@
} }
}; };
async function queryDataById(value: string) {
try {
const res = await queryById({ id: value });
if (res) {
//
const Area = Array.isArray(res) ? res[0] : res;
if (Area) {
// 使ensureUnique
allAreas.value = ensureUnique(allAreas.value, Area);
Options.value = ensureUnique(Options.value, Area);
}
return Area;
}
} catch (error) {
console.error('查询库区失败:', error);
}
return null;
}
/** /**
* 根据选项值找到对应的选项对象 * 根据选项值找到对应的选项对象
*/ */
function findOptionByValue(value: string): Area | undefined { function findOptionByValue(value: string): Area | undefined {
if (props.returnValue === 'object' || props.returnValue === 'id') { if (props.returnValue === 'object' || props.returnValue === 'id') {
return allAreas.value.find((item) => item.id === value); return allAreas.value.find((Area) => Area.id === value);
} else { } else {
return allAreas.value.find((item) => item[props.returnValue as keyof Area] === value); return allAreas.value.find((Area) => Area[props.returnValue as keyof Area] === value);
} }
} }
@ -242,7 +273,7 @@
isHasData.value = true; isHasData.value = true;
// API // API
fetchAreas(1, value, true); queryData(1, value, true);
}, 300); }, 300);
/** /**
@ -253,7 +284,7 @@
if (allAreas.value.length === 0 && props.async) { if (allAreas.value.length === 0 && props.async) {
pageNo.value = 1; pageNo.value = 1;
isHasData.value = true; isHasData.value = true;
fetchAreas(1, ''); queryData(1, '');
} }
attrs.onFocus?.(); attrs.onFocus?.();
} }
@ -266,7 +297,6 @@
// //
const returnValue = getReturnValue(value); const returnValue = getReturnValue(value);
console.log('值变化:', returnValue);
emit('update:value', returnValue); emit('update:value', returnValue);
emit('change', returnValue); emit('change', returnValue);
} }
@ -279,11 +309,10 @@
const { scrollTop, scrollHeight, clientHeight } = target; const { scrollTop, scrollHeight, clientHeight } = target;
if (!scrollLoading.value && isHasData.value && scrollTop + clientHeight >= scrollHeight - 10) { if (!scrollLoading.value && isHasData.value && scrollTop + clientHeight >= scrollHeight - 10) {
console.log('滚动加载更多');
scrollLoading.value = true; scrollLoading.value = true;
pageNo.value++; pageNo.value++;
fetchAreas(pageNo.value, searchKeyword.value) queryData(pageNo.value, searchKeyword.value)
.finally(() => { .finally(() => {
scrollLoading.value = false; scrollLoading.value = false;
}) })
@ -304,22 +333,50 @@
// //
if (props.async && allAreas.value.length === 0) { if (props.async && allAreas.value.length === 0) {
await fetchAreas(); await queryData();
} }
// returnValue // returnValue
let valueIds: string[] = [];
if (props.returnValue === 'object') { if (props.returnValue === 'object') {
// value // value
if (Array.isArray(props.value)) { if (Array.isArray(props.value)) {
selectedValue.value = props.value.map((item: any) => item.id); valueIds = props.value.map((Area: any) => Area.id);
selectedValue.value = valueIds;
} else { } else {
selectedValue.value = (props.value as any).id; valueIds = [(props.value as any).id];
selectedValue.value = valueIds[0];
} }
} else if (props.returnValue === 'id') { } else if (props.returnValue === 'id') {
selectedValue.value = props.value as string | string[]; if (Array.isArray(props.value)) {
valueIds = props.value as string[];
selectedValue.value = valueIds;
} else {
valueIds = [props.value as string];
selectedValue.value = valueIds[0];
}
} else { } else {
// 使 // 使
selectedValue.value = props.value as string | string[]; selectedValue.value = props.value as string | string[];
// ID
if (Array.isArray(props.value)) {
valueIds = props.value.map((v) => {
const option = allAreas.value.find((Area) => Area[props.returnValue as keyof Area] === v);
return option ? option.id : v;
});
} else {
const option = allAreas.value.find((Area) => Area[props.returnValue as keyof Area] === props.value);
valueIds = option ? [option.id] : [props.value as string];
}
}
//
const missingIds = valueIds.filter((id) => !allAreas.value.some((Area) => Area.id === id));
if (missingIds.length > 0) {
// ID
const queryPromises = missingIds.map((id) => queryDataById(id));
await Promise.all(queryPromises);
} }
}; };
@ -335,13 +392,13 @@
// //
onMounted(() => { onMounted(() => {
if (!props.async) { if (!props.async) {
fetchAreas(); queryData();
} }
}); });
return { return {
attrs, attrs,
areaOptions, Options,
loading, loading,
selectedValue, selectedValue,
notFoundContent, notFoundContent,

View File

@ -17,8 +17,7 @@
v-bind="attrs" v-bind="attrs"
> >
<template #notFoundContent> <template #notFoundContent>
<a-spin v-if="loading" size="small" />
<span v-else></span>
</template> </template>
<a-select-option v-for="option in Options" :key="option.id" :value="getOptionValue(option)"> <a-select-option v-for="option in Options" :key="option.id" :value="getOptionValue(option)">
{{ getOptionLabel(option) }} {{ getOptionLabel(option) }}
@ -78,6 +77,8 @@
returnValue: propTypes.string.def('id'), returnValue: propTypes.string.def('id'),
// //
izActive: propTypes.number.def(1), izActive: propTypes.number.def(1),
//
delFlag: propTypes.number.def(0),
}, },
emits: ['change', 'update:value', 'optionsLoaded'], emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) { setup(props, { emit }) {
@ -97,7 +98,7 @@
// //
const notFoundContent = computed(() => { const notFoundContent = computed(() => {
return loading.value ? undefined : null; return loading.value ? undefined : '暂无数据';
}); });
/** /**
@ -165,6 +166,7 @@
pageNo: page, pageNo: page,
keyword: keyword, keyword: keyword,
izActive: props.izActive, izActive: props.izActive,
delFlag: props.delFlag,
}, },
}); });

View File

@ -16,10 +16,7 @@
:getPopupContainer="getParentContainer" :getPopupContainer="getParentContainer"
v-bind="attrs" v-bind="attrs"
> >
<template #notFoundContent> <template #notFoundContent></template>
<a-spin v-if="loading" size="small" />
<span v-else></span>
</template>
<a-select-option v-for="option in Options" :key="option.id" :value="getOptionValue(option)"> <a-select-option v-for="option in Options" :key="option.id" :value="getOptionValue(option)">
{{ getOptionLabel(option) }} {{ getOptionLabel(option) }}
</a-select-option> </a-select-option>
@ -76,8 +73,14 @@
immediateChange: propTypes.bool.def(false), immediateChange: propTypes.bool.def(false),
// : 'id'() | 'object' | // : 'id'() | 'object' |
returnValue: propTypes.string.def('id'), returnValue: propTypes.string.def('id'),
//
status: propTypes.number.def(0),
// //
izActive: propTypes.number.def(1), izActive: propTypes.number.def(1),
//
delFlag: propTypes.number.def(0),
//ID
areaCode: propTypes.array,
}, },
emits: ['change', 'update:value', 'optionsLoaded'], emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) { setup(props, { emit }) {
@ -97,7 +100,7 @@
// //
const notFoundContent = computed(() => { const notFoundContent = computed(() => {
return loading.value ? undefined : null; return loading.value ? undefined : '暂无数据';
}); });
/** /**
@ -147,7 +150,7 @@
*/ */
function ensureUnique(Points: Point[], newPoint: Point): Point[] { function ensureUnique(Points: Point[], newPoint: Point): Point[] {
// id // id
const filtered = Points.filter(Point => Point.id !== newPoint.id); const filtered = Points.filter((Point) => Point.id !== newPoint.id);
return [newPoint, ...filtered]; return [newPoint, ...filtered];
} }
@ -164,7 +167,10 @@
pageSize: props.pageSize, pageSize: props.pageSize,
pageNo: page, pageNo: page,
keyword: keyword, keyword: keyword,
status: props.status,
izActive: props.izActive, izActive: props.izActive,
delFlag: props.delFlag,
areaCode: props.areaCode,
}, },
}); });
@ -176,9 +182,7 @@
Options.value = records; Options.value = records;
} else { } else {
// //
const newRecords = records.filter(record => const newRecords = records.filter((record) => !allPoints.value.some((Point) => Point.id === record.id));
!allPoints.value.some(Point => Point.id === record.id)
);
allPoints.value = [...allPoints.value, ...newRecords]; allPoints.value = [...allPoints.value, ...newRecords];
Options.value = [...Options.value, ...newRecords]; Options.value = [...Options.value, ...newRecords];
} }

View File

@ -21,11 +21,6 @@ export const columns: BasicColumn[] = [
return render.renderTag(text, color); return render.renderTag(text, color);
}, },
}, },
{
title: '库位',
align: "center",
dataIndex: 'pointId_dictText'
},
{ {
title: '是否启用', title: '是否启用',
align: 'center', align: 'center',

View File

@ -10,12 +10,6 @@
<JInput v-model:value="queryParam.stockCode" :placeholder="'请输入容器编码'" :type="JInputTypeEnum.JINPUT_RIGHT_LIKE" /> <JInput v-model:value="queryParam.stockCode" :placeholder="'请输入容器编码'" :type="JInputTypeEnum.JINPUT_RIGHT_LIKE" />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :lg="6">
<a-form-item name="pointId">
<template #label><span title="库位">库位</span></template>
<PointSelect v-model:value="queryParam.pointId" placeholder="请选择库位" />
</a-form-item>
</a-col>
<a-col :lg="6"> <a-col :lg="6">
<a-form-item name="status"> <a-form-item name="status">
<template #label><span title="状态">状态</span></template> <template #label><span title="状态">状态</span></template>
@ -88,21 +82,16 @@
import { list, deleteOne, batchDelete, saveOrUpdate, getImportUrl, getExportUrl } from './Stock.api'; import { list, deleteOne, batchDelete, saveOrUpdate, getImportUrl, getExportUrl } from './Stock.api';
import StockModal from './components/StockModal.vue'; import StockModal from './components/StockModal.vue';
import SwitchStatus from '/@/views/base/SwitchStatus.vue'; import SwitchStatus from '/@/views/base/SwitchStatus.vue';
import { useUserStore } from '/@/store/modules/user';
import { useMessage } from '/@/hooks/web/useMessage';
import { getDateByPicker } from '/@/utils'; import { getDateByPicker } from '/@/utils';
import { JDictSelectTag, JSearchSelect } from '@/components/Form'; import { JDictSelectTag, JSearchSelect } from '@/components/Form';
import { JInputTypeEnum } from '@/enums/cpteEnum'; import { JInputTypeEnum } from '@/enums/cpteEnum';
import JInput from '../../../components/Form/src/jeecg/components/JInput.vue'; import JInput from '../../../components/Form/src/jeecg/components/JInput.vue';
import PointSelect from '@/views/base/point/components/PointSelect.vue';
const fieldPickers = reactive({}); const fieldPickers = reactive({});
const formRef = ref(); const formRef = ref();
const queryParam = reactive<any>({}); const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false); const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref(); const registerModal = ref();
const userStore = useUserStore();
const { createMessage } = useMessage();
// //
const enhancedColumns = columns.map((col) => { const enhancedColumns = columns.map((col) => {
@ -130,7 +119,7 @@
}); });
//table //table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({ const { tableContext, onExportXls, onImportXls } = useListPage({
tableProps: { tableProps: {
title: '容器', title: '容器',
api: list, api: list,
@ -164,7 +153,7 @@
success: handleSuccess, success: handleSuccess,
}, },
}); });
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = const [registerTable, { reload }, { rowSelection, selectedRowKeys }] =
tableContext; tableContext;
const labelCol = reactive({ const labelCol = reactive({
xs: 24, xs: 24,

View File

@ -25,11 +25,6 @@
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24">
<a-form-item label="库位" v-bind="validateInfos.pointId" id="StockForm-pointId" name="pointId">
<PointSelect v-model:value="formData.pointId" />
</a-form-item>
</a-col>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="描述" v-bind="validateInfos.description" id="StockForm-description" name="description"> <a-form-item label="描述" v-bind="validateInfos.description" id="StockForm-description" name="description">
<a-textarea v-model:value="formData.description" :rows="4" placeholder="请输入描述" /> <a-textarea v-model:value="formData.description" :rows="4" placeholder="请输入描述" />
@ -57,7 +52,6 @@
import JSwitch from '@/components/Form/src/jeecg/components/JSwitch.vue'; import JSwitch from '@/components/Form/src/jeecg/components/JSwitch.vue';
import { JDictSelectTag } from '@/components/Form'; import { JDictSelectTag } from '@/components/Form';
import { getTenantId } from '@/utils/auth'; import { getTenantId } from '@/utils/auth';
import PointSelect from '@/views/base/point/components/PointSelect.vue';
const props = defineProps({ const props = defineProps({
formDisabled: { type: Boolean, default: false }, formDisabled: { type: Boolean, default: false },
@ -71,7 +65,6 @@
let tenantId = getTenantId(); let tenantId = getTenantId();
const formData = reactive<Record<string, any>>({ const formData = reactive<Record<string, any>>({
id: '', id: '',
pointId: '',
stockCode: '', stockCode: '',
stockType: 'TRAY', stockType: 'TRAY',
status: 0, status: 0,

View File

@ -17,8 +17,7 @@
v-bind="attrs" v-bind="attrs"
> >
<template #notFoundContent> <template #notFoundContent>
<a-spin v-if="loading" size="small" />
<span v-else></span>
</template> </template>
<a-select-option v-for="option in Options" :key="option.id" :value="getOptionValue(option)"> <a-select-option v-for="option in Options" :key="option.id" :value="getOptionValue(option)">
{{ getOptionLabel(option) }} {{ getOptionLabel(option) }}
@ -75,8 +74,14 @@
immediateChange: propTypes.bool.def(false), immediateChange: propTypes.bool.def(false),
// : 'id'() | 'object' | // : 'id'() | 'object' |
returnValue: propTypes.string.def('id'), returnValue: propTypes.string.def('id'),
//
status: propTypes.number.def(0),
// //
izActive: propTypes.number.def(1), izActive: propTypes.number.def(1),
//
delFlag: propTypes.number.def(0),
//
izScan: propTypes.bool.def(false),
}, },
emits: ['change', 'update:value', 'optionsLoaded'], emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) { setup(props, { emit }) {
@ -96,7 +101,7 @@
// //
const notFoundContent = computed(() => { const notFoundContent = computed(() => {
return loading.value ? undefined : null; return loading.value ? undefined : '暂无数据';
}); });
/** /**
@ -146,7 +151,7 @@
*/ */
function ensureUnique(Stocks: Stock[], newStock: Stock): Stock[] { function ensureUnique(Stocks: Stock[], newStock: Stock): Stock[] {
// id // id
const filtered = Stocks.filter(Stock => Stock.id !== newStock.id); const filtered = Stocks.filter((Stock) => Stock.id !== newStock.id);
return [newStock, ...filtered]; return [newStock, ...filtered];
} }
@ -163,11 +168,15 @@
pageSize: props.pageSize, pageSize: props.pageSize,
pageNo: page, pageNo: page,
keyword: keyword, keyword: keyword,
status: props.status,
izActive: props.izActive, izActive: props.izActive,
delFlag: props.delFlag,
izScan: props.izScan,
}, },
}); });
const records = res.records || []; const records = res.records || [];
console.log('res', records)
if (page === 1 || isSearch) { if (page === 1 || isSearch) {
// //
@ -175,9 +184,7 @@
Options.value = records; Options.value = records;
} else { } else {
// //
const newRecords = records.filter(record => const newRecords = records.filter((record) => !allStocks.value.some((Stock) => Stock.id === record.id));
!allStocks.value.some(Stock => Stock.id === record.id)
);
allStocks.value = [...allStocks.value, ...newRecords]; allStocks.value = [...allStocks.value, ...newRecords];
Options.value = [...Options.value, ...newRecords]; Options.value = [...Options.value, ...newRecords];
} }
@ -296,6 +303,7 @@
const returnValue = getReturnValue(value); const returnValue = getReturnValue(value);
emit('update:value', returnValue); emit('update:value', returnValue);
emit('change', returnValue); emit('change', returnValue);
console.log('值变化:', returnValue);
} }
/** /**

View File

@ -13,7 +13,7 @@
<a-col :lg="6"> <a-col :lg="6">
<a-form-item name="pointId"> <a-form-item name="pointId">
<template #label><span title="库位">库位</span></template> <template #label><span title="库位">库位</span></template>
<PointSelect v-model:value="queryParam.pointId" /> <PointSelect v-model:value="queryParam.pointId" :area-code="['CPCCQ', 'MJCCQ']" />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :lg="6"> <a-col :lg="6">

View File

@ -7,6 +7,12 @@ export const columns: BasicColumn[] = [
dataIndex: 'logType_dictText', dataIndex: 'logType_dictText',
width: 100, width: 100,
}, },
{
title: '业务单号',
align: 'center',
dataIndex: 'businessNo',
width: 130,
},
{ {
title: '物料', title: '物料',
align: 'center', align: 'center',
@ -17,19 +23,19 @@ export const columns: BasicColumn[] = [
title: '原库位', title: '原库位',
align: 'center', align: 'center',
dataIndex: 'fromPointId_dictText', dataIndex: 'fromPointId_dictText',
width: 120, width: 100,
}, },
{ {
title: '目标库位', title: '目标库位',
align: 'center', align: 'center',
dataIndex: 'toPointId_dictText', dataIndex: 'toPointId_dictText',
width: 120, width: 100,
}, },
{ {
title: '容器', title: '容器',
align: 'center', align: 'center',
dataIndex: 'stockId_dictText', dataIndex: 'stockId_dictText',
width: 120, width: 100,
}, },
{ {
title: '变动前数量', title: '变动前数量',
@ -50,15 +56,36 @@ export const columns: BasicColumn[] = [
width: 100, width: 100,
}, },
{ {
title: '变动前分配数量', title: '分配数量',
align: 'center', align: 'center',
dataIndex: 'beforeAllocatedQty', dataIndex: 'beforeAllocatedQty',
width: 120, width: 100,
}, },
{ {
title: '变动后分配数量', title: '分配数量',
align: 'center',
dataIndex: 'allocatedQty',
width: 100,
customRender: ({ record }) => {
// 从记录中获取分配前和分配后的数量
const before = record.beforeAllocatedQty || 0;
const after = record.afterAllocatedQty || 0;
if(record.logType_dictText==='分配'){
if(before>0){
return after - before;
}
return before + after;
}else if(record.logType_dictText==='取消分配'){
return before - after;
}else {
return 0;
}
}
},
{
title: '分配后数量',
align: 'center', align: 'center',
dataIndex: 'afterAllocatedQty', dataIndex: 'afterAllocatedQty',
width: 120, width: 100,
} }
]; ];

View File

@ -6,12 +6,7 @@
<a-row> <a-row>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="托盘" v-bind="validateInfos.stockCode" id="ScanTrayForm-stockCode" name="stockCode"> <a-form-item label="托盘" v-bind="validateInfos.stockCode" id="ScanTrayForm-stockCode" name="stockCode">
<JSearchSelect <StockSelect v-model:value="formData.stockCode" :return-value="'stockCode'" :status="1" :iz-scan="true" />
v-model:value="formData.stockCode"
placeholder="请选择托盘"
dict="base_stock where status=1 and iz_active=1 and del_flag=0,stock_code,stock_code"
allowClear
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24"> <a-col :span="24">
@ -38,6 +33,7 @@
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue'; import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import { JSearchSelect } from '@/components/Form'; import { JSearchSelect } from '@/components/Form';
import { scanTray } from '@/views/conveyorLine/ConveyorLine.api'; import { scanTray } from '@/views/conveyorLine/ConveyorLine.api';
import StockSelect from '@/views/base/stock/components/StockSelect.vue';
const props = defineProps({ const props = defineProps({
formDisabled: { type: Boolean, default: false }, formDisabled: { type: Boolean, default: false },

View File

@ -16,6 +16,7 @@ enum Api {
queryTaskByMainId = '/shipping/pick/queryTaskByMainId', queryTaskByMainId = '/shipping/pick/queryTaskByMainId',
allocatePick = '/shipping/pick/allocatePick', allocatePick = '/shipping/pick/allocatePick',
cancelAllocate = '/shipping/pick/cancelAllocate', cancelAllocate = '/shipping/pick/cancelAllocate',
pickTask = '/shipping/pick/pickTask',
} }
/** /**
@ -123,3 +124,13 @@ export const cancelAllocate = (ids,handleSuccess) => {
handleSuccess(); handleSuccess();
}); });
}; };
/**
*
* @param params
*/
export const pickTask = (ids,handleSuccess) => {
return defHttp.get({ url: Api.pickTask, params: { ids } }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};

View File

@ -37,9 +37,9 @@
</a-row> </a-row>
<a-row :gutter="24"> <a-row :gutter="24">
<a-col :lg="6"> <a-col :lg="6">
<a-form-item name="status"> <a-form-item name="status_MultiString">
<template #label><span title="状态">状态</span></template> <template #label><span title="状态">状态</span></template>
<JDictSelectTag v-model:value="queryParam.status" placeholder="请选择" dictCode="pick_status" mode="multiple" allowClear /> <JSelectMultiple v-model:value="queryParam.status_MultiString" dictCode="pick_status" />
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> </a-row>
@ -53,22 +53,34 @@
<a-button <a-button
type="primary" type="primary"
:loading="allocate_loading" :loading="allocate_loading"
:disabled="selectedRowKeys.length === 0"
v-auth="'shipping:data_pick:allocatePick'" v-auth="'shipping:data_pick:allocatePick'"
@click="handleAllocatePick" @click="handleAllocatePick"
preIcon="ant-design:edit-outlined" preIcon="ant-design:edit-outlined"
> >
分配 批量分配
</a-button> </a-button>
<a-button <a-button
type="primary" type="primary"
danger danger
:loading="cancel_loading" :loading="cancel_loading"
:disabled="selectedRowKeys.length === 0"
v-auth="'shipping:data_pick:cancelAllocate'" v-auth="'shipping:data_pick:cancelAllocate'"
@click="handleCancelAllocate" @click="handleCancelAllocate"
preIcon="ant-design:edit-outlined" preIcon="ant-design:edit-outlined"
> >
取消分配 取消分配
</a-button> </a-button>
<a-button
type="primary"
:loading="pick_loading"
:disabled="selectedRowKeys.length === 0"
v-auth="'shipping:data_pick:pickTask'"
@click="handlePick"
preIcon="ant-design:edit-outlined"
>
批量拣货
</a-button>
<a-button type="primary" v-auth="'shipping:data_pick:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> </a-button> <a-button type="primary" v-auth="'shipping:data_pick:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> </a-button>
<j-upload-button type="primary" v-auth="'shipping:data_pick:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls" <j-upload-button type="primary" v-auth="'shipping:data_pick:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls"
>导入 >导入
@ -107,15 +119,17 @@
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import PickModal from './components/PickModal.vue'; import PickModal from './components/PickModal.vue';
import { columns } from './Pick.data'; import { columns } from './Pick.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, allocatePick, cancelAllocate } from './Pick.api'; import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, allocatePick, cancelAllocate, pickTask } from './Pick.api';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { getDateByPicker } from '/@/utils'; import { getDateByPicker } from '/@/utils';
import { JInputTypeEnum } from '@/enums/cpteEnum'; import { JInputTypeEnum } from '@/enums/cpteEnum';
import { JInput, JDictSelectTag } from '@/components/Form'; import { JInput, JDictSelectTag } from '@/components/Form';
import JRangeDate from '@/components/Form/src/jeecg/components/JRangeDate.vue'; import JRangeDate from '@/components/Form/src/jeecg/components/JRangeDate.vue';
import JSelectMultiple from '/@/components/Form/src/jeecg/components/JSelectMultiple.vue';
const allocate_loading = ref(false); const allocate_loading = ref(false);
const cancel_loading = ref(false); const cancel_loading = ref(false);
const pick_loading = ref(false);
const fieldPickers = reactive({}); const fieldPickers = reactive({});
const formRef = ref(); const formRef = ref();
const queryParam = reactive<any>({}); const queryParam = reactive<any>({});
@ -184,10 +198,6 @@
* 分配事件 * 分配事件
*/ */
async function handleAllocatePick() { async function handleAllocatePick() {
if (selectedRowKeys.value.length === 0) {
return createMessage.error('请选择出库单');
}
// 124 true,false // 124 true,false
const validStatuses = [1, 2, 4]; const validStatuses = [1, 2, 4];
const allValidStatus = selectedRows.value.every((row: any) => validStatuses.includes(row.status)); const allValidStatus = selectedRows.value.every((row: any) => validStatuses.includes(row.status));
@ -214,10 +224,6 @@
* 取消分配 * 取消分配
*/ */
async function handleCancelAllocate() { async function handleCancelAllocate() {
if (selectedRowKeys.value.length === 0) {
return createMessage.error('请选择出库单');
}
// 23 true,false // 23 true,false
const validStatuses = [2, 3]; const validStatuses = [2, 3];
const allValidStatus = selectedRows.value.every((row: any) => validStatuses.includes(row.status)); const allValidStatus = selectedRows.value.every((row: any) => validStatuses.includes(row.status));
@ -240,6 +246,32 @@
} }
} }
/**
* 拣货事件
*/
async function handlePick() {
// 124 true,false
const validStatuses = [2, 3, 4];
const allValidStatus = selectedRows.value.every((row: any) => validStatuses.includes(row.status));
if (!allValidStatus) {
return createMessage.error('【部分分配、已分配、部分拣货】状态的出库单才允许拣货');
}
if (pick_loading.value) {
return;
}
//
pick_loading.value = true;
try {
await pickTask(selectedRowKeys.value, handleSuccess);
} catch (e) {
console.error('拣货失败:', e);
handleSuccess();
} finally {
//
pick_loading.value = false;
}
}
/** /**
* 编辑事件 * 编辑事件
*/ */