| | |
| | | return String(value ?? '').trim() |
| | | } |
| | | |
| | | function normalizeIds(ids) { |
| | | if (Array.isArray(ids)) { |
| | | return ids |
| | | .map((item) => Number(item)) |
| | | .filter((item) => Number.isFinite(item)) |
| | | .join(',') |
| | | } |
| | | return String(ids ?? '') |
| | | .split(',') |
| | | .map((item) => Number(item)) |
| | | .filter((item) => Number.isFinite(item)) |
| | | .join(',') |
| | | } |
| | | |
| | | function normalizeIdList(ids) { |
| | | if (Array.isArray(ids)) { |
| | | return ids.map((item) => Number(item)).filter((item) => Number.isFinite(item)) |
| | | } |
| | | return String(ids ?? '') |
| | | .split(',') |
| | | .map((item) => Number(item)) |
| | | .filter((item) => Number.isFinite(item)) |
| | | } |
| | | |
| | | function normalizeQueryParams(params = {}) { |
| | | const allowKeys = new Set([ |
| | | 'condition', |
| | | 'code', |
| | | 'name', |
| | | 'spec', |
| | | 'model', |
| | | 'color', |
| | | 'size', |
| | | 'barcode', |
| | | 'groupId', |
| | | 'unit', |
| | | 'status', |
| | | 'flagCheck', |
| | | 'validWarn' |
| | | ]) |
| | | const result = { |
| | | current: params.current || 1, |
| | | pageSize: params.pageSize || params.size || 20 |
| | | pageSize: params.pageSize || params.size || 20, |
| | | orderBy: normalizeText(params.orderBy) || 'create_time desc' |
| | | } |
| | | |
| | | ;['condition', 'code', 'name', 'spec', 'model', 'color', 'size', 'barcode', 'groupId'].forEach((key) => { |
| | | Array.from(allowKeys).forEach((key) => { |
| | | const value = params[key] |
| | | if (value === undefined || value === null || value === '') { |
| | | return |
| | |
| | | const trimmed = normalizeText(value) |
| | | if (trimmed) { |
| | | result[key] = trimmed |
| | | } |
| | | return |
| | | } |
| | | result[key] = value |
| | | }) |
| | | |
| | | Object.entries(params).forEach(([key, value]) => { |
| | | if (['current', 'pageSize', 'size', 'orderBy'].includes(key) || allowKeys.has(key)) { |
| | | return |
| | | } |
| | | if (value === undefined || value === null || value === '') { |
| | | return |
| | | } |
| | | if (typeof value === 'string') { |
| | | const trimmed = normalizeText(value) |
| | | if (trimmed) { |
| | | result[key] = trimmed |
| | | } |
| | | return |
| | | } |
| | | if (Array.isArray(value)) { |
| | | if (value.length) { |
| | | result[key] = value |
| | | } |
| | | return |
| | | } |
| | |
| | | return request.get({ url: `/matnr/${id}` }) |
| | | } |
| | | |
| | | export function fetchGetMatnrMany(ids) { |
| | | return request.post({ url: `/matnr/many/${normalizeIds(ids)}` }) |
| | | } |
| | | |
| | | export function fetchEnabledFields() { |
| | | return request.get({ url: '/fields/enable/list' }) |
| | | } |
| | | |
| | | export function fetchSaveMatnr(params = {}) { |
| | | return request.post({ url: '/matnr/save', params }) |
| | | } |
| | | |
| | | export function fetchUpdateMatnr(params = {}) { |
| | | return request.post({ url: '/matnr/update', params }) |
| | | } |
| | | |
| | | export function fetchDeleteMatnr(ids) { |
| | | return request.post({ url: `/matnr/remove/${normalizeIds(ids)}` }) |
| | | } |
| | | |
| | | export function fetchBindMatnrGroup(payload = {}) { |
| | | return request.post({ |
| | | url: '/matnr/group/bind', |
| | | params: { |
| | | ids: normalizeIdList(payload.ids), |
| | | ...(payload.groupId !== undefined && payload.groupId !== null && payload.groupId !== '' |
| | | ? { groupId: Number(payload.groupId) } |
| | | : {}) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export function fetchBatchUpdateMatnr(payload = {}) { |
| | | const matnr = payload.matnr && typeof payload.matnr === 'object' ? payload.matnr : {} |
| | | return request.post({ |
| | | url: '/matnr/batch/update', |
| | | params: { |
| | | ids: normalizeIdList(payload.ids), |
| | | matnr: Object.fromEntries( |
| | | Object.entries(matnr).filter( |
| | | ([, value]) => value !== undefined && value !== null && value !== '' |
| | | ) |
| | | ) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export function fetchMatnrGroupTree(params = {}) { |
| | | return request.post({ |
| | | url: '/matnrGroup/tree', |
| | |
| | | }) |
| | | } |
| | | |
| | | export async function fetchExportMatnrReport(payload = {}, options = {}) { |
| | | return fetch(`${import.meta.env.VITE_API_URL}/matnr/export`, { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Content-Type': 'application/json', |
| | | ...(options.headers || {}) |
| | | }, |
| | | body: JSON.stringify(payload) |
| | | }) |
| | | } |
| | | |
| | | export async function fetchDownloadMatnrTemplate(payload = {}, options = {}) { |
| | | return fetch(`${import.meta.env.VITE_API_URL}/matnr/template/download`, { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Content-Type': 'application/json', |
| | | ...(options.headers || {}) |
| | | }, |
| | | body: JSON.stringify(payload) |
| | | }) |
| | | } |
| | | |
| | | export function fetchImportMatnr(file) { |
| | | const formData = new FormData() |
| | | formData.append('file', file) |
| | | return request.post({ |
| | | url: '/matnr/import', |
| | | data: formData, |
| | | headers: { |
| | | 'Content-Type': 'multipart/form-data' |
| | | } |
| | | }) |
| | | } |
| | |
| | | const BUTTON_ACTION_MAP = { |
| | | query: 'list', |
| | | add: 'save', |
| | | update: 'update', |
| | | edit: 'update', |
| | | delete: 'remove' |
| | | } |
| | |
| | | "setting": { |
| | | "menuType": { |
| | | "title": "Menu Layout", |
| | | "list": [ |
| | | "Vertical", |
| | | "Horizontal", |
| | | "Mixed", |
| | | "Dual" |
| | | ] |
| | | "list": ["Vertical", "Horizontal", "Mixed", "Dual"] |
| | | }, |
| | | "theme": { |
| | | "title": "Theme Style", |
| | | "list": [ |
| | | "Light", |
| | | "Dark", |
| | | "System" |
| | | ] |
| | | "list": ["Light", "Dark", "System"] |
| | | }, |
| | | "menu": { |
| | | "title": "Menu Style" |
| | |
| | | }, |
| | | "box": { |
| | | "title": "Box Style", |
| | | "list": [ |
| | | "Border", |
| | | "Shadow" |
| | | ] |
| | | "list": ["Border", "Shadow"] |
| | | }, |
| | | "container": { |
| | | "title": "Container Width", |
| | | "list": [ |
| | | "Full", |
| | | "Boxed" |
| | | ] |
| | | "list": ["Full", "Boxed"] |
| | | }, |
| | | "basics": { |
| | | "title": "Basic Config", |
| | |
| | | "send": "Send", |
| | | "renameDialogTitle": "Rename Session", |
| | | "sessionTitleField": "Session Title", |
| | | "requestMetric": "Req: {value}", |
| | | "sessionMetric": "Session: {id}", |
| | | "promptMetric": "Prompt: {value}", |
| | | "modelMetric": "Model: {value}", |
| | | "promptLabel": "Prompt", |
| | | "modelLabel": "Model", |
| | | "modelSelectorLabel": "Chat Model", |
| | | "modelSelectorHint": "Switching only affects subsequent replies in this session and does not change the global default model.", |
| | | "modelSwitchFailed": "Failed to switch the chat model", |
| | | "defaultModelSuffix": "(Default)", |
| | | "mcpMetric": "MCP: {value}", |
| | | "historyMetric": "History: {value}", |
| | | "mcpLabel": "MCP", |
| | | "historyLabel": "History", |
| | | "recentMetric": "Recent: {value}", |
| | | "requestMetric": "Req: {value}", |
| | | "sessionMetric": "Session: {id}", |
| | | "promptMetric": "Prompt: {value}", |
| | | "modelMetric": "Model: {value}", |
| | | "promptLabel": "Prompt", |
| | | "modelLabel": "Model", |
| | | "modelSelectorLabel": "Chat Model", |
| | | "modelSelectorHint": "Switching only affects subsequent replies in this session and does not change the global default model.", |
| | | "modelSwitchFailed": "Failed to switch the chat model", |
| | | "defaultModelSuffix": "(Default)", |
| | | "mcpMetric": "MCP: {value}", |
| | | "historyMetric": "History: {value}", |
| | | "mcpLabel": "MCP", |
| | | "historyLabel": "History", |
| | | "recentMetric": "Recent: {value}", |
| | | "elapsedMetric": "Elapsed: {value} ms", |
| | | "firstTokenMetric": "First token: {value} ms", |
| | | "tokenMetric": "Tokens: prompt {prompt} / completion {completion} / total {total}", |
| | |
| | | "systemPrompt": "System Prompt", |
| | | "userPromptTemplate": "User Prompt Template" |
| | | }, |
| | | "dialog": { |
| | | "titleCreate": "Create Prompt", |
| | | "titleEdit": "Edit Prompt", |
| | | "titleDetail": "Prompt Detail", |
| | | "defaultPreviewInput": "Please summarize the current input", |
| | | "previewTitle": "Render Preview", |
| | | "dialog": { |
| | | "titleCreate": "Create Prompt", |
| | | "titleEdit": "Edit Prompt", |
| | | "titleDetail": "Prompt Detail", |
| | | "defaultPreviewInput": "Please summarize the current input", |
| | | "previewTitle": "Render Preview", |
| | | "previewDescription": "Input sample content and metadata to preview the final rendering.", |
| | | "previewAction": "Render Preview", |
| | | "previewResolvedVariables": "Resolved variables: {value}", |
| | |
| | | }, |
| | | "whMat": { |
| | | "title": "Materials", |
| | | "entity": "Material", |
| | | "labels": { |
| | | "allMaterials": "All Materials" |
| | | }, |
| | | "actions": { |
| | | "add": "Add Material", |
| | | "batchGroup": "Batch Group", |
| | | "batchWarn": "Batch Warning", |
| | | "batchFlagCheck": "Batch QC", |
| | | "batchStatus": "Batch Status", |
| | | "batchStockLevel": "Batch Stock Level", |
| | | "bindLoc": "Bind Location", |
| | | "import": "Import", |
| | | "downloadTemplate": "Download Template" |
| | | }, |
| | | "search": { |
| | | "groupKeywordPlaceholder": "Search material groups", |
| | |
| | | "codePlaceholder": "Enter material code", |
| | | "name": "Material Name", |
| | | "namePlaceholder": "Enter material name", |
| | | "groupId": "Material Group", |
| | | "groupIdPlaceholder": "Select material group", |
| | | "platCode": "Platform Code", |
| | | "platCodePlaceholder": "Enter platform code", |
| | | "spec": "Specification", |
| | | "specPlaceholder": "Enter specification", |
| | | "model": "Model", |
| | | "modelPlaceholder": "Enter model", |
| | | "color": "Color", |
| | | "colorPlaceholder": "Enter color", |
| | | "size": "Size", |
| | | "sizePlaceholder": "Enter size", |
| | | "unit": "Unit", |
| | | "unitPlaceholder": "Enter unit", |
| | | "purUnit": "Purchase Unit", |
| | | "purUnitPlaceholder": "Enter purchase unit", |
| | | "stockUnit": "Stock Unit", |
| | | "stockUnitPlaceholder": "Enter stock unit", |
| | | "barcode": "Barcode", |
| | | "barcodePlaceholder": "Enter barcode" |
| | | "barcodePlaceholder": "Enter barcode", |
| | | "describle": "Description", |
| | | "describlePlaceholder": "Enter description", |
| | | "rglarId": "Batch Rule", |
| | | "rglarIdPlaceholder": "Select batch rule", |
| | | "weight": "Weight", |
| | | "weightPlaceholder": "Enter weight", |
| | | "nromNum": "Standard Pack Qty", |
| | | "nromNumPlaceholder": "Enter standard pack qty", |
| | | "stockLevel": "Stock Level", |
| | | "stockLevelPlaceholder": "Select stock level", |
| | | "flagLabelMange": "Label Management", |
| | | "flagLabelMangePlaceholder": "Select label management", |
| | | "safeQty": "Safe Qty", |
| | | "safeQtyPlaceholder": "Enter safe qty", |
| | | "minQty": "Min Qty", |
| | | "minQtyPlaceholder": "Enter min qty", |
| | | "maxQty": "Max Qty", |
| | | "maxQtyPlaceholder": "Enter max qty", |
| | | "stagn": "Stagnant Days", |
| | | "stagnPlaceholder": "Enter stagnant days", |
| | | "valid": "Shelf Life Days", |
| | | "validPlaceholder": "Enter shelf life days", |
| | | "validWarn": "Expiry Warning", |
| | | "validWarnPlaceholder": "Enter expiry warning", |
| | | "flagCheck": "Exempt Inspection", |
| | | "flagCheckPlaceholder": "Select exempt inspection", |
| | | "status": "Status", |
| | | "statusPlaceholder": "Select status", |
| | | "memo": "Memo", |
| | | "memoPlaceholder": "Enter memo", |
| | | "dynamicPlaceholder": "Enter {field}" |
| | | }, |
| | | "messages": { |
| | | "emptyGroups": "No material groups", |
| | | "groupTimeout": "Material groups loading timed out and waiting has stopped", |
| | | "groupLoadFailed": "Failed to load material groups", |
| | | "serialRuleTimeout": "Batch rules loading timed out and waiting has stopped", |
| | | "serialRuleLoadFailed": "Failed to load batch rules", |
| | | "listTimeout": "Material list loading timed out and waiting has stopped", |
| | | "listLoadFailed": "Failed to load material list", |
| | | "detailTimeout": "Material detail timed out and waiting has stopped", |
| | | "detailLoadFailed": "Failed to load material detail" |
| | | "detailLoadFailed": "Failed to load material detail", |
| | | "importSuccess": "Material import succeeded", |
| | | "importFailed": "Material import failed", |
| | | "templateDownloadSuccess": "Template downloaded successfully", |
| | | "templateDownloadFailed": "Template download failed", |
| | | "enabledFieldsTimeout": "Dynamic fields loading timed out", |
| | | "bindLocTimeout": "Bind-location options loading timed out", |
| | | "bindLocLoadFailed": "Failed to load bind-location options", |
| | | "selectAtLeastOne": "Please select at least one material" |
| | | }, |
| | | "table": { |
| | | "code": "Material Code", |
| | |
| | | "spec": "Specification", |
| | | "model": "Model" |
| | | }, |
| | | "dialog": { |
| | | "titleCreate": "Add Material", |
| | | "titleEdit": "Edit Material", |
| | | "tabs": { |
| | | "basic": "Basic Information", |
| | | "control": "Control Information", |
| | | "batchRule": "Batch Rule" |
| | | }, |
| | | "fields": { |
| | | "code": "Material Code", |
| | | "name": "Material Name", |
| | | "groupId": "Material Group", |
| | | "useOrgName": "Using Organization", |
| | | "spec": "Specification", |
| | | "model": "Model", |
| | | "color": "Color", |
| | | "size": "Size", |
| | | "weight": "Weight", |
| | | "unit": "Unit", |
| | | "purUnit": "Purchase Unit", |
| | | "describle": "Description", |
| | | "safeQty": "Safety Stock", |
| | | "minQty": "Minimum Stock", |
| | | "maxQty": "Maximum Stock", |
| | | "stagn": "Stagnation Days", |
| | | "valid": "Shelf Life Days", |
| | | "validWarn": "Validity Warning Threshold", |
| | | "flagCheck": "Exempt Inspection", |
| | | "rglarId": "Batch Rule" |
| | | }, |
| | | "placeholders": { |
| | | "code": "Enter material code", |
| | | "name": "Enter material name", |
| | | "groupId": "Select material group", |
| | | "useOrgName": "Enter using organization", |
| | | "spec": "Enter specification", |
| | | "model": "Enter model", |
| | | "color": "Enter color", |
| | | "size": "Enter size", |
| | | "unit": "Enter unit", |
| | | "purUnit": "Enter purchase unit", |
| | | "describle": "Enter description", |
| | | "flagCheck": "Select exempt inspection", |
| | | "rglarId": "Select batch rule" |
| | | }, |
| | | "validation": { |
| | | "code": "Please enter material code", |
| | | "name": "Please enter material name", |
| | | "groupId": "Please select material group" |
| | | } |
| | | }, |
| | | "batchDialog": { |
| | | "titles": { |
| | | "status": "Batch Update Status", |
| | | "stockLevel": "Batch Update Stock Level", |
| | | "validWarn": "Batch Update Expiry Warning", |
| | | "flagCheck": "Batch Update QC Status" |
| | | }, |
| | | "fields": { |
| | | "stockLevel": "Stock Level" |
| | | }, |
| | | "placeholders": { |
| | | "stockLevel": "Select stock level", |
| | | "validWarn": "Enter expiry warning", |
| | | "valid": "Enter shelf life days", |
| | | "flagCheck": "Select exempt inspection" |
| | | }, |
| | | "validation": { |
| | | "status": "Please select status", |
| | | "stockLevel": "Please select stock level", |
| | | "validWarn": "Please enter expiry warning", |
| | | "valid": "Please enter shelf life days", |
| | | "flagCheck": "Please select exempt inspection" |
| | | } |
| | | }, |
| | | "batchGroupDialog": { |
| | | "title": "Batch Update Material Group" |
| | | }, |
| | | "bindLocDialog": { |
| | | "title": "Bind Location", |
| | | "fields": { |
| | | "areaMatId": "Area Material", |
| | | "areaId": "Area", |
| | | "locId": "Location" |
| | | }, |
| | | "placeholders": { |
| | | "areaMatId": "Select area material", |
| | | "areaId": "Select area", |
| | | "locId": "Select locations" |
| | | }, |
| | | "validation": { |
| | | "areaMatId": "Please select area material", |
| | | "areaId": "Please select area", |
| | | "locId": "Please select locations" |
| | | } |
| | | }, |
| | | "detail": { |
| | | "title": "Material Detail", |
| | | "sections": { |
| | |
| | | "setting": { |
| | | "menuType": { |
| | | "title": "菜单布局", |
| | | "list": [ |
| | | "垂直", |
| | | "水平", |
| | | "混合", |
| | | "双列" |
| | | ] |
| | | "list": ["垂直", "水平", "混合", "双列"] |
| | | }, |
| | | "theme": { |
| | | "title": "主题风格", |
| | | "list": [ |
| | | "浅色", |
| | | "深色", |
| | | "系统" |
| | | ] |
| | | "list": ["浅色", "深色", "系统"] |
| | | }, |
| | | "menu": { |
| | | "title": "菜单风格" |
| | |
| | | }, |
| | | "box": { |
| | | "title": "盒子样式", |
| | | "list": [ |
| | | "边框", |
| | | "阴影" |
| | | ] |
| | | "list": ["边框", "阴影"] |
| | | }, |
| | | "container": { |
| | | "title": "容器宽度", |
| | | "list": [ |
| | | "铺满", |
| | | "定宽" |
| | | ] |
| | | "list": ["铺满", "定宽"] |
| | | }, |
| | | "basics": { |
| | | "title": "基础配置", |
| | |
| | | "send": "发送", |
| | | "renameDialogTitle": "重命名会话", |
| | | "sessionTitleField": "会话标题", |
| | | "requestMetric": "Req: {value}", |
| | | "sessionMetric": "Session: {id}", |
| | | "promptMetric": "Prompt: {value}", |
| | | "modelMetric": "Model: {value}", |
| | | "promptLabel": "Prompt", |
| | | "modelLabel": "Model", |
| | | "modelSelectorLabel": "对话模型", |
| | | "modelSelectorHint": "切换后仅影响当前会话后续回复,不会改动全局默认模型。", |
| | | "modelSwitchFailed": "切换对话模型失败", |
| | | "defaultModelSuffix": "(默认)", |
| | | "mcpMetric": "MCP: {value}", |
| | | "historyMetric": "History: {value}", |
| | | "mcpLabel": "MCP", |
| | | "historyLabel": "History", |
| | | "recentMetric": "Recent: {value}", |
| | | "requestMetric": "Req: {value}", |
| | | "sessionMetric": "Session: {id}", |
| | | "promptMetric": "Prompt: {value}", |
| | | "modelMetric": "Model: {value}", |
| | | "promptLabel": "Prompt", |
| | | "modelLabel": "Model", |
| | | "modelSelectorLabel": "对话模型", |
| | | "modelSelectorHint": "切换后仅影响当前会话后续回复,不会改动全局默认模型。", |
| | | "modelSwitchFailed": "切换对话模型失败", |
| | | "defaultModelSuffix": "(默认)", |
| | | "mcpMetric": "MCP: {value}", |
| | | "historyMetric": "History: {value}", |
| | | "mcpLabel": "MCP", |
| | | "historyLabel": "History", |
| | | "recentMetric": "Recent: {value}", |
| | | "elapsedMetric": "耗时: {value} ms", |
| | | "firstTokenMetric": "首包: {value} ms", |
| | | "tokenMetric": "Tokens: prompt {prompt} / completion {completion} / total {total}", |
| | |
| | | "systemPrompt": "系统提示词", |
| | | "userPromptTemplate": "用户提示词模板" |
| | | }, |
| | | "dialog": { |
| | | "titleCreate": "新建 Prompt", |
| | | "titleEdit": "编辑 Prompt", |
| | | "titleDetail": "Prompt 详情", |
| | | "defaultPreviewInput": "请根据当前输入给出摘要", |
| | | "previewTitle": "渲染预览", |
| | | "dialog": { |
| | | "titleCreate": "新建 Prompt", |
| | | "titleEdit": "编辑 Prompt", |
| | | "titleDetail": "Prompt 详情", |
| | | "defaultPreviewInput": "请根据当前输入给出摘要", |
| | | "previewTitle": "渲染预览", |
| | | "previewDescription": "输入示例内容和 metadata,直接预览最终渲染结果。", |
| | | "previewAction": "渲染预览", |
| | | "previewResolvedVariables": "已解析变量:{value}", |
| | |
| | | }, |
| | | "whMat": { |
| | | "title": "物料", |
| | | "entity": "物料", |
| | | "labels": { |
| | | "allMaterials": "全部物料" |
| | | }, |
| | | "actions": { |
| | | "add": "新增物料", |
| | | "batchGroup": "批量改分组", |
| | | "batchWarn": "批量改预警", |
| | | "batchFlagCheck": "批量质检", |
| | | "batchStatus": "批量状态", |
| | | "batchStockLevel": "批量库存等级", |
| | | "bindLoc": "绑定库位", |
| | | "import": "导入", |
| | | "downloadTemplate": "下载模板" |
| | | }, |
| | | "search": { |
| | | "groupKeywordPlaceholder": "搜索物料分组", |
| | |
| | | "codePlaceholder": "请输入物料编码", |
| | | "name": "物料名称", |
| | | "namePlaceholder": "请输入物料名称", |
| | | "groupId": "物料分组", |
| | | "groupIdPlaceholder": "请选择物料分组", |
| | | "platCode": "平台编码", |
| | | "platCodePlaceholder": "请输入平台编码", |
| | | "spec": "规格", |
| | | "specPlaceholder": "请输入规格", |
| | | "model": "型号", |
| | | "modelPlaceholder": "请输入型号", |
| | | "color": "颜色", |
| | | "colorPlaceholder": "请输入颜色", |
| | | "size": "尺寸", |
| | | "sizePlaceholder": "请输入尺寸", |
| | | "unit": "单位", |
| | | "unitPlaceholder": "请输入单位", |
| | | "purUnit": "采购单位", |
| | | "purUnitPlaceholder": "请输入采购单位", |
| | | "stockUnit": "库位单位", |
| | | "stockUnitPlaceholder": "请输入库位单位", |
| | | "barcode": "条码", |
| | | "barcodePlaceholder": "请输入条码" |
| | | "barcodePlaceholder": "请输入条码", |
| | | "describle": "描述", |
| | | "describlePlaceholder": "请输入描述", |
| | | "rglarId": "批次规则", |
| | | "rglarIdPlaceholder": "请选择批次规则", |
| | | "weight": "重量", |
| | | "weightPlaceholder": "请输入重量", |
| | | "nromNum": "标包数量", |
| | | "nromNumPlaceholder": "请输入标包数量", |
| | | "stockLevel": "库存等级", |
| | | "stockLevelPlaceholder": "请选择库存等级", |
| | | "flagLabelMange": "标签管理", |
| | | "flagLabelMangePlaceholder": "请选择标签管理", |
| | | "safeQty": "安全库存", |
| | | "safeQtyPlaceholder": "请输入安全库存", |
| | | "minQty": "最小库存", |
| | | "minQtyPlaceholder": "请输入最小库存", |
| | | "maxQty": "最大库存", |
| | | "maxQtyPlaceholder": "请输入最大库存", |
| | | "stagn": "停滞天数", |
| | | "stagnPlaceholder": "请输入停滞天数", |
| | | "valid": "保质期天数", |
| | | "validPlaceholder": "请输入保质期天数", |
| | | "validWarn": "效期预警阈值", |
| | | "validWarnPlaceholder": "请输入效期预警阈值", |
| | | "flagCheck": "是否免检", |
| | | "flagCheckPlaceholder": "请选择是否免检", |
| | | "status": "状态", |
| | | "statusPlaceholder": "请选择状态", |
| | | "memo": "备注", |
| | | "memoPlaceholder": "请输入备注", |
| | | "dynamicPlaceholder": "请输入{field}" |
| | | }, |
| | | "messages": { |
| | | "emptyGroups": "暂无物料分组", |
| | | "groupTimeout": "物料分组加载超时,已停止等待", |
| | | "groupLoadFailed": "获取物料分组失败", |
| | | "serialRuleTimeout": "批次规则加载超时,已停止等待", |
| | | "serialRuleLoadFailed": "获取批次规则失败", |
| | | "listTimeout": "物料列表加载超时,已停止等待", |
| | | "listLoadFailed": "获取物料列表失败", |
| | | "detailTimeout": "物料详情加载超时,已停止等待", |
| | | "detailLoadFailed": "获取物料详情失败" |
| | | "detailLoadFailed": "获取物料详情失败", |
| | | "importSuccess": "物料导入成功", |
| | | "importFailed": "物料导入失败", |
| | | "templateDownloadSuccess": "模板下载成功", |
| | | "templateDownloadFailed": "模板下载失败", |
| | | "enabledFieldsTimeout": "扩展字段加载超时,已停止等待", |
| | | "bindLocTimeout": "绑定库位选项加载超时,已停止等待", |
| | | "bindLocLoadFailed": "获取绑定库位选项失败", |
| | | "selectAtLeastOne": "请至少选择一条物料记录" |
| | | }, |
| | | "table": { |
| | | "code": "物料编码", |
| | |
| | | "spec": "规格", |
| | | "model": "型号" |
| | | }, |
| | | "dialog": { |
| | | "titleCreate": "新增物料", |
| | | "titleEdit": "编辑物料", |
| | | "tabs": { |
| | | "basic": "基础信息", |
| | | "control": "控制信息", |
| | | "batchRule": "批次规则" |
| | | }, |
| | | "fields": { |
| | | "code": "物料编码", |
| | | "name": "物料名称", |
| | | "groupId": "物料分组", |
| | | "useOrgName": "使用组织", |
| | | "spec": "规格", |
| | | "model": "型号", |
| | | "color": "颜色", |
| | | "size": "尺寸", |
| | | "weight": "重量", |
| | | "unit": "单位", |
| | | "purUnit": "采购单位", |
| | | "describle": "描述", |
| | | "safeQty": "安全库存", |
| | | "minQty": "最小库存", |
| | | "maxQty": "最大库存", |
| | | "stagn": "停滞天数", |
| | | "valid": "保质期天数", |
| | | "validWarn": "效期预警阈值", |
| | | "flagCheck": "是否免检", |
| | | "rglarId": "批次规则" |
| | | }, |
| | | "placeholders": { |
| | | "code": "请输入物料编码", |
| | | "name": "请输入物料名称", |
| | | "groupId": "请选择物料分组", |
| | | "useOrgName": "请输入使用组织", |
| | | "spec": "请输入规格", |
| | | "model": "请输入型号", |
| | | "color": "请输入颜色", |
| | | "size": "请输入尺寸", |
| | | "unit": "请输入单位", |
| | | "purUnit": "请输入采购单位", |
| | | "describle": "请输入描述", |
| | | "flagCheck": "请选择是否免检", |
| | | "rglarId": "请选择批次规则" |
| | | }, |
| | | "validation": { |
| | | "code": "请输入物料编码", |
| | | "name": "请输入物料名称", |
| | | "groupId": "请选择物料分组" |
| | | } |
| | | }, |
| | | "batchDialog": { |
| | | "titles": { |
| | | "status": "批量修改状态", |
| | | "stockLevel": "批量修改库存等级", |
| | | "validWarn": "批量修改效期预警", |
| | | "flagCheck": "批量修改质检状态" |
| | | }, |
| | | "fields": { |
| | | "stockLevel": "库存等级" |
| | | }, |
| | | "placeholders": { |
| | | "stockLevel": "请选择库存等级", |
| | | "validWarn": "请输入效期预警阈值", |
| | | "valid": "请输入保质期天数", |
| | | "flagCheck": "请选择是否免检" |
| | | }, |
| | | "validation": { |
| | | "status": "请选择状态", |
| | | "stockLevel": "请选择库存等级", |
| | | "validWarn": "请输入效期预警阈值", |
| | | "valid": "请输入保质期天数", |
| | | "flagCheck": "请选择是否免检" |
| | | } |
| | | }, |
| | | "batchGroupDialog": { |
| | | "title": "批量修改物料分组" |
| | | }, |
| | | "bindLocDialog": { |
| | | "title": "绑定库位", |
| | | "fields": { |
| | | "areaMatId": "库区物料", |
| | | "areaId": "库区", |
| | | "locId": "库位" |
| | | }, |
| | | "placeholders": { |
| | | "areaMatId": "请选择库区物料", |
| | | "areaId": "请选择库区", |
| | | "locId": "请选择库位" |
| | | }, |
| | | "validation": { |
| | | "areaMatId": "请选择库区物料", |
| | | "areaId": "请选择库区", |
| | | "locId": "请选择库位" |
| | | } |
| | | }, |
| | | "detail": { |
| | | "title": "物料详情", |
| | | "sections": { |
| | |
| | | } |
| | | return { |
| | | value: Number(value), |
| | | label: normalizeText(item.name || item.areaName || item.code || item.areaCode || `${$t('menu.warehouseAreas')} ${value}`) |
| | | label: normalizeText( |
| | | item.name || |
| | | item.areaName || |
| | | item.code || |
| | | item.areaCode || |
| | | `${$t('menu.warehouseAreas')} ${value}` |
| | | ) |
| | | } |
| | | }) |
| | | .filter(Boolean) |
| | |
| | | } |
| | | return { |
| | | value: Number(value), |
| | | label: normalizeText(item.stationName || item.stationId || item.name || `${$t('menu.basStation')} ${value}`) |
| | | label: normalizeText( |
| | | item.stationName || item.stationId || item.name || `${$t('menu.basStation')} ${value}` |
| | | ) |
| | | } |
| | | }) |
| | | .filter(Boolean) |
| | |
| | | containerType: normalizeText(params.containerType), |
| | | barcode: normalizeText(params.barcode), |
| | | autoTransfer: |
| | | params.autoTransfer !== undefined && params.autoTransfer !== null && params.autoTransfer !== '' |
| | | params.autoTransfer !== undefined && |
| | | params.autoTransfer !== null && |
| | | params.autoTransfer !== '' |
| | | ? Number(params.autoTransfer) |
| | | : void 0, |
| | | stationAlias: normalizeText(params.stationAlias), |
| | |
| | | } |
| | | |
| | | return Object.fromEntries( |
| | | Object.entries(searchParams).filter(([, value]) => value !== '' && value !== void 0 && value !== null) |
| | | Object.entries(searchParams).filter( |
| | | ([, value]) => value !== '' && value !== void 0 && value !== null |
| | | ) |
| | | ) |
| | | } |
| | | |
| | |
| | | return { |
| | | current: params.current || 1, |
| | | pageSize: params.pageSize || params.size || 20, |
| | | orderBy: normalizeText(params.orderBy) || 'create_time desc', |
| | | ...buildBasStationAreaSearchParams(params) |
| | | } |
| | | } |
| | |
| | | ...(formData.area !== void 0 && formData.area !== null && formData.area !== '' |
| | | ? { area: Number(formData.area) } |
| | | : {}), |
| | | ...(formData.isCrossZone !== void 0 && formData.isCrossZone !== null && formData.isCrossZone !== '' |
| | | ...(formData.isCrossZone !== void 0 && |
| | | formData.isCrossZone !== null && |
| | | formData.isCrossZone !== '' |
| | | ? { isCrossZone: Number(formData.isCrossZone) } |
| | | : {}), |
| | | ...(Array.isArray(formData.crossZoneArea) && formData.crossZoneArea.length |
| | |
| | | ? { containerType: normalizeIdArray(formData.containerType) } |
| | | : {}), |
| | | barcode: normalizeText(formData.barcode) || '', |
| | | ...(formData.autoTransfer !== void 0 && formData.autoTransfer !== null && formData.autoTransfer !== '' |
| | | ...(formData.autoTransfer !== void 0 && |
| | | formData.autoTransfer !== null && |
| | | formData.autoTransfer !== '' |
| | | ? { autoTransfer: Number(formData.autoTransfer) } |
| | | : {}), |
| | | ...(Array.isArray(formData.stationAlias) && formData.stationAlias.length |
| | |
| | | } |
| | | } |
| | | |
| | | export function buildBasStationAreaDialogModel(record = {}, resolvers = {}) { |
| | | export function buildBasStationAreaDialogModel(record = {}) { |
| | | return { |
| | | ...createBasStationAreaFormState(), |
| | | ...(record.id !== void 0 && record.id !== null && record.id !== '' ? { id: Number(record.id) } : {}), |
| | | ...(record.id !== void 0 && record.id !== null && record.id !== '' |
| | | ? { id: Number(record.id) } |
| | | : {}), |
| | | stationAreaName: normalizeText(record.stationAreaName || ''), |
| | | stationAreaId: normalizeText(record.stationAreaId || ''), |
| | | type: normalizeIdValue(record.type), |
| | |
| | | outAble: record.outAble !== void 0 && record.outAble !== null ? Number(record.outAble) : 0, |
| | | useStatus: normalizeText(record.useStatus || ''), |
| | | area: normalizeIdValue(record.area), |
| | | isCrossZone: record.isCrossZone !== void 0 && record.isCrossZone !== null ? Number(record.isCrossZone) : 0, |
| | | isCrossZone: |
| | | record.isCrossZone !== void 0 && record.isCrossZone !== null ? Number(record.isCrossZone) : 0, |
| | | crossZoneArea: normalizeIdArray(record.crossZoneArea), |
| | | isWcs: record.isWcs !== void 0 && record.isWcs !== null ? Number(record.isWcs) : 0, |
| | | wcsData: normalizeText(record.wcsData || ''), |
| | | containerType: normalizeIdArray(record.containerType ?? record.containerTypes), |
| | | barcode: normalizeText(record.barcode || ''), |
| | | autoTransfer: record.autoTransfer !== void 0 && record.autoTransfer !== null ? Number(record.autoTransfer) : 0, |
| | | autoTransfer: |
| | | record.autoTransfer !== void 0 && record.autoTransfer !== null |
| | | ? Number(record.autoTransfer) |
| | | : 0, |
| | | stationAlias: normalizeIdArray(record.stationAlias), |
| | | status: record.status !== void 0 && record.status !== null ? Number(record.status) : 1, |
| | | memo: normalizeText(record.memo || '') |
| | |
| | | stationAreaName: normalizeText(record.stationAreaName) || t('common.placeholder.empty'), |
| | | stationAreaId: normalizeText(record.stationAreaId) || t('common.placeholder.empty'), |
| | | type: normalizeIdValue(record.type), |
| | | typeText: normalizeText( |
| | | record.type$ || record.typeText || resolvers.resolveTypeLabel?.(typeValue) || typeValue |
| | | ) || t('common.placeholder.empty'), |
| | | typeText: |
| | | normalizeText( |
| | | record.type$ || record.typeText || resolvers.resolveTypeLabel?.(typeValue) || typeValue |
| | | ) || t('common.placeholder.empty'), |
| | | inAble: normalizeIdValue(record.inAble), |
| | | inAbleText: normalizeBooleanText(record.inAble, t), |
| | | outAble: normalizeIdValue(record.outAble), |
| | | outAbleText: normalizeBooleanText(record.outAble, t), |
| | | useStatus: normalizeText(record.useStatus), |
| | | useStatusText: |
| | | normalizeText(record.useStatus$ || record.useStatusText || resolvers.resolveUseStatusLabel?.(record.useStatus) || record.useStatus) || |
| | | t('common.placeholder.empty'), |
| | | normalizeText( |
| | | record.useStatus$ || |
| | | record.useStatusText || |
| | | resolvers.resolveUseStatusLabel?.(record.useStatus) || |
| | | record.useStatus |
| | | ) || t('common.placeholder.empty'), |
| | | area: normalizeIdValue(areaId), |
| | | areaText: normalizeText(record.area$ || record.areaText || resolvers.resolveAreaLabel?.(areaId) || '') || t('common.placeholder.empty'), |
| | | areaText: |
| | | normalizeText( |
| | | record.area$ || record.areaText || resolvers.resolveAreaLabel?.(areaId) || '' |
| | | ) || t('common.placeholder.empty'), |
| | | isCrossZone: normalizeIdValue(record.isCrossZone), |
| | | isCrossZoneText: normalizeBooleanText(record.isCrossZone, t), |
| | | crossZoneArea: crossZoneAreaIds, |
| | | crossZoneAreaText: |
| | | resolveOptionText(crossZoneAreaIds, resolvers.resolveCrossZoneAreaLabel, record.crossZoneAreaText || []) || |
| | | t('common.placeholder.empty'), |
| | | resolveOptionText( |
| | | crossZoneAreaIds, |
| | | resolvers.resolveCrossZoneAreaLabel, |
| | | record.crossZoneAreaText || [] |
| | | ) || t('common.placeholder.empty'), |
| | | isWcs: normalizeIdValue(record.isWcs), |
| | | isWcsText: normalizeBooleanText(record.isWcs, t), |
| | | wcsData: normalizeText(record.wcsData) || t('common.placeholder.empty'), |
| | | containerType: containerTypeIds, |
| | | containerTypeText: |
| | | resolveOptionText(containerTypeIds, resolvers.resolveContainerTypeLabel, record.containerTypesText || []) || |
| | | t('common.placeholder.empty'), |
| | | resolveOptionText( |
| | | containerTypeIds, |
| | | resolvers.resolveContainerTypeLabel, |
| | | record.containerTypesText || [] |
| | | ) || t('common.placeholder.empty'), |
| | | barcode: normalizeText(record.barcode) || t('common.placeholder.empty'), |
| | | autoTransfer: normalizeIdValue(record.autoTransfer), |
| | | autoTransferText: normalizeBooleanText(record.autoTransfer, t), |
| | |
| | | statusType: statusMeta.type, |
| | | statusBool: record.statusBool !== void 0 ? Boolean(record.statusBool) : statusMeta.bool, |
| | | memo: normalizeText(record.memo) || t('common.placeholder.empty'), |
| | | createByText: normalizeText(record.createBy$ || record.createByText || '') || t('common.placeholder.empty'), |
| | | createTimeText: normalizeText(record.createTime$ || record.createTime || '') || t('common.placeholder.empty'), |
| | | updateByText: normalizeText(record.updateBy$ || record.updateByText || '') || t('common.placeholder.empty'), |
| | | updateTimeText: normalizeText(record.updateTime$ || record.updateTime || '') || t('common.placeholder.empty') |
| | | createByText: |
| | | normalizeText(record.createBy$ || record.createByText || '') || t('common.placeholder.empty'), |
| | | createTimeText: |
| | | normalizeText(record.createTime$ || record.createTime || '') || t('common.placeholder.empty'), |
| | | updateByText: |
| | | normalizeText(record.updateBy$ || record.updateByText || '') || t('common.placeholder.empty'), |
| | | updateTimeText: |
| | | normalizeText(record.updateTime$ || record.updateTime || '') || t('common.placeholder.empty') |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | if (canDelete && handleDelete) { |
| | | operations.push({ key: 'delete', label: t('common.actions.delete'), icon: 'ri:delete-bin-5-line', color: 'var(--art-error)' }) |
| | | operations.push({ |
| | | key: 'delete', |
| | | label: t('common.actions.delete'), |
| | | icon: 'ri:delete-bin-5-line', |
| | | color: 'var(--art-error)' |
| | | }) |
| | | } |
| | | |
| | | return [ |
| | |
| | | label: t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'id', |
| | | label: t('table.id'), |
| | | width: 90, |
| | | align: 'center', |
| | | formatter: (row) => row.id ?? '--' |
| | | }, |
| | | { |
| | | prop: 'stationAreaId', |
| | |
| | | width: 96, |
| | | align: 'center', |
| | | formatter: (row) => { |
| | | const status = getBasStationAreaStatusOptions(t).find((item) => Number(item.value) === Number(row.status)) |
| | | const status = getBasStationAreaStatusOptions(t).find( |
| | | (item) => Number(item.value) === Number(row.status) |
| | | ) |
| | | const text = status?.label || row.statusText || '--' |
| | | const type = Number(row.status) === 1 ? 'success' : Number(row.status) === 0 ? 'danger' : 'info' |
| | | const type = |
| | | Number(row.status) === 1 ? 'success' : Number(row.status) === 0 ? 'danger' : 'info' |
| | | return h(ElTag, { type, effect: 'light' }, () => text) |
| | | } |
| | | }, |
| | | { |
| | | prop: 'updateByText', |
| | | label: t('table.updateBy'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.updateByText || '--' |
| | | }, |
| | | { |
| | | prop: 'updateTimeText', |
| | |
| | | formatter: (row) => row.updateTimeText || '--' |
| | | }, |
| | | { |
| | | prop: 'createByText', |
| | | label: t('table.createBy'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.createByText || '--' |
| | | }, |
| | | { |
| | | prop: 'createTimeText', |
| | | label: t('table.createTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.createTimeText || '--' |
| | | }, |
| | | { |
| | | prop: 'memo', |
| | | label: t('pages.basicInfo.basStationArea.search.memo'), |
| | | minWidth: 180, |
| | |
| | | import { |
| | | buildBasStationAreaDialogModel, |
| | | createBasStationAreaFormState, |
| | | getBasStationAreaBinaryOptions, |
| | | getBasStationAreaStatusOptions, |
| | | getBasStationAreaTypeOptions |
| | | getBasStationAreaStatusOptions |
| | | } from '../basStationAreaPage.helpers' |
| | | |
| | | const props = defineProps({ |
| | |
| | | areaOptions: { type: Array, default: () => [] }, |
| | | crossZoneAreaOptions: { type: Array, default: () => [] }, |
| | | containerTypeOptions: { type: Array, default: () => [] }, |
| | | stationOptions: { type: Array, default: () => [] } |
| | | stationOptions: { type: Array, default: () => [] }, |
| | | useStatusOptions: { type: Array, default: () => [] } |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | |
| | | |
| | | const isEdit = computed(() => props.dialogType === 'edit') |
| | | const dialogTitle = computed(() => |
| | | t(isEdit.value ? 'pages.basicInfo.basStationArea.dialog.titleEdit' : 'pages.basicInfo.basStationArea.dialog.titleAdd') |
| | | t( |
| | | isEdit.value |
| | | ? 'pages.basicInfo.basStationArea.dialog.titleEdit' |
| | | : 'pages.basicInfo.basStationArea.dialog.titleAdd' |
| | | ) |
| | | ) |
| | | |
| | | const rules = computed(() => ({ |
| | | stationAreaName: [{ required: true, message: t('pages.basicInfo.basStationArea.dialog.validation.stationAreaName'), trigger: 'blur' }], |
| | | stationAreaId: [{ required: true, message: t('pages.basicInfo.basStationArea.dialog.validation.stationAreaId'), trigger: 'blur' }], |
| | | type: [{ required: true, message: t('pages.basicInfo.basStationArea.dialog.validation.type'), trigger: 'change' }], |
| | | area: [{ required: true, message: t('pages.basicInfo.basStationArea.dialog.validation.area'), trigger: 'change' }], |
| | | containerType: [{ type: 'array', required: true, message: t('pages.basicInfo.basStationArea.dialog.validation.containerType'), trigger: 'change' }], |
| | | stationAlias: [{ type: 'array', required: true, message: t('pages.basicInfo.basStationArea.dialog.validation.stationAlias'), trigger: 'change' }] |
| | | stationAreaName: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.basStationArea.dialog.validation.stationAreaName'), |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | stationAreaId: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.basStationArea.dialog.validation.stationAreaId'), |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | containerType: [ |
| | | { |
| | | type: 'array', |
| | | required: true, |
| | | message: t('pages.basicInfo.basStationArea.dialog.validation.containerType'), |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | stationAlias: [ |
| | | { |
| | | type: 'array', |
| | | required: true, |
| | | message: t('pages.basicInfo.basStationArea.dialog.validation.stationAlias'), |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | })) |
| | | |
| | | const formItems = computed(() => [ |
| | | const baseLegacyItems = computed(() => [ |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.stationAreaName'), |
| | | key: 'stationAreaName', |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.stationAreaId'), |
| | | key: 'stationAreaId', |
| | | type: 'input', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.stationAreaId'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.type'), |
| | | key: 'type', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.type'), |
| | | clearable: true, |
| | | options: getBasStationAreaTypeOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.area'), |
| | | key: 'area', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.area'), |
| | | clearable: true, |
| | | filterable: true, |
| | | options: props.areaOptions || [] |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.crossZoneArea'), |
| | | label: t('pages.basicInfo.basStation.table.crossZoneArea'), |
| | | key: 'crossZoneArea', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.crossZoneArea'), |
| | | placeholder: t('pages.basicInfo.basStation.table.crossZoneArea'), |
| | | clearable: true, |
| | | multiple: true, |
| | | collapseTags: true, |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.containerType'), |
| | | label: t('pages.basicInfo.basStation.table.containerTypes'), |
| | | key: 'containerType', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.containerType'), |
| | | placeholder: t('pages.basicInfo.basStation.table.containerTypes'), |
| | | clearable: true, |
| | | multiple: true, |
| | | collapseTags: true, |
| | | filterable: true, |
| | | options: props.containerTypeOptions || [] |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.stationAreaId'), |
| | | key: 'stationAreaId', |
| | | type: 'input', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.stationAreaId'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | |
| | | filterable: true, |
| | | options: props.stationOptions || [] |
| | | } |
| | | }, |
| | | } |
| | | ]) |
| | | |
| | | const createOnlyItems = computed(() => [ |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.inAble'), |
| | | key: 'inAble', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.inAble'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.outAble'), |
| | | key: 'outAble', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.outAble'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.isCrossZone'), |
| | | key: 'isCrossZone', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.isCrossZone'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.isWcs'), |
| | | key: 'isWcs', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.isWcs'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.autoTransfer'), |
| | | key: 'autoTransfer', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.autoTransfer'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.useStatus'), |
| | | key: 'useStatus', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.useStatus'), |
| | | clearable: true, |
| | | filterable: true, |
| | | options: props.useStatusOptions || [] |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.wcsData'), |
| | | key: 'wcsData', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | type: 'textarea', |
| | | rows: 3, |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.wcsData'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.barcode'), |
| | | key: 'barcode', |
| | | type: 'input', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.barcode'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.status'), |
| | | label: t('table.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: t('pages.basicInfo.basStationArea.search.status'), |
| | | placeholder: t('table.status'), |
| | | clearable: true, |
| | | options: getBasStationAreaStatusOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.basStationArea.dialog.memo'), |
| | | label: t('table.memo'), |
| | | key: 'memo', |
| | | type: 'input', |
| | | span: 24, |
| | |
| | | } |
| | | } |
| | | ]) |
| | | |
| | | const formItems = computed(() => |
| | | isEdit.value ? baseLegacyItems.value : [...baseLegacyItems.value, ...createOnlyItems.value] |
| | | ) |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(form, createBasStationAreaFormState()) |
| | |
| | | if (!formRef.value) return |
| | | try { |
| | | await formRef.value.validate() |
| | | emit('submit', { ...form }) |
| | | const payload = isEdit.value |
| | | ? { |
| | | id: form.id, |
| | | stationAreaName: form.stationAreaName, |
| | | crossZoneArea: Array.isArray(form.crossZoneArea) ? [...form.crossZoneArea] : [], |
| | | containerType: Array.isArray(form.containerType) ? [...form.containerType] : [], |
| | | stationAreaId: form.stationAreaId, |
| | | stationAlias: Array.isArray(form.stationAlias) ? [...form.stationAlias] : [] |
| | | } |
| | | : { |
| | | stationAreaName: form.stationAreaName, |
| | | crossZoneArea: Array.isArray(form.crossZoneArea) ? [...form.crossZoneArea] : [], |
| | | containerType: Array.isArray(form.containerType) ? [...form.containerType] : [], |
| | | stationAreaId: form.stationAreaId, |
| | | stationAlias: Array.isArray(form.stationAlias) ? [...form.stationAlias] : [], |
| | | status: form.status, |
| | | memo: form.memo |
| | | } |
| | | emit('submit', payload) |
| | | } catch { |
| | | return |
| | | } |
| | |
| | | <ElCard class="wh-mat-page__sidebar-card"> |
| | | <div class="mb-3 flex items-center justify-between gap-3"> |
| | | <div> |
| | | <div class="text-base font-medium text-[var(--art-text-primary)]">{{ t('pages.basicInfo.whMat.title') }}</div> |
| | | <div class="text-base font-medium text-[var(--art-text-primary)]">{{ |
| | | t('pages.basicInfo.whMat.title') |
| | | }}</div> |
| | | <div class="text-xs text-[var(--art-text-secondary)]"> |
| | | {{ selectedGroupLabel }} |
| | | </div> |
| | |
| | | <div v-if="groupTreeLoading" class="py-6"> |
| | | <ElSkeleton :rows="10" animated /> |
| | | </div> |
| | | <ElEmpty v-else-if="!groupTreeData.length" :description="t('pages.basicInfo.whMat.messages.emptyGroups')" /> |
| | | <ElEmpty |
| | | v-else-if="!groupTreeData.length" |
| | | :description="t('pages.basicInfo.whMat.messages.emptyGroups')" |
| | | /> |
| | | <ElTree |
| | | v-else |
| | | :data="groupTreeData" |
| | | :props="treeProps" |
| | | node-key="id" |
| | | highlight-current |
| | | default-expand-all |
| | | :default-expanded-keys="defaultExpandedGroupKeys" |
| | | :current-node-key="selectedGroupId" |
| | | @node-click="handleGroupNodeClick" |
| | | > |
| | | <template #default="{ data }"> |
| | | <div class="flex items-center gap-2"> |
| | | <span class="font-medium">{{ data.name || t('common.placeholder.empty') }}</span> |
| | | <span class="text-xs text-[var(--art-text-secondary)]">{{ data.code || t('common.placeholder.empty') }}</span> |
| | | <span class="text-xs text-[var(--art-text-secondary)]">{{ |
| | | data.code || t('common.placeholder.empty') |
| | | }}</span> |
| | | </div> |
| | | </template> |
| | | </ElTree> |
| | |
| | | /> |
| | | |
| | | <ElCard class="art-table-card"> |
| | | <ArtTableHeader :loading="loading" v-model:columns="columnChecks" @refresh="loadMatnrList" /> |
| | | <ArtTableHeader |
| | | :loading="loading" |
| | | v-model:columns="columnChecks" |
| | | @refresh="handleRefresh" |
| | | > |
| | | <template #left> |
| | | <ElSpace wrap> |
| | | <ElButton v-auth="'add'" @click="handleShowDialog('add')" v-ripple> |
| | | {{ t('pages.basicInfo.whMat.actions.add') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-if="showBatchActionButtons" |
| | | v-auth="'update'" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="openBatchGroupDialog" |
| | | v-ripple |
| | | > |
| | | {{ t('pages.basicInfo.whMat.actions.batchGroup') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-if="showBatchActionButtons" |
| | | v-auth="'update'" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="openBatchDialog('validWarn')" |
| | | v-ripple |
| | | > |
| | | {{ t('pages.basicInfo.whMat.actions.batchWarn') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-if="showBatchActionButtons" |
| | | v-auth="'update'" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="openBatchDialog('flagCheck')" |
| | | v-ripple |
| | | > |
| | | {{ t('pages.basicInfo.whMat.actions.batchFlagCheck') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-if="showBatchActionButtons" |
| | | v-auth="'update'" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="openBatchDialog('status')" |
| | | v-ripple |
| | | > |
| | | {{ t('pages.basicInfo.whMat.actions.batchStatus') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-if="showBatchActionButtons" |
| | | v-auth="'update'" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="openBatchDialog('stockLevel')" |
| | | v-ripple |
| | | > |
| | | {{ t('pages.basicInfo.whMat.actions.batchStockLevel') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-if="showBatchActionButtons" |
| | | v-auth="'update'" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="openBindLocDialog" |
| | | v-ripple |
| | | > |
| | | {{ t('pages.basicInfo.whMat.actions.bindLoc') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-auth="'delete'" |
| | | type="danger" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="handleBatchDelete" |
| | | v-ripple |
| | | > |
| | | {{ t('common.actions.batchDelete') }} |
| | | </ElButton> |
| | | <div v-auth="'update'"> |
| | | <ElUpload |
| | | :auto-upload="false" |
| | | :show-file-list="false" |
| | | accept=".xlsx,.xls" |
| | | @change="handleImportFileChange" |
| | | > |
| | | <ElButton :loading="importing" v-ripple> |
| | | {{ t('pages.basicInfo.whMat.actions.import') }} |
| | | </ElButton> |
| | | </ElUpload> |
| | | </div> |
| | | <ElButton :loading="templateDownloading" @click="handleDownloadTemplate" v-ripple> |
| | | {{ t('pages.basicInfo.whMat.actions.downloadTemplate') }} |
| | | </ElButton> |
| | | <ListExportPrint |
| | | class="inline-flex" |
| | | :preview-visible="previewVisible" |
| | | @update:previewVisible="handlePreviewVisibleChange" |
| | | :report-title="reportTitle" |
| | | :selected-rows="selectedRows" |
| | | :query-params="reportQueryParams" |
| | | :columns="columns" |
| | | :preview-rows="previewRows" |
| | | :preview-meta="resolvedPreviewMeta" |
| | | :total="pagination.total" |
| | | :disabled="loading" |
| | | @export="handleExport" |
| | | @print="handlePrint" |
| | | /> |
| | | </ElSpace> |
| | | </template> |
| | | </ArtTableHeader> |
| | | |
| | | <ArtTable |
| | | :loading="loading" |
| | | :data="tableData" |
| | | :columns="columns" |
| | | :pagination="pagination" |
| | | row-key="id" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination:size-change="handleSizeChange" |
| | | @pagination:current-change="handleCurrentChange" |
| | | > |
| | | <template #action="{ row }"> |
| | | <ArtButtonTable icon="ri:eye-line" @click="openDetailDrawer(row)" /> |
| | | </template> |
| | | </ArtTable> |
| | | /> |
| | | </ElCard> |
| | | </div> |
| | | </div> |
| | | |
| | | <WhMatDialog |
| | | v-model:visible="dialogVisible" |
| | | :dialog-type="dialogType" |
| | | :material-data="currentMaterialData" |
| | | :group-options="groupOptions" |
| | | :serial-rule-options="serialRuleOptions" |
| | | @submit="handleDialogSubmit" |
| | | /> |
| | | |
| | | <WhMatBatchDialog |
| | | v-model:visible="batchDialogVisible" |
| | | :action-type="batchDialogType" |
| | | @submit="handleBatchDialogSubmit" |
| | | /> |
| | | |
| | | <WhMatBatchGroupDialog |
| | | v-model:visible="batchGroupDialogVisible" |
| | | :group-options="groupOptions" |
| | | @submit="handleBatchGroupSubmit" |
| | | /> |
| | | |
| | | <WhMatBindLocDialog |
| | | v-model:visible="bindLocDialogVisible" |
| | | :area-mat-options="areaMatOptions" |
| | | :area-options="areaOptions" |
| | | :loc-options="locOptions" |
| | | @submit="handleBindLocSubmit" |
| | | /> |
| | | |
| | | <WhMatDetailDrawer |
| | | v-model:visible="detailDrawerVisible" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ElMessage } from 'element-plus' |
| | | import { computed, onMounted, reactive, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { useI18n } from 'vue-i18n' |
| | | import ArtButtonTable from '@/components/core/forms/art-button-table/index.vue' |
| | | import ListExportPrint from '@/components/biz/list-export-print/index.vue' |
| | | import { useAuth } from '@/hooks/core/useAuth' |
| | | import { useTableColumns } from '@/hooks/core/useTableColumns' |
| | | import { useUserStore } from '@/store/modules/user' |
| | | import { fetchSerialRulePage } from '@/api/system-manage' |
| | | import { fetchWarehouseAreasList } from '@/api/warehouse-areas' |
| | | import { fetchLocPage } from '@/api/loc' |
| | | import { fetchLocAreaMatList } from '@/api/loc-area-mat' |
| | | import { fetchBindLocAreaMatRelaByMatnr } from '@/api/loc-area-mat-rela' |
| | | import { defaultResponseAdapter } from '@/utils/table/tableUtils' |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { fetchMatnrDetail, fetchMatnrGroupTree, fetchMatnrPage } from '@/api/wh-mat' |
| | | import { useCrudPage } from '@/views/system/common/useCrudPage' |
| | | import { usePrintExportPage } from '@/views/system/common/usePrintExportPage' |
| | | import { |
| | | fetchBatchUpdateMatnr, |
| | | fetchBindMatnrGroup, |
| | | fetchDeleteMatnr, |
| | | fetchDownloadMatnrTemplate, |
| | | fetchEnabledFields, |
| | | fetchExportMatnrReport, |
| | | fetchGetMatnrMany, |
| | | fetchImportMatnr, |
| | | fetchMatnrDetail, |
| | | fetchMatnrGroupTree, |
| | | fetchMatnrPage, |
| | | fetchSaveMatnr, |
| | | fetchUpdateMatnr |
| | | } from '@/api/wh-mat' |
| | | import WhMatBatchDialog from './modules/wh-mat-batch-dialog.vue' |
| | | import WhMatBatchGroupDialog from './modules/wh-mat-batch-group-dialog.vue' |
| | | import WhMatBindLocDialog from './modules/wh-mat-bind-loc-dialog.vue' |
| | | import WhMatDialog from './modules/wh-mat-dialog.vue' |
| | | import WhMatDetailDrawer from './modules/wh-mat-detail-drawer.vue' |
| | | import { createWhMatTableColumns } from './whMatTable.columns' |
| | | import { |
| | | WH_MAT_REPORT_STYLE, |
| | | WH_MAT_REPORT_TITLE, |
| | | buildMatnrGroupTreeQueryParams, |
| | | buildMatnrPageQueryParams, |
| | | buildWhMatDialogModel, |
| | | buildWhMatPrintRows, |
| | | buildWhMatReportMeta, |
| | | buildWhMatSavePayload, |
| | | createWhMatSearchState, |
| | | getWhMatDynamicFieldKey, |
| | | getWhMatFlagLabelManageOptions, |
| | | getWhMatFlagCheckOptions, |
| | | getWhMatStockLevelOptions, |
| | | getWhMatStatusOptions, |
| | | getWhMatTreeNodeLabel, |
| | | normalizeMatnrDetail, |
| | | normalizeWhMatEnabledFields, |
| | | normalizeMatnrGroupTreeRows, |
| | | normalizeMatnrRow |
| | | normalizeMatnrRow, |
| | | resolveWhMatGroupOptions, |
| | | resolveWhMatSerialRuleOptions |
| | | } from './whMatPage.helpers' |
| | | |
| | | defineOptions({ name: 'WhMat' }) |
| | | const { t } = useI18n() |
| | | |
| | | const { t } = useI18n() |
| | | const { hasAuth } = useAuth() |
| | | const userStore = useUserStore() |
| | | |
| | | const showBatchActionButtons = false |
| | | const loading = ref(false) |
| | | const groupTreeLoading = ref(false) |
| | | const detailDrawerVisible = ref(false) |
| | | const detailLoading = ref(false) |
| | | const batchDialogVisible = ref(false) |
| | | const batchGroupDialogVisible = ref(false) |
| | | const bindLocDialogVisible = ref(false) |
| | | const bindLocOptionsLoading = ref(false) |
| | | const importing = ref(false) |
| | | const templateDownloading = ref(false) |
| | | const tableData = ref([]) |
| | | const groupTreeData = ref([]) |
| | | const detailData = ref({}) |
| | | const enabledFields = ref([]) |
| | | const serialRuleOptions = ref([]) |
| | | const areaOptions = ref([]) |
| | | const areaMatOptions = ref([]) |
| | | const locOptions = ref([]) |
| | | const selectedGroupId = ref(null) |
| | | const groupSearch = ref('') |
| | | const batchDialogType = ref('status') |
| | | const searchForm = ref(createWhMatSearchState()) |
| | | let handleDeleteAction = null |
| | | |
| | | const pagination = reactive({ |
| | | current: 1, |
| | |
| | | label: 'name', |
| | | children: 'children' |
| | | } |
| | | |
| | | const reportTitle = WH_MAT_REPORT_TITLE |
| | | const groupOptions = computed(() => resolveWhMatGroupOptions(groupTreeData.value)) |
| | | const defaultExpandedGroupKeys = computed(() => collectExpandedGroupKeys(groupTreeData.value)) |
| | | const reportQueryParams = computed(() => |
| | | buildMatnrPageQueryParams({ |
| | | ...searchForm.value, |
| | | groupId: searchForm.value?.groupId || selectedGroupId.value, |
| | | current: 1, |
| | | pageSize: pagination.size |
| | | }) |
| | | ) |
| | | |
| | | const searchItems = computed(() => [ |
| | | { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.groupId'), |
| | | key: 'groupId', |
| | | type: 'treeselect', |
| | | props: { |
| | | data: groupOptions.value, |
| | | props: { |
| | | label: 'displayLabel', |
| | | value: 'value', |
| | | children: 'children' |
| | | }, |
| | | checkStrictly: true, |
| | | defaultExpandAll: true, |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.groupIdPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.platCode'), |
| | | key: 'platCode', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.platCodePlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.spec'), |
| | | key: 'spec', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.specPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.model'), |
| | | key: 'model', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.modelPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.color'), |
| | | key: 'color', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.colorPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.size'), |
| | | key: 'size', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.sizePlaceholder') |
| | | } |
| | | }, |
| | | { |
| | |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.barcodePlaceholder') |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.unit'), |
| | | key: 'unit', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.unitPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.purUnit'), |
| | | key: 'purUnit', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.purUnitPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.stockUnit'), |
| | | key: 'stockUnit', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.stockUnitPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.describle'), |
| | | key: 'describle', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.describlePlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.rglarId'), |
| | | key: 'rglarId', |
| | | type: 'select', |
| | | props: { |
| | | clearable: true, |
| | | filterable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.rglarIdPlaceholder'), |
| | | options: serialRuleOptions.value |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.weight'), |
| | | key: 'weight', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.search.weightPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.nromNum'), |
| | | key: 'nromNum', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.search.nromNumPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.stockLevel'), |
| | | key: 'stockLevel', |
| | | type: 'select', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.stockLevelPlaceholder'), |
| | | options: getWhMatStockLevelOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.flagLabelMange'), |
| | | key: 'flagLabelMange', |
| | | type: 'select', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.flagLabelMangePlaceholder'), |
| | | options: getWhMatFlagLabelManageOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.safeQty'), |
| | | key: 'safeQty', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.search.safeQtyPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.minQty'), |
| | | key: 'minQty', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.search.minQtyPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.maxQty'), |
| | | key: 'maxQty', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.search.maxQtyPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.stagn'), |
| | | key: 'stagn', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.search.stagnPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.valid'), |
| | | key: 'valid', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.search.validPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.validWarn'), |
| | | key: 'validWarn', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.search.validWarnPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.flagCheck'), |
| | | key: 'flagCheck', |
| | | type: 'select', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.flagCheckPlaceholder'), |
| | | options: getWhMatFlagCheckOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.statusPlaceholder'), |
| | | options: getWhMatStatusOptions(t) |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.search.memo'), |
| | | key: 'memo', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.memoPlaceholder') |
| | | } |
| | | }, |
| | | ...enabledFields.value.map((field) => ({ |
| | | label: field.fieldsAlise, |
| | | key: getWhMatDynamicFieldKey(field.fields), |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.dynamicPlaceholder', { |
| | | field: field.fieldsAlise |
| | | }) |
| | | } |
| | | })) |
| | | ]) |
| | | |
| | | const { columnChecks, columns } = useTableColumns(() => |
| | | const { columnChecks, columns, resetColumns } = useTableColumns(() => |
| | | createWhMatTableColumns({ |
| | | t, |
| | | handleViewDetail: openDetailDrawer |
| | | enabledFields: enabledFields.value, |
| | | handleViewDetail: openDetailDrawer, |
| | | handleEdit: hasAuth('update') ? openEditDialog : null, |
| | | handleDelete: hasAuth('delete') ? (row) => handleDeleteAction?.(row) : null, |
| | | handlePrint: (row) => handlePrint({ ids: [row.id] }), |
| | | canEdit: hasAuth('update'), |
| | | canDelete: hasAuth('delete'), |
| | | t |
| | | }) |
| | | ) |
| | | |
| | |
| | | } |
| | | } |
| | | return null |
| | | } |
| | | |
| | | function collectExpandedGroupKeys(nodes, depth = 1, maxExpandedDepth = 1) { |
| | | if (!Array.isArray(nodes) || depth > maxExpandedDepth) { |
| | | return [] |
| | | } |
| | | |
| | | return nodes.flatMap((node) => { |
| | | const currentId = node?.id !== undefined && node?.id !== null ? [node.id] : [] |
| | | return [ |
| | | ...currentId, |
| | | ...collectExpandedGroupKeys(node?.children || [], depth + 1, maxExpandedDepth) |
| | | ] |
| | | }) |
| | | } |
| | | |
| | | function normalizeOptionText(value) { |
| | | return String(value ?? '').trim() |
| | | } |
| | | |
| | | function buildOption(value, label, extra = {}) { |
| | | return { |
| | | value, |
| | | label, |
| | | ...extra |
| | | } |
| | | } |
| | | |
| | | async function loadEnabledFieldDefinitions() { |
| | | const fields = await guardRequestWithMessage(fetchEnabledFields(), [], { |
| | | timeoutMessage: t('pages.basicInfo.whMat.messages.enabledFieldsTimeout') |
| | | }) |
| | | enabledFields.value = normalizeWhMatEnabledFields(fields) |
| | | enabledFields.value.forEach((field) => { |
| | | const dynamicKey = getWhMatDynamicFieldKey(field.fields) |
| | | if (searchForm.value[dynamicKey] === undefined) { |
| | | searchForm.value[dynamicKey] = '' |
| | | } |
| | | }) |
| | | resetColumns() |
| | | } |
| | | |
| | | function updatePaginationState(target, response, fallbackCurrent, fallbackSize) { |
| | |
| | | } |
| | | } |
| | | |
| | | async function loadSerialRuleOptions() { |
| | | try { |
| | | const response = await guardRequestWithMessage( |
| | | fetchSerialRulePage({ current: 1, pageSize: 200 }), |
| | | { records: [] }, |
| | | { timeoutMessage: t('pages.basicInfo.whMat.messages.serialRuleTimeout') } |
| | | ) |
| | | serialRuleOptions.value = resolveWhMatSerialRuleOptions( |
| | | defaultResponseAdapter(response).records |
| | | ) |
| | | } catch (error) { |
| | | serialRuleOptions.value = [] |
| | | ElMessage.error(error?.message || t('pages.basicInfo.whMat.messages.serialRuleLoadFailed')) |
| | | } |
| | | } |
| | | |
| | | async function ensureBindLocOptionsLoaded(force = false) { |
| | | if ( |
| | | !force && |
| | | areaOptions.value.length && |
| | | areaMatOptions.value.length && |
| | | locOptions.value.length |
| | | ) { |
| | | return |
| | | } |
| | | if (bindLocOptionsLoading.value) { |
| | | return |
| | | } |
| | | |
| | | bindLocOptionsLoading.value = true |
| | | try { |
| | | const [areasResponse, areaMatResponse, locResponse] = await Promise.all([ |
| | | guardRequestWithMessage(fetchWarehouseAreasList(), [], { |
| | | timeoutMessage: t('pages.basicInfo.whMat.messages.bindLocTimeout') |
| | | }), |
| | | guardRequestWithMessage(fetchLocAreaMatList(), [], { |
| | | timeoutMessage: t('pages.basicInfo.whMat.messages.bindLocTimeout') |
| | | }), |
| | | guardRequestWithMessage( |
| | | fetchLocPage({ current: 1, pageSize: 1000 }), |
| | | { records: [] }, |
| | | { |
| | | timeoutMessage: t('pages.basicInfo.whMat.messages.bindLocTimeout') |
| | | } |
| | | ) |
| | | ]) |
| | | |
| | | areaOptions.value = defaultResponseAdapter(areasResponse) |
| | | .records.map((item) => |
| | | buildOption( |
| | | Number(item.id), |
| | | [normalizeOptionText(item.name), normalizeOptionText(item.code)] |
| | | .filter(Boolean) |
| | | .join(' · ') || t('common.placeholder.empty'), |
| | | { |
| | | areaId: Number(item.id), |
| | | warehouseId: item.warehouseId !== undefined ? Number(item.warehouseId) : void 0 |
| | | } |
| | | ) |
| | | ) |
| | | .filter((item) => Number.isFinite(item.value)) |
| | | |
| | | areaMatOptions.value = defaultResponseAdapter(areaMatResponse) |
| | | .records.map((item) => |
| | | buildOption( |
| | | Number(item.id), |
| | | [normalizeOptionText(item.code), normalizeOptionText(item.depict || item.name)] |
| | | .filter(Boolean) |
| | | .join(' · ') || t('common.placeholder.empty'), |
| | | { |
| | | areaMatId: Number(item.id), |
| | | areaId: item.areaId !== undefined ? Number(item.areaId) : void 0 |
| | | } |
| | | ) |
| | | ) |
| | | .filter((item) => Number.isFinite(item.value)) |
| | | |
| | | locOptions.value = defaultResponseAdapter(locResponse) |
| | | .records.map((item) => |
| | | buildOption( |
| | | Number(item.id), |
| | | normalizeOptionText(item.code) || t('common.placeholder.empty'), |
| | | { |
| | | areaId: item.areaId !== undefined ? Number(item.areaId) : void 0 |
| | | } |
| | | ) |
| | | ) |
| | | .filter((item) => Number.isFinite(item.value)) |
| | | } finally { |
| | | bindLocOptionsLoading.value = false |
| | | } |
| | | } |
| | | |
| | | async function loadMatnrList() { |
| | | loading.value = true |
| | | try { |
| | |
| | | fetchMatnrPage( |
| | | buildMatnrPageQueryParams({ |
| | | ...searchForm.value, |
| | | groupId: selectedGroupId.value, |
| | | groupId: searchForm.value?.groupId || selectedGroupId.value, |
| | | current: pagination.current, |
| | | pageSize: pagination.size |
| | | }) |
| | |
| | | { timeoutMessage: t('pages.basicInfo.whMat.messages.listTimeout') } |
| | | ) |
| | | tableData.value = Array.isArray(response?.records) |
| | | ? response.records.map((record) => normalizeMatnrRow(record, t)) |
| | | ? response.records.map((record) => normalizeMatnrRow(record, t, enabledFields.value)) |
| | | : [] |
| | | updatePaginationState(pagination, response, pagination.current, pagination.size) |
| | | } catch (error) { |
| | |
| | | } |
| | | } |
| | | |
| | | async function loadMatnrDetail(id) { |
| | | return await guardRequestWithMessage( |
| | | fetchMatnrDetail(id), |
| | | {}, |
| | | { |
| | | timeoutMessage: t('pages.basicInfo.whMat.messages.detailTimeout') |
| | | } |
| | | ) |
| | | } |
| | | |
| | | async function openDetailDrawer(row) { |
| | | detailDrawerVisible.value = true |
| | | detailLoading.value = true |
| | | try { |
| | | detailData.value = normalizeMatnrDetail( |
| | | await guardRequestWithMessage(fetchMatnrDetail(row.id), {}, { |
| | | timeoutMessage: t('pages.basicInfo.whMat.messages.detailTimeout') |
| | | }), |
| | | t |
| | | ) |
| | | detailData.value = normalizeMatnrDetail(await loadMatnrDetail(row.id), t, enabledFields.value) |
| | | } catch (error) { |
| | | detailDrawerVisible.value = false |
| | | detailData.value = {} |
| | |
| | | } |
| | | } |
| | | |
| | | async function openEditDialog(row) { |
| | | try { |
| | | const detail = await loadMatnrDetail(row.id) |
| | | showDialog('edit', detail) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || t('pages.basicInfo.whMat.messages.detailLoadFailed')) |
| | | } |
| | | } |
| | | |
| | | const { |
| | | dialogVisible, |
| | | dialogType, |
| | | currentRecord: currentMaterialData, |
| | | selectedRows, |
| | | handleSelectionChange, |
| | | showDialog, |
| | | handleDialogSubmit, |
| | | handleDelete, |
| | | handleBatchDelete |
| | | } = useCrudPage({ |
| | | createEmptyModel: () => |
| | | buildWhMatDialogModel({ groupId: selectedGroupId.value || searchForm.value?.groupId || '' }), |
| | | buildEditModel: (record) => buildWhMatDialogModel(record), |
| | | buildSavePayload: (formData) => buildWhMatSavePayload(formData), |
| | | saveRequest: fetchSaveMatnr, |
| | | updateRequest: fetchUpdateMatnr, |
| | | deleteRequest: fetchDeleteMatnr, |
| | | entityName: t('pages.basicInfo.whMat.entity'), |
| | | resolveRecordLabel: (record) => record?.name || record?.code || record?.id, |
| | | refreshCreate: loadMatnrList, |
| | | refreshUpdate: loadMatnrList, |
| | | refreshRemove: loadMatnrList |
| | | }) |
| | | handleDeleteAction = handleDelete |
| | | |
| | | const getSelectedIds = () => |
| | | selectedRows.value.map((item) => Number(item?.id)).filter((id) => Number.isFinite(id)) |
| | | |
| | | const ensureSelectedRows = () => { |
| | | const ids = getSelectedIds() |
| | | if (!ids.length) { |
| | | ElMessage.warning(t('pages.basicInfo.whMat.messages.selectAtLeastOne')) |
| | | return [] |
| | | } |
| | | return ids |
| | | } |
| | | |
| | | function openBatchDialog(type) { |
| | | if (!ensureSelectedRows().length) { |
| | | return |
| | | } |
| | | batchDialogType.value = type |
| | | batchDialogVisible.value = true |
| | | } |
| | | |
| | | function openBatchGroupDialog() { |
| | | if (!ensureSelectedRows().length) { |
| | | return |
| | | } |
| | | batchGroupDialogVisible.value = true |
| | | } |
| | | |
| | | async function openBindLocDialog() { |
| | | if (!ensureSelectedRows().length) { |
| | | return |
| | | } |
| | | try { |
| | | await ensureBindLocOptionsLoaded() |
| | | bindLocDialogVisible.value = true |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || t('pages.basicInfo.whMat.messages.bindLocLoadFailed')) |
| | | } |
| | | } |
| | | |
| | | async function handleBatchDialogSubmit(formData) { |
| | | const ids = ensureSelectedRows() |
| | | if (!ids.length) { |
| | | batchDialogVisible.value = false |
| | | return |
| | | } |
| | | |
| | | try { |
| | | await fetchBatchUpdateMatnr({ |
| | | ids, |
| | | matnr: formData |
| | | }) |
| | | ElMessage.success(t('crud.messages.updateSuccess')) |
| | | batchDialogVisible.value = false |
| | | selectedRows.value = [] |
| | | await loadMatnrList() |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || t('crud.messages.submitFailed')) |
| | | } |
| | | } |
| | | |
| | | async function handleBatchGroupSubmit(formData) { |
| | | const ids = ensureSelectedRows() |
| | | if (!ids.length) { |
| | | batchGroupDialogVisible.value = false |
| | | return |
| | | } |
| | | |
| | | try { |
| | | await fetchBindMatnrGroup({ |
| | | ids, |
| | | groupId: formData.groupId |
| | | }) |
| | | ElMessage.success(t('crud.messages.updateSuccess')) |
| | | batchGroupDialogVisible.value = false |
| | | selectedRows.value = [] |
| | | await loadMatnrList() |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || t('crud.messages.submitFailed')) |
| | | } |
| | | } |
| | | |
| | | async function handleBindLocSubmit(formData) { |
| | | const ids = ensureSelectedRows() |
| | | if (!ids.length) { |
| | | bindLocDialogVisible.value = false |
| | | return |
| | | } |
| | | |
| | | try { |
| | | await fetchBindLocAreaMatRelaByMatnr({ |
| | | ...formData, |
| | | matnrId: ids |
| | | }) |
| | | ElMessage.success(t('crud.messages.updateSuccess')) |
| | | bindLocDialogVisible.value = false |
| | | selectedRows.value = [] |
| | | await loadMatnrList() |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || t('crud.messages.submitFailed')) |
| | | } |
| | | } |
| | | |
| | | const buildPreviewMeta = (rows) => { |
| | | const now = new Date() |
| | | return { |
| | | reportDate: now.toLocaleDateString('zh-CN'), |
| | | printedAt: now.toLocaleString('zh-CN', { hour12: false }), |
| | | operator: userStore.getUserInfo?.name || userStore.getUserInfo?.username || '', |
| | | count: rows.length, |
| | | reportStyle: { ...WH_MAT_REPORT_STYLE } |
| | | } |
| | | } |
| | | |
| | | const resolvePrintRecords = async (payload) => { |
| | | if (Array.isArray(payload?.ids) && payload.ids.length > 0) { |
| | | return defaultResponseAdapter(await fetchGetMatnrMany(payload.ids)).records |
| | | } |
| | | return tableData.value |
| | | } |
| | | |
| | | const { |
| | | previewVisible, |
| | | previewRows, |
| | | previewMeta, |
| | | handlePreviewVisibleChange, |
| | | handleExport, |
| | | handlePrint |
| | | } = usePrintExportPage({ |
| | | downloadFileName: 'matnr.xlsx', |
| | | requestExport: (payload) => |
| | | fetchExportMatnrReport(payload, { |
| | | headers: { |
| | | Authorization: userStore.accessToken || '' |
| | | } |
| | | }), |
| | | resolvePrintRecords, |
| | | buildPreviewRows: (records) => buildWhMatPrintRows(records, t), |
| | | buildPreviewMeta |
| | | }) |
| | | |
| | | const resolvedPreviewMeta = computed(() => |
| | | buildWhMatReportMeta({ |
| | | previewMeta: previewMeta.value, |
| | | count: previewRows.value.length, |
| | | orientation: previewMeta.value?.reportStyle?.orientation || WH_MAT_REPORT_STYLE.orientation |
| | | }) |
| | | ) |
| | | |
| | | async function downloadFile(response, fallbackName) { |
| | | if (!response?.ok) { |
| | | throw new Error( |
| | | t('crud.messages.exportFailedWithStatus', { status: response?.status || '-' }) |
| | | ) |
| | | } |
| | | const blob = await response.blob() |
| | | const downloadUrl = window.URL.createObjectURL(blob) |
| | | const link = document.createElement('a') |
| | | link.href = downloadUrl |
| | | link.download = fallbackName |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | link.remove() |
| | | window.URL.revokeObjectURL(downloadUrl) |
| | | } |
| | | |
| | | function handleShowDialog(type) { |
| | | showDialog(type) |
| | | } |
| | | |
| | | function handleSearch(params) { |
| | | searchForm.value = { |
| | | ...searchForm.value, |
| | | ...params |
| | | ...params, |
| | | orderBy: searchForm.value?.orderBy || 'create_time desc' |
| | | } |
| | | pagination.current = 1 |
| | | if (searchForm.value.groupId) { |
| | | selectedGroupId.value = null |
| | | } |
| | | loadMatnrList() |
| | | } |
| | | |
| | | async function handleReset() { |
| | | searchForm.value = createWhMatSearchState() |
| | | enabledFields.value.forEach((field) => { |
| | | searchForm.value[getWhMatDynamicFieldKey(field.fields)] = '' |
| | | }) |
| | | pagination.current = 1 |
| | | selectedGroupId.value = null |
| | | groupSearch.value = '' |
| | | await Promise.all([loadGroupTree(), loadMatnrList()]) |
| | | } |
| | | |
| | | function handleRefresh() { |
| | | loadMatnrList() |
| | | } |
| | | |
| | | function handleSizeChange(size) { |
| | |
| | | |
| | | function handleGroupNodeClick(data) { |
| | | selectedGroupId.value = data?.id ?? null |
| | | delete searchForm.value.groupId |
| | | pagination.current = 1 |
| | | loadMatnrList() |
| | | } |
| | |
| | | await Promise.all([loadGroupTree(), loadMatnrList()]) |
| | | } |
| | | |
| | | async function handleImportFileChange(uploadFile) { |
| | | if (!uploadFile?.raw) { |
| | | return |
| | | } |
| | | importing.value = true |
| | | try { |
| | | await fetchImportMatnr(uploadFile.raw) |
| | | ElMessage.success(t('pages.basicInfo.whMat.messages.importSuccess')) |
| | | await loadMatnrList() |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || t('pages.basicInfo.whMat.messages.importFailed')) |
| | | } finally { |
| | | importing.value = false |
| | | } |
| | | } |
| | | |
| | | async function handleDownloadTemplate() { |
| | | templateDownloading.value = true |
| | | try { |
| | | const response = await fetchDownloadMatnrTemplate( |
| | | {}, |
| | | { |
| | | headers: { |
| | | Authorization: userStore.accessToken || '' |
| | | } |
| | | } |
| | | ) |
| | | await downloadFile(response, 'matnr-template.xlsx') |
| | | ElMessage.success(t('pages.basicInfo.whMat.messages.templateDownloadSuccess')) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || t('pages.basicInfo.whMat.messages.templateDownloadFailed')) |
| | | } finally { |
| | | templateDownloading.value = false |
| | | } |
| | | } |
| | | |
| | | onMounted(async () => { |
| | | await Promise.all([loadGroupTree(), loadMatnrList()]) |
| | | await Promise.allSettled([ |
| | | loadEnabledFieldDefinitions(), |
| | | loadGroupTree(), |
| | | loadSerialRuleOptions() |
| | | ]) |
| | | await loadMatnrList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .wh-mat-page-root { |
| | | height: 100%; |
| | | min-height: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .wh-mat-page { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: flex-start; |
| | | align-items: stretch; |
| | | gap: 16px; |
| | | flex: 1 1 auto; |
| | | min-height: 0; |
| | | } |
| | | |
| | | .wh-mat-page__sidebar { |
| | | width: 320px; |
| | | flex: 0 0 320px; |
| | | min-height: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .wh-mat-page__sidebar-card { |
| | | position: sticky; |
| | | top: 16px; |
| | | height: 100%; |
| | | min-height: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .wh-mat-page__sidebar-card :deep(.el-card__body) { |
| | | height: 100%; |
| | | min-height: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .wh-mat-page__tree-scroll { |
| | | height: calc(100vh - 320px); |
| | | min-height: 420px; |
| | | flex: 1 1 auto; |
| | | min-height: 0; |
| | | } |
| | | |
| | | .wh-mat-page__content { |
| | | height: 100%; |
| | | min-width: 0; |
| | | min-height: 0; |
| | | flex: 1 1 auto; |
| | | display: flex; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .wh-mat-page__content > * + * { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .wh-mat-page__content > :deep(.art-search-bar) { |
| | | flex: 0 0 auto; |
| | | } |
| | | |
| | | .wh-mat-page__content > :deep(.art-table-card) { |
| | | flex: 1 1 auto; |
| | | min-height: 0; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .wh-mat-page__content > :deep(.art-table-card .el-card__body) { |
| | | display: flex; |
| | | min-height: 0; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .wh-mat-page__content > :deep(.art-table-card #art-table-header) { |
| | | flex: 0 0 auto; |
| | | } |
| | | |
| | | .wh-mat-page__content > :deep(.art-table-card .art-table) { |
| | | flex: 1 1 auto; |
| | | min-height: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .wh-mat-page__content > :deep(.art-table-card .art-table .el-table) { |
| | | flex: 1 1 auto; |
| | | min-height: 0; |
| | | height: auto; |
| | | } |
| | | |
| | | .wh-mat-page__content > :deep(.art-table-card .art-table .pagination) { |
| | | flex: 0 0 auto; |
| | | } |
| | | |
| | | @media (max-width: 1024px) { |
| | | .wh-mat-page { |
| | | flex-direction: column; |
| | | flex: none; |
| | | } |
| | | |
| | | .wh-mat-page__sidebar { |
| | |
| | | } |
| | | |
| | | .wh-mat-page__sidebar-card { |
| | | position: static; |
| | | height: auto; |
| | | } |
| | | |
| | | .wh-mat-page__tree-scroll { |
| New file |
| | |
| | | <template> |
| | | <ElDialog |
| | | :title="dialogTitle" |
| | | :model-value="visible" |
| | | width="640px" |
| | | align-center |
| | | destroy-on-close |
| | | @update:model-value="handleCancel" |
| | | @closed="handleClosed" |
| | | > |
| | | <ArtForm |
| | | ref="formRef" |
| | | v-model="form" |
| | | :items="formItems" |
| | | :rules="rules" |
| | | :span="12" |
| | | :gutter="20" |
| | | label-width="120px" |
| | | :show-reset="false" |
| | | :show-submit="false" |
| | | /> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">{{ t('common.confirm') }}</ElButton> |
| | | </span> |
| | | </template> |
| | | </ElDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, nextTick, reactive, ref, watch } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import ArtForm from '@/components/core/forms/art-form/index.vue' |
| | | import { |
| | | getWhMatFlagCheckOptions, |
| | | getWhMatStatusOptions, |
| | | getWhMatStockLevelOptions |
| | | } from '../whMatPage.helpers' |
| | | |
| | | const props = defineProps({ |
| | | visible: { type: Boolean, default: false }, |
| | | actionType: { type: String, default: 'status' } |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | | const { t } = useI18n() |
| | | |
| | | const formRef = ref() |
| | | const form = reactive(createFormState()) |
| | | |
| | | function createFormState() { |
| | | return { |
| | | status: '', |
| | | stockLevel: '', |
| | | validWarn: null, |
| | | valid: null, |
| | | flagCheck: '' |
| | | } |
| | | } |
| | | |
| | | const dialogTitle = computed(() => |
| | | t(`pages.basicInfo.whMat.batchDialog.titles.${props.actionType}`) |
| | | ) |
| | | |
| | | const formItems = computed(() => { |
| | | if (props.actionType === 'status') { |
| | | return [ |
| | | { |
| | | label: t('table.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.search.statusPlaceholder'), |
| | | options: getWhMatStatusOptions(t) |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | |
| | | if (props.actionType === 'stockLevel') { |
| | | return [ |
| | | { |
| | | label: t('pages.basicInfo.whMat.batchDialog.fields.stockLevel'), |
| | | key: 'stockLevel', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.batchDialog.placeholders.stockLevel'), |
| | | options: getWhMatStockLevelOptions() |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | |
| | | if (props.actionType === 'validWarn') { |
| | | return [ |
| | | { |
| | | label: t('pages.basicInfo.whMat.dialog.fields.validWarn'), |
| | | key: 'validWarn', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.batchDialog.placeholders.validWarn') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.dialog.fields.valid'), |
| | | key: 'valid', |
| | | type: 'number', |
| | | props: { |
| | | min: 0, |
| | | controlsPosition: 'right', |
| | | valueOnClear: null, |
| | | placeholder: t('pages.basicInfo.whMat.batchDialog.placeholders.valid') |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | |
| | | return [ |
| | | { |
| | | label: t('pages.basicInfo.whMat.dialog.fields.flagCheck'), |
| | | key: 'flagCheck', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | clearable: true, |
| | | placeholder: t('pages.basicInfo.whMat.batchDialog.placeholders.flagCheck'), |
| | | options: getWhMatFlagCheckOptions(t) |
| | | } |
| | | } |
| | | ] |
| | | }) |
| | | |
| | | const rules = computed(() => { |
| | | if (props.actionType === 'status') { |
| | | return { |
| | | status: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.batchDialog.validation.status'), |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | |
| | | if (props.actionType === 'stockLevel') { |
| | | return { |
| | | stockLevel: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.batchDialog.validation.stockLevel'), |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | |
| | | if (props.actionType === 'validWarn') { |
| | | return { |
| | | validWarn: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.batchDialog.validation.validWarn'), |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | valid: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.batchDialog.validation.valid'), |
| | | trigger: 'blur' |
| | | } |
| | | ] |
| | | } |
| | | } |
| | | |
| | | return { |
| | | flagCheck: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.batchDialog.validation.flagCheck'), |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | } |
| | | }) |
| | | |
| | | function resetForm() { |
| | | Object.assign(form, createFormState()) |
| | | formRef.value?.clearValidate?.() |
| | | } |
| | | |
| | | async function handleSubmit() { |
| | | if (!formRef.value) return |
| | | try { |
| | | await formRef.value.validate() |
| | | emit('submit', { ...form }) |
| | | } catch { |
| | | return |
| | | } |
| | | } |
| | | |
| | | function handleCancel() { |
| | | emit('update:visible', false) |
| | | } |
| | | |
| | | function handleClosed() { |
| | | resetForm() |
| | | } |
| | | |
| | | watch( |
| | | () => props.visible, |
| | | (visible) => { |
| | | if (visible) { |
| | | resetForm() |
| | | nextTick(() => { |
| | | formRef.value?.clearValidate?.() |
| | | }) |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ) |
| | | </script> |
| New file |
| | |
| | | <template> |
| | | <ElDialog |
| | | :title="t('pages.basicInfo.whMat.batchGroupDialog.title')" |
| | | :model-value="visible" |
| | | width="640px" |
| | | align-center |
| | | destroy-on-close |
| | | @update:model-value="handleCancel" |
| | | @closed="handleClosed" |
| | | > |
| | | <ArtForm |
| | | ref="formRef" |
| | | v-model="form" |
| | | :items="formItems" |
| | | :rules="rules" |
| | | :span="24" |
| | | :gutter="20" |
| | | label-width="120px" |
| | | :show-reset="false" |
| | | :show-submit="false" |
| | | /> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">{{ t('common.confirm') }}</ElButton> |
| | | </span> |
| | | </template> |
| | | </ElDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, nextTick, reactive, ref, watch } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import ArtForm from '@/components/core/forms/art-form/index.vue' |
| | | |
| | | const props = defineProps({ |
| | | visible: { type: Boolean, default: false }, |
| | | groupOptions: { type: Array, default: () => [] } |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | | const { t } = useI18n() |
| | | |
| | | const formRef = ref() |
| | | const form = reactive({ groupId: '' }) |
| | | |
| | | const formItems = computed(() => [ |
| | | { |
| | | label: t('pages.basicInfo.whMat.dialog.fields.groupId'), |
| | | key: 'groupId', |
| | | type: 'treeselect', |
| | | props: { |
| | | data: props.groupOptions, |
| | | props: { |
| | | label: 'displayLabel', |
| | | value: 'value', |
| | | children: 'children' |
| | | }, |
| | | placeholder: t('pages.basicInfo.whMat.dialog.placeholders.groupId'), |
| | | clearable: false, |
| | | checkStrictly: true, |
| | | defaultExpandAll: true |
| | | } |
| | | } |
| | | ]) |
| | | |
| | | const rules = computed(() => ({ |
| | | groupId: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.dialog.validation.groupId'), |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | })) |
| | | |
| | | function resetForm() { |
| | | form.groupId = '' |
| | | formRef.value?.clearValidate?.() |
| | | } |
| | | |
| | | async function handleSubmit() { |
| | | if (!formRef.value) return |
| | | try { |
| | | await formRef.value.validate() |
| | | emit('submit', { ...form }) |
| | | } catch { |
| | | return |
| | | } |
| | | } |
| | | |
| | | function handleCancel() { |
| | | emit('update:visible', false) |
| | | } |
| | | |
| | | function handleClosed() { |
| | | resetForm() |
| | | } |
| | | |
| | | watch( |
| | | () => props.visible, |
| | | (visible) => { |
| | | if (visible) { |
| | | resetForm() |
| | | nextTick(() => { |
| | | formRef.value?.clearValidate?.() |
| | | }) |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ) |
| | | </script> |
| New file |
| | |
| | | <template> |
| | | <ElDialog |
| | | :title="t('pages.basicInfo.whMat.bindLocDialog.title')" |
| | | :model-value="visible" |
| | | width="960px" |
| | | align-center |
| | | destroy-on-close |
| | | @update:model-value="handleCancel" |
| | | @closed="handleClosed" |
| | | > |
| | | <ArtForm |
| | | ref="formRef" |
| | | v-model="form" |
| | | :items="formItems" |
| | | :rules="rules" |
| | | :span="12" |
| | | :gutter="20" |
| | | label-width="120px" |
| | | :show-reset="false" |
| | | :show-submit="false" |
| | | /> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">{{ t('common.confirm') }}</ElButton> |
| | | </span> |
| | | </template> |
| | | </ElDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, nextTick, reactive, ref, watch } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import ArtForm from '@/components/core/forms/art-form/index.vue' |
| | | |
| | | const props = defineProps({ |
| | | visible: { type: Boolean, default: false }, |
| | | areaMatOptions: { type: Array, default: () => [] }, |
| | | areaOptions: { type: Array, default: () => [] }, |
| | | locOptions: { type: Array, default: () => [] } |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | | const { t } = useI18n() |
| | | |
| | | const formRef = ref() |
| | | const form = reactive({ |
| | | areaMatId: '', |
| | | areaId: '', |
| | | locId: [] |
| | | }) |
| | | |
| | | const filteredAreaMatOptions = computed(() => { |
| | | const selectedAreaId = |
| | | form.areaId !== undefined && form.areaId !== null && form.areaId !== '' |
| | | ? Number(form.areaId) |
| | | : void 0 |
| | | if (selectedAreaId === void 0) { |
| | | return props.areaMatOptions |
| | | } |
| | | return props.areaMatOptions.filter( |
| | | (item) => item.areaId === void 0 || Number(item.areaId) === selectedAreaId |
| | | ) |
| | | }) |
| | | |
| | | const filteredLocOptions = computed(() => { |
| | | const selectedAreaId = |
| | | form.areaId !== undefined && form.areaId !== null && form.areaId !== '' |
| | | ? Number(form.areaId) |
| | | : void 0 |
| | | if (selectedAreaId === void 0) { |
| | | return props.locOptions |
| | | } |
| | | return props.locOptions.filter( |
| | | (item) => item.areaId === void 0 || Number(item.areaId) === selectedAreaId |
| | | ) |
| | | }) |
| | | |
| | | const formItems = computed(() => [ |
| | | { |
| | | label: t('pages.basicInfo.whMat.bindLocDialog.fields.areaMatId'), |
| | | key: 'areaMatId', |
| | | type: 'select', |
| | | props: { |
| | | clearable: true, |
| | | filterable: true, |
| | | placeholder: t('pages.basicInfo.whMat.bindLocDialog.placeholders.areaMatId'), |
| | | options: filteredAreaMatOptions.value |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.bindLocDialog.fields.areaId'), |
| | | key: 'areaId', |
| | | type: 'select', |
| | | props: { |
| | | clearable: true, |
| | | filterable: true, |
| | | placeholder: t('pages.basicInfo.whMat.bindLocDialog.placeholders.areaId'), |
| | | options: props.areaOptions |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.basicInfo.whMat.bindLocDialog.fields.locId'), |
| | | key: 'locId', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | clearable: true, |
| | | filterable: true, |
| | | multiple: true, |
| | | collapseTags: true, |
| | | placeholder: t('pages.basicInfo.whMat.bindLocDialog.placeholders.locId'), |
| | | options: filteredLocOptions.value |
| | | } |
| | | } |
| | | ]) |
| | | |
| | | const rules = computed(() => ({ |
| | | areaMatId: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.bindLocDialog.validation.areaMatId'), |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | areaId: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.bindLocDialog.validation.areaId'), |
| | | trigger: 'change' |
| | | } |
| | | ], |
| | | locId: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.bindLocDialog.validation.locId'), |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | })) |
| | | |
| | | function resetForm() { |
| | | form.areaMatId = '' |
| | | form.areaId = '' |
| | | form.locId = [] |
| | | formRef.value?.clearValidate?.() |
| | | } |
| | | |
| | | async function handleSubmit() { |
| | | if (!formRef.value) return |
| | | try { |
| | | await formRef.value.validate() |
| | | emit('submit', { |
| | | areaMatId: form.areaMatId, |
| | | areaId: form.areaId, |
| | | locId: Array.isArray(form.locId) ? [...form.locId] : [] |
| | | }) |
| | | } catch { |
| | | return |
| | | } |
| | | } |
| | | |
| | | function handleCancel() { |
| | | emit('update:visible', false) |
| | | } |
| | | |
| | | function handleClosed() { |
| | | resetForm() |
| | | } |
| | | |
| | | watch( |
| | | () => props.visible, |
| | | (visible) => { |
| | | if (visible) { |
| | | resetForm() |
| | | nextTick(() => { |
| | | formRef.value?.clearValidate?.() |
| | | }) |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ) |
| | | </script> |
| New file |
| | |
| | | <template> |
| | | <ElDialog |
| | | :title="dialogTitle" |
| | | :model-value="visible" |
| | | width="960px" |
| | | align-center |
| | | destroy-on-close |
| | | @update:model-value="handleCancel" |
| | | @closed="handleClosed" |
| | | > |
| | | <ElForm |
| | | ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="110px" |
| | | class="wh-mat-dialog-form" |
| | | > |
| | | <ElTabs v-model="activeTab"> |
| | | <ElTabPane :label="t('pages.basicInfo.whMat.dialog.tabs.basic')" name="basic"> |
| | | <ElRow :gutter="20"> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.code')" prop="code"> |
| | | <ElInput |
| | | v-model.trim="form.code" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.code')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.name')" prop="name"> |
| | | <ElInput |
| | | v-model.trim="form.name" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.name')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.groupId')" prop="groupId"> |
| | | <ElTreeSelect |
| | | v-model="form.groupId" |
| | | :data="groupOptions" |
| | | :props="groupTreeProps" |
| | | check-strictly |
| | | default-expand-all |
| | | clearable |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.groupId')" |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem |
| | | :label="t('pages.basicInfo.whMat.dialog.fields.useOrgName')" |
| | | prop="useOrgName" |
| | | > |
| | | <ElInput |
| | | v-model.trim="form.useOrgName" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.useOrgName')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.spec')" prop="spec"> |
| | | <ElInput |
| | | v-model.trim="form.spec" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.spec')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.model')" prop="model"> |
| | | <ElInput |
| | | v-model.trim="form.model" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.model')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.color')" prop="color"> |
| | | <ElInput |
| | | v-model.trim="form.color" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.color')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.size')" prop="size"> |
| | | <ElInput |
| | | v-model.trim="form.size" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.size')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.weight')" prop="weight"> |
| | | <ElInputNumber |
| | | v-model="form.weight" |
| | | :min="0" |
| | | controls-position="right" |
| | | class="w-full" |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.unit')" prop="unit"> |
| | | <ElInput |
| | | v-model.trim="form.unit" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.unit')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.purUnit')" prop="purUnit"> |
| | | <ElInput |
| | | v-model.trim="form.purUnit" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.purUnit')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem |
| | | :label="t('pages.basicInfo.whMat.dialog.fields.describle')" |
| | | prop="describle" |
| | | > |
| | | <ElInput |
| | | v-model.trim="form.describle" |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.describle')" |
| | | clearable |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | </ElRow> |
| | | </ElTabPane> |
| | | |
| | | <ElTabPane :label="t('pages.basicInfo.whMat.dialog.tabs.control')" name="control"> |
| | | <ElRow :gutter="20"> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.safeQty')" prop="safeQty"> |
| | | <ElInputNumber |
| | | v-model="form.safeQty" |
| | | :min="0" |
| | | controls-position="right" |
| | | class="w-full" |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.minQty')" prop="minQty"> |
| | | <ElInputNumber |
| | | v-model="form.minQty" |
| | | :min="0" |
| | | controls-position="right" |
| | | class="w-full" |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.maxQty')" prop="maxQty"> |
| | | <ElInputNumber |
| | | v-model="form.maxQty" |
| | | :min="0" |
| | | controls-position="right" |
| | | class="w-full" |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.stagn')" prop="stagn"> |
| | | <ElInputNumber |
| | | v-model="form.stagn" |
| | | :min="0" |
| | | controls-position="right" |
| | | class="w-full" |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.valid')" prop="valid"> |
| | | <ElInputNumber |
| | | v-model="form.valid" |
| | | :min="0" |
| | | controls-position="right" |
| | | class="w-full" |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem |
| | | :label="t('pages.basicInfo.whMat.dialog.fields.validWarn')" |
| | | prop="validWarn" |
| | | > |
| | | <ElInputNumber |
| | | v-model="form.validWarn" |
| | | :min="0" |
| | | controls-position="right" |
| | | class="w-full" |
| | | /> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | <ElCol :span="12"> |
| | | <ElFormItem |
| | | :label="t('pages.basicInfo.whMat.dialog.fields.flagCheck')" |
| | | prop="flagCheck" |
| | | > |
| | | <ElSelect |
| | | v-model="form.flagCheck" |
| | | clearable |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.flagCheck')" |
| | | > |
| | | <ElOption |
| | | v-for="option in flagCheckOptions" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | </ElSelect> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | </ElRow> |
| | | </ElTabPane> |
| | | |
| | | <ElTabPane :label="t('pages.basicInfo.whMat.dialog.tabs.batchRule')" name="batchRule"> |
| | | <ElRow :gutter="20"> |
| | | <ElCol :span="12"> |
| | | <ElFormItem :label="t('pages.basicInfo.whMat.dialog.fields.rglarId')" prop="rglarId"> |
| | | <ElSelect |
| | | v-model="form.rglarId" |
| | | clearable |
| | | filterable |
| | | :placeholder="t('pages.basicInfo.whMat.dialog.placeholders.rglarId')" |
| | | > |
| | | <ElOption |
| | | v-for="option in serialRuleOptions" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | </ElSelect> |
| | | </ElFormItem> |
| | | </ElCol> |
| | | </ElRow> |
| | | </ElTabPane> |
| | | </ElTabs> |
| | | </ElForm> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">{{ t('common.confirm') }}</ElButton> |
| | | </span> |
| | | </template> |
| | | </ElDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, nextTick, reactive, ref, watch } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { |
| | | buildWhMatDialogModel, |
| | | createWhMatFormState, |
| | | getWhMatFlagCheckOptions |
| | | } from '../whMatPage.helpers' |
| | | |
| | | const props = defineProps({ |
| | | visible: { type: Boolean, default: false }, |
| | | dialogType: { type: String, default: 'add' }, |
| | | materialData: { type: Object, default: () => ({}) }, |
| | | groupOptions: { type: Array, default: () => [] }, |
| | | serialRuleOptions: { type: Array, default: () => [] } |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | | const { t } = useI18n() |
| | | |
| | | const formRef = ref() |
| | | const activeTab = ref('basic') |
| | | const form = reactive(createWhMatFormState()) |
| | | |
| | | const dialogTitle = computed(() => |
| | | props.dialogType === 'edit' |
| | | ? t('pages.basicInfo.whMat.dialog.titleEdit') |
| | | : t('pages.basicInfo.whMat.dialog.titleCreate') |
| | | ) |
| | | const flagCheckOptions = computed(() => getWhMatFlagCheckOptions(t)) |
| | | const groupTreeProps = { |
| | | label: 'displayLabel', |
| | | value: 'value', |
| | | children: 'children' |
| | | } |
| | | |
| | | const rules = computed(() => ({ |
| | | code: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.dialog.validation.code'), |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | name: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.dialog.validation.name'), |
| | | trigger: 'blur' |
| | | } |
| | | ], |
| | | groupId: [ |
| | | { |
| | | required: true, |
| | | message: t('pages.basicInfo.whMat.dialog.validation.groupId'), |
| | | trigger: 'change' |
| | | } |
| | | ] |
| | | })) |
| | | |
| | | function loadFormData() { |
| | | Object.assign(form, buildWhMatDialogModel(props.materialData)) |
| | | activeTab.value = 'basic' |
| | | } |
| | | |
| | | function resetForm() { |
| | | Object.assign(form, createWhMatFormState()) |
| | | formRef.value?.clearValidate?.() |
| | | activeTab.value = 'basic' |
| | | } |
| | | |
| | | async function handleSubmit() { |
| | | try { |
| | | await formRef.value?.validate?.() |
| | | emit('submit', { ...form }) |
| | | } catch { |
| | | return |
| | | } |
| | | } |
| | | |
| | | function handleCancel() { |
| | | emit('update:visible', false) |
| | | } |
| | | |
| | | function handleClosed() { |
| | | resetForm() |
| | | } |
| | | |
| | | watch( |
| | | () => props.visible, |
| | | (visible) => { |
| | | if (visible) { |
| | | loadFormData() |
| | | nextTick(() => { |
| | | formRef.value?.clearValidate?.() |
| | | }) |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ) |
| | | |
| | | watch( |
| | | () => props.materialData, |
| | | () => { |
| | | if (props.visible) { |
| | | loadFormData() |
| | | } |
| | | }, |
| | | { deep: true } |
| | | ) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .wh-mat-dialog-form :deep(.el-select), |
| | | .wh-mat-dialog-form :deep(.el-tree-select) { |
| | | width: 100%; |
| | | } |
| | | </style> |
| | |
| | | import { $t } from '@/locales' |
| | | |
| | | export const WH_MAT_REPORT_TITLE = '物料报表' |
| | | export const WH_MAT_REPORT_STYLE = { |
| | | orientation: 'landscape', |
| | | titleAlign: 'center', |
| | | titleLevel: 'h2' |
| | | } |
| | | export const WH_MAT_DYNAMIC_FIELD_PREFIX = 'extendField__' |
| | | |
| | | function normalizeText(value) { |
| | | return String(value ?? '').trim() |
| | | } |
| | |
| | | return Number.isFinite(numericValue) ? numericValue : null |
| | | } |
| | | |
| | | function normalizeNullableInteger(value) { |
| | | const numericValue = normalizeNullableNumber(value) |
| | | return numericValue === null ? null : Math.trunc(numericValue) |
| | | } |
| | | |
| | | function normalizeBooleanLikeText(value, t = $t) { |
| | | if (value === 1 || value === '1') return t('common.status.yes') |
| | | if (value === 0 || value === '0') return t('common.status.no') |
| | | return t('common.placeholder.empty') |
| | | } |
| | | |
| | | export function createWhMatSearchState() { |
| | | return { |
| | | condition: '', |
| | | code: '', |
| | | name: '', |
| | | platCode: '', |
| | | spec: '', |
| | | model: '', |
| | | barcode: '' |
| | | color: '', |
| | | size: '', |
| | | unit: '', |
| | | purUnit: '', |
| | | stockUnit: '', |
| | | barcode: '', |
| | | describle: '', |
| | | groupId: '', |
| | | rglarId: '', |
| | | weight: null, |
| | | nromNum: null, |
| | | stockLevel: '', |
| | | flagLabelMange: '', |
| | | safeQty: null, |
| | | minQty: null, |
| | | maxQty: null, |
| | | stagn: null, |
| | | valid: null, |
| | | status: '', |
| | | flagCheck: '', |
| | | validWarn: null, |
| | | memo: '', |
| | | orderBy: 'create_time desc' |
| | | } |
| | | } |
| | | |
| | | export function createWhMatFormState() { |
| | | return { |
| | | id: void 0, |
| | | code: '', |
| | | name: '', |
| | | groupId: '', |
| | | useOrgName: '', |
| | | spec: '', |
| | | model: '', |
| | | color: '', |
| | | size: '', |
| | | weight: void 0, |
| | | unit: '', |
| | | purUnit: '', |
| | | describle: '', |
| | | safeQty: void 0, |
| | | minQty: void 0, |
| | | maxQty: void 0, |
| | | stagn: void 0, |
| | | valid: void 0, |
| | | validWarn: void 0, |
| | | flagCheck: 0, |
| | | rglarId: '' |
| | | } |
| | | } |
| | | |
| | | export function buildWhMatPageQueryParams(params = {}) { |
| | | const result = { |
| | | current: params.current || 1, |
| | | pageSize: params.pageSize || params.size || 20 |
| | | pageSize: params.pageSize || params.size || 20, |
| | | orderBy: normalizeText(params.orderBy) || 'create_time desc' |
| | | } |
| | | |
| | | ;['condition', 'code', 'name', 'spec', 'model', 'barcode'].forEach((key) => { |
| | | ;[ |
| | | 'condition', |
| | | 'code', |
| | | 'name', |
| | | 'platCode', |
| | | 'spec', |
| | | 'model', |
| | | 'color', |
| | | 'size', |
| | | 'unit', |
| | | 'purUnit', |
| | | 'stockUnit', |
| | | 'barcode', |
| | | 'describle', |
| | | 'memo' |
| | | ].forEach((key) => { |
| | | const value = normalizeText(params[key]) |
| | | if (value) { |
| | | result[key] = value |
| | | } |
| | | }) |
| | | ;[ |
| | | 'groupId', |
| | | 'rglarId', |
| | | 'weight', |
| | | 'nromNum', |
| | | 'stockLevel', |
| | | 'flagLabelMange', |
| | | 'safeQty', |
| | | 'minQty', |
| | | 'maxQty', |
| | | 'stagn', |
| | | 'valid', |
| | | 'status', |
| | | 'flagCheck', |
| | | 'validWarn' |
| | | ].forEach((key) => { |
| | | const value = params[key] |
| | | if (value !== '' && value !== null && value !== undefined) { |
| | | const numericValue = Number(value) |
| | | result[key] = Number.isFinite(numericValue) ? numericValue : value |
| | | } |
| | | }) |
| | | |
| | | if (params.groupId !== undefined && params.groupId !== null && params.groupId !== '') { |
| | | result.groupId = String(params.groupId) |
| | | } |
| | | Object.entries(params).forEach(([key, value]) => { |
| | | if (!key.startsWith(WH_MAT_DYNAMIC_FIELD_PREFIX)) { |
| | | return |
| | | } |
| | | const normalizedValue = normalizeText(value) |
| | | if (normalizedValue) { |
| | | result[key.slice(WH_MAT_DYNAMIC_FIELD_PREFIX.length)] = normalizedValue |
| | | } |
| | | }) |
| | | |
| | | return result |
| | | } |
| | |
| | | } |
| | | |
| | | return records.map((item) => { |
| | | const children = normalizeWhMatGroupTreeRows(item?.children || []) |
| | | const children = normalizeWhMatGroupTreeRows(item?.children || [], t) |
| | | const id = normalizeNullableNumber(item?.id) |
| | | const code = normalizeText(item?.code) |
| | | const name = normalizeText(item?.name) |
| | |
| | | name, |
| | | label, |
| | | displayLabel: label, |
| | | value: id, |
| | | status: normalizeNullableNumber(item?.status), |
| | | statusText: normalizeNumber(item?.status, 1) === 1 ? t('common.status.normal') : t('common.status.frozen'), |
| | | statusText: |
| | | normalizeNumber(item?.status, 1) === 1 |
| | | ? t('common.status.normal') |
| | | : t('common.status.frozen'), |
| | | statusType: normalizeNumber(item?.status, 1) === 1 ? 'success' : 'danger', |
| | | memo: normalizeText(item?.memo) || t('common.placeholder.empty'), |
| | | children |
| | |
| | | }) |
| | | } |
| | | |
| | | export function normalizeWhMatRow(record = {}, t = $t) { |
| | | const statusValue = normalizeNullableNumber(record?.status) |
| | | export function resolveWhMatGroupOptions(treeRows = []) { |
| | | if (!Array.isArray(treeRows)) { |
| | | return [] |
| | | } |
| | | |
| | | return treeRows.map((item) => ({ |
| | | id: item.id, |
| | | value: item.id, |
| | | label: |
| | | item.displayLabel || item.label || [item.name, item.code].filter(Boolean).join(' · ') || '-', |
| | | displayLabel: |
| | | item.displayLabel || item.label || [item.name, item.code].filter(Boolean).join(' · ') || '-', |
| | | children: resolveWhMatGroupOptions(item.children || []) |
| | | })) |
| | | } |
| | | |
| | | export function resolveWhMatSerialRuleOptions(records = []) { |
| | | if (!Array.isArray(records)) { |
| | | return [] |
| | | } |
| | | return records |
| | | .map((item) => ({ |
| | | value: normalizeNullableNumber(item?.id), |
| | | label: normalizeText(item?.name || item?.code || item?.description) |
| | | })) |
| | | .filter((item) => item.value !== null && item.label) |
| | | } |
| | | |
| | | export function getWhMatStatusOptions(t = $t) { |
| | | return [ |
| | | { value: 1, label: t('common.status.normal') }, |
| | | { value: 0, label: t('common.status.frozen') } |
| | | ] |
| | | } |
| | | |
| | | export function getWhMatFlagCheckOptions(t = $t) { |
| | | return [ |
| | | { value: 0, label: t('common.status.no') }, |
| | | { value: 1, label: t('common.status.yes') } |
| | | ] |
| | | } |
| | | |
| | | export function getWhMatStockLevelOptions() { |
| | | return [ |
| | | { value: 0, label: 'A' }, |
| | | { value: 1, label: 'B' }, |
| | | { value: 2, label: 'C' } |
| | | ] |
| | | } |
| | | |
| | | export function getWhMatFlagLabelManageOptions(t = $t) { |
| | | return [ |
| | | { value: 0, label: t('common.status.no') }, |
| | | { value: 1, label: t('common.status.yes') } |
| | | ] |
| | | } |
| | | |
| | | export function getWhMatDynamicFieldKey(fieldName) { |
| | | return `${WH_MAT_DYNAMIC_FIELD_PREFIX}${fieldName}` |
| | | } |
| | | |
| | | export function normalizeWhMatEnabledFields(fields = []) { |
| | | if (!Array.isArray(fields)) { |
| | | return [] |
| | | } |
| | | |
| | | return fields |
| | | .map((item) => ({ |
| | | fields: normalizeText(item?.fields), |
| | | fieldsAlise: normalizeText(item?.fieldsAlise || item?.fieldsAlias || item?.fields) |
| | | })) |
| | | .filter((item) => item.fields) |
| | | } |
| | | |
| | | export function attachWhMatDynamicFields(record = {}, enabledFields = []) { |
| | | const extendFields = |
| | | record?.extendFields && |
| | | typeof record.extendFields === 'object' && |
| | | !Array.isArray(record.extendFields) |
| | | ? record.extendFields |
| | | : {} |
| | | const dynamicValues = {} |
| | | |
| | | enabledFields.forEach((field) => { |
| | | dynamicValues[getWhMatDynamicFieldKey(field.fields)] = extendFields[field.fields] || '' |
| | | }) |
| | | |
| | | return { |
| | | ...record, |
| | | code: normalizeText(record?.code) || t('common.placeholder.empty'), |
| | | name: normalizeText(record?.name) || t('common.placeholder.empty'), |
| | | groupName: normalizeText(record?.groupId$ || record?.groupCode) || t('common.placeholder.empty'), |
| | | shipperName: normalizeText(record?.shipperId$ || record?.shipperName) || t('common.placeholder.empty'), |
| | | barcode: normalizeText(record?.barcode) || t('common.placeholder.empty'), |
| | | spec: normalizeText(record?.spec) || t('common.placeholder.empty'), |
| | | model: normalizeText(record?.model) || t('common.placeholder.empty'), |
| | | color: normalizeText(record?.color) || t('common.placeholder.empty'), |
| | | size: normalizeText(record?.size) || t('common.placeholder.empty'), |
| | | unit: normalizeText(record?.unit) || t('common.placeholder.empty'), |
| | | purUnit: normalizeText(record?.purUnit) || t('common.placeholder.empty'), |
| | | stockUnit: normalizeText(record?.stockUnit) || t('common.placeholder.empty'), |
| | | stockLevelText: normalizeText(record?.stockLeval$) || t('common.placeholder.empty'), |
| | | flagLabelManageText: normalizeText(record?.flagLabelMange$) || t('common.placeholder.empty'), |
| | | flagCheckText: |
| | | record?.flagCheck === 1 || record?.flagCheck === '1' |
| | | ? t('common.status.yes') |
| | | : record?.flagCheck === 0 || record?.flagCheck === '0' |
| | | ? t('common.status.no') |
| | | : t('common.placeholder.empty'), |
| | | statusText: |
| | | normalizeText(record?.status$) || |
| | | (statusValue === 1 |
| | | ? t('common.status.normal') |
| | | : statusValue === 0 |
| | | ? t('common.status.frozen') |
| | | : t('common.placeholder.empty')), |
| | | statusType: statusValue === 1 ? 'success' : statusValue === 0 ? 'danger' : 'info', |
| | | safeQty: record?.safeQty ?? t('common.placeholder.empty'), |
| | | minQty: record?.minQty ?? t('common.placeholder.empty'), |
| | | maxQty: record?.maxQty ?? t('common.placeholder.empty'), |
| | | valid: record?.valid ?? t('common.placeholder.empty'), |
| | | validWarn: record?.validWarn ?? t('common.placeholder.empty'), |
| | | stagn: record?.stagn ?? t('common.placeholder.empty'), |
| | | describle: normalizeText(record?.describle) || t('common.placeholder.empty'), |
| | | baseUnit: normalizeText(record?.baseUnit) || t('common.placeholder.empty'), |
| | | useOrgName: normalizeText(record?.useOrgName) || t('common.placeholder.empty'), |
| | | erpClsId: normalizeText(record?.erpClsId) || t('common.placeholder.empty'), |
| | | memo: normalizeText(record?.memo) || t('common.placeholder.empty'), |
| | | updateByText: normalizeText(record?.updateBy$) || t('common.placeholder.empty'), |
| | | createByText: normalizeText(record?.createBy$) || t('common.placeholder.empty'), |
| | | updateTimeText: normalizeText(record?.updateTime$ || record?.updateTime) || t('common.placeholder.empty'), |
| | | createTimeText: normalizeText(record?.createTime$ || record?.createTime) || t('common.placeholder.empty'), |
| | | extendFields: |
| | | record?.extendFields && typeof record.extendFields === 'object' && !Array.isArray(record.extendFields) |
| | | ? record.extendFields |
| | | : {} |
| | | ...dynamicValues, |
| | | extendFields |
| | | } |
| | | } |
| | | |
| | | export function normalizeWhMatDetail(record = {}, t = $t) { |
| | | return normalizeWhMatRow(record, t) |
| | | export function normalizeWhMatRow(record = {}, t = $t, enabledFields = []) { |
| | | const statusValue = normalizeNullableNumber(record?.status) |
| | | const validWarn = record?.validWarn ?? record?.valid_warn |
| | | const purUnit = record?.purUnit ?? record?.purchaseUnit |
| | | const stockLevelLabel = |
| | | getWhMatStockLevelOptions().find( |
| | | (item) => item.value === normalizeNullableNumber(record?.stockLevel) |
| | | )?.label || '' |
| | | const flagLabelManageLabel = |
| | | getWhMatFlagLabelManageOptions(t).find( |
| | | (item) => item.value === normalizeNullableNumber(record?.flagLabelMange) |
| | | )?.label || '' |
| | | |
| | | return attachWhMatDynamicFields( |
| | | { |
| | | ...record, |
| | | id: normalizeNullableNumber(record?.id), |
| | | code: normalizeText(record?.code) || t('common.placeholder.empty'), |
| | | name: normalizeText(record?.name) || t('common.placeholder.empty'), |
| | | groupId: normalizeNullableNumber(record?.groupId), |
| | | groupName: |
| | | normalizeText(record?.groupId$ || record?.groupCode || record?.groupName) || |
| | | t('common.placeholder.empty'), |
| | | shipperName: |
| | | normalizeText(record?.shipperId$ || record?.shipperName) || t('common.placeholder.empty'), |
| | | barcode: normalizeText(record?.barcode) || t('common.placeholder.empty'), |
| | | platCode: normalizeText(record?.platCode) || t('common.placeholder.empty'), |
| | | spec: normalizeText(record?.spec) || t('common.placeholder.empty'), |
| | | model: normalizeText(record?.model) || t('common.placeholder.empty'), |
| | | color: normalizeText(record?.color) || t('common.placeholder.empty'), |
| | | size: normalizeText(record?.size) || t('common.placeholder.empty'), |
| | | weight: record?.weight ?? t('common.placeholder.empty'), |
| | | nromNum: record?.nromNum ?? t('common.placeholder.empty'), |
| | | unit: normalizeText(record?.unit) || t('common.placeholder.empty'), |
| | | purUnit: normalizeText(purUnit) || t('common.placeholder.empty'), |
| | | stockUnit: normalizeText(record?.stockUnit) || t('common.placeholder.empty'), |
| | | stockLevelText: |
| | | normalizeText(record?.stockLeval$ || record?.stockLevel$ || stockLevelLabel) || |
| | | t('common.placeholder.empty'), |
| | | flagLabelManageText: |
| | | normalizeText(record?.flagLabelMange$ || record?.isLabelMange$ || flagLabelManageLabel) || |
| | | t('common.placeholder.empty'), |
| | | flagCheckText: normalizeBooleanLikeText(record?.flagCheck, t), |
| | | statusText: |
| | | normalizeText(record?.status$) || |
| | | (statusValue === 1 |
| | | ? t('common.status.normal') |
| | | : statusValue === 0 |
| | | ? t('common.status.frozen') |
| | | : t('common.placeholder.empty')), |
| | | statusType: statusValue === 1 ? 'success' : statusValue === 0 ? 'danger' : 'info', |
| | | safeQty: record?.safeQty ?? t('common.placeholder.empty'), |
| | | minQty: record?.minQty ?? t('common.placeholder.empty'), |
| | | maxQty: record?.maxQty ?? t('common.placeholder.empty'), |
| | | valid: record?.valid ?? t('common.placeholder.empty'), |
| | | validWarn: validWarn ?? t('common.placeholder.empty'), |
| | | stagn: record?.stagn ?? t('common.placeholder.empty'), |
| | | describle: normalizeText(record?.describle) || t('common.placeholder.empty'), |
| | | baseUnit: normalizeText(record?.baseUnit) || t('common.placeholder.empty'), |
| | | useOrgName: normalizeText(record?.useOrgName) || t('common.placeholder.empty'), |
| | | erpClsId: normalizeText(record?.erpClsId) || t('common.placeholder.empty'), |
| | | rglarId: normalizeNullableNumber(record?.rglarId), |
| | | rglarName: |
| | | normalizeText(record?.rglarId$ || record?.rglarName || record?.rglarCode) || |
| | | t('common.placeholder.empty'), |
| | | memo: normalizeText(record?.memo) || t('common.placeholder.empty'), |
| | | updateByText: normalizeText(record?.updateBy$) || t('common.placeholder.empty'), |
| | | createByText: normalizeText(record?.createBy$) || t('common.placeholder.empty'), |
| | | updateTimeText: |
| | | normalizeText(record?.updateTime$ || record?.updateTime) || t('common.placeholder.empty'), |
| | | createTimeText: |
| | | normalizeText(record?.createTime$ || record?.createTime) || t('common.placeholder.empty') |
| | | }, |
| | | enabledFields |
| | | ) |
| | | } |
| | | |
| | | export function normalizeWhMatDetail(record = {}, t = $t, enabledFields = []) { |
| | | return normalizeWhMatRow(record, t, enabledFields) |
| | | } |
| | | |
| | | export function buildWhMatDialogModel(record = {}) { |
| | | const source = normalizeWhMatRow(record) |
| | | return { |
| | | ...createWhMatFormState(), |
| | | id: source.id ?? void 0, |
| | | code: normalizeText(record?.code), |
| | | name: normalizeText(record?.name), |
| | | groupId: source.groupId ?? '', |
| | | useOrgName: normalizeText(record?.useOrgName), |
| | | spec: normalizeText(record?.spec), |
| | | model: normalizeText(record?.model), |
| | | color: normalizeText(record?.color), |
| | | size: normalizeText(record?.size), |
| | | weight: normalizeNullableNumber(record?.weight), |
| | | unit: normalizeText(record?.unit), |
| | | purUnit: normalizeText(record?.purUnit || record?.purchaseUnit), |
| | | describle: normalizeText(record?.describle), |
| | | safeQty: normalizeNullableNumber(record?.safeQty), |
| | | minQty: normalizeNullableNumber(record?.minQty), |
| | | maxQty: normalizeNullableNumber(record?.maxQty), |
| | | stagn: normalizeNullableInteger(record?.stagn), |
| | | valid: normalizeNullableInteger(record?.valid), |
| | | validWarn: normalizeNullableInteger(record?.validWarn), |
| | | flagCheck: normalizeNullableInteger(record?.flagCheck) ?? 0, |
| | | rglarId: normalizeNullableNumber(record?.rglarId) ?? '' |
| | | } |
| | | } |
| | | |
| | | export function buildWhMatSavePayload(formData = {}) { |
| | | const payload = { |
| | | ...(formData.id !== undefined && formData.id !== null ? { id: Number(formData.id) } : {}), |
| | | code: normalizeText(formData.code), |
| | | name: normalizeText(formData.name), |
| | | groupId: |
| | | formData.groupId !== undefined && formData.groupId !== null && formData.groupId !== '' |
| | | ? Number(formData.groupId) |
| | | : void 0, |
| | | useOrgName: normalizeText(formData.useOrgName), |
| | | spec: normalizeText(formData.spec), |
| | | model: normalizeText(formData.model), |
| | | color: normalizeText(formData.color), |
| | | size: normalizeText(formData.size), |
| | | weight: normalizeNullableNumber(formData.weight), |
| | | unit: normalizeText(formData.unit), |
| | | purUnit: normalizeText(formData.purUnit), |
| | | describle: normalizeText(formData.describle), |
| | | safeQty: normalizeNullableNumber(formData.safeQty), |
| | | minQty: normalizeNullableNumber(formData.minQty), |
| | | maxQty: normalizeNullableNumber(formData.maxQty), |
| | | stagn: normalizeNullableInteger(formData.stagn), |
| | | valid: normalizeNullableInteger(formData.valid), |
| | | validWarn: normalizeNullableInteger(formData.validWarn), |
| | | flagCheck: normalizeNullableInteger(formData.flagCheck), |
| | | rglarId: |
| | | formData.rglarId !== undefined && formData.rglarId !== null && formData.rglarId !== '' |
| | | ? Number(formData.rglarId) |
| | | : void 0 |
| | | } |
| | | |
| | | return Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== undefined)) |
| | | } |
| | | |
| | | export function getWhMatTreeNodeLabel(node = {}) { |
| | |
| | | return [name, code].filter(Boolean).join(' · ') || $t('common.placeholder.empty') |
| | | } |
| | | |
| | | export function buildWhMatPrintRows(records = [], t = $t) { |
| | | return records.map((record) => { |
| | | const normalizedRecord = normalizeWhMatRow(record, t) |
| | | return { |
| | | 物料编码: normalizedRecord.code, |
| | | 物料名称: normalizedRecord.name, |
| | | 物料分组: normalizedRecord.groupName, |
| | | 规格: normalizedRecord.spec, |
| | | 型号: normalizedRecord.model, |
| | | 单位: normalizedRecord.unit, |
| | | 状态: normalizedRecord.statusText, |
| | | 更新时间: normalizedRecord.updateTimeText |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export function buildWhMatReportMeta({ |
| | | previewMeta = {}, |
| | | count = 0, |
| | | orientation = WH_MAT_REPORT_STYLE.orientation |
| | | } = {}) { |
| | | return { |
| | | reportTitle: WH_MAT_REPORT_TITLE, |
| | | count, |
| | | ...previewMeta, |
| | | reportStyle: { |
| | | ...WH_MAT_REPORT_STYLE, |
| | | ...(previewMeta.reportStyle || {}), |
| | | orientation |
| | | } |
| | | } |
| | | } |
| | | |
| | | export const buildMatnrPageQueryParams = buildWhMatPageQueryParams |
| | | export const buildMatnrGroupTreeQueryParams = buildWhMatGroupTreeQueryParams |
| | | export const normalizeMatnrGroupTreeRows = normalizeWhMatGroupTreeRows |
| | |
| | | import { h } from 'vue' |
| | | import { ElTag } from 'element-plus' |
| | | import { $t } from '@/locales' |
| | | import ArtButtonMore from '@/components/core/forms/art-button-more/index.vue' |
| | | import { getWhMatDynamicFieldKey } from './whMatPage.helpers' |
| | | |
| | | export function createWhMatTableColumns({ handleViewDetail, t = $t }) { |
| | | export function createWhMatTableColumns({ |
| | | handleViewDetail, |
| | | handleEdit, |
| | | handleDelete, |
| | | handlePrint, |
| | | enabledFields = [], |
| | | canEdit = true, |
| | | canDelete = true, |
| | | t = $t |
| | | } = {}) { |
| | | const operations = [{ key: 'view', label: t('common.actions.detail'), icon: 'ri:eye-line' }] |
| | | |
| | | if (canEdit && handleEdit) { |
| | | operations.push({ key: 'edit', label: t('common.actions.edit'), icon: 'ri:pencil-line' }) |
| | | } |
| | | |
| | | if (handlePrint) { |
| | | operations.push({ key: 'print', label: t('common.actions.print'), icon: 'ri:printer-line' }) |
| | | } |
| | | |
| | | if (canDelete && handleDelete) { |
| | | operations.push({ |
| | | key: 'delete', |
| | | label: t('common.actions.delete'), |
| | | icon: 'ri:delete-bin-5-line', |
| | | color: 'var(--art-error)' |
| | | }) |
| | | } |
| | | |
| | | const dynamicColumns = Array.isArray(enabledFields) |
| | | ? enabledFields.map((field) => ({ |
| | | prop: getWhMatDynamicFieldKey(field.fields), |
| | | label: field.fieldsAlise, |
| | | minWidth: 140, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row[getWhMatDynamicFieldKey(field.fields)] || '--' |
| | | })) |
| | | : [] |
| | | |
| | | return [ |
| | | { |
| | | type: 'selection', |
| | | width: 48, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | type: 'globalIndex', |
| | | label: t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'id', |
| | | label: t('table.id'), |
| | | width: 90, |
| | | align: 'center', |
| | | formatter: (row) => row.id ?? '--' |
| | | }, |
| | | { |
| | | prop: 'code', |
| | | label: t('pages.basicInfo.whMat.table.code'), |
| | |
| | | { |
| | | prop: 'groupName', |
| | | label: t('pages.basicInfo.whMat.table.groupName'), |
| | | minWidth: 160, |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | |
| | | { |
| | | prop: 'spec', |
| | | label: t('pages.basicInfo.whMat.table.spec'), |
| | | minWidth: 150, |
| | | minWidth: 160, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'model', |
| | | label: t('pages.basicInfo.whMat.table.model'), |
| | | minWidth: 150, |
| | | minWidth: 160, |
| | | showOverflowTooltip: true |
| | | }, |
| | | ...dynamicColumns, |
| | | { |
| | | prop: 'unit', |
| | | label: t('table.unit'), |
| | |
| | | width: 100, |
| | | align: 'center', |
| | | formatter: (row) => |
| | | h(ElTag, { type: row.statusType || 'info', effect: 'light' }, () => row.statusText || t('common.placeholder.empty')) |
| | | h( |
| | | ElTag, |
| | | { type: row.statusType || 'info', effect: 'light' }, |
| | | () => row.statusText || t('common.placeholder.empty') |
| | | ) |
| | | }, |
| | | { |
| | | prop: 'updateByText', |
| | | label: t('table.updateBy'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'updateTimeText', |
| | |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'action', |
| | | prop: 'createByText', |
| | | label: t('table.createBy'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'createTimeText', |
| | | label: t('table.createTime'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'memo', |
| | | label: t('table.memo'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'operation', |
| | | label: t('table.operation'), |
| | | width: 100, |
| | | fixed: 'right', |
| | | width: 120, |
| | | align: 'center', |
| | | useSlot: true |
| | | fixed: 'right', |
| | | formatter: (row) => |
| | | h( |
| | | 'div', |
| | | { class: 'flex justify-center' }, |
| | | h(ArtButtonMore, { |
| | | list: operations, |
| | | onClick: (item) => { |
| | | if (item.key === 'view') handleViewDetail?.(row) |
| | | if (item.key === 'edit') handleEdit?.(row) |
| | | if (item.key === 'print') handlePrint?.(row) |
| | | if (item.key === 'delete') handleDelete?.(row) |
| | | } |
| | | }) |
| | | ) |
| | | } |
| | | ] |
| | | } |