no message

main
HUOJIN\92525 2025-12-19 18:06:39 +08:00
parent 7b2f3fe311
commit d308c16400
23 changed files with 1113 additions and 251 deletions

View File

@ -14,7 +14,7 @@
@focus="handleAsyncFocus"
@search="loadData"
@change="handleAsyncChange"
@popupScroll="handlePopupScroll"
@popup-scroll="handlePopupScroll"
:mode="multiple?'multiple':''"
@select="handleSelect"
@deselect="handleDeSelect"
@ -176,7 +176,7 @@
isHasData = true;
searchKeyword = value;
// update-end--author:liaozhiyang---date:20240731---forTV360X-1898JsearchSelect
lastLoad.value += 1;
const currentLoad = unref(lastLoad);
options.value = [];
@ -399,7 +399,7 @@
callback();
}
}
/**
* 异步值取消选中事件
* @param selectedObj
@ -423,7 +423,7 @@
}
}
//update-end---author:wangshuai---date:2025-04-17---for:issues/8101dict---
/**
*回调方法
* */
@ -480,12 +480,12 @@
// [orderby:create_time,desc]
if(props.params && props.params.column && props.params.order){
let temp = text||''
//update-begin-author:taoyan date:2023-5-22 for: /issues/4905 Sgin #4905
temp = temp+'[orderby:'+props.params.column+','+props.params.order+']'
return encodeURI(temp);
//update-end-author:taoyan date:2023-5-22 for: /issues/4905 Sgin #4905
}else{
return text;
}

View File

@ -161,7 +161,6 @@
}
async function setModalHeight(option?) {
console.log("---------性能监控--------setModalHeight----------")
const options = option || {};
const source = options.source;
const callBack = options.callBack;
@ -208,7 +207,7 @@
callBack(realHeightRef.value);
}
// update-end--author:liaozhiyang---date:2024-04-18---forQQYUN-9035basicModalmaxHeightheightsetModalHeight使MutationObserver
emit('height-change', unref(realHeightRef));
} catch (error) {
console.log(error);

View File

@ -1,12 +1,13 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/base/item/list',
save='/base/item/add',
edit='/base/item/edit',
queryById = '/base/item/queryById',
save = '/base/item/add',
edit = '/base/item/edit',
deleteOne = '/base/item/delete',
deleteBatch = '/base/item/deleteBatch',
importExcel = '/base/item/importExcel',
@ -30,16 +31,22 @@ 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
* @param handleSuccess
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
export const deleteOne = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
}
};
/**
*
@ -54,12 +61,20 @@ export const batchDelete = (params, handleSuccess) => {
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
return defHttp
.delete(
{
url: Api.deleteBatch,
data: params,
},
{ joinParamsToUrl: true }
)
.then(() => {
handleSuccess();
});
},
});
}
};
/**
*
@ -67,6 +82,6 @@ export const batchDelete = (params, handleSuccess) => {
* @param isUpdate
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
const url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
}
};

View File

@ -0,0 +1,416 @@
<!-- 物料选择 -->
<template>
<a-select
v-model:value="selectedValue"
showSearch
:placeholder="placeholder"
:loading="loading"
:allowClear="true"
:filterOption="filterOption"
:notFoundContent="notFoundContent"
:mode="multiple ? 'multiple' : 'default'"
@change="handleChange"
@search="handleSearch"
@focus="handleFocus"
@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 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 { queryById } from '@/views/base/item/Item.api';
import { setPopContainer } from '/@/utils';
import { debounce } from 'lodash-es';
//
interface Item {
id: string;
itemCode: string;
itemName: string;
}
//
interface ResponseData {
records: Item[];
total: number;
size: number;
current: number;
page: number;
}
export default defineComponent({
name: 'ItemSelect',
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,
},
// change
immediateChange: propTypes.bool.def(false),
// : 'id'() | 'object' |
returnValue: propTypes.string.def('id'),
//
izActive: propTypes.number.def(1),
},
emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) {
const Options = ref<Item[]>([]);
const loading = ref<boolean>(false);
const allItems = ref<Item[]>([]);
const attrs = useAttrs({ excludeDefaultKeys: false });
//
const pageNo = ref(1);
const isHasData = ref(true);
const scrollLoading = ref(false);
const searchKeyword = ref('');
//
const selectedValue = ref<string | string[] | undefined>(undefined);
//
const notFoundContent = computed(() => {
return loading.value ? undefined : null;
});
/**
* 获取选项显示文本 - 始终显示完整格式
*/
function getOptionLabel(option: Item) {
return `${option.itemCode} - ${option.itemName}`;
}
/**
* 获取选项值 - 根据returnValue确定实际存储的值
*/
function getOptionValue(option: Item) {
if (props.returnValue === 'object') {
return option.id; // object使idchange
} else if (props.returnValue === 'id') {
return option.id;
} else {
return option[props.returnValue as keyof Item] as string;
}
}
/**
* 获取弹出层容器
*/
function getParentContainer(node: HTMLElement) {
if (props.popContainer) {
return setPopContainer(node, props.popContainer);
} else {
if (typeof props.getPopupContainer === 'function') {
return props.getPopupContainer(node);
} else {
return node?.parentNode;
}
}
}
/**
* 过滤选项 - 禁用前端过滤使用后端搜索
*/
function filterOption(_input: string, _option: any) {
return true; //
}
/**
* 确保物料唯一性的辅助函数
*/
function ensureUnique(items: Item[], newItem: Item): Item[] {
// id
const filtered = items.filter(item => item.id !== newItem.id);
return [newItem, ...filtered];
}
/**
* 获取物料数据
*/
const queryData = async (page = 1, keyword = '', isSearch = false) => {
try {
loading.value = true;
const res = await defHttp.get<ResponseData>({
url: '/base/item/list',
params: {
pageSize: props.pageSize,
pageNo: page,
keyword: keyword,
izActive: props.izActive,
},
});
const records = res.records || [];
if (page === 1 || isSearch) {
//
allItems.value = records;
Options.value = records;
} else {
//
const newRecords = records.filter(record =>
!allItems.value.some(item => item.id === record.id)
);
allItems.value = [...allItems.value, ...newRecords];
Options.value = [...Options.value, ...newRecords];
}
//
isHasData.value = records.length >= props.pageSize;
emit('optionsLoaded', allItems.value);
} catch (error) {
if (page === 1) {
allItems.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 item = Array.isArray(res) ? res[0] : res;
if (item) {
// 使ensureUnique
allItems.value = ensureUnique(allItems.value, item);
Options.value = ensureUnique(Options.value, item);
}
return item;
}
} catch (error) {
console.error('查询物料失败:', error);
}
return null;
}
/**
* 根据选项值找到对应的选项对象
*/
function findOptionByValue(value: string): Item | undefined {
if (props.returnValue === 'object' || props.returnValue === 'id') {
return allItems.value.find((item) => item.id === value);
} else {
return allItems.value.find((item) => item[props.returnValue as keyof Item] === 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);
}
}
// 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 Item] : v;
});
} else {
const option = findOptionByValue(value);
return option ? option[props.returnValue as keyof Item] : value;
}
}
}
/**
* 搜索处理防抖
*/
const handleSearch = debounce(function (value: string) {
searchKeyword.value = value;
pageNo.value = 1;
isHasData.value = true;
// API
queryData(1, value, true);
}, 300);
/**
* 处理焦点事件
*/
function handleFocus() {
//
if (allItems.value.length === 0 && props.async) {
pageNo.value = 1;
isHasData.value = true;
queryData(1, '');
}
attrs.onFocus?.();
}
/**
* 处理值变化
*/
function handleChange(value: string | string[]) {
selectedValue.value = value;
//
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;
}
//
if (props.async && allItems.value.length === 0) {
await queryData();
}
// returnValue
let valueIds: string[] = [];
if (props.returnValue === 'object') {
// value
if (Array.isArray(props.value)) {
valueIds = props.value.map((item: any) => item.id);
selectedValue.value = valueIds;
} else {
valueIds = [(props.value as any).id];
selectedValue.value = valueIds[0];
}
} 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 = allItems.value.find((item) => item[props.returnValue as keyof Item] === v);
return option ? option.id : v;
});
} else {
const option = allItems.value.find((item) => item[props.returnValue as keyof Item] === props.value);
valueIds = option ? [option.id] : [props.value as string];
}
}
//
const missingIds = valueIds.filter((id) => !allItems.value.some((item) => item.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

@ -5,6 +5,7 @@ const { createConfirm } = useMessage();
enum Api {
list = '/base/point/list',
queryById='/base/point/queryById',
save='/base/point/add',
edit='/base/point/edit',
deleteOne = '/base/point/delete',
@ -30,6 +31,13 @@ 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
@ -67,6 +75,6 @@ export const batchDelete = (params, handleSuccess) => {
* @param isUpdate
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
const url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
}

View File

@ -92,8 +92,6 @@
import { columns } from './Point.data';
import { list, deleteOne, batchDelete, saveOrUpdate, getImportUrl, getExportUrl } from './Point.api';
import PointModal from './components/PointModal.vue';
import { useUserStore } from '/@/store/modules/user';
import { useMessage } from '/@/hooks/web/useMessage';
import { getDateByPicker } from '/@/utils';
import { JInputTypeEnum } from '@/enums/cpteEnum';
import JInput from '../../../components/Form/src/jeecg/components/JInput.vue';
@ -106,8 +104,6 @@
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
const { createMessage } = useMessage();
//
const enhancedColumns = columns.map((col) => {
@ -135,7 +131,7 @@
});
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
const { tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '库位',
api: list,
@ -169,8 +165,7 @@
success: handleSuccess,
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] =
tableContext;
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs: 24,
sm: 4,

View File

@ -1,4 +1,4 @@
<!-- 库位下拉选择-->
<!-- 库位选择 -->
<template>
<a-select
v-model:value="selectedValue"
@ -12,7 +12,7 @@
@change="handleChange"
@search="handleSearch"
@focus="handleFocus"
@popupScroll="handlePopupScroll"
@popup-scroll="handlePopupScroll"
:getPopupContainer="getParentContainer"
v-bind="attrs"
>
@ -20,7 +20,7 @@
<a-spin v-if="loading" size="small" />
<span v-else></span>
</template>
<a-select-option v-for="option in PointOptions" :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>
@ -31,6 +31,7 @@
import { useAttrs } from '/@/hooks/core/useAttrs';
import { propTypes } from '/@/utils/propTypes';
import { defHttp } from '/@/utils/http/axios';
import { queryById } from '@/views/base/point/Point.api';
import { setPopContainer } from '/@/utils';
import { debounce } from 'lodash-es';
@ -63,7 +64,7 @@
//
async: propTypes.bool.def(true),
//
pageSize: propTypes.number.def(20),
pageSize: propTypes.number.def(10),
//
popContainer: propTypes.string,
//
@ -80,7 +81,7 @@
},
emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) {
const PointOptions = ref<Point[]>([]);
const Options = ref<Point[]>([]);
const loading = ref<boolean>(false);
const allPoints = ref<Point[]>([]);
const attrs = useAttrs({ excludeDefaultKeys: false });
@ -103,7 +104,7 @@
* 获取选项显示文本 - 始终显示完整格式
*/
function getOptionLabel(option: Point) {
return `${option.pointCode} - ${option.areaId_dictText }`;
return `${option.pointCode} - ${option.areaId_dictText}`;
}
/**
@ -141,10 +142,19 @@
return true; //
}
/**
* 确保库位唯一性的辅助函数
*/
function ensureUnique(Points: Point[], newPoint: Point): Point[] {
// id
const filtered = Points.filter(Point => Point.id !== newPoint.id);
return [newPoint, ...filtered];
}
/**
* 获取库位数据
*/
const fetchPoints = async (page = 1, keyword = '', isSearch = false) => {
const queryData = async (page = 1, keyword = '', isSearch = false) => {
try {
loading.value = true;
@ -158,29 +168,29 @@
},
});
console.log('获取库位数据成功:', res);
const records = res.records || [];
if (page === 1 || isSearch) {
//
allPoints.value = records;
PointOptions.value = records;
Options.value = records;
} else {
//
allPoints.value = [...allPoints.value, ...records];
PointOptions.value = [...PointOptions.value, ...records];
//
const newRecords = records.filter(record =>
!allPoints.value.some(Point => Point.id === record.id)
);
allPoints.value = [...allPoints.value, ...newRecords];
Options.value = [...Options.value, ...newRecords];
}
//
isHasData.value = records.length >= props.pageSize;
console.log('是否还有更多数据:', records.length);
emit('optionsLoaded', allPoints.value);
} catch (error) {
console.error('获取库位数据失败:', error);
if (page === 1) {
allPoints.value = [];
PointOptions.value = [];
Options.value = [];
}
} finally {
loading.value = false;
@ -188,14 +198,33 @@
}
};
async function queryDataById(value: string) {
try {
const res = await queryById({ id: value });
if (res) {
//
const Point = Array.isArray(res) ? res[0] : res;
if (Point) {
// 使ensureUnique
allPoints.value = ensureUnique(allPoints.value, Point);
Options.value = ensureUnique(Options.value, Point);
}
return Point;
}
} catch (error) {
console.error('查询库位失败:', error);
}
return null;
}
/**
* 根据选项值找到对应的选项对象
*/
function findOptionByValue(value: string): Point | undefined {
if (props.returnValue === 'object' || props.returnValue === 'id') {
return allPoints.value.find((item) => item.id === value);
return allPoints.value.find((Point) => Point.id === value);
} else {
return allPoints.value.find((item) => item[props.returnValue as keyof Point] === value);
return allPoints.value.find((Point) => Point[props.returnValue as keyof Point] === value);
}
}
@ -242,7 +271,7 @@
isHasData.value = true;
// API
fetchPoints(1, value, true);
queryData(1, value, true);
}, 300);
/**
@ -253,7 +282,7 @@
if (allPoints.value.length === 0 && props.async) {
pageNo.value = 1;
isHasData.value = true;
fetchPoints(1, '');
queryData(1, '');
}
attrs.onFocus?.();
}
@ -266,7 +295,6 @@
//
const returnValue = getReturnValue(value);
console.log('值变化:', returnValue);
emit('update:value', returnValue);
emit('change', returnValue);
}
@ -279,11 +307,10 @@
const { scrollTop, scrollHeight, clientHeight } = target;
if (!scrollLoading.value && isHasData.value && scrollTop + clientHeight >= scrollHeight - 10) {
console.log('滚动加载更多');
scrollLoading.value = true;
pageNo.value++;
fetchPoints(pageNo.value, searchKeyword.value)
queryData(pageNo.value, searchKeyword.value)
.finally(() => {
scrollLoading.value = false;
})
@ -304,22 +331,50 @@
//
if (props.async && allPoints.value.length === 0) {
await fetchPoints();
await queryData();
}
// returnValue
let valueIds: string[] = [];
if (props.returnValue === 'object') {
// value
if (Array.isArray(props.value)) {
selectedValue.value = props.value.map((item: any) => item.id);
valueIds = props.value.map((Point: any) => Point.id);
selectedValue.value = valueIds;
} else {
selectedValue.value = (props.value as any).id;
valueIds = [(props.value as any).id];
selectedValue.value = valueIds[0];
}
} 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 {
// 使
selectedValue.value = props.value as string | string[];
// ID
if (Array.isArray(props.value)) {
valueIds = props.value.map((v) => {
const option = allPoints.value.find((Point) => Point[props.returnValue as keyof Point] === v);
return option ? option.id : v;
});
} else {
const option = allPoints.value.find((Point) => Point[props.returnValue as keyof Point] === props.value);
valueIds = option ? [option.id] : [props.value as string];
}
}
//
const missingIds = valueIds.filter((id) => !allPoints.value.some((Point) => Point.id === id));
if (missingIds.length > 0) {
// ID
const queryPromises = missingIds.map((id) => queryDataById(id));
await Promise.all(queryPromises);
}
};
@ -335,13 +390,13 @@
//
onMounted(() => {
if (!props.async) {
fetchPoints();
queryData();
}
});
return {
attrs,
PointOptions,
Options,
loading,
selectedValue,
notFoundContent,

View File

@ -5,6 +5,7 @@ const { createConfirm } = useMessage();
enum Api {
list = '/base/stock/list',
queryById='/base/stock/queryById',
save='/base/stock/add',
edit='/base/stock/edit',
deleteOne = '/base/stock/delete',
@ -30,6 +31,12 @@ 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

@ -13,12 +13,7 @@
<a-col :lg="6">
<a-form-item name="pointId">
<template #label><span title="库位">库位</span></template>
<JSearchSelect
v-model:value="queryParam.pointId"
placeholder="请选择库位"
dict="base_point where iz_active=1 and del_flag=0 ,point_code,id"
allowClear
/>
<PointSelect v-model:value="queryParam.pointId" placeholder="请选择库位" />
</a-form-item>
</a-col>
<a-col :lg="6">
@ -99,7 +94,7 @@
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();

View File

@ -27,12 +27,7 @@
</a-col>
<a-col :span="24">
<a-form-item label="库位" v-bind="validateInfos.pointId" id="StockForm-pointId" name="pointId">
<JSearchSelect
v-model:value="formData.pointId"
placeholder="请选择库位"
dict="base_point where iz_active=1 and del_flag=0 ,point_code,id"
allowClear
/>
<PointSelect v-model:value="formData.pointId" />
</a-form-item>
</a-col>
<a-col :span="24">
@ -60,8 +55,9 @@
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import JSwitch from '@/components/Form/src/jeecg/components/JSwitch.vue';
import { JDictSelectTag, JSearchSelect } from '@/components/Form';
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 },

View File

@ -0,0 +1,415 @@
<!-- 容器选择 -->
<template>
<a-select
v-model:value="selectedValue"
showSearch
:placeholder="placeholder"
:loading="loading"
:allowClear="true"
:filterOption="filterOption"
:notFoundContent="notFoundContent"
:mode="multiple ? 'multiple' : 'default'"
@change="handleChange"
@search="handleSearch"
@focus="handleFocus"
@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 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 { queryById } from '@/views/base/stock/Stock.api';
import { setPopContainer } from '/@/utils';
import { debounce } from 'lodash-es';
//
interface Stock {
id: string;
stockCode: string;
}
//
interface ResponseData {
records: Stock[];
total: number;
size: number;
current: number;
page: number;
}
export default defineComponent({
name: 'StockSelect',
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,
},
// change
immediateChange: propTypes.bool.def(false),
// : 'id'() | 'object' |
returnValue: propTypes.string.def('id'),
//
izActive: propTypes.number.def(1),
},
emits: ['change', 'update:value', 'optionsLoaded'],
setup(props, { emit }) {
const Options = ref<Stock[]>([]);
const loading = ref<boolean>(false);
const allStocks = ref<Stock[]>([]);
const attrs = useAttrs({ excludeDefaultKeys: false });
//
const pageNo = ref(1);
const isHasData = ref(true);
const scrollLoading = ref(false);
const searchKeyword = ref('');
//
const selectedValue = ref<string | string[] | undefined>(undefined);
//
const notFoundContent = computed(() => {
return loading.value ? undefined : null;
});
/**
* 获取选项显示文本 - 始终显示完整格式
*/
function getOptionLabel(option: Stock) {
return `${option.stockCode}`;
}
/**
* 获取选项值 - 根据returnValue确定实际存储的值
*/
function getOptionValue(option: Stock) {
if (props.returnValue === 'object') {
return option.id; // object使idchange
} else if (props.returnValue === 'id') {
return option.id;
} else {
return option[props.returnValue as keyof Stock] as string;
}
}
/**
* 获取弹出层容器
*/
function getParentContainer(node: HTMLElement) {
if (props.popContainer) {
return setPopContainer(node, props.popContainer);
} else {
if (typeof props.getPopupContainer === 'function') {
return props.getPopupContainer(node);
} else {
return node?.parentNode;
}
}
}
/**
* 过滤选项 - 禁用前端过滤使用后端搜索
*/
function filterOption(_input: string, _option: any) {
return true; //
}
/**
* 确保容器唯一性的辅助函数
*/
function ensureUnique(Stocks: Stock[], newStock: Stock): Stock[] {
// id
const filtered = Stocks.filter(Stock => Stock.id !== newStock.id);
return [newStock, ...filtered];
}
/**
* 获取容器数据
*/
const queryData = async (page = 1, keyword = '', isSearch = false) => {
try {
loading.value = true;
const res = await defHttp.get<ResponseData>({
url: '/base/stock/list',
params: {
pageSize: props.pageSize,
pageNo: page,
keyword: keyword,
izActive: props.izActive,
},
});
const records = res.records || [];
if (page === 1 || isSearch) {
//
allStocks.value = records;
Options.value = records;
} else {
//
const newRecords = records.filter(record =>
!allStocks.value.some(Stock => Stock.id === record.id)
);
allStocks.value = [...allStocks.value, ...newRecords];
Options.value = [...Options.value, ...newRecords];
}
//
isHasData.value = records.length >= props.pageSize;
emit('optionsLoaded', allStocks.value);
} catch (error) {
if (page === 1) {
allStocks.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 Stock = Array.isArray(res) ? res[0] : res;
if (Stock) {
// 使ensureUnique
allStocks.value = ensureUnique(allStocks.value, Stock);
Options.value = ensureUnique(Options.value, Stock);
}
return Stock;
}
} catch (error) {
console.error('查询容器失败:', error);
}
return null;
}
/**
* 根据选项值找到对应的选项对象
*/
function findOptionByValue(value: string): Stock | undefined {
if (props.returnValue === 'object' || props.returnValue === 'id') {
return allStocks.value.find((Stock) => Stock.id === value);
} else {
return allStocks.value.find((Stock) => Stock[props.returnValue as keyof Stock] === 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);
}
}
// 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 Stock] : v;
});
} else {
const option = findOptionByValue(value);
return option ? option[props.returnValue as keyof Stock] : value;
}
}
}
/**
* 搜索处理防抖
*/
const handleSearch = debounce(function (value: string) {
searchKeyword.value = value;
pageNo.value = 1;
isHasData.value = true;
// API
queryData(1, value, true);
}, 300);
/**
* 处理焦点事件
*/
function handleFocus() {
//
if (allStocks.value.length === 0 && props.async) {
pageNo.value = 1;
isHasData.value = true;
queryData(1, '');
}
attrs.onFocus?.();
}
/**
* 处理值变化
*/
function handleChange(value: string | string[]) {
selectedValue.value = value;
//
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;
}
//
if (props.async && allStocks.value.length === 0) {
await queryData();
}
// returnValue
let valueIds: string[] = [];
if (props.returnValue === 'object') {
// value
if (Array.isArray(props.value)) {
valueIds = props.value.map((Stock: any) => Stock.id);
selectedValue.value = valueIds;
} else {
valueIds = [(props.value as any).id];
selectedValue.value = valueIds[0];
}
} 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 = allStocks.value.find((Stock) => Stock[props.returnValue as keyof Stock] === v);
return option ? option.id : v;
});
} else {
const option = allStocks.value.find((Stock) => Stock[props.returnValue as keyof Stock] === props.value);
valueIds = option ? [option.id] : [props.value as string];
}
}
//
const missingIds = valueIds.filter((id) => !allStocks.value.some((Stock) => Stock.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

@ -31,7 +31,7 @@
<main class="dashboard-card">
<section class="scan-section">
<div class="section-header">
<span class="label-cn">当前扫描</span>
<span class="label-cn">当前托盘</span>
<span class="label-en">CURRENT SCAN</span>
</div>
<div class="scan-content">
@ -123,7 +123,7 @@
});
async function queryData() {
const conveyorLine = 'CKJBK01';
const conveyorLine = 'ST102';
const res = await showConveyorLine(conveyorLine);
scanData.value = {
stockCode: res.stockCode,

View File

@ -1,4 +1,5 @@
import { BasicColumn } from '/@/components/Table';
import { render } from '@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
{
@ -36,7 +37,19 @@ export const columns: BasicColumn[] = [
align: 'center',
dataIndex: 'status_dictText',
width: 100,
customRender: ({ text }) => {
const statusColorMap = {
: 'red',
: 'green',
: 'orange',
: 'cyan',
: 'blue',
: 'purple',
: 'pink',
};
const color = statusColorMap[text] || 'red';
return render.renderTag(text, color);
},
},
{
title: '外部仓库',

View File

@ -7,34 +7,19 @@
<a-col :lg="6">
<a-form-item name="itemId">
<template #label><span title="物料">物料</span></template>
<JSearchSelect
v-model:value="queryParam.itemId"
placeholder="请选择物料"
dict="base_item where iz_active=1 and del_flag=0 ,item_code,id"
allowClear
/>
<ItemSelect v-model:value="queryParam.itemId" />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="pointId">
<template #label><span title="库位">库位</span></template>
<JSearchSelect
v-model:value="queryParam.pointId"
placeholder="请选择库位"
dict="base_point where iz_active=1 and del_flag=0 ,point_code,id"
allowClear
/>
<PointSelect v-model:value="queryParam.pointId" />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="stockId">
<template #label><span title="容器">容器</span></template>
<JSearchSelect
v-model:value="queryParam.stockId"
placeholder="请选择容器"
dict="base_stock where iz_active=1 and del_flag=0 ,stock_code,id"
allowClear
/>
<StockSelect v-model:value="queryParam.stockId" />
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
@ -52,7 +37,7 @@
</a-row>
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="status">
<a-form-item name="status" v-if="toggleSearchStatus">
<template #label><span title="库存状态">库存状态</span></template>
<JDictSelectTag v-model:value="queryParam.status" placeholder="请选择" dictCode="inventory_status" allowClear />
</a-form-item>
@ -90,7 +75,7 @@
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
<template v-slot:bodyCell="{ column, record, index, text }"> </template>
<template v-slot:bodyCell="{ column, record, index, text }"></template>
</BasicTable>
<!-- 表单区域 -->
<InventoryModal ref="registerModal" @success="handleSuccess"></InventoryModal>
@ -108,6 +93,9 @@
import { useMessage } from '/@/hooks/web/useMessage';
import { getDateByPicker } from '/@/utils';
import { JDictSelectTag, JSearchSelect } from '@/components/Form';
import ItemSelect from '@/views/base/item/components/ItemSelect.vue';
import PointSelect from '@/views/base/point/components/PointSelect.vue';
import StockSelect from '@/views/base/stock/components/StockSelect.vue';
const fieldPickers = reactive({});

View File

@ -6,32 +6,17 @@
<a-row class="form-row" :gutter="24">
<a-col :span="8">
<a-form-item label="物料" v-bind="validateInfos.itemId" id="InventoryForm-itemId" name="itemId">
<JSearchSelect
v-model:value="formData.itemId"
placeholder="请选择物料"
dict="base_item where iz_active=1 and del_flag=0 ,item_code,id"
allowClear
/>
<ItemSelect v-model:value="formData.itemId" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="库位" v-bind="validateInfos.pointId" id="InventoryForm-pointId" name="pointId">
<JSearchSelect
v-model:value="formData.pointId"
placeholder="请选择库位"
dict="base_point where iz_active=1 and del_flag=0 ,point_code,id"
allowClear
/>
<PointSelect v-model:value="formData.pointId" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="容器" v-bind="validateInfos.stockId" id="InventoryForm-stockId" name="stockId">
<JSearchSelect
v-model:value="formData.stockId"
placeholder="请选择容器"
dict="base_stock where iz_active=1 and del_flag=0 ,stock_code,id"
allowClear
/>
<StockSelect v-model:value="formData.stockId" />
</a-form-item>
</a-col>
</a-row>
@ -41,9 +26,32 @@
<a-input-number v-model:value="formData.quantity" placeholder="请输入数量" style="width: 100%" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="占用数" v-bind="validateInfos.quantity" id="InventoryForm-queuedQty" name="queuedQty">
<a-input-number v-model:value="formData.queuedQty" placeholder="请输入占用数" style="width: 100%" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="库存状态" v-bind="validateInfos.status" id="InventoryForm-status" name="status">
<JDictSelectTag v-model:value="formData.status" placeholder="请选择" dictCode="inventory_status" string-to-number="true" allowClear />
<JDictSelectTag
v-model:value="formData.status"
placeholder="请选择"
dictCode="inventory_status"
:string-to-number="true"
allowClear
/>
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="24">
<a-col :span="8">
<a-form-item label="项目号" v-bind="validateInfos.project" id="InventoryForm-project" name="project">
<a-input v-model:value="formData.project" placeholder="请输入项目号" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="任务号" v-bind="validateInfos.taskNo" id="InventoryForm-taskNo" name="taskNo">
<a-input v-model:value="formData.taskNo" placeholder="请输入任务号" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="8">
@ -63,17 +71,6 @@
<a-input v-model:value="formData.propC3" placeholder="请输入外部库存状态" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="生产日期" v-bind="validateInfos.propD1" id="InventoryForm-propD1" name="propD1">
<a-date-picker
placeholder="请选择生产日期"
v-model:value="formData.propD1"
value-format="YYYY-MM-DD"
style="width: 100%"
allow-clear
/>
</a-form-item>
</a-col>
</a-row>
<a-row class="form-row" :gutter="24">
<a-col :span="24">
@ -103,7 +100,10 @@
import { saveOrUpdate } from '../Inventory.api';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import { JDictSelectTag, JSearchSelect } from '@/components/Form';
import { JDictSelectTag } from '@/components/Form';
import ItemSelect from '@/views/base/item/components/ItemSelect.vue';
import PointSelect from '@/views/base/point/components/PointSelect.vue';
import StockSelect from '@/views/base/stock/components/StockSelect.vue';
const props = defineProps({
formDisabled: { type: Boolean, default: false },
@ -117,17 +117,17 @@
let tenantId = getTenantId();
const formData = reactive<Record<string, any>>({
id: '',
itemId: undefined,
pointId: undefined,
stockId: undefined,
itemId: '',
pointId: '',
stockId: '',
quantity: '',
queuedQty: 0,
whCode: '',
project: '',
taskNo: '',
propC1: '',
propC2: '',
propC3: '',
status: '',
propD1: '',
status: 1,
description: '',
tenantId: tenantId,
});

View File

@ -1,18 +1,27 @@
<template><j-modal :title="title" :maxHeight="500" :width="800" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<template>
<j-modal
:title="title"
:maxHeight="600"
:width="900"
:visible="visible"
@ok="handleOk"
:okButtonProps="{ class: { 'jee-hidden': disableSubmit } }"
@cancel="handleCancel"
cancelText="关闭"
>
<InventoryForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></InventoryForm>
<template #footer>
<a-button @click="handleCancel"></a-button>
<a-button :class="{ 'jee-hidden': disableSubmit }" type="primary" @click="handleOk"></a-button>
</template>
<template #footer>
<a-button @click="handleCancel"></a-button>
<a-button :class="{ 'jee-hidden': disableSubmit }" type="primary" @click="handleOk"> </a-button>
</template>
</j-modal>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import InventoryForm from './InventoryForm.vue'
import InventoryForm from './InventoryForm.vue';
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
const { createMessage } = useMessage();
const title = ref<string>('');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
@ -63,6 +72,7 @@
function handleCancel() {
visible.value = false;
}
defineExpose({
add,
edit,

View File

@ -60,35 +60,5 @@ export const columns: BasicColumn[] = [
align: 'center',
dataIndex: 'afterAllocatedQty',
width: 120,
},
{
title: '项目号',
align: 'center',
dataIndex: 'project',
width: 100,
},
{
title: '任务号',
align: 'center',
dataIndex: 'taskNo',
width: 100,
},
{
title: '批次号',
align: 'center',
dataIndex: 'propC1',
width: 100,
},
{
title: '外部库存状态',
align: 'center',
dataIndex: 'propC3',
width: 100,
},
{
title: '备注',
align: 'center',
dataIndex: 'description',
ellipsis: true,
},
}
];

View File

@ -7,34 +7,19 @@
<a-col :lg="6">
<a-form-item name="itemId">
<template #label><span title="物料">物料</span></template>
<JSearchSelect
v-model:value="queryParam.itemId"
placeholder="请选择物料"
dict="base_item where iz_active=1 and del_flag=0 ,item_code,id"
allowClear
/>
<ItemSelect v-model:value="queryParam.itemId" />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="pointId">
<template #label><span title="库位">库位</span></template>
<JSearchSelect
v-model:value="queryParam.pointId"
placeholder="请选择库位"
dict="base_point where iz_active=1 and del_flag=0 ,point_code,id"
allowClear
/>
<PointSelect v-model:value="queryParam.pointId" />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="stockId">
<template #label><span title="容器">容器</span></template>
<JSearchSelect
v-model:value="queryParam.stockId"
placeholder="请选择容器"
dict="base_stock where iz_active=1 and del_flag=0 ,stock_code,id"
allowClear
/>
<StockSelect v-model:value="queryParam.stockId" />
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
@ -52,7 +37,7 @@
</a-row>
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="logType">
<a-form-item name="logType" v-if="toggleSearchStatus">
<template #label><span title="日志类型">日志类型</span></template>
<JDictSelectTag v-model:value="queryParam.logType" placeholder="请选择" dictCode="inventory_log_type" allowClear />
</a-form-item>
@ -112,10 +97,11 @@
import { columns } from './InventoryLog.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './InventoryLog.api';
import InventoryLogModal from './components/InventoryLogModal.vue';
import { useUserStore } from '/@/store/modules/user';
import { useMessage } from '/@/hooks/web/useMessage';
import { getDateByPicker } from '/@/utils';
import { JDictSelectTag, JSearchSelect } from '@/components/Form';
import { JDictSelectTag } from '@/components/Form';
import ItemSelect from '@/views/base/item/components/ItemSelect.vue';
import PointSelect from '@/views/base/point/components/PointSelect.vue';
import StockSelect from '@/views/base/stock/components/StockSelect.vue';
const fieldPickers = reactive({});
@ -123,10 +109,8 @@
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
const { createMessage } = useMessage();
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
const { tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '库存日志',
api: list,
@ -161,8 +145,7 @@
success: handleSuccess,
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] =
tableContext;
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs: 24,
sm: 4,

View File

@ -27,13 +27,14 @@ export const columns: BasicColumn[] = [
dataIndex: 'status_dictText',
width: '80px',
customRender: ({ text }) => {
//入库状态:1.已创建;2.部分收货;3.收货完成;4.已关闭,5.已取消
//入库状态:1.已创建;2.部分收货;3.收货完成;4.已关闭,5.已取消、6.已扫描
const statusColorMap = {
: 'orange',
: 'blue',
: 'green',
: 'green',
: 'red',
: 'purple',
};
const color = statusColorMap[text] || 'red';
return render.renderTag(text, color);
@ -74,8 +75,8 @@ export const columns: BasicColumn[] = [
align: 'center',
dataIndex: 'resMessage',
customRender: ({ text }) => {
return render.renderTip(text)
}
return render.renderTip(text);
},
},
{
title: '订单日期',
@ -181,7 +182,6 @@ export const asnDetailColumns: JVxeColumn[] = [
3: '收货完成',
4: '已关闭',
5: '已取消',
};
// 状态颜色映射
const statusColorMap = {

View File

@ -4,12 +4,6 @@
<div class="jeecg-basic-table-form-container">
<a-form ref="formRef" @keyup.enter.native="reload" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="orderNo">
<template #label><span title="系统单号">系统单号</span></template>
<JInput v-model:value="queryParam.orderNo" :placeholder="'请输入系统单号'" :type="JInputTypeEnum.JINPUT_RIGHT_LIKE" />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="no">
<template #label><span title="任务号">任务号</span></template>
@ -22,6 +16,12 @@
<JDictSelectTag v-model:value="queryParam.orderType" placeholder="请选择" dictCode="asn_order_type" allowClear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="orderDate">
<template #label><span title="订单日期">订单日期</span></template>
<JRangeDate v-model:value="queryParam.orderDate" />
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6">
@ -36,18 +36,13 @@
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :lg="6">
<!-- <a-col :lg="6">
<a-form-item name="status">
<template #label><span title="状态">状态</span></template>
<JDictSelectTag v-model:value="queryParam.status" placeholder="请选择" dictCode="asn_status" allowClear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="orderDate">
<template #label><span title="订单日期">订单日期</span></template>
<JRangeDate v-model:value="queryParam.orderDate" />
</a-form-item>
</a-col>
</a-col>-->
</a-row>
</a-form>
</div>

View File

@ -221,24 +221,37 @@ export const taskColumns: JVxeColumn[] = [
{
title: '物料',
key: 'itemId',
type: JVxeTypes.normal,
type: JVxeTypes.selectDictSearch,
disabled: true,
async: true, // 异步搜索,默认为 true
//查询状态启用、未删除的物料
dict: 'base_item where iz_active=1 and del_flag=0,item_code,id',
tipsContent: '请搜索物料',
dict: 'base_item,item_code,id',
},
{
title: '单位',
key: 'unit',
type: JVxeTypes.normal,
dictCode: 'package_unit',
placeholder: '请选择${title}',
defaultValue: '托',
title: '原库位',
key: 'fromPointId',
type: JVxeTypes.selectDictSearch,
disabled: true,
async: true, // 异步搜索,默认为 true
dict: 'base_point,point_code,id',
},
{
title: '目标库位',
key: 'toPointId',
type: JVxeTypes.selectDictSearch,
disabled: true,
async: true, // 异步搜索,默认为 true
dict: 'base_point,point_code,id',
},
{
title: '分配数量',
key: 'planQty',
type: JVxeTypes.normal,
defaultValue: '0',
disabled: true,
},
{
title: '拣货数量',
key: 'planQty',
key: 'moveQty',
type: JVxeTypes.normal,
defaultValue: '0',
disabled: true,
@ -247,6 +260,5 @@ export const taskColumns: JVxeColumn[] = [
title: '返回报文',
key: 'resMessage',
type: JVxeTypes.normal,
width: '200px',
},
}
];

View File

@ -4,12 +4,6 @@
<div class="jeecg-basic-table-form-container">
<a-form ref="formRef" @keyup.enter.native="reload" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="orderNo">
<template #label><span title="系统单号">系统单号</span></template>
<JInput v-model:value="queryParam.orderNo" :placeholder="'请输入系统单号'" :type="JInputTypeEnum.JINPUT_RIGHT_LIKE" />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="no">
<template #label><span title="任务号">任务号</span></template>
@ -22,6 +16,12 @@
<JDictSelectTag v-model:value="queryParam.orderType" placeholder="请选择" dictCode="pick_order_type" allowClear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="orderDate">
<template #label><span title="订单日期">订单日期</span></template>
<JRangeDate v-model:value="queryParam.orderDate" />
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6">
@ -39,13 +39,7 @@
<a-col :lg="6">
<a-form-item name="status">
<template #label><span title="状态">状态</span></template>
<JDictSelectTag v-model:value="queryParam.status" placeholder="请选择" dictCode="pick_status" allowClear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="orderDate">
<template #label><span title="订单日期">订单日期</span></template>
<JRangeDate v-model:value="queryParam.orderDate" />
<JDictSelectTag v-model:value="queryParam.status" placeholder="请选择" dictCode="pick_status" mode="multiple" allowClear />
</a-form-item>
</a-col>
</a-row>
@ -116,7 +110,6 @@
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, allocatePick, cancelAllocate } from './Pick.api';
import { useMessage } from '/@/hooks/web/useMessage';
import { getDateByPicker } from '/@/utils';
import { useUserStore } from '/@/store/modules/user';
import { JInputTypeEnum } from '@/enums/cpteEnum';
import { JInput, JDictSelectTag } from '@/components/Form';
import JRangeDate from '@/components/Form/src/jeecg/components/JRangeDate.vue';
@ -126,13 +119,11 @@
const fieldPickers = reactive({});
const formRef = ref();
const queryParam = reactive<any>({});
const checkedKeys = ref<Array<string | number>>([]);
//model
const [registerModal, { openModal }] = useModal();
const userStore = useUserStore();
const { createMessage } = useMessage();
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
const { tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '出库单',
api: list,
@ -212,11 +203,10 @@
await allocatePick(selectedRowKeys.value, handleSuccess);
} catch (e) {
console.error('分配失败:', e);
handleSuccess()
handleSuccess();
} finally {
//
allocate_loading.value = false;
}
}
@ -243,7 +233,7 @@
await cancelAllocate(selectedRowKeys.value, handleSuccess);
} catch (e) {
console.error('取消失败:', e);
handleSuccess()
handleSuccess();
} finally {
//
cancel_loading.value = false;

View File

@ -73,8 +73,8 @@
<a-tab-pane tab="出库明细" key="pickDetail" :forceRender="true">
<j-vxe-table
:keep-source="true"
resizable
ref="pickDetailTableRef"
resizable
:loading="pickDetailTable.loading"
:columns="pickDetailTable.columns"
:dataSource="pickDetailTable.dataSource"
@ -107,7 +107,7 @@
<script lang="ts">
import { defineComponent, ref, reactive, computed, toRaw } from 'vue';
import { useValidateAntFormAndTable } from '/@/hooks/system/useJvxeMethods';
import { queryPickDetailListByMainId, queryDataById, saveOrUpdate } from '../Pick.api';
import { queryPickDetailListByMainId, queryDataById, saveOrUpdate,queryTaskByMainId } from '../Pick.api';
import { JVxeTable } from '/@/components/jeecg/JVxeTable';
import { pickDetailColumns, taskColumns } from '../Pick.data';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';