feat(mes): 完善条码管理迁移并补齐业务选择器
parent
7ee42b9888
commit
6b6d45132f
|
|
@ -21,6 +21,8 @@ export namespace MesProWorkOrderApi {
|
||||||
routeName?: string;
|
routeName?: string;
|
||||||
clientId?: number;
|
clientId?: number;
|
||||||
clientName?: string;
|
clientName?: string;
|
||||||
|
vendorId?: number; // 供应商编号
|
||||||
|
vendorName?: string; // 供应商名称
|
||||||
planStartTime?: number | string;
|
planStartTime?: number | string;
|
||||||
planEndTime?: number | string;
|
planEndTime?: number | string;
|
||||||
actualStartTime?: number | string;
|
actualStartTime?: number | string;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace MesWmItemReceiptApi {
|
export namespace MesWmItemReceiptApi {
|
||||||
|
|
@ -19,16 +21,66 @@ export namespace MesWmItemReceiptApi {
|
||||||
locationName?: string; // 库区名称
|
locationName?: string; // 库区名称
|
||||||
areaId?: number; // 库位编号
|
areaId?: number; // 库位编号
|
||||||
areaName?: string; // 库位名称
|
areaName?: string; // 库位名称
|
||||||
receiptDate?: Date | number | string; // 入库日期
|
receiptDate?: number; // 入库日期
|
||||||
status?: number; // 状态
|
status?: number; // 状态
|
||||||
remark?: string; // 备注
|
remark?: string; // 备注
|
||||||
createTime?: Date; // 创建时间
|
createTime?: Date; // 创建时间
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 查询采购入库单分页 */
|
||||||
|
export function getItemReceiptPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MesWmItemReceiptApi.ItemReceipt>>(
|
||||||
|
'/mes/wm/item-receipt/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** 查询采购入库单详情 */
|
/** 查询采购入库单详情 */
|
||||||
export function getItemReceipt(id: number) {
|
export function getItemReceipt(id: number) {
|
||||||
return requestClient.get<MesWmItemReceiptApi.ItemReceipt>(
|
return requestClient.get<MesWmItemReceiptApi.ItemReceipt>(
|
||||||
`/mes/wm/item-receipt/get?id=${id}`,
|
`/mes/wm/item-receipt/get?id=${id}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 新增采购入库单 */
|
||||||
|
export function createItemReceipt(data: MesWmItemReceiptApi.ItemReceipt) {
|
||||||
|
return requestClient.post<number>('/mes/wm/item-receipt/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改采购入库单 */
|
||||||
|
export function updateItemReceipt(data: MesWmItemReceiptApi.ItemReceipt) {
|
||||||
|
return requestClient.put('/mes/wm/item-receipt/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除采购入库单 */
|
||||||
|
export function deleteItemReceipt(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/item-receipt/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交采购入库单 */
|
||||||
|
export function submitItemReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/item-receipt/submit?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行上架 */
|
||||||
|
export function stockItemReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/item-receipt/stock?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行入库 */
|
||||||
|
export function finishItemReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/item-receipt/finish?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消采购入库单 */
|
||||||
|
export function cancelItemReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/item-receipt/cancel?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出采购入库单 */
|
||||||
|
export function exportItemReceipt(params: any) {
|
||||||
|
return requestClient.download('/mes/wm/item-receipt/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace MesWmItemReceiptLineApi {
|
export namespace MesWmItemReceiptLineApi {
|
||||||
/** MES 物料接收单行 */
|
/** MES 采购入库单行 */
|
||||||
export interface ItemReceiptLine {
|
export interface ItemReceiptLine {
|
||||||
id?: number; // 行编号
|
id?: number; // 行编号
|
||||||
receiptId?: number; // 入库单编号
|
receiptId?: number; // 入库单编号
|
||||||
receiptCode?: string; // 入库单编码
|
receiptCode?: string; // 入库单编码
|
||||||
|
arrivalNoticeLineId?: number; // 到货通知单行编号
|
||||||
purchaseOrderCode?: string; // 采购订单号
|
purchaseOrderCode?: string; // 采购订单号
|
||||||
itemId?: number; // 物料编号
|
itemId?: number; // 物料编号
|
||||||
itemCode?: string; // 物料编码
|
itemCode?: string; // 物料编码
|
||||||
|
|
@ -15,14 +16,48 @@ export namespace MesWmItemReceiptLineApi {
|
||||||
specification?: string; // 规格型号
|
specification?: string; // 规格型号
|
||||||
unitMeasureName?: string; // 单位
|
unitMeasureName?: string; // 单位
|
||||||
receivedQuantity?: number; // 入库数量
|
receivedQuantity?: number; // 入库数量
|
||||||
|
batchId?: number; // 批次编号
|
||||||
batchCode?: string; // 批次号
|
batchCode?: string; // 批次号
|
||||||
|
productionDate?: number; // 生产日期
|
||||||
|
expireDate?: number; // 有效期
|
||||||
|
lotNumber?: string; // 生产批号
|
||||||
|
iqcCheckFlag?: boolean; // 是否检验
|
||||||
|
iqcId?: number; // 来料检验单编号
|
||||||
|
iqcCode?: string; // 来料检验单编码
|
||||||
|
remark?: string; // 备注
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询物料接收单行分页 */
|
/** 查询采购入库单行分页 */
|
||||||
export function getItemReceiptLinePage(params: PageParam) {
|
export function getItemReceiptLinePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<MesWmItemReceiptLineApi.ItemReceiptLine>>(
|
return requestClient.get<PageResult<MesWmItemReceiptLineApi.ItemReceiptLine>>(
|
||||||
'/mes/wm/item-receipt-line/page',
|
'/mes/wm/item-receipt-line/page',
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 查询采购入库单行详情 */
|
||||||
|
export function getItemReceiptLine(id: number) {
|
||||||
|
return requestClient.get<MesWmItemReceiptLineApi.ItemReceiptLine>(
|
||||||
|
`/mes/wm/item-receipt-line/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增采购入库单行 */
|
||||||
|
export function createItemReceiptLine(
|
||||||
|
data: MesWmItemReceiptLineApi.ItemReceiptLine,
|
||||||
|
) {
|
||||||
|
return requestClient.post<number>('/mes/wm/item-receipt-line/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改采购入库单行 */
|
||||||
|
export function updateItemReceiptLine(
|
||||||
|
data: MesWmItemReceiptLineApi.ItemReceiptLine,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/item-receipt-line/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除采购入库单行 */
|
||||||
|
export function deleteItemReceiptLine(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/item-receipt-line/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceIssueDetailApi {
|
||||||
|
/** MES 外协发料单明细 */
|
||||||
|
export interface OutsourceIssueDetail {
|
||||||
|
id?: number; // 明细编号
|
||||||
|
lineId?: number; // 行编号
|
||||||
|
issueId?: number; // 发料单编号
|
||||||
|
itemId?: number; // 物料编号
|
||||||
|
itemCode?: string; // 物料编码
|
||||||
|
itemName?: string; // 物料名称
|
||||||
|
specification?: string; // 规格型号
|
||||||
|
unitMeasureName?: string; // 计量单位名称
|
||||||
|
quantity?: number; // 数量
|
||||||
|
materialStockId?: number; // 库存编号
|
||||||
|
batchId?: number; // 批次编号
|
||||||
|
batchCode?: string; // 批次编码
|
||||||
|
warehouseId?: number; // 仓库编号
|
||||||
|
warehouseName?: string; // 仓库名称
|
||||||
|
locationId?: number; // 库区编号
|
||||||
|
locationName?: string; // 库区名称
|
||||||
|
areaId?: number; // 库位编号
|
||||||
|
areaName?: string; // 库位名称
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单明细列表 */
|
||||||
|
export function getOutsourceIssueDetailListByLineId(lineId: number) {
|
||||||
|
return requestClient.get<
|
||||||
|
MesWmOutsourceIssueDetailApi.OutsourceIssueDetail[]
|
||||||
|
>('/mes/wm/outsource-issue-detail/list-by-line', { params: { lineId } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单明细详情 */
|
||||||
|
export function getOutsourceIssueDetail(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceIssueDetailApi.OutsourceIssueDetail>(
|
||||||
|
`/mes/wm/outsource-issue-detail/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协发料单明细 */
|
||||||
|
export function createOutsourceIssueDetail(
|
||||||
|
data: MesWmOutsourceIssueDetailApi.OutsourceIssueDetail,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/mes/wm/outsource-issue-detail/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协发料单明细 */
|
||||||
|
export function updateOutsourceIssueDetail(
|
||||||
|
data: MesWmOutsourceIssueDetailApi.OutsourceIssueDetail,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-issue-detail/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协发料单明细 */
|
||||||
|
export function deleteOutsourceIssueDetail(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-issue-detail/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceIssueApi {
|
||||||
|
/** MES 外协发料单 */
|
||||||
|
export interface OutsourceIssue {
|
||||||
|
id?: number; // 发料单编号
|
||||||
|
code?: string; // 发料单编号
|
||||||
|
name?: string; // 发料单名称
|
||||||
|
vendorId?: number; // 供应商编号
|
||||||
|
vendorCode?: string; // 供应商编码
|
||||||
|
vendorName?: string; // 供应商名称
|
||||||
|
workOrderId?: number; // 生产工单编号
|
||||||
|
workOrderCode?: string; // 生产工单编码
|
||||||
|
workOrderName?: string; // 生产工单名称
|
||||||
|
issueDate?: number; // 发料日期
|
||||||
|
status?: number; // 单据状态
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单分页 */
|
||||||
|
export function getOutsourceIssuePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MesWmOutsourceIssueApi.OutsourceIssue>>(
|
||||||
|
'/mes/wm/outsource-issue/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单详情 */
|
||||||
|
export function getOutsourceIssue(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceIssueApi.OutsourceIssue>(
|
||||||
|
`/mes/wm/outsource-issue/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协发料单 */
|
||||||
|
export function createOutsourceIssue(
|
||||||
|
data: MesWmOutsourceIssueApi.OutsourceIssue,
|
||||||
|
) {
|
||||||
|
return requestClient.post<number>('/mes/wm/outsource-issue/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协发料单 */
|
||||||
|
export function updateOutsourceIssue(
|
||||||
|
data: MesWmOutsourceIssueApi.OutsourceIssue,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-issue/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协发料单 */
|
||||||
|
export function deleteOutsourceIssue(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-issue/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交外协发料单 */
|
||||||
|
export function submitOutsourceIssue(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-issue/submit?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行拣货 */
|
||||||
|
export function stockOutsourceIssue(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-issue/stock?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行领出 */
|
||||||
|
export function finishOutsourceIssue(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-issue/finish?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消外协发料单 */
|
||||||
|
export function cancelOutsourceIssue(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-issue/cancel?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 校验外协发料单拣货数量是否与发料数量一致 */
|
||||||
|
export function checkOutsourceIssueQuantity(id: number) {
|
||||||
|
return requestClient.get<boolean>(
|
||||||
|
`/mes/wm/outsource-issue/check-quantity?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出外协发料单 */
|
||||||
|
export function exportOutsourceIssue(params: any) {
|
||||||
|
return requestClient.download('/mes/wm/outsource-issue/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceIssueLineApi {
|
||||||
|
/** MES 外协发料单行 */
|
||||||
|
export interface OutsourceIssueLine {
|
||||||
|
id?: number; // 行编号
|
||||||
|
issueId?: number; // 发料单编号
|
||||||
|
itemId?: number; // 物料编号
|
||||||
|
itemCode?: string; // 物料编码
|
||||||
|
itemName?: string; // 物料名称
|
||||||
|
specification?: string; // 规格型号
|
||||||
|
unitMeasureName?: string; // 计量单位名称
|
||||||
|
quantity?: number; // 发料数量
|
||||||
|
materialStockId?: number; // 库存编号
|
||||||
|
batchId?: number; // 批次编号
|
||||||
|
batchCode?: string; // 批次编码
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单行分页 */
|
||||||
|
export function getOutsourceIssueLinePage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MesWmOutsourceIssueLineApi.OutsourceIssueLine>
|
||||||
|
>('/mes/wm/outsource-issue-line/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单行详情 */
|
||||||
|
export function getOutsourceIssueLine(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceIssueLineApi.OutsourceIssueLine>(
|
||||||
|
`/mes/wm/outsource-issue-line/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协发料单行 */
|
||||||
|
export function createOutsourceIssueLine(
|
||||||
|
data: MesWmOutsourceIssueLineApi.OutsourceIssueLine,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/mes/wm/outsource-issue-line/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协发料单行 */
|
||||||
|
export function updateOutsourceIssueLine(
|
||||||
|
data: MesWmOutsourceIssueLineApi.OutsourceIssueLine,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-issue-line/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协发料单行 */
|
||||||
|
export function deleteOutsourceIssueLine(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-issue-line/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceReceiptDetailApi {
|
||||||
|
/** MES 外协入库单明细 */
|
||||||
|
export interface OutsourceReceiptDetail {
|
||||||
|
id?: number; // 明细编号
|
||||||
|
lineId?: number; // 行编号
|
||||||
|
receiptId?: number; // 入库单编号
|
||||||
|
itemId?: number; // 物料编号
|
||||||
|
itemCode?: string; // 物料编码
|
||||||
|
itemName?: string; // 物料名称
|
||||||
|
specification?: string; // 规格型号
|
||||||
|
unitMeasureName?: string; // 计量单位名称
|
||||||
|
quantity?: number; // 上架数量
|
||||||
|
batchId?: number; // 批次编号
|
||||||
|
batchCode?: string; // 批次编码
|
||||||
|
warehouseId?: number; // 仓库编号
|
||||||
|
warehouseName?: string; // 仓库名称
|
||||||
|
locationId?: number; // 库区编号
|
||||||
|
locationName?: string; // 库区名称
|
||||||
|
areaId?: number; // 库位编号
|
||||||
|
areaName?: string; // 库位名称
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单明细列表 */
|
||||||
|
export function getOutsourceReceiptDetailListByLineId(lineId: number) {
|
||||||
|
return requestClient.get<
|
||||||
|
MesWmOutsourceReceiptDetailApi.OutsourceReceiptDetail[]
|
||||||
|
>('/mes/wm/outsource-receipt-detail/list-by-line', { params: { lineId } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单明细详情 */
|
||||||
|
export function getOutsourceReceiptDetail(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceReceiptDetailApi.OutsourceReceiptDetail>(
|
||||||
|
`/mes/wm/outsource-receipt-detail/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协入库单明细 */
|
||||||
|
export function createOutsourceReceiptDetail(
|
||||||
|
data: MesWmOutsourceReceiptDetailApi.OutsourceReceiptDetail,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/mes/wm/outsource-receipt-detail/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协入库单明细 */
|
||||||
|
export function updateOutsourceReceiptDetail(
|
||||||
|
data: MesWmOutsourceReceiptDetailApi.OutsourceReceiptDetail,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-receipt-detail/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协入库单明细 */
|
||||||
|
export function deleteOutsourceReceiptDetail(id: number) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/mes/wm/outsource-receipt-detail/delete?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceReceiptApi {
|
||||||
|
/** MES 外协入库单 */
|
||||||
|
export interface OutsourceReceipt {
|
||||||
|
id?: number; // 入库单编号
|
||||||
|
code?: string; // 入库单编码
|
||||||
|
name?: string; // 入库单名称
|
||||||
|
workOrderId?: number; // 外协工单编号
|
||||||
|
workOrderCode?: string; // 外协工单编码
|
||||||
|
vendorId?: number; // 供应商编号
|
||||||
|
vendorName?: string; // 供应商名称
|
||||||
|
receiptDate?: number; // 入库日期
|
||||||
|
status?: number; // 单据状态
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单分页 */
|
||||||
|
export function getOutsourceReceiptPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MesWmOutsourceReceiptApi.OutsourceReceipt>>(
|
||||||
|
'/mes/wm/outsource-receipt/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单详情 */
|
||||||
|
export function getOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceReceiptApi.OutsourceReceipt>(
|
||||||
|
`/mes/wm/outsource-receipt/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协入库单 */
|
||||||
|
export function createOutsourceReceipt(
|
||||||
|
data: MesWmOutsourceReceiptApi.OutsourceReceipt,
|
||||||
|
) {
|
||||||
|
return requestClient.post<number>('/mes/wm/outsource-receipt/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协入库单 */
|
||||||
|
export function updateOutsourceReceipt(
|
||||||
|
data: MesWmOutsourceReceiptApi.OutsourceReceipt,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-receipt/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协入库单 */
|
||||||
|
export function deleteOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-receipt/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交外协入库单 */
|
||||||
|
export function submitOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-receipt/submit?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行上架 */
|
||||||
|
export function stockOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-receipt/stock?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 完成入库 */
|
||||||
|
export function finishOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-receipt/finish?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消外协入库单 */
|
||||||
|
export function cancelOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-receipt/cancel?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出外协入库单 */
|
||||||
|
export function exportOutsourceReceipt(params: any) {
|
||||||
|
return requestClient.download('/mes/wm/outsource-receipt/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceReceiptLineApi {
|
||||||
|
/** MES 外协入库单行 */
|
||||||
|
export interface OutsourceReceiptLine {
|
||||||
|
id?: number; // 行编号
|
||||||
|
receiptId?: number; // 入库单编号
|
||||||
|
itemId?: number; // 物料编号
|
||||||
|
itemCode?: string; // 物料编码
|
||||||
|
itemName?: string; // 物料名称
|
||||||
|
specification?: string; // 规格型号
|
||||||
|
unitMeasureName?: string; // 计量单位名称
|
||||||
|
quantity?: number; // 入库数量
|
||||||
|
batchId?: number; // 批次编号
|
||||||
|
batchCode?: string; // 批次编码
|
||||||
|
productionDate?: number; // 生产日期
|
||||||
|
expireDate?: number; // 有效期
|
||||||
|
lotNumber?: string; // 生产批号
|
||||||
|
iqcCheckFlag?: boolean; // 是否需要质检
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单行分页 */
|
||||||
|
export function getOutsourceReceiptLinePage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MesWmOutsourceReceiptLineApi.OutsourceReceiptLine>
|
||||||
|
>('/mes/wm/outsource-receipt-line/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单行详情 */
|
||||||
|
export function getOutsourceReceiptLine(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceReceiptLineApi.OutsourceReceiptLine>(
|
||||||
|
`/mes/wm/outsource-receipt-line/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协入库单行 */
|
||||||
|
export function createOutsourceReceiptLine(
|
||||||
|
data: MesWmOutsourceReceiptLineApi.OutsourceReceiptLine,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/mes/wm/outsource-receipt-line/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协入库单行 */
|
||||||
|
export function updateOutsourceReceiptLine(
|
||||||
|
data: MesWmOutsourceReceiptLineApi.OutsourceReceiptLine,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-receipt-line/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协入库单行 */
|
||||||
|
export function deleteOutsourceReceiptLine(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-receipt-line/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -5,12 +5,24 @@ import { requestClient } from '#/api/request';
|
||||||
export namespace MesWmProductSalesApi {
|
export namespace MesWmProductSalesApi {
|
||||||
/** MES 销售出库单 */
|
/** MES 销售出库单 */
|
||||||
export interface ProductSales {
|
export interface ProductSales {
|
||||||
id?: number; // 销售出库单编号
|
id?: number; // 出库单编号
|
||||||
code?: string; // 出库单编号
|
code?: string; // 出库单编号
|
||||||
name?: string; // 出库单名称
|
name?: string; // 出库单名称
|
||||||
|
noticeId?: number; // 发货通知单编号
|
||||||
|
noticeCode?: string; // 发货通知单编码
|
||||||
|
clientId?: number; // 客户编号
|
||||||
|
clientCode?: string; // 客户编码
|
||||||
|
clientName?: string; // 客户名称
|
||||||
salesOrderCode?: string; // 销售订单编号
|
salesOrderCode?: string; // 销售订单编号
|
||||||
salesDate?: Date; // 出库日期
|
salesDate?: number; // 出库日期
|
||||||
|
contactName?: string; // 收货人
|
||||||
|
contactTelephone?: string; // 联系方式
|
||||||
|
contactAddress?: string; // 收货地址
|
||||||
|
carrier?: string; // 承运商
|
||||||
|
shippingNumber?: string; // 运输单号
|
||||||
status?: number; // 单据状态
|
status?: number; // 单据状态
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,3 +33,64 @@ export function getProductSalesPage(params: PageParam) {
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 查询销售出库单详情 */
|
||||||
|
export function getProductSales(id: number) {
|
||||||
|
return requestClient.get<MesWmProductSalesApi.ProductSales>(
|
||||||
|
`/mes/wm/product-sales/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增销售出库单 */
|
||||||
|
export function createProductSales(data: MesWmProductSalesApi.ProductSales) {
|
||||||
|
return requestClient.post<number>('/mes/wm/product-sales/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改销售出库单 */
|
||||||
|
export function updateProductSales(data: MesWmProductSalesApi.ProductSales) {
|
||||||
|
return requestClient.put('/mes/wm/product-sales/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除销售出库单 */
|
||||||
|
export function deleteProductSales(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/product-sales/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交销售出库单 */
|
||||||
|
export function submitProductSales(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/product-sales/submit?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行拣货 */
|
||||||
|
export function stockProductSales(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/product-sales/stock?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 填写运单 */
|
||||||
|
export function shippingProductSales(data: MesWmProductSalesApi.ProductSales) {
|
||||||
|
return requestClient.put('/mes/wm/product-sales/shipping', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行出库 */
|
||||||
|
export function finishProductSales(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/product-sales/finish?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消销售出库单 */
|
||||||
|
export function cancelProductSales(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/product-sales/cancel?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 校验销售出库单拣货数量是否与出库数量一致 */
|
||||||
|
export function checkProductSalesQuantity(id: number) {
|
||||||
|
return requestClient.get<boolean>(
|
||||||
|
`/mes/wm/product-sales/check-quantity?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出销售出库单 */
|
||||||
|
export function exportProductSales(params: any) {
|
||||||
|
return requestClient.download('/mes/wm/product-sales/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,19 @@ export namespace MesWmProductSalesLineApi {
|
||||||
/** MES 销售出库单行 */
|
/** MES 销售出库单行 */
|
||||||
export interface ProductSalesLine {
|
export interface ProductSalesLine {
|
||||||
id?: number; // 行编号
|
id?: number; // 行编号
|
||||||
|
salesId?: number; // 出库单编号
|
||||||
|
noticeLineId?: number; // 发货通知单行编号
|
||||||
itemId?: number; // 物料编号
|
itemId?: number; // 物料编号
|
||||||
itemCode?: string; // 物料编码
|
itemCode?: string; // 物料编码
|
||||||
itemName?: string; // 物料名称
|
itemName?: string; // 物料名称
|
||||||
specification?: string; // 规格型号
|
specification?: string; // 规格型号
|
||||||
unitMeasureName?: string; // 单位
|
unitMeasureName?: string; // 单位
|
||||||
quantity?: number; // 出库数量
|
quantity?: number; // 出库数量
|
||||||
|
pickedQuantity?: number; // 已拣货数量
|
||||||
|
batchId?: number; // 批次编号
|
||||||
batchCode?: string; // 批次号
|
batchCode?: string; // 批次号
|
||||||
|
oqcCheckFlag?: boolean; // 是否检验
|
||||||
|
remark?: string; // 备注
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,3 +28,29 @@ export function getProductSalesLinePage(params: PageParam) {
|
||||||
PageResult<MesWmProductSalesLineApi.ProductSalesLine>
|
PageResult<MesWmProductSalesLineApi.ProductSalesLine>
|
||||||
>('/mes/wm/product-sales-line/page', { params });
|
>('/mes/wm/product-sales-line/page', { params });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 查询销售出库单行详情 */
|
||||||
|
export function getProductSalesLine(id: number) {
|
||||||
|
return requestClient.get<MesWmProductSalesLineApi.ProductSalesLine>(
|
||||||
|
`/mes/wm/product-sales-line/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增销售出库单行 */
|
||||||
|
export function createProductSalesLine(
|
||||||
|
data: MesWmProductSalesLineApi.ProductSalesLine,
|
||||||
|
) {
|
||||||
|
return requestClient.post<number>('/mes/wm/product-sales-line/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改销售出库单行 */
|
||||||
|
export function updateProductSalesLine(
|
||||||
|
data: MesWmProductSalesLineApi.ProductSalesLine,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/product-sales-line/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除销售出库单行 */
|
||||||
|
export function deleteProductSalesLine(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/product-sales-line/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as ProCardSelectDialog } from './pro-card-select-dialog.vue';
|
||||||
|
export { default as ProCardSelect } from './pro-card-select.vue';
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MesProCardApi } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
|
import { Button, message, Modal } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getCardPage } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import { useCardSelectGridColumns, useCardSelectGridFormSchema } from '../data';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
selected: [rows: MesProCardApi.Card[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const open = ref(false); // 弹窗是否打开
|
||||||
|
const multiple = ref(false); // 是否多选;默认按单选选择器使用
|
||||||
|
const selectedRows = ref<MesProCardApi.Card[]>([]); // 已选流转卡列表
|
||||||
|
const preSelectedIds = ref<number[]>([]); // 预选流转卡编号列表
|
||||||
|
|
||||||
|
/** 获取多选记录,包含 VXE reserve 跨页记录 */
|
||||||
|
function getMultipleSelectedRows() {
|
||||||
|
const selectedMap = new Map<number, MesProCardApi.Card>();
|
||||||
|
const records = [
|
||||||
|
...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
|
||||||
|
...(gridApi.grid.getCheckboxRecords?.() ?? []),
|
||||||
|
] as MesProCardApi.Card[];
|
||||||
|
records.forEach((row) => {
|
||||||
|
const rowId = row.id;
|
||||||
|
if (rowId !== undefined) {
|
||||||
|
selectedMap.set(rowId, row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return [...selectedMap.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理多选勾选变化 */
|
||||||
|
function handleCheckboxSelectChange() {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理单选切换 */
|
||||||
|
function handleRadioChange(row: MesProCardApi.Card) {
|
||||||
|
selectedRows.value = [row];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选模式下切换行勾选 */
|
||||||
|
async function toggleMultipleRow(row: MesProCardApi.Card) {
|
||||||
|
const selected = gridApi.grid.isCheckedByCheckboxRow(row);
|
||||||
|
await gridApi.grid.setCheckboxRow(row, !selected);
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理行双击:单选直接确认,多选切换勾选 */
|
||||||
|
async function handleCellDblclick({ row }: { row: MesProCardApi.Card }) {
|
||||||
|
if (multiple.value) {
|
||||||
|
await toggleMultipleRow(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedRows.value = [row];
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
handleConfirm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 回显预选流转卡 */
|
||||||
|
async function applyPreSelection() {
|
||||||
|
if (preSelectedIds.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rows = gridApi.grid.getData() as MesProCardApi.Card[];
|
||||||
|
for (const row of rows) {
|
||||||
|
if (row.id === undefined || !preSelectedIds.value.includes(row.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
await gridApi.grid.setCheckboxRow(row, true);
|
||||||
|
} else {
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
selectedRows.value = [row];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useCardSelectGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useCardSelectGridColumns(false),
|
||||||
|
height: 520,
|
||||||
|
keepSource: true,
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
range: true,
|
||||||
|
reserve: true,
|
||||||
|
},
|
||||||
|
radioConfig: {
|
||||||
|
highlight: true,
|
||||||
|
trigger: 'row',
|
||||||
|
},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getCardPage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<MesProCardApi.Card>,
|
||||||
|
gridEvents: {
|
||||||
|
cellDblclick: handleCellDblclick,
|
||||||
|
checkboxAll: handleCheckboxSelectChange,
|
||||||
|
checkboxChange: handleCheckboxSelectChange,
|
||||||
|
radioChange: ({ row }: { row: MesProCardApi.Card }) => {
|
||||||
|
handleRadioChange(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 重置查询和选择状态 */
|
||||||
|
async function resetQueryState() {
|
||||||
|
selectedRows.value = [];
|
||||||
|
await gridApi.grid.clearCheckboxRow();
|
||||||
|
await gridApi.grid.clearCheckboxReserve();
|
||||||
|
await gridApi.grid.clearRadioRow();
|
||||||
|
await gridApi.formApi.resetForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开流转卡选择弹窗 */
|
||||||
|
async function openModal(
|
||||||
|
selectedIds?: number[],
|
||||||
|
options?: { multiple?: boolean },
|
||||||
|
) {
|
||||||
|
open.value = true;
|
||||||
|
multiple.value = options?.multiple ?? false;
|
||||||
|
preSelectedIds.value = selectedIds || [];
|
||||||
|
await nextTick();
|
||||||
|
gridApi.setGridOptions({
|
||||||
|
columns: useCardSelectGridColumns(multiple.value),
|
||||||
|
});
|
||||||
|
await resetQueryState();
|
||||||
|
await gridApi.query();
|
||||||
|
await nextTick();
|
||||||
|
await applyPreSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭流转卡选择弹窗 */
|
||||||
|
function closeModal() {
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认选择流转卡 */
|
||||||
|
function handleConfirm() {
|
||||||
|
const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value;
|
||||||
|
if (rows.length === 0) {
|
||||||
|
message.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('selected', multiple.value ? rows : [rows[0]!]);
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open: openModal });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
v-model:open="open"
|
||||||
|
title="流转卡选择"
|
||||||
|
width="70%"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@ok="handleConfirm"
|
||||||
|
@cancel="closeModal"
|
||||||
|
>
|
||||||
|
<Grid table-title="流转卡列表" />
|
||||||
|
<template #footer>
|
||||||
|
<Button @click="closeModal">取消</Button>
|
||||||
|
<Button type="primary" @click="handleConfirm">确定</Button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { MesProCardApi } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import { computed, ref, useAttrs, watch } from 'vue';
|
||||||
|
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { Input, Tooltip } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getCard } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import ProCardSelectDialog from './pro-card-select-dialog.vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'ProCardSelect', inheritAttrs: false });
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
allowClear?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
modelValue?: number;
|
||||||
|
placeholder?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
allowClear: true,
|
||||||
|
disabled: false,
|
||||||
|
modelValue: undefined,
|
||||||
|
placeholder: '请选择流转卡',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [item: MesProCardApi.Card | undefined];
|
||||||
|
'update:modelValue': [value: number | undefined];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
const dialogRef = ref<InstanceType<typeof ProCardSelectDialog>>();
|
||||||
|
const hovering = ref(false);
|
||||||
|
const selectedItem = ref<MesProCardApi.Card>();
|
||||||
|
|
||||||
|
const displayLabel = computed(() => selectedItem.value?.code ?? '');
|
||||||
|
|
||||||
|
const showClear = computed(
|
||||||
|
() =>
|
||||||
|
props.allowClear &&
|
||||||
|
!props.disabled &&
|
||||||
|
hovering.value &&
|
||||||
|
props.modelValue != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 根据编号单条查询流转卡信息(用于编辑回显) */
|
||||||
|
async function resolveItemById(id: number | undefined) {
|
||||||
|
if (id == null) {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedItem.value?.id === id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = await getCard(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.modelValue, resolveItemById, { immediate: true });
|
||||||
|
|
||||||
|
/** 清空已选流转卡 */
|
||||||
|
function clearSelected() {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
emit('update:modelValue', undefined);
|
||||||
|
emit('change', undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开流转卡选择弹窗 */
|
||||||
|
function handleClick(event: MouseEvent) {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
if (showClear.value && target.closest('.ant-input-suffix')) {
|
||||||
|
event.stopPropagation();
|
||||||
|
clearSelected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectedIds = props.modelValue == null ? [] : [props.modelValue];
|
||||||
|
dialogRef.value?.open(selectedIds, { multiple: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 弹窗选中回调 */
|
||||||
|
function handleSelected(rows: MesProCardApi.Card[]) {
|
||||||
|
const item = rows[0];
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = item;
|
||||||
|
emit('update:modelValue', item.id);
|
||||||
|
emit('change', item);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-bind="attrs"
|
||||||
|
class="w-full"
|
||||||
|
:class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
|
||||||
|
@click="handleClick"
|
||||||
|
@mouseenter="hovering = true"
|
||||||
|
@mouseleave="hovering = false"
|
||||||
|
>
|
||||||
|
<Tooltip :mouse-enter-delay="0.5" :open="selectedItem ? undefined : false">
|
||||||
|
<template #title>
|
||||||
|
<div v-if="selectedItem" class="leading-6">
|
||||||
|
<div>编号:{{ selectedItem.code || '-' }}</div>
|
||||||
|
<div>工单:{{ selectedItem.workOrderCode || '-' }}</div>
|
||||||
|
<div>批次:{{ selectedItem.batchCode || '-' }}</div>
|
||||||
|
<div>产品:{{ selectedItem.itemName || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<Input
|
||||||
|
:disabled="disabled"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:value="displayLabel"
|
||||||
|
readonly
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<IconifyIcon
|
||||||
|
class="size-4"
|
||||||
|
:icon="showClear ? 'lucide:circle-x' : 'lucide:search'"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Input>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<ProCardSelectDialog ref="dialogRef" @selected="handleSelected" />
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MesProCardApi } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import { markRaw } from 'vue';
|
||||||
|
|
||||||
|
import { MdItemSelect } from '#/views/mes/md/item/components';
|
||||||
|
import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components';
|
||||||
|
|
||||||
|
/** 流转卡选择弹窗的搜索表单 */
|
||||||
|
export function useCardSelectGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'code',
|
||||||
|
label: '流转卡编号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入流转卡编号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'workOrderId',
|
||||||
|
label: '生产工单',
|
||||||
|
component: markRaw(ProWorkOrderSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择生产工单',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'itemId',
|
||||||
|
label: '产品物料',
|
||||||
|
component: markRaw(MdItemSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择产品物料',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'batchCode',
|
||||||
|
label: '批次号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入批次号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 流转卡选择弹窗的字段 */
|
||||||
|
export function useCardSelectGridColumns(
|
||||||
|
multiple = false,
|
||||||
|
): VxeTableGridOptions<MesProCardApi.Card>['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: multiple ? 'checkbox' : 'radio',
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'code',
|
||||||
|
title: '流转卡编号',
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'workOrderCode',
|
||||||
|
title: '生产工单编号',
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemCode',
|
||||||
|
title: '产品物料编码',
|
||||||
|
width: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'batchCode',
|
||||||
|
title: '批次号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemName',
|
||||||
|
title: '产品物料名称',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'specification',
|
||||||
|
title: '规格型号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'unitMeasureName',
|
||||||
|
title: '单位',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'transferedQuantity',
|
||||||
|
title: '流转数量',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -151,11 +151,22 @@ export const MesAutoCodeRuleCode = {
|
||||||
TM_TOOL_CODE: 'TM_TOOL_CODE',
|
TM_TOOL_CODE: 'TM_TOOL_CODE',
|
||||||
WM_AREA_CODE: 'WM_AREA_CODE',
|
WM_AREA_CODE: 'WM_AREA_CODE',
|
||||||
WM_LOCATION_CODE: 'WM_LOCATION_CODE',
|
WM_LOCATION_CODE: 'WM_LOCATION_CODE',
|
||||||
|
WM_ARRIVAL_NOTICE_CODE: 'WM_ARRIVAL_NOTICE_CODE',
|
||||||
|
WM_ITEM_RECEIPT_CODE: 'WM_ITEM_RECEIPT_CODE',
|
||||||
|
WM_RETURN_VENDOR_CODE: 'WM_RETURN_VENDOR_CODE',
|
||||||
|
WM_SALES_NOTICE_CODE: 'WM_SALES_NOTICE_CODE',
|
||||||
|
WM_RETURN_SALES_CODE: 'WM_RETURN_SALES_CODE',
|
||||||
|
WM_RETURN_ISSUE_CODE: 'WM_RETURN_ISSUE_CODE',
|
||||||
|
WM_PRODUCT_ISSUE_CODE: 'WM_PRODUCT_ISSUE_CODE',
|
||||||
|
WM_PRODUCT_SALES_CODE: 'WM_PRODUCT_SALES_CODE',
|
||||||
|
PRODUCTRECPT_CODE: 'PRODUCTRECPT_CODE',
|
||||||
WM_MISC_ISSUE_CODE: 'WM_MISC_ISSUE_CODE',
|
WM_MISC_ISSUE_CODE: 'WM_MISC_ISSUE_CODE',
|
||||||
WM_MISC_RECEIPT_CODE: 'WM_MISC_RECEIPT_CODE',
|
WM_MISC_RECEIPT_CODE: 'WM_MISC_RECEIPT_CODE',
|
||||||
WM_OUTSOURCE_ISSUE_CODE: 'WM_OUTSOURCE_ISSUE_CODE',
|
WM_OUTSOURCE_ISSUE_CODE: 'WM_OUTSOURCE_ISSUE_CODE',
|
||||||
WM_OUTSOURCE_RECEIPT_CODE: 'WM_OUTSOURCE_RECEIPT_CODE',
|
WM_OUTSOURCE_RECEIPT_CODE: 'WM_OUTSOURCE_RECEIPT_CODE',
|
||||||
WM_PACKAGE_CODE: 'WM_PACKAGE_CODE',
|
WM_PACKAGE_CODE: 'WM_PACKAGE_CODE',
|
||||||
|
WM_STOCK_TAKING_CODE: 'WM_STOCK_TAKING_CODE',
|
||||||
|
WM_STOCK_TAKING_PLAN_CODE: 'WM_STOCK_TAKING_PLAN_CODE',
|
||||||
WM_WAREHOUSE_CODE: 'WM_WAREHOUSE_CODE',
|
WM_WAREHOUSE_CODE: 'WM_WAREHOUSE_CODE',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|
@ -165,6 +176,38 @@ export const MesWmPackageStatusEnum = {
|
||||||
FINISHED: MesOrderStatusConstants.FINISHED,
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
/** MES 盘点类型枚举 */
|
||||||
|
export const MesWmStockTakingTypeEnum = {
|
||||||
|
STATIC: 1,
|
||||||
|
DYNAMIC: 2,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 盘点任务状态枚举 */
|
||||||
|
export const MesWmStockTakingTaskStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 盘点任务行状态枚举 */
|
||||||
|
export const MesWmStockTakingTaskLineStatusEnum = {
|
||||||
|
UNCOUNTED: 0,
|
||||||
|
NORMAL: 1,
|
||||||
|
GAIN: 2,
|
||||||
|
LOSS: 3,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 盘点方案参数类型枚举 */
|
||||||
|
export const MesWmStockTakingParamTypeEnum = {
|
||||||
|
WAREHOUSE: 102,
|
||||||
|
LOCATION: 103,
|
||||||
|
AREA: 104,
|
||||||
|
BATCH: 107,
|
||||||
|
ITEM: 600,
|
||||||
|
QUALITY_STATUS: 900,
|
||||||
|
} as const;
|
||||||
|
|
||||||
/** MES 生产工单状态枚举 */
|
/** MES 生产工单状态枚举 */
|
||||||
export const MesProWorkOrderStatusEnum = {
|
export const MesProWorkOrderStatusEnum = {
|
||||||
PREPARE: MesOrderStatusConstants.DRAFT,
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
|
@ -263,6 +306,87 @@ export const MesWmOutsourceReceiptStatusEnum = {
|
||||||
CANCELED: MesOrderStatusConstants.CANCELLED,
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
/** MES 到货通知单状态枚举 */
|
||||||
|
export const MesWmArrivalNoticeStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
PENDING_QC: MesOrderStatusConstants.APPROVING,
|
||||||
|
PENDING_RECEIPT: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 采购入库单状态枚举 */
|
||||||
|
export const MesWmItemReceiptStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 供应商退货单状态枚举 */
|
||||||
|
export const MesWmReturnVendorStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 发货通知单状态枚举 */
|
||||||
|
export const MesWmSalesNoticeStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 销售退货单状态枚举 */
|
||||||
|
export const MesWmReturnSalesStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
CONFIRMED: MesOrderStatusConstants.CONFIRMED,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 生产退料单状态枚举 */
|
||||||
|
export const MesWmReturnIssueStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
CONFIRMED: MesOrderStatusConstants.CONFIRMED,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 领料出库单状态枚举 */
|
||||||
|
export const MesWmProductIssueStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 产品入库单状态枚举 */
|
||||||
|
export const MesWmProductReceiptStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 销售出库单状态枚举 */
|
||||||
|
export const MesWmProductSalesStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
CONFIRMED: MesOrderStatusConstants.CONFIRMED,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
SHIPPING: 10, // 待填写运单
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
/** MES 质检结果值类型枚举 */
|
/** MES 质检结果值类型枚举 */
|
||||||
export const MesQcResultValueType = {
|
export const MesQcResultValueType = {
|
||||||
FLOAT: 1,
|
FLOAT: 1,
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,12 @@ import MdItemSelect from '#/views/mes/md/item/components/md-item-select.vue';
|
||||||
import MdVendorSelect from '#/views/mes/md/vendor/components/md-vendor-select.vue';
|
import MdVendorSelect from '#/views/mes/md/vendor/components/md-vendor-select.vue';
|
||||||
import MdWorkshopSelect from '#/views/mes/md/workstation/components/md-workshop-select.vue';
|
import MdWorkshopSelect from '#/views/mes/md/workstation/components/md-workshop-select.vue';
|
||||||
import MdWorkstationSelect from '#/views/mes/md/workstation/components/md-workstation-select.vue';
|
import MdWorkstationSelect from '#/views/mes/md/workstation/components/md-workstation-select.vue';
|
||||||
|
import { ProCardSelect } from '#/views/mes/pro/card/components';
|
||||||
import ProWorkOrderSelect from '#/views/mes/pro/workorder/components/pro-work-order-select.vue';
|
import ProWorkOrderSelect from '#/views/mes/pro/workorder/components/pro-work-order-select.vue';
|
||||||
import TmToolSelect from '#/views/mes/tm/tool/components/tm-tool-select.vue';
|
import TmToolSelect from '#/views/mes/tm/tool/components/tm-tool-select.vue';
|
||||||
import { BarcodeBizTypeEnum } from '#/views/mes/utils/constants';
|
import { BarcodeBizTypeEnum } from '#/views/mes/utils/constants';
|
||||||
|
import { WmBatchSelect } from '#/views/mes/wm/batch/components';
|
||||||
|
import { UserSelect } from '#/views/system/user/components';
|
||||||
|
|
||||||
import WmMaterialStockSelect from './../materialstock/components/wm-material-stock-select.vue';
|
import WmMaterialStockSelect from './../materialstock/components/wm-material-stock-select.vue';
|
||||||
import { WmPackageSelect } from './../packages/components';
|
import { WmPackageSelect } from './../packages/components';
|
||||||
|
|
@ -51,15 +54,31 @@ async function syncBizDetail(
|
||||||
}
|
}
|
||||||
let bizCode: string | undefined;
|
let bizCode: string | undefined;
|
||||||
let bizName: string | undefined;
|
let bizName: string | undefined;
|
||||||
if (bizType === BarcodeBizTypeEnum.STOCK) {
|
switch (bizType) {
|
||||||
bizCode = item.itemCode;
|
case BarcodeBizTypeEnum.BATCH: {
|
||||||
bizName = item.itemName;
|
bizCode = item.code;
|
||||||
} else if (bizType === BarcodeBizTypeEnum.PACKAGE) {
|
bizName = item.itemName || item.code;
|
||||||
bizCode = item.code;
|
break;
|
||||||
bizName = item.clientName || item.code;
|
}
|
||||||
} else {
|
case BarcodeBizTypeEnum.PACKAGE: {
|
||||||
bizCode = item.code || item.username;
|
bizCode = item.code;
|
||||||
bizName = item.name || item.nickname;
|
bizName = item.clientName || item.code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BarcodeBizTypeEnum.PROCARD: {
|
||||||
|
bizCode = item.code;
|
||||||
|
bizName = item.workOrderName || item.code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BarcodeBizTypeEnum.STOCK: {
|
||||||
|
bizCode = item.itemCode;
|
||||||
|
bizName = item.itemName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
bizCode = item.code || item.username;
|
||||||
|
bizName = item.name || item.nickname;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 先回填业务编码、名称并清空旧条码内容
|
// 先回填业务编码、名称并清空旧条码内容
|
||||||
await formApi.setValues({ bizCode, bizName, content: undefined });
|
await formApi.setValues({ bizCode, bizName, content: undefined });
|
||||||
|
|
@ -328,6 +347,45 @@ export function useFormSchema(formApi?: VbenFormApi): VbenFormSchema[] {
|
||||||
},
|
},
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'bizId',
|
||||||
|
label: '批次',
|
||||||
|
component: markRaw(WmBatchSelect),
|
||||||
|
componentProps: {
|
||||||
|
onChange: (item: any) => syncBizDetail(formApi, item),
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['bizType'],
|
||||||
|
show: (values) => values.bizType === BarcodeBizTypeEnum.BATCH,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'bizId',
|
||||||
|
label: '流转卡',
|
||||||
|
component: markRaw(ProCardSelect),
|
||||||
|
componentProps: {
|
||||||
|
onChange: (item: any) => syncBizDetail(formApi, item),
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['bizType'],
|
||||||
|
show: (values) => values.bizType === BarcodeBizTypeEnum.PROCARD,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'bizId',
|
||||||
|
label: '人员',
|
||||||
|
component: markRaw(UserSelect),
|
||||||
|
componentProps: {
|
||||||
|
onChange: (item: any) => syncBizDetail(formApi, item),
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['bizType'],
|
||||||
|
show: (values) => values.bizType === BarcodeBizTypeEnum.USER,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'bizId',
|
fieldName: 'bizId',
|
||||||
label: '业务编号',
|
label: '业务编号',
|
||||||
|
|
@ -343,13 +401,16 @@ export function useFormSchema(formApi?: VbenFormApi): VbenFormSchema[] {
|
||||||
values.bizType !== undefined &&
|
values.bizType !== undefined &&
|
||||||
![
|
![
|
||||||
BarcodeBizTypeEnum.AREA,
|
BarcodeBizTypeEnum.AREA,
|
||||||
|
BarcodeBizTypeEnum.BATCH,
|
||||||
BarcodeBizTypeEnum.CLIENT,
|
BarcodeBizTypeEnum.CLIENT,
|
||||||
BarcodeBizTypeEnum.ITEM,
|
BarcodeBizTypeEnum.ITEM,
|
||||||
BarcodeBizTypeEnum.LOCATION,
|
BarcodeBizTypeEnum.LOCATION,
|
||||||
BarcodeBizTypeEnum.MACHINERY,
|
BarcodeBizTypeEnum.MACHINERY,
|
||||||
BarcodeBizTypeEnum.PACKAGE,
|
BarcodeBizTypeEnum.PACKAGE,
|
||||||
|
BarcodeBizTypeEnum.PROCARD,
|
||||||
BarcodeBizTypeEnum.STOCK,
|
BarcodeBizTypeEnum.STOCK,
|
||||||
BarcodeBizTypeEnum.TOOL,
|
BarcodeBizTypeEnum.TOOL,
|
||||||
|
BarcodeBizTypeEnum.USER,
|
||||||
BarcodeBizTypeEnum.VENDOR,
|
BarcodeBizTypeEnum.VENDOR,
|
||||||
BarcodeBizTypeEnum.WAREHOUSE,
|
BarcodeBizTypeEnum.WAREHOUSE,
|
||||||
BarcodeBizTypeEnum.WORKORDER,
|
BarcodeBizTypeEnum.WORKORDER,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as WmBatchSelectDialog } from './wm-batch-select-dialog.vue';
|
||||||
|
export { default as WmBatchSelect } from './wm-batch-select.vue';
|
||||||
|
|
@ -0,0 +1,248 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MesWmBatchApi } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import { computed, nextTick, ref } from 'vue';
|
||||||
|
|
||||||
|
import { Alert, Button, message, Modal } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getBatchPage } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import { useBatchSelectGridColumns, useBatchSelectGridFormSchema } from '../data';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
selected: [rows: MesWmBatchApi.Batch[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const open = ref(false); // 弹窗是否打开
|
||||||
|
const multiple = ref(false); // 是否多选;默认按单选选择器使用
|
||||||
|
const selectedRows = ref<MesWmBatchApi.Batch[]>([]); // 已选批次列表
|
||||||
|
const preSelectedIds = ref<number[]>([]); // 预选批次编号列表
|
||||||
|
const externalItemId = ref<number>(); // 外部传入的默认物料过滤
|
||||||
|
const externalClientId = ref<number>(); // 外部传入的默认客户过滤
|
||||||
|
const externalVendorId = ref<number>(); // 外部传入的默认供应商过滤
|
||||||
|
const externalSalesOrderCode = ref<string>(); // 外部传入的默认销售订单过滤
|
||||||
|
|
||||||
|
const filterTip = computed(() => {
|
||||||
|
const parts: string[] = [];
|
||||||
|
if (externalClientId.value != null) {
|
||||||
|
parts.push('客户');
|
||||||
|
}
|
||||||
|
if (externalVendorId.value != null) {
|
||||||
|
parts.push('供应商');
|
||||||
|
}
|
||||||
|
if (externalSalesOrderCode.value != null) {
|
||||||
|
parts.push('销售订单');
|
||||||
|
}
|
||||||
|
return parts.length > 0 ? `已按${parts.join('/')}预过滤` : '';
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 获取多选记录,包含 VXE reserve 跨页记录 */
|
||||||
|
function getMultipleSelectedRows() {
|
||||||
|
const selectedMap = new Map<number, MesWmBatchApi.Batch>();
|
||||||
|
const records = [
|
||||||
|
...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
|
||||||
|
...(gridApi.grid.getCheckboxRecords?.() ?? []),
|
||||||
|
] as MesWmBatchApi.Batch[];
|
||||||
|
records.forEach((row) => {
|
||||||
|
const rowId = row.id;
|
||||||
|
if (rowId !== undefined) {
|
||||||
|
selectedMap.set(rowId, row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return [...selectedMap.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理多选勾选变化 */
|
||||||
|
function handleCheckboxSelectChange() {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理单选切换 */
|
||||||
|
function handleRadioChange(row: MesWmBatchApi.Batch) {
|
||||||
|
selectedRows.value = [row];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选模式下切换行勾选 */
|
||||||
|
async function toggleMultipleRow(row: MesWmBatchApi.Batch) {
|
||||||
|
const selected = gridApi.grid.isCheckedByCheckboxRow(row);
|
||||||
|
await gridApi.grid.setCheckboxRow(row, !selected);
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理行双击:单选直接确认,多选切换勾选 */
|
||||||
|
async function handleCellDblclick({ row }: { row: MesWmBatchApi.Batch }) {
|
||||||
|
if (multiple.value) {
|
||||||
|
await toggleMultipleRow(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedRows.value = [row];
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
handleConfirm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 回显预选批次 */
|
||||||
|
async function applyPreSelection() {
|
||||||
|
if (preSelectedIds.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rows = gridApi.grid.getData() as MesWmBatchApi.Batch[];
|
||||||
|
for (const row of rows) {
|
||||||
|
if (row.id === undefined || !preSelectedIds.value.includes(row.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
await gridApi.grid.setCheckboxRow(row, true);
|
||||||
|
} else {
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
selectedRows.value = [row];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useBatchSelectGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useBatchSelectGridColumns(false),
|
||||||
|
height: 520,
|
||||||
|
keepSource: true,
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
range: true,
|
||||||
|
reserve: true,
|
||||||
|
},
|
||||||
|
radioConfig: {
|
||||||
|
highlight: true,
|
||||||
|
trigger: 'row',
|
||||||
|
},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getBatchPage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<MesWmBatchApi.Batch>,
|
||||||
|
gridEvents: {
|
||||||
|
cellDblclick: handleCellDblclick,
|
||||||
|
checkboxAll: handleCheckboxSelectChange,
|
||||||
|
checkboxChange: handleCheckboxSelectChange,
|
||||||
|
radioChange: ({ row }: { row: MesWmBatchApi.Batch }) => {
|
||||||
|
handleRadioChange(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 重置查询和选择状态,保留外部传入的默认过滤 */
|
||||||
|
async function resetQueryState() {
|
||||||
|
selectedRows.value = [];
|
||||||
|
await gridApi.grid.clearCheckboxRow();
|
||||||
|
await gridApi.grid.clearCheckboxReserve();
|
||||||
|
await gridApi.grid.clearRadioRow();
|
||||||
|
await gridApi.formApi.resetForm();
|
||||||
|
if (externalItemId.value) {
|
||||||
|
await gridApi.formApi.setFieldValue('itemId', externalItemId.value);
|
||||||
|
}
|
||||||
|
if (externalClientId.value) {
|
||||||
|
await gridApi.formApi.setFieldValue('clientId', externalClientId.value);
|
||||||
|
}
|
||||||
|
if (externalVendorId.value) {
|
||||||
|
await gridApi.formApi.setFieldValue('vendorId', externalVendorId.value);
|
||||||
|
}
|
||||||
|
if (externalSalesOrderCode.value) {
|
||||||
|
await gridApi.formApi.setFieldValue(
|
||||||
|
'salesOrderCode',
|
||||||
|
externalSalesOrderCode.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开批次选择弹窗 */
|
||||||
|
async function openModal(
|
||||||
|
selectedIds?: number[],
|
||||||
|
options?: {
|
||||||
|
clientId?: number;
|
||||||
|
itemId?: number;
|
||||||
|
multiple?: boolean;
|
||||||
|
salesOrderCode?: string;
|
||||||
|
vendorId?: number;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
open.value = true;
|
||||||
|
multiple.value = options?.multiple ?? false;
|
||||||
|
preSelectedIds.value = selectedIds || [];
|
||||||
|
externalItemId.value = options?.itemId;
|
||||||
|
externalClientId.value = options?.clientId;
|
||||||
|
externalVendorId.value = options?.vendorId;
|
||||||
|
externalSalesOrderCode.value = options?.salesOrderCode;
|
||||||
|
await nextTick();
|
||||||
|
gridApi.setGridOptions({
|
||||||
|
columns: useBatchSelectGridColumns(multiple.value),
|
||||||
|
});
|
||||||
|
await resetQueryState();
|
||||||
|
await gridApi.query();
|
||||||
|
await nextTick();
|
||||||
|
await applyPreSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭批次选择弹窗 */
|
||||||
|
function closeModal() {
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认选择批次 */
|
||||||
|
function handleConfirm() {
|
||||||
|
const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value;
|
||||||
|
if (rows.length === 0) {
|
||||||
|
message.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('selected', multiple.value ? rows : [rows[0]!]);
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open: openModal });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
v-model:open="open"
|
||||||
|
title="批次选择"
|
||||||
|
width="80%"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@ok="handleConfirm"
|
||||||
|
@cancel="closeModal"
|
||||||
|
>
|
||||||
|
<Alert
|
||||||
|
v-if="filterTip"
|
||||||
|
:message="filterTip"
|
||||||
|
type="info"
|
||||||
|
show-icon
|
||||||
|
class="!mb-3"
|
||||||
|
/>
|
||||||
|
<Grid table-title="批次列表" />
|
||||||
|
<template #footer>
|
||||||
|
<Button @click="closeModal">取消</Button>
|
||||||
|
<Button type="primary" @click="handleConfirm">确定</Button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { MesWmBatchApi } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import { computed, ref, useAttrs, watch } from 'vue';
|
||||||
|
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { Input, Tooltip } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getBatch } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import WmBatchSelectDialog from './wm-batch-select-dialog.vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'WmBatchSelect', inheritAttrs: false });
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
allowClear?: boolean;
|
||||||
|
clientId?: number; // 默认过滤的客户 ID
|
||||||
|
disabled?: boolean;
|
||||||
|
itemId?: number; // 默认过滤的物料 ID
|
||||||
|
modelValue?: number;
|
||||||
|
placeholder?: string;
|
||||||
|
salesOrderCode?: string; // 默认过滤的销售订单编号
|
||||||
|
vendorId?: number; // 默认过滤的供应商 ID
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
allowClear: true,
|
||||||
|
clientId: undefined,
|
||||||
|
disabled: false,
|
||||||
|
itemId: undefined,
|
||||||
|
modelValue: undefined,
|
||||||
|
placeholder: '请选择批次',
|
||||||
|
salesOrderCode: undefined,
|
||||||
|
vendorId: undefined,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [item: MesWmBatchApi.Batch | undefined];
|
||||||
|
'update:modelValue': [value: number | undefined];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
const dialogRef = ref<InstanceType<typeof WmBatchSelectDialog>>();
|
||||||
|
const hovering = ref(false);
|
||||||
|
const selectedItem = ref<MesWmBatchApi.Batch>();
|
||||||
|
|
||||||
|
const displayLabel = computed(() => selectedItem.value?.code ?? '');
|
||||||
|
|
||||||
|
const showClear = computed(
|
||||||
|
() =>
|
||||||
|
props.allowClear &&
|
||||||
|
!props.disabled &&
|
||||||
|
hovering.value &&
|
||||||
|
props.modelValue != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 根据编号单条查询批次信息(用于编辑回显) */
|
||||||
|
async function resolveItemById(id: number | undefined) {
|
||||||
|
if (id == null) {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedItem.value?.id === id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = await getBatch(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.modelValue, resolveItemById, { immediate: true });
|
||||||
|
|
||||||
|
/** 清空已选批次 */
|
||||||
|
function clearSelected() {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
emit('update:modelValue', undefined);
|
||||||
|
emit('change', undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开批次选择弹窗 */
|
||||||
|
function handleClick(event: MouseEvent) {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
if (showClear.value && target.closest('.ant-input-suffix')) {
|
||||||
|
event.stopPropagation();
|
||||||
|
clearSelected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectedIds = props.modelValue == null ? [] : [props.modelValue];
|
||||||
|
dialogRef.value?.open(selectedIds, {
|
||||||
|
clientId: props.clientId,
|
||||||
|
itemId: props.itemId,
|
||||||
|
multiple: false,
|
||||||
|
salesOrderCode: props.salesOrderCode,
|
||||||
|
vendorId: props.vendorId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 弹窗选中回调 */
|
||||||
|
function handleSelected(rows: MesWmBatchApi.Batch[]) {
|
||||||
|
const item = rows[0];
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = item;
|
||||||
|
emit('update:modelValue', item.id);
|
||||||
|
emit('change', item);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-bind="attrs"
|
||||||
|
class="w-full"
|
||||||
|
:class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
|
||||||
|
@click="handleClick"
|
||||||
|
@mouseenter="hovering = true"
|
||||||
|
@mouseleave="hovering = false"
|
||||||
|
>
|
||||||
|
<Tooltip :mouse-enter-delay="0.5" :open="selectedItem ? undefined : false">
|
||||||
|
<template #title>
|
||||||
|
<div v-if="selectedItem" class="leading-6">
|
||||||
|
<div>批次编号:{{ selectedItem.code || '-' }}</div>
|
||||||
|
<div>物料编码:{{ selectedItem.itemCode || '-' }}</div>
|
||||||
|
<div>物料名称:{{ selectedItem.itemName || '-' }}</div>
|
||||||
|
<div>生产批号:{{ selectedItem.lotNumber || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<Input
|
||||||
|
:disabled="disabled"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:value="displayLabel"
|
||||||
|
readonly
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<IconifyIcon
|
||||||
|
class="size-4"
|
||||||
|
:icon="showClear ? 'lucide:circle-x' : 'lucide:search'"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Input>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<WmBatchSelectDialog ref="dialogRef" @selected="handleSelected" />
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MesWmBatchApi } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import { markRaw } from 'vue';
|
||||||
|
|
||||||
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
||||||
|
import MdClientSelect from '#/views/mes/md/client/components/md-client-select.vue';
|
||||||
|
import MdItemSelect from '#/views/mes/md/item/components/md-item-select.vue';
|
||||||
|
import MdVendorSelect from '#/views/mes/md/vendor/components/md-vendor-select.vue';
|
||||||
|
import { MdWorkstationSelect } from '#/views/mes/md/workstation/components';
|
||||||
|
import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components';
|
||||||
|
import { TmToolSelect } from '#/views/mes/tm/tool/components';
|
||||||
|
|
||||||
|
/** 批次选择弹窗的搜索表单 */
|
||||||
|
export function useBatchSelectGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'code',
|
||||||
|
label: '批次编号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入批次编号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'itemId',
|
||||||
|
label: '产品物料',
|
||||||
|
component: markRaw(MdItemSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择产品物料',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'vendorId',
|
||||||
|
label: '供应商',
|
||||||
|
component: markRaw(MdVendorSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择供应商',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'clientId',
|
||||||
|
label: '客户',
|
||||||
|
component: markRaw(MdClientSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择客户',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'workOrderId',
|
||||||
|
label: '生产工单',
|
||||||
|
component: markRaw(ProWorkOrderSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择生产工单',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'workstationId',
|
||||||
|
label: '工作站',
|
||||||
|
component: markRaw(MdWorkstationSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择工作站',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'toolId',
|
||||||
|
label: '工具',
|
||||||
|
component: markRaw(TmToolSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择工具',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'salesOrderCode',
|
||||||
|
label: '销售订单编号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入销售订单编号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'purchaseOrderCode',
|
||||||
|
label: '采购订单编号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入采购订单编号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'lotNumber',
|
||||||
|
label: '生产批号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入生产批号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'qualityStatus',
|
||||||
|
label: '质量状态',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
options: getDictOptions(DICT_TYPE.MES_WM_QUALITY_STATUS, 'number'),
|
||||||
|
placeholder: '请选择质量状态',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批次选择弹窗的字段 */
|
||||||
|
export function useBatchSelectGridColumns(
|
||||||
|
multiple = false,
|
||||||
|
): VxeTableGridOptions<MesWmBatchApi.Batch>['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: multiple ? 'checkbox' : 'radio',
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'code',
|
||||||
|
title: '批次编号',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemCode',
|
||||||
|
title: '物料编码',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemName',
|
||||||
|
title: '物料名称',
|
||||||
|
minWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemSpecification',
|
||||||
|
title: '规格型号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'unitName',
|
||||||
|
title: '单位',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'vendorCode',
|
||||||
|
title: '供应商编码',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'vendorName',
|
||||||
|
title: '供应商名称',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'clientCode',
|
||||||
|
title: '客户编码',
|
||||||
|
width: 110,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'clientName',
|
||||||
|
title: '客户名称',
|
||||||
|
width: 110,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'salesOrderCode',
|
||||||
|
title: '销售订单编号',
|
||||||
|
width: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'purchaseOrderCode',
|
||||||
|
title: '采购订单编号',
|
||||||
|
width: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'workOrderCode',
|
||||||
|
title: '工单编码',
|
||||||
|
width: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'workstationCode',
|
||||||
|
title: '工作站编码',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'taskCode',
|
||||||
|
title: '生产任务编号',
|
||||||
|
width: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'toolCode',
|
||||||
|
title: '工具编号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'lotNumber',
|
||||||
|
title: '生产批号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'qualityStatus',
|
||||||
|
title: '质量状态',
|
||||||
|
width: 100,
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.MES_WM_QUALITY_STATUS },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'produceDate',
|
||||||
|
title: '生产日期',
|
||||||
|
width: 120,
|
||||||
|
formatter: 'formatDate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'expireDate',
|
||||||
|
title: '有效期',
|
||||||
|
width: 120,
|
||||||
|
formatter: 'formatDate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'receiptDate',
|
||||||
|
title: '入库日期',
|
||||||
|
width: 120,
|
||||||
|
formatter: 'formatDate',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,488 @@
|
||||||
|
import type { VbenFormApi, VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MesProWorkOrderApi } from '#/api/mes/pro/workorder';
|
||||||
|
import type { MesWmMaterialStockApi } from '#/api/mes/wm/materialstock';
|
||||||
|
import type { MesWmOutsourceIssueApi } from '#/api/mes/wm/outsourceissue';
|
||||||
|
import type { MesWmOutsourceIssueDetailApi } from '#/api/mes/wm/outsourceissue/detail';
|
||||||
|
import type { MesWmOutsourceIssueLineApi } from '#/api/mes/wm/outsourceissue/line';
|
||||||
|
|
||||||
|
import { h, markRaw } from 'vue';
|
||||||
|
|
||||||
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
|
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { generateAutoCode } from '#/api/mes/md/autocode/record';
|
||||||
|
import { getRangePickerDefaultProps } from '#/utils';
|
||||||
|
import MdItemSelect from '#/views/mes/md/item/components/md-item-select.vue';
|
||||||
|
import MdVendorSelect from '#/views/mes/md/vendor/components/md-vendor-select.vue';
|
||||||
|
import ProWorkOrderSelect from '#/views/mes/pro/workorder/components/pro-work-order-select.vue';
|
||||||
|
import {
|
||||||
|
MesAutoCodeRuleCode,
|
||||||
|
MesProWorkOrderStatusEnum,
|
||||||
|
MesProWorkOrderTypeEnum,
|
||||||
|
} from '#/views/mes/utils/constants';
|
||||||
|
import { WmMaterialStockSelect } from '#/views/mes/wm/materialstock/components';
|
||||||
|
import {
|
||||||
|
WmWarehouseAreaSelect,
|
||||||
|
WmWarehouseLocationSelect,
|
||||||
|
WmWarehouseSelect,
|
||||||
|
} from '#/views/mes/wm/warehouse/components';
|
||||||
|
|
||||||
|
/** 表单类型 */
|
||||||
|
export type FormType = 'create' | 'detail' | 'finish' | 'stock' | 'update';
|
||||||
|
|
||||||
|
/** 表单头部是否只读(拣货、详情、领出态) */
|
||||||
|
function isHeaderReadonly(formType: FormType): boolean {
|
||||||
|
return (
|
||||||
|
formType === 'detail' || formType === 'finish' || formType === 'stock'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增/修改的表单 */
|
||||||
|
export function useFormSchema(
|
||||||
|
formType: FormType,
|
||||||
|
formApi?: VbenFormApi,
|
||||||
|
): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'id',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'status',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'code',
|
||||||
|
label: '发料单编号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入发料单编号',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
suffix: isHeaderReadonly(formType)
|
||||||
|
? undefined
|
||||||
|
: () =>
|
||||||
|
h(
|
||||||
|
Button,
|
||||||
|
{
|
||||||
|
type: 'default',
|
||||||
|
onClick: async () => {
|
||||||
|
const code = await generateAutoCode(
|
||||||
|
MesAutoCodeRuleCode.WM_OUTSOURCE_ISSUE_CODE,
|
||||||
|
);
|
||||||
|
await formApi?.setFieldValue('code', code);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ default: () => '生成' },
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'name',
|
||||||
|
label: '发料单名称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入发料单名称',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'issueDate',
|
||||||
|
label: '发料日期',
|
||||||
|
component: 'DatePicker',
|
||||||
|
componentProps: {
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
placeholder: '请选择发料日期',
|
||||||
|
valueFormat: 'x',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'workOrderId',
|
||||||
|
label: '外协工单',
|
||||||
|
component: markRaw(ProWorkOrderSelect),
|
||||||
|
componentProps: {
|
||||||
|
// 选择外协工单后,自动回填供应商
|
||||||
|
onChange: async (workOrder?: MesProWorkOrderApi.WorkOrder) => {
|
||||||
|
await formApi?.setFieldValue('vendorId', workOrder?.vendorId);
|
||||||
|
},
|
||||||
|
status: MesProWorkOrderStatusEnum.CONFIRMED,
|
||||||
|
type: MesProWorkOrderTypeEnum.OUTSOURCE,
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'vendorId',
|
||||||
|
label: '供应商',
|
||||||
|
component: markRaw(MdVendorSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择供应商',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'remark',
|
||||||
|
label: '备注',
|
||||||
|
component: 'Textarea',
|
||||||
|
formItemClass: 'col-span-3',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入备注',
|
||||||
|
rows: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表的搜索表单 */
|
||||||
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'code',
|
||||||
|
label: '发料单编号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入发料单编号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'name',
|
||||||
|
label: '发料单名称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入发料单名称',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'vendorId',
|
||||||
|
label: '供应商',
|
||||||
|
component: markRaw(MdVendorSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择供应商',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'issueDate',
|
||||||
|
label: '发料日期',
|
||||||
|
component: 'RangePicker',
|
||||||
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表的字段 */
|
||||||
|
export function useGridColumns(): VxeTableGridOptions<MesWmOutsourceIssueApi.OutsourceIssue>['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'code',
|
||||||
|
title: '发料单编号',
|
||||||
|
minWidth: 160,
|
||||||
|
slots: { default: 'code' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
title: '发料单名称',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'workOrderCode',
|
||||||
|
title: '生产工单号',
|
||||||
|
minWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'vendorName',
|
||||||
|
title: '供应商名称',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'issueDate',
|
||||||
|
title: '发料日期',
|
||||||
|
width: 180,
|
||||||
|
formatter: 'formatDate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: '单据状态',
|
||||||
|
minWidth: 100,
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.MES_WM_OUTSOURCE_ISSUE_STATUS },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 240,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'actions' },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发料单行子表的字段 */
|
||||||
|
export function useLineGridColumns(
|
||||||
|
editable: boolean,
|
||||||
|
stockable: boolean,
|
||||||
|
): VxeTableGridOptions<MesWmOutsourceIssueLineApi.OutsourceIssueLine>['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: 'expand',
|
||||||
|
width: 48,
|
||||||
|
slots: { content: 'detail' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemCode',
|
||||||
|
title: '物料编码',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemName',
|
||||||
|
title: '物料名称',
|
||||||
|
minWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'specification',
|
||||||
|
title: '规格型号',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'unitMeasureName',
|
||||||
|
title: '单位',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'quantity',
|
||||||
|
title: '领料数量',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'batchCode',
|
||||||
|
title: '批次号',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'remark',
|
||||||
|
title: '备注',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
...(editable || stockable
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 160,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'actions' },
|
||||||
|
} as const,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发料单行新增/修改的表单 */
|
||||||
|
export function useLineFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'itemId',
|
||||||
|
label: '物料',
|
||||||
|
component: markRaw(MdItemSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择物料',
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'quantity',
|
||||||
|
label: '发料数量',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
class: '!w-full',
|
||||||
|
min: 0,
|
||||||
|
placeholder: '请输入发料数量',
|
||||||
|
precision: 2,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'batchCode',
|
||||||
|
label: '批次号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入批次号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'remark',
|
||||||
|
label: '备注',
|
||||||
|
component: 'Textarea',
|
||||||
|
formItemClass: 'col-span-3',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入备注',
|
||||||
|
rows: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发料明细子表的字段 */
|
||||||
|
export function useDetailGridColumns(
|
||||||
|
stockable: boolean,
|
||||||
|
): VxeTableGridOptions<MesWmOutsourceIssueDetailApi.OutsourceIssueDetail>['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'warehouseName',
|
||||||
|
title: '仓库名称',
|
||||||
|
minWidth: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'locationName',
|
||||||
|
title: '库区名称',
|
||||||
|
minWidth: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'areaName',
|
||||||
|
title: '库位名称',
|
||||||
|
minWidth: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'quantity',
|
||||||
|
title: '数量',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
...(stockable
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'actions' },
|
||||||
|
} as const,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发料明细新增/修改的表单 */
|
||||||
|
export function useDetailFormSchema(formApi?: VbenFormApi): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'quantityMax',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'materialStockId',
|
||||||
|
label: '库存记录',
|
||||||
|
component: markRaw(WmMaterialStockSelect),
|
||||||
|
componentProps: {
|
||||||
|
// 选择库存记录后,自动回填仓库/库区/库位/批次/数量
|
||||||
|
onChange: async (stock?: MesWmMaterialStockApi.MaterialStock) => {
|
||||||
|
await formApi?.setValues({
|
||||||
|
areaId: stock?.areaId,
|
||||||
|
batchCode: stock?.batchCode,
|
||||||
|
batchId: stock?.batchId,
|
||||||
|
locationId: stock?.locationId,
|
||||||
|
quantity: stock?.quantity,
|
||||||
|
quantityMax: stock?.quantity,
|
||||||
|
warehouseId: stock?.warehouseId,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['itemId'],
|
||||||
|
componentProps: (values) => ({
|
||||||
|
itemId: values.itemId,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'itemId',
|
||||||
|
label: '物料',
|
||||||
|
component: markRaw(MdItemSelect),
|
||||||
|
componentProps: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'quantity',
|
||||||
|
label: '数量',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
class: '!w-full',
|
||||||
|
min: 0,
|
||||||
|
placeholder: '请输入数量',
|
||||||
|
precision: 2,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['quantityMax'],
|
||||||
|
componentProps: (values) => ({
|
||||||
|
class: '!w-full',
|
||||||
|
max: values.quantityMax,
|
||||||
|
min: 0,
|
||||||
|
placeholder: '请输入数量',
|
||||||
|
precision: 2,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'warehouseId',
|
||||||
|
label: '发料仓库',
|
||||||
|
component: markRaw(WmWarehouseSelect),
|
||||||
|
componentProps: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'locationId',
|
||||||
|
label: '库区',
|
||||||
|
component: markRaw(WmWarehouseLocationSelect),
|
||||||
|
componentProps: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['warehouseId'],
|
||||||
|
componentProps: (values) => ({
|
||||||
|
disabled: true,
|
||||||
|
warehouseId: values.warehouseId,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'areaId',
|
||||||
|
label: '库位',
|
||||||
|
component: markRaw(WmWarehouseAreaSelect),
|
||||||
|
componentProps: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['locationId'],
|
||||||
|
componentProps: (values) => ({
|
||||||
|
disabled: true,
|
||||||
|
locationId: values.locationId,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'batchCode',
|
||||||
|
label: '批次号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export { default as DeptSelectModal } from './select-modal.vue';
|
export { default as DeptSelectModal } from './select-modal.vue';
|
||||||
|
export { default as DeptTreeSelect } from './tree-select.vue';
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,16 @@ import { Input, Spin, Tree } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getSimpleDeptList } from '#/api/system/dept';
|
import { getSimpleDeptList } from '#/api/system/dept';
|
||||||
|
|
||||||
const emit = defineEmits(['select']);
|
defineOptions({ name: 'DeptTreeSelect' });
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
select: [dept?: SystemDeptApi.Dept];
|
||||||
|
}>();
|
||||||
|
|
||||||
const deptList = ref<SystemDeptApi.Dept[]>([]); // 部门列表
|
const deptList = ref<SystemDeptApi.Dept[]>([]); // 部门列表
|
||||||
const deptTree = ref<any[]>([]); // 部门树
|
const deptTree = ref<any[]>([]); // 部门树
|
||||||
const expandedKeys = ref<number[]>([]); // 展开的节点
|
const expandedKeys = ref<number[]>([]); // 展开的节点
|
||||||
|
const selectedKeys = ref<number[]>([]); // 选中的节点
|
||||||
const loading = ref(false); // 加载状态
|
const loading = ref(false); // 加载状态
|
||||||
const searchValue = ref(''); // 搜索值
|
const searchValue = ref(''); // 搜索值
|
||||||
|
|
||||||
|
|
@ -31,11 +37,21 @@ function handleSearch(e: any) {
|
||||||
expandedKeys.value = deptTree.value.map((node) => node.id!);
|
expandedKeys.value = deptTree.value.map((node) => node.id!);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 选中部门 */
|
/** 选中部门:点击已选中的节点时取消选中 */
|
||||||
function handleSelect(_selectedKeys: any[], info: any) {
|
function handleSelect(_selectedKeys: any[], info: any) {
|
||||||
emit('select', info.node.dataRef);
|
emit('select', info.selected ? info.node.dataRef : undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 重置选中状态(供外部重置按钮调用) */
|
||||||
|
function reset() {
|
||||||
|
searchValue.value = '';
|
||||||
|
selectedKeys.value = [];
|
||||||
|
deptTree.value = handleTree(deptList.value);
|
||||||
|
emit('select', undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ reset });
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -43,8 +59,6 @@ onMounted(async () => {
|
||||||
const data = await getSimpleDeptList();
|
const data = await getSimpleDeptList();
|
||||||
deptList.value = data;
|
deptList.value = data;
|
||||||
deptTree.value = handleTree(data);
|
deptTree.value = handleTree(data);
|
||||||
} catch (error) {
|
|
||||||
console.error('获取部门数据失败', error);
|
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
@ -54,24 +68,25 @@ onMounted(async () => {
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Input
|
<Input
|
||||||
placeholder="搜索部门"
|
|
||||||
allow-clear
|
|
||||||
v-model:value="searchValue"
|
v-model:value="searchValue"
|
||||||
@change="handleSearch"
|
allow-clear
|
||||||
class="w-full"
|
class="w-full"
|
||||||
|
placeholder="搜索部门"
|
||||||
|
@change="handleSearch"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<IconifyIcon icon="lucide:search" class="size-4" />
|
<IconifyIcon class="size-4" icon="lucide:search" />
|
||||||
</template>
|
</template>
|
||||||
</Input>
|
</Input>
|
||||||
<Spin :spinning="loading" wrapper-class-name="w-full">
|
<Spin :spinning="loading" wrapper-class-name="w-full">
|
||||||
<Tree
|
<Tree
|
||||||
@select="handleSelect"
|
|
||||||
v-if="deptTree.length > 0"
|
v-if="deptTree.length > 0"
|
||||||
|
v-model:selected-keys="selectedKeys"
|
||||||
class="pt-2"
|
class="pt-2"
|
||||||
:tree-data="deptTree"
|
|
||||||
:default-expand-all="true"
|
:default-expand-all="true"
|
||||||
:field-names="{ title: 'name', key: 'id', children: 'children' }"
|
:field-names="{ title: 'name', key: 'id', children: 'children' }"
|
||||||
|
:tree-data="deptTree"
|
||||||
|
@select="handleSelect"
|
||||||
/>
|
/>
|
||||||
<div v-else-if="!loading" class="py-4 text-center text-gray-500">
|
<div v-else-if="!loading" class="py-4 text-center text-gray-500">
|
||||||
暂无数据
|
暂无数据
|
||||||
|
|
@ -1 +1,3 @@
|
||||||
|
export { default as UserSelectDialog } from './select-dialog.vue';
|
||||||
export { default as UserSelectModal } from './select-modal.vue';
|
export { default as UserSelectModal } from './select-modal.vue';
|
||||||
|
export { default as UserSelect } from './select.vue';
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,305 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
|
import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
|
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
|
||||||
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
||||||
|
import { Button, Col, message, Modal, Row } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getUserPage } from '#/api/system/user';
|
||||||
|
import { DeptTreeSelect } from '#/views/system/dept/components';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
selected: [rows: SystemUserApi.User[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const open = ref(false); // 弹窗是否打开
|
||||||
|
const multiple = ref(false); // 是否多选;默认按单选选择器使用
|
||||||
|
const selectedRows = ref<SystemUserApi.User[]>([]); // 已选用户列表
|
||||||
|
const preSelectedIds = ref<number[]>([]); // 预选用户编号列表
|
||||||
|
const deptId = ref<number>(); // 当前部门过滤
|
||||||
|
const deptTreeRef = ref<InstanceType<typeof DeptTreeSelect>>(); // 部门树
|
||||||
|
|
||||||
|
/** 用户选择弹窗的搜索表单 */
|
||||||
|
function useUserSelectGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'username',
|
||||||
|
label: '用户名称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入用户名称',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'nickname',
|
||||||
|
label: '用户昵称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入用户昵称',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'mobile',
|
||||||
|
label: '手机号码',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入手机号码',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'status',
|
||||||
|
label: '状态',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'),
|
||||||
|
placeholder: '请选择状态',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用户选择弹窗的字段 */
|
||||||
|
function useUserSelectGridColumns(
|
||||||
|
isMultiple = false,
|
||||||
|
): VxeTableGridOptions<SystemUserApi.User>['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: isMultiple ? 'checkbox' : 'radio',
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'id',
|
||||||
|
title: '用户编号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'username',
|
||||||
|
title: '用户名称',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'nickname',
|
||||||
|
title: '用户昵称',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'mobile',
|
||||||
|
title: '手机号码',
|
||||||
|
width: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: '状态',
|
||||||
|
width: 90,
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.COMMON_STATUS },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取多选记录,包含 VXE reserve 跨页记录 */
|
||||||
|
function getMultipleSelectedRows() {
|
||||||
|
const selectedMap = new Map<number, SystemUserApi.User>();
|
||||||
|
const records = [
|
||||||
|
...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
|
||||||
|
...(gridApi.grid.getCheckboxRecords?.() ?? []),
|
||||||
|
] as SystemUserApi.User[];
|
||||||
|
records.forEach((row) => {
|
||||||
|
const rowId = row.id;
|
||||||
|
if (rowId !== undefined) {
|
||||||
|
selectedMap.set(rowId, row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return [...selectedMap.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理多选勾选变化 */
|
||||||
|
function handleCheckboxSelectChange() {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理单选切换 */
|
||||||
|
function handleRadioChange(row: SystemUserApi.User) {
|
||||||
|
selectedRows.value = [row];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选模式下切换行勾选 */
|
||||||
|
async function toggleMultipleRow(row: SystemUserApi.User) {
|
||||||
|
const selected = gridApi.grid.isCheckedByCheckboxRow(row);
|
||||||
|
await gridApi.grid.setCheckboxRow(row, !selected);
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理行双击:单选直接确认,多选切换勾选 */
|
||||||
|
async function handleCellDblclick({ row }: { row: SystemUserApi.User }) {
|
||||||
|
if (multiple.value) {
|
||||||
|
await toggleMultipleRow(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedRows.value = [row];
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
handleConfirm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 回显预选用户 */
|
||||||
|
async function applyPreSelection() {
|
||||||
|
if (preSelectedIds.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rows = gridApi.grid.getData() as SystemUserApi.User[];
|
||||||
|
for (const row of rows) {
|
||||||
|
if (row.id === undefined || !preSelectedIds.value.includes(row.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
await gridApi.grid.setCheckboxRow(row, true);
|
||||||
|
} else {
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
selectedRows.value = [row];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useUserSelectGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useUserSelectGridColumns(false),
|
||||||
|
height: 520,
|
||||||
|
keepSource: true,
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
range: true,
|
||||||
|
reserve: true,
|
||||||
|
},
|
||||||
|
radioConfig: {
|
||||||
|
highlight: true,
|
||||||
|
trigger: 'row',
|
||||||
|
},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getUserPage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
deptId: deptId.value,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<SystemUserApi.User>,
|
||||||
|
gridEvents: {
|
||||||
|
cellDblclick: handleCellDblclick,
|
||||||
|
checkboxAll: handleCheckboxSelectChange,
|
||||||
|
checkboxChange: handleCheckboxSelectChange,
|
||||||
|
radioChange: ({ row }: { row: SystemUserApi.User }) => {
|
||||||
|
handleRadioChange(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 部门树节点点击 */
|
||||||
|
function handleDeptNodeClick(dept?: SystemDeptApi.Dept) {
|
||||||
|
deptId.value = dept?.id;
|
||||||
|
gridApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置查询和选择状态 */
|
||||||
|
async function resetQueryState() {
|
||||||
|
selectedRows.value = [];
|
||||||
|
deptId.value = undefined;
|
||||||
|
await gridApi.grid.clearCheckboxRow();
|
||||||
|
await gridApi.grid.clearCheckboxReserve();
|
||||||
|
await gridApi.grid.clearRadioRow();
|
||||||
|
await gridApi.formApi.resetForm();
|
||||||
|
deptTreeRef.value?.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开用户选择弹窗 */
|
||||||
|
async function openModal(
|
||||||
|
selectedIds?: number[],
|
||||||
|
options?: { multiple?: boolean },
|
||||||
|
) {
|
||||||
|
open.value = true;
|
||||||
|
multiple.value = options?.multiple ?? false;
|
||||||
|
preSelectedIds.value = selectedIds || [];
|
||||||
|
await nextTick();
|
||||||
|
gridApi.setGridOptions({
|
||||||
|
columns: useUserSelectGridColumns(multiple.value),
|
||||||
|
});
|
||||||
|
await resetQueryState();
|
||||||
|
await gridApi.formApi.setFieldValue('status', CommonStatusEnum.ENABLE);
|
||||||
|
await gridApi.query();
|
||||||
|
await nextTick();
|
||||||
|
await applyPreSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭用户选择弹窗 */
|
||||||
|
function closeModal() {
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认选择用户 */
|
||||||
|
function handleConfirm() {
|
||||||
|
const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value;
|
||||||
|
if (rows.length === 0) {
|
||||||
|
message.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('selected', multiple.value ? rows : [rows[0]!]);
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open: openModal });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
v-model:open="open"
|
||||||
|
title="人员选择"
|
||||||
|
width="80%"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@ok="handleConfirm"
|
||||||
|
@cancel="closeModal"
|
||||||
|
>
|
||||||
|
<Row :gutter="12">
|
||||||
|
<Col :span="5">
|
||||||
|
<DeptTreeSelect ref="deptTreeRef" @select="handleDeptNodeClick" />
|
||||||
|
</Col>
|
||||||
|
<Col :span="19">
|
||||||
|
<Grid table-title="用户列表" />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<template #footer>
|
||||||
|
<Button @click="closeModal">取消</Button>
|
||||||
|
<Button type="primary" @click="handleConfirm">确定</Button>
|
||||||
|
</template>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
|
import { computed, ref, useAttrs, watch } from 'vue';
|
||||||
|
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { Input, Tooltip } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getUser } from '#/api/system/user';
|
||||||
|
|
||||||
|
import UserSelectDialog from './select-dialog.vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'UserSelect', inheritAttrs: false });
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
allowClear?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
modelValue?: number;
|
||||||
|
placeholder?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
allowClear: true,
|
||||||
|
disabled: false,
|
||||||
|
modelValue: undefined,
|
||||||
|
placeholder: '请选择用户',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [item: SystemUserApi.User | undefined];
|
||||||
|
'update:modelValue': [value: number | undefined];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
const dialogRef = ref<InstanceType<typeof UserSelectDialog>>();
|
||||||
|
const hovering = ref(false);
|
||||||
|
const selectedItem = ref<SystemUserApi.User>();
|
||||||
|
|
||||||
|
const displayLabel = computed(
|
||||||
|
() => selectedItem.value?.nickname ?? selectedItem.value?.username ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
|
const showClear = computed(
|
||||||
|
() =>
|
||||||
|
props.allowClear &&
|
||||||
|
!props.disabled &&
|
||||||
|
hovering.value &&
|
||||||
|
props.modelValue != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 根据编号单条查询用户信息(用于编辑回显) */
|
||||||
|
async function resolveItemById(id: number | undefined) {
|
||||||
|
if (id == null) {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedItem.value?.id === id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = await getUser(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.modelValue, resolveItemById, { immediate: true });
|
||||||
|
|
||||||
|
/** 清空已选用户 */
|
||||||
|
function clearSelected() {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
emit('update:modelValue', undefined);
|
||||||
|
emit('change', undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开用户选择弹窗 */
|
||||||
|
function handleClick(event: MouseEvent) {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
if (showClear.value && target.closest('.ant-input-suffix')) {
|
||||||
|
event.stopPropagation();
|
||||||
|
clearSelected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectedIds = props.modelValue == null ? [] : [props.modelValue];
|
||||||
|
dialogRef.value?.open(selectedIds, { multiple: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 弹窗选中回调 */
|
||||||
|
function handleSelected(rows: SystemUserApi.User[]) {
|
||||||
|
const item = rows[0];
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = item;
|
||||||
|
emit('update:modelValue', item.id);
|
||||||
|
emit('change', item);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-bind="attrs"
|
||||||
|
class="w-full"
|
||||||
|
:class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
|
||||||
|
@click="handleClick"
|
||||||
|
@mouseenter="hovering = true"
|
||||||
|
@mouseleave="hovering = false"
|
||||||
|
>
|
||||||
|
<Tooltip :mouse-enter-delay="0.5" :open="selectedItem ? undefined : false">
|
||||||
|
<template #title>
|
||||||
|
<div v-if="selectedItem" class="leading-6">
|
||||||
|
<div>用户名称:{{ selectedItem.username || '-' }}</div>
|
||||||
|
<div>用户昵称:{{ selectedItem.nickname || '-' }}</div>
|
||||||
|
<div>手机号码:{{ selectedItem.mobile || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<Input
|
||||||
|
:disabled="disabled"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:value="displayLabel"
|
||||||
|
readonly
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<IconifyIcon
|
||||||
|
class="size-4"
|
||||||
|
:icon="showClear ? 'lucide:circle-x' : 'lucide:search'"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Input>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<UserSelectDialog ref="dialogRef" @selected="handleSelected" />
|
||||||
|
</template>
|
||||||
|
|
@ -21,10 +21,10 @@ import {
|
||||||
updateUserStatus,
|
updateUserStatus,
|
||||||
} from '#/api/system/user';
|
} from '#/api/system/user';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
import { DeptTreeSelect } from '#/views/system/dept/components';
|
||||||
|
|
||||||
import { useGridColumns, useGridFormSchema } from './data';
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
import AssignRoleForm from './modules/assign-role-form.vue';
|
import AssignRoleForm from './modules/assign-role-form.vue';
|
||||||
import DeptTree from './modules/dept-tree.vue';
|
|
||||||
import Form from './modules/form.vue';
|
import Form from './modules/form.vue';
|
||||||
import ImportForm from './modules/import-form.vue';
|
import ImportForm from './modules/import-form.vue';
|
||||||
import ResetPasswordForm from './modules/reset-password-form.vue';
|
import ResetPasswordForm from './modules/reset-password-form.vue';
|
||||||
|
|
@ -62,8 +62,8 @@ async function handleExport() {
|
||||||
|
|
||||||
/** 选择部门 */
|
/** 选择部门 */
|
||||||
const searchDeptId = ref<number | undefined>(undefined);
|
const searchDeptId = ref<number | undefined>(undefined);
|
||||||
async function handleDeptSelect(dept: SystemDeptApi.Dept) {
|
async function handleDeptSelect(dept?: SystemDeptApi.Dept) {
|
||||||
searchDeptId.value = dept.id;
|
searchDeptId.value = dept?.id;
|
||||||
handleRefresh();
|
handleRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +205,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<div class="flex h-full w-full">
|
<div class="flex h-full w-full">
|
||||||
<!-- 左侧部门树 -->
|
<!-- 左侧部门树 -->
|
||||||
<Card class="mr-4 h-full w-1/6">
|
<Card class="mr-4 h-full w-1/6">
|
||||||
<DeptTree @select="handleDeptSelect" />
|
<DeptTreeSelect @select="handleDeptSelect" />
|
||||||
</Card>
|
</Card>
|
||||||
<!-- 右侧用户列表 -->
|
<!-- 右侧用户列表 -->
|
||||||
<div class="w-5/6">
|
<div class="w-5/6">
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ export namespace MesProWorkOrderApi {
|
||||||
routeName?: string;
|
routeName?: string;
|
||||||
clientId?: number;
|
clientId?: number;
|
||||||
clientName?: string;
|
clientName?: string;
|
||||||
|
vendorId?: number; // 供应商编号
|
||||||
|
vendorName?: string; // 供应商名称
|
||||||
planStartTime?: number | string;
|
planStartTime?: number | string;
|
||||||
planEndTime?: number | string;
|
planEndTime?: number | string;
|
||||||
actualStartTime?: number | string;
|
actualStartTime?: number | string;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceIssueDetailApi {
|
||||||
|
/** MES 外协发料单明细 */
|
||||||
|
export interface OutsourceIssueDetail {
|
||||||
|
id?: number; // 明细编号
|
||||||
|
lineId?: number; // 行编号
|
||||||
|
issueId?: number; // 发料单编号
|
||||||
|
itemId?: number; // 物料编号
|
||||||
|
itemCode?: string; // 物料编码
|
||||||
|
itemName?: string; // 物料名称
|
||||||
|
specification?: string; // 规格型号
|
||||||
|
unitMeasureName?: string; // 计量单位名称
|
||||||
|
quantity?: number; // 数量
|
||||||
|
materialStockId?: number; // 库存编号
|
||||||
|
batchId?: number; // 批次编号
|
||||||
|
batchCode?: string; // 批次编码
|
||||||
|
warehouseId?: number; // 仓库编号
|
||||||
|
warehouseName?: string; // 仓库名称
|
||||||
|
locationId?: number; // 库区编号
|
||||||
|
locationName?: string; // 库区名称
|
||||||
|
areaId?: number; // 库位编号
|
||||||
|
areaName?: string; // 库位名称
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单明细列表 */
|
||||||
|
export function getOutsourceIssueDetailListByLineId(lineId: number) {
|
||||||
|
return requestClient.get<
|
||||||
|
MesWmOutsourceIssueDetailApi.OutsourceIssueDetail[]
|
||||||
|
>('/mes/wm/outsource-issue-detail/list-by-line', { params: { lineId } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单明细详情 */
|
||||||
|
export function getOutsourceIssueDetail(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceIssueDetailApi.OutsourceIssueDetail>(
|
||||||
|
`/mes/wm/outsource-issue-detail/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协发料单明细 */
|
||||||
|
export function createOutsourceIssueDetail(
|
||||||
|
data: MesWmOutsourceIssueDetailApi.OutsourceIssueDetail,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/mes/wm/outsource-issue-detail/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协发料单明细 */
|
||||||
|
export function updateOutsourceIssueDetail(
|
||||||
|
data: MesWmOutsourceIssueDetailApi.OutsourceIssueDetail,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-issue-detail/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协发料单明细 */
|
||||||
|
export function deleteOutsourceIssueDetail(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-issue-detail/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceIssueApi {
|
||||||
|
/** MES 外协发料单 */
|
||||||
|
export interface OutsourceIssue {
|
||||||
|
id?: number; // 发料单编号
|
||||||
|
code?: string; // 发料单编号
|
||||||
|
name?: string; // 发料单名称
|
||||||
|
vendorId?: number; // 供应商编号
|
||||||
|
vendorCode?: string; // 供应商编码
|
||||||
|
vendorName?: string; // 供应商名称
|
||||||
|
workOrderId?: number; // 生产工单编号
|
||||||
|
workOrderCode?: string; // 生产工单编码
|
||||||
|
workOrderName?: string; // 生产工单名称
|
||||||
|
issueDate?: number; // 发料日期
|
||||||
|
status?: number; // 单据状态
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单分页 */
|
||||||
|
export function getOutsourceIssuePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MesWmOutsourceIssueApi.OutsourceIssue>>(
|
||||||
|
'/mes/wm/outsource-issue/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单详情 */
|
||||||
|
export function getOutsourceIssue(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceIssueApi.OutsourceIssue>(
|
||||||
|
`/mes/wm/outsource-issue/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协发料单 */
|
||||||
|
export function createOutsourceIssue(
|
||||||
|
data: MesWmOutsourceIssueApi.OutsourceIssue,
|
||||||
|
) {
|
||||||
|
return requestClient.post<number>('/mes/wm/outsource-issue/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协发料单 */
|
||||||
|
export function updateOutsourceIssue(
|
||||||
|
data: MesWmOutsourceIssueApi.OutsourceIssue,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-issue/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协发料单 */
|
||||||
|
export function deleteOutsourceIssue(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-issue/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交外协发料单 */
|
||||||
|
export function submitOutsourceIssue(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-issue/submit?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行拣货 */
|
||||||
|
export function stockOutsourceIssue(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-issue/stock?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行领出 */
|
||||||
|
export function finishOutsourceIssue(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-issue/finish?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消外协发料单 */
|
||||||
|
export function cancelOutsourceIssue(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-issue/cancel?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 校验外协发料单拣货数量是否与发料数量一致 */
|
||||||
|
export function checkOutsourceIssueQuantity(id: number) {
|
||||||
|
return requestClient.get<boolean>(
|
||||||
|
`/mes/wm/outsource-issue/check-quantity?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出外协发料单 */
|
||||||
|
export function exportOutsourceIssue(params: any) {
|
||||||
|
return requestClient.download('/mes/wm/outsource-issue/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceIssueLineApi {
|
||||||
|
/** MES 外协发料单行 */
|
||||||
|
export interface OutsourceIssueLine {
|
||||||
|
id?: number; // 行编号
|
||||||
|
issueId?: number; // 发料单编号
|
||||||
|
itemId?: number; // 物料编号
|
||||||
|
itemCode?: string; // 物料编码
|
||||||
|
itemName?: string; // 物料名称
|
||||||
|
specification?: string; // 规格型号
|
||||||
|
unitMeasureName?: string; // 计量单位名称
|
||||||
|
quantity?: number; // 发料数量
|
||||||
|
materialStockId?: number; // 库存编号
|
||||||
|
batchId?: number; // 批次编号
|
||||||
|
batchCode?: string; // 批次编码
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单行分页 */
|
||||||
|
export function getOutsourceIssueLinePage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MesWmOutsourceIssueLineApi.OutsourceIssueLine>
|
||||||
|
>('/mes/wm/outsource-issue-line/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协发料单行详情 */
|
||||||
|
export function getOutsourceIssueLine(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceIssueLineApi.OutsourceIssueLine>(
|
||||||
|
`/mes/wm/outsource-issue-line/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协发料单行 */
|
||||||
|
export function createOutsourceIssueLine(
|
||||||
|
data: MesWmOutsourceIssueLineApi.OutsourceIssueLine,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/mes/wm/outsource-issue-line/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协发料单行 */
|
||||||
|
export function updateOutsourceIssueLine(
|
||||||
|
data: MesWmOutsourceIssueLineApi.OutsourceIssueLine,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-issue-line/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协发料单行 */
|
||||||
|
export function deleteOutsourceIssueLine(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-issue-line/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceReceiptDetailApi {
|
||||||
|
/** MES 外协入库单明细 */
|
||||||
|
export interface OutsourceReceiptDetail {
|
||||||
|
id?: number; // 明细编号
|
||||||
|
lineId?: number; // 行编号
|
||||||
|
receiptId?: number; // 入库单编号
|
||||||
|
itemId?: number; // 物料编号
|
||||||
|
itemCode?: string; // 物料编码
|
||||||
|
itemName?: string; // 物料名称
|
||||||
|
specification?: string; // 规格型号
|
||||||
|
unitMeasureName?: string; // 计量单位名称
|
||||||
|
quantity?: number; // 上架数量
|
||||||
|
batchId?: number; // 批次编号
|
||||||
|
batchCode?: string; // 批次编码
|
||||||
|
warehouseId?: number; // 仓库编号
|
||||||
|
warehouseName?: string; // 仓库名称
|
||||||
|
locationId?: number; // 库区编号
|
||||||
|
locationName?: string; // 库区名称
|
||||||
|
areaId?: number; // 库位编号
|
||||||
|
areaName?: string; // 库位名称
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单明细列表 */
|
||||||
|
export function getOutsourceReceiptDetailListByLineId(lineId: number) {
|
||||||
|
return requestClient.get<
|
||||||
|
MesWmOutsourceReceiptDetailApi.OutsourceReceiptDetail[]
|
||||||
|
>('/mes/wm/outsource-receipt-detail/list-by-line', { params: { lineId } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单明细详情 */
|
||||||
|
export function getOutsourceReceiptDetail(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceReceiptDetailApi.OutsourceReceiptDetail>(
|
||||||
|
`/mes/wm/outsource-receipt-detail/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协入库单明细 */
|
||||||
|
export function createOutsourceReceiptDetail(
|
||||||
|
data: MesWmOutsourceReceiptDetailApi.OutsourceReceiptDetail,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/mes/wm/outsource-receipt-detail/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协入库单明细 */
|
||||||
|
export function updateOutsourceReceiptDetail(
|
||||||
|
data: MesWmOutsourceReceiptDetailApi.OutsourceReceiptDetail,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-receipt-detail/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协入库单明细 */
|
||||||
|
export function deleteOutsourceReceiptDetail(id: number) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/mes/wm/outsource-receipt-detail/delete?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceReceiptApi {
|
||||||
|
/** MES 外协入库单 */
|
||||||
|
export interface OutsourceReceipt {
|
||||||
|
id?: number; // 入库单编号
|
||||||
|
code?: string; // 入库单编码
|
||||||
|
name?: string; // 入库单名称
|
||||||
|
workOrderId?: number; // 外协工单编号
|
||||||
|
workOrderCode?: string; // 外协工单编码
|
||||||
|
vendorId?: number; // 供应商编号
|
||||||
|
vendorName?: string; // 供应商名称
|
||||||
|
receiptDate?: number; // 入库日期
|
||||||
|
status?: number; // 单据状态
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单分页 */
|
||||||
|
export function getOutsourceReceiptPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MesWmOutsourceReceiptApi.OutsourceReceipt>>(
|
||||||
|
'/mes/wm/outsource-receipt/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单详情 */
|
||||||
|
export function getOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceReceiptApi.OutsourceReceipt>(
|
||||||
|
`/mes/wm/outsource-receipt/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协入库单 */
|
||||||
|
export function createOutsourceReceipt(
|
||||||
|
data: MesWmOutsourceReceiptApi.OutsourceReceipt,
|
||||||
|
) {
|
||||||
|
return requestClient.post<number>('/mes/wm/outsource-receipt/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协入库单 */
|
||||||
|
export function updateOutsourceReceipt(
|
||||||
|
data: MesWmOutsourceReceiptApi.OutsourceReceipt,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-receipt/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协入库单 */
|
||||||
|
export function deleteOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-receipt/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交外协入库单 */
|
||||||
|
export function submitOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-receipt/submit?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 执行上架 */
|
||||||
|
export function stockOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-receipt/stock?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 完成入库 */
|
||||||
|
export function finishOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-receipt/finish?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消外协入库单 */
|
||||||
|
export function cancelOutsourceReceipt(id: number) {
|
||||||
|
return requestClient.put(`/mes/wm/outsource-receipt/cancel?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出外协入库单 */
|
||||||
|
export function exportOutsourceReceipt(params: any) {
|
||||||
|
return requestClient.download('/mes/wm/outsource-receipt/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MesWmOutsourceReceiptLineApi {
|
||||||
|
/** MES 外协入库单行 */
|
||||||
|
export interface OutsourceReceiptLine {
|
||||||
|
id?: number; // 行编号
|
||||||
|
receiptId?: number; // 入库单编号
|
||||||
|
itemId?: number; // 物料编号
|
||||||
|
itemCode?: string; // 物料编码
|
||||||
|
itemName?: string; // 物料名称
|
||||||
|
specification?: string; // 规格型号
|
||||||
|
unitMeasureName?: string; // 计量单位名称
|
||||||
|
quantity?: number; // 入库数量
|
||||||
|
batchId?: number; // 批次编号
|
||||||
|
batchCode?: string; // 批次编码
|
||||||
|
productionDate?: number; // 生产日期
|
||||||
|
expireDate?: number; // 有效期
|
||||||
|
lotNumber?: string; // 生产批号
|
||||||
|
iqcCheckFlag?: boolean; // 是否需要质检
|
||||||
|
remark?: string; // 备注
|
||||||
|
createTime?: Date; // 创建时间
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单行分页 */
|
||||||
|
export function getOutsourceReceiptLinePage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MesWmOutsourceReceiptLineApi.OutsourceReceiptLine>
|
||||||
|
>('/mes/wm/outsource-receipt-line/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询外协入库单行详情 */
|
||||||
|
export function getOutsourceReceiptLine(id: number) {
|
||||||
|
return requestClient.get<MesWmOutsourceReceiptLineApi.OutsourceReceiptLine>(
|
||||||
|
`/mes/wm/outsource-receipt-line/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增外协入库单行 */
|
||||||
|
export function createOutsourceReceiptLine(
|
||||||
|
data: MesWmOutsourceReceiptLineApi.OutsourceReceiptLine,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/mes/wm/outsource-receipt-line/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改外协入库单行 */
|
||||||
|
export function updateOutsourceReceiptLine(
|
||||||
|
data: MesWmOutsourceReceiptLineApi.OutsourceReceiptLine,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/mes/wm/outsource-receipt-line/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除外协入库单行 */
|
||||||
|
export function deleteOutsourceReceiptLine(id: number) {
|
||||||
|
return requestClient.delete(`/mes/wm/outsource-receipt-line/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as ProCardSelectDialog } from './pro-card-select-dialog.vue';
|
||||||
|
export { default as ProCardSelect } from './pro-card-select.vue';
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MesProCardApi } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
|
import { ElButton, ElDialog, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getCardPage } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import { useCardSelectGridColumns, useCardSelectGridFormSchema } from '../data';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
selected: [rows: MesProCardApi.Card[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const open = ref(false); // 弹窗是否打开
|
||||||
|
const multiple = ref(false); // 是否多选;默认按单选选择器使用
|
||||||
|
const selectedRows = ref<MesProCardApi.Card[]>([]); // 已选流转卡列表
|
||||||
|
const preSelectedIds = ref<number[]>([]); // 预选流转卡编号列表
|
||||||
|
|
||||||
|
/** 获取多选记录,包含 VXE reserve 跨页记录 */
|
||||||
|
function getMultipleSelectedRows() {
|
||||||
|
const selectedMap = new Map<number, MesProCardApi.Card>();
|
||||||
|
const records = [
|
||||||
|
...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
|
||||||
|
...(gridApi.grid.getCheckboxRecords?.() ?? []),
|
||||||
|
] as MesProCardApi.Card[];
|
||||||
|
records.forEach((row) => {
|
||||||
|
const rowId = row.id;
|
||||||
|
if (rowId !== undefined) {
|
||||||
|
selectedMap.set(rowId, row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return [...selectedMap.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理多选勾选变化 */
|
||||||
|
function handleCheckboxSelectChange() {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理单选切换 */
|
||||||
|
function handleRadioChange(row: MesProCardApi.Card) {
|
||||||
|
selectedRows.value = [row];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选模式下切换行勾选 */
|
||||||
|
async function toggleMultipleRow(row: MesProCardApi.Card) {
|
||||||
|
const selected = gridApi.grid.isCheckedByCheckboxRow(row);
|
||||||
|
await gridApi.grid.setCheckboxRow(row, !selected);
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理行双击:单选直接确认,多选切换勾选 */
|
||||||
|
async function handleCellDblclick({ row }: { row: MesProCardApi.Card }) {
|
||||||
|
if (multiple.value) {
|
||||||
|
await toggleMultipleRow(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedRows.value = [row];
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
handleConfirm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 回显预选流转卡 */
|
||||||
|
async function applyPreSelection() {
|
||||||
|
if (preSelectedIds.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rows = gridApi.grid.getData() as MesProCardApi.Card[];
|
||||||
|
for (const row of rows) {
|
||||||
|
if (row.id === undefined || !preSelectedIds.value.includes(row.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
await gridApi.grid.setCheckboxRow(row, true);
|
||||||
|
} else {
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
selectedRows.value = [row];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useCardSelectGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useCardSelectGridColumns(false),
|
||||||
|
height: 520,
|
||||||
|
keepSource: true,
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
range: true,
|
||||||
|
reserve: true,
|
||||||
|
},
|
||||||
|
radioConfig: {
|
||||||
|
highlight: true,
|
||||||
|
trigger: 'row',
|
||||||
|
},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getCardPage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<MesProCardApi.Card>,
|
||||||
|
gridEvents: {
|
||||||
|
cellDblclick: handleCellDblclick,
|
||||||
|
checkboxAll: handleCheckboxSelectChange,
|
||||||
|
checkboxChange: handleCheckboxSelectChange,
|
||||||
|
radioChange: ({ row }: { row: MesProCardApi.Card }) => {
|
||||||
|
handleRadioChange(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 重置查询和选择状态 */
|
||||||
|
async function resetQueryState() {
|
||||||
|
selectedRows.value = [];
|
||||||
|
await gridApi.grid.clearCheckboxRow();
|
||||||
|
await gridApi.grid.clearCheckboxReserve();
|
||||||
|
await gridApi.grid.clearRadioRow();
|
||||||
|
await gridApi.formApi.resetForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开流转卡选择弹窗 */
|
||||||
|
async function openModal(
|
||||||
|
selectedIds?: number[],
|
||||||
|
options?: { multiple?: boolean },
|
||||||
|
) {
|
||||||
|
open.value = true;
|
||||||
|
multiple.value = options?.multiple ?? false;
|
||||||
|
preSelectedIds.value = selectedIds || [];
|
||||||
|
await nextTick();
|
||||||
|
gridApi.setGridOptions({
|
||||||
|
columns: useCardSelectGridColumns(multiple.value),
|
||||||
|
});
|
||||||
|
await resetQueryState();
|
||||||
|
await gridApi.query();
|
||||||
|
await nextTick();
|
||||||
|
await applyPreSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭流转卡选择弹窗 */
|
||||||
|
function closeModal() {
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认选择流转卡 */
|
||||||
|
function handleConfirm() {
|
||||||
|
const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value;
|
||||||
|
if (rows.length === 0) {
|
||||||
|
ElMessage.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('selected', multiple.value ? rows : [rows[0]!]);
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open: openModal });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ElDialog v-model="open" title="流转卡选择" width="70%">
|
||||||
|
<Grid table-title="流转卡列表" />
|
||||||
|
<template #footer>
|
||||||
|
<ElButton @click="closeModal">取消</ElButton>
|
||||||
|
<ElButton type="primary" @click="handleConfirm">确定</ElButton>
|
||||||
|
</template>
|
||||||
|
</ElDialog>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { MesProCardApi } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import { computed, ref, useAttrs, watch } from 'vue';
|
||||||
|
|
||||||
|
import { CircleX, Search } from '@vben/icons';
|
||||||
|
|
||||||
|
import { ElInput, ElTooltip } from 'element-plus';
|
||||||
|
|
||||||
|
import { getCard } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import ProCardSelectDialog from './pro-card-select-dialog.vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'ProCardSelect', inheritAttrs: false });
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
clearable?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
modelValue?: number;
|
||||||
|
placeholder?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
clearable: true,
|
||||||
|
disabled: false,
|
||||||
|
modelValue: undefined,
|
||||||
|
placeholder: '请选择流转卡',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [item: MesProCardApi.Card | undefined];
|
||||||
|
'update:modelValue': [value: number | undefined];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
const dialogRef = ref<InstanceType<typeof ProCardSelectDialog>>();
|
||||||
|
const hovering = ref(false);
|
||||||
|
const selectedItem = ref<MesProCardApi.Card>();
|
||||||
|
|
||||||
|
const displayLabel = computed(() => selectedItem.value?.code ?? '');
|
||||||
|
|
||||||
|
const showClear = computed(
|
||||||
|
() =>
|
||||||
|
props.clearable &&
|
||||||
|
!props.disabled &&
|
||||||
|
hovering.value &&
|
||||||
|
props.modelValue != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 根据编号单条查询流转卡信息(用于编辑回显) */
|
||||||
|
async function resolveItemById(id: number | undefined) {
|
||||||
|
if (id == null) {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedItem.value?.id === id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = await getCard(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.modelValue, resolveItemById, { immediate: true });
|
||||||
|
|
||||||
|
/** 清空已选流转卡 */
|
||||||
|
function clearSelected() {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
emit('update:modelValue', undefined);
|
||||||
|
emit('change', undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开流转卡选择弹窗 */
|
||||||
|
function handleClick(event: MouseEvent) {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
if (showClear.value && target.closest('.el-input__suffix')) {
|
||||||
|
event.stopPropagation();
|
||||||
|
clearSelected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectedIds = props.modelValue == null ? [] : [props.modelValue];
|
||||||
|
dialogRef.value?.open(selectedIds, { multiple: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 弹窗选中回调 */
|
||||||
|
function handleSelected(rows: MesProCardApi.Card[]) {
|
||||||
|
const item = rows[0];
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = item;
|
||||||
|
emit('update:modelValue', item.id);
|
||||||
|
emit('change', item);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-bind="attrs"
|
||||||
|
class="w-full"
|
||||||
|
:class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
|
||||||
|
@click="handleClick"
|
||||||
|
@mouseenter="hovering = true"
|
||||||
|
@mouseleave="hovering = false"
|
||||||
|
>
|
||||||
|
<ElTooltip :disabled="!selectedItem" placement="top" :show-after="500">
|
||||||
|
<template #content>
|
||||||
|
<div v-if="selectedItem" class="leading-6">
|
||||||
|
<div>编号:{{ selectedItem.code || '-' }}</div>
|
||||||
|
<div>工单:{{ selectedItem.workOrderCode || '-' }}</div>
|
||||||
|
<div>批次:{{ selectedItem.batchCode || '-' }}</div>
|
||||||
|
<div>产品:{{ selectedItem.itemName || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<ElInput
|
||||||
|
:disabled="disabled"
|
||||||
|
:model-value="displayLabel"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
readonly
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<CircleX v-if="showClear" class="size-4" />
|
||||||
|
<Search v-else class="size-4" />
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
</ElTooltip>
|
||||||
|
</div>
|
||||||
|
<ProCardSelectDialog ref="dialogRef" @selected="handleSelected" />
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MesProCardApi } from '#/api/mes/pro/card';
|
||||||
|
|
||||||
|
import { markRaw } from 'vue';
|
||||||
|
|
||||||
|
import { MdItemSelect } from '#/views/mes/md/item/components';
|
||||||
|
import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components';
|
||||||
|
|
||||||
|
/** 流转卡选择弹窗的搜索表单 */
|
||||||
|
export function useCardSelectGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'code',
|
||||||
|
label: '流转卡编号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
clearable: true,
|
||||||
|
placeholder: '请输入流转卡编号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'workOrderId',
|
||||||
|
label: '生产工单',
|
||||||
|
component: markRaw(ProWorkOrderSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择生产工单',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'itemId',
|
||||||
|
label: '产品物料',
|
||||||
|
component: markRaw(MdItemSelect),
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择产品物料',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'batchCode',
|
||||||
|
label: '批次号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
clearable: true,
|
||||||
|
placeholder: '请输入批次号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 流转卡选择弹窗的字段 */
|
||||||
|
export function useCardSelectGridColumns(
|
||||||
|
multiple = false,
|
||||||
|
): VxeTableGridOptions<MesProCardApi.Card>['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: multiple ? 'checkbox' : 'radio',
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'code',
|
||||||
|
title: '流转卡编号',
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'workOrderCode',
|
||||||
|
title: '生产工单编号',
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemCode',
|
||||||
|
title: '产品物料编码',
|
||||||
|
width: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'batchCode',
|
||||||
|
title: '批次号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'itemName',
|
||||||
|
title: '产品物料名称',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'specification',
|
||||||
|
title: '规格型号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'unitMeasureName',
|
||||||
|
title: '单位',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'transferedQuantity',
|
||||||
|
title: '流转数量',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -151,9 +151,22 @@ export const MesAutoCodeRuleCode = {
|
||||||
TM_TOOL_CODE: 'TM_TOOL_CODE',
|
TM_TOOL_CODE: 'TM_TOOL_CODE',
|
||||||
WM_AREA_CODE: 'WM_AREA_CODE',
|
WM_AREA_CODE: 'WM_AREA_CODE',
|
||||||
WM_LOCATION_CODE: 'WM_LOCATION_CODE',
|
WM_LOCATION_CODE: 'WM_LOCATION_CODE',
|
||||||
|
WM_ARRIVAL_NOTICE_CODE: 'WM_ARRIVAL_NOTICE_CODE',
|
||||||
|
WM_ITEM_RECEIPT_CODE: 'WM_ITEM_RECEIPT_CODE',
|
||||||
|
WM_RETURN_VENDOR_CODE: 'WM_RETURN_VENDOR_CODE',
|
||||||
|
WM_SALES_NOTICE_CODE: 'WM_SALES_NOTICE_CODE',
|
||||||
|
WM_RETURN_SALES_CODE: 'WM_RETURN_SALES_CODE',
|
||||||
|
WM_RETURN_ISSUE_CODE: 'WM_RETURN_ISSUE_CODE',
|
||||||
|
WM_PRODUCT_ISSUE_CODE: 'WM_PRODUCT_ISSUE_CODE',
|
||||||
|
WM_PRODUCT_SALES_CODE: 'WM_PRODUCT_SALES_CODE',
|
||||||
|
PRODUCTRECPT_CODE: 'PRODUCTRECPT_CODE',
|
||||||
WM_MISC_ISSUE_CODE: 'WM_MISC_ISSUE_CODE',
|
WM_MISC_ISSUE_CODE: 'WM_MISC_ISSUE_CODE',
|
||||||
WM_MISC_RECEIPT_CODE: 'WM_MISC_RECEIPT_CODE',
|
WM_MISC_RECEIPT_CODE: 'WM_MISC_RECEIPT_CODE',
|
||||||
|
WM_OUTSOURCE_ISSUE_CODE: 'WM_OUTSOURCE_ISSUE_CODE',
|
||||||
|
WM_OUTSOURCE_RECEIPT_CODE: 'WM_OUTSOURCE_RECEIPT_CODE',
|
||||||
WM_PACKAGE_CODE: 'WM_PACKAGE_CODE',
|
WM_PACKAGE_CODE: 'WM_PACKAGE_CODE',
|
||||||
|
WM_STOCK_TAKING_CODE: 'WM_STOCK_TAKING_CODE',
|
||||||
|
WM_STOCK_TAKING_PLAN_CODE: 'WM_STOCK_TAKING_PLAN_CODE',
|
||||||
WM_WAREHOUSE_CODE: 'WM_WAREHOUSE_CODE',
|
WM_WAREHOUSE_CODE: 'WM_WAREHOUSE_CODE',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|
@ -163,6 +176,38 @@ export const MesWmPackageStatusEnum = {
|
||||||
FINISHED: MesOrderStatusConstants.FINISHED,
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
/** MES 盘点类型枚举 */
|
||||||
|
export const MesWmStockTakingTypeEnum = {
|
||||||
|
STATIC: 1,
|
||||||
|
DYNAMIC: 2,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 盘点任务状态枚举 */
|
||||||
|
export const MesWmStockTakingTaskStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 盘点任务行状态枚举 */
|
||||||
|
export const MesWmStockTakingTaskLineStatusEnum = {
|
||||||
|
UNCOUNTED: 0,
|
||||||
|
NORMAL: 1,
|
||||||
|
GAIN: 2,
|
||||||
|
LOSS: 3,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 盘点方案参数类型枚举 */
|
||||||
|
export const MesWmStockTakingParamTypeEnum = {
|
||||||
|
WAREHOUSE: 102,
|
||||||
|
LOCATION: 103,
|
||||||
|
AREA: 104,
|
||||||
|
BATCH: 107,
|
||||||
|
ITEM: 600,
|
||||||
|
QUALITY_STATUS: 900,
|
||||||
|
} as const;
|
||||||
|
|
||||||
/** MES 生产工单状态枚举 */
|
/** MES 生产工单状态枚举 */
|
||||||
export const MesProWorkOrderStatusEnum = {
|
export const MesProWorkOrderStatusEnum = {
|
||||||
PREPARE: MesOrderStatusConstants.DRAFT,
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
|
@ -173,6 +218,13 @@ export const MesProWorkOrderStatusEnum = {
|
||||||
CANCELLED: MesOrderStatusConstants.CANCELLED,
|
CANCELLED: MesOrderStatusConstants.CANCELLED,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
/** MES 工单类型枚举 */
|
||||||
|
export const MesProWorkOrderTypeEnum = {
|
||||||
|
SELF: 1, // 自行生产
|
||||||
|
OUTSOURCE: 2, // 代工
|
||||||
|
PURCHASE: 3, // 采购
|
||||||
|
} as const;
|
||||||
|
|
||||||
/** MES 生产任务状态枚举 */
|
/** MES 生产任务状态枚举 */
|
||||||
export const MesProTaskStatusEnum = {
|
export const MesProTaskStatusEnum = {
|
||||||
PREPARE: MesOrderStatusConstants.DRAFT,
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
|
@ -236,6 +288,105 @@ export const MesWmMiscReceiptStatusEnum = {
|
||||||
CANCELED: MesOrderStatusConstants.CANCELLED,
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
/** MES 外协发料单状态枚举 */
|
||||||
|
export const MesWmOutsourceIssueStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELLED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 外协入库单状态枚举 */
|
||||||
|
export const MesWmOutsourceReceiptStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 到货通知单状态枚举 */
|
||||||
|
export const MesWmArrivalNoticeStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
PENDING_QC: MesOrderStatusConstants.APPROVING,
|
||||||
|
PENDING_RECEIPT: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 采购入库单状态枚举 */
|
||||||
|
export const MesWmItemReceiptStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 供应商退货单状态枚举 */
|
||||||
|
export const MesWmReturnVendorStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 发货通知单状态枚举 */
|
||||||
|
export const MesWmSalesNoticeStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 销售退货单状态枚举 */
|
||||||
|
export const MesWmReturnSalesStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
CONFIRMED: MesOrderStatusConstants.CONFIRMED,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 生产退料单状态枚举 */
|
||||||
|
export const MesWmReturnIssueStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
CONFIRMED: MesOrderStatusConstants.CONFIRMED,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 领料出库单状态枚举 */
|
||||||
|
export const MesWmProductIssueStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 产品入库单状态枚举 */
|
||||||
|
export const MesWmProductReceiptStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
/** MES 销售出库单状态枚举 */
|
||||||
|
export const MesWmProductSalesStatusEnum = {
|
||||||
|
PREPARE: MesOrderStatusConstants.DRAFT,
|
||||||
|
CONFIRMED: MesOrderStatusConstants.CONFIRMED,
|
||||||
|
APPROVING: MesOrderStatusConstants.APPROVING,
|
||||||
|
SHIPPING: 10, // 待填写运单
|
||||||
|
APPROVED: MesOrderStatusConstants.APPROVED,
|
||||||
|
FINISHED: MesOrderStatusConstants.FINISHED,
|
||||||
|
CANCELED: MesOrderStatusConstants.CANCELLED,
|
||||||
|
} as const;
|
||||||
|
|
||||||
/** MES 质检结果值类型枚举 */
|
/** MES 质检结果值类型枚举 */
|
||||||
export const MesQcResultValueType = {
|
export const MesQcResultValueType = {
|
||||||
FLOAT: 1,
|
FLOAT: 1,
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,12 @@ import MdItemSelect from '#/views/mes/md/item/components/md-item-select.vue';
|
||||||
import MdVendorSelect from '#/views/mes/md/vendor/components/md-vendor-select.vue';
|
import MdVendorSelect from '#/views/mes/md/vendor/components/md-vendor-select.vue';
|
||||||
import MdWorkshopSelect from '#/views/mes/md/workstation/components/md-workshop-select.vue';
|
import MdWorkshopSelect from '#/views/mes/md/workstation/components/md-workshop-select.vue';
|
||||||
import MdWorkstationSelect from '#/views/mes/md/workstation/components/md-workstation-select.vue';
|
import MdWorkstationSelect from '#/views/mes/md/workstation/components/md-workstation-select.vue';
|
||||||
|
import { ProCardSelect } from '#/views/mes/pro/card/components';
|
||||||
import ProWorkOrderSelect from '#/views/mes/pro/workorder/components/pro-work-order-select.vue';
|
import ProWorkOrderSelect from '#/views/mes/pro/workorder/components/pro-work-order-select.vue';
|
||||||
import TmToolSelect from '#/views/mes/tm/tool/components/tm-tool-select.vue';
|
import TmToolSelect from '#/views/mes/tm/tool/components/tm-tool-select.vue';
|
||||||
import { BarcodeBizTypeEnum } from '#/views/mes/utils/constants';
|
import { BarcodeBizTypeEnum } from '#/views/mes/utils/constants';
|
||||||
|
import { WmBatchSelect } from '#/views/mes/wm/batch/components';
|
||||||
|
import { UserSelect } from '#/views/system/user/components';
|
||||||
|
|
||||||
import WmMaterialStockSelect from './../materialstock/components/wm-material-stock-select.vue';
|
import WmMaterialStockSelect from './../materialstock/components/wm-material-stock-select.vue';
|
||||||
import { WmPackageSelect } from './../packages/components';
|
import { WmPackageSelect } from './../packages/components';
|
||||||
|
|
@ -51,15 +54,31 @@ async function syncBizDetail(
|
||||||
}
|
}
|
||||||
let bizCode: string | undefined;
|
let bizCode: string | undefined;
|
||||||
let bizName: string | undefined;
|
let bizName: string | undefined;
|
||||||
if (bizType === BarcodeBizTypeEnum.STOCK) {
|
switch (bizType) {
|
||||||
bizCode = item.itemCode;
|
case BarcodeBizTypeEnum.BATCH: {
|
||||||
bizName = item.itemName;
|
bizCode = item.code;
|
||||||
} else if (bizType === BarcodeBizTypeEnum.PACKAGE) {
|
bizName = item.itemName || item.code;
|
||||||
bizCode = item.code;
|
break;
|
||||||
bizName = item.clientName || item.code;
|
}
|
||||||
} else {
|
case BarcodeBizTypeEnum.PACKAGE: {
|
||||||
bizCode = item.code || item.username;
|
bizCode = item.code;
|
||||||
bizName = item.name || item.nickname;
|
bizName = item.clientName || item.code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BarcodeBizTypeEnum.PROCARD: {
|
||||||
|
bizCode = item.code;
|
||||||
|
bizName = item.workOrderName || item.code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BarcodeBizTypeEnum.STOCK: {
|
||||||
|
bizCode = item.itemCode;
|
||||||
|
bizName = item.itemName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
bizCode = item.code || item.username;
|
||||||
|
bizName = item.name || item.nickname;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 先回填业务编码、名称并清空旧条码内容
|
// 先回填业务编码、名称并清空旧条码内容
|
||||||
await formApi.setValues({ bizCode, bizName, content: undefined });
|
await formApi.setValues({ bizCode, bizName, content: undefined });
|
||||||
|
|
@ -328,6 +347,45 @@ export function useFormSchema(formApi?: VbenFormApi): VbenFormSchema[] {
|
||||||
},
|
},
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'bizId',
|
||||||
|
label: '批次',
|
||||||
|
component: markRaw(WmBatchSelect),
|
||||||
|
componentProps: {
|
||||||
|
onChange: (item: any) => syncBizDetail(formApi, item),
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['bizType'],
|
||||||
|
show: (values) => values.bizType === BarcodeBizTypeEnum.BATCH,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'bizId',
|
||||||
|
label: '流转卡',
|
||||||
|
component: markRaw(ProCardSelect),
|
||||||
|
componentProps: {
|
||||||
|
onChange: (item: any) => syncBizDetail(formApi, item),
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['bizType'],
|
||||||
|
show: (values) => values.bizType === BarcodeBizTypeEnum.PROCARD,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'bizId',
|
||||||
|
label: '人员',
|
||||||
|
component: markRaw(UserSelect),
|
||||||
|
componentProps: {
|
||||||
|
onChange: (item: any) => syncBizDetail(formApi, item),
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['bizType'],
|
||||||
|
show: (values) => values.bizType === BarcodeBizTypeEnum.USER,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'bizId',
|
fieldName: 'bizId',
|
||||||
label: '业务编号',
|
label: '业务编号',
|
||||||
|
|
@ -344,13 +402,16 @@ export function useFormSchema(formApi?: VbenFormApi): VbenFormSchema[] {
|
||||||
values.bizType !== undefined &&
|
values.bizType !== undefined &&
|
||||||
![
|
![
|
||||||
BarcodeBizTypeEnum.AREA,
|
BarcodeBizTypeEnum.AREA,
|
||||||
|
BarcodeBizTypeEnum.BATCH,
|
||||||
BarcodeBizTypeEnum.CLIENT,
|
BarcodeBizTypeEnum.CLIENT,
|
||||||
BarcodeBizTypeEnum.ITEM,
|
BarcodeBizTypeEnum.ITEM,
|
||||||
BarcodeBizTypeEnum.LOCATION,
|
BarcodeBizTypeEnum.LOCATION,
|
||||||
BarcodeBizTypeEnum.MACHINERY,
|
BarcodeBizTypeEnum.MACHINERY,
|
||||||
BarcodeBizTypeEnum.PACKAGE,
|
BarcodeBizTypeEnum.PACKAGE,
|
||||||
|
BarcodeBizTypeEnum.PROCARD,
|
||||||
BarcodeBizTypeEnum.STOCK,
|
BarcodeBizTypeEnum.STOCK,
|
||||||
BarcodeBizTypeEnum.TOOL,
|
BarcodeBizTypeEnum.TOOL,
|
||||||
|
BarcodeBizTypeEnum.USER,
|
||||||
BarcodeBizTypeEnum.VENDOR,
|
BarcodeBizTypeEnum.VENDOR,
|
||||||
BarcodeBizTypeEnum.WAREHOUSE,
|
BarcodeBizTypeEnum.WAREHOUSE,
|
||||||
BarcodeBizTypeEnum.WORKORDER,
|
BarcodeBizTypeEnum.WORKORDER,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as WmBatchSelectDialog } from './wm-batch-select-dialog.vue';
|
||||||
|
export { default as WmBatchSelect } from './wm-batch-select.vue';
|
||||||
|
|
@ -0,0 +1,241 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MesWmBatchApi } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import { computed, nextTick, ref } from 'vue';
|
||||||
|
|
||||||
|
import { ElAlert, ElButton, ElDialog, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getBatchPage } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import { useBatchSelectGridColumns, useBatchSelectGridFormSchema } from '../data';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
selected: [rows: MesWmBatchApi.Batch[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const open = ref(false); // 弹窗是否打开
|
||||||
|
const multiple = ref(false); // 是否多选;默认按单选选择器使用
|
||||||
|
const selectedRows = ref<MesWmBatchApi.Batch[]>([]); // 已选批次列表
|
||||||
|
const preSelectedIds = ref<number[]>([]); // 预选批次编号列表
|
||||||
|
const externalItemId = ref<number>(); // 外部传入的默认物料过滤
|
||||||
|
const externalClientId = ref<number>(); // 外部传入的默认客户过滤
|
||||||
|
const externalVendorId = ref<number>(); // 外部传入的默认供应商过滤
|
||||||
|
const externalSalesOrderCode = ref<string>(); // 外部传入的默认销售订单过滤
|
||||||
|
|
||||||
|
const filterTip = computed(() => {
|
||||||
|
const parts: string[] = [];
|
||||||
|
if (externalClientId.value != null) {
|
||||||
|
parts.push('客户');
|
||||||
|
}
|
||||||
|
if (externalVendorId.value != null) {
|
||||||
|
parts.push('供应商');
|
||||||
|
}
|
||||||
|
if (externalSalesOrderCode.value != null) {
|
||||||
|
parts.push('销售订单');
|
||||||
|
}
|
||||||
|
return parts.length > 0 ? `已按${parts.join('/')}预过滤` : '';
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 获取多选记录,包含 VXE reserve 跨页记录 */
|
||||||
|
function getMultipleSelectedRows() {
|
||||||
|
const selectedMap = new Map<number, MesWmBatchApi.Batch>();
|
||||||
|
const records = [
|
||||||
|
...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
|
||||||
|
...(gridApi.grid.getCheckboxRecords?.() ?? []),
|
||||||
|
] as MesWmBatchApi.Batch[];
|
||||||
|
records.forEach((row) => {
|
||||||
|
const rowId = row.id;
|
||||||
|
if (rowId !== undefined) {
|
||||||
|
selectedMap.set(rowId, row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return [...selectedMap.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理多选勾选变化 */
|
||||||
|
function handleCheckboxSelectChange() {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理单选切换 */
|
||||||
|
function handleRadioChange(row: MesWmBatchApi.Batch) {
|
||||||
|
selectedRows.value = [row];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选模式下切换行勾选 */
|
||||||
|
async function toggleMultipleRow(row: MesWmBatchApi.Batch) {
|
||||||
|
const selected = gridApi.grid.isCheckedByCheckboxRow(row);
|
||||||
|
await gridApi.grid.setCheckboxRow(row, !selected);
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理行双击:单选直接确认,多选切换勾选 */
|
||||||
|
async function handleCellDblclick({ row }: { row: MesWmBatchApi.Batch }) {
|
||||||
|
if (multiple.value) {
|
||||||
|
await toggleMultipleRow(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedRows.value = [row];
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
handleConfirm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 回显预选批次 */
|
||||||
|
async function applyPreSelection() {
|
||||||
|
if (preSelectedIds.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rows = gridApi.grid.getData() as MesWmBatchApi.Batch[];
|
||||||
|
for (const row of rows) {
|
||||||
|
if (row.id === undefined || !preSelectedIds.value.includes(row.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
await gridApi.grid.setCheckboxRow(row, true);
|
||||||
|
} else {
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
selectedRows.value = [row];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useBatchSelectGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useBatchSelectGridColumns(false),
|
||||||
|
height: 520,
|
||||||
|
keepSource: true,
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
range: true,
|
||||||
|
reserve: true,
|
||||||
|
},
|
||||||
|
radioConfig: {
|
||||||
|
highlight: true,
|
||||||
|
trigger: 'row',
|
||||||
|
},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getBatchPage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<MesWmBatchApi.Batch>,
|
||||||
|
gridEvents: {
|
||||||
|
cellDblclick: handleCellDblclick,
|
||||||
|
checkboxAll: handleCheckboxSelectChange,
|
||||||
|
checkboxChange: handleCheckboxSelectChange,
|
||||||
|
radioChange: ({ row }: { row: MesWmBatchApi.Batch }) => {
|
||||||
|
handleRadioChange(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 重置查询和选择状态,保留外部传入的默认过滤 */
|
||||||
|
async function resetQueryState() {
|
||||||
|
selectedRows.value = [];
|
||||||
|
await gridApi.grid.clearCheckboxRow();
|
||||||
|
await gridApi.grid.clearCheckboxReserve();
|
||||||
|
await gridApi.grid.clearRadioRow();
|
||||||
|
await gridApi.formApi.resetForm();
|
||||||
|
if (externalItemId.value) {
|
||||||
|
await gridApi.formApi.setFieldValue('itemId', externalItemId.value);
|
||||||
|
}
|
||||||
|
if (externalClientId.value) {
|
||||||
|
await gridApi.formApi.setFieldValue('clientId', externalClientId.value);
|
||||||
|
}
|
||||||
|
if (externalVendorId.value) {
|
||||||
|
await gridApi.formApi.setFieldValue('vendorId', externalVendorId.value);
|
||||||
|
}
|
||||||
|
if (externalSalesOrderCode.value) {
|
||||||
|
await gridApi.formApi.setFieldValue(
|
||||||
|
'salesOrderCode',
|
||||||
|
externalSalesOrderCode.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开批次选择弹窗 */
|
||||||
|
async function openModal(
|
||||||
|
selectedIds?: number[],
|
||||||
|
options?: {
|
||||||
|
clientId?: number;
|
||||||
|
itemId?: number;
|
||||||
|
multiple?: boolean;
|
||||||
|
salesOrderCode?: string;
|
||||||
|
vendorId?: number;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
open.value = true;
|
||||||
|
multiple.value = options?.multiple ?? false;
|
||||||
|
preSelectedIds.value = selectedIds || [];
|
||||||
|
externalItemId.value = options?.itemId;
|
||||||
|
externalClientId.value = options?.clientId;
|
||||||
|
externalVendorId.value = options?.vendorId;
|
||||||
|
externalSalesOrderCode.value = options?.salesOrderCode;
|
||||||
|
await nextTick();
|
||||||
|
gridApi.setGridOptions({
|
||||||
|
columns: useBatchSelectGridColumns(multiple.value),
|
||||||
|
});
|
||||||
|
await resetQueryState();
|
||||||
|
await gridApi.query();
|
||||||
|
await nextTick();
|
||||||
|
await applyPreSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭批次选择弹窗 */
|
||||||
|
function closeModal() {
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认选择批次 */
|
||||||
|
function handleConfirm() {
|
||||||
|
const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value;
|
||||||
|
if (rows.length === 0) {
|
||||||
|
ElMessage.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('selected', multiple.value ? rows : [rows[0]!]);
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open: openModal });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ElDialog v-model="open" title="批次选择" width="80%">
|
||||||
|
<ElAlert
|
||||||
|
v-if="filterTip"
|
||||||
|
:closable="false"
|
||||||
|
class="!mb-3"
|
||||||
|
:title="filterTip"
|
||||||
|
type="info"
|
||||||
|
/>
|
||||||
|
<Grid table-title="批次列表" />
|
||||||
|
<template #footer>
|
||||||
|
<ElButton @click="closeModal">取消</ElButton>
|
||||||
|
<ElButton type="primary" @click="handleConfirm">确定</ElButton>
|
||||||
|
</template>
|
||||||
|
</ElDialog>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { MesWmBatchApi } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import { computed, ref, useAttrs, watch } from 'vue';
|
||||||
|
|
||||||
|
import { CircleX, Search } from '@vben/icons';
|
||||||
|
|
||||||
|
import { ElInput, ElTooltip } from 'element-plus';
|
||||||
|
|
||||||
|
import { getBatch } from '#/api/mes/wm/batch';
|
||||||
|
|
||||||
|
import WmBatchSelectDialog from './wm-batch-select-dialog.vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'WmBatchSelect', inheritAttrs: false });
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
clearable?: boolean;
|
||||||
|
clientId?: number; // 默认过滤的客户 ID
|
||||||
|
disabled?: boolean;
|
||||||
|
itemId?: number; // 默认过滤的物料 ID
|
||||||
|
modelValue?: number;
|
||||||
|
placeholder?: string;
|
||||||
|
salesOrderCode?: string; // 默认过滤的销售订单编号
|
||||||
|
vendorId?: number; // 默认过滤的供应商 ID
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
clearable: true,
|
||||||
|
clientId: undefined,
|
||||||
|
disabled: false,
|
||||||
|
itemId: undefined,
|
||||||
|
modelValue: undefined,
|
||||||
|
placeholder: '请选择批次',
|
||||||
|
salesOrderCode: undefined,
|
||||||
|
vendorId: undefined,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [item: MesWmBatchApi.Batch | undefined];
|
||||||
|
'update:modelValue': [value: number | undefined];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
const dialogRef = ref<InstanceType<typeof WmBatchSelectDialog>>();
|
||||||
|
const hovering = ref(false);
|
||||||
|
const selectedItem = ref<MesWmBatchApi.Batch>();
|
||||||
|
|
||||||
|
const displayLabel = computed(() => selectedItem.value?.code ?? '');
|
||||||
|
|
||||||
|
const showClear = computed(
|
||||||
|
() =>
|
||||||
|
props.clearable &&
|
||||||
|
!props.disabled &&
|
||||||
|
hovering.value &&
|
||||||
|
props.modelValue != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 根据编号单条查询批次信息(用于编辑回显) */
|
||||||
|
async function resolveItemById(id: number | undefined) {
|
||||||
|
if (id == null) {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedItem.value?.id === id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = await getBatch(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.modelValue, resolveItemById, { immediate: true });
|
||||||
|
|
||||||
|
/** 清空已选批次 */
|
||||||
|
function clearSelected() {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
emit('update:modelValue', undefined);
|
||||||
|
emit('change', undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开批次选择弹窗 */
|
||||||
|
function handleClick(event: MouseEvent) {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
if (showClear.value && target.closest('.el-input__suffix')) {
|
||||||
|
event.stopPropagation();
|
||||||
|
clearSelected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectedIds = props.modelValue == null ? [] : [props.modelValue];
|
||||||
|
dialogRef.value?.open(selectedIds, {
|
||||||
|
clientId: props.clientId,
|
||||||
|
itemId: props.itemId,
|
||||||
|
multiple: false,
|
||||||
|
salesOrderCode: props.salesOrderCode,
|
||||||
|
vendorId: props.vendorId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 弹窗选中回调 */
|
||||||
|
function handleSelected(rows: MesWmBatchApi.Batch[]) {
|
||||||
|
const item = rows[0];
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = item;
|
||||||
|
emit('update:modelValue', item.id);
|
||||||
|
emit('change', item);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-bind="attrs"
|
||||||
|
class="w-full"
|
||||||
|
:class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
|
||||||
|
@click="handleClick"
|
||||||
|
@mouseenter="hovering = true"
|
||||||
|
@mouseleave="hovering = false"
|
||||||
|
>
|
||||||
|
<ElTooltip :disabled="!selectedItem" placement="top" :show-after="500">
|
||||||
|
<template #content>
|
||||||
|
<div v-if="selectedItem" class="leading-6">
|
||||||
|
<div>批次编号:{{ selectedItem.code || '-' }}</div>
|
||||||
|
<div>物料编码:{{ selectedItem.itemCode || '-' }}</div>
|
||||||
|
<div>物料名称:{{ selectedItem.itemName || '-' }}</div>
|
||||||
|
<div>生产批号:{{ selectedItem.lotNumber || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<ElInput
|
||||||
|
:disabled="disabled"
|
||||||
|
:model-value="displayLabel"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
readonly
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<CircleX v-if="showClear" class="size-4" />
|
||||||
|
<Search v-else class="size-4" />
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
</ElTooltip>
|
||||||
|
</div>
|
||||||
|
<WmBatchSelectDialog ref="dialogRef" @selected="handleSelected" />
|
||||||
|
</template>
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export { default as DeptSelectModal } from './select-modal.vue';
|
export { default as DeptSelectModal } from './select-modal.vue';
|
||||||
|
export { default as DeptTreeSelect } from './tree-select.vue';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// TODO @jason:看看这个有没办法,整体代码的文件顺序,注释风格等,和 /Users/yunai/Java/yudao-ui-admin-vben-v5/apps/web-antd/src/views/system/dept/components/select-modal.vue 一致。原因是:好维护~
|
|
||||||
import type { SystemDeptApi } from '#/api/system/dept';
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
|
|
||||||
import { nextTick, ref } from 'vue';
|
import { nextTick, ref } from 'vue';
|
||||||
|
|
@ -15,16 +14,11 @@ defineOptions({ name: 'DeptSelectModal' });
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
// 取消按钮文本
|
cancelText?: string; // 取消按钮文本
|
||||||
cancelText?: string;
|
checkStrictly?: boolean; // checkable 状态下节点选择完全受控
|
||||||
// checkable 状态下节点选择完全受控
|
confirmText?: string; // 确认按钮文本
|
||||||
checkStrictly?: boolean;
|
multiple?: boolean; // 是否支持多选
|
||||||
// 确认按钮文本
|
title?: string; // 标题
|
||||||
confirmText?: string;
|
|
||||||
// 是否支持多选
|
|
||||||
multiple?: boolean;
|
|
||||||
// 标题
|
|
||||||
title?: string;
|
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
|
|
@ -39,16 +33,11 @@ const emit = defineEmits<{
|
||||||
confirm: [deptList: SystemDeptApi.Dept[]];
|
confirm: [deptList: SystemDeptApi.Dept[]];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 部门树形结构
|
const deptTree = ref<any[]>([]); // 部门树形结构
|
||||||
const deptTree = ref<any[]>([]);
|
const selectedDeptIds = ref<number[]>([]); // 选中的部门 ID 列表
|
||||||
// 选中的部门 ID 列表
|
const deptData = ref<SystemDeptApi.Dept[]>([]); // 部门数据
|
||||||
const selectedDeptIds = ref<number[]>([]);
|
const treeRef = ref(); // Tree 组件引用
|
||||||
// 部门数据
|
|
||||||
const deptData = ref<SystemDeptApi.Dept[]>([]);
|
|
||||||
// Tree 组件引用
|
|
||||||
const treeRef = ref();
|
|
||||||
|
|
||||||
// 对话框配置
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
const [Modal, modalApi] = useVbenModal({
|
||||||
async onConfirm() {
|
async onConfirm() {
|
||||||
// 获取选中的部门ID
|
// 获取选中的部门ID
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,18 @@ import { ElInput, ElTree } from 'element-plus';
|
||||||
|
|
||||||
import { getSimpleDeptList } from '#/api/system/dept';
|
import { getSimpleDeptList } from '#/api/system/dept';
|
||||||
|
|
||||||
const emit = defineEmits(['select']);
|
defineOptions({ name: 'DeptTreeSelect' });
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
select: [dept?: SystemDeptApi.Dept];
|
||||||
|
}>();
|
||||||
|
|
||||||
const deptList = ref<SystemDeptApi.Dept[]>([]); // 部门列表
|
const deptList = ref<SystemDeptApi.Dept[]>([]); // 部门列表
|
||||||
const deptTree = ref<any[]>([]); // 部门树
|
const deptTree = ref<any[]>([]); // 部门树
|
||||||
const expandedKeys = ref<number[]>([]); // 展开的节点
|
|
||||||
const loading = ref(false); // 加载状态
|
const loading = ref(false); // 加载状态
|
||||||
const searchValue = ref(''); // 搜索值
|
const searchValue = ref(''); // 搜索值
|
||||||
|
const treeRef = ref<InstanceType<typeof ElTree>>(); // 树 Ref
|
||||||
|
let currentNodeId: number | undefined; // 当前选中的节点 ID
|
||||||
|
|
||||||
/** 处理搜索逻辑 */
|
/** 处理搜索逻辑 */
|
||||||
function handleSearch(value: string) {
|
function handleSearch(value: string) {
|
||||||
|
|
@ -26,15 +32,31 @@ function handleSearch(value: string) {
|
||||||
)
|
)
|
||||||
: deptList.value;
|
: deptList.value;
|
||||||
deptTree.value = handleTree(filteredList);
|
deptTree.value = handleTree(filteredList);
|
||||||
// 展开所有节点
|
|
||||||
expandedKeys.value = deptTree.value.map((node) => node.id!);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 选中部门 */
|
/** 选中部门:点击已选中的节点时取消选中 */
|
||||||
function handleSelect(data: any) {
|
function handleSelect(data: SystemDeptApi.Dept) {
|
||||||
|
if (currentNodeId === data.id) {
|
||||||
|
currentNodeId = undefined;
|
||||||
|
treeRef.value?.setCurrentKey(undefined);
|
||||||
|
emit('select', undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentNodeId = data.id;
|
||||||
emit('select', data);
|
emit('select', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 重置选中状态(供外部重置按钮调用) */
|
||||||
|
function reset() {
|
||||||
|
searchValue.value = '';
|
||||||
|
currentNodeId = undefined;
|
||||||
|
treeRef.value?.setCurrentKey(undefined);
|
||||||
|
deptTree.value = handleTree(deptList.value);
|
||||||
|
emit('select', undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ reset });
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -42,8 +64,6 @@ onMounted(async () => {
|
||||||
const data = await getSimpleDeptList();
|
const data = await getSimpleDeptList();
|
||||||
deptList.value = data;
|
deptList.value = data;
|
||||||
deptTree.value = handleTree(data);
|
deptTree.value = handleTree(data);
|
||||||
} catch (error) {
|
|
||||||
console.error('获取部门数据失败', error);
|
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
@ -53,11 +73,11 @@ onMounted(async () => {
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<ElInput
|
<ElInput
|
||||||
placeholder="搜索部门"
|
|
||||||
clearable
|
|
||||||
v-model="searchValue"
|
v-model="searchValue"
|
||||||
@input="handleSearch"
|
|
||||||
class="w-full"
|
class="w-full"
|
||||||
|
clearable
|
||||||
|
placeholder="搜索部门"
|
||||||
|
@input="handleSearch"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<Search class="size-4" />
|
<Search class="size-4" />
|
||||||
|
|
@ -65,13 +85,15 @@ onMounted(async () => {
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
<ElTree
|
<ElTree
|
||||||
class="pt-2"
|
|
||||||
v-if="deptTree.length > 0"
|
v-if="deptTree.length > 0"
|
||||||
|
ref="treeRef"
|
||||||
|
class="pt-2"
|
||||||
:data="deptTree"
|
:data="deptTree"
|
||||||
|
default-expand-all
|
||||||
|
highlight-current
|
||||||
|
node-key="id"
|
||||||
:props="{ label: 'name', children: 'children' }"
|
:props="{ label: 'name', children: 'children' }"
|
||||||
@node-click="handleSelect"
|
@node-click="handleSelect"
|
||||||
default-expand-all
|
|
||||||
node-key="id"
|
|
||||||
/>
|
/>
|
||||||
<div v-else-if="!loading" class="py-4 text-center text-gray-500">
|
<div v-else-if="!loading" class="py-4 text-center text-gray-500">
|
||||||
暂无数据
|
暂无数据
|
||||||
|
|
@ -1 +1,3 @@
|
||||||
|
export { default as UserSelectDialog } from './select-dialog.vue';
|
||||||
export { default as UserSelectModal } from './select-modal.vue';
|
export { default as UserSelectModal } from './select-modal.vue';
|
||||||
|
export { default as UserSelect } from './select.vue';
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,298 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
|
import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
|
import { CommonStatusEnum, DICT_TYPE } from '@vben/constants';
|
||||||
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
|
||||||
|
import { ElButton, ElCol, ElDialog, ElMessage, ElRow } from 'element-plus';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getUserPage } from '#/api/system/user';
|
||||||
|
import { DeptTreeSelect } from '#/views/system/dept/components';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
selected: [rows: SystemUserApi.User[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const open = ref(false); // 弹窗是否打开
|
||||||
|
const multiple = ref(false); // 是否多选;默认按单选选择器使用
|
||||||
|
const selectedRows = ref<SystemUserApi.User[]>([]); // 已选用户列表
|
||||||
|
const preSelectedIds = ref<number[]>([]); // 预选用户编号列表
|
||||||
|
const deptId = ref<number>(); // 当前部门过滤
|
||||||
|
const deptTreeRef = ref<InstanceType<typeof DeptTreeSelect>>(); // 部门树
|
||||||
|
|
||||||
|
/** 用户选择弹窗的搜索表单 */
|
||||||
|
function useUserSelectGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'username',
|
||||||
|
label: '用户名称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
clearable: true,
|
||||||
|
placeholder: '请输入用户名称',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'nickname',
|
||||||
|
label: '用户昵称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
clearable: true,
|
||||||
|
placeholder: '请输入用户昵称',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'mobile',
|
||||||
|
label: '手机号码',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
clearable: true,
|
||||||
|
placeholder: '请输入手机号码',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'status',
|
||||||
|
label: '状态',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
clearable: true,
|
||||||
|
options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'),
|
||||||
|
placeholder: '请选择状态',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用户选择弹窗的字段 */
|
||||||
|
function useUserSelectGridColumns(
|
||||||
|
isMultiple = false,
|
||||||
|
): VxeTableGridOptions<SystemUserApi.User>['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: isMultiple ? 'checkbox' : 'radio',
|
||||||
|
width: 50,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'id',
|
||||||
|
title: '用户编号',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'username',
|
||||||
|
title: '用户名称',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'nickname',
|
||||||
|
title: '用户昵称',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'mobile',
|
||||||
|
title: '手机号码',
|
||||||
|
width: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: '状态',
|
||||||
|
width: 90,
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.COMMON_STATUS },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取多选记录,包含 VXE reserve 跨页记录 */
|
||||||
|
function getMultipleSelectedRows() {
|
||||||
|
const selectedMap = new Map<number, SystemUserApi.User>();
|
||||||
|
const records = [
|
||||||
|
...(gridApi.grid.getCheckboxReserveRecords?.() ?? []),
|
||||||
|
...(gridApi.grid.getCheckboxRecords?.() ?? []),
|
||||||
|
] as SystemUserApi.User[];
|
||||||
|
records.forEach((row) => {
|
||||||
|
const rowId = row.id;
|
||||||
|
if (rowId !== undefined) {
|
||||||
|
selectedMap.set(rowId, row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return [...selectedMap.values()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理多选勾选变化 */
|
||||||
|
function handleCheckboxSelectChange() {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理单选切换 */
|
||||||
|
function handleRadioChange(row: SystemUserApi.User) {
|
||||||
|
selectedRows.value = [row];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选模式下切换行勾选 */
|
||||||
|
async function toggleMultipleRow(row: SystemUserApi.User) {
|
||||||
|
const selected = gridApi.grid.isCheckedByCheckboxRow(row);
|
||||||
|
await gridApi.grid.setCheckboxRow(row, !selected);
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理行双击:单选直接确认,多选切换勾选 */
|
||||||
|
async function handleCellDblclick({ row }: { row: SystemUserApi.User }) {
|
||||||
|
if (multiple.value) {
|
||||||
|
await toggleMultipleRow(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedRows.value = [row];
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
handleConfirm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 回显预选用户 */
|
||||||
|
async function applyPreSelection() {
|
||||||
|
if (preSelectedIds.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rows = gridApi.grid.getData() as SystemUserApi.User[];
|
||||||
|
for (const row of rows) {
|
||||||
|
if (row.id === undefined || !preSelectedIds.value.includes(row.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
await gridApi.grid.setCheckboxRow(row, true);
|
||||||
|
} else {
|
||||||
|
await gridApi.grid.setRadioRow(row);
|
||||||
|
selectedRows.value = [row];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (multiple.value) {
|
||||||
|
selectedRows.value = getMultipleSelectedRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useUserSelectGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useUserSelectGridColumns(false),
|
||||||
|
height: 520,
|
||||||
|
keepSource: true,
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
range: true,
|
||||||
|
reserve: true,
|
||||||
|
},
|
||||||
|
radioConfig: {
|
||||||
|
highlight: true,
|
||||||
|
trigger: 'row',
|
||||||
|
},
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getUserPage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
deptId: deptId.value,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<SystemUserApi.User>,
|
||||||
|
gridEvents: {
|
||||||
|
cellDblclick: handleCellDblclick,
|
||||||
|
checkboxAll: handleCheckboxSelectChange,
|
||||||
|
checkboxChange: handleCheckboxSelectChange,
|
||||||
|
radioChange: ({ row }: { row: SystemUserApi.User }) => {
|
||||||
|
handleRadioChange(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 部门树节点点击 */
|
||||||
|
function handleDeptNodeClick(dept?: SystemDeptApi.Dept) {
|
||||||
|
deptId.value = dept?.id;
|
||||||
|
gridApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置查询和选择状态 */
|
||||||
|
async function resetQueryState() {
|
||||||
|
selectedRows.value = [];
|
||||||
|
deptId.value = undefined;
|
||||||
|
await gridApi.grid.clearCheckboxRow();
|
||||||
|
await gridApi.grid.clearCheckboxReserve();
|
||||||
|
await gridApi.grid.clearRadioRow();
|
||||||
|
await gridApi.formApi.resetForm();
|
||||||
|
deptTreeRef.value?.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开用户选择弹窗 */
|
||||||
|
async function openModal(
|
||||||
|
selectedIds?: number[],
|
||||||
|
options?: { multiple?: boolean },
|
||||||
|
) {
|
||||||
|
open.value = true;
|
||||||
|
multiple.value = options?.multiple ?? false;
|
||||||
|
preSelectedIds.value = selectedIds || [];
|
||||||
|
await nextTick();
|
||||||
|
gridApi.setGridOptions({
|
||||||
|
columns: useUserSelectGridColumns(multiple.value),
|
||||||
|
});
|
||||||
|
await resetQueryState();
|
||||||
|
await gridApi.formApi.setFieldValue('status', CommonStatusEnum.ENABLE);
|
||||||
|
await gridApi.query();
|
||||||
|
await nextTick();
|
||||||
|
await applyPreSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭用户选择弹窗 */
|
||||||
|
function closeModal() {
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认选择用户 */
|
||||||
|
function handleConfirm() {
|
||||||
|
const rows = multiple.value ? getMultipleSelectedRows() : selectedRows.value;
|
||||||
|
if (rows.length === 0) {
|
||||||
|
ElMessage.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('selected', multiple.value ? rows : [rows[0]!]);
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open: openModal });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ElDialog v-model="open" title="人员选择" width="80%">
|
||||||
|
<ElRow :gutter="12">
|
||||||
|
<ElCol :span="5">
|
||||||
|
<DeptTreeSelect ref="deptTreeRef" @select="handleDeptNodeClick" />
|
||||||
|
</ElCol>
|
||||||
|
<ElCol :span="19">
|
||||||
|
<Grid table-title="用户列表" />
|
||||||
|
</ElCol>
|
||||||
|
</ElRow>
|
||||||
|
<template #footer>
|
||||||
|
<ElButton @click="closeModal">取消</ElButton>
|
||||||
|
<ElButton type="primary" @click="handleConfirm">确定</ElButton>
|
||||||
|
</template>
|
||||||
|
</ElDialog>
|
||||||
|
</template>
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// TODO @jason:看看这个有没办法,整体代码的文件顺序,注释风格等,和 /Users/yunai/Java/yudao-ui-admin-vben-v5/apps/web-antd/src/views/system/user/components/select-modal.vue 一致。原因是:好维护~
|
|
||||||
import type { SystemDeptApi } from '#/api/system/dept';
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
import type { SystemUserApi } from '#/api/system/user';
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
|
|
@ -22,7 +21,7 @@ import {
|
||||||
import { getSimpleDeptList } from '#/api/system/dept';
|
import { getSimpleDeptList } from '#/api/system/dept';
|
||||||
import { getUserPage } from '#/api/system/user';
|
import { getUserPage } from '#/api/system/user';
|
||||||
|
|
||||||
// 部门树节点接口
|
/** 部门树节点接口 */
|
||||||
interface DeptTreeNode {
|
interface DeptTreeNode {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
|
@ -67,7 +66,6 @@ const deptSearchKeys = ref('');
|
||||||
const userList = ref<SystemUserApi.User[]>([]); // 存储所有已知用户
|
const userList = ref<SystemUserApi.User[]>([]); // 存储所有已知用户
|
||||||
const selectedUserIds = ref<number[]>([]);
|
const selectedUserIds = ref<number[]>([]);
|
||||||
|
|
||||||
// 弹窗配置
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
const [Modal, modalApi] = useVbenModal({
|
||||||
onCancel: handleCancel,
|
onCancel: handleCancel,
|
||||||
onClosed: handleClosed,
|
onClosed: handleClosed,
|
||||||
|
|
@ -143,7 +141,7 @@ const rightListState = ref({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 计算属性:Transfer 数据源
|
/** 计算属性:Transfer 数据源 */
|
||||||
const transferDataSource = computed(() => {
|
const transferDataSource = computed(() => {
|
||||||
// 使用 Map 来去重,确保每个用户只出现一次
|
// 使用 Map 来去重,确保每个用户只出现一次
|
||||||
const userMap = new Map<number, any>();
|
const userMap = new Map<number, any>();
|
||||||
|
|
@ -170,7 +168,7 @@ const transferDataSource = computed(() => {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
// 过滤部门树数据
|
/** 过滤部门树数据 */
|
||||||
const filteredDeptTree = computed(() => {
|
const filteredDeptTree = computed(() => {
|
||||||
if (!deptSearchKeys.value) return deptTree.value;
|
if (!deptSearchKeys.value) return deptTree.value;
|
||||||
|
|
||||||
|
|
@ -210,7 +208,7 @@ const filteredDeptTree = computed(() => {
|
||||||
return deptTree.value.map((node: any) => filterNode(node)).filter(Boolean);
|
return deptTree.value.map((node: any) => filterNode(node)).filter(Boolean);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载用户数据
|
/** 加载用户数据 */
|
||||||
async function loadUserData(pageNo: number, pageSize: number) {
|
async function loadUserData(pageNo: number, pageSize: number) {
|
||||||
try {
|
try {
|
||||||
const { list, total } = await getUserPage({
|
const { list, total } = await getUserPage({
|
||||||
|
|
@ -237,7 +235,7 @@ async function loadUserData(pageNo: number, pageSize: number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新右侧列表数据
|
/** 更新右侧列表数据 */
|
||||||
function updateRightListData() {
|
function updateRightListData() {
|
||||||
// 使用 Set 来去重选中的用户ID
|
// 使用 Set 来去重选中的用户ID
|
||||||
const uniqueSelectedIds = new Set(selectedUserIds.value);
|
const uniqueSelectedIds = new Set(selectedUserIds.value);
|
||||||
|
|
@ -269,18 +267,18 @@ function updateRightListData() {
|
||||||
rightListState.value.dataSource = filteredUsers.slice(startIndex, endIndex);
|
rightListState.value.dataSource = filteredUsers.slice(startIndex, endIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理左侧分页变化
|
/** 处理左侧分页变化 */
|
||||||
async function handleLeftPaginationChange(page: number) {
|
async function handleLeftPaginationChange(page: number) {
|
||||||
await loadUserData(page, leftListState.value.pagination.pageSize);
|
await loadUserData(page, leftListState.value.pagination.pageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理右侧分页变化
|
/** 处理右侧分页变化 */
|
||||||
function handleRightPaginationChange(page: number) {
|
function handleRightPaginationChange(page: number) {
|
||||||
rightListState.value.pagination.current = page;
|
rightListState.value.pagination.current = page;
|
||||||
updateRightListData();
|
updateRightListData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理用户选择变化
|
/** 处理用户选择变化 */
|
||||||
function handleUserChange(
|
function handleUserChange(
|
||||||
value: (number | string)[],
|
value: (number | string)[],
|
||||||
_direction: string,
|
_direction: string,
|
||||||
|
|
@ -292,7 +290,7 @@ function handleUserChange(
|
||||||
updateRightListData();
|
updateRightListData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置数据
|
/** 重置数据 */
|
||||||
function resetData() {
|
function resetData() {
|
||||||
userList.value = [];
|
userList.value = [];
|
||||||
selectedUserIds.value = [];
|
selectedUserIds.value = [];
|
||||||
|
|
@ -324,7 +322,7 @@ function resetData() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理部门搜索
|
/** 处理部门搜索 */
|
||||||
function handleDeptSearch(value: string) {
|
function handleDeptSearch(value: string) {
|
||||||
deptSearchKeys.value = value;
|
deptSearchKeys.value = value;
|
||||||
|
|
||||||
|
|
@ -347,7 +345,7 @@ function handleDeptSearch(value: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理部门选择
|
/** 处理部门选择 */
|
||||||
async function handleDeptSelect(node: any) {
|
async function handleDeptSelect(node: any) {
|
||||||
// 更新选中的部门ID
|
// 更新选中的部门ID
|
||||||
const newDeptId = node.id ? Number(node.id) : undefined;
|
const newDeptId = node.id ? Number(node.id) : undefined;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
|
import { computed, ref, useAttrs, watch } from 'vue';
|
||||||
|
|
||||||
|
import { CircleX, Search } from '@vben/icons';
|
||||||
|
|
||||||
|
import { ElInput, ElTooltip } from 'element-plus';
|
||||||
|
|
||||||
|
import { getUser } from '#/api/system/user';
|
||||||
|
|
||||||
|
import UserSelectDialog from './select-dialog.vue';
|
||||||
|
|
||||||
|
defineOptions({ name: 'UserSelect', inheritAttrs: false });
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
clearable?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
modelValue?: number;
|
||||||
|
placeholder?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
clearable: true,
|
||||||
|
disabled: false,
|
||||||
|
modelValue: undefined,
|
||||||
|
placeholder: '请选择用户',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [item: SystemUserApi.User | undefined];
|
||||||
|
'update:modelValue': [value: number | undefined];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
const dialogRef = ref<InstanceType<typeof UserSelectDialog>>();
|
||||||
|
const hovering = ref(false);
|
||||||
|
const selectedItem = ref<SystemUserApi.User>();
|
||||||
|
|
||||||
|
const displayLabel = computed(
|
||||||
|
() => selectedItem.value?.nickname ?? selectedItem.value?.username ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
|
const showClear = computed(
|
||||||
|
() =>
|
||||||
|
props.clearable &&
|
||||||
|
!props.disabled &&
|
||||||
|
hovering.value &&
|
||||||
|
props.modelValue != null,
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 根据编号单条查询用户信息(用于编辑回显) */
|
||||||
|
async function resolveItemById(id: number | undefined) {
|
||||||
|
if (id == null) {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selectedItem.value?.id === id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = await getUser(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.modelValue, resolveItemById, { immediate: true });
|
||||||
|
|
||||||
|
/** 清空已选用户 */
|
||||||
|
function clearSelected() {
|
||||||
|
selectedItem.value = undefined;
|
||||||
|
emit('update:modelValue', undefined);
|
||||||
|
emit('change', undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开用户选择弹窗 */
|
||||||
|
function handleClick(event: MouseEvent) {
|
||||||
|
if (props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
if (showClear.value && target.closest('.el-input__suffix')) {
|
||||||
|
event.stopPropagation();
|
||||||
|
clearSelected();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectedIds = props.modelValue == null ? [] : [props.modelValue];
|
||||||
|
dialogRef.value?.open(selectedIds, { multiple: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 弹窗选中回调 */
|
||||||
|
function handleSelected(rows: SystemUserApi.User[]) {
|
||||||
|
const item = rows[0];
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectedItem.value = item;
|
||||||
|
emit('update:modelValue', item.id);
|
||||||
|
emit('change', item);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-bind="attrs"
|
||||||
|
class="w-full"
|
||||||
|
:class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
|
||||||
|
@click="handleClick"
|
||||||
|
@mouseenter="hovering = true"
|
||||||
|
@mouseleave="hovering = false"
|
||||||
|
>
|
||||||
|
<ElTooltip :disabled="!selectedItem" placement="top" :show-after="500">
|
||||||
|
<template #content>
|
||||||
|
<div v-if="selectedItem" class="leading-6">
|
||||||
|
<div>用户名称:{{ selectedItem.username || '-' }}</div>
|
||||||
|
<div>用户昵称:{{ selectedItem.nickname || '-' }}</div>
|
||||||
|
<div>手机号码:{{ selectedItem.mobile || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<ElInput
|
||||||
|
:disabled="disabled"
|
||||||
|
:model-value="displayLabel"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
readonly
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<CircleX v-if="showClear" class="size-4" />
|
||||||
|
<Search v-else class="size-4" />
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
</ElTooltip>
|
||||||
|
</div>
|
||||||
|
<UserSelectDialog ref="dialogRef" @selected="handleSelected" />
|
||||||
|
</template>
|
||||||
|
|
@ -21,10 +21,10 @@ import {
|
||||||
updateUserStatus,
|
updateUserStatus,
|
||||||
} from '#/api/system/user';
|
} from '#/api/system/user';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
import { DeptTreeSelect } from '#/views/system/dept/components';
|
||||||
|
|
||||||
import { useGridColumns, useGridFormSchema } from './data';
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
import AssignRoleForm from './modules/assign-role-form.vue';
|
import AssignRoleForm from './modules/assign-role-form.vue';
|
||||||
import DeptTree from './modules/dept-tree.vue';
|
|
||||||
import Form from './modules/form.vue';
|
import Form from './modules/form.vue';
|
||||||
import ImportForm from './modules/import-form.vue';
|
import ImportForm from './modules/import-form.vue';
|
||||||
import ResetPasswordForm from './modules/reset-password-form.vue';
|
import ResetPasswordForm from './modules/reset-password-form.vue';
|
||||||
|
|
@ -62,8 +62,8 @@ async function handleExport() {
|
||||||
|
|
||||||
/** 选择部门 */
|
/** 选择部门 */
|
||||||
const searchDeptId = ref<number | undefined>(undefined);
|
const searchDeptId = ref<number | undefined>(undefined);
|
||||||
async function handleDeptSelect(dept: SystemDeptApi.Dept) {
|
async function handleDeptSelect(dept?: SystemDeptApi.Dept) {
|
||||||
searchDeptId.value = dept.id;
|
searchDeptId.value = dept?.id;
|
||||||
handleRefresh();
|
handleRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,7 +203,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<div class="flex h-full w-full">
|
<div class="flex h-full w-full">
|
||||||
<!-- 左侧部门树 -->
|
<!-- 左侧部门树 -->
|
||||||
<ElCard class="mr-4 h-full w-1/6">
|
<ElCard class="mr-4 h-full w-1/6">
|
||||||
<DeptTree @select="handleDeptSelect" />
|
<DeptTreeSelect @select="handleDeptSelect" />
|
||||||
</ElCard>
|
</ElCard>
|
||||||
<!-- 右侧用户列表 -->
|
<!-- 右侧用户列表 -->
|
||||||
<div class="w-5/6">
|
<div class="w-5/6">
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,19 @@ const MES_DICT = {
|
||||||
MES_WM_MISC_RECEIPT_STATUS: 'mes_wm_misc_receipt_status', // MES 杂项入库单状态
|
MES_WM_MISC_RECEIPT_STATUS: 'mes_wm_misc_receipt_status', // MES 杂项入库单状态
|
||||||
MES_WM_OUTSOURCE_ISSUE_STATUS: 'mes_wm_outsource_issue_status', // MES 外协发料单状态
|
MES_WM_OUTSOURCE_ISSUE_STATUS: 'mes_wm_outsource_issue_status', // MES 外协发料单状态
|
||||||
MES_WM_OUTSOURCE_RECEIPT_STATUS: 'mes_wm_outsource_receipt_status', // MES 外协入库单状态
|
MES_WM_OUTSOURCE_RECEIPT_STATUS: 'mes_wm_outsource_receipt_status', // MES 外协入库单状态
|
||||||
|
MES_WM_ARRIVAL_NOTICE_STATUS: 'mes_wm_arrival_notice_status', // MES 到货通知单状态
|
||||||
|
MES_WM_ITEM_RECEIPT_STATUS: 'mes_wm_item_receipt_status', // MES 采购入库单状态
|
||||||
|
MES_WM_RETURN_VENDOR_STATUS: 'mes_wm_return_vendor_status', // MES 供应商退货单状态
|
||||||
|
MES_WM_SALES_NOTICE_STATUS: 'mes_wm_sales_notice_status', // MES 发货通知单状态
|
||||||
|
MES_WM_RETURN_SALES_STATUS: 'mes_wm_return_sales_status', // MES 销售退货单状态
|
||||||
|
MES_WM_RETURN_ISSUE_STATUS: 'mes_wm_return_issue_status', // MES 生产退料单状态
|
||||||
|
MES_WM_RETURN_ISSUE_TYPE: 'mes_wm_return_issue_type', // MES 退料类型
|
||||||
|
MES_WM_PRODUCT_ISSUE_STATUS: 'mes_wm_product_issue_status', // MES 领料出库单状态
|
||||||
|
MES_WM_PRODUCT_RECEIPT_STATUS: 'mes_wm_product_receipt_status', // MES 产品入库单状态
|
||||||
|
MES_WM_STOCK_TAKING_TYPE: 'mes_wm_stock_taking_type', // MES 盘点类型
|
||||||
|
MES_WM_STOCK_TAKING_TASK_STATUS: 'mes_wm_stock_taking_task_status', // MES 盘点任务状态
|
||||||
|
MES_WM_STOCK_TAKING_LINE_STATUS: 'mes_wm_stock_taking_task_line_status', // MES 盘点任务行状态
|
||||||
|
MES_WM_STOCK_TAKING_PLAN_PARAM_TYPE: 'mes_wm_stock_taking_plan_param_type', // MES 盘点方案参数类型
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
/** ========== WMS - 仓储管理模块 ========== */
|
/** ========== WMS - 仓储管理模块 ========== */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue