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 {
list = '/base/area/list',
queryById='/base/area/queryById',
save = '/base/area/add',
edit = '/base/area/edit',
deleteOne = '/base/area/delete',
@ -30,6 +31,11 @@ export const getImportUrl = Api.importExcel;
*/
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

View File

@ -1,4 +1,4 @@
<!-- 库区下拉选择-->
<!-- 库区选择 -->
<template>
<a-select
v-model:value="selectedValue"
@ -12,350 +12,407 @@
@change="handleChange"
@search="handleSearch"
@focus="handleFocus"
@popupScroll="handlePopupScroll"
@popup-scroll="handlePopupScroll"
:getPopupContainer="getParentContainer"
v-bind="attrs"
>
<template #notFoundContent>
<a-spin v-if="loading" size="small" />
<span v-else></span>
</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) }}
</a-select-option>
</a-select>
</template>
<script lang="ts">
import { defineComponent, ref, watch, computed, onMounted } from 'vue';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { propTypes } from '/@/utils/propTypes';
import { defHttp } from '/@/utils/http/axios';
import { setPopContainer } from '/@/utils';
import { debounce } from 'lodash-es';
import { defineComponent, ref, watch, computed, onMounted } from 'vue';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { propTypes } from '/@/utils/propTypes';
import { defHttp } from '/@/utils/http/axios';
import { queryById } from '@/views/base/area/Area.api';
import { setPopContainer } from '/@/utils';
import { debounce } from 'lodash-es';
//
interface Area {
id: string;
areaCode: string;
areaName: string;
}
//
interface Area {
id: string;
areaCode: string;
areaName: string;
}
//
interface ResponseData {
records: Area[];
total: number;
size: number;
current: number;
page: number;
}
//
interface ResponseData {
records: Area[];
total: number;
size: number;
current: number;
page: number;
}
export default defineComponent({
name: 'AreaSelect',
inheritAttrs: false,
props: {
// v-model
value: propTypes.oneOfType([propTypes.string, propTypes.array, propTypes.object]),
//
placeholder: propTypes.string.def('请选择库区'),
//
multiple: propTypes.bool.def(false),
//
async: propTypes.bool.def(true),
//
pageSize: propTypes.number.def(20),
//
popContainer: propTypes.string,
//
getPopupContainer: {
type: Function,
default: (node: HTMLElement) => node?.parentNode,
},
// change
immediateChange: propTypes.bool.def(false),
// : 'id'() | 'object' |
returnValue: propTypes.string.def('id'),
//
izActive: propTypes.number.def(1),
export default defineComponent({
name: 'AreaSelect',
inheritAttrs: false,
props: {
// v-model
value: propTypes.oneOfType([propTypes.string, propTypes.array, propTypes.object]),
//
placeholder: propTypes.string.def('请选择库区'),
//
multiple: propTypes.bool.def(false),
//
async: propTypes.bool.def(true),
//
pageSize: propTypes.number.def(10),
//
popContainer: propTypes.string,
//
getPopupContainer: {
type: Function,
default: (node: HTMLElement) => node?.parentNode,
},
emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) {
const areaOptions = ref<Area[]>([]);
const loading = ref<boolean>(false);
const allAreas = ref<Area[]>([]);
const attrs = useAttrs({ excludeDefaultKeys: false });
// change
immediateChange: propTypes.bool.def(false),
// : 'id'() | 'object' |
returnValue: propTypes.string.def('id'),
//
izActive: propTypes.number.def(1),
//
delFlag:propTypes.number.def(0)
},
emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) {
const Options = ref<Area[]>([]);
const loading = ref<boolean>(false);
const allAreas = ref<Area[]>([]);
const attrs = useAttrs({ excludeDefaultKeys: false });
//
const pageNo = ref(1);
const isHasData = ref(true);
const scrollLoading = ref(false);
const searchKeyword = ref('');
//
const pageNo = ref(1);
const isHasData = ref(true);
const scrollLoading = ref(false);
const searchKeyword = ref('');
//
const selectedValue = ref<string | string[] | undefined>(undefined);
//
const selectedValue = ref<string | string[] | undefined>(undefined);
//
const notFoundContent = computed(() => {
return loading.value ? undefined : null;
});
//
const notFoundContent = computed(() => {
return loading.value ? undefined : '暂无数据';
});
/**
* 获取选项显示文本 - 始终显示完整格式
*/
function getOptionLabel(option: Area) {
return `${option.areaCode} - ${option.areaName}`;
/**
* 获取选项显示文本 - 始终显示完整格式
*/
function getOptionLabel(option: Area) {
return `${option.areaCode} - ${option.areaName}`;
}
/**
* 获取选项值 - 根据returnValue确定实际存储的值
*/
function getOptionValue(option: Area) {
if (props.returnValue === 'object') {
return option.id; // object使idchange
} else if (props.returnValue === 'id') {
return option.id;
} else {
return option[props.returnValue as keyof Area] as string;
}
}
/**
* 获取选项值 - 根据returnValue确定实际存储的值
*/
function getOptionValue(option: Area) {
if (props.returnValue === 'object') {
return option.id; // object使idchange
} else if (props.returnValue === 'id') {
return option.id;
/**
* 获取弹出层容器
*/
function getParentContainer(node: HTMLElement) {
if (props.popContainer) {
return setPopContainer(node, props.popContainer);
} else {
if (typeof props.getPopupContainer === 'function') {
return props.getPopupContainer(node);
} else {
return option[props.returnValue as keyof Area] as string;
return node?.parentNode;
}
}
}
/**
* 获取弹出层容器
*/
function getParentContainer(node: HTMLElement) {
if (props.popContainer) {
return setPopContainer(node, props.popContainer);
/**
* 过滤选项 - 禁用前端过滤使用后端搜索
*/
function filterOption(_input: string, _option: any) {
return true; //
}
/**
* 确保库区唯一性的辅助函数
*/
function ensureUnique(Areas: Area[], newArea: Area): Area[] {
// id
const filtered = Areas.filter(Area => Area.id !== newArea.id);
return [newArea, ...filtered];
}
/**
* 获取库区数据
*/
const queryData = async (page = 1, keyword = '', isSearch = false) => {
try {
loading.value = true;
const res = await defHttp.get<ResponseData>({
url: '/base/Area/list',
params: {
pageSize: props.pageSize,
pageNo: page,
keyword: keyword,
izActive: props.izActive,
delFlag: props.delFlag
},
});
const records = res.records || [];
if (page === 1 || isSearch) {
//
allAreas.value = records;
Options.value = records;
} else {
if (typeof props.getPopupContainer === 'function') {
return props.getPopupContainer(node);
} else {
return node?.parentNode;
//
const newRecords = records.filter(record =>
!allAreas.value.some(Area => Area.id === record.id)
);
allAreas.value = [...allAreas.value, ...newRecords];
Options.value = [...Options.value, ...newRecords];
}
//
isHasData.value = records.length >= props.pageSize;
emit('optionsLoaded', allAreas.value);
} catch (error) {
if (page === 1) {
allAreas.value = [];
Options.value = [];
}
} finally {
loading.value = false;
scrollLoading.value = false;
}
};
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 {
if (props.returnValue === 'object' || props.returnValue === 'id') {
return allAreas.value.find((Area) => Area.id === value);
} else {
return allAreas.value.find((Area) => Area[props.returnValue as keyof Area] === value);
}
}
/**
* 获取需要返回的值
*/
function getReturnValue(value: string | string[]) {
if (!value) {
return props.multiple ? [] : undefined;
}
//
if (props.returnValue === 'object') {
if (Array.isArray(value)) {
return value.map((v) => findOptionByValue(v)).filter(Boolean);
} else {
return findOptionByValue(value);
}
}
/**
* 过滤选项 - 禁用前端过滤使用后端搜索
*/
function filterOption(_input: string, _option: any) {
return true; //
// ID
else if (props.returnValue === 'id') {
return value;
}
/**
* 获取库区数据
*/
const fetchAreas = async (page = 1, keyword = '', isSearch = false) => {
try {
loading.value = true;
const res = await defHttp.get<ResponseData>({
url: '/base/area/list',
params: {
pageSize: props.pageSize,
pageNo: page,
keyword: keyword,
izActive: props.izActive,
},
//
else {
if (Array.isArray(value)) {
return value.map((v) => {
const option = findOptionByValue(v);
return option ? option[props.returnValue as keyof Area] : v;
});
console.log('获取库区数据成功:', res);
const records = res.records || [];
if (page === 1 || isSearch) {
//
allAreas.value = records;
areaOptions.value = records;
} else {
//
allAreas.value = [...allAreas.value, ...records];
areaOptions.value = [...areaOptions.value, ...records];
}
//
isHasData.value = records.length >= props.pageSize;
console.log('是否还有更多数据:', records.length);
emit('optionsLoaded', allAreas.value);
} catch (error) {
console.error('获取库区数据失败:', error);
if (page === 1) {
allAreas.value = [];
areaOptions.value = [];
}
} finally {
loading.value = false;
scrollLoading.value = false;
}
};
/**
* 根据选项值找到对应的选项对象
*/
function findOptionByValue(value: string): Area | undefined {
if (props.returnValue === 'object' || props.returnValue === 'id') {
return allAreas.value.find((item) => item.id === value);
} else {
return allAreas.value.find((item) => item[props.returnValue as keyof Area] === value);
const option = findOptionByValue(value);
return option ? option[props.returnValue as keyof Area] : value;
}
}
}
/**
* 获取需要返回的值
*/
function getReturnValue(value: string | string[]) {
if (!value) {
return props.multiple ? [] : undefined;
}
/**
* 搜索处理防抖
*/
const handleSearch = debounce(function (value: string) {
searchKeyword.value = value;
pageNo.value = 1;
isHasData.value = true;
//
if (props.returnValue === 'object') {
if (Array.isArray(value)) {
return value.map((v) => findOptionByValue(v)).filter(Boolean);
} else {
return findOptionByValue(value);
}
}
// ID
else if (props.returnValue === 'id') {
return value;
}
//
else {
if (Array.isArray(value)) {
return value.map((v) => {
const option = findOptionByValue(v);
return option ? option[props.returnValue as keyof Area] : v;
});
} else {
const option = findOptionByValue(value);
return option ? option[props.returnValue as keyof Area] : value;
}
}
}
// API
queryData(1, value, true);
}, 300);
/**
* 搜索处理防抖
*/
const handleSearch = debounce(function (value: string) {
searchKeyword.value = value;
/**
* 处理焦点事件
*/
function handleFocus() {
//
if (allAreas.value.length === 0 && props.async) {
pageNo.value = 1;
isHasData.value = true;
queryData(1, '');
}
attrs.onFocus?.();
}
// API
fetchAreas(1, value, true);
}, 300);
/**
* 处理值变化
*/
function handleChange(value: string | string[]) {
selectedValue.value = value;
/**
* 处理焦点事件
*/
function handleFocus() {
//
if (allAreas.value.length === 0 && props.async) {
pageNo.value = 1;
isHasData.value = true;
fetchAreas(1, '');
}
attrs.onFocus?.();
//
const returnValue = getReturnValue(value);
emit('update:value', returnValue);
emit('change', returnValue);
}
/**
* 滚动加载处理
*/
function handlePopupScroll(e: Event) {
const target = e.target as HTMLElement;
const { scrollTop, scrollHeight, clientHeight } = target;
if (!scrollLoading.value && isHasData.value && scrollTop + clientHeight >= scrollHeight - 10) {
scrollLoading.value = true;
pageNo.value++;
queryData(pageNo.value, searchKeyword.value)
.finally(() => {
scrollLoading.value = false;
})
.catch(() => {
pageNo.value--;
});
}
}
/**
* 根据选中值初始化显示文本
*/
const initSelectValue = async () => {
if (!props.value) {
selectedValue.value = props.multiple ? [] : undefined;
return;
}
/**
* 处理值变化
*/
function handleChange(value: string | string[]) {
selectedValue.value = value;
//
const returnValue = getReturnValue(value);
console.log('值变化:', returnValue);
emit('update:value', returnValue);
emit('change', returnValue);
//
if (props.async && allAreas.value.length === 0) {
await queryData();
}
/**
* 滚动加载处理
*/
function handlePopupScroll(e: Event) {
const target = e.target as HTMLElement;
const { scrollTop, scrollHeight, clientHeight } = target;
// returnValue
let valueIds: string[] = [];
if (!scrollLoading.value && isHasData.value && scrollTop + clientHeight >= scrollHeight - 10) {
console.log('滚动加载更多');
scrollLoading.value = true;
pageNo.value++;
fetchAreas(pageNo.value, searchKeyword.value)
.finally(() => {
scrollLoading.value = false;
})
.catch(() => {
pageNo.value--;
});
}
}
/**
* 根据选中值初始化显示文本
*/
const initSelectValue = async () => {
if (!props.value) {
selectedValue.value = props.multiple ? [] : undefined;
return;
}
//
if (props.async && allAreas.value.length === 0) {
await fetchAreas();
}
// returnValue
if (props.returnValue === 'object') {
// value
if (Array.isArray(props.value)) {
selectedValue.value = props.value.map((item: any) => item.id);
} else {
selectedValue.value = (props.value as any).id;
}
} else if (props.returnValue === 'id') {
selectedValue.value = props.value as string | string[];
if (props.returnValue === 'object') {
// value
if (Array.isArray(props.value)) {
valueIds = props.value.map((Area: any) => Area.id);
selectedValue.value = valueIds;
} else {
// 使
selectedValue.value = props.value as string | string[];
valueIds = [(props.value as any).id];
selectedValue.value = valueIds[0];
}
};
// value
watch(
() => props.value,
() => {
initSelectValue();
},
{ immediate: true }
);
//
onMounted(() => {
if (!props.async) {
fetchAreas();
} else if (props.returnValue === 'id') {
if (Array.isArray(props.value)) {
valueIds = props.value as string[];
selectedValue.value = valueIds;
} else {
valueIds = [props.value as string];
selectedValue.value = valueIds[0];
}
});
} else {
// 使
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];
}
}
return {
attrs,
areaOptions,
loading,
selectedValue,
notFoundContent,
getParentContainer,
filterOption,
handleChange,
handleSearch,
handleFocus,
getOptionLabel,
getOptionValue,
handlePopupScroll,
};
},
});
//
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);
}
};
// value
watch(
() => props.value,
() => {
initSelectValue();
},
{ immediate: true }
);
//
onMounted(() => {
if (!props.async) {
queryData();
}
});
return {
attrs,
Options,
loading,
selectedValue,
notFoundContent,
getParentContainer,
filterOption,
handleChange,
handleSearch,
handleFocus,
getOptionLabel,
getOptionValue,
handlePopupScroll,
};
},
});
</script>
<style lang="less" scoped></style>

View File

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

View File

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

View File

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

View File

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

View File

@ -25,11 +25,6 @@
/>
</a-form-item>
</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-form-item label="描述" v-bind="validateInfos.description" id="StockForm-description" name="description">
<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 { JDictSelectTag } from '@/components/Form';
import { getTenantId } from '@/utils/auth';
import PointSelect from '@/views/base/point/components/PointSelect.vue';
const props = defineProps({
formDisabled: { type: Boolean, default: false },
@ -71,7 +65,6 @@
let tenantId = getTenantId();
const formData = reactive<Record<string, any>>({
id: '',
pointId: '',
stockCode: '',
stockType: 'TRAY',
status: 0,

View File

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

View File

@ -13,7 +13,7 @@
<a-col :lg="6">
<a-form-item name="pointId">
<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-col>
<a-col :lg="6">

View File

@ -7,6 +7,12 @@ export const columns: BasicColumn[] = [
dataIndex: 'logType_dictText',
width: 100,
},
{
title: '业务单号',
align: 'center',
dataIndex: 'businessNo',
width: 130,
},
{
title: '物料',
align: 'center',
@ -17,19 +23,19 @@ export const columns: BasicColumn[] = [
title: '原库位',
align: 'center',
dataIndex: 'fromPointId_dictText',
width: 120,
width: 100,
},
{
title: '目标库位',
align: 'center',
dataIndex: 'toPointId_dictText',
width: 120,
width: 100,
},
{
title: '容器',
align: 'center',
dataIndex: 'stockId_dictText',
width: 120,
width: 100,
},
{
title: '变动前数量',
@ -50,15 +56,36 @@ export const columns: BasicColumn[] = [
width: 100,
},
{
title: '变动前分配数量',
title: '分配数量',
align: 'center',
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',
dataIndex: 'afterAllocatedQty',
width: 120,
width: 100,
}
];

View File

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

View File

@ -16,6 +16,7 @@ enum Api {
queryTaskByMainId = '/shipping/pick/queryTaskByMainId',
allocatePick = '/shipping/pick/allocatePick',
cancelAllocate = '/shipping/pick/cancelAllocate',
pickTask = '/shipping/pick/pickTask',
}
/**
@ -123,3 +124,13 @@ export const cancelAllocate = (ids,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 :gutter="24">
<a-col :lg="6">
<a-form-item name="status">
<a-form-item name="status_MultiString">
<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-col>
</a-row>
@ -53,22 +53,34 @@
<a-button
type="primary"
:loading="allocate_loading"
:disabled="selectedRowKeys.length === 0"
v-auth="'shipping:data_pick:allocatePick'"
@click="handleAllocatePick"
preIcon="ant-design:edit-outlined"
>
分配
批量分配
</a-button>
<a-button
type="primary"
danger
:loading="cancel_loading"
:disabled="selectedRowKeys.length === 0"
v-auth="'shipping:data_pick:cancelAllocate'"
@click="handleCancelAllocate"
preIcon="ant-design:edit-outlined"
>
取消分配
</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>
<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 PickModal from './components/PickModal.vue';
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 { getDateByPicker } from '/@/utils';
import { JInputTypeEnum } from '@/enums/cpteEnum';
import { JInput, JDictSelectTag } from '@/components/Form';
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 cancel_loading = ref(false);
const pick_loading = ref(false);
const fieldPickers = reactive({});
const formRef = ref();
const queryParam = reactive<any>({});
@ -184,10 +198,6 @@
* 分配事件
*/
async function handleAllocatePick() {
if (selectedRowKeys.value.length === 0) {
return createMessage.error('请选择出库单');
}
// 124 true,false
const validStatuses = [1, 2, 4];
const allValidStatus = selectedRows.value.every((row: any) => validStatuses.includes(row.status));
@ -214,10 +224,6 @@
* 取消分配
*/
async function handleCancelAllocate() {
if (selectedRowKeys.value.length === 0) {
return createMessage.error('请选择出库单');
}
// 23 true,false
const validStatuses = [2, 3];
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;
}
}
/**
* 编辑事件
*/