| | |
| | | <template> |
| | | <ElSpace v-bind="attrs" wrap> |
| | | <ElButton :disabled="disabled" @click="handleExport">导出</ElButton> |
| | | <ElButton :disabled="disabled" @click="handlePrint">打印</ElButton> |
| | | <ElButton :disabled="disabled" @click="handleExport">{{ t('common.actions.export') }}</ElButton> |
| | | <ElButton :disabled="disabled" @click="handlePrint">{{ t('common.actions.print') }}</ElButton> |
| | | </ElSpace> |
| | | |
| | | <ListPrintPreviewDialog |
| | |
| | | |
| | | <script setup> |
| | | import { computed, useAttrs } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import ListPrintPreviewDialog from './list-print-preview-dialog.vue' |
| | | import { |
| | | buildListExportPayload, |
| | |
| | | }) |
| | | |
| | | const attrs = useAttrs() |
| | | const { t } = useI18n() |
| | | |
| | | const props = defineProps({ |
| | | reportTitle: { type: String, default: '报表' }, |
| | | reportTitle: { type: String, default: '' }, |
| | | selectedRows: { type: Array, default: () => [] }, |
| | | queryParams: { type: Object, default: () => ({}) }, |
| | | columns: { type: Array, default: () => [] }, |
| | |
| | | import { $t } from '@/locales' |
| | | |
| | | const DEFAULT_MAX_RESULTS = 1000 |
| | | const DEFAULT_PRINT_PAGE_SIZE = 20 |
| | | const HIDDEN_EXPORT_COLUMNS = new Set(['selection', 'operation']) |
| | |
| | | } |
| | | |
| | | return [ |
| | | { source: '__sequence__', label: '序号', align: 'center' }, |
| | | { source: '__sequence__', label: $t('table.index'), align: 'center' }, |
| | | ...normalizedColumns |
| | | ] |
| | | } |
| | |
| | | import { $t } from '@/locales' |
| | | |
| | | function escapeHtml(value) { |
| | | return String(value ?? '') |
| | | .replaceAll('&', '&') |
| | |
| | | |
| | | function getMetaItems(meta = {}) { |
| | | return [ |
| | | { key: 'reportDate', label: '报表日期', value: meta.reportDate ?? '--' }, |
| | | { key: 'operator', label: '打印人', value: meta.operator ?? '--' }, |
| | | { key: 'printedAt', label: '打印时间', value: meta.printedAt ?? '--' }, |
| | | { key: 'count', label: '记录数', value: meta.count ?? '--' } |
| | | { key: 'reportDate', label: $t('print.reportDate'), value: meta.reportDate ?? '--' }, |
| | | { key: 'operator', label: $t('print.operator'), value: meta.operator ?? '--' }, |
| | | { key: 'printedAt', label: $t('print.printedAt'), value: meta.printedAt ?? '--' }, |
| | | { key: 'count', label: $t('print.count'), value: meta.count ?? '--' } |
| | | ] |
| | | } |
| | | |
| | |
| | | return alignMap[column.align] ?? alignMap.left |
| | | } |
| | | |
| | | export function buildPrintDocumentHtml({ title = '报表', meta = {}, rows = [], columns = [] } = {}) { |
| | | export function buildPrintDocumentHtml({ title = '', meta = {}, rows = [], columns = [] } = {}) { |
| | | const reportStyle = getReportStyle(meta) |
| | | const reportTitle = meta.reportTitle || title |
| | | const reportTitle = meta.reportTitle || title || $t('print.defaultReportTitle') |
| | | const titleClass = `${getTitleAlignClass(reportStyle.titleAlign)} ${getTitleLevelClass(reportStyle.titleLevel)}` |
| | | const orientation = getPageOrientation(reportStyle) |
| | | const showBorder = reportStyle.showBorder !== false |
| | |
| | | return `<tr>${cells}</tr>` |
| | | }) |
| | | .join('') |
| | | : `<tr><td colspan="${Math.max(columns.length, 1)}" class="empty-cell">暂无打印数据</td></tr>` |
| | | : `<tr><td colspan="${Math.max(columns.length, 1)}" class="empty-cell">${escapeHtml($t('print.noData'))}</td></tr>` |
| | | |
| | | const metaHtml = metaItems |
| | | .map( |
| | |
| | | > |
| | | <div class="flex flex-wrap items-center justify-end gap-2 pb-2"> |
| | | <ElRadioGroup v-model="currentShowBorder" size="small"> |
| | | <ElRadioButton :label="true">边框开</ElRadioButton> |
| | | <ElRadioButton :label="false">边框关</ElRadioButton> |
| | | <ElRadioButton :label="true">{{ t('print.borderOn') }}</ElRadioButton> |
| | | <ElRadioButton :label="false">{{ t('print.borderOff') }}</ElRadioButton> |
| | | </ElRadioGroup> |
| | | |
| | | <ElRadioGroup v-model="currentOrientation" size="small"> |
| | | <ElRadioButton label="portrait">竖版</ElRadioButton> |
| | | <ElRadioButton label="landscape">横版</ElRadioButton> |
| | | <ElRadioButton label="portrait">{{ t('print.portrait') }}</ElRadioButton> |
| | | <ElRadioButton label="landscape">{{ t('print.landscape') }}</ElRadioButton> |
| | | </ElRadioGroup> |
| | | </div> |
| | | |
| | |
| | | v-if="hiddenRowCount > 0" |
| | | class="mt-3 rounded-md border border-amber-200 bg-amber-50 px-2.5 py-1.5 text-[11px] leading-tight text-amber-700" |
| | | > |
| | | 预览仅展示前 {{ previewRows.length }} 条,点击打印将输出全部 {{ rows.length }} 条数据。 |
| | | {{ t('print.previewLimited', { previewCount: previewRows.length, totalCount: rows.length }) }} |
| | | </div> |
| | | |
| | | <div :class="tableWrapClass" class="mt-4 min-h-0 flex-1 overflow-auto"> |
| | |
| | | :colspan="Math.max(columns.length, 1)" |
| | | :class="emptyCellClass" |
| | | > |
| | | 暂无打印数据 |
| | | {{ t('print.noData') }} |
| | | </td> |
| | | </tr> |
| | | <tr v-for="(row, index) in previewRows" :key="row?.id ?? index"> |
| | |
| | | |
| | | <template #footer> |
| | | <div class="flex items-center justify-end gap-2 print:hidden"> |
| | | <ElButton @click="visible = false">关闭</ElButton> |
| | | <ElButton type="primary" @click="handlePrint">打印</ElButton> |
| | | <ElButton @click="visible = false">{{ t('common.actions.close') }}</ElButton> |
| | | <ElButton type="primary" @click="handlePrint">{{ t('common.actions.print') }}</ElButton> |
| | | </div> |
| | | </template> |
| | | </ElDialog> |
| | |
| | | |
| | | <script setup> |
| | | import { computed, ref, watch } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { printReportDocument } from './list-print-document.js' |
| | | |
| | | defineOptions({ name: 'ListPrintPreviewDialog' }) |
| | |
| | | const visible = defineModel('visible', { type: Boolean, default: false }) |
| | | |
| | | const props = defineProps({ |
| | | title: { type: String, default: '打印预览' }, |
| | | title: { type: String, default: '' }, |
| | | meta: { type: Object, default: () => ({}) }, |
| | | rows: { type: Array, default: () => [] }, |
| | | columns: { type: Array, default: () => [] }, |
| | | maxPreviewRows: { type: Number, default: 50 } |
| | | }) |
| | | const { t } = useI18n() |
| | | |
| | | const meta = computed(() => (props.meta && typeof props.meta === 'object' ? props.meta : {})) |
| | | const reportStyleSource = computed(() => |
| | |
| | | |
| | | const metaItems = computed(() => { |
| | | return [ |
| | | { key: 'reportDate', label: '报表日期', value: meta.value.reportDate }, |
| | | { key: 'operator', label: '打印人', value: meta.value.operator }, |
| | | { key: 'printedAt', label: '打印时间', value: meta.value.printedAt }, |
| | | { key: 'count', label: '记录数', value: meta.value.count } |
| | | { key: 'reportDate', label: t('print.reportDate'), value: meta.value.reportDate }, |
| | | { key: 'operator', label: t('print.operator'), value: meta.value.operator }, |
| | | { key: 'printedAt', label: t('print.printedAt'), value: meta.value.printedAt }, |
| | | { key: 'count', label: t('print.count'), value: meta.value.count } |
| | | ] |
| | | }) |
| | | const previewRows = computed(() => props.rows.slice(0, props.maxPreviewRows)) |
| | |
| | | <!-- 导出 Excel 文件 --> |
| | | <template> |
| | | <ElButton |
| | | :type="type" |
| | |
| | | <ElIcon class="is-loading"> |
| | | <Loading /> |
| | | </ElIcon> |
| | | {{ loadingText }} |
| | | {{ resolvedLoadingText }} |
| | | </template> |
| | | <slot>{{ buttonText }}</slot> |
| | | <slot>{{ resolvedButtonText }}</slot> |
| | | </ElButton> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import * as XLSX from 'xlsx' |
| | | import FileSaver from 'file-saver' |
| | | import { ref, computed, nextTick } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { ref, computed, nextTick, readonly } from 'vue' |
| | | import { Loading } from '@element-plus/icons-vue' |
| | | import { useThrottleFn } from '@vueuse/core' |
| | | import { useI18n } from 'vue-i18n' |
| | | defineOptions({ name: 'ArtExcelExport' }) |
| | | const { t } = useI18n() |
| | | const props = defineProps({ |
| | | filename: { |
| | | required: false, |
| | |
| | | type: { required: false, default: 'primary' }, |
| | | size: { required: false, default: 'default' }, |
| | | disabled: { required: false, default: false }, |
| | | buttonText: { required: false, default: '导出 Excel' }, |
| | | loadingText: { required: false, default: '导出中...' }, |
| | | buttonText: { required: false, default: '' }, |
| | | loadingText: { required: false, default: '' }, |
| | | autoIndex: { required: false, default: false }, |
| | | indexColumnTitle: { required: false, default: '序号' }, |
| | | indexColumnTitle: { required: false, default: '' }, |
| | | columns: { required: false, default: () => ({}) }, |
| | | headers: { required: false, default: () => ({}) }, |
| | | maxRows: { required: false, default: 1e5 }, |
| | |
| | | } |
| | | const isExporting = ref(false) |
| | | const hasData = computed(() => Array.isArray(props.data) && props.data.length > 0) |
| | | const resolvedButtonText = computed(() => props.buttonText || t('common.actions.export')) |
| | | const resolvedLoadingText = computed(() => props.loadingText || t('common.actions.exporting')) |
| | | const resolvedIndexColumnTitle = computed(() => props.indexColumnTitle || t('table.index')) |
| | | const validateData = (data) => { |
| | | if (!Array.isArray(data)) { |
| | | throw new ExportError('数据必须是数组格式', 'INVALID_DATA_TYPE') |
| | | throw new ExportError(t('message.exportInvalidDataType'), 'INVALID_DATA_TYPE') |
| | | } |
| | | if (data.length === 0) { |
| | | throw new ExportError('没有可导出的数据', 'NO_DATA') |
| | | throw new ExportError(t('message.exportNoData'), 'NO_DATA') |
| | | } |
| | | if (data.length > props.maxRows) { |
| | | throw new ExportError(`数据行数超过限制(${props.maxRows}行)`, 'EXCEED_MAX_ROWS', { |
| | | throw new ExportError(t('message.exportExceedMaxRows', { maxRows: props.maxRows }), 'EXCEED_MAX_ROWS', { |
| | | currentRows: data.length, |
| | | maxRows: props.maxRows |
| | | }) |
| | |
| | | return value.toLocaleDateString('zh-CN') |
| | | } |
| | | if (typeof value === 'boolean') { |
| | | return value ? '是' : '否' |
| | | return value ? t('common.status.yes') : t('common.status.no') |
| | | } |
| | | return String(value) |
| | | } |
| | |
| | | const processedData = data.map((item, index) => { |
| | | const processedItem = {} |
| | | if (props.autoIndex) { |
| | | processedItem[props.indexColumnTitle] = String(index + 1) |
| | | processedItem[resolvedIndexColumnTitle.value] = String(index + 1) |
| | | } |
| | | Object.entries(item).forEach(([key, value]) => { |
| | | let columnTitle = key |
| | |
| | | if (props.workbookOptions) { |
| | | workbook.Props = { |
| | | Title: filename, |
| | | Subject: '数据导出', |
| | | Subject: t('message.exportWorkbookSubject'), |
| | | Author: props.workbookOptions.creator || 'Art Design Pro', |
| | | Manager: props.workbookOptions.lastModifiedBy || '', |
| | | Company: '系统导出', |
| | | Category: '数据', |
| | | Keywords: 'excel,export,data', |
| | | Comments: '由系统自动生成', |
| | | Company: t('message.exportWorkbookCompany'), |
| | | Category: t('message.exportWorkbookCategory'), |
| | | Keywords: t('message.exportWorkbookKeywords'), |
| | | Comments: t('message.exportWorkbookComments'), |
| | | CreatedDate: props.workbookOptions.created || /* @__PURE__ */ new Date(), |
| | | ModifiedDate: props.workbookOptions.modified || /* @__PURE__ */ new Date() |
| | | } |
| | |
| | | await nextTick() |
| | | return Promise.resolve() |
| | | } catch (error) { |
| | | throw new ExportError(`Excel 导出失败: ${error.message}`, 'EXPORT_FAILED', error) |
| | | throw new ExportError( |
| | | t('message.exportExcelFailed', { message: error.message }), |
| | | 'EXPORT_FAILED', |
| | | error |
| | | ) |
| | | } |
| | | } |
| | | const handleExport = useThrottleFn(async () => { |
| | |
| | | emit('export-success', props.filename, props.data.length) |
| | | if (props.showSuccessMessage) { |
| | | ElMessage.success({ |
| | | message: `成功导出 ${props.data.length} 条数据`, |
| | | message: t('message.exportSuccessWithCount', { count: props.data.length }), |
| | | duration: 3e3 |
| | | }) |
| | | } |
| | |
| | | const exportError = |
| | | error instanceof ExportError |
| | | ? error |
| | | : new ExportError(`导出失败: ${error.message}`, 'UNKNOWN_ERROR', error) |
| | | : new ExportError( |
| | | t('message.exportFailedUnknown', { message: error.message }), |
| | | 'UNKNOWN_ERROR', |
| | | error |
| | | ) |
| | | emit('export-error', exportError) |
| | | if (props.showErrorMessage) { |
| | | ElMessage.error({ |
| | |
| | | await router.push(item.path) |
| | | } |
| | | } catch (error) { |
| | | console.error('导航失败:', error) |
| | | console.error('Breadcrumb navigation failed:', error) |
| | | } |
| | | } |
| | | </script> |
| | |
| | | <div class="min-w-0 flex-1"> |
| | | <div class="flex flex-wrap items-center gap-2"> |
| | | <h3 class="text-base font-semibold text-[var(--art-gray-900)]">{{ $t('ai.drawer.title') }}</h3> |
| | | <ElTag v-if="streaming" type="success" effect="light" round>Streaming</ElTag> |
| | | <ElTag v-if="streaming" type="success" effect="light" round>{{ $t('ai.drawer.streaming') }}</ElTag> |
| | | </div> |
| | | <p class="mt-1 truncate text-xs text-[var(--art-gray-500)]"> |
| | | {{ runtime?.promptName || runtime?.promptCode || DEFAULT_PROMPT_CODE }} |
| | |
| | | |
| | | <div class="mt-3 flex flex-wrap items-center justify-between gap-3"> |
| | | <div class="text-xs text-[var(--art-gray-500)]"> |
| | | Enter 发送,Shift + Enter 换行 |
| | | {{ $t('ai.drawer.inputHotkeyHint') }} |
| | | </div> |
| | | |
| | | <div class="flex flex-wrap items-center gap-2"> |
| | |
| | | <ElTooltip |
| | | class="box-item" |
| | | effect="dark" |
| | | :content="$t(menu.meta.title)" |
| | | :content="formatMenuTitle(menu.meta.title)" |
| | | placement="right" |
| | | :offset="15" |
| | | :hide-after="0" |
| | |
| | | }" |
| | | /> |
| | | <span v-if="dualMenuShowText" class="text-md text-g-700"> |
| | | {{ $t(menu.meta.title) }} |
| | | {{ formatMenuTitle(menu.meta.title) }} |
| | | </span> |
| | | <div v-if="menu.meta.showBadge" class="art-badge art-badge-dual" /> |
| | | </div> |
| | |
| | | <script setup> |
| | | import AppConfig from '@/config' |
| | | import { handleMenuJump } from '@/utils/navigation' |
| | | import { formatMenuTitle } from '@/utils/router' |
| | | |
| | | import SidebarSubmenu from './widget/SidebarSubmenu.vue' |
| | | |
| | |
| | | class="text-base mr-1 group-hover:text-theme" |
| | | :class="item.path === activeTab ? 'text-theme' : 'text-g-600'" |
| | | /> |
| | | {{ item.customTitle || formatMenuTitle(item.title) }} |
| | | {{ formatMenuTitle(item.customTitle || item.title) }} |
| | | <span |
| | | v-if="list.length > 1 && !item.fixedTab" |
| | | class="inline-flex flex-cc relative ml-0.5 p-1 rounded-full tad-200 hover:bg-g-200" |
| | |
| | | |
| | | <template #empty> |
| | | <div v-if="loading"></div> |
| | | <ElEmpty v-else :description="emptyText" :image-size="120" /> |
| | | <ElEmpty v-else :description="resolvedEmptyText" :image-size="120" /> |
| | | </template> |
| | | </ElTable> |
| | | |
| | |
| | | |
| | | <script setup> |
| | | import { ref, computed, nextTick, watchEffect, getCurrentInstance, useAttrs } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { storeToRefs } from 'pinia' |
| | | import { useTableStore } from '@/store/modules/table' |
| | | import { useCommon } from '@/hooks/core/useCommon' |
| | |
| | | const elTableRef = ref(null) |
| | | const paginationRef = ref() |
| | | const tableHeaderRef = ref() |
| | | const { t } = useI18n() |
| | | const tableStore = useTableStore() |
| | | const { isBorder, isZebra, tableSize, isFullScreen, isHeaderBackground } = storeToRefs(tableStore) |
| | | const props = defineProps({ |
| | |
| | | border: { required: false, default: void 0 }, |
| | | size: { required: false, default: void 0 }, |
| | | emptyHeight: { required: false, default: '100%' }, |
| | | emptyText: { required: false, default: '暂无数据' }, |
| | | emptyText: { required: false, default: '' }, |
| | | showTableHeader: { required: false, default: true } |
| | | }) |
| | | const instance = getCurrentInstance() |
| | |
| | | : void 0 |
| | | })) |
| | | const showPagination = computed(() => props.pagination && !isEmpty.value) |
| | | const resolvedEmptyText = computed(() => props.emptyText || t('table.emptyText')) |
| | | const shouldRenderSlotScope = (slotScope) => { |
| | | return slotScope.$index === void 0 || slotScope.$index >= 0 |
| | | } |
| | |
| | | "tips": "Prompt", |
| | | "cancel": "Cancel", |
| | | "confirm": "Confirm", |
| | | "logOutTips": "Do you want to log out?" |
| | | "logOutTips": "Do you want to log out?", |
| | | "count": "{count} items", |
| | | "listSeparator": ", ", |
| | | "actions": { |
| | | "search": "Search", |
| | | "reset": "Reset", |
| | | "refresh": "Refresh", |
| | | "add": "Add", |
| | | "batchDelete": "Batch Delete", |
| | | "edit": "Edit", |
| | | "delete": "Delete", |
| | | "detail": "Detail", |
| | | "items": "Items", |
| | | "print": "Print", |
| | | "export": "Export", |
| | | "exporting": "Exporting...", |
| | | "close": "Close", |
| | | "complete": "Complete", |
| | | "expand": "Expand", |
| | | "collapse": "Collapse", |
| | | "viewAll": "View All", |
| | | "save": "Save", |
| | | "submit": "Submit" |
| | | }, |
| | | "status": { |
| | | "enabled": "Enabled", |
| | | "disabled": "Disabled", |
| | | "normal": "Normal", |
| | | "frozen": "Frozen", |
| | | "unknown": "Unknown", |
| | | "yes": "Yes", |
| | | "no": "No" |
| | | }, |
| | | "placeholder": { |
| | | "empty": "--" |
| | | } |
| | | }, |
| | | "crud": { |
| | | "messages": { |
| | | "createSuccess": "Created successfully", |
| | | "updateSuccess": "Updated successfully", |
| | | "deleteSuccess": "Deleted successfully", |
| | | "batchDeleteSuccess": "Batch deleted successfully", |
| | | "submitFailed": "Submit failed", |
| | | "deleteFailed": "Delete failed", |
| | | "batchDeleteFailed": "Batch delete failed", |
| | | "exportSuccess": "Export succeeded", |
| | | "exportFailed": "Export failed", |
| | | "exportFailedWithStatus": "Export failed ({status})", |
| | | "printFailed": "Print failed", |
| | | "loadFailed": "Load failed" |
| | | }, |
| | | "confirm": { |
| | | "deleteTitle": "Delete confirmation", |
| | | "deleteMessage": "Are you sure you want to delete {entity} \"{label}\"?", |
| | | "batchDeleteTitle": "Batch delete confirmation", |
| | | "batchDeleteMessage": "Are you sure you want to delete {count} selected {entity}?" |
| | | } |
| | | }, |
| | | "print": { |
| | | "previewTitle": "Print Preview", |
| | | "defaultReportTitle": "Report", |
| | | "borderOn": "Border On", |
| | | "borderOff": "Border Off", |
| | | "portrait": "Portrait", |
| | | "landscape": "Landscape", |
| | | "reportDate": "Report Date", |
| | | "operator": "Operator", |
| | | "printedAt": "Printed At", |
| | | "count": "Records", |
| | | "previewLimited": "Preview shows the first {previewCount} records only. Printing will output all {totalCount} records.", |
| | | "noData": "No printable data" |
| | | }, |
| | | "table": { |
| | | "index": "No.", |
| | | "unit": "Unit", |
| | | "id": "ID", |
| | | "wcs": "WCS", |
| | | "source": "Source", |
| | | "supplier": "Supplier", |
| | | "supplierBatch": "Supplier Batch" |
| | | }, |
| | | "search": { |
| | | "placeholder": "Search page", |
| | |
| | | "assistantRole": "AI", |
| | | "thinking": "Thinking...", |
| | | "inputPlaceholder": "Type your question. Press Enter to send, Shift + Enter for a new line", |
| | | "inputHotkeyHint": "Enter to send, Shift + Enter for a new line", |
| | | "clearInput": "Clear Input", |
| | | "stop": "Stop", |
| | | "send": "Send", |
| | |
| | | "recentMetric": "Recent: {value}", |
| | | "elapsedMetric": "Elapsed: {value} ms", |
| | | "firstTokenMetric": "First token: {value} ms", |
| | | "tokenMetric": "Tokens: prompt {prompt} / completion {completion} / total {total}" |
| | | "tokenMetric": "Tokens: prompt {prompt} / completion {completion} / total {total}", |
| | | "streaming": "Streaming" |
| | | } |
| | | }, |
| | | "table": { |
| | |
| | | "expand": "Expand", |
| | | "index": "Index" |
| | | }, |
| | | "index": "Index", |
| | | "id": "ID", |
| | | "operation": "Operation", |
| | | "status": "Status", |
| | | "type": "Type", |
| | | "source": "Source", |
| | | "supplier": "Supplier", |
| | | "supplierBatch": "Supplier Batch", |
| | | "remark": "Remark", |
| | | "updateBy": "Updated By", |
| | | "updateTime": "Updated At", |
| | | "createTime": "Created At", |
| | | "unit": "Unit", |
| | | "batch": "Batch", |
| | | "quantity": "Quantity", |
| | | "materialCode": "Material Code", |
| | | "materialName": "Material Name", |
| | | "wcs": "WCS", |
| | | "menuType": "Menu Type", |
| | | "iconPreview": "Icon Preview", |
| | | "componentKey": "Component Key", |
| | | "permissionKey": "Permission Key", |
| | | "sort": "Sort", |
| | | "zebra": "Zebra", |
| | | "border": "Border", |
| | | "headerBackground": "Header BG" |
| | | "headerBackground": "Header BG", |
| | | "topLevelMenu": "Top Level Menu", |
| | | "emptyText": "No data" |
| | | }, |
| | | "message": { |
| | | "requestTimeoutStopped": "Request timed out and waiting has stopped", |
| | | "exportTimeoutStopped": "Export request timed out and waiting has stopped", |
| | | "printTimeoutStopped": "Print data loading timed out and waiting has stopped", |
| | | "exportInvalidDataType": "Data must be an array", |
| | | "exportNoData": "No data available for export", |
| | | "exportExceedMaxRows": "Row count exceeds the limit ({maxRows} rows)", |
| | | "exportExcelFailed": "Excel export failed: {message}", |
| | | "exportSuccessWithCount": "Successfully exported {count} records", |
| | | "exportFailedUnknown": "Export failed: {message}", |
| | | "exportWorkbookSubject": "Data Export", |
| | | "exportWorkbookCompany": "System Export", |
| | | "exportWorkbookCategory": "Data", |
| | | "exportWorkbookKeywords": "excel,export,data", |
| | | "exportWorkbookComments": "Generated automatically by the system" |
| | | }, |
| | | "pages": { |
| | | "system": { |
| | | "role": { |
| | | "entity": "Role", |
| | | "reportTitle": "Role Report", |
| | | "buttons": { |
| | | "add": "Add Role" |
| | | }, |
| | | "search": { |
| | | "name": "Role Name", |
| | | "namePlaceholder": "Enter role name", |
| | | "code": "Role Code", |
| | | "codePlaceholder": "Enter role code", |
| | | "memo": "Remark", |
| | | "memoPlaceholder": "Enter remark", |
| | | "condition": "Keyword", |
| | | "conditionPlaceholder": "Search by keyword", |
| | | "status": "Status", |
| | | "statusPlaceholder": "Select status" |
| | | }, |
| | | "table": { |
| | | "name": "Role Name", |
| | | "code": "Role Code", |
| | | "memo": "Remark", |
| | | "status": "Status", |
| | | "updateTime": "Updated At", |
| | | "createTime": "Created At", |
| | | "operation": "Operation" |
| | | }, |
| | | "actions": { |
| | | "scopeMenu": "Web Permissions", |
| | | "scopePda": "PDA Permissions", |
| | | "scopeMatnr": "Material Permissions", |
| | | "scopeWarehouse": "Warehouse Permissions", |
| | | "edit": "Edit Role", |
| | | "delete": "Delete Role" |
| | | }, |
| | | "scopes": { |
| | | "menu": "Web Permissions", |
| | | "pda": "PDA Permissions", |
| | | "matnr": "Material Permissions", |
| | | "warehouse": "Warehouse Permissions" |
| | | }, |
| | | "dialog": { |
| | | "addTitle": "Add Role", |
| | | "editTitle": "Edit Role", |
| | | "validationName": "Please enter the role name", |
| | | "name": "Role Name", |
| | | "namePlaceholder": "Enter role name", |
| | | "code": "Role Code", |
| | | "codePlaceholder": "Enter role code", |
| | | "status": "Status", |
| | | "statusPlaceholder": "Select status", |
| | | "memo": "Remark", |
| | | "memoPlaceholder": "Enter remark" |
| | | }, |
| | | "permission": { |
| | | "title": "Role Permissions", |
| | | "currentRole": "Current Role: ", |
| | | "unselected": "No role selected", |
| | | "selectAll": "Select All", |
| | | "clear": "Clear", |
| | | "saveCurrent": "Save Current Permissions", |
| | | "searchPlaceholder": "Search permission tree", |
| | | "authButton": "Button", |
| | | "scopeLoadTimeout": "{title} loading timed out and waiting has stopped", |
| | | "scopeLoadFailed": "Failed to load {title}", |
| | | "saveSuccess": "Permissions saved successfully", |
| | | "saveFailed": "Failed to save permissions" |
| | | } |
| | | }, |
| | | "menu": { |
| | | "title": "Menu Management", |
| | | "addMenu": "Add Menu", |
| | | "menuName": "Menu Name", |
| | | "route": "Route Path", |
| | | "iconPreview": "Icon Preview", |
| | | "menuType": "Menu Type", |
| | | "componentKey": "Component Key", |
| | | "authority": "Authority", |
| | | "sort": "Sort", |
| | | "status": "Status", |
| | | "memo": "Remark", |
| | | "operation": "Operation", |
| | | "types": { |
| | | "button": "Button", |
| | | "directory": "Directory", |
| | | "menu": "Menu" |
| | | }, |
| | | "addPermission": "Add Permission", |
| | | "deleteMenuMessage": "Are you sure you want to delete menu \"{label}\"? This action cannot be undone.", |
| | | "deleteAuthMessage": "Are you sure you want to delete permission \"{label}\"? This action cannot be undone.", |
| | | "selfParentError": "The parent menu cannot be the current menu" |
| | | } |
| | | }, |
| | | "orders": { |
| | | "asnOrder": { |
| | | "reportTitle": "ASN Report", |
| | | "entity": "ASN", |
| | | "buttons": { |
| | | "createByPo": "Create by PO" |
| | | }, |
| | | "search": { |
| | | "condition": "Keyword", |
| | | "conditionPlaceholder": "Enter ASN No./PO No./Supplier", |
| | | "code": "ASN No.", |
| | | "codePlaceholder": "Enter ASN No.", |
| | | "poCode": "PO No.", |
| | | "poCodePlaceholder": "Enter PO No.", |
| | | "wkType": "Business Type", |
| | | "wkTypePlaceholder": "Enter business type", |
| | | "exceStatus": "Document Status", |
| | | "supplierName": "Supplier", |
| | | "supplierPlaceholder": "Enter supplier", |
| | | "purchaseUserName": "Purchaser", |
| | | "purchaseUserPlaceholder": "Enter purchaser" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "Enter ASN No./PO No./Supplier", |
| | | "code": "Enter ASN No.", |
| | | "poCode": "Enter PO No.", |
| | | "wkType": "Enter business type", |
| | | "supplierName": "Enter supplier", |
| | | "purchaseUserName": "Enter purchaser" |
| | | }, |
| | | "status": { |
| | | "pending": "Pending", |
| | | "running": "In Progress", |
| | | "receiving": "Received", |
| | | "taskRunning": "Task Running", |
| | | "completed": "Completed", |
| | | "cancelled": "Cancelled", |
| | | "closed": "Closed" |
| | | }, |
| | | "actions": { |
| | | "view": "View Detail", |
| | | "items": "Receiving Items", |
| | | "print": "Print", |
| | | "complete": "Complete" |
| | | }, |
| | | "detail": { |
| | | "title": "ASN Detail", |
| | | "baseInfo": "Basic Information", |
| | | "items": "Order Items", |
| | | "asnCode": "ASN No.", |
| | | "poCode": "PO No.", |
| | | "wkType": "Business Type", |
| | | "orderType": "Order Type", |
| | | "status": "Document Status", |
| | | "purchaseOrg": "Purchasing Org", |
| | | "purchaseUser": "Purchaser", |
| | | "supplier": "Supplier", |
| | | "anfme": "Expected Qty", |
| | | "qty": "Received Qty", |
| | | "updateTime": "Updated At", |
| | | "createTime": "Created At", |
| | | "memo": "Remark", |
| | | "count": "{count} items", |
| | | "completeTitle": "Complete Confirmation", |
| | | "completeConfirm": "Are you sure you want to complete ASN {code}?", |
| | | "completeSuccess": "ASN completed", |
| | | "actionFailed": "ASN action failed", |
| | | "detailTimeout": "ASN detail items timed out and waiting has stopped", |
| | | "itemsTimeout": "ASN detail items timed out and waiting has stopped" |
| | | }, |
| | | "createByPoDialog": { |
| | | "title": "Create by PO", |
| | | "purchaseList": "Available PO List", |
| | | "purchasePreview": "PO Item Preview", |
| | | "purchaseSelected": "Selected: {code}", |
| | | "purchaseEmpty": "Select a PO from the left first", |
| | | "purchaseGenerateHint": "Generate ASN from {count} items of PO {code}", |
| | | "purchaseGenerateEmpty": "Please select an available PO", |
| | | "generate": "Generate ASN", |
| | | "refreshItems": "Refresh Items", |
| | | "messages": { |
| | | "purchaseItemsTimeout": "PO items timed out and waiting has stopped", |
| | | "purchaseItemsAllTimeout": "Full PO items timed out and waiting has stopped", |
| | | "purchaseRequired": "Please select a PO first", |
| | | "purchaseItemsEmpty": "The selected PO has no buildable items", |
| | | "createByPoSuccess": "ASN created from PO successfully", |
| | | "createByPoFailed": "Create ASN by PO failed" |
| | | }, |
| | | "search": { |
| | | "condition": "Keyword", |
| | | "conditionPlaceholder": "Enter PO No./source/supplier", |
| | | "code": "PO No.", |
| | | "codePlaceholder": "Enter PO No.", |
| | | "source": "Source", |
| | | "sourcePlaceholder": "Enter source", |
| | | "supplierName": "Supplier", |
| | | "supplierNamePlaceholder": "Enter supplier" |
| | | } |
| | | }, |
| | | "table": { |
| | | "poItemId": "PO Line No.", |
| | | "expectedQty": "Expected Qty", |
| | | "receivedQty": "Received Qty", |
| | | "remainingQty": "Creatable Qty", |
| | | "poStatus": "PO Status", |
| | | "purchaseQty": "Purchase Qty", |
| | | "generatedQty": "Generated ASN Qty", |
| | | "receivedQtyTotal": "Received Qty" |
| | | } |
| | | }, |
| | | "delivery": { |
| | | "reportTitle": "DO Report", |
| | | "detailReportTitle": "DO Item Report", |
| | | "entity": "DO", |
| | | "search": { |
| | | "condition": "Keyword", |
| | | "conditionPlaceholder": "Enter No./ERP master order/platform order", |
| | | "code": "No.", |
| | | "codePlaceholder": "Enter No.", |
| | | "platId": "ERP Master Order ID", |
| | | "platIdPlaceholder": "Enter ERP master order ID", |
| | | "type": "Order Type", |
| | | "typePlaceholder": "Enter order type", |
| | | "wkType": "Business Type", |
| | | "wkTypePlaceholder": "Enter business type", |
| | | "source": "Order Source", |
| | | "sourcePlaceholder": "Enter order source", |
| | | "exceStatus": "Execution Status", |
| | | "exceStatusPlaceholder": "Enter execution status", |
| | | "memo": "Remark", |
| | | "memoPlaceholder": "Enter remark" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "Enter No./ERP master order/platform order", |
| | | "code": "Enter No.", |
| | | "platId": "Enter ERP master order ID", |
| | | "type": "Enter order type", |
| | | "wkType": "Enter business type", |
| | | "source": "Enter order source", |
| | | "exceStatus": "Enter execution status", |
| | | "memo": "Enter remark" |
| | | }, |
| | | "status": { |
| | | "normal": "Normal", |
| | | "disabled": "Disabled", |
| | | "pending": "Pending", |
| | | "running": "Running", |
| | | "partial": "Partially Completed", |
| | | "completed": "Completed" |
| | | }, |
| | | "actions": { |
| | | "view": "View Detail", |
| | | "items": "Items", |
| | | "delete": "Delete" |
| | | }, |
| | | "detail": { |
| | | "title": "Handover Order Detail", |
| | | "baseInfo": "Basic Information", |
| | | "auditInfo": "Audit Information", |
| | | "items": "Handover Order Items", |
| | | "code": "Handover No.", |
| | | "platId": "ERP Master Order ID", |
| | | "platCode": "Platform Order No.", |
| | | "type": "Order Type", |
| | | "wkType": "Business Type", |
| | | "source": "Order Source", |
| | | "anfme": "Expected Qty", |
| | | "qty": "Received Qty", |
| | | "workQty": "In-progress Qty", |
| | | "status": "Status", |
| | | "exceStatus": "Execution Status", |
| | | "memo": "Remark", |
| | | "startTime": "Planned Outbound Time", |
| | | "endTime": "Planned Outbound End Time", |
| | | "createBy": "Created By", |
| | | "createTime": "Created At", |
| | | "updateBy": "Updated By", |
| | | "updateTime": "Updated At", |
| | | "count": "{count} items" |
| | | }, |
| | | "table": { |
| | | "deliveryCode": "Handover No.", |
| | | "platCode": "Platform Order No.", |
| | | "platItemId": "Platform Line No.", |
| | | "matnrCode": "Material Code", |
| | | "maktx": "Material Name", |
| | | "fieldsIndex": "Dynamic Field Index", |
| | | "anfme": "Qty", |
| | | "workQty": "Working Qty", |
| | | "qty": "Outbound Qty", |
| | | "startTime": "Planned Outbound Time", |
| | | "endTime": "Planned Outbound End Time", |
| | | "nromQty": "Std. Pack", |
| | | "printQty": "Print Qty", |
| | | "splrName": "Supplier Name", |
| | | "splrCode": "Supplier Code", |
| | | "splrBatch": "Supplier Batch" |
| | | }, |
| | | "messages": { |
| | | "itemsTimeout": "DO items timed out and waiting has stopped", |
| | | "detailTimeout": "DO detail timed out and waiting has stopped", |
| | | "detailLoadFailed": "Failed to load DO detail" |
| | | } |
| | | }, |
| | | "transfer": { |
| | | "reportTitle": "Transfer Report", |
| | | "entity": "Transfer Order", |
| | | "buttons": { |
| | | "add": "Add Transfer", |
| | | "publish": "Dispatch" |
| | | }, |
| | | "search": { |
| | | "condition": "Keyword", |
| | | "conditionPlaceholder": "Enter No./remark/warehouse/area", |
| | | "code": "Transfer No.", |
| | | "codePlaceholder": "Enter transfer No.", |
| | | "type": "Transfer Type", |
| | | "source": "Source", |
| | | "exceStatus": "Execution Status", |
| | | "orgWareName": "Source Warehouse", |
| | | "orgWareNamePlaceholder": "Enter source warehouse", |
| | | "tarWareName": "Target Warehouse", |
| | | "tarWareNamePlaceholder": "Enter target warehouse", |
| | | "orgAreaName": "Source Area", |
| | | "orgAreaNamePlaceholder": "Enter source area", |
| | | "tarAreaName": "Target Area", |
| | | "tarAreaNamePlaceholder": "Enter target area", |
| | | "status": "Status", |
| | | "memo": "Remark", |
| | | "memoPlaceholder": "Enter remark" |
| | | }, |
| | | "status": { |
| | | "sourceErp": "ERP", |
| | | "sourceWms": "WMS Generated", |
| | | "sourceExcel": "Excel Import", |
| | | "sourceQms": "QMS", |
| | | "pending": "Pending", |
| | | "running": "Running", |
| | | "completed": "Completed", |
| | | "normal": "Normal", |
| | | "frozen": "Frozen" |
| | | }, |
| | | "actions": { |
| | | "add": "Add Transfer", |
| | | "view": "View Detail", |
| | | "items": "Items", |
| | | "edit": "Edit", |
| | | "publish": "Dispatch", |
| | | "delete": "Delete" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "Enter No./remark/warehouse/area", |
| | | "code": "Enter transfer No.", |
| | | "orgWareName": "Enter source warehouse", |
| | | "tarWareName": "Enter target warehouse", |
| | | "orgAreaName": "Enter source area", |
| | | "tarAreaName": "Enter target area", |
| | | "memo": "Enter remark" |
| | | }, |
| | | "detail": { |
| | | "title": "Transfer Detail", |
| | | "baseInfo": "Basic Information", |
| | | "auditInfo": "Audit Information", |
| | | "source": "Source", |
| | | "orgWareName": "Source Warehouse", |
| | | "tarWareName": "Target Warehouse", |
| | | "orgAreaName": "Source Area", |
| | | "tarAreaName": "Target Area", |
| | | "memo": "Remark", |
| | | "createBy": "Created By", |
| | | "createTime": "Created At", |
| | | "updateBy": "Updated By", |
| | | "updateTime": "Updated At", |
| | | "relatedOrders": "Related Orders", |
| | | "relatedCode": "Related Order No.", |
| | | "code": "Transfer No.", |
| | | "type": "Transfer Type", |
| | | "wkType": "Business Type", |
| | | "exceStatus": "Execution Status", |
| | | "status": "Status", |
| | | "workQty": "In-progress Qty", |
| | | "qty": "Completed Qty", |
| | | "stationId": "Station No.", |
| | | "businessTime": "Business Time" |
| | | }, |
| | | "dialog": { |
| | | "titleAdd": "Add Transfer", |
| | | "titleEdit": "Edit Transfer", |
| | | "tip": "The transfer number is generated by the system. When creating a new record, only maintain the transfer type, source/target area, and remark.", |
| | | "code": "Transfer No.", |
| | | "type": "Transfer Type", |
| | | "orgAreaId": "Source Area", |
| | | "tarAreaId": "Target Area", |
| | | "status": "Status", |
| | | "memo": "Remark", |
| | | "placeholderCode": "Generated after saving", |
| | | "placeholderType": "Please select a transfer type", |
| | | "placeholderOrgAreaId": "Please select a source area", |
| | | "placeholderTarAreaId": "Please select a target area", |
| | | "placeholderStatus": "Please select a status", |
| | | "placeholderMemo": "Please enter a remark", |
| | | "validation": { |
| | | "type": "Please select a transfer type", |
| | | "orgAreaId": "Please select a source area", |
| | | "tarAreaId": "Please select a target area" |
| | | } |
| | | }, |
| | | "messages": { |
| | | "detailTimeout": "Transfer detail timed out and waiting has stopped", |
| | | "ordersTimeout": "Transfer items timed out and waiting has stopped", |
| | | "ordersLoadFailed": "Failed to load transfer items", |
| | | "detailLoadFailed": "Failed to load transfer detail", |
| | | "publishConfirm": "Are you sure you want to dispatch transfer order \"{code}\"?", |
| | | "publishTitle": "Dispatch Confirmation", |
| | | "publishSuccess": "Dispatched successfully", |
| | | "publishFailed": "Dispatch failed", |
| | | "typeOptionsTimeout": "Transfer type options timed out and waiting has stopped", |
| | | "areaOptionsTimeout": "Area options timed out and waiting has stopped" |
| | | } |
| | | } |
| | | }, |
| | | "task": { |
| | | "title": "Task Management", |
| | | "buttons": { |
| | | "autoRun": "Enable Auto Dispatch", |
| | | "pauseAutoRun": "Pause Auto Dispatch" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "Enter task No./location/pallet code", |
| | | "taskCode": "Enter task No.", |
| | | "orgLoc": "Enter source location", |
| | | "targLoc": "Enter target location", |
| | | "barcode": "Enter pallet code" |
| | | }, |
| | | "search": { |
| | | "condition": "Keyword", |
| | | "conditionPlaceholder": "Enter task No./location/pallet code", |
| | | "taskCode": "Task No.", |
| | | "taskCodePlaceholder": "Enter task No.", |
| | | "orgLoc": "Source Location", |
| | | "orgLocPlaceholder": "Enter source location", |
| | | "targLoc": "Target Location", |
| | | "targLocPlaceholder": "Enter target location", |
| | | "barcode": "Pallet Code", |
| | | "barcodePlaceholder": "Enter pallet code" |
| | | }, |
| | | "actions": { |
| | | "view": "View Detail", |
| | | "flowStep": "Flow Steps", |
| | | "complete": "Complete Task", |
| | | "check": "Check Outbound", |
| | | "pick": "Pick Outbound", |
| | | "top": "Pin Task", |
| | | "remove": "Cancel Task" |
| | | }, |
| | | "detail": { |
| | | "title": "Task Detail", |
| | | "taskCode": "Task No.", |
| | | "baseInfo": "Basic Information", |
| | | "pathInfo": "Execution Path", |
| | | "items": "Task Items", |
| | | "itemsHint": "View related orders, materials, and execution records of the current task", |
| | | "flowStep": "Flow Steps", |
| | | "taskStatus": "Task Status", |
| | | "taskType": "Task Type", |
| | | "warehType": "Device Type", |
| | | "priority": "Priority", |
| | | "status": "Status", |
| | | "robotCode": "Robot Code", |
| | | "createTime": "Created At", |
| | | "updateTime": "Updated At", |
| | | "memo": "Remark", |
| | | "orgLoc": "Source Location", |
| | | "orgSite": "Source Station", |
| | | "targLoc": "Target Location", |
| | | "targSite": "Target Station", |
| | | "barcode": "Pallet Code" |
| | | }, |
| | | "expand": { |
| | | "title": "Task Items", |
| | | "empty": "No task items", |
| | | "orderType": "Order Type", |
| | | "wkType": "Business Type", |
| | | "platWorkCode": "Work Order No.", |
| | | "platItemId": "Line No.", |
| | | "anfme": "Quantity" |
| | | }, |
| | | "flowStepDialog": { |
| | | "title": "Flow Steps", |
| | | "currentTask": "Current Task", |
| | | "flowInstanceNo": "Flow Instance No.", |
| | | "stepCode": "Step Code", |
| | | "stepName": "Step Name", |
| | | "stepType": "Step Type", |
| | | "executeResult": "Execution Result", |
| | | "startTime": "Start Time", |
| | | "endTime": "End Time", |
| | | "timeout": "Flow steps timed out and waiting has stopped" |
| | | }, |
| | | "messages": { |
| | | "completeConfirm": "Are you sure you want to complete task {code}?", |
| | | "completeSuccess": "Task completed successfully", |
| | | "removeConfirm": "Are you sure you want to cancel task {code}?", |
| | | "removeSuccess": "Task canceled successfully", |
| | | "checkConfirm": "Are you sure you want to execute check outbound task {code}?", |
| | | "checkSuccess": "Check outbound completed successfully", |
| | | "pickConfirm": "Are you sure you want to execute pick outbound task {code}?", |
| | | "pickSuccess": "Pick outbound completed successfully", |
| | | "topSuccess": "Task pinned successfully", |
| | | "actionFailed": "Task action failed", |
| | | "autoRunEnabled": "Auto dispatch enabled", |
| | | "autoRunPaused": "Auto dispatch paused", |
| | | "autoRunFailed": "Failed to update auto dispatch settings", |
| | | "detailLoadFailed": "Failed to load task items", |
| | | "listTimeout": "Task list timed out and waiting has stopped", |
| | | "autoRunTimeout": "Auto dispatch config timed out and waiting has stopped", |
| | | "autoRunOnSuccess": "Auto dispatch enabled", |
| | | "autoRunOffSuccess": "Auto dispatch paused", |
| | | "autoRunUpdateFailed": "Failed to update auto dispatch settings", |
| | | "itemsTimeout": "Task items timed out and waiting has stopped" |
| | | } |
| | | }, |
| | | "basicInfo": { |
| | | "basStationArea": { |
| | | "reportTitle": "Station Area Report", |
| | | "entity": "Station Area", |
| | | "buttons": { |
| | | "add": "Add Station Area", |
| | | "batchDelete": "Batch Delete" |
| | | }, |
| | | "actions": { |
| | | "add": "Add Station Area" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "Enter station area name/code/remark", |
| | | "timeStart": "Select start time", |
| | | "timeEnd": "Select end time", |
| | | "stationAreaName": "Enter station area name", |
| | | "stationAreaId": "Enter station area code", |
| | | "crossZoneArea": "Enter cross-zone area", |
| | | "wcsData": "Enter WCS data", |
| | | "containerType": "Enter container type", |
| | | "barcode": "Enter barcode", |
| | | "stationAlias": "Enter station alias", |
| | | "memo": "Enter remark" |
| | | }, |
| | | "search": { |
| | | "condition": "Keyword", |
| | | "conditionPlaceholder": "Enter station area name/code/remark", |
| | | "timeStart": "Start Time", |
| | | "timeStartPlaceholder": "Select start time", |
| | | "timeEnd": "End Time", |
| | | "timeEndPlaceholder": "Select end time", |
| | | "stationAreaName": "Station Area Name", |
| | | "stationAreaNamePlaceholder": "Enter station area name", |
| | | "stationAreaId": "Station Area Code", |
| | | "stationAreaIdPlaceholder": "Enter station area code", |
| | | "type": "Station Type", |
| | | "area": "Warehouse Area", |
| | | "useStatus": "Usage Status", |
| | | "inAble": "Inbound Allowed", |
| | | "outAble": "Outbound Allowed", |
| | | "isCrossZone": "Cross Zone", |
| | | "crossZoneArea": "Cross-zone Area", |
| | | "crossZoneAreaPlaceholder": "Enter cross-zone area", |
| | | "isWcs": "WCS Enabled", |
| | | "wcsData": "WCS Data", |
| | | "wcsDataPlaceholder": "Enter WCS data", |
| | | "containerType": "Container Type", |
| | | "containerTypePlaceholder": "Enter container type", |
| | | "autoTransfer": "Auto Transfer", |
| | | "barcode": "Barcode", |
| | | "barcodePlaceholder": "Enter barcode", |
| | | "stationAlias": "Station Alias", |
| | | "stationAliasPlaceholder": "Enter station alias", |
| | | "status": "Status", |
| | | "memo": "Remark", |
| | | "memoPlaceholder": "Enter remark" |
| | | }, |
| | | "type": { |
| | | "smart": "Smart Station", |
| | | "normal": "Normal Station" |
| | | }, |
| | | "table": { |
| | | "crossZoneArea": "Cross-zone Area", |
| | | "inAble": "Inbound Allowed", |
| | | "outAble": "Outbound Allowed", |
| | | "isCrossZone": "Cross Zone" |
| | | }, |
| | | "detail": { |
| | | "title": "Station Area Detail", |
| | | "baseInfo": "Basic Information", |
| | | "auditInfo": "Audit Information", |
| | | "stationAreaName": "Station Area Name", |
| | | "stationAreaId": "Station Area Code", |
| | | "type": "Station Type", |
| | | "area": "Warehouse Area", |
| | | "crossZoneArea": "Cross-zone Area", |
| | | "containerType": "Container Type", |
| | | "stationAlias": "Station Alias", |
| | | "inAble": "Inbound Allowed", |
| | | "outAble": "Outbound Allowed", |
| | | "isCrossZone": "Cross Zone", |
| | | "isWcs": "WCS Enabled", |
| | | "autoTransfer": "Auto Transfer", |
| | | "useStatus": "Usage Status", |
| | | "barcode": "Barcode", |
| | | "status": "Status", |
| | | "wcsData": "WCS Data", |
| | | "memo": "Remark", |
| | | "createBy": "Created By", |
| | | "createTime": "Created At", |
| | | "updateBy": "Updated By", |
| | | "updateTime": "Updated At" |
| | | }, |
| | | "dialog": { |
| | | "titleAdd": "Add Station Area", |
| | | "titleEdit": "Edit Station Area", |
| | | "stationAreaName": "Station Area Name", |
| | | "stationAreaId": "Station Area Code", |
| | | "type": "Station Type", |
| | | "area": "Warehouse Area", |
| | | "crossZoneArea": "Cross-zone Area", |
| | | "containerType": "Container Type", |
| | | "stationAlias": "Station Alias", |
| | | "inAble": "Inbound Allowed", |
| | | "outAble": "Outbound Allowed", |
| | | "isCrossZone": "Cross Zone", |
| | | "isWcs": "WCS Enabled", |
| | | "autoTransfer": "Auto Transfer", |
| | | "useStatus": "Usage Status", |
| | | "wcsData": "WCS Data", |
| | | "barcode": "Barcode", |
| | | "status": "Status", |
| | | "memo": "Remark", |
| | | "validation": { |
| | | "stationAreaName": "Please enter the station area name", |
| | | "stationAreaId": "Please enter the station area code", |
| | | "type": "Please select a station type", |
| | | "area": "Please select a warehouse area", |
| | | "containerType": "Please select container types", |
| | | "stationAlias": "Please select station aliases" |
| | | } |
| | | }, |
| | | "messages": { |
| | | "detailLoadFailed": "Failed to load station area detail", |
| | | "detailTimeout": "Station area detail timed out and waiting has stopped", |
| | | "stationAliasTimeout": "Station alias options timed out and waiting has stopped", |
| | | "areaOptionsTimeout": "Area options timed out and waiting has stopped", |
| | | "containerTypeTimeout": "Container type options timed out and waiting has stopped", |
| | | "useStatusTimeout": "Usage status options timed out and waiting has stopped" |
| | | } |
| | | } |
| | | }, |
| | | "system": { |
| | | "role": { |
| | | "entity": "Role", |
| | | "reportTitle": "Role Report", |
| | | "buttons": { |
| | | "add": "Add Role" |
| | | }, |
| | | "search": { |
| | | "name": "Role Name", |
| | | "namePlaceholder": "Enter role name", |
| | | "code": "Role Code", |
| | | "codePlaceholder": "Enter role code", |
| | | "memo": "Remark", |
| | | "memoPlaceholder": "Enter remark", |
| | | "condition": "Keyword", |
| | | "conditionPlaceholder": "Search by keyword", |
| | | "status": "Status", |
| | | "statusPlaceholder": "Select status" |
| | | }, |
| | | "table": { |
| | | "name": "Role Name", |
| | | "code": "Role Code", |
| | | "memo": "Remark", |
| | | "status": "Status", |
| | | "updateTime": "Updated At", |
| | | "createTime": "Created At", |
| | | "operation": "Operation" |
| | | }, |
| | | "actions": { |
| | | "scopeMenu": "Web Permissions", |
| | | "scopePda": "PDA Permissions", |
| | | "scopeMatnr": "Material Permissions", |
| | | "scopeWarehouse": "Warehouse Permissions", |
| | | "edit": "Edit Role", |
| | | "delete": "Delete Role" |
| | | }, |
| | | "scopes": { |
| | | "menu": "Web Permissions", |
| | | "pda": "PDA Permissions", |
| | | "matnr": "Material Permissions", |
| | | "warehouse": "Warehouse Permissions" |
| | | }, |
| | | "dialog": { |
| | | "addTitle": "Add Role", |
| | | "editTitle": "Edit Role", |
| | | "validationName": "Please enter the role name", |
| | | "name": "Role Name", |
| | | "namePlaceholder": "Enter role name", |
| | | "code": "Role Code", |
| | | "codePlaceholder": "Enter role code", |
| | | "status": "Status", |
| | | "statusPlaceholder": "Select status", |
| | | "memo": "Remark", |
| | | "memoPlaceholder": "Enter remark" |
| | | }, |
| | | "permission": { |
| | | "title": "Role Permissions", |
| | | "currentRole": "Current Role: ", |
| | | "unselected": "No role selected", |
| | | "selectAll": "Select All", |
| | | "clear": "Clear", |
| | | "saveCurrent": "Save Current Permissions", |
| | | "searchPlaceholder": "Search permission tree", |
| | | "authButton": "Button", |
| | | "scopeLoadTimeout": "{title} loading timed out and waiting has stopped", |
| | | "scopeLoadFailed": "Failed to load {title}", |
| | | "saveSuccess": "Permissions saved successfully", |
| | | "saveFailed": "Failed to save permissions" |
| | | } |
| | | }, |
| | | "menu": { |
| | | "title": "Menu Management", |
| | | "entities": { |
| | | "permission": "Permission" |
| | | }, |
| | | "buttons": { |
| | | "add": "Add Menu" |
| | | }, |
| | | "actions": { |
| | | "addAuth": "Add Permission", |
| | | "expand": "Expand", |
| | | "collapse": "Collapse" |
| | | }, |
| | | "types": { |
| | | "button": "Button", |
| | | "directory": "Directory", |
| | | "menu": "Menu" |
| | | }, |
| | | "search": { |
| | | "name": "Menu Name", |
| | | "route": "Route" |
| | | }, |
| | | "messages": { |
| | | "menuSelfParent": "Parent menu cannot be the current menu", |
| | | "loadFailed": "Failed to load menu", |
| | | "loadTimeout": "Menu loading timed out and waiting has stopped", |
| | | "submitFailed": "Submit failed", |
| | | "authCount": "{count} permission keys", |
| | | "deleteMenuConfirm": "Are you sure you want to delete menu \"{title}\"? This action cannot be undone", |
| | | "deleteAuthConfirm": "Are you sure you want to delete permission \"{title}\"? This action cannot be undone" |
| | | }, |
| | | "form": { |
| | | "typeMenu": "Menu", |
| | | "typeButton": "Button", |
| | | "titleAddMenu": "Create Menu", |
| | | "titleEditMenu": "Edit Menu", |
| | | "titleAddButton": "Create Permission", |
| | | "titleEditButton": "Edit Permission", |
| | | "menuType": "Menu Type", |
| | | "parentId": "Parent Menu", |
| | | "nameMenu": "Menu Name", |
| | | "nameButton": "Permission Name", |
| | | "route": "Route", |
| | | "component": "Component Key", |
| | | "authority": "Authority", |
| | | "icon": "Icon", |
| | | "sort": "Sort", |
| | | "status": "Status", |
| | | "memo": "Remark", |
| | | "placeholderParent": "Please select a parent menu", |
| | | "placeholderMenuName": "Please enter a menu name", |
| | | "placeholderButtonName": "Please enter a permission name", |
| | | "placeholderRoute": "Please enter a route", |
| | | "placeholderComponent": "Please enter a component key", |
| | | "placeholderAuthority": "Please enter an authority", |
| | | "placeholderIcon": "Please enter an icon name", |
| | | "placeholderStatus": "Please select a status", |
| | | "placeholderMemo": "Please enter a remark", |
| | | "validationMenuName": "Please enter a menu name", |
| | | "validationButtonName": "Please enter a permission name", |
| | | "validationRoute": "Please enter a route", |
| | | "validationAuthority": "Please enter an authority" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | "tips": "提示", |
| | | "cancel": "取消", |
| | | "confirm": "确定", |
| | | "logOutTips": "您是否要退出登录?" |
| | | "logOutTips": "您是否要退出登录?", |
| | | "count": "共 {count} 条", |
| | | "listSeparator": "、", |
| | | "actions": { |
| | | "search": "查询", |
| | | "reset": "重置", |
| | | "refresh": "刷新", |
| | | "add": "新增", |
| | | "batchDelete": "批量删除", |
| | | "edit": "编辑", |
| | | "delete": "删除", |
| | | "detail": "详情", |
| | | "items": "明细", |
| | | "print": "打印", |
| | | "export": "导出", |
| | | "exporting": "导出中...", |
| | | "close": "关闭", |
| | | "complete": "完成", |
| | | "expand": "展开", |
| | | "collapse": "收起", |
| | | "viewAll": "查看全部", |
| | | "save": "保存", |
| | | "submit": "提交" |
| | | }, |
| | | "status": { |
| | | "enabled": "启用", |
| | | "disabled": "禁用", |
| | | "normal": "正常", |
| | | "frozen": "冻结", |
| | | "unknown": "未知", |
| | | "yes": "是", |
| | | "no": "否" |
| | | }, |
| | | "placeholder": { |
| | | "empty": "--" |
| | | } |
| | | }, |
| | | "crud": { |
| | | "messages": { |
| | | "createSuccess": "新增成功", |
| | | "updateSuccess": "修改成功", |
| | | "deleteSuccess": "删除成功", |
| | | "batchDeleteSuccess": "批量删除成功", |
| | | "submitFailed": "提交失败", |
| | | "deleteFailed": "删除失败", |
| | | "batchDeleteFailed": "批量删除失败", |
| | | "exportSuccess": "导出成功", |
| | | "exportFailed": "导出失败", |
| | | "exportFailedWithStatus": "导出失败({status})", |
| | | "printFailed": "打印失败", |
| | | "loadFailed": "加载失败" |
| | | }, |
| | | "confirm": { |
| | | "deleteTitle": "删除确认", |
| | | "deleteMessage": "确定要删除{entity}「{label}」吗?", |
| | | "batchDeleteTitle": "批量删除确认", |
| | | "batchDeleteMessage": "确定要批量删除选中的 {count} 个{entity}吗?" |
| | | } |
| | | }, |
| | | "print": { |
| | | "previewTitle": "打印预览", |
| | | "defaultReportTitle": "报表", |
| | | "borderOn": "边框开", |
| | | "borderOff": "边框关", |
| | | "portrait": "竖版", |
| | | "landscape": "横版", |
| | | "reportDate": "报表日期", |
| | | "operator": "打印人", |
| | | "printedAt": "打印时间", |
| | | "count": "记录数", |
| | | "previewLimited": "预览仅展示前 {previewCount} 条,点击打印将输出全部 {totalCount} 条数据。", |
| | | "noData": "暂无打印数据" |
| | | }, |
| | | "table": { |
| | | "index": "序号", |
| | | "unit": "单位", |
| | | "id": "ID", |
| | | "wcs": "WCS", |
| | | "source": "来源", |
| | | "supplier": "供应商", |
| | | "supplierBatch": "供应商批次" |
| | | }, |
| | | "search": { |
| | | "placeholder": "搜索页面", |
| | |
| | | "assistantRole": "AI", |
| | | "thinking": "思考中...", |
| | | "inputPlaceholder": "输入你的问题,按 Enter 发送,Shift + Enter 换行", |
| | | "inputHotkeyHint": "Enter 发送,Shift + Enter 换行", |
| | | "clearInput": "清空输入", |
| | | "stop": "停止", |
| | | "send": "发送", |
| | |
| | | "recentMetric": "Recent: {value}", |
| | | "elapsedMetric": "耗时: {value} ms", |
| | | "firstTokenMetric": "首包: {value} ms", |
| | | "tokenMetric": "Tokens: prompt {prompt} / completion {completion} / total {total}" |
| | | "tokenMetric": "Tokens: prompt {prompt} / completion {completion} / total {total}", |
| | | "streaming": "生成中" |
| | | } |
| | | }, |
| | | "table": { |
| | |
| | | "expand": "展开", |
| | | "index": "序号" |
| | | }, |
| | | "index": "序号", |
| | | "id": "ID", |
| | | "operation": "操作", |
| | | "status": "状态", |
| | | "type": "类型", |
| | | "source": "来源", |
| | | "supplier": "供应商", |
| | | "supplierBatch": "供应商批次", |
| | | "remark": "备注", |
| | | "updateBy": "更新人", |
| | | "updateTime": "更新时间", |
| | | "createTime": "创建时间", |
| | | "unit": "单位", |
| | | "batch": "批次", |
| | | "quantity": "数量", |
| | | "materialCode": "物料编码", |
| | | "materialName": "物料名称", |
| | | "wcs": "WCS", |
| | | "menuType": "菜单类型", |
| | | "iconPreview": "图标预览", |
| | | "componentKey": "组件标识", |
| | | "permissionKey": "权限标识", |
| | | "sort": "排序", |
| | | "zebra": "斑马纹", |
| | | "border": "边框", |
| | | "headerBackground": "表头背景" |
| | | "headerBackground": "表头背景", |
| | | "topLevelMenu": "顶级菜单", |
| | | "emptyText": "暂无数据" |
| | | }, |
| | | "message": { |
| | | "requestTimeoutStopped": "请求超时,已停止等待", |
| | | "exportTimeoutStopped": "导出请求超时,已停止等待", |
| | | "printTimeoutStopped": "打印数据加载超时,已停止等待", |
| | | "exportInvalidDataType": "数据必须是数组格式", |
| | | "exportNoData": "没有可导出的数据", |
| | | "exportExceedMaxRows": "数据行数超过限制({maxRows}行)", |
| | | "exportExcelFailed": "Excel 导出失败: {message}", |
| | | "exportSuccessWithCount": "成功导出 {count} 条数据", |
| | | "exportFailedUnknown": "导出失败: {message}", |
| | | "exportWorkbookSubject": "数据导出", |
| | | "exportWorkbookCompany": "系统导出", |
| | | "exportWorkbookCategory": "数据", |
| | | "exportWorkbookKeywords": "excel,export,data", |
| | | "exportWorkbookComments": "由系统自动生成" |
| | | }, |
| | | "pages": { |
| | | "system": { |
| | | "role": { |
| | | "entity": "角色", |
| | | "reportTitle": "角色管理报表", |
| | | "buttons": { |
| | | "add": "新增角色" |
| | | }, |
| | | "search": { |
| | | "name": "角色名称", |
| | | "namePlaceholder": "请输入角色名称", |
| | | "code": "角色编码", |
| | | "codePlaceholder": "请输入角色编码", |
| | | "memo": "备注", |
| | | "memoPlaceholder": "请输入备注", |
| | | "condition": "关键字", |
| | | "conditionPlaceholder": "输入关键字搜索", |
| | | "status": "状态", |
| | | "statusPlaceholder": "请选择状态" |
| | | }, |
| | | "table": { |
| | | "name": "角色名称", |
| | | "code": "角色编码", |
| | | "memo": "备注", |
| | | "status": "状态", |
| | | "updateTime": "更新时间", |
| | | "createTime": "创建时间", |
| | | "operation": "操作" |
| | | }, |
| | | "actions": { |
| | | "scopeMenu": "网页权限", |
| | | "scopePda": "PDA权限", |
| | | "scopeMatnr": "物料权限", |
| | | "scopeWarehouse": "仓库权限", |
| | | "edit": "编辑角色", |
| | | "delete": "删除角色" |
| | | }, |
| | | "scopes": { |
| | | "menu": "网页权限", |
| | | "pda": "PDA权限", |
| | | "matnr": "物料权限", |
| | | "warehouse": "仓库权限" |
| | | }, |
| | | "dialog": { |
| | | "addTitle": "新增角色", |
| | | "editTitle": "编辑角色", |
| | | "validationName": "请输入角色名称", |
| | | "name": "角色名称", |
| | | "namePlaceholder": "请输入角色名称", |
| | | "code": "角色编码", |
| | | "codePlaceholder": "请输入角色编码", |
| | | "status": "状态", |
| | | "statusPlaceholder": "请选择状态", |
| | | "memo": "备注", |
| | | "memoPlaceholder": "请输入备注" |
| | | }, |
| | | "permission": { |
| | | "title": "角色权限", |
| | | "currentRole": "当前角色:", |
| | | "unselected": "未选择角色", |
| | | "selectAll": "全选", |
| | | "clear": "清空", |
| | | "saveCurrent": "保存当前权限", |
| | | "searchPlaceholder": "搜索权限树", |
| | | "authButton": "按钮", |
| | | "scopeLoadTimeout": "{title}加载超时,已停止等待", |
| | | "scopeLoadFailed": "加载{title}失败", |
| | | "saveSuccess": "权限保存成功", |
| | | "saveFailed": "权限保存失败" |
| | | } |
| | | }, |
| | | "menu": { |
| | | "title": "菜单管理", |
| | | "addMenu": "添加菜单", |
| | | "menuName": "菜单名称", |
| | | "route": "路由地址", |
| | | "iconPreview": "图标预览", |
| | | "menuType": "菜单类型", |
| | | "componentKey": "组件标识", |
| | | "authority": "权限标识", |
| | | "sort": "排序", |
| | | "status": "状态", |
| | | "memo": "备注", |
| | | "operation": "操作", |
| | | "types": { |
| | | "button": "按钮", |
| | | "directory": "目录", |
| | | "menu": "菜单" |
| | | }, |
| | | "addPermission": "新增权限", |
| | | "deleteMenuMessage": "确定要删除菜单「{label}」吗?删除后无法恢复", |
| | | "deleteAuthMessage": "确定要删除权限「{label}」吗?删除后无法恢复", |
| | | "selfParentError": "上级菜单不能选择当前菜单" |
| | | } |
| | | }, |
| | | "orders": { |
| | | "asnOrder": { |
| | | "reportTitle": "入库通知单报表", |
| | | "entity": "入库通知单", |
| | | "buttons": { |
| | | "createByPo": "按PO建单" |
| | | }, |
| | | "search": { |
| | | "condition": "关键字", |
| | | "conditionPlaceholder": "请输入 ASN 单号/PO 单号/供应商", |
| | | "code": "ASN单号", |
| | | "codePlaceholder": "请输入 ASN 单号", |
| | | "poCode": "PO单号", |
| | | "poCodePlaceholder": "请输入 PO 单号", |
| | | "wkType": "业务类型", |
| | | "wkTypePlaceholder": "请输入业务类型", |
| | | "exceStatus": "单据状态", |
| | | "supplierName": "供应商", |
| | | "supplierPlaceholder": "请输入供应商", |
| | | "purchaseUserName": "采购员", |
| | | "purchaseUserPlaceholder": "请输入采购员" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "请输入 ASN 单号/PO 单号/供应商", |
| | | "code": "请输入 ASN 单号", |
| | | "poCode": "请输入 PO 单号", |
| | | "wkType": "请输入业务类型", |
| | | "supplierName": "请输入供应商", |
| | | "purchaseUserName": "请输入采购员" |
| | | }, |
| | | "status": { |
| | | "pending": "未执行", |
| | | "running": "执行中", |
| | | "receiving": "收货完成", |
| | | "taskRunning": "任务执行中", |
| | | "completed": "已完成", |
| | | "cancelled": "取消", |
| | | "closed": "已关闭" |
| | | }, |
| | | "actions": { |
| | | "view": "查看详情", |
| | | "items": "收货明细", |
| | | "print": "打印", |
| | | "complete": "完成" |
| | | }, |
| | | "detail": { |
| | | "title": "入库通知单详情", |
| | | "baseInfo": "基础信息", |
| | | "items": "单据明细", |
| | | "asnCode": "ASN单号", |
| | | "poCode": "PO单号", |
| | | "wkType": "业务类型", |
| | | "orderType": "单据类型", |
| | | "status": "单据状态", |
| | | "purchaseOrg": "采购组织", |
| | | "purchaseUser": "采购员", |
| | | "supplier": "供应商", |
| | | "anfme": "应收数量", |
| | | "qty": "已收数量", |
| | | "updateTime": "更新时间", |
| | | "createTime": "创建时间", |
| | | "memo": "备注", |
| | | "count": "共 {count} 条", |
| | | "completeTitle": "完成确认", |
| | | "completeConfirm": "确定完成入库通知单 {code} 吗?", |
| | | "completeSuccess": "入库通知单已完成", |
| | | "actionFailed": "入库通知单操作失败", |
| | | "detailTimeout": "入库通知单明细加载超时,已停止等待", |
| | | "itemsTimeout": "入库通知单明细加载超时,已停止等待" |
| | | }, |
| | | "createByPoDialog": { |
| | | "title": "按PO建单", |
| | | "purchaseList": "可建单 PO 列表", |
| | | "purchasePreview": "PO 明细预览", |
| | | "purchaseSelected": "当前选择:{code}", |
| | | "purchaseEmpty": "请先在左侧选择一个 PO 单", |
| | | "purchaseGenerateHint": "将按 PO {code} 的 {count} 条明细生成入库通知单", |
| | | "purchaseGenerateEmpty": "请选择一个可建单的 PO 单", |
| | | "generate": "生成入库通知单", |
| | | "refreshItems": "刷新明细", |
| | | "messages": { |
| | | "purchaseItemsTimeout": "PO 明细加载超时,已停止等待", |
| | | "purchaseItemsAllTimeout": "PO 全量明细加载超时,已停止等待", |
| | | "purchaseRequired": "请先选择一个 PO 单", |
| | | "purchaseItemsEmpty": "当前 PO 单没有可建单明细", |
| | | "createByPoSuccess": "已根据 PO 单生成入库通知单", |
| | | "createByPoFailed": "按 PO 建单失败" |
| | | }, |
| | | "search": { |
| | | "condition": "关键字", |
| | | "conditionPlaceholder": "请输入 PO 单号/来源/供应商", |
| | | "code": "PO单号", |
| | | "codePlaceholder": "请输入 PO 单号", |
| | | "source": "来源", |
| | | "sourcePlaceholder": "请输入来源", |
| | | "supplierName": "供应商", |
| | | "supplierNamePlaceholder": "请输入供应商" |
| | | } |
| | | }, |
| | | "table": { |
| | | "poItemId": "PO行号", |
| | | "expectedQty": "应收数量", |
| | | "receivedQty": "已收数量", |
| | | "remainingQty": "可建单数量", |
| | | "poStatus": "PO状态", |
| | | "purchaseQty": "采购数量", |
| | | "generatedQty": "已生成ASN数量", |
| | | "receivedQtyTotal": "收货数量" |
| | | } |
| | | }, |
| | | "delivery": { |
| | | "reportTitle": "DO单报表", |
| | | "detailReportTitle": "DO单明细报表", |
| | | "entity": "DO单", |
| | | "search": { |
| | | "condition": "关键字", |
| | | "conditionPlaceholder": "请输入单号/ERP主单标识/平台单号", |
| | | "code": "单号", |
| | | "codePlaceholder": "请输入单号", |
| | | "platId": "ERP主单标识", |
| | | "platIdPlaceholder": "请输入ERP主单标识", |
| | | "type": "单据类型", |
| | | "typePlaceholder": "请输入单据类型", |
| | | "wkType": "业务类型", |
| | | "wkTypePlaceholder": "请输入业务类型", |
| | | "source": "单据来源", |
| | | "sourcePlaceholder": "请输入单据来源", |
| | | "exceStatus": "执行状态", |
| | | "exceStatusPlaceholder": "请输入执行状态", |
| | | "memo": "备注", |
| | | "memoPlaceholder": "请输入备注" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "请输入单号/ERP主单标识/平台单号", |
| | | "code": "请输入单号", |
| | | "platId": "请输入ERP主单标识", |
| | | "type": "请输入单据类型", |
| | | "wkType": "请输入业务类型", |
| | | "source": "请输入单据来源", |
| | | "exceStatus": "请输入执行状态", |
| | | "memo": "请输入备注" |
| | | }, |
| | | "status": { |
| | | "normal": "正常", |
| | | "disabled": "禁用", |
| | | "pending": "未执行", |
| | | "running": "执行中", |
| | | "partial": "部分完成", |
| | | "completed": "已完成" |
| | | }, |
| | | "actions": { |
| | | "view": "查看详情", |
| | | "items": "明细", |
| | | "delete": "删除" |
| | | }, |
| | | "detail": { |
| | | "title": "交接单详情", |
| | | "baseInfo": "基础信息", |
| | | "auditInfo": "审计信息", |
| | | "items": "交接单明细", |
| | | "code": "交接单号", |
| | | "platId": "ERP主单标识", |
| | | "platCode": "平台单号", |
| | | "type": "单据类型", |
| | | "wkType": "业务类型", |
| | | "source": "单据来源", |
| | | "anfme": "应收数量", |
| | | "qty": "实收数量", |
| | | "workQty": "执行中数量", |
| | | "status": "状态", |
| | | "exceStatus": "执行状态", |
| | | "memo": "备注", |
| | | "startTime": "计划出库时间", |
| | | "endTime": "计划出库结束时间", |
| | | "createBy": "创建人", |
| | | "createTime": "创建时间", |
| | | "updateBy": "更新人", |
| | | "updateTime": "更新时间", |
| | | "count": "共 {count} 条" |
| | | }, |
| | | "table": { |
| | | "deliveryCode": "交接单号", |
| | | "platCode": "平台单号", |
| | | "platItemId": "平台行号", |
| | | "matnrCode": "物料编码", |
| | | "maktx": "物料名称", |
| | | "fieldsIndex": "动态字段索引", |
| | | "anfme": "数量", |
| | | "workQty": "执行数量", |
| | | "qty": "已出数量", |
| | | "startTime": "计划出库时间", |
| | | "endTime": "计划出库结束时间", |
| | | "nromQty": "标准包装", |
| | | "printQty": "打印数量", |
| | | "splrName": "供应商名称", |
| | | "splrCode": "供应商编码", |
| | | "splrBatch": "供应商批次" |
| | | }, |
| | | "messages": { |
| | | "itemsTimeout": "DO单明细加载超时,已停止等待", |
| | | "detailTimeout": "DO单详情加载超时,已停止等待", |
| | | "detailLoadFailed": "DO单详情加载失败" |
| | | } |
| | | }, |
| | | "transfer": { |
| | | "reportTitle": "调拨单报表", |
| | | "entity": "调拨单", |
| | | "buttons": { |
| | | "add": "新增调拨单", |
| | | "publish": "下发执行" |
| | | }, |
| | | "search": { |
| | | "condition": "关键字", |
| | | "conditionPlaceholder": "请输入单号/备注/仓库/库区", |
| | | "code": "调拨单号", |
| | | "codePlaceholder": "请输入调拨单号", |
| | | "type": "调拨类型", |
| | | "source": "来源", |
| | | "exceStatus": "执行状态", |
| | | "orgWareName": "源仓库", |
| | | "orgWareNamePlaceholder": "请输入源仓库", |
| | | "tarWareName": "目标仓库", |
| | | "tarWareNamePlaceholder": "请输入目标仓库", |
| | | "orgAreaName": "源库区", |
| | | "orgAreaNamePlaceholder": "请输入源库区", |
| | | "tarAreaName": "目标库区", |
| | | "tarAreaNamePlaceholder": "请输入目标库区", |
| | | "status": "状态", |
| | | "memo": "备注", |
| | | "memoPlaceholder": "请输入备注" |
| | | }, |
| | | "status": { |
| | | "sourceErp": "ERP系统", |
| | | "sourceWms": "WMS系统生成", |
| | | "sourceExcel": "EXCEL导入", |
| | | "sourceQms": "QMS系统", |
| | | "pending": "未执行", |
| | | "running": "执行中", |
| | | "completed": "执行完成", |
| | | "normal": "正常", |
| | | "frozen": "冻结" |
| | | }, |
| | | "actions": { |
| | | "add": "新增调拨单", |
| | | "view": "查看详情", |
| | | "items": "明细", |
| | | "edit": "编辑", |
| | | "publish": "下发执行", |
| | | "delete": "删除" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "请输入单号/备注/仓库/库区", |
| | | "code": "请输入调拨单号", |
| | | "orgWareName": "请输入源仓库", |
| | | "tarWareName": "请输入目标仓库", |
| | | "orgAreaName": "请输入源库区", |
| | | "tarAreaName": "请输入目标库区", |
| | | "memo": "请输入备注" |
| | | }, |
| | | "detail": { |
| | | "title": "调拨单详情", |
| | | "baseInfo": "基础信息", |
| | | "auditInfo": "审计信息", |
| | | "source": "来源", |
| | | "orgWareName": "源仓库", |
| | | "tarWareName": "目标仓库", |
| | | "orgAreaName": "源库区", |
| | | "tarAreaName": "目标库区", |
| | | "memo": "备注", |
| | | "createBy": "创建人", |
| | | "createTime": "创建时间", |
| | | "updateBy": "更新人", |
| | | "updateTime": "更新时间", |
| | | "relatedOrders": "关联单据", |
| | | "relatedCode": "关联单号", |
| | | "code": "调拨单号", |
| | | "type": "调拨类型", |
| | | "wkType": "业务类型", |
| | | "exceStatus": "执行状态", |
| | | "status": "状态", |
| | | "workQty": "执行中数量", |
| | | "qty": "已完成数量", |
| | | "stationId": "站点编号", |
| | | "businessTime": "业务时间" |
| | | }, |
| | | "dialog": { |
| | | "titleAdd": "新增调拨单", |
| | | "titleEdit": "编辑调拨单", |
| | | "tip": "调拨单号由系统生成,新增时只需维护调拨类型、源/目标库区和备注。", |
| | | "code": "调拨单号", |
| | | "type": "调拨类型", |
| | | "orgAreaId": "源库区", |
| | | "tarAreaId": "目标库区", |
| | | "status": "状态", |
| | | "memo": "备注", |
| | | "placeholderCode": "保存后自动生成", |
| | | "placeholderType": "请选择调拨类型", |
| | | "placeholderOrgAreaId": "请选择源库区", |
| | | "placeholderTarAreaId": "请选择目标库区", |
| | | "placeholderStatus": "请选择状态", |
| | | "placeholderMemo": "请输入备注", |
| | | "validation": { |
| | | "type": "请选择调拨类型", |
| | | "orgAreaId": "请选择源库区", |
| | | "tarAreaId": "请选择目标库区" |
| | | } |
| | | }, |
| | | "messages": { |
| | | "detailTimeout": "调拨单详情加载超时,已停止等待", |
| | | "ordersTimeout": "调拨单明细加载超时,已停止等待", |
| | | "ordersLoadFailed": "调拨单明细加载失败", |
| | | "detailLoadFailed": "调拨单详情加载失败", |
| | | "publishConfirm": "确定要下发调拨单「{code}」吗?", |
| | | "publishTitle": "下发确认", |
| | | "publishSuccess": "下发执行成功", |
| | | "publishFailed": "下发执行失败", |
| | | "typeOptionsTimeout": "调拨类型选项加载超时,已停止等待", |
| | | "areaOptionsTimeout": "库区选项加载超时,已停止等待" |
| | | } |
| | | } |
| | | }, |
| | | "task": { |
| | | "title": "任务管理", |
| | | "buttons": { |
| | | "autoRun": "自动下发任务", |
| | | "pauseAutoRun": "暂停自动下发" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "请输入任务号/库位/托盘码", |
| | | "taskCode": "请输入任务号", |
| | | "orgLoc": "请输入源库位", |
| | | "targLoc": "请输入目标库位", |
| | | "barcode": "请输入托盘码" |
| | | }, |
| | | "search": { |
| | | "condition": "关键字", |
| | | "conditionPlaceholder": "请输入任务号/库位/托盘码", |
| | | "taskCode": "任务号", |
| | | "taskCodePlaceholder": "请输入任务号", |
| | | "orgLoc": "源库位", |
| | | "orgLocPlaceholder": "请输入源库位", |
| | | "targLoc": "目标库位", |
| | | "targLocPlaceholder": "请输入目标库位", |
| | | "barcode": "托盘码", |
| | | "barcodePlaceholder": "请输入托盘码" |
| | | }, |
| | | "actions": { |
| | | "view": "查看详情", |
| | | "flowStep": "流程步骤", |
| | | "complete": "完成任务", |
| | | "check": "盘点出库", |
| | | "pick": "拣料出库", |
| | | "top": "任务置顶", |
| | | "remove": "取消任务" |
| | | }, |
| | | "detail": { |
| | | "title": "任务详情", |
| | | "taskCode": "任务号", |
| | | "baseInfo": "任务基础信息", |
| | | "pathInfo": "执行路径", |
| | | "items": "任务明细", |
| | | "itemsHint": "查看当前任务关联的业务单据、物料和执行记录", |
| | | "flowStep": "流程步骤", |
| | | "taskStatus": "任务状态", |
| | | "taskType": "任务类型", |
| | | "warehType": "设备类型", |
| | | "priority": "优先级", |
| | | "status": "状态", |
| | | "robotCode": "机器人编码", |
| | | "createTime": "创建时间", |
| | | "updateTime": "更新时间", |
| | | "memo": "备注", |
| | | "orgLoc": "源库位", |
| | | "orgSite": "源站点", |
| | | "targLoc": "目标库位", |
| | | "targSite": "目标站点", |
| | | "barcode": "托盘码" |
| | | }, |
| | | "expand": { |
| | | "title": "任务明细", |
| | | "empty": "暂无任务明细", |
| | | "orderType": "单据类型", |
| | | "wkType": "业务类型", |
| | | "platWorkCode": "工单号", |
| | | "platItemId": "行号", |
| | | "anfme": "数量" |
| | | }, |
| | | "flowStepDialog": { |
| | | "title": "流程步骤", |
| | | "currentTask": "当前任务", |
| | | "flowInstanceNo": "流程实例号", |
| | | "stepCode": "步骤编码", |
| | | "stepName": "步骤名称", |
| | | "stepType": "步骤类型", |
| | | "executeResult": "执行结果", |
| | | "startTime": "开始时间", |
| | | "endTime": "结束时间", |
| | | "timeout": "流程步骤加载超时,已停止等待" |
| | | }, |
| | | "messages": { |
| | | "completeConfirm": "确定完成任务 {code} 吗?", |
| | | "completeSuccess": "任务完成成功", |
| | | "removeConfirm": "确定取消任务 {code} 吗?", |
| | | "removeSuccess": "任务取消成功", |
| | | "checkConfirm": "确定执行盘点出库任务 {code} 吗?", |
| | | "checkSuccess": "盘点出库成功", |
| | | "pickConfirm": "确定执行拣料出库任务 {code} 吗?", |
| | | "pickSuccess": "拣料出库成功", |
| | | "topSuccess": "任务置顶成功", |
| | | "actionFailed": "任务操作失败", |
| | | "autoRunEnabled": "已开启自动下发任务", |
| | | "autoRunPaused": "已暂停自动下发任务", |
| | | "autoRunFailed": "自动下发配置更新失败", |
| | | "detailLoadFailed": "任务明细加载失败", |
| | | "listTimeout": "任务列表加载超时,已停止等待", |
| | | "autoRunTimeout": "自动下发配置加载超时,已停止等待", |
| | | "autoRunOnSuccess": "已开启自动下发任务", |
| | | "autoRunOffSuccess": "已暂停自动下发任务", |
| | | "autoRunUpdateFailed": "自动下发配置更新失败", |
| | | "itemsTimeout": "任务明细加载超时,已停止等待" |
| | | } |
| | | }, |
| | | "basicInfo": { |
| | | "basStationArea": { |
| | | "reportTitle": "站点区域报表", |
| | | "entity": "站点区域", |
| | | "buttons": { |
| | | "add": "新增站点区域", |
| | | "batchDelete": "批量删除" |
| | | }, |
| | | "actions": { |
| | | "add": "新增站点区域" |
| | | }, |
| | | "placeholder": { |
| | | "condition": "请输入站点区域名称/编号/备注", |
| | | "timeStart": "请选择开始时间", |
| | | "timeEnd": "请选择结束时间", |
| | | "stationAreaName": "请输入站点区域名称", |
| | | "stationAreaId": "请输入站点区域编号", |
| | | "crossZoneArea": "请输入跨区区域", |
| | | "wcsData": "请输入WCS数据", |
| | | "containerType": "请输入容器类型", |
| | | "barcode": "请输入条码", |
| | | "stationAlias": "请输入站点别名", |
| | | "memo": "请输入备注" |
| | | }, |
| | | "search": { |
| | | "condition": "关键字", |
| | | "conditionPlaceholder": "请输入站点区域名称/编号/备注", |
| | | "timeStart": "开始时间", |
| | | "timeStartPlaceholder": "请选择开始时间", |
| | | "timeEnd": "结束时间", |
| | | "timeEndPlaceholder": "请选择结束时间", |
| | | "stationAreaName": "站点区域名称", |
| | | "stationAreaNamePlaceholder": "请输入站点区域名称", |
| | | "stationAreaId": "站点区域编号", |
| | | "stationAreaIdPlaceholder": "请输入站点区域编号", |
| | | "type": "站点类型", |
| | | "area": "所属库区", |
| | | "useStatus": "使用状态", |
| | | "inAble": "可入", |
| | | "outAble": "可出", |
| | | "isCrossZone": "是否跨区", |
| | | "crossZoneArea": "跨区区域", |
| | | "crossZoneAreaPlaceholder": "请输入跨区区域", |
| | | "isWcs": "是否WCS", |
| | | "wcsData": "WCS数据", |
| | | "wcsDataPlaceholder": "请输入WCS数据", |
| | | "containerType": "容器类型", |
| | | "containerTypePlaceholder": "请输入容器类型", |
| | | "autoTransfer": "自动调拨", |
| | | "barcode": "条码", |
| | | "barcodePlaceholder": "请输入条码", |
| | | "stationAlias": "站点别名", |
| | | "stationAliasPlaceholder": "请输入站点别名", |
| | | "status": "状态", |
| | | "memo": "备注", |
| | | "memoPlaceholder": "请输入备注" |
| | | }, |
| | | "type": { |
| | | "smart": "智能站点", |
| | | "normal": "普通站点" |
| | | }, |
| | | "table": { |
| | | "crossZoneArea": "跨区区域", |
| | | "inAble": "可入", |
| | | "outAble": "可出", |
| | | "isCrossZone": "是否跨区" |
| | | }, |
| | | "detail": { |
| | | "title": "站点区域详情", |
| | | "baseInfo": "基础信息", |
| | | "auditInfo": "审计信息", |
| | | "stationAreaName": "站点区域名称", |
| | | "stationAreaId": "站点区域编号", |
| | | "type": "站点类型", |
| | | "area": "所属库区", |
| | | "crossZoneArea": "可跨区库区", |
| | | "containerType": "容器类型", |
| | | "stationAlias": "站点别名", |
| | | "inAble": "可入", |
| | | "outAble": "可出", |
| | | "isCrossZone": "是否跨区", |
| | | "isWcs": "是否WCS", |
| | | "autoTransfer": "自动调拨", |
| | | "useStatus": "使用状态", |
| | | "barcode": "条码", |
| | | "status": "状态", |
| | | "wcsData": "WCS数据", |
| | | "memo": "备注", |
| | | "createBy": "创建人", |
| | | "createTime": "创建时间", |
| | | "updateBy": "更新人", |
| | | "updateTime": "更新时间" |
| | | }, |
| | | "dialog": { |
| | | "titleAdd": "新增站点区域", |
| | | "titleEdit": "编辑站点区域", |
| | | "stationAreaName": "站点区域名称", |
| | | "stationAreaId": "站点区域编号", |
| | | "type": "站点类型", |
| | | "area": "所属库区", |
| | | "crossZoneArea": "可跨区库区", |
| | | "containerType": "容器类型", |
| | | "stationAlias": "站点别名", |
| | | "inAble": "可入", |
| | | "outAble": "可出", |
| | | "isCrossZone": "是否跨区", |
| | | "isWcs": "是否WCS", |
| | | "autoTransfer": "自动调拨", |
| | | "useStatus": "使用状态", |
| | | "wcsData": "WCS数据", |
| | | "barcode": "条码", |
| | | "status": "状态", |
| | | "memo": "备注", |
| | | "validation": { |
| | | "stationAreaName": "请输入站点区域名称", |
| | | "stationAreaId": "请输入站点区域编号", |
| | | "type": "请选择站点类型", |
| | | "area": "请选择所属库区", |
| | | "containerType": "请选择容器类型", |
| | | "stationAlias": "请选择站点别名" |
| | | } |
| | | }, |
| | | "messages": { |
| | | "detailLoadFailed": "获取站点区域详情失败", |
| | | "detailTimeout": "站点区域详情加载超时,已停止等待", |
| | | "stationAliasTimeout": "站点别名选项加载超时,已停止等待", |
| | | "areaOptionsTimeout": "库区选项加载超时,已停止等待", |
| | | "containerTypeTimeout": "容器类型选项加载超时,已停止等待", |
| | | "useStatusTimeout": "使用状态选项加载超时,已停止等待" |
| | | } |
| | | } |
| | | }, |
| | | "system": { |
| | | "role": { |
| | | "entity": "角色", |
| | | "reportTitle": "角色管理报表", |
| | | "buttons": { |
| | | "add": "新增角色" |
| | | }, |
| | | "search": { |
| | | "name": "角色名称", |
| | | "namePlaceholder": "请输入角色名称", |
| | | "code": "角色编码", |
| | | "codePlaceholder": "请输入角色编码", |
| | | "memo": "备注", |
| | | "memoPlaceholder": "请输入备注", |
| | | "condition": "关键字", |
| | | "conditionPlaceholder": "输入关键字搜索", |
| | | "status": "状态", |
| | | "statusPlaceholder": "请选择状态" |
| | | }, |
| | | "table": { |
| | | "name": "角色名称", |
| | | "code": "角色编码", |
| | | "memo": "备注", |
| | | "status": "状态", |
| | | "updateTime": "更新时间", |
| | | "createTime": "创建时间", |
| | | "operation": "操作" |
| | | }, |
| | | "actions": { |
| | | "scopeMenu": "网页权限", |
| | | "scopePda": "PDA权限", |
| | | "scopeMatnr": "物料权限", |
| | | "scopeWarehouse": "仓库权限", |
| | | "edit": "编辑角色", |
| | | "delete": "删除角色" |
| | | }, |
| | | "scopes": { |
| | | "menu": "网页权限", |
| | | "pda": "PDA权限", |
| | | "matnr": "物料权限", |
| | | "warehouse": "仓库权限" |
| | | }, |
| | | "dialog": { |
| | | "addTitle": "新增角色", |
| | | "editTitle": "编辑角色", |
| | | "validationName": "请输入角色名称", |
| | | "name": "角色名称", |
| | | "namePlaceholder": "请输入角色名称", |
| | | "code": "角色编码", |
| | | "codePlaceholder": "请输入角色编码", |
| | | "status": "状态", |
| | | "statusPlaceholder": "请选择状态", |
| | | "memo": "备注", |
| | | "memoPlaceholder": "请输入备注" |
| | | }, |
| | | "permission": { |
| | | "title": "角色权限", |
| | | "currentRole": "当前角色:", |
| | | "unselected": "未选择角色", |
| | | "selectAll": "全选", |
| | | "clear": "清空", |
| | | "saveCurrent": "保存当前权限", |
| | | "searchPlaceholder": "搜索权限树", |
| | | "authButton": "按钮", |
| | | "scopeLoadTimeout": "{title}加载超时,已停止等待", |
| | | "scopeLoadFailed": "加载{title}失败", |
| | | "saveSuccess": "权限保存成功", |
| | | "saveFailed": "权限保存失败" |
| | | } |
| | | }, |
| | | "menu": { |
| | | "title": "菜单管理", |
| | | "entities": { |
| | | "permission": "权限" |
| | | }, |
| | | "buttons": { |
| | | "add": "添加菜单" |
| | | }, |
| | | "actions": { |
| | | "addAuth": "新增权限", |
| | | "expand": "展开", |
| | | "collapse": "收起" |
| | | }, |
| | | "types": { |
| | | "button": "按钮", |
| | | "directory": "目录", |
| | | "menu": "菜单" |
| | | }, |
| | | "search": { |
| | | "name": "菜单名称", |
| | | "route": "路由地址" |
| | | }, |
| | | "messages": { |
| | | "menuSelfParent": "上级菜单不能选择当前菜单", |
| | | "loadFailed": "获取菜单失败", |
| | | "loadTimeout": "菜单加载超时,已停止等待", |
| | | "submitFailed": "提交失败", |
| | | "authCount": "{count} 个权限标识", |
| | | "deleteMenuConfirm": "确定要删除菜单「{title}」吗?删除后无法恢复", |
| | | "deleteAuthConfirm": "确定要删除权限「{title}」吗?删除后无法恢复" |
| | | }, |
| | | "form": { |
| | | "typeMenu": "菜单", |
| | | "typeButton": "按钮", |
| | | "titleAddMenu": "新建菜单", |
| | | "titleEditMenu": "编辑菜单", |
| | | "titleAddButton": "新建按钮", |
| | | "titleEditButton": "编辑按钮", |
| | | "menuType": "菜单类型", |
| | | "parentId": "上级菜单", |
| | | "nameMenu": "菜单名称", |
| | | "nameButton": "权限名称", |
| | | "route": "路由地址", |
| | | "component": "组件标识", |
| | | "authority": "权限标识", |
| | | "icon": "图标", |
| | | "sort": "排序", |
| | | "status": "状态", |
| | | "memo": "备注", |
| | | "placeholderParent": "请选择上级菜单", |
| | | "placeholderMenuName": "请输入菜单名称", |
| | | "placeholderButtonName": "请输入权限名称", |
| | | "placeholderRoute": "请输入路由地址", |
| | | "placeholderComponent": "请输入组件标识", |
| | | "placeholderAuthority": "请输入权限标识", |
| | | "placeholderIcon": "请输入图标名称", |
| | | "placeholderStatus": "请选择状态", |
| | | "placeholderMemo": "请输入备注", |
| | | "validationMenuName": "请输入菜单名称", |
| | | "validationButtonName": "请输入权限名称", |
| | | "validationRoute": "请输入路由地址", |
| | | "validationAuthority": "请输入权限标识" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | function buildMeta(node) { |
| | | const meta = { |
| | | title: normalizeTitle(node.name || node.meta?.title || '') |
| | | title: normalizeTitle(node.name || node.meta?.title || '', node.component) |
| | | } |
| | | const metaSource = node.meta && typeof node.meta === 'object' ? node.meta : node |
| | | const supportedKeys = [ |
| | |
| | | return meta |
| | | } |
| | | |
| | | function normalizeTitle(title) { |
| | | function normalizeTitle(title, componentKey) { |
| | | if (typeof title !== 'string') { |
| | | return '' |
| | | return resolveBackendMenuTitle('', componentKey) |
| | | } |
| | | return resolveBackendMenuTitle(title) |
| | | return resolveBackendMenuTitle(title, componentKey) |
| | | } |
| | | |
| | | function normalizeIcon(icon) { |
| | |
| | | keepAlive: true, |
| | | roles: ['R_SUPER'], |
| | | authList: [ |
| | | { title: '新增', authMark: 'add' }, |
| | | { title: '编辑', authMark: 'edit' }, |
| | | { title: '删除', authMark: 'delete' } |
| | | { title: 'common.actions.add', authMark: 'add' }, |
| | | { title: 'common.actions.edit', authMark: 'edit' }, |
| | | { title: 'common.actions.delete', authMark: 'delete' } |
| | | ] |
| | | } |
| | | } |
| | |
| | | 'menu.whMat': '库区物料关系' |
| | | } |
| | | |
| | | export function resolveBackendMenuTitle(title) { |
| | | if (typeof title !== 'string') { |
| | | const DASHBOARD_MENU_KEYS = new Set(['menus.dashboard.title', 'menus.dashboard.console']) |
| | | const BACKEND_MENU_TITLE_KEY_MAP = Object.entries(LEGACY_BACKEND_MENU_TITLES).reduce( |
| | | (accumulator, [key, value]) => { |
| | | accumulator[key] = key |
| | | accumulator[value] = key |
| | | return accumulator |
| | | }, |
| | | { |
| | | '仪表盘': 'menus.dashboard.title', |
| | | '工作台': 'menus.dashboard.console', |
| | | 'menus.dashboard.title': 'menus.dashboard.title', |
| | | 'menus.dashboard.console': 'menus.dashboard.console' |
| | | } |
| | | ) |
| | | |
| | | function normalizeComponentMenuKey(componentKey) { |
| | | if (typeof componentKey !== 'string') { |
| | | return '' |
| | | } |
| | | |
| | | const trimmedTitle = title.trim() |
| | | if (!trimmedTitle) { |
| | | const normalizedComponentKey = componentKey.trim() |
| | | if (!normalizedComponentKey) { |
| | | return '' |
| | | } |
| | | |
| | | if (LEGACY_BACKEND_MENU_TITLES[trimmedTitle]) { |
| | | return LEGACY_BACKEND_MENU_TITLES[trimmedTitle] |
| | | if (normalizedComponentKey === 'console') { |
| | | return 'menus.dashboard.console' |
| | | } |
| | | |
| | | if (trimmedTitle.startsWith('menus.')) { |
| | | const legacyMenuKey = `menu.${trimmedTitle.slice('menus.'.length)}` |
| | | if (LEGACY_BACKEND_MENU_TITLES[legacyMenuKey]) { |
| | | return LEGACY_BACKEND_MENU_TITLES[legacyMenuKey] |
| | | } |
| | | return trimmedTitle.split('.').pop() || trimmedTitle |
| | | } |
| | | |
| | | if (trimmedTitle.startsWith('menu.')) { |
| | | return trimmedTitle.split('.').pop() || trimmedTitle |
| | | } |
| | | |
| | | return trimmedTitle |
| | | return `menu.${normalizedComponentKey}` |
| | | } |
| | | |
| | | function normalizeMenuKey(menuKey) { |
| | | if (!menuKey) { |
| | | return '' |
| | | } |
| | | |
| | | if (DASHBOARD_MENU_KEYS.has(menuKey)) { |
| | | return menuKey |
| | | } |
| | | |
| | | if (menuKey.startsWith('menus.')) { |
| | | const leaf = menuKey.slice('menus.'.length) |
| | | const aliasKey = `menu.${leaf}` |
| | | if (Object.prototype.hasOwnProperty.call(LEGACY_BACKEND_MENU_TITLES, aliasKey)) { |
| | | return aliasKey |
| | | } |
| | | } |
| | | |
| | | return menuKey |
| | | } |
| | | |
| | | function containsHan(value) { |
| | | return /[\u3400-\u9fff]/.test(value) |
| | | } |
| | | |
| | | export function resolveBackendMenuTitle(title, componentKey = '') { |
| | | const trimmedTitle = typeof title === 'string' ? title.trim() : '' |
| | | |
| | | if (trimmedTitle) { |
| | | if (trimmedTitle.startsWith('menu.') || trimmedTitle.startsWith('menus.')) { |
| | | const normalizedExistingKey = normalizeMenuKey(trimmedTitle) |
| | | if (normalizedExistingKey) { |
| | | return normalizedExistingKey |
| | | } |
| | | } |
| | | |
| | | const mappedKey = BACKEND_MENU_TITLE_KEY_MAP[trimmedTitle] |
| | | if (mappedKey) { |
| | | return normalizeMenuKey(mappedKey) |
| | | } |
| | | } |
| | | |
| | | const componentMenuKey = normalizeMenuKey(normalizeComponentMenuKey(componentKey)) |
| | | if (componentMenuKey) { |
| | | return componentMenuKey |
| | | } |
| | | |
| | | if (trimmedTitle && !containsHan(trimmedTitle)) { |
| | | return trimmedTitle |
| | | } |
| | | |
| | | return '' |
| | | } |
| | | |
| | | export { LEGACY_BACKEND_MENU_TITLES } |
| | |
| | | } |
| | | const formatMenuTitle = (title) => { |
| | | if (title) { |
| | | if (i18n.global.te(title)) { |
| | | return $t(title) |
| | | } |
| | | if (title.startsWith('menus.') || title.startsWith('menu.')) { |
| | | if (i18n.global.te(title)) { |
| | | return $t(title) |
| | | } else { |
| | | const fallbackTitle = |
| | | title.startsWith('menus.') && title.split('.').pop() |
| | | ? `menu.${title.split('.').pop()}` |
| | | : '' |
| | | if (fallbackTitle && i18n.global.te(fallbackTitle)) { |
| | | return $t(fallbackTitle) |
| | | } |
| | | return title.split('.').pop() || title |
| | | const leaf = title.startsWith('menus.') ? title.slice('menus.'.length) : '' |
| | | const aliasTitle = leaf ? `menu.${leaf}` : '' |
| | | if (aliasTitle && i18n.global.te(aliasTitle)) { |
| | | return $t(aliasTitle) |
| | | } |
| | | return '' |
| | | } |
| | | return title |
| | | } |
| | |
| | | import { ElMessage } from 'element-plus' |
| | | import { $t } from '@/locales' |
| | | |
| | | const DEFAULT_REQUEST_GUARD_TIMEOUT = 8e3 |
| | | const DEFAULT_REQUEST_TIMEOUT_MESSAGE = '请求超时,已停止等待' |
| | | const DEFAULT_REQUEST_TIMEOUT_MESSAGE = () => $t('message.requestTimeoutStopped') |
| | | |
| | | function withRequestGuard(task, fallbackValue, options = {}) { |
| | | const { timeoutMs = DEFAULT_REQUEST_GUARD_TIMEOUT, onFallback } = options |
| | |
| | | function guardRequestWithMessage(task, fallbackValue, options = {}) { |
| | | const { |
| | | timeoutMs = DEFAULT_REQUEST_GUARD_TIMEOUT, |
| | | timeoutMessage = DEFAULT_REQUEST_TIMEOUT_MESSAGE, |
| | | timeoutMessage = DEFAULT_REQUEST_TIMEOUT_MESSAGE(), |
| | | errorMessage, |
| | | resolveErrorMessage |
| | | } = options |
| | |
| | | import { $t } from '@/locales' |
| | | |
| | | const STATUS_META = { |
| | | 1: { text: '正常', type: 'success', bool: true }, |
| | | 0: { text: '冻结', type: 'danger', bool: false } |
| | | 1: { text: $t('common.status.normal'), type: 'success', bool: true }, |
| | | 0: { text: $t('common.status.frozen'), type: 'danger', bool: false } |
| | | } |
| | | |
| | | const TYPE_OPTIONS = [ |
| | | { label: '智能站点', value: 0 }, |
| | | { label: '普通站点', value: 1 } |
| | | { label: $t('pages.basicInfo.basStationArea.type.smart'), value: 0 }, |
| | | { label: $t('pages.basicInfo.basStationArea.type.normal'), value: 1 } |
| | | ] |
| | | |
| | | const BINARY_OPTIONS = [ |
| | | { label: '否', value: 0 }, |
| | | { label: '是', value: 1 } |
| | | { label: $t('common.status.no'), value: 0 }, |
| | | { label: $t('common.status.yes'), value: 1 } |
| | | ] |
| | | |
| | | const STATUS_OPTIONS = [ |
| | | { label: '正常', value: 1 }, |
| | | { label: '冻结', value: 0 } |
| | | { label: $t('common.status.normal'), value: 1 }, |
| | | { label: $t('common.status.frozen'), value: 0 } |
| | | ] |
| | | |
| | | export const BAS_STATION_AREA_REPORT_TITLE = '站点区域报表' |
| | | export const BAS_STATION_AREA_REPORT_TITLE = $t('pages.basicInfo.basStationArea.reportTitle') |
| | | export const BAS_STATION_AREA_REPORT_STYLE = { |
| | | titleAlign: 'center', |
| | | titleLevel: 'strong', |
| | |
| | | } |
| | | |
| | | function normalizeBooleanText(value) { |
| | | if (value === 1 || value === '1' || value === true || value === '是') { |
| | | return '是' |
| | | if (value === 1 || value === '1' || value === true || value === $t('common.status.yes')) { |
| | | return $t('common.status.yes') |
| | | } |
| | | if (value === 0 || value === '0' || value === false || value === '否') { |
| | | return '否' |
| | | if (value === 0 || value === '0' || value === false || value === $t('common.status.no')) { |
| | | return $t('common.status.no') |
| | | } |
| | | return normalizeText(value) || '--' |
| | | return normalizeText(value) || $t('common.placeholder.empty') |
| | | } |
| | | |
| | | function normalizeIdArray(values = []) { |
| | |
| | | }) |
| | | .filter(Boolean) |
| | | |
| | | return labels.length ? labels.join('、') : '--' |
| | | return labels.length ? labels.join($t('common.listSeparator')) : $t('common.placeholder.empty') |
| | | } |
| | | |
| | | function getStatusMeta(status) { |
| | |
| | | if (status === false || Number(status) === 0) { |
| | | return STATUS_META[0] |
| | | } |
| | | return { text: '未知', type: 'info', bool: false } |
| | | return { text: $t('common.status.unknown'), type: 'info', bool: false } |
| | | } |
| | | |
| | | export function createBasStationAreaSearchState() { |
| | |
| | | } |
| | | return { |
| | | value: Number(value), |
| | | label: normalizeText(item.name || item.areaName || item.code || item.areaCode || `库区 ${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 || `站点 ${value}`) |
| | | label: normalizeText(item.stationName || item.stationId || item.name || `${$t('menu.basStation')} ${value}`) |
| | | } |
| | | }) |
| | | .filter(Boolean) |
| | |
| | | return { |
| | | ...record, |
| | | id: normalizeIdValue(record.id), |
| | | stationAreaName: normalizeText(record.stationAreaName) || '--', |
| | | stationAreaId: normalizeText(record.stationAreaId) || '--', |
| | | 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'), |
| | | inAble: normalizeIdValue(record.inAble), |
| | | inAbleText: normalizeBooleanText(record.inAble), |
| | | outAble: normalizeIdValue(record.outAble), |
| | | outAbleText: normalizeBooleanText(record.outAble), |
| | | useStatus: normalizeText(record.useStatus), |
| | | useStatusText: normalizeText(record.useStatus$ || record.useStatusText || resolvers.resolveUseStatusLabel?.(record.useStatus) || record.useStatus) || '--', |
| | | useStatusText: |
| | | 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) || '') || '--', |
| | | areaText: normalizeText(record.area$ || record.areaText || resolvers.resolveAreaLabel?.(areaId) || '') || $t('common.placeholder.empty'), |
| | | isCrossZone: normalizeIdValue(record.isCrossZone), |
| | | isCrossZoneText: normalizeBooleanText(record.isCrossZone), |
| | | crossZoneArea: crossZoneAreaIds, |
| | | crossZoneAreaText: |
| | | resolveOptionText(crossZoneAreaIds, resolvers.resolveCrossZoneAreaLabel, record.crossZoneAreaText || []) || '--', |
| | | resolveOptionText(crossZoneAreaIds, resolvers.resolveCrossZoneAreaLabel, record.crossZoneAreaText || []) || |
| | | $t('common.placeholder.empty'), |
| | | isWcs: normalizeIdValue(record.isWcs), |
| | | isWcsText: normalizeBooleanText(record.isWcs), |
| | | wcsData: normalizeText(record.wcsData) || '--', |
| | | wcsData: normalizeText(record.wcsData) || $t('common.placeholder.empty'), |
| | | containerType: containerTypeIds, |
| | | containerTypeText: |
| | | resolveOptionText(containerTypeIds, resolvers.resolveContainerTypeLabel, record.containerTypesText || []) || '--', |
| | | barcode: normalizeText(record.barcode) || '--', |
| | | 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), |
| | | stationAlias: stationAliasIds, |
| | |
| | | stationAliasIds, |
| | | resolvers.resolveStationAliasLabel, |
| | | stationAliasNames.length ? stationAliasNames : record.stationAliasText || [] |
| | | ) || '--', |
| | | ) || $t('common.placeholder.empty'), |
| | | status: normalizeIdValue(record.status), |
| | | statusText: statusMeta.text, |
| | | statusType: statusMeta.type, |
| | | statusBool: record.statusBool !== void 0 ? Boolean(record.statusBool) : statusMeta.bool, |
| | | memo: normalizeText(record.memo) || '--', |
| | | createByText: normalizeText(record.createBy$ || record.createByText || ''), |
| | | createTimeText: normalizeText(record.createTime$ || record.createTime || ''), |
| | | updateByText: normalizeText(record.updateBy$ || record.updateByText || ''), |
| | | updateTimeText: normalizeText(record.updateTime$ || record.updateTime || '') |
| | | 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') |
| | | } |
| | | } |
| | | |
| | |
| | | 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 { getBasStationAreaStatusOptions } from './basStationAreaPage.helpers' |
| | | |
| | |
| | | canEdit = true, |
| | | canDelete = true |
| | | } = {}) { |
| | | const operations = [{ key: 'view', label: '详情', icon: 'ri:eye-line' }] |
| | | const operations = [{ key: 'view', label: $t('common.actions.detail'), icon: 'ri:eye-line' }] |
| | | |
| | | if (canEdit && handleEdit) { |
| | | operations.push({ key: 'edit', label: '编辑', icon: 'ri:pencil-line' }) |
| | | operations.push({ key: 'edit', label: $t('common.actions.edit'), icon: 'ri:pencil-line' }) |
| | | } |
| | | |
| | | if (canDelete && handleDelete) { |
| | | operations.push({ key: 'delete', label: '删除', 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 [ |
| | |
| | | }, |
| | | { |
| | | type: 'globalIndex', |
| | | label: '序号', |
| | | label: $t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'stationAreaId', |
| | | label: '站点区域编号', |
| | | label: $t('pages.basicInfo.basStationArea.search.stationAreaId'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.stationAreaId || '--' |
| | | }, |
| | | { |
| | | prop: 'stationAreaName', |
| | | label: '站点区域名称', |
| | | label: $t('pages.basicInfo.basStationArea.search.stationAreaName'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.stationAreaName || '--' |
| | | }, |
| | | { |
| | | prop: 'typeText', |
| | | label: '站点类型', |
| | | label: $t('pages.basicInfo.basStationArea.search.type'), |
| | | width: 120, |
| | | align: 'center', |
| | | formatter: (row) => row.typeText || '--' |
| | | }, |
| | | { |
| | | prop: 'areaText', |
| | | label: '所属库区', |
| | | label: $t('pages.basicInfo.basStationArea.search.area'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.areaText || '--' |
| | | }, |
| | | { |
| | | prop: 'crossZoneAreaText', |
| | | label: '可跨区区域', |
| | | label: $t('pages.basicInfo.basStationArea.table.crossZoneArea'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.crossZoneAreaText || '--' |
| | | }, |
| | | { |
| | | prop: 'containerTypeText', |
| | | label: '容器类型', |
| | | label: $t('pages.basicInfo.basStationArea.search.containerType'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.containerTypeText || '--' |
| | | }, |
| | | { |
| | | prop: 'stationAliasText', |
| | | label: '站点别名', |
| | | label: $t('pages.basicInfo.basStationArea.search.stationAlias'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.stationAliasText || '--' |
| | | }, |
| | | { |
| | | prop: 'inAbleText', |
| | | label: '可入', |
| | | label: $t('pages.basicInfo.basStationArea.table.inAble'), |
| | | width: 84, |
| | | align: 'center', |
| | | formatter: (row) => row.inAbleText || '--' |
| | | }, |
| | | { |
| | | prop: 'outAbleText', |
| | | label: '可出', |
| | | label: $t('pages.basicInfo.basStationArea.table.outAble'), |
| | | width: 84, |
| | | align: 'center', |
| | | formatter: (row) => row.outAbleText || '--' |
| | | }, |
| | | { |
| | | prop: 'isCrossZoneText', |
| | | label: '跨区', |
| | | label: $t('pages.basicInfo.basStationArea.table.isCrossZone'), |
| | | width: 84, |
| | | align: 'center', |
| | | formatter: (row) => row.isCrossZoneText || '--' |
| | | }, |
| | | { |
| | | prop: 'isWcsText', |
| | | label: 'WCS', |
| | | label: $t('table.wcs'), |
| | | width: 84, |
| | | align: 'center', |
| | | formatter: (row) => row.isWcsText || '--' |
| | | }, |
| | | { |
| | | prop: 'autoTransferText', |
| | | label: '自动调拨', |
| | | label: $t('pages.basicInfo.basStationArea.search.autoTransfer'), |
| | | width: 100, |
| | | align: 'center', |
| | | formatter: (row) => row.autoTransferText || '--' |
| | | }, |
| | | { |
| | | prop: 'useStatusText', |
| | | label: '使用状态', |
| | | label: $t('pages.basicInfo.basStationArea.search.useStatus'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.useStatusText || '--' |
| | | }, |
| | | { |
| | | prop: 'barcode', |
| | | label: '条码', |
| | | label: $t('pages.basicInfo.basStationArea.search.barcode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.barcode || '--' |
| | | }, |
| | | { |
| | | prop: 'status', |
| | | label: '状态', |
| | | label: $t('pages.basicInfo.basStationArea.search.status'), |
| | | width: 96, |
| | | align: 'center', |
| | | formatter: (row) => { |
| | |
| | | }, |
| | | { |
| | | prop: 'updateTimeText', |
| | | label: '更新时间', |
| | | label: $t('table.updateTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.updateTimeText || '--' |
| | | }, |
| | | { |
| | | prop: 'memo', |
| | | label: '备注', |
| | | label: $t('pages.basicInfo.basStationArea.search.memo'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.memo || '--' |
| | | }, |
| | | { |
| | | prop: 'operation', |
| | | label: '操作', |
| | | label: $t('table.operation'), |
| | | width: 120, |
| | | align: 'center', |
| | | fixed: 'right', |
| | |
| | | <ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData"> |
| | | <template #left> |
| | | <ElSpace wrap> |
| | | <ElButton v-auth="'add'" @click="handleShowDialog('add')" v-ripple |
| | | >新增站点区域</ElButton |
| | | > |
| | | <ElButton v-auth="'add'" @click="handleShowDialog('add')" v-ripple> |
| | | {{ t('pages.basicInfo.basStationArea.actions.add') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-auth="'delete'" |
| | | type="danger" |
| | |
| | | @click="handleBatchDelete" |
| | | v-ripple |
| | | > |
| | | 批量删除 |
| | | {{ t('common.actions.batchDelete') }} |
| | | </ElButton> |
| | | <ListExportPrint |
| | | class="inline-flex" |
| | |
| | | <script setup> |
| | | import { computed, onMounted, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { useI18n } from 'vue-i18n' |
| | | import ListExportPrint from '@/components/biz/list-export-print/index.vue' |
| | | import { useAuth } from '@/hooks/core/useAuth' |
| | | import { useTable } from '@/hooks/core/useTable' |
| | |
| | | |
| | | const { hasAuth } = useAuth() |
| | | const userStore = useUserStore() |
| | | const { t } = useI18n() |
| | | |
| | | const searchForm = ref(createBasStationAreaSearchState()) |
| | | const detailDrawerVisible = ref(false) |
| | |
| | | |
| | | const searchItems = computed(() => [ |
| | | { |
| | | label: '关键字', |
| | | label: t('pages.basicInfo.basStationArea.search.condition'), |
| | | key: 'condition', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入站点区域名称/编号/备注' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.condition') |
| | | } |
| | | }, |
| | | { |
| | | label: '开始时间', |
| | | label: t('pages.basicInfo.basStationArea.search.timeStart'), |
| | | key: 'timeStart', |
| | | type: 'date', |
| | | props: { |
| | | clearable: true, |
| | | type: 'date', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | placeholder: '请选择开始时间' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.timeStart') |
| | | } |
| | | }, |
| | | { |
| | | label: '结束时间', |
| | | label: t('pages.basicInfo.basStationArea.search.timeEnd'), |
| | | key: 'timeEnd', |
| | | type: 'date', |
| | | props: { |
| | | clearable: true, |
| | | type: 'date', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | placeholder: '请选择结束时间' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.timeEnd') |
| | | } |
| | | }, |
| | | { |
| | | label: '站点区域名称', |
| | | label: t('pages.basicInfo.basStationArea.search.stationAreaName'), |
| | | key: 'stationAreaName', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入站点区域名称' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.stationAreaName') |
| | | } |
| | | }, |
| | | { |
| | | label: '站点区域编号', |
| | | label: t('pages.basicInfo.basStationArea.search.stationAreaId'), |
| | | key: 'stationAreaId', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入站点区域编号' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.stationAreaId') |
| | | } |
| | | }, |
| | | { |
| | | label: '站点类型', |
| | | label: t('pages.basicInfo.basStationArea.search.type'), |
| | | key: 'type', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '所属库区', |
| | | label: t('pages.basicInfo.basStationArea.search.area'), |
| | | key: 'area', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '使用状态', |
| | | label: t('pages.basicInfo.basStationArea.search.useStatus'), |
| | | key: 'useStatus', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '可入', |
| | | label: t('pages.basicInfo.basStationArea.search.inAble'), |
| | | key: 'inAble', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '可出', |
| | | label: t('pages.basicInfo.basStationArea.search.outAble'), |
| | | key: 'outAble', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '是否跨区', |
| | | label: t('pages.basicInfo.basStationArea.search.isCrossZone'), |
| | | key: 'isCrossZone', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '跨区区域', |
| | | label: t('pages.basicInfo.basStationArea.search.crossZoneArea'), |
| | | key: 'crossZoneArea', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入跨区区域' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.crossZoneArea') |
| | | } |
| | | }, |
| | | { |
| | | label: '是否WCS', |
| | | label: t('pages.basicInfo.basStationArea.search.isWcs'), |
| | | key: 'isWcs', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: 'WCS数据', |
| | | label: t('pages.basicInfo.basStationArea.search.wcsData'), |
| | | key: 'wcsData', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入WCS数据' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.wcsData') |
| | | } |
| | | }, |
| | | { |
| | | label: '容器类型', |
| | | label: t('pages.basicInfo.basStationArea.search.containerType'), |
| | | key: 'containerType', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入容器类型' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.containerType') |
| | | } |
| | | }, |
| | | { |
| | | label: '自动调拨', |
| | | label: t('pages.basicInfo.basStationArea.search.autoTransfer'), |
| | | key: 'autoTransfer', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '条码', |
| | | label: t('pages.basicInfo.basStationArea.search.barcode'), |
| | | key: 'barcode', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入条码' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.barcode') |
| | | } |
| | | }, |
| | | { |
| | | label: '站点别名', |
| | | label: t('pages.basicInfo.basStationArea.search.stationAlias'), |
| | | key: 'stationAlias', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入站点别名' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.stationAlias') |
| | | } |
| | | }, |
| | | { |
| | | label: '状态', |
| | | label: t('pages.basicInfo.basStationArea.search.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '备注', |
| | | label: t('pages.basicInfo.basStationArea.search.memo'), |
| | | key: 'memo', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入备注' |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.memo') |
| | | } |
| | | } |
| | | ]) |
| | |
| | | fetchBasStationAreaDetail(row.id), |
| | | {}, |
| | | { |
| | | timeoutMessage: '站点区域详情加载超时,已停止等待' |
| | | timeoutMessage: t('pages.basicInfo.basStationArea.messages.detailTimeout') |
| | | } |
| | | ) |
| | | detailData.value = normalizeBasStationAreaDetailRecord(detail, { |
| | |
| | | } catch (error) { |
| | | detailDrawerVisible.value = false |
| | | detailData.value = {} |
| | | ElMessage.error(error?.message || '获取站点区域详情失败') |
| | | ElMessage.error(error?.message || t('pages.basicInfo.basStationArea.messages.detailLoadFailed')) |
| | | } finally { |
| | | detailLoading.value = false |
| | | } |
| | |
| | | ), |
| | | { records: [] }, |
| | | { |
| | | timeoutMessage: '站点别名选项加载超时,已停止等待' |
| | | timeoutMessage: t('pages.basicInfo.basStationArea.messages.stationAliasTimeout') |
| | | } |
| | | ) |
| | | stationOptions.value = resolveBasStationAreaStationOptions( |
| | |
| | | fetchBasStationAreaDetail(row.id), |
| | | {}, |
| | | { |
| | | timeoutMessage: '站点区域详情加载超时,已停止等待' |
| | | timeoutMessage: t('pages.basicInfo.basStationArea.messages.detailTimeout') |
| | | } |
| | | ) |
| | | await handleShowDialog('edit', detail) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '获取站点区域详情失败') |
| | | ElMessage.error(error?.message || t('pages.basicInfo.basStationArea.messages.detailLoadFailed')) |
| | | } |
| | | } |
| | | |
| | |
| | | saveRequest: fetchSaveBasStationArea, |
| | | updateRequest: fetchUpdateBasStationArea, |
| | | deleteRequest: fetchDeleteBasStationArea, |
| | | entityName: '站点区域', |
| | | entityName: t('pages.basicInfo.basStationArea.entity'), |
| | | resolveRecordLabel: (record) => record?.stationAreaName || record?.stationAreaId || record?.id, |
| | | refreshCreate, |
| | | refreshUpdate, |
| | |
| | | |
| | | async function loadAreaOptions() { |
| | | const response = await guardRequestWithMessage(fetchWarehouseAreasList(), [], { |
| | | timeoutMessage: '库区选项加载超时,已停止等待' |
| | | timeoutMessage: t('pages.basicInfo.basStationArea.messages.areaOptionsTimeout') |
| | | }) |
| | | const options = resolveBasStationAreaWarehouseAreaOptions( |
| | | defaultResponseAdapter(response).records |
| | |
| | | status: 1 |
| | | }), |
| | | { records: [] }, |
| | | { timeoutMessage: '容器类型选项加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.basicInfo.basStationArea.messages.containerTypeTimeout') } |
| | | ) |
| | | containerTypeOptions.value = resolveBasStationAreaContainerTypeOptions( |
| | | defaultResponseAdapter(response).records |
| | |
| | | status: 1 |
| | | }), |
| | | { records: [] }, |
| | | { timeoutMessage: '使用状态选项加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.basicInfo.basStationArea.messages.useStatusTimeout') } |
| | | ) |
| | | useStatusOptions.value = resolveBasStationAreaUseStatusOptions( |
| | | defaultResponseAdapter(response).records |
| | |
| | | <template> |
| | | <ElDrawer |
| | | :model-value="visible" |
| | | title="站点区域详情" |
| | | :title="t('pages.basicInfo.basStationArea.detail.title')" |
| | | size="960px" |
| | | destroy-on-close |
| | | @update:model-value="handleVisibleChange" |
| | |
| | | <ElSkeleton :rows="12" animated /> |
| | | </div> |
| | | <div v-else class="space-y-4"> |
| | | <ElDescriptions title="基础信息" :column="2" border> |
| | | <ElDescriptionsItem label="站点区域名称">{{ detail.stationAreaName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="站点区域编号">{{ detail.stationAreaId || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="站点类型">{{ detail.typeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="所属库区">{{ detail.areaText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="可跨区库区" :span="2">{{ detail.crossZoneAreaText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="容器类型" :span="2">{{ detail.containerTypeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="站点别名" :span="2">{{ detail.stationAliasText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="可入">{{ detail.inAbleText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="可出">{{ detail.outAbleText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="是否跨区">{{ detail.isCrossZoneText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="是否WCS">{{ detail.isWcsText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="自动调拨">{{ detail.autoTransferText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="使用状态">{{ detail.useStatusText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="条码">{{ detail.barcode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="状态"> |
| | | <ElDescriptions :title="t('pages.basicInfo.basStationArea.detail.baseInfo')" :column="2" border> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.stationAreaName')">{{ detail.stationAreaName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.stationAreaId')">{{ detail.stationAreaId || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.type')">{{ detail.typeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.area')">{{ detail.areaText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.crossZoneArea')" :span="2">{{ detail.crossZoneAreaText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.containerType')" :span="2">{{ detail.containerTypeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.stationAlias')" :span="2">{{ detail.stationAliasText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.inAble')">{{ detail.inAbleText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.outAble')">{{ detail.outAbleText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.isCrossZone')">{{ detail.isCrossZoneText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.isWcs')">{{ detail.isWcsText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.autoTransfer')">{{ detail.autoTransferText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.useStatus')">{{ detail.useStatusText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.barcode')">{{ detail.barcode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.status')"> |
| | | <ElTag :type="detail.statusType || 'info'" effect="light"> |
| | | {{ detail.statusText || '--' }} |
| | | </ElTag> |
| | | </ElDescriptionsItem> |
| | | <ElDescriptionsItem label="WCS数据" :span="2">{{ detail.wcsData || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="备注" :span="2">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.wcsData')" :span="2">{{ detail.wcsData || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.memo')" :span="2">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | |
| | | <ElDescriptions title="审计信息" :column="2" border> |
| | | <ElDescriptionsItem label="创建人">{{ detail.createByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="创建时间">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="更新人">{{ detail.updateByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="更新时间">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptions :title="t('pages.basicInfo.basStationArea.detail.auditInfo')" :column="2" border> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.createBy')">{{ detail.createByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.createTime')">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.updateBy')">{{ detail.updateByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.basicInfo.basStationArea.detail.updateTime')">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | </div> |
| | | </ElScrollbar> |
| | |
| | | |
| | | <script setup> |
| | | import { computed } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | |
| | | const props = defineProps({ |
| | | visible: { type: Boolean, default: false }, |
| | |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible']) |
| | | const { t } = useI18n() |
| | | |
| | | const visible = computed({ |
| | | get: () => props.visible, |
| | |
| | | visible.value = value |
| | | } |
| | | </script> |
| | | |
| | |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">取消</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">确定</ElButton> |
| | | <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">{{ t('common.confirm') }}</ElButton> |
| | | </span> |
| | | </template> |
| | | </ElDialog> |
| | |
| | | |
| | | <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 { |
| | | buildBasStationAreaDialogModel, |
| | |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | | const { t } = useI18n() |
| | | const formRef = ref() |
| | | const form = reactive(createBasStationAreaFormState()) |
| | | |
| | | const isEdit = computed(() => props.dialogType === 'edit') |
| | | const dialogTitle = computed(() => (isEdit.value ? '编辑站点区域' : '新增站点区域')) |
| | | const dialogTitle = computed(() => |
| | | t(isEdit.value ? 'pages.basicInfo.basStationArea.dialog.titleEdit' : 'pages.basicInfo.basStationArea.dialog.titleAdd') |
| | | ) |
| | | |
| | | const rules = computed(() => ({ |
| | | stationAreaName: [{ required: true, message: '请输入站点区域名称', trigger: 'blur' }], |
| | | stationAreaId: [{ required: true, message: '请输入站点区域编号', trigger: 'blur' }], |
| | | type: [{ required: true, message: '请选择站点类型', trigger: 'change' }], |
| | | area: [{ required: true, message: '请选择所属库区', trigger: 'change' }], |
| | | containerType: [{ type: 'array', required: true, message: '请选择容器类型', trigger: 'change' }], |
| | | stationAlias: [{ type: 'array', required: true, message: '请选择站点别名', 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' }], |
| | | 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' }] |
| | | })) |
| | | |
| | | const formItems = computed(() => [ |
| | | { |
| | | label: '站点区域名称', |
| | | label: t('pages.basicInfo.basStationArea.dialog.stationAreaName'), |
| | | key: 'stationAreaName', |
| | | type: 'input', |
| | | props: { |
| | | placeholder: '请输入站点区域名称', |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.stationAreaName'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: '站点区域编号', |
| | | label: t('pages.basicInfo.basStationArea.dialog.stationAreaId'), |
| | | key: 'stationAreaId', |
| | | type: 'input', |
| | | props: { |
| | | placeholder: '请输入站点区域编号', |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.stationAreaId'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: '站点类型', |
| | | label: t('pages.basicInfo.basStationArea.dialog.type'), |
| | | key: 'type', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择站点类型', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.type'), |
| | | clearable: true, |
| | | options: getBasStationAreaTypeOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: '所属库区', |
| | | label: t('pages.basicInfo.basStationArea.dialog.area'), |
| | | key: 'area', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择所属库区', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.area'), |
| | | clearable: true, |
| | | filterable: true, |
| | | options: props.areaOptions || [] |
| | | } |
| | | }, |
| | | { |
| | | label: '可跨区库区', |
| | | label: t('pages.basicInfo.basStationArea.dialog.crossZoneArea'), |
| | | key: 'crossZoneArea', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | placeholder: '请选择可跨区库区', |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.crossZoneArea'), |
| | | clearable: true, |
| | | multiple: true, |
| | | collapseTags: true, |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '容器类型', |
| | | label: t('pages.basicInfo.basStationArea.dialog.containerType'), |
| | | key: 'containerType', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | placeholder: '请选择容器类型', |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.containerType'), |
| | | clearable: true, |
| | | multiple: true, |
| | | collapseTags: true, |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '站点别名', |
| | | label: t('pages.basicInfo.basStationArea.dialog.stationAlias'), |
| | | key: 'stationAlias', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | placeholder: '请选择站点别名', |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.stationAlias'), |
| | | clearable: true, |
| | | multiple: true, |
| | | collapseTags: true, |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '可入', |
| | | label: t('pages.basicInfo.basStationArea.dialog.inAble'), |
| | | key: 'inAble', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择可入', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.inAble'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: '可出', |
| | | label: t('pages.basicInfo.basStationArea.dialog.outAble'), |
| | | key: 'outAble', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择可出', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.outAble'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: '是否跨区', |
| | | label: t('pages.basicInfo.basStationArea.dialog.isCrossZone'), |
| | | key: 'isCrossZone', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择是否跨区', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.isCrossZone'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: '是否WCS', |
| | | label: t('pages.basicInfo.basStationArea.dialog.isWcs'), |
| | | key: 'isWcs', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择是否WCS', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.isWcs'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: '自动调拨', |
| | | label: t('pages.basicInfo.basStationArea.dialog.autoTransfer'), |
| | | key: 'autoTransfer', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择自动调拨', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.autoTransfer'), |
| | | clearable: true, |
| | | options: getBasStationAreaBinaryOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: '使用状态', |
| | | label: t('pages.basicInfo.basStationArea.dialog.useStatus'), |
| | | key: 'useStatus', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择使用状态', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.useStatus'), |
| | | clearable: true, |
| | | filterable: true, |
| | | options: props.useStatusOptions || [] |
| | | } |
| | | }, |
| | | { |
| | | label: 'WCS数据', |
| | | label: t('pages.basicInfo.basStationArea.dialog.wcsData'), |
| | | key: 'wcsData', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | type: 'textarea', |
| | | rows: 3, |
| | | placeholder: '请输入WCS数据', |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.wcsData'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: '条码', |
| | | label: t('pages.basicInfo.basStationArea.dialog.barcode'), |
| | | key: 'barcode', |
| | | type: 'input', |
| | | props: { |
| | | placeholder: '请输入条码', |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.barcode'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: '状态', |
| | | label: t('pages.basicInfo.basStationArea.dialog.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择状态', |
| | | placeholder: t('pages.basicInfo.basStationArea.search.status'), |
| | | clearable: true, |
| | | options: getBasStationAreaStatusOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: '备注', |
| | | label: t('pages.basicInfo.basStationArea.dialog.memo'), |
| | | key: 'memo', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | type: 'textarea', |
| | | rows: 3, |
| | | placeholder: '请输入备注', |
| | | placeholder: t('pages.basicInfo.basStationArea.placeholder.memo'), |
| | | clearable: true |
| | | } |
| | | } |
| | |
| | | { deep: true } |
| | | ) |
| | | </script> |
| | | |
| | |
| | | :loading="autoRunLoading" |
| | | @click="handleToggleAutoRun(true)" |
| | | > |
| | | 自动下发任务 |
| | | {{ t('pages.task.buttons.autoRun') }} |
| | | </ElButton> |
| | | <ElButton |
| | | v-else |
| | |
| | | :loading="autoRunLoading" |
| | | @click="handleToggleAutoRun(false)" |
| | | > |
| | | 暂停自动下发 |
| | | {{ t('pages.task.buttons.pauseAutoRun') }} |
| | | </ElButton> |
| | | </ElSpace> |
| | | </template> |
| | |
| | | <script setup> |
| | | import { ElMessage } from 'element-plus' |
| | | import { computed, h, onMounted, onUnmounted, reactive, ref } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { useTableColumns } from '@/hooks/core/useTableColumns' |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { |
| | |
| | | } from './taskPage.helpers' |
| | | |
| | | defineOptions({ name: 'Task' }) |
| | | const { t } = useI18n() |
| | | |
| | | const loading = ref(false) |
| | | const tableData = ref([]) |
| | |
| | | |
| | | const searchItems = computed(() => [ |
| | | { |
| | | label: '关键字', |
| | | label: t('pages.task.search.condition'), |
| | | key: 'condition', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: '请输入任务号/库位/托盘码' } |
| | | props: { clearable: true, placeholder: t('pages.task.placeholder.condition') } |
| | | }, |
| | | { |
| | | label: '任务号', |
| | | label: t('pages.task.search.taskCode'), |
| | | key: 'taskCode', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: '请输入任务号' } |
| | | props: { clearable: true, placeholder: t('pages.task.placeholder.taskCode') } |
| | | }, |
| | | { |
| | | label: '源库位', |
| | | label: t('pages.task.search.orgLoc'), |
| | | key: 'orgLoc', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: '请输入源库位' } |
| | | props: { clearable: true, placeholder: t('pages.task.placeholder.orgLoc') } |
| | | }, |
| | | { |
| | | label: '目标库位', |
| | | label: t('pages.task.search.targLoc'), |
| | | key: 'targLoc', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: '请输入目标库位' } |
| | | props: { clearable: true, placeholder: t('pages.task.placeholder.targLoc') } |
| | | }, |
| | | { |
| | | label: '托盘码', |
| | | label: t('pages.task.search.barcode'), |
| | | key: 'barcode', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: '请输入托盘码' } |
| | | props: { clearable: true, placeholder: t('pages.task.placeholder.barcode') } |
| | | } |
| | | ]) |
| | | |
| | | const detailColumns = computed(() => [ |
| | | { |
| | | type: 'globalIndex', |
| | | label: '序号', |
| | | label: t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'orderTypeLabel', |
| | | label: '单据类型', |
| | | label: t('pages.orders.delivery.detail.type'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'wkTypeLabel', |
| | | label: '业务类型', |
| | | label: t('pages.orders.delivery.detail.wkType'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'platWorkCode', |
| | | label: '工单号', |
| | | label: t('pages.orders.transfer.detail.relatedCode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'platItemId', |
| | | label: '行号', |
| | | label: t('pages.orders.delivery.table.platItemId'), |
| | | minWidth: 100, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'matnrCode', |
| | | label: '物料编码', |
| | | label: t('pages.orders.delivery.table.matnrCode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'maktx', |
| | | label: '物料名称', |
| | | label: t('pages.orders.delivery.table.maktx'), |
| | | minWidth: 220, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'batch', |
| | | label: '批次', |
| | | label: t('table.batch'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'unit', |
| | | label: '单位', |
| | | label: t('table.unit'), |
| | | width: 100 |
| | | }, |
| | | { |
| | | prop: 'anfme', |
| | | label: '数量', |
| | | label: t('pages.orders.delivery.table.anfme'), |
| | | width: 100, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'updateByText', |
| | | label: '更新人', |
| | | label: t('pages.orders.delivery.detail.updateBy'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'updateTimeText', |
| | | label: '更新时间', |
| | | label: t('pages.orders.delivery.detail.updateTime'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | } |
| | |
| | | } |
| | | |
| | | if (action.key === 'complete') { |
| | | await confirmTaskAction(`确定完成任务 ${row.taskCode || ''} 吗?`) |
| | | await confirmTaskAction(t('pages.task.messages.completeConfirm', { code: row.taskCode || '' })) |
| | | await fetchCompleteTask(row.id) |
| | | ElMessage.success('任务完成成功') |
| | | ElMessage.success(t('pages.task.messages.completeSuccess')) |
| | | } else if (action.key === 'remove') { |
| | | await confirmTaskAction(`确定取消任务 ${row.taskCode || ''} 吗?`) |
| | | await confirmTaskAction(t('pages.task.messages.removeConfirm', { code: row.taskCode || '' })) |
| | | await fetchRemoveTask(row.id) |
| | | ElMessage.success('任务取消成功') |
| | | ElMessage.success(t('pages.task.messages.removeSuccess')) |
| | | } else if (action.key === 'check') { |
| | | await confirmTaskAction(`确定执行盘点出库任务 ${row.taskCode || ''} 吗?`) |
| | | await confirmTaskAction(t('pages.task.messages.checkConfirm', { code: row.taskCode || '' })) |
| | | await fetchCheckTask(row.id) |
| | | ElMessage.success('盘点出库成功') |
| | | ElMessage.success(t('pages.task.messages.checkSuccess')) |
| | | } else if (action.key === 'pick') { |
| | | await confirmTaskAction(`确定执行拣料出库任务 ${row.taskCode || ''} 吗?`) |
| | | await confirmTaskAction(t('pages.task.messages.pickConfirm', { code: row.taskCode || '' })) |
| | | await fetchPickTask(row.id) |
| | | ElMessage.success('拣料出库成功') |
| | | ElMessage.success(t('pages.task.messages.pickSuccess')) |
| | | } else if (action.key === 'top') { |
| | | await fetchTopTask(row.id) |
| | | ElMessage.success('任务置顶成功') |
| | | ElMessage.success(t('pages.task.messages.topSuccess')) |
| | | } |
| | | |
| | | await loadPageData() |
| | |
| | | if (error === 'cancel') { |
| | | return |
| | | } |
| | | ElMessage.error(error?.message || '任务操作失败') |
| | | ElMessage.error(error?.message || t('pages.task.messages.actionFailed')) |
| | | } |
| | | } |
| | | |
| | |
| | | current: pagination.current, |
| | | size: pagination.size |
| | | }, |
| | | { timeoutMessage: '任务列表加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.task.messages.listTimeout') } |
| | | ) |
| | | tableData.value = Array.isArray(response?.records) |
| | | ? response.records.map((record) => normalizeTaskRow(record)) |
| | |
| | | autoRunLoading.value = true |
| | | try { |
| | | const response = await guardRequestWithMessage(fetchTaskAutoRunFlag(), { val: false }, { |
| | | timeoutMessage: '自动下发配置加载超时,已停止等待' |
| | | timeoutMessage: t('pages.task.messages.autoRunTimeout') |
| | | }) |
| | | const rawValue = response?.val |
| | | autoRunEnabled.value = |
| | |
| | | try { |
| | | await fetchUpdateTaskAutoRunFlag(enabled) |
| | | autoRunEnabled.value = enabled |
| | | ElMessage.success(enabled ? '已开启自动下发任务' : '已暂停自动下发任务') |
| | | ElMessage.success(enabled ? t('pages.task.messages.autoRunOnSuccess') : t('pages.task.messages.autoRunOffSuccess')) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '自动下发配置更新失败') |
| | | ElMessage.error(error?.message || t('pages.task.messages.autoRunUpdateFailed')) |
| | | } finally { |
| | | autoRunLoading.value = false |
| | | } |
| | |
| | | current: detailPagination.current, |
| | | size: detailPagination.size |
| | | }, |
| | | { timeoutMessage: '任务明细加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.task.messages.itemsTimeout') } |
| | | ) |
| | | |
| | | detailData.value = normalizeTaskRow(activeTaskRow.value) |
| | |
| | | updatePaginationState(detailPagination, taskItemResponse, detailPagination.current, detailPagination.size) |
| | | } catch (error) { |
| | | detailTableData.value = [] |
| | | ElMessage.error(error?.message || '任务明细加载失败') |
| | | ElMessage.error(error?.message || t('pages.task.messages.detailLoadFailed')) |
| | | } finally { |
| | | detailLoading.value = false |
| | | } |
| | |
| | | <template> |
| | | <ElDrawer |
| | | :model-value="visible" |
| | | title="任务详情" |
| | | :title="t('pages.task.detail.title')" |
| | | size="85%" |
| | | @update:model-value="handleVisibleChange" |
| | | > |
| | |
| | | <ElCard shadow="never" class="border border-[var(--el-border-color-lighter)]"> |
| | | <template #header> |
| | | <div class="flex items-center justify-between"> |
| | | <span class="font-medium text-[var(--art-text-gray-900)]">任务基础信息</span> |
| | | <span class="font-medium text-[var(--art-text-gray-900)]">{{ t('pages.task.detail.baseInfo') }}</span> |
| | | <ElTag size="small" effect="plain" type="primary"> |
| | | {{ detail.taskCode || '--' }} |
| | | </ElTag> |
| | |
| | | </template> |
| | | |
| | | <ElDescriptions :column="2" border> |
| | | <ElDescriptionsItem label="任务状态">{{ detail.taskStatusLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="任务类型">{{ detail.taskTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="设备类型">{{ detail.warehTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="优先级">{{ detail.sort ?? '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="状态">{{ detail.statusText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="机器人编码">{{ detail.robotCode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="创建时间">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="更新时间">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="备注" :span="2">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.taskStatus')">{{ detail.taskStatusLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.taskType')">{{ detail.taskTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.warehType')">{{ detail.warehTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.priority')">{{ detail.sort ?? '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.status')">{{ detail.statusText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.robotCode')">{{ detail.robotCode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.createTime')">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.updateTime')">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.memo')" :span="2">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | </ElCard> |
| | | |
| | | <ElCard shadow="never" class="border border-[var(--el-border-color-lighter)]"> |
| | | <template #header> |
| | | <div class="flex items-center justify-between"> |
| | | <span class="font-medium text-[var(--art-text-gray-900)]">执行路径</span> |
| | | <ElButton text type="primary" @click="$emit('flow-step')">流程步骤</ElButton> |
| | | <span class="font-medium text-[var(--art-text-gray-900)]">{{ t('pages.task.detail.pathInfo') }}</span> |
| | | <ElButton text type="primary" @click="$emit('flow-step')">{{ t('pages.task.detail.flowStep') }}</ElButton> |
| | | </div> |
| | | </template> |
| | | |
| | | <ElDescriptions :column="1" border> |
| | | <ElDescriptionsItem label="源库位">{{ detail.orgLoc || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="源站点">{{ detail.orgSiteLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="目标库位">{{ detail.targLoc || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="目标站点">{{ detail.targSiteLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="托盘码">{{ detail.barcode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.orgLoc')">{{ detail.orgLoc || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.orgSite')">{{ detail.orgSiteLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.targLoc')">{{ detail.targLoc || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.targSite')">{{ detail.targSiteLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.task.detail.barcode')">{{ detail.barcode || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | </ElCard> |
| | | </div> |
| | | |
| | | <div class="flex items-center justify-between"> |
| | | <div> |
| | | <div class="text-sm font-medium text-[var(--art-text-gray-900)]">任务明细</div> |
| | | <div class="text-sm font-medium text-[var(--art-text-gray-900)]">{{ t('pages.task.detail.items') }}</div> |
| | | <div class="mt-1 text-xs text-[var(--art-text-gray-500)]"> |
| | | 查看当前任务关联的业务单据、物料和执行记录 |
| | | {{ t('pages.task.detail.itemsHint') }} |
| | | </div> |
| | | </div> |
| | | <div class="flex items-center gap-2"> |
| | | <ElButton :loading="loading" @click="$emit('refresh')">刷新</ElButton> |
| | | <ElButton :loading="loading" @click="$emit('refresh')">{{ t('common.actions.refresh') }}</ElButton> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useI18n } from 'vue-i18n' |
| | | |
| | | const { t } = useI18n() |
| | | |
| | | defineProps({ |
| | | visible: { type: Boolean, default: false }, |
| | | loading: { type: Boolean, default: false }, |
| | |
| | | <template> |
| | | <div class="rounded-xl bg-[var(--el-fill-color-blank)] px-4 py-4"> |
| | | <div class="mb-3 flex items-center justify-between"> |
| | | <div class="text-sm font-medium text-[var(--art-gray-900)]">任务明细</div> |
| | | <ElButton text size="small" :loading="loading" @click="loadData">刷新</ElButton> |
| | | <div class="text-sm font-medium text-[var(--art-gray-900)]">{{ t('pages.task.expand.title') }}</div> |
| | | <ElButton text size="small" :loading="loading" @click="loadData">{{ t('common.actions.refresh') }}</ElButton> |
| | | </div> |
| | | |
| | | <ArtTable |
| | | :loading="loading" |
| | | :data="rows" |
| | | :columns="columns" |
| | | empty-text="暂无任务明细" |
| | | :empty-text="t('pages.task.expand.empty')" |
| | | :empty-height="'220px'" |
| | | /> |
| | | </div> |
| | |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, watch } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { fetchTaskItemPage } from '@/api/task' |
| | | import { normalizeTaskItemRow } from '../taskPage.helpers' |
| | |
| | | |
| | | const loading = ref(false) |
| | | const rows = ref([]) |
| | | const { t } = useI18n() |
| | | |
| | | const columns = [ |
| | | { |
| | | type: 'globalIndex', |
| | | label: '序号', |
| | | label: t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'orderTypeLabel', |
| | | label: '单据类型', |
| | | label: t('pages.task.expand.orderType'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'wkTypeLabel', |
| | | label: '业务类型', |
| | | label: t('pages.task.expand.wkType'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'platWorkCode', |
| | | label: '工单号', |
| | | label: t('pages.task.expand.platWorkCode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'platItemId', |
| | | label: '行号', |
| | | label: t('pages.task.expand.platItemId'), |
| | | minWidth: 100, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'matnrCode', |
| | | label: '物料编码', |
| | | label: t('table.materialCode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'maktx', |
| | | label: '物料名称', |
| | | label: t('table.materialName'), |
| | | minWidth: 220, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'batch', |
| | | label: '批次', |
| | | label: t('table.batch'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'unit', |
| | | label: '单位', |
| | | label: t('table.unit'), |
| | | width: 100 |
| | | }, |
| | | { |
| | | prop: 'anfme', |
| | | label: '数量', |
| | | label: t('pages.task.expand.anfme'), |
| | | width: 100, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'updateByText', |
| | | label: '更新人', |
| | | label: t('table.updateBy'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'updateTimeText', |
| | | label: '更新时间', |
| | | label: t('table.updateTime'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | } |
| | |
| | | pageSize: 50 |
| | | }), |
| | | { records: [] }, |
| | | { timeoutMessage: '任务明细加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.task.messages.itemsTimeout') } |
| | | ) |
| | | rows.value = Array.isArray(response?.records) |
| | | ? response.records.map((record) => normalizeTaskItemRow(record)) |
| | |
| | | width="80%" |
| | | top="6vh" |
| | | destroy-on-close |
| | | title="流程步骤" |
| | | :title="t('pages.task.flowStepDialog.title')" |
| | | @update:model-value="emit('update:visible', $event)" |
| | | > |
| | | <div class="flex flex-col gap-4"> |
| | | <div class="rounded-xl border border-[var(--el-border-color-lighter)] bg-[var(--el-fill-color-blank)] px-4 py-3"> |
| | | <div class="text-sm text-[var(--art-gray-500)]">当前任务</div> |
| | | <div class="text-sm text-[var(--art-gray-500)]">{{ t('pages.task.flowStepDialog.currentTask') }}</div> |
| | | <div class="mt-1 flex flex-wrap items-center gap-x-6 gap-y-2 text-sm text-[var(--art-gray-900)]"> |
| | | <span>任务号:{{ taskRow?.taskCode || '--' }}</span> |
| | | <span>任务状态:{{ taskRow?.taskStatusLabel || '--' }}</span> |
| | | <span>任务类型:{{ taskRow?.taskTypeLabel || '--' }}</span> |
| | | <span>{{ t('pages.task.detail.taskCode') }}:{{ taskRow?.taskCode || '--' }}</span> |
| | | <span>{{ t('pages.task.detail.taskStatus') }}:{{ taskRow?.taskStatusLabel || '--' }}</span> |
| | | <span>{{ t('pages.task.detail.taskType') }}:{{ taskRow?.taskTypeLabel || '--' }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | |
| | | <script setup> |
| | | import { computed, reactive, ref, watch } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { fetchFlowStepInstancePage } from '@/api/flow-step-instance' |
| | | import { normalizeFlowStepInstanceRow } from '@/views/system/flow-step-instance/flowStepInstancePage.helpers' |
| | |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible']) |
| | | const { t } = useI18n() |
| | | |
| | | const loading = ref(false) |
| | | const rows = ref([]) |
| | |
| | | const columns = computed(() => [ |
| | | { |
| | | type: 'globalIndex', |
| | | label: '序号', |
| | | label: t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'flowInstanceNo', |
| | | label: '流程实例号', |
| | | label: t('pages.task.flowStepDialog.flowInstanceNo'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'stepCode', |
| | | label: '步骤编码', |
| | | label: t('pages.task.flowStepDialog.stepCode'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'stepName', |
| | | label: '步骤名称', |
| | | label: t('pages.task.flowStepDialog.stepName'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'stepType', |
| | | label: '步骤类型', |
| | | label: t('pages.task.flowStepDialog.stepType'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'executeResult', |
| | | label: '执行结果', |
| | | label: t('pages.task.flowStepDialog.executeResult'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'statusText', |
| | | label: '状态', |
| | | label: t('table.status'), |
| | | width: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'startTimeText', |
| | | label: '开始时间', |
| | | label: t('pages.task.flowStepDialog.startTime'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'endTimeText', |
| | | label: '结束时间', |
| | | label: t('pages.task.flowStepDialog.endTime'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | } |
| | |
| | | current: pagination.current, |
| | | size: pagination.size |
| | | }, |
| | | { timeoutMessage: '流程步骤加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.task.flowStepDialog.timeout') } |
| | | ) |
| | | rows.value = Array.isArray(response?.records) |
| | | ? response.records.map((record) => normalizeFlowStepInstanceRow(record)) |
| | |
| | | import { ElMessageBox } from 'element-plus' |
| | | import { $t } from '@/locales' |
| | | |
| | | function normalizeText(value) { |
| | | return String(value ?? '').trim() |
| | |
| | | return [ |
| | | { |
| | | key: 'view', |
| | | label: '查看详情', |
| | | label: $t('pages.task.actions.view'), |
| | | icon: 'ri:eye-line' |
| | | }, |
| | | { |
| | | key: 'flowStep', |
| | | label: '流程步骤', |
| | | label: $t('pages.task.actions.flowStep'), |
| | | icon: 'ri:node-tree' |
| | | }, |
| | | ...(row.canComplete |
| | | ? [ |
| | | { |
| | | key: 'complete', |
| | | label: '完成任务', |
| | | label: $t('pages.task.actions.complete'), |
| | | icon: 'ri:checkbox-circle-line', |
| | | auth: 'update' |
| | | } |
| | |
| | | ? [ |
| | | { |
| | | key: 'check', |
| | | label: '盘点出库', |
| | | label: $t('pages.task.actions.check'), |
| | | icon: 'ri:file-check-line', |
| | | auth: 'update' |
| | | } |
| | |
| | | ? [ |
| | | { |
| | | key: 'pick', |
| | | label: '拣料出库', |
| | | label: $t('pages.task.actions.pick'), |
| | | icon: 'ri:paint-line', |
| | | auth: 'update' |
| | | } |
| | |
| | | ? [ |
| | | { |
| | | key: 'top', |
| | | label: '任务置顶', |
| | | label: $t('pages.task.actions.top'), |
| | | icon: 'ri:pushpin-line', |
| | | auth: 'update' |
| | | } |
| | |
| | | ? [ |
| | | { |
| | | key: 'remove', |
| | | label: '取消任务', |
| | | label: $t('pages.task.actions.remove'), |
| | | icon: 'ri:close-circle-line', |
| | | color: '#f56c6c', |
| | | auth: 'delete' |
| | |
| | | } |
| | | |
| | | export async function confirmTaskAction(message) { |
| | | await ElMessageBox.confirm(message, '提示', { |
| | | await ElMessageBox.confirm(message, $t('crud.confirm.deleteTitle'), { |
| | | type: 'warning', |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消' |
| | | confirmButtonText: $t('common.confirm'), |
| | | cancelButtonText: $t('common.cancel') |
| | | }) |
| | | } |
| | |
| | | import { h } from 'vue' |
| | | import { $t } from '@/locales' |
| | | import ArtButtonMore from '@/components/core/forms/art-button-more/index.vue' |
| | | import { getTaskActionList } from './taskPage.helpers' |
| | | |
| | |
| | | : []), |
| | | { |
| | | prop: 'taskCode', |
| | | label: '任务号', |
| | | label: $t('pages.task.search.taskCode'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'taskStatusLabel', |
| | | label: '任务状态', |
| | | label: $t('table.status'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'taskTypeLabel', |
| | | label: '任务类型', |
| | | label: $t('table.type'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'warehTypeLabel', |
| | | label: '设备类型', |
| | | label: $t('pages.task.detail.warehType'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'orgLoc', |
| | | label: '源库位', |
| | | label: $t('pages.task.search.orgLoc'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'orgSiteLabel', |
| | | label: '源站点', |
| | | label: $t('pages.task.detail.orgSite'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'targLoc', |
| | | label: '目标库位', |
| | | label: $t('pages.task.search.targLoc'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'targSiteLabel', |
| | | label: '目标站点', |
| | | label: $t('pages.task.detail.targSite'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'barcode', |
| | | label: '托盘码', |
| | | label: $t('pages.task.search.barcode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'robotCode', |
| | | label: '机器人编码', |
| | | label: $t('pages.task.detail.robotCode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'sort', |
| | | label: '优先级', |
| | | label: $t('pages.task.detail.priority'), |
| | | width: 100, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'updateTimeText', |
| | | label: '更新时间', |
| | | label: $t('table.updateTime'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'operation', |
| | | label: '操作', |
| | | label: $t('table.operation'), |
| | | width: 120, |
| | | align: 'center', |
| | | fixed: 'right', |
| | |
| | | export const ASN_ORDER_REPORT_TITLE = '入库通知单报表' |
| | | import { $t } from '@/locales' |
| | | |
| | | export const ASN_ORDER_REPORT_TITLE = $t('pages.orders.asnOrder.reportTitle') |
| | | export const ASN_ORDER_REPORT_STYLE = { |
| | | titleAlign: 'center', |
| | | titleLevel: 'strong', |
| | |
| | | } |
| | | |
| | | const ASN_ORDER_STATUS_MAP = { |
| | | 0: { label: '未执行', tagType: 'info' }, |
| | | 1: { label: '执行中', tagType: 'warning' }, |
| | | 2: { label: '收货完成', tagType: 'success' }, |
| | | 3: { label: '任务执行中', tagType: 'warning' }, |
| | | 4: { label: '已完成', tagType: 'success' }, |
| | | 8: { label: '取消', tagType: 'danger' }, |
| | | 9: { label: '已关闭', tagType: 'info' } |
| | | 0: { label: $t('pages.orders.asnOrder.status.pending'), tagType: 'info' }, |
| | | 1: { label: $t('pages.orders.asnOrder.status.running'), tagType: 'warning' }, |
| | | 2: { label: $t('pages.orders.asnOrder.status.receiving'), tagType: 'success' }, |
| | | 3: { label: $t('pages.orders.asnOrder.status.taskRunning'), tagType: 'warning' }, |
| | | 4: { label: $t('pages.orders.asnOrder.status.completed'), tagType: 'success' }, |
| | | 8: { label: $t('pages.orders.asnOrder.status.cancelled'), tagType: 'danger' }, |
| | | 9: { label: $t('pages.orders.asnOrder.status.closed'), tagType: 'info' } |
| | | } |
| | | |
| | | function normalizeText(value) { |
| | |
| | | return [ |
| | | { |
| | | key: 'view', |
| | | label: '查看详情', |
| | | label: $t('pages.orders.asnOrder.actions.view'), |
| | | icon: 'ri:eye-line' |
| | | }, |
| | | { |
| | | key: 'items', |
| | | label: '收货明细', |
| | | label: $t('pages.orders.asnOrder.actions.items'), |
| | | icon: 'ri:list-check-3' |
| | | }, |
| | | { |
| | | key: 'print', |
| | | label: '打印', |
| | | label: $t('pages.orders.asnOrder.actions.print'), |
| | | icon: 'ri:printer-line' |
| | | }, |
| | | { |
| | | key: 'complete', |
| | | label: '完成', |
| | | label: $t('pages.orders.asnOrder.actions.complete'), |
| | | icon: 'ri:check-line', |
| | | color: 'var(--el-color-success)', |
| | | disabled: !normalizedRow.canComplete |
| | |
| | | import { h } from 'vue' |
| | | import { ElButton, ElTag } from 'element-plus' |
| | | import { $t } from '@/locales' |
| | | import ArtButtonMore from '@/components/core/forms/art-button-more/index.vue' |
| | | import ArtButtonTable from '@/components/core/forms/art-button-table/index.vue' |
| | | import { getAsnOrderActionList } from './asnOrderPage.helpers' |
| | |
| | | }, |
| | | { |
| | | type: 'globalIndex', |
| | | label: '序号', |
| | | label: $t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'code', |
| | | label: 'ASN单号', |
| | | label: $t('pages.orders.asnOrder.search.code'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'poCode', |
| | | label: 'PO单号', |
| | | label: $t('pages.orders.asnOrder.search.poCode'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'wkTypeLabel', |
| | | label: '业务类型', |
| | | label: $t('pages.orders.asnOrder.search.wkType'), |
| | | minWidth: 130, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'anfme', |
| | | label: '应收数量', |
| | | label: $t('pages.orders.asnOrder.detail.anfme'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'qty', |
| | | label: '已收数量', |
| | | label: $t('pages.orders.asnOrder.detail.qty'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'supplierName', |
| | | label: '供应商', |
| | | label: $t('pages.orders.asnOrder.search.supplierName'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'purchaseUserName', |
| | | label: '采购员', |
| | | label: $t('pages.orders.asnOrder.search.purchaseUserName'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'exceStatusText', |
| | | label: '单据状态', |
| | | label: $t('pages.orders.asnOrder.search.exceStatus'), |
| | | width: 120, |
| | | formatter: (row) => |
| | | h( |
| | |
| | | }, |
| | | { |
| | | prop: 'updateTimeText', |
| | | label: '更新时间', |
| | | label: $t('pages.orders.asnOrder.detail.updateTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'operation', |
| | | label: '操作', |
| | | label: $t('table.operation'), |
| | | width: 120, |
| | | align: 'center', |
| | | fixed: 'right', |
| | |
| | | return [ |
| | | { |
| | | type: 'globalIndex', |
| | | label: '序号', |
| | | label: $t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'matnrCode', |
| | | label: '物料编码', |
| | | label: $t('table.materialCode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'maktx', |
| | | label: '物料名称', |
| | | label: $t('table.materialName'), |
| | | minWidth: 220, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'platItemId', |
| | | label: 'PO行号', |
| | | label: $t('pages.orders.asnOrder.table.poItemId'), |
| | | width: 110 |
| | | }, |
| | | { |
| | | prop: 'splrBatch', |
| | | label: '供应商批次', |
| | | label: $t('table.supplierBatch'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'splrName', |
| | | label: '供应商', |
| | | label: $t('table.supplier'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'stockUnit', |
| | | label: '单位', |
| | | label: $t('table.unit'), |
| | | width: 100 |
| | | }, |
| | | { |
| | | prop: 'anfme', |
| | | label: '应收数量', |
| | | label: $t('pages.orders.asnOrder.table.expectedQty'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'qty', |
| | | label: '已收数量', |
| | | label: $t('pages.orders.asnOrder.table.receivedQty'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'memo', |
| | | label: '备注', |
| | | label: $t('table.remark'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | } |
| | |
| | | return [ |
| | | { |
| | | type: 'globalIndex', |
| | | label: '序号', |
| | | label: $t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'code', |
| | | label: 'PO单号', |
| | | label: $t('pages.orders.asnOrder.search.poCode'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'wkTypeLabel', |
| | | label: '业务类型', |
| | | label: $t('pages.orders.asnOrder.search.wkType'), |
| | | minWidth: 130, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'source', |
| | | label: '来源', |
| | | label: $t('table.source'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'supplierName', |
| | | label: '供应商', |
| | | label: $t('pages.orders.asnOrder.search.supplierName'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'purchaseUserName', |
| | | label: '采购员', |
| | | label: $t('pages.orders.asnOrder.search.purchaseUserName'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'remainingQty', |
| | | label: '可建单数量', |
| | | label: $t('pages.orders.asnOrder.table.remainingQty'), |
| | | width: 120, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'exceStatusText', |
| | | label: 'PO状态', |
| | | label: $t('pages.orders.asnOrder.table.poStatus'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'operation', |
| | | label: '操作', |
| | | label: $t('table.operation'), |
| | | width: 120, |
| | | align: 'center', |
| | | fixed: 'right', |
| | |
| | | return [ |
| | | { |
| | | type: 'globalIndex', |
| | | label: '序号', |
| | | label: $t('table.index'), |
| | | width: 72, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'platItemId', |
| | | label: 'PO行号', |
| | | label: $t('pages.orders.asnOrder.table.poItemId'), |
| | | width: 110 |
| | | }, |
| | | { |
| | | prop: 'matnrCode', |
| | | label: '物料编码', |
| | | label: $t('table.materialCode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'maktx', |
| | | label: '物料名称', |
| | | label: $t('table.materialName'), |
| | | minWidth: 220, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'splrName', |
| | | label: '供应商', |
| | | label: $t('table.supplier'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'splrBatch', |
| | | label: '供应商批次', |
| | | label: $t('table.supplierBatch'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'unit', |
| | | label: '单位', |
| | | label: $t('table.unit'), |
| | | width: 100 |
| | | }, |
| | | { |
| | | prop: 'anfme', |
| | | label: '采购数量', |
| | | label: $t('pages.orders.asnOrder.table.purchaseQty'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'qty', |
| | | label: '已生成ASN数量', |
| | | label: $t('pages.orders.asnOrder.table.generatedQty'), |
| | | width: 130, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'nromQty', |
| | | label: '收货数量', |
| | | label: $t('pages.orders.asnOrder.table.receivedQtyTotal'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'selectAction', |
| | | label: '操作提示', |
| | | label: $t('table.operation'), |
| | | minWidth: 120, |
| | | formatter: () => |
| | | h( |
| | |
| | | type: 'primary', |
| | | class: '!px-0' |
| | | }, |
| | | () => '随 PO 全量建单' |
| | | () => $t('pages.orders.asnOrder.buttons.createByPo') |
| | | ) |
| | | } |
| | | ] |
| | |
| | | <ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData"> |
| | | <template #left> |
| | | <ElSpace wrap> |
| | | <ElButton type="primary" @click="poDialogVisible = true">按PO建单</ElButton> |
| | | <ElButton type="primary" @click="poDialogVisible = true">{{ t('pages.orders.asnOrder.buttons.createByPo') }}</ElButton> |
| | | <ListExportPrint |
| | | :preview-visible="previewVisible" |
| | | @update:previewVisible="handlePreviewVisibleChange" |
| | |
| | | <script setup> |
| | | import { computed, reactive, ref } from 'vue' |
| | | import { useRouter } from 'vue-router' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { useUserStore } from '@/store/modules/user' |
| | | import { useTable } from '@/hooks/core/useTable' |
| | |
| | | |
| | | const userStore = useUserStore() |
| | | const router = useRouter() |
| | | const { t } = useI18n() |
| | | const reportTitle = ASN_ORDER_REPORT_TITLE |
| | | const searchForm = ref(createAsnOrderSearchState()) |
| | | const selectedRows = ref([]) |
| | |
| | | const detailColumns = computed(() => createAsnOrderDetailItemColumns()) |
| | | const searchItems = computed(() => [ |
| | | { |
| | | label: '关键字', |
| | | label: t('pages.orders.asnOrder.search.condition'), |
| | | key: 'condition', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入 ASN 单号/PO 单号/供应商' |
| | | placeholder: t('pages.orders.asnOrder.placeholder.condition') |
| | | } |
| | | }, |
| | | { |
| | | label: 'ASN单号', |
| | | label: t('pages.orders.asnOrder.search.code'), |
| | | key: 'code', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入 ASN 单号' |
| | | placeholder: t('pages.orders.asnOrder.placeholder.code') |
| | | } |
| | | }, |
| | | { |
| | | label: 'PO单号', |
| | | label: t('pages.orders.asnOrder.search.poCode'), |
| | | key: 'poCode', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入 PO 单号' |
| | | placeholder: t('pages.orders.asnOrder.placeholder.poCode') |
| | | } |
| | | }, |
| | | { |
| | | label: '业务类型', |
| | | label: t('pages.orders.asnOrder.search.wkType'), |
| | | key: 'wkType', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入业务类型' |
| | | placeholder: t('pages.orders.asnOrder.placeholder.wkType') |
| | | } |
| | | }, |
| | | { |
| | | label: '单据状态', |
| | | label: t('pages.orders.asnOrder.search.exceStatus'), |
| | | key: 'exceStatus', |
| | | type: 'select', |
| | | props: { |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '供应商', |
| | | label: t('pages.orders.asnOrder.search.supplierName'), |
| | | key: 'supplierName', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入供应商' |
| | | placeholder: t('pages.orders.asnOrder.placeholder.supplierName') |
| | | } |
| | | }, |
| | | { |
| | | label: '采购员', |
| | | label: t('pages.orders.asnOrder.search.purchaseUserName'), |
| | | key: 'purchaseUserName', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入采购员' |
| | | placeholder: t('pages.orders.asnOrder.placeholder.purchaseUserName') |
| | | } |
| | | } |
| | | ]) |
| | |
| | | } |
| | | |
| | | if (action.key === 'complete') { |
| | | await ElMessageBox.confirm(`确定完成入库通知单 ${row.code || ''} 吗?`, '完成确认', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }) |
| | | await ElMessageBox.confirm( |
| | | t('pages.orders.asnOrder.detail.completeConfirm', { code: row.code || '' }), |
| | | t('pages.orders.asnOrder.detail.completeTitle'), |
| | | { |
| | | confirmButtonText: t('common.confirm'), |
| | | cancelButtonText: t('common.cancel'), |
| | | type: 'warning' |
| | | } |
| | | ) |
| | | await fetchCompleteAsnOrder(row.id) |
| | | ElMessage.success('入库通知单已完成') |
| | | ElMessage.success(t('pages.orders.asnOrder.detail.completeSuccess')) |
| | | await refreshData() |
| | | if (detailDrawerVisible.value && activeOrderId.value === row.id) { |
| | | await loadDetailResources() |
| | |
| | | if (error === 'cancel' || error?.message === 'cancel') { |
| | | return |
| | | } |
| | | ElMessage.error(error?.message || '入库通知单操作失败') |
| | | ElMessage.error(error?.message || t('pages.orders.asnOrder.detail.actionFailed')) |
| | | } |
| | | } |
| | | |
| | |
| | | size: detailPagination.size |
| | | }, |
| | | { |
| | | timeoutMessage: '入库通知单明细加载超时,已停止等待' |
| | | timeoutMessage: t('pages.orders.asnOrder.detail.itemsTimeout') |
| | | } |
| | | ) |
| | | |
| | |
| | | <template> |
| | | <ElDialog |
| | | :model-value="visible" |
| | | title="按PO建单" |
| | | :title="t('pages.orders.asnOrder.createByPoDialog.title')" |
| | | width="90%" |
| | | top="4vh" |
| | | destroy-on-close |
| | |
| | | <ElCard class="art-table-card" shadow="never"> |
| | | <template #header> |
| | | <div class="flex items-center justify-between gap-3"> |
| | | <div class="text-sm font-medium">可建单 PO 列表</div> |
| | | <ElButton :loading="purchaseLoading" @click="refreshPurchaseData">刷新</ElButton> |
| | | <div class="text-sm font-medium">{{ t('pages.orders.asnOrder.createByPoDialog.purchaseList') }}</div> |
| | | <ElButton :loading="purchaseLoading" @click="refreshPurchaseData">{{ t('common.actions.refresh') }}</ElButton> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | <template #header> |
| | | <div class="flex items-center justify-between gap-3"> |
| | | <div class="flex flex-col"> |
| | | <span class="text-sm font-medium">PO 明细预览</span> |
| | | <span class="text-sm font-medium">{{ t('pages.orders.asnOrder.createByPoDialog.purchasePreview') }}</span> |
| | | <span class="text-xs text-[var(--art-gray-600)]"> |
| | | {{ |
| | | selectedPurchase.code |
| | | ? `当前选择:${selectedPurchase.code}` |
| | | : '请先在左侧选择一个 PO 单' |
| | | ? t('pages.orders.asnOrder.createByPoDialog.purchaseSelected', { code: selectedPurchase.code }) |
| | | : t('pages.orders.asnOrder.createByPoDialog.purchaseEmpty') |
| | | }} |
| | | </span> |
| | | </div> |
| | |
| | | :loading="itemLoading" |
| | | @click="reloadSelectedPurchaseItems" |
| | | > |
| | | 刷新明细 |
| | | {{ t('pages.orders.asnOrder.createByPoDialog.refreshItems') }} |
| | | </ElButton> |
| | | </div> |
| | | </template> |
| | |
| | | <div class="text-xs text-[var(--art-gray-600)]"> |
| | | {{ |
| | | selectedPurchase.id |
| | | ? `将按 PO ${selectedPurchase.code} 的 ${purchaseItems.length} 条明细生成入库通知单` |
| | | : '请选择一个可建单的 PO 单' |
| | | ? t('pages.orders.asnOrder.createByPoDialog.purchaseGenerateHint', { code: selectedPurchase.code, count: purchaseItems.length }) |
| | | : t('pages.orders.asnOrder.createByPoDialog.purchaseGenerateEmpty') |
| | | }} |
| | | </div> |
| | | <ElSpace> |
| | | <ElButton @click="handleVisibleChange(false)">取消</ElButton> |
| | | <ElButton @click="handleVisibleChange(false)">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton |
| | | type="primary" |
| | | :loading="submitLoading" |
| | | :disabled="!selectedPurchase.id" |
| | | @click="handleConfirm" |
| | | > |
| | | 生成入库通知单 |
| | | {{ t('pages.orders.asnOrder.createByPoDialog.generate') }} |
| | | </ElButton> |
| | | </ElSpace> |
| | | </div> |
| | |
| | | <script setup> |
| | | import { computed, ref, watch } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { useTable } from '@/hooks/core/useTable' |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { |
| | |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'success']) |
| | | const { t } = useI18n() |
| | | |
| | | const searchForm = ref(createPurchaseFilterSearchState()) |
| | | const selectedPurchase = ref({}) |
| | |
| | | |
| | | const searchItems = computed(() => [ |
| | | { |
| | | label: '关键字', |
| | | label: t('pages.orders.asnOrder.createByPoDialog.search.condition'), |
| | | key: 'condition', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入 PO 单号/来源/供应商' |
| | | placeholder: t('pages.orders.asnOrder.createByPoDialog.search.conditionPlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: 'PO单号', |
| | | label: t('pages.orders.asnOrder.createByPoDialog.search.code'), |
| | | key: 'code', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入 PO 单号' |
| | | placeholder: t('pages.orders.asnOrder.createByPoDialog.search.codePlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: '来源', |
| | | label: t('pages.orders.asnOrder.createByPoDialog.search.source'), |
| | | key: 'source', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入来源' |
| | | placeholder: t('pages.orders.asnOrder.createByPoDialog.search.sourcePlaceholder') |
| | | } |
| | | }, |
| | | { |
| | | label: '供应商', |
| | | label: t('pages.orders.asnOrder.createByPoDialog.search.supplierName'), |
| | | key: 'supplierName', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入供应商' |
| | | placeholder: t('pages.orders.asnOrder.createByPoDialog.search.supplierNamePlaceholder') |
| | | } |
| | | } |
| | | ]) |
| | |
| | | current: 1, |
| | | size: 200 |
| | | }, |
| | | { |
| | | timeoutMessage: 'PO 明细加载超时,已停止等待' |
| | | { |
| | | timeoutMessage: t('pages.orders.asnOrder.createByPoDialog.messages.purchaseItemsTimeout') |
| | | } |
| | | ) |
| | | |
| | |
| | | size: total |
| | | }, |
| | | { |
| | | timeoutMessage: 'PO 全量明细加载超时,已停止等待' |
| | | timeoutMessage: t('pages.orders.asnOrder.createByPoDialog.messages.purchaseItemsAllTimeout') |
| | | } |
| | | ) |
| | | purchaseItems.value = Array.isArray(fullPage?.records) |
| | |
| | | |
| | | async function handleConfirm() { |
| | | if (!selectedPurchase.value?.id) { |
| | | ElMessage.warning('请先选择一个 PO 单') |
| | | ElMessage.warning(t('pages.orders.asnOrder.createByPoDialog.messages.purchaseRequired')) |
| | | return |
| | | } |
| | | if (!purchaseItems.value.length) { |
| | | ElMessage.warning('当前 PO 单没有可建单明细') |
| | | ElMessage.warning(t('pages.orders.asnOrder.createByPoDialog.messages.purchaseItemsEmpty')) |
| | | return |
| | | } |
| | | |
| | |
| | | purchaseId: selectedPurchase.value.id, |
| | | items: purchaseItems.value.map((item) => ({ ...item })) |
| | | }) |
| | | ElMessage.success('已根据 PO 单生成入库通知单') |
| | | ElMessage.success(t('pages.orders.asnOrder.createByPoDialog.messages.createByPoSuccess')) |
| | | emit('success') |
| | | handleVisibleChange(false) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '按 PO 建单失败') |
| | | ElMessage.error(error?.message || t('pages.orders.asnOrder.createByPoDialog.messages.createByPoFailed')) |
| | | } finally { |
| | | submitLoading.value = false |
| | | } |
| | |
| | | <template> |
| | | <ElDrawer |
| | | :model-value="visible" |
| | | title="入库通知单详情" |
| | | :title="t('pages.orders.asnOrder.detail.title')" |
| | | size="1180px" |
| | | destroy-on-close |
| | | @update:model-value="handleVisibleChange" |
| | | > |
| | | <ElScrollbar class="h-[calc(100vh-180px)] pr-1"> |
| | | <div class="space-y-4"> |
| | | <ElDescriptions title="基础信息" :column="4" border> |
| | | <ElDescriptionsItem label="ASN单号">{{ detail.code || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="PO单号">{{ detail.poCode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="业务类型">{{ detail.wkTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="单据类型">{{ detail.orderTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="单据状态">{{ detail.exceStatusText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="采购组织">{{ detail.purchaseOrgName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="采购员">{{ detail.purchaseUserName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="供应商">{{ detail.supplierName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="应收数量">{{ detail.anfme ?? 0 }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="已收数量">{{ detail.qty ?? 0 }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="更新时间">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="创建时间">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="备注" :span="4">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptions :title="t('pages.orders.asnOrder.detail.baseInfo')" :column="4" border> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.asnCode')">{{ detail.code || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.poCode')">{{ detail.poCode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.wkType')">{{ detail.wkTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.orderType')">{{ detail.orderTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.status')">{{ detail.exceStatusText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.purchaseOrg')">{{ detail.purchaseOrgName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.purchaseUser')">{{ detail.purchaseUserName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.supplier')">{{ detail.supplierName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.anfme')">{{ detail.anfme ?? 0 }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.qty')">{{ detail.qty ?? 0 }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.updateTime')">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.createTime')">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.asnOrder.detail.memo')" :span="4">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | |
| | | <div class="space-y-3"> |
| | | <div class="flex items-center justify-between"> |
| | | <div class="text-sm font-medium text-[var(--art-gray-900)]">单据明细</div> |
| | | <div class="text-sm font-medium text-[var(--art-gray-900)]">{{ t('pages.orders.asnOrder.detail.items') }}</div> |
| | | <div class="flex items-center gap-3"> |
| | | <ElTag effect="plain">共 {{ data.length }} 条</ElTag> |
| | | <ElButton :loading="loading" @click="$emit('refresh')">刷新</ElButton> |
| | | <ElTag effect="plain">{{ t('pages.orders.asnOrder.detail.count', { count: data.length }) }}</ElTag> |
| | | <ElButton :loading="loading" @click="$emit('refresh')">{{ t('common.actions.refresh') }}</ElButton> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useI18n } from 'vue-i18n' |
| | | |
| | | defineOptions({ name: 'AsnOrderDetailDrawer' }) |
| | | const { t } = useI18n() |
| | | |
| | | defineProps({ |
| | | visible: { type: Boolean, default: false }, |
| | |
| | | import { $t } from '@/locales' |
| | | |
| | | const DELIVERY_STATUS_META = { |
| | | 1: { text: '正常', type: 'success', bool: true }, |
| | | 0: { text: '禁用', type: 'danger', bool: false } |
| | | 1: { text: $t('pages.orders.delivery.status.normal'), type: 'success', bool: true }, |
| | | 0: { text: $t('pages.orders.delivery.status.disabled'), type: 'danger', bool: false } |
| | | } |
| | | |
| | | const DELIVERY_EXCE_STATUS_META = { |
| | | 0: { text: '未执行', type: 'info' }, |
| | | 1: { text: '执行中', type: 'warning' }, |
| | | 2: { text: '部分完成', type: 'primary' }, |
| | | 3: { text: '已完成', type: 'success' } |
| | | 0: { text: $t('pages.orders.delivery.status.pending'), type: 'info' }, |
| | | 1: { text: $t('pages.orders.delivery.status.running'), type: 'warning' }, |
| | | 2: { text: $t('pages.orders.delivery.status.partial'), type: 'primary' }, |
| | | 3: { text: $t('pages.orders.delivery.status.completed'), type: 'success' } |
| | | } |
| | | |
| | | export const DELIVERY_REPORT_TITLE = 'DO单报表' |
| | | export const DELIVERY_REPORT_TITLE = $t('pages.orders.delivery.reportTitle') |
| | | export const DELIVERY_REPORT_STYLE = { |
| | | titleAlign: 'center', |
| | | titleLevel: 'strong', |
| | |
| | | if (status === false || Number(status) === 0) { |
| | | return DELIVERY_STATUS_META[0] |
| | | } |
| | | return { text: '未知', type: 'info', bool: false } |
| | | return { text: $t('common.status.unknown'), type: 'info', bool: false } |
| | | } |
| | | |
| | | function normalizeExceStatusMeta(exceStatus, exceStatusText) { |
| | |
| | | orientation = DELIVERY_REPORT_STYLE.orientation |
| | | } = {}) { |
| | | return { |
| | | reportTitle: 'DO单明细报表', |
| | | reportTitle: $t('pages.orders.delivery.detailReportTitle'), |
| | | reportDate: previewMeta.reportDate, |
| | | printedAt: previewMeta.printedAt, |
| | | operator: previewMeta.operator, |
| | |
| | | const actions = [ |
| | | { |
| | | key: 'view', |
| | | label: '查看详情', |
| | | label: $t('pages.orders.delivery.actions.view'), |
| | | icon: 'ri:eye-line' |
| | | }, |
| | | { |
| | | key: 'items', |
| | | label: '明细', |
| | | label: $t('pages.orders.delivery.actions.items'), |
| | | icon: 'ri:list-check-3' |
| | | } |
| | | ] |
| | |
| | | if (Number(normalizedRow.exceStatus) === 0) { |
| | | actions.push({ |
| | | key: 'delete', |
| | | label: '删除', |
| | | label: $t('pages.orders.delivery.actions.delete'), |
| | | icon: 'ri:delete-bin-5-line', |
| | | color: 'var(--art-error)' |
| | | }) |
| | |
| | | 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 { getDeliveryActionList } from './deliveryPage.helpers.js' |
| | | |
| | | export function createDeliveryTableColumns({ handleActionClick } = {}) { |
| | | return [ |
| | | { type: 'selection', width: 48, align: 'center' }, |
| | | { type: 'globalIndex', label: '序号', width: 72, align: 'center' }, |
| | | { type: 'globalIndex', label: $t('table.index'), width: 72, align: 'center' }, |
| | | { |
| | | prop: 'code', |
| | | label: '单号', |
| | | label: $t('pages.orders.delivery.search.code'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.code || '--' |
| | | }, |
| | | { |
| | | prop: 'platId', |
| | | label: 'ERP主单标识', |
| | | label: $t('pages.orders.delivery.search.platId'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.platId || '--' |
| | | }, |
| | | { |
| | | prop: 'typeLabel', |
| | | label: '单据类型', |
| | | label: $t('pages.orders.delivery.search.type'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.typeLabel || '--' |
| | | }, |
| | | { |
| | | prop: 'wkTypeLabel', |
| | | label: '业务类型', |
| | | label: $t('pages.orders.delivery.search.wkType'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.wkTypeLabel || '--' |
| | | }, |
| | | { |
| | | prop: 'source', |
| | | label: '单据来源', |
| | | label: $t('pages.orders.delivery.search.source'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.source || '--' |
| | | }, |
| | | { |
| | | prop: 'anfme', |
| | | label: '应收数量', |
| | | label: $t('pages.orders.delivery.table.anfme'), |
| | | width: 110, |
| | | align: 'right', |
| | | formatter: (row) => row.anfme ?? '--' |
| | | }, |
| | | { |
| | | prop: 'workQty', |
| | | label: '执行中数量', |
| | | label: $t('pages.orders.delivery.table.workQty'), |
| | | width: 110, |
| | | align: 'right', |
| | | formatter: (row) => row.workQty ?? '--' |
| | | }, |
| | | { |
| | | prop: 'qty', |
| | | label: '实收数量', |
| | | label: $t('pages.orders.delivery.table.qty'), |
| | | width: 110, |
| | | align: 'right', |
| | | formatter: (row) => row.qty ?? '--' |
| | | }, |
| | | { |
| | | prop: 'platCode', |
| | | label: '平台单号', |
| | | label: $t('pages.orders.delivery.table.platCode'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.platCode || '--' |
| | | }, |
| | | { |
| | | prop: 'status', |
| | | label: '状态', |
| | | label: $t('pages.orders.transfer.search.status'), |
| | | width: 96, |
| | | align: 'center', |
| | | formatter: (row) => |
| | |
| | | }, |
| | | { |
| | | prop: 'exceStatusText', |
| | | label: '执行状态', |
| | | label: $t('pages.orders.delivery.search.exceStatus'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => |
| | |
| | | }, |
| | | { |
| | | prop: 'startTimeText', |
| | | label: '计划出库时间', |
| | | label: $t('pages.orders.delivery.table.startTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.startTimeText || '--' |
| | | }, |
| | | { |
| | | prop: 'endTimeText', |
| | | label: '计划出库结束时间', |
| | | label: $t('pages.orders.delivery.table.endTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.endTimeText || '--' |
| | | }, |
| | | { |
| | | prop: 'memo', |
| | | label: '备注', |
| | | label: $t('pages.orders.delivery.search.memo'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.memo || '--' |
| | | }, |
| | | { |
| | | prop: 'operation', |
| | | label: '操作', |
| | | label: $t('table.operation'), |
| | | width: 120, |
| | | align: 'center', |
| | | fixed: 'right', |
| | |
| | | <script setup> |
| | | import { computed, reactive, ref } from 'vue' |
| | | import { useRouter } from 'vue-router' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { useUserStore } from '@/store/modules/user' |
| | | import { useTable } from '@/hooks/core/useTable' |
| | |
| | | |
| | | const userStore = useUserStore() |
| | | const router = useRouter() |
| | | const reportTitle = 'DO单报表' |
| | | const { t } = useI18n() |
| | | const reportTitle = t('pages.orders.delivery.reportTitle') |
| | | const searchForm = ref(createDeliverySearchState()) |
| | | const selectedRows = ref([]) |
| | | const detailDrawerVisible = ref(false) |
| | |
| | | const reportQueryParams = computed(() => buildDeliverySearchParams(searchForm.value)) |
| | | const searchItems = computed(() => [ |
| | | { |
| | | label: '关键字', |
| | | label: t('pages.orders.delivery.search.condition'), |
| | | key: 'condition', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入单号/ERP主单标识/平台单号' |
| | | placeholder: t('pages.orders.delivery.placeholder.condition') |
| | | } |
| | | }, |
| | | { |
| | | label: '单号', |
| | | label: t('pages.orders.delivery.search.code'), |
| | | key: 'code', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入单号' |
| | | placeholder: t('pages.orders.delivery.placeholder.code') |
| | | } |
| | | }, |
| | | { |
| | | label: 'ERP主单标识', |
| | | label: t('pages.orders.delivery.search.platId'), |
| | | key: 'platId', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入ERP主单标识' |
| | | placeholder: t('pages.orders.delivery.placeholder.platId') |
| | | } |
| | | }, |
| | | { |
| | | label: '单据类型', |
| | | label: t('pages.orders.delivery.search.type'), |
| | | key: 'type', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入单据类型' |
| | | placeholder: t('pages.orders.delivery.placeholder.type') |
| | | } |
| | | }, |
| | | { |
| | | label: '业务类型', |
| | | label: t('pages.orders.delivery.search.wkType'), |
| | | key: 'wkType', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入业务类型' |
| | | placeholder: t('pages.orders.delivery.placeholder.wkType') |
| | | } |
| | | }, |
| | | { |
| | | label: '单据来源', |
| | | label: t('pages.orders.delivery.search.source'), |
| | | key: 'source', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入单据来源' |
| | | placeholder: t('pages.orders.delivery.placeholder.source') |
| | | } |
| | | }, |
| | | { |
| | | label: '执行状态', |
| | | label: t('pages.orders.delivery.search.exceStatus'), |
| | | key: 'exceStatus', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入执行状态' |
| | | placeholder: t('pages.orders.delivery.placeholder.exceStatus') |
| | | } |
| | | }, |
| | | { |
| | | label: '备注', |
| | | label: t('pages.orders.delivery.search.memo'), |
| | | key: 'memo', |
| | | type: 'input', |
| | | props: { |
| | | clearable: true, |
| | | placeholder: '请输入备注' |
| | | placeholder: t('pages.orders.delivery.placeholder.memo') |
| | | } |
| | | } |
| | | ]) |
| | |
| | | }) |
| | | ), |
| | | { records: [] }, |
| | | { timeoutMessage: '交接单明细加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.orders.delivery.messages.itemsTimeout') } |
| | | ) |
| | | const normalizedResponse = defaultResponseAdapter(response) |
| | | detailItemRows.value = normalizedResponse.records.map((item) => normalizeDeliveryItemRow(item)) |
| | |
| | | const detail = await guardRequestWithMessage( |
| | | fetchGetDeliveryDetail(row.id), |
| | | {}, |
| | | { timeoutMessage: '交接单详情加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.orders.delivery.messages.detailTimeout') } |
| | | ) |
| | | detailData.value = normalizeDeliveryRow(detail) |
| | | } finally { |
| | |
| | | await loadDetailItems(row.id) |
| | | } catch (error) { |
| | | detailDrawerVisible.value = false |
| | | ElMessage.error(error?.message || '获取交接单详情失败') |
| | | ElMessage.error(error?.message || t('pages.orders.delivery.messages.detailLoadFailed')) |
| | | } |
| | | } |
| | | |
| | | async function handleDelete(row) { |
| | | try { |
| | | await ElMessageBox.confirm(`确定要删除交接单「${row.code || row.id}」吗?`, '删除确认', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }) |
| | | await ElMessageBox.confirm( |
| | | t('crud.confirm.deleteMessage', { |
| | | entity: t('pages.orders.delivery.entity'), |
| | | label: row.code || row.id |
| | | }), |
| | | t('crud.confirm.deleteTitle'), |
| | | { |
| | | confirmButtonText: t('common.confirm'), |
| | | cancelButtonText: t('common.cancel'), |
| | | type: 'warning' |
| | | } |
| | | ) |
| | | await fetchDeleteDelivery(row.id) |
| | | ElMessage.success('删除成功') |
| | | ElMessage.success(t('crud.messages.deleteSuccess')) |
| | | await refreshRemove() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error(error?.message || '删除失败') |
| | | ElMessage.error(error?.message || t('crud.messages.deleteFailed')) |
| | | } |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <ElDrawer |
| | | :model-value="visible" |
| | | title="交接单详情" |
| | | :title="t('pages.orders.delivery.detail.title')" |
| | | size="1180px" |
| | | destroy-on-close |
| | | @update:model-value="handleVisibleChange" |
| | |
| | | <ElSkeleton :rows="12" animated /> |
| | | </div> |
| | | <div v-else class="space-y-4"> |
| | | <ElDescriptions title="基础信息" :column="2" border> |
| | | <ElDescriptionsItem label="交接单号">{{ detail.code || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="ERP主单标识">{{ detail.platId || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="平台单号">{{ detail.platCode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="单据类型">{{ detail.typeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="业务类型">{{ detail.wkTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="单据来源">{{ detail.source || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="应收数量">{{ detail.anfme ?? '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="实收数量">{{ detail.qty ?? '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="执行中数量">{{ detail.workQty ?? '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="状态"> |
| | | <ElDescriptions :title="t('pages.orders.delivery.detail.baseInfo')" :column="2" border> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.code')">{{ detail.code || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.platId')">{{ detail.platId || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.platCode')">{{ detail.platCode || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.type')">{{ detail.typeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.wkType')">{{ detail.wkTypeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.source')">{{ detail.source || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.anfme')">{{ detail.anfme ?? '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.qty')">{{ detail.qty ?? '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.workQty')">{{ detail.workQty ?? '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.status')"> |
| | | <ElTag :type="detail.statusType || 'info'" effect="light"> |
| | | {{ detail.statusText || '--' }} |
| | | </ElTag> |
| | | </ElDescriptionsItem> |
| | | <ElDescriptionsItem label="执行状态"> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.exceStatus')"> |
| | | <ElTag :type="detail.exceStatusTagType || 'info'" effect="light"> |
| | | {{ detail.exceStatusText || '--' }} |
| | | </ElTag> |
| | | </ElDescriptionsItem> |
| | | <ElDescriptionsItem label="备注" :span="2">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="计划出库时间">{{ detail.startTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="计划出库结束时间">{{ detail.endTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.memo')" :span="2">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.startTime')">{{ detail.startTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.endTime')">{{ detail.endTimeText || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | |
| | | <ElDescriptions title="审计信息" :column="2" border> |
| | | <ElDescriptionsItem label="创建人">{{ detail.createByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="创建时间">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="更新人">{{ detail.updateByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="更新时间">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptions :title="t('pages.orders.delivery.detail.auditInfo')" :column="2" border> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.createBy')">{{ detail.createByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.createTime')">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.updateBy')">{{ detail.updateByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.delivery.detail.updateTime')">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | |
| | | <div class="space-y-3"> |
| | | <div class="flex items-center justify-between"> |
| | | <div class="text-sm font-medium text-[var(--art-gray-900)]">交接单明细</div> |
| | | <ElTag effect="plain">共 {{ itemRows.length }} 条</ElTag> |
| | | <div class="text-sm font-medium text-[var(--art-gray-900)]">{{ t('pages.orders.delivery.detail.items') }}</div> |
| | | <ElTag effect="plain">{{ t('pages.orders.delivery.detail.count', { count: itemRows.length }) }}</ElTag> |
| | | </div> |
| | | <ArtTable |
| | | :loading="itemsLoading" |
| | |
| | | |
| | | <script setup> |
| | | import { computed } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import ArtTable from '@/components/core/tables/art-table/index.vue' |
| | | |
| | | defineOptions({ name: 'DeliveryDetailDrawer' }) |
| | | const { t } = useI18n() |
| | | |
| | | const props = defineProps({ |
| | | visible: { type: Boolean, default: false }, |
| | |
| | | const emit = defineEmits(['update:visible', 'size-change', 'current-change']) |
| | | |
| | | const itemColumns = [ |
| | | { type: 'globalIndex', label: '序号', width: 72, align: 'center' }, |
| | | { type: 'globalIndex', label: t('table.index'), width: 72, align: 'center' }, |
| | | { |
| | | prop: 'deliveryCode', |
| | | label: '交接单号', |
| | | label: t('pages.orders.delivery.table.deliveryCode'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'platItemId', |
| | | label: '平台行号', |
| | | label: t('pages.orders.delivery.table.platItemId'), |
| | | minWidth: 130, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'matnrCode', |
| | | label: '物料编码', |
| | | label: t('pages.orders.delivery.table.matnrCode'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'maktx', |
| | | label: '物料名称', |
| | | label: t('pages.orders.delivery.table.maktx'), |
| | | minWidth: 220, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'fieldsIndex', |
| | | label: '动态字段索引', |
| | | label: t('pages.orders.delivery.table.fieldsIndex'), |
| | | minWidth: 150, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'unit', |
| | | label: '单位', |
| | | label: t('table.unit'), |
| | | width: 90, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'anfme', |
| | | label: '数量', |
| | | label: t('pages.orders.delivery.table.anfme'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'workQty', |
| | | label: '执行数量', |
| | | label: t('pages.orders.delivery.table.workQty'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'qty', |
| | | label: '已出数量', |
| | | label: t('pages.orders.delivery.table.qty'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'nromQty', |
| | | label: '标准包装', |
| | | label: t('pages.orders.delivery.table.nromQty'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'printQty', |
| | | label: '打印数量', |
| | | label: t('pages.orders.delivery.table.printQty'), |
| | | width: 110, |
| | | align: 'right' |
| | | }, |
| | | { |
| | | prop: 'splrName', |
| | | label: '供应商名称', |
| | | label: t('pages.orders.delivery.table.splrName'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'splrCode', |
| | | label: '供应商编码', |
| | | label: t('pages.orders.delivery.table.splrCode'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | }, |
| | | { |
| | | prop: 'splrBatch', |
| | | label: '供应商批次', |
| | | label: t('pages.orders.delivery.table.splrBatch'), |
| | | minWidth: 140, |
| | | showOverflowTooltip: true |
| | | } |
| | |
| | | <ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData"> |
| | | <template #left> |
| | | <ElSpace wrap> |
| | | <ElButton v-if="canCreate" type="primary" @click="showDialog('add')" v-ripple>新增调拨单</ElButton> |
| | | <ElButton v-if="canCreate" type="primary" @click="showDialog('add')" v-ripple>{{ t('pages.orders.transfer.actions.add') }}</ElButton> |
| | | <ElButton |
| | | v-if="canDelete" |
| | | type="danger" |
| | |
| | | @click="handleBatchDelete" |
| | | v-ripple |
| | | > |
| | | 批量删除 |
| | | {{ t('common.actions.batchDelete') }} |
| | | </ElButton> |
| | | <ListExportPrint |
| | | class="inline-flex" |
| | |
| | | <script setup> |
| | | import { computed, onMounted, reactive, ref } from 'vue' |
| | | import { useRouter } from 'vue-router' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { useAuth } from '@/hooks/core/useAuth' |
| | | import { useUserStore } from '@/store/modules/user' |
| | |
| | | const { hasAuth } = useAuth() |
| | | const userStore = useUserStore() |
| | | const router = useRouter() |
| | | const { t } = useI18n() |
| | | |
| | | const reportTitle = TRANSFER_REPORT_TITLE |
| | | const searchForm = ref(createTransferSearchState()) |
| | |
| | | |
| | | const reportQueryParams = computed(() => buildTransferSearchParams(searchForm.value)) |
| | | const searchItems = computed(() => [ |
| | | { label: '关键字', key: 'condition', type: 'input', props: { clearable: true, placeholder: '请输入单号/备注/仓库/库区' } }, |
| | | { label: '调拨单号', key: 'code', type: 'input', props: { clearable: true, placeholder: '请输入调拨单号' } }, |
| | | { label: t('pages.orders.transfer.search.condition'), key: 'condition', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.condition') } }, |
| | | { label: t('pages.orders.transfer.search.code'), key: 'code', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.code') } }, |
| | | { |
| | | label: '调拨类型', |
| | | label: t('pages.orders.transfer.search.type'), |
| | | key: 'type', |
| | | type: 'select', |
| | | props: { clearable: true, filterable: true, options: typeOptions.value } |
| | | }, |
| | | { |
| | | label: '来源', |
| | | label: t('pages.orders.transfer.search.source'), |
| | | key: 'source', |
| | | type: 'select', |
| | | props: { clearable: true, options: getTransferSourceOptions() } |
| | | }, |
| | | { |
| | | label: '执行状态', |
| | | label: t('pages.orders.transfer.search.exceStatus'), |
| | | key: 'exceStatus', |
| | | type: 'select', |
| | | props: { clearable: true, options: getTransferExceStatusOptions() } |
| | | }, |
| | | { label: '源仓库', key: 'orgWareName', type: 'input', props: { clearable: true, placeholder: '请输入源仓库' } }, |
| | | { label: '目标仓库', key: 'tarWareName', type: 'input', props: { clearable: true, placeholder: '请输入目标仓库' } }, |
| | | { label: '源库区', key: 'orgAreaName', type: 'input', props: { clearable: true, placeholder: '请输入源库区' } }, |
| | | { label: '目标库区', key: 'tarAreaName', type: 'input', props: { clearable: true, placeholder: '请输入目标库区' } }, |
| | | { label: t('pages.orders.transfer.search.orgWareName'), key: 'orgWareName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgWareName') } }, |
| | | { label: t('pages.orders.transfer.search.tarWareName'), key: 'tarWareName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarWareName') } }, |
| | | { label: t('pages.orders.transfer.search.orgAreaName'), key: 'orgAreaName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgAreaName') } }, |
| | | { label: t('pages.orders.transfer.search.tarAreaName'), key: 'tarAreaName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarAreaName') } }, |
| | | { |
| | | label: '状态', |
| | | label: t('pages.orders.transfer.search.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | props: { clearable: true, options: getTransferStatusOptions() } |
| | | }, |
| | | { label: '备注', key: 'memo', type: 'input', props: { clearable: true, placeholder: '请输入备注' } } |
| | | { label: t('pages.orders.transfer.search.memo'), key: 'memo', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.memo') } } |
| | | ]) |
| | | |
| | | function handleSelectionChange(rows) { |
| | |
| | | const response = await guardRequestWithMessage( |
| | | fetchTransferDetail(transferId), |
| | | {}, |
| | | { timeoutMessage: '调拨单详情加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.orders.transfer.messages.detailTimeout') } |
| | | ) |
| | | detailData.value = normalizeTransferDetailRecord(response) |
| | | } finally { |
| | |
| | | }) |
| | | ), |
| | | { records: [], total: 0, current: detailOrderPagination.current, size: detailOrderPagination.size }, |
| | | { timeoutMessage: '关联单据加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.orders.transfer.messages.ordersTimeout') } |
| | | ) |
| | | const normalized = defaultResponseAdapter(response) |
| | | detailOrderRows.value = normalized.records.map((item) => normalizeTransferOrderRow(item)) |
| | |
| | | } catch (error) { |
| | | detailOrderRows.value = [] |
| | | detailOrderPagination.total = 0 |
| | | ElMessage.error(error?.message || '获取关联单据失败') |
| | | ElMessage.error(error?.message || t('pages.orders.transfer.messages.ordersLoadFailed')) |
| | | } finally { |
| | | detailOrdersLoading.value = false |
| | | } |
| | |
| | | detailDrawerVisible.value = false |
| | | detailData.value = {} |
| | | detailOrderRows.value = [] |
| | | ElMessage.error(error?.message || '获取调拨单详情失败') |
| | | ElMessage.error(error?.message || t('pages.orders.transfer.messages.detailLoadFailed')) |
| | | } |
| | | } |
| | | |
| | |
| | | const detail = await guardRequestWithMessage( |
| | | fetchTransferDetail(row.id), |
| | | {}, |
| | | { timeoutMessage: '调拨单详情加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.orders.transfer.messages.detailTimeout') } |
| | | ) |
| | | showDialog('edit', detail) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '获取调拨单详情失败') |
| | | ElMessage.error(error?.message || t('pages.orders.transfer.messages.detailLoadFailed')) |
| | | } |
| | | } |
| | | |
| | | async function handlePublish(row) { |
| | | try { |
| | | await ElMessageBox.confirm(`确定要下发调拨单「${row.code || row.id}」吗?`, '下发确认', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | await ElMessageBox.confirm(t('pages.orders.transfer.messages.publishConfirm', { code: row.code || row.id }), t('pages.orders.transfer.messages.publishTitle'), { |
| | | confirmButtonText: t('common.confirm'), |
| | | cancelButtonText: t('common.cancel'), |
| | | type: 'warning' |
| | | }) |
| | | const response = await fetchTransferPubOutStock({ id: row.id }) |
| | | if (response?.code !== 200 && response?.success !== true) { |
| | | throw new Error(response?.message || '下发执行失败') |
| | | throw new Error(response?.message || t('pages.orders.transfer.messages.publishFailed')) |
| | | } |
| | | ElMessage.success(response?.message || '下发执行成功') |
| | | ElMessage.success(response?.message || t('pages.orders.transfer.messages.publishSuccess')) |
| | | await refreshData() |
| | | if (detailDrawerVisible.value && activeTransferId.value === row.id) { |
| | | await loadTransferDetail(row.id) |
| | |
| | | } |
| | | } catch (error) { |
| | | if (error === 'cancel' || error?.message === 'cancel') return |
| | | ElMessage.error(error?.message || '下发执行失败') |
| | | ElMessage.error(error?.message || t('pages.orders.transfer.messages.publishFailed')) |
| | | } |
| | | } |
| | | |
| | |
| | | saveRequest: fetchSaveTransfer, |
| | | updateRequest: fetchUpdateTransfer, |
| | | deleteRequest: fetchDeleteTransfer, |
| | | entityName: '调拨单', |
| | | entityName: t('pages.orders.transfer.entity'), |
| | | resolveRecordLabel: (record) => record?.code || record?.id, |
| | | refreshCreate, |
| | | refreshUpdate, |
| | |
| | | const response = await guardRequestWithMessage( |
| | | fetchDictDataPage({ current: 1, pageSize: 200, dictTypeCode: 'sys_transfer_type', status: 1 }), |
| | | { records: [] }, |
| | | { timeoutMessage: '调拨类型选项加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.orders.transfer.messages.typeOptionsTimeout') } |
| | | ) |
| | | typeOptions.value = resolveTransferTypeOptions(defaultResponseAdapter(response).records) |
| | | } |
| | |
| | | const response = await guardRequestWithMessage( |
| | | fetchWarehouseAreasList(), |
| | | { records: [] }, |
| | | { timeoutMessage: '库区选项加载超时,已停止等待' } |
| | | { timeoutMessage: t('pages.orders.transfer.messages.areaOptionsTimeout') } |
| | | ) |
| | | areaOptions.value = resolveTransferAreaOptions(defaultResponseAdapter(response).records) |
| | | } |
| | |
| | | <template> |
| | | <ElDrawer |
| | | :model-value="visible" |
| | | title="调拨单详情" |
| | | :title="t('pages.orders.transfer.detail.title')" |
| | | size="1200px" |
| | | destroy-on-close |
| | | @update:model-value="handleVisibleChange" |
| | |
| | | <ElSkeleton :rows="12" animated /> |
| | | </div> |
| | | <div v-else class="space-y-4"> |
| | | <ElDescriptions title="基础信息" :column="2" border> |
| | | <ElDescriptionsItem label="调拨单号">{{ detail.code || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="调拨类型">{{ detail.typeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="来源"> |
| | | <ElDescriptions :title="t('pages.orders.transfer.detail.baseInfo')" :column="2" border> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.code')">{{ detail.code || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.type')">{{ detail.typeLabel || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.source')"> |
| | | <ElTag :type="detail.sourceTagType || 'info'" effect="light"> |
| | | {{ detail.sourceText || '--' }} |
| | | </ElTag> |
| | | </ElDescriptionsItem> |
| | | <ElDescriptionsItem label="执行状态"> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.exceStatus')"> |
| | | <ElTag :type="detail.exceStatusTagType || 'info'" effect="light"> |
| | | {{ detail.exceStatusText || '--' }} |
| | | </ElTag> |
| | | </ElDescriptionsItem> |
| | | <ElDescriptionsItem label="源仓库">{{ detail.orgWareName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="目标仓库">{{ detail.tarWareName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="源库区">{{ detail.orgAreaName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="目标库区">{{ detail.tarAreaName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="状态"> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.orgWareName')">{{ detail.orgWareName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.tarWareName')">{{ detail.tarWareName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.orgAreaName')">{{ detail.orgAreaName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.tarAreaName')">{{ detail.tarAreaName || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.status')"> |
| | | <ElTag :type="detail.statusType || 'info'" effect="light"> |
| | | {{ detail.statusText || '--' }} |
| | | </ElTag> |
| | | </ElDescriptionsItem> |
| | | <ElDescriptionsItem label="备注" :span="2">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.memo')" :span="2">{{ detail.memo || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | |
| | | <ElDescriptions title="审计信息" :column="2" border> |
| | | <ElDescriptionsItem label="创建人">{{ detail.createByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="创建时间">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="更新人">{{ detail.updateByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem label="更新时间">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptions :title="t('pages.orders.transfer.detail.auditInfo')" :column="2" border> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.createBy')">{{ detail.createByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.createTime')">{{ detail.createTimeText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.updateBy')">{{ detail.updateByText || '--' }}</ElDescriptionsItem> |
| | | <ElDescriptionsItem :label="t('pages.orders.transfer.detail.updateTime')">{{ detail.updateTimeText || '--' }}</ElDescriptionsItem> |
| | | </ElDescriptions> |
| | | |
| | | <div class="space-y-3"> |
| | | <div class="flex items-center justify-between"> |
| | | <div class="text-sm font-medium text-[var(--art-gray-900)]">关联单据</div> |
| | | <ElTag effect="plain">共 {{ orderRows.length }} 条</ElTag> |
| | | <div class="text-sm font-medium text-[var(--art-gray-900)]">{{ t('pages.orders.transfer.detail.relatedOrders') }}</div> |
| | | <ElTag effect="plain">{{ t('common.count', { count: orderRows.length }) }}</ElTag> |
| | | </div> |
| | | <ArtTable |
| | | :loading="ordersLoading" |
| | |
| | | |
| | | <script setup> |
| | | import { computed } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import ArtTable from '@/components/core/tables/art-table/index.vue' |
| | | import { createTransferOrderTableColumns } from '../transferTable.columns.js' |
| | | |
| | |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'size-change', 'current-change']) |
| | | const { t } = useI18n() |
| | | |
| | | const orderColumns = createTransferOrderTableColumns() |
| | | |
| | |
| | | <template> |
| | | <ElDialog |
| | | :title="dialogTitle" |
| | | :model-value="visible" |
| | | width="760px" |
| | | align-center |
| | | destroy-on-close |
| | | @update:model-value="handleCancel" |
| | | @closed="handleClosed" |
| | | > |
| | | <div class="mb-3 rounded-lg border border-[var(--art-border-color)] bg-[var(--art-bg-color)] px-3 py-2 text-xs text-[var(--art-text-gray-600)]"> |
| | | 调拨单号由系统生成,新增时只需维护调拨类型、源/目标库区和备注。 |
| | | </div> |
| | | |
| | | <ArtForm |
| | | ref="formRef" |
| | | v-model="form" |
| | | :items="formItems" |
| | | :rules="rules" |
| | | :span="12" |
| | | :gutter="20" |
| | | label-width="110px" |
| | | :show-reset="false" |
| | | :show-submit="false" |
| | | /> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">取消</ElButton> |
| | | <ElButton type="primary" :loading="submitLoading" @click="handleSubmit">确定</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 { |
| | | buildTransferDialogModel, |
| | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | | const formRef = ref() |
| | | const form = reactive(createTransferFormState()) |
| | | const { t } = useI18n() |
| | | |
| | | const isEdit = computed(() => props.dialogType === 'edit') |
| | | const dialogTitle = computed(() => (isEdit.value ? '编辑调拨单' : '新增调拨单')) |
| | | const dialogTitle = computed(() => |
| | | isEdit.value ? t('pages.orders.transfer.dialog.titleEdit') : t('pages.orders.transfer.dialog.titleAdd') |
| | | ) |
| | | |
| | | const rules = computed(() => ({ |
| | | type: [{ required: true, message: '请选择调拨类型', trigger: 'change' }], |
| | | orgAreaId: [{ required: true, message: '请选择源库区', trigger: 'change' }], |
| | | tarAreaId: [{ required: true, message: '请选择目标库区', trigger: 'change' }] |
| | | type: [{ required: true, message: t('pages.orders.transfer.dialog.validation.type'), trigger: 'change' }], |
| | | orgAreaId: [{ required: true, message: t('pages.orders.transfer.dialog.validation.orgAreaId'), trigger: 'change' }], |
| | | tarAreaId: [{ required: true, message: t('pages.orders.transfer.dialog.validation.tarAreaId'), trigger: 'change' }] |
| | | })) |
| | | |
| | | const formItems = computed(() => [ |
| | | { |
| | | label: '调拨单号', |
| | | label: t('pages.orders.transfer.dialog.code'), |
| | | key: 'code', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | disabled: true, |
| | | placeholder: '保存后自动生成' |
| | | placeholder: t('pages.orders.transfer.dialog.placeholderCode') |
| | | } |
| | | }, |
| | | { |
| | | label: '调拨类型', |
| | | label: t('pages.orders.transfer.dialog.type'), |
| | | key: 'type', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择调拨类型', |
| | | placeholder: t('pages.orders.transfer.dialog.placeholderType'), |
| | | clearable: true, |
| | | filterable: true, |
| | | options: props.typeOptions |
| | | } |
| | | }, |
| | | { |
| | | label: '源库区', |
| | | label: t('pages.orders.transfer.dialog.orgAreaId'), |
| | | key: 'orgAreaId', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择源库区', |
| | | placeholder: t('pages.orders.transfer.dialog.placeholderOrgAreaId'), |
| | | clearable: true, |
| | | filterable: true, |
| | | options: props.areaOptions |
| | | } |
| | | }, |
| | | { |
| | | label: '目标库区', |
| | | label: t('pages.orders.transfer.dialog.tarAreaId'), |
| | | key: 'tarAreaId', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择目标库区', |
| | | placeholder: t('pages.orders.transfer.dialog.placeholderTarAreaId'), |
| | | clearable: true, |
| | | filterable: true, |
| | | options: props.areaOptions |
| | | } |
| | | }, |
| | | { |
| | | label: '状态', |
| | | label: t('pages.orders.transfer.dialog.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | props: { |
| | | placeholder: '请选择状态', |
| | | placeholder: t('pages.orders.transfer.dialog.placeholderStatus'), |
| | | clearable: true, |
| | | options: getTransferStatusOptions() |
| | | } |
| | | }, |
| | | { |
| | | label: '备注', |
| | | label: t('pages.orders.transfer.dialog.memo'), |
| | | key: 'memo', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | type: 'textarea', |
| | | rows: 3, |
| | | placeholder: '请输入备注', |
| | | placeholder: t('pages.orders.transfer.dialog.placeholderMemo'), |
| | | clearable: true |
| | | } |
| | | } |
| | |
| | | { deep: true } |
| | | ) |
| | | </script> |
| | | |
| | | <template> |
| | | <ElDialog |
| | | :title="dialogTitle" |
| | | :model-value="visible" |
| | | width="760px" |
| | | align-center |
| | | destroy-on-close |
| | | @update:model-value="handleCancel" |
| | | @closed="handleClosed" |
| | | > |
| | | <div class="mb-3 rounded-lg border border-[var(--art-border-color)] bg-[var(--art-bg-color)] px-3 py-2 text-xs text-[var(--art-text-gray-600)]"> |
| | | {{ t('pages.orders.transfer.dialog.tip') }} |
| | | </div> |
| | | |
| | | <ArtForm |
| | | ref="formRef" |
| | | v-model="form" |
| | | :items="formItems" |
| | | :rules="rules" |
| | | :span="12" |
| | | :gutter="20" |
| | | label-width="110px" |
| | | :show-reset="false" |
| | | :show-submit="false" |
| | | /> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton type="primary" :loading="submitLoading" @click="handleSubmit">{{ t('common.confirm') }}</ElButton> |
| | | </span> |
| | | </template> |
| | | </ElDialog> |
| | | </template> |
| | |
| | | import { $t } from '@/locales' |
| | | |
| | | const TRANSFER_SOURCE_META = { |
| | | 1: { text: 'ERP系统', type: 'info' }, |
| | | 2: { text: 'WMS系统生成', type: 'primary' }, |
| | | 3: { text: 'EXCEL导入', type: 'warning' }, |
| | | 4: { text: 'QMS系统', type: 'success' } |
| | | 1: { text: $t('pages.orders.transfer.status.sourceErp'), type: 'info' }, |
| | | 2: { text: $t('pages.orders.transfer.status.sourceWms'), type: 'primary' }, |
| | | 3: { text: $t('pages.orders.transfer.status.sourceExcel'), type: 'warning' }, |
| | | 4: { text: $t('pages.orders.transfer.status.sourceQms'), type: 'success' } |
| | | } |
| | | |
| | | const TRANSFER_EXCE_STATUS_META = { |
| | | 0: { text: '未执行', type: 'info' }, |
| | | 1: { text: '执行中', type: 'warning' }, |
| | | 2: { text: '执行完成', type: 'success' } |
| | | 0: { text: $t('pages.orders.transfer.status.pending'), type: 'info' }, |
| | | 1: { text: $t('pages.orders.transfer.status.running'), type: 'warning' }, |
| | | 2: { text: $t('pages.orders.transfer.status.completed'), type: 'success' } |
| | | } |
| | | |
| | | const TRANSFER_STATUS_META = { |
| | | 1: { text: '正常', type: 'success', bool: true }, |
| | | 0: { text: '冻结', type: 'danger', bool: false } |
| | | 1: { text: $t('pages.orders.transfer.status.normal'), type: 'success', bool: true }, |
| | | 0: { text: $t('pages.orders.transfer.status.frozen'), type: 'danger', bool: false } |
| | | } |
| | | |
| | | export const TRANSFER_REPORT_TITLE = '调拨单报表' |
| | | export const TRANSFER_REPORT_TITLE = $t('pages.orders.transfer.reportTitle') |
| | | export const TRANSFER_REPORT_STYLE = { |
| | | titleAlign: 'center', |
| | | titleLevel: 'strong', |
| | |
| | | |
| | | export function getTransferSourceOptions() { |
| | | return [ |
| | | { label: 'ERP系统', value: 1 }, |
| | | { label: 'WMS系统生成', value: 2 }, |
| | | { label: 'EXCEL导入', value: 3 }, |
| | | { label: 'QMS系统', value: 4 } |
| | | { label: $t('pages.orders.transfer.status.sourceErp'), value: 1 }, |
| | | { label: $t('pages.orders.transfer.status.sourceWms'), value: 2 }, |
| | | { label: $t('pages.orders.transfer.status.sourceExcel'), value: 3 }, |
| | | { label: $t('pages.orders.transfer.status.sourceQms'), value: 4 } |
| | | ] |
| | | } |
| | | |
| | | export function getTransferStatusOptions() { |
| | | return [ |
| | | { label: '正常', value: 1 }, |
| | | { label: '冻结', value: 0 } |
| | | { label: $t('pages.orders.transfer.status.normal'), value: 1 }, |
| | | { label: $t('pages.orders.transfer.status.frozen'), value: 0 } |
| | | ] |
| | | } |
| | | |
| | | export function getTransferExceStatusOptions() { |
| | | return [ |
| | | { label: '未执行', value: 0 }, |
| | | { label: '执行中', value: 1 }, |
| | | { label: '执行完成', value: 2 } |
| | | { label: $t('pages.orders.transfer.status.pending'), value: 0 }, |
| | | { label: $t('pages.orders.transfer.status.running'), value: 1 }, |
| | | { label: $t('pages.orders.transfer.status.completed'), value: 2 } |
| | | ] |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | export function normalizeTransferRow(record = {}) { |
| | | const statusMeta = metaByValue(record.statusBool ?? record.status, TRANSFER_STATUS_META, '未知') |
| | | const statusMeta = metaByValue(record.statusBool ?? record.status, TRANSFER_STATUS_META, $t('common.status.unknown')) |
| | | const exceStatusMeta = metaByValue(record.exceStatus, TRANSFER_EXCE_STATUS_META, record.exceStatusText) |
| | | const sourceMeta = metaByValue(record.source, TRANSFER_SOURCE_META, record.sourceText) |
| | | return { |
| | |
| | | } |
| | | |
| | | export function normalizeTransferOrderRow(record = {}) { |
| | | const statusMeta = metaByValue(record.statusBool ?? record.status, TRANSFER_STATUS_META, '未知') |
| | | const statusMeta = metaByValue(record.statusBool ?? record.status, TRANSFER_STATUS_META, $t('common.status.unknown')) |
| | | const exceStatusMeta = metaByValue(record.exceStatus, TRANSFER_EXCE_STATUS_META, record.exceStatusText) |
| | | return { |
| | | ...record, |
| | |
| | | export function getTransferActionList(row = {}) { |
| | | const normalizedRow = normalizeTransferRow(row) |
| | | const actions = [ |
| | | { key: 'view', label: '查看详情', icon: 'ri:eye-line' }, |
| | | { key: 'items', label: '明细', icon: 'ri:list-check-3' }, |
| | | { key: 'edit', label: '编辑', icon: 'ri:pencil-line' } |
| | | { key: 'view', label: $t('pages.orders.transfer.actions.view'), icon: 'ri:eye-line' }, |
| | | { key: 'items', label: $t('pages.orders.transfer.actions.items'), icon: 'ri:list-check-3' }, |
| | | { key: 'edit', label: $t('pages.orders.transfer.actions.edit'), icon: 'ri:pencil-line' } |
| | | ] |
| | | if (Number(normalizedRow.exceStatus) === 0) { |
| | | actions.push({ key: 'publish', label: '下发执行', icon: 'ri:send-plane-line' }) |
| | | actions.push({ key: 'delete', label: '删除', icon: 'ri:delete-bin-5-line', color: 'var(--art-error)' }) |
| | | actions.push({ key: 'publish', label: $t('pages.orders.transfer.actions.publish'), icon: 'ri:send-plane-line' }) |
| | | actions.push({ key: 'delete', label: $t('pages.orders.transfer.actions.delete'), icon: 'ri:delete-bin-5-line', color: 'var(--art-error)' }) |
| | | } |
| | | return actions |
| | | } |
| | |
| | | if (value === void 0) return null |
| | | return { |
| | | value, |
| | | label: normalizeText(item.name || item.areaName || item.code || item.warehouseId$ || item.warehouseName || `库区 ${value}`), |
| | | label: normalizeText(item.name || item.areaName || item.code || item.warehouseId$ || item.warehouseName || `${$t('menu.warehouseAreas')} ${value}`), |
| | | raw: item |
| | | } |
| | | }) |
| | |
| | | if (value === void 0) return null |
| | | return { |
| | | value, |
| | | label: normalizeText(item.label || item.name || item.dictLabel || `类型 ${value}`) |
| | | label: normalizeText(item.label || item.name || item.dictLabel || `${$t('pages.orders.transfer.dialog.type')} ${value}`) |
| | | } |
| | | }) |
| | | .filter(Boolean) |
| | |
| | | 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 { getTransferActionList } from './transferPage.helpers.js' |
| | | |
| | | export function createTransferTableColumns({ handleActionClick } = {}) { |
| | | return [ |
| | | { type: 'selection', width: 48, align: 'center' }, |
| | | { type: 'globalIndex', label: '序号', width: 72, align: 'center' }, |
| | | { type: 'globalIndex', label: $t('table.index'), width: 72, align: 'center' }, |
| | | { |
| | | prop: 'code', |
| | | label: '调拨单号', |
| | | label: $t('pages.orders.transfer.search.code'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.code || '--' |
| | | }, |
| | | { |
| | | prop: 'typeLabel', |
| | | label: '调拨类型', |
| | | label: $t('pages.orders.transfer.search.type'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.typeLabel || '--' |
| | | }, |
| | | { |
| | | prop: 'sourceText', |
| | | label: '来源', |
| | | label: $t('pages.orders.transfer.search.source'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => |
| | |
| | | }, |
| | | { |
| | | prop: 'orgWareName', |
| | | label: '源仓库', |
| | | label: $t('pages.orders.transfer.search.orgWareName'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.orgWareName || '--' |
| | | }, |
| | | { |
| | | prop: 'tarWareName', |
| | | label: '目标仓库', |
| | | label: $t('pages.orders.transfer.search.tarWareName'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.tarWareName || '--' |
| | | }, |
| | | { |
| | | prop: 'orgAreaName', |
| | | label: '源库区', |
| | | label: $t('pages.orders.transfer.search.orgAreaName'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.orgAreaName || '--' |
| | | }, |
| | | { |
| | | prop: 'tarAreaName', |
| | | label: '目标库区', |
| | | label: $t('pages.orders.transfer.search.tarAreaName'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.tarAreaName || '--' |
| | | }, |
| | | { |
| | | prop: 'exceStatusText', |
| | | label: '执行状态', |
| | | label: $t('pages.orders.transfer.search.exceStatus'), |
| | | minWidth: 120, |
| | | formatter: (row) => |
| | | h(ElTag, { type: row.exceStatusTagType || 'info', effect: 'light' }, () => row.exceStatusText || '--') |
| | | }, |
| | | { |
| | | prop: 'statusText', |
| | | label: '状态', |
| | | label: $t('pages.orders.transfer.search.status'), |
| | | width: 96, |
| | | align: 'center', |
| | | formatter: (row) => |
| | |
| | | }, |
| | | { |
| | | prop: 'updateTimeText', |
| | | label: '更新时间', |
| | | label: $t('table.updateTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.updateTimeText || '--' |
| | | }, |
| | | { |
| | | prop: 'createTimeText', |
| | | label: '创建时间', |
| | | label: $t('table.createTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.createTimeText || '--' |
| | | }, |
| | | { |
| | | prop: 'memo', |
| | | label: '备注', |
| | | label: $t('pages.orders.transfer.search.memo'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.memo || '--' |
| | | }, |
| | | { |
| | | prop: 'operation', |
| | | label: '操作', |
| | | label: $t('table.operation'), |
| | | width: 120, |
| | | align: 'center', |
| | | fixed: 'right', |
| | |
| | | |
| | | export function createTransferOrderTableColumns() { |
| | | return [ |
| | | { type: 'globalIndex', label: '序号', width: 72, align: 'center' }, |
| | | { type: 'globalIndex', label: $t('table.index'), width: 72, align: 'center' }, |
| | | { |
| | | prop: 'code', |
| | | label: '关联单号', |
| | | label: $t('pages.orders.transfer.detail.relatedCode'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.code || '--' |
| | | }, |
| | | { |
| | | prop: 'poCode', |
| | | label: '调拨单号', |
| | | label: $t('pages.orders.transfer.detail.code'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.poCode || '--' |
| | | }, |
| | | { |
| | | prop: 'typeLabel', |
| | | label: '单据类型', |
| | | label: $t('pages.orders.transfer.detail.type'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.typeLabel || '--' |
| | | }, |
| | | { |
| | | prop: 'wkTypeLabel', |
| | | label: '业务类型', |
| | | label: $t('pages.orders.transfer.detail.wkType'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.wkTypeLabel || '--' |
| | | }, |
| | | { |
| | | prop: 'exceStatusText', |
| | | label: '执行状态', |
| | | label: $t('pages.orders.transfer.detail.exceStatus'), |
| | | minWidth: 120, |
| | | formatter: (row) => |
| | | h(ElTag, { type: row.exceStatusTagType || 'info', effect: 'light' }, () => row.exceStatusText || '--') |
| | | }, |
| | | { |
| | | prop: 'statusText', |
| | | label: '状态', |
| | | label: $t('pages.orders.transfer.detail.status'), |
| | | width: 96, |
| | | align: 'center', |
| | | formatter: (row) => |
| | |
| | | }, |
| | | { |
| | | prop: 'anfme', |
| | | label: '数量', |
| | | label: $t('table.quantity'), |
| | | width: 110, |
| | | align: 'right', |
| | | formatter: (row) => row.anfme ?? '--' |
| | | }, |
| | | { |
| | | prop: 'workQty', |
| | | label: '执行数量', |
| | | label: $t('pages.orders.transfer.detail.workQty'), |
| | | width: 110, |
| | | align: 'right', |
| | | formatter: (row) => row.workQty ?? '--' |
| | | }, |
| | | { |
| | | prop: 'qty', |
| | | label: '已完成数量', |
| | | label: $t('pages.orders.transfer.detail.qty'), |
| | | width: 110, |
| | | align: 'right', |
| | | formatter: (row) => row.qty ?? '--' |
| | | }, |
| | | { |
| | | prop: 'stationId', |
| | | label: '站点', |
| | | label: $t('pages.orders.transfer.detail.stationId'), |
| | | minWidth: 120, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.stationId || '--' |
| | | }, |
| | | { |
| | | prop: 'businessTimeText', |
| | | label: '业务时间', |
| | | label: $t('pages.orders.transfer.detail.businessTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.businessTimeText || '--' |
| | | }, |
| | | { |
| | | prop: 'createTimeText', |
| | | label: '创建时间', |
| | | label: $t('table.createTime'), |
| | | minWidth: 170, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.createTimeText || '--' |
| | |
| | | import { ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { $t } from '@/locales' |
| | | |
| | | export function useCrudPage({ |
| | | createEmptyModel, |
| | |
| | | try { |
| | | if (dialogType.value === 'edit') { |
| | | await updateRequest(payload) |
| | | ElMessage.success('修改成功') |
| | | ElMessage.success($t('crud.messages.updateSuccess')) |
| | | closeDialog() |
| | | await refreshUpdate?.() |
| | | return |
| | | } |
| | | |
| | | await saveRequest(payload) |
| | | ElMessage.success('新增成功') |
| | | ElMessage.success($t('crud.messages.createSuccess')) |
| | | closeDialog() |
| | | await refreshCreate?.() |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '提交失败') |
| | | ElMessage.error(error?.message || $t('crud.messages.submitFailed')) |
| | | } |
| | | } |
| | | |
| | | const handleDelete = async (record) => { |
| | | try { |
| | | const recordLabel = resolveRecordLabel?.(record) || record?.id |
| | | await ElMessageBox.confirm(`确定要删除${entityName}「${recordLabel}」吗?`, '删除确认', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | await ElMessageBox.confirm($t('crud.confirm.deleteMessage', { entity: entityName, label: recordLabel }), $t('crud.confirm.deleteTitle'), { |
| | | confirmButtonText: $t('common.confirm'), |
| | | cancelButtonText: $t('common.cancel'), |
| | | type: 'warning' |
| | | }) |
| | | await deleteRequest(record.id) |
| | | ElMessage.success('删除成功') |
| | | ElMessage.success($t('crud.messages.deleteSuccess')) |
| | | await refreshRemove?.() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error(error?.message || '删除失败') |
| | | ElMessage.error(error?.message || $t('crud.messages.deleteFailed')) |
| | | } |
| | | } |
| | | } |
| | |
| | | if (!ids.length) return |
| | | |
| | | try { |
| | | await ElMessageBox.confirm(`确定要批量删除选中的 ${ids.length} 个${entityName}吗?`, '批量删除确认', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | await ElMessageBox.confirm($t('crud.confirm.batchDeleteMessage', { count: ids.length, entity: entityName }), $t('crud.confirm.batchDeleteTitle'), { |
| | | confirmButtonText: $t('common.confirm'), |
| | | cancelButtonText: $t('common.cancel'), |
| | | type: 'warning' |
| | | }) |
| | | await deleteRequest(ids.join(',')) |
| | | ElMessage.success('批量删除成功') |
| | | ElMessage.success($t('crud.messages.batchDeleteSuccess')) |
| | | selectedRows.value = [] |
| | | await refreshRemove?.() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error(error?.message || '批量删除失败') |
| | | ElMessage.error(error?.message || $t('crud.messages.batchDeleteFailed')) |
| | | } |
| | | } |
| | | } |
| | |
| | | import { ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { $t } from '@/locales' |
| | | |
| | | export function usePrintExportPage({ |
| | | downloadFileName, |
| | |
| | | try { |
| | | const response = await guardRequestWithMessage(requestExport(payload), null, { |
| | | timeoutMs, |
| | | timeoutMessage: '导出请求超时,已停止等待' |
| | | timeoutMessage: $t('message.exportTimeoutStopped') |
| | | }) |
| | | if (!response) { |
| | | return |
| | | } |
| | | if (!response.ok) { |
| | | throw new Error(`导出失败 (${response.status})`) |
| | | throw new Error($t('crud.messages.exportFailedWithStatus', { status: response.status })) |
| | | } |
| | | |
| | | const blob = await response.blob() |
| | |
| | | link.click() |
| | | link.remove() |
| | | window.URL.revokeObjectURL(downloadUrl) |
| | | ElMessage.success('导出成功') |
| | | ElMessage.success($t('crud.messages.exportSuccess')) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '导出失败') |
| | | ElMessage.error(error?.message || $t('crud.messages.exportFailed')) |
| | | } |
| | | } |
| | | |
| | |
| | | try { |
| | | const records = await guardRequestWithMessage(resolvePrintRecords(payload), null, { |
| | | timeoutMs, |
| | | timeoutMessage: '打印数据加载超时,已停止等待' |
| | | timeoutMessage: $t('message.printTimeoutStopped') |
| | | }) |
| | | if (activePrintToken.value !== token) { |
| | | return |
| | |
| | | if (activePrintToken.value !== token) { |
| | | return |
| | | } |
| | | ElMessage.error(error?.message || '打印失败') |
| | | ElMessage.error(error?.message || $t('crud.messages.printFailed')) |
| | | } |
| | | } |
| | | |
| | |
| | | <!-- 菜单管理页面 --> |
| | | <template> |
| | | <div class="menu-page art-full-height"> |
| | | <ArtSearchBar |
| | |
| | | @refresh="handleRefresh" |
| | | > |
| | | <template #left> |
| | | <ElButton v-auth="'add'" @click="handleAddMenu" v-ripple>添加菜单</ElButton> |
| | | <ElButton v-auth="'add'" @click="handleAddMenu" v-ripple>{{ t('pages.system.menu.buttons.add') }}</ElButton> |
| | | <ElButton @click="toggleExpand" v-ripple> |
| | | {{ isExpanded ? '收起' : '展开' }} |
| | | {{ isExpanded ? t('pages.system.menu.actions.collapse') : t('pages.system.menu.actions.expand') }} |
| | | </ElButton> |
| | | </template> |
| | | </ArtTableHeader> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, nextTick, onMounted, reactive, ref } from 'vue' |
| | | import { useI18n } from 'vue-i18n' |
| | | import MenuDialog from './modules/menu-dialog.vue' |
| | | |
| | | import { formatMenuTitle } from '@/utils/router' |
| | |
| | | } from './menuPage.helpers' |
| | | |
| | | defineOptions({ name: 'Menus' }) |
| | | const { t } = useI18n() |
| | | |
| | | const loading = ref(false) |
| | | const isExpanded = ref(false) |
| | |
| | | |
| | | const formItems = computed(() => [ |
| | | { |
| | | label: '菜单名称', |
| | | label: t('pages.system.menu.search.name'), |
| | | key: 'name', |
| | | type: 'input', |
| | | props: { clearable: true } |
| | | }, |
| | | { |
| | | label: '路由地址', |
| | | label: t('pages.system.menu.search.route'), |
| | | key: 'route', |
| | | type: 'input', |
| | | props: { clearable: true } |
| | |
| | | loading.value = true |
| | | try { |
| | | const list = await guardRequestWithMessage(fetchGetMenuList({}), null, { |
| | | timeoutMessage: '菜单加载超时,已停止等待' |
| | | timeoutMessage: t('pages.system.menu.messages.loadTimeout') |
| | | }) |
| | | if (list === null) { |
| | | tableData.value = [] |
| | |
| | | tableData.value = Array.isArray(list) ? list : [] |
| | | menuTreeOptions.value = buildMenuTreeOptions(tableData.value, formatMenuTitle) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '获取菜单失败') |
| | | ElMessage.error(error?.message || t('pages.system.menu.messages.loadFailed')) |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | |
| | | async function handleSubmit(formData) { |
| | | const payload = buildMenuSubmitPayload(formData) |
| | | if (payload.id && payload.id === payload.parentId) { |
| | | ElMessage.error('上级菜单不能选择当前菜单') |
| | | ElMessage.error(t('pages.system.menu.messages.menuSelfParent')) |
| | | return |
| | | } |
| | | |
| | | try { |
| | | if (payload.id) { |
| | | await fetchUpdateMenu(payload) |
| | | ElMessage.success('修改成功') |
| | | ElMessage.success(t('crud.messages.updateSuccess')) |
| | | } else { |
| | | await fetchSaveMenu(payload) |
| | | ElMessage.success('新增成功') |
| | | ElMessage.success(t('crud.messages.createSuccess')) |
| | | } |
| | | closeDialog() |
| | | await loadMenuResources() |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '提交失败') |
| | | ElMessage.error(error?.message || t('pages.system.menu.messages.submitFailed')) |
| | | } |
| | | } |
| | | |
| | | async function handleDeleteMenu(row) { |
| | | try { |
| | | await ElMessageBox.confirm( |
| | | `确定要删除菜单「${getMenuDisplayTitle(row, formatMenuTitle)}」吗?删除后无法恢复`, |
| | | '删除确认', |
| | | t('pages.system.menu.messages.deleteMenuConfirm', { |
| | | title: getMenuDisplayTitle(row, formatMenuTitle) |
| | | }), |
| | | t('crud.confirm.deleteTitle'), |
| | | { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | confirmButtonText: t('common.confirm'), |
| | | cancelButtonText: t('common.cancel'), |
| | | type: 'warning' |
| | | } |
| | | ) |
| | | await fetchDeleteMenu(row.id) |
| | | ElMessage.success('删除成功') |
| | | ElMessage.success(t('crud.messages.deleteSuccess')) |
| | | await loadMenuResources() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error(error?.message || '删除失败') |
| | | ElMessage.error(error?.message || t('crud.messages.deleteFailed')) |
| | | } |
| | | } |
| | | } |
| | | |
| | | async function handleDeleteAuth(row) { |
| | | try { |
| | | await ElMessageBox.confirm(`确定要删除权限「${row.name || row.authority || row.id}」吗?删除后无法恢复`, '删除确认', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }) |
| | | await ElMessageBox.confirm( |
| | | t('pages.system.menu.messages.deleteAuthConfirm', { |
| | | title: row.name || row.authority || row.id |
| | | }), |
| | | t('crud.confirm.deleteTitle'), |
| | | { |
| | | confirmButtonText: t('common.confirm'), |
| | | cancelButtonText: t('common.cancel'), |
| | | type: 'warning' |
| | | } |
| | | ) |
| | | await fetchDeleteMenu(row.id) |
| | | ElMessage.success('删除成功') |
| | | ElMessage.success(t('crud.messages.deleteSuccess')) |
| | | await loadMenuResources() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error(error?.message || '删除失败') |
| | | ElMessage.error(error?.message || t('crud.messages.deleteFailed')) |
| | | } |
| | | } |
| | | } |
| | |
| | | import { $t } from '@/locales' |
| | | |
| | | export function createMenuSearchState() { |
| | | return { |
| | | name: '', |
| | |
| | | if (!title) { |
| | | return '' |
| | | } |
| | | return String(title).split('.').pop() || String(title) |
| | | return String(title).trim() |
| | | } |
| | | |
| | | export function getMenuDisplayTitle(row = {}, titleFormatter = defaultMenuTitleFormatter) { |
| | |
| | | } |
| | | |
| | | export function getMenuTypeText(row = {}) { |
| | | if (row.meta?.isAuthButton || Number(row.type) === 1) return '按钮' |
| | | if (hasNestedMenus(row)) return '目录' |
| | | return '菜单' |
| | | if (row.meta?.isAuthButton || Number(row.type) === 1) return $t('pages.system.menu.types.button') |
| | | if (hasNestedMenus(row)) return $t('pages.system.menu.types.directory') |
| | | return $t('pages.system.menu.types.menu') |
| | | } |
| | | |
| | | export function getMenuStatusMeta(status) { |
| | | return normalizeMenuNumber(status, 1) === 1 |
| | | ? { text: '启用', type: 'success' } |
| | | : { text: '禁用', type: 'danger' } |
| | | ? { text: $t('common.status.enabled'), type: 'success' } |
| | | : { text: $t('common.status.disabled'), type: 'danger' } |
| | | } |
| | | |
| | | export function normalizeMenuTreeOptions(nodes = [], titleFormatter = defaultMenuTitleFormatter) { |
| | |
| | | export function buildMenuTreeOptions(tree = [], titleFormatter = defaultMenuTitleFormatter) { |
| | | return [ |
| | | { |
| | | label: '顶级菜单', |
| | | label: $t('table.topLevelMenu'), |
| | | value: 0, |
| | | children: normalizeMenuTreeOptions(tree, titleFormatter) |
| | | } |
| | |
| | | import { h } from 'vue' |
| | | import { ElTag } from 'element-plus' |
| | | import { $t } from '@/locales' |
| | | import ArtSvgIcon from '@/components/core/base/art-svg-icon/index.vue' |
| | | import ArtButtonTable from '@/components/core/forms/art-button-table/index.vue' |
| | | import { |
| | |
| | | return [ |
| | | { |
| | | prop: 'meta.title', |
| | | label: '菜单名称', |
| | | label: $t('pages.system.menu.search.name'), |
| | | minWidth: 180, |
| | | formatter: (row) => getMenuDisplayTitle(row, titleFormatter) |
| | | }, |
| | | { |
| | | prop: 'meta.icon', |
| | | label: '图标预览', |
| | | label: $t('table.iconPreview'), |
| | | width: 96, |
| | | align: 'center', |
| | | formatter: (row) => { |
| | |
| | | }, |
| | | { |
| | | prop: 'type', |
| | | label: '菜单类型', |
| | | label: $t('table.menuType'), |
| | | width: 110, |
| | | formatter: (row) => |
| | | h(ElTag, { type: getMenuTypeTag(row), effect: 'light' }, () => getMenuTypeText(row)) |
| | | }, |
| | | { |
| | | prop: 'route', |
| | | label: '路由', |
| | | label: $t('pages.system.menu.search.route'), |
| | | minWidth: 180, |
| | | formatter: (row) => { |
| | | if (row.meta?.isAuthButton) return '' |
| | |
| | | }, |
| | | { |
| | | prop: 'component', |
| | | label: '组件标识', |
| | | label: $t('table.componentKey'), |
| | | minWidth: 160, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => { |
| | |
| | | }, |
| | | { |
| | | prop: 'authority', |
| | | label: '权限标识', |
| | | label: $t('table.permissionKey'), |
| | | minWidth: 180, |
| | | formatter: (row) => { |
| | | if (row.meta?.isAuthButton) { |
| | | return row.authority || row.meta?.authMark || '' |
| | | } |
| | | if (!row.meta?.authList?.length) return row.authority || '' |
| | | return `${row.meta.authList.length} 个权限标识` |
| | | return $t('pages.system.menu.messages.authCount', { |
| | | count: row.meta.authList.length |
| | | }) |
| | | } |
| | | }, |
| | | { |
| | | prop: 'sort', |
| | | label: '排序', |
| | | label: $t('table.sort'), |
| | | width: 90 |
| | | }, |
| | | { |
| | | prop: 'id', |
| | | label: 'ID', |
| | | label: $t('table.id'), |
| | | width: 96, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | prop: 'status', |
| | | label: '状态', |
| | | label: $t('table.status'), |
| | | width: 100, |
| | | formatter: (row) => { |
| | | const statusMeta = getMenuStatusMeta(row.status) |
| | |
| | | }, |
| | | { |
| | | prop: 'memo', |
| | | label: '备注', |
| | | label: $t('table.remark'), |
| | | minWidth: 180, |
| | | showOverflowTooltip: true, |
| | | formatter: (row) => row.memo || '-' |
| | | }, |
| | | { |
| | | prop: 'operation', |
| | | label: '操作', |
| | | label: $t('table.operation'), |
| | | width: 180, |
| | | align: 'center', |
| | | formatter: (row) => { |
| | |
| | | h(ArtButtonTable, { |
| | | type: 'add', |
| | | onClick: () => handleAddAuth(row), |
| | | title: '新增权限' |
| | | title: $t('pages.system.menu.actions.addAuth') |
| | | }), |
| | | h(ArtButtonTable, { |
| | | type: 'edit', |
| | |
| | | > |
| | | <template #menuType> |
| | | <ElRadioGroup v-model="form.menuType" :disabled="disableMenuType"> |
| | | <ElRadioButton value="menu">菜单</ElRadioButton> |
| | | <ElRadioButton value="button">按钮</ElRadioButton> |
| | | <ElRadioButton value="menu">{{ t('pages.system.menu.form.typeMenu') }}</ElRadioButton> |
| | | <ElRadioButton value="button">{{ t('pages.system.menu.form.typeButton') }}</ElRadioButton> |
| | | </ElRadioGroup> |
| | | </template> |
| | | </ArtForm> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">取消</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">确定</ElButton> |
| | | <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">{{ t('common.confirm') }}</ElButton> |
| | | </span> |
| | | </template> |
| | | </ElDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useI18n } from 'vue-i18n' |
| | | import ArtForm from '@/components/core/forms/art-form/index.vue' |
| | | |
| | | const createMenuFormState = () => ({ |
| | |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | | const { t } = useI18n() |
| | | const formRef = ref() |
| | | const form = reactive(createMenuFormState()) |
| | | |
| | | const isEdit = computed(() => Boolean(form.id)) |
| | | const dialogTitle = computed(() => `${isEdit.value ? '编辑' : '新建'}${form.menuType === 'button' ? '按钮' : '菜单'}`) |
| | | const dialogTitle = computed(() => |
| | | form.menuType === 'button' |
| | | ? t(isEdit.value ? 'pages.system.menu.form.titleEditButton' : 'pages.system.menu.form.titleAddButton') |
| | | : t(isEdit.value ? 'pages.system.menu.form.titleEditMenu' : 'pages.system.menu.form.titleAddMenu') |
| | | ) |
| | | const disableMenuType = computed(() => props.lockType || isEdit.value) |
| | | |
| | | const rules = computed(() => ({ |
| | | name: [{ required: true, message: form.menuType === 'button' ? '请输入权限名称' : '请输入菜单名称', trigger: 'blur' }], |
| | | name: [{ required: true, message: form.menuType === 'button' ? t('pages.system.menu.form.validationButtonName') : t('pages.system.menu.form.validationMenuName'), trigger: 'blur' }], |
| | | route: |
| | | form.menuType === 'menu' |
| | | ? [{ required: true, message: '请输入路由地址', trigger: 'blur' }] |
| | | ? [{ required: true, message: t('pages.system.menu.form.validationRoute'), trigger: 'blur' }] |
| | | : [], |
| | | authority: |
| | | form.menuType === 'button' |
| | | ? [{ required: true, message: '请输入权限标识', trigger: 'blur' }] |
| | | ? [{ required: true, message: t('pages.system.menu.form.validationAuthority'), trigger: 'blur' }] |
| | | : [] |
| | | })) |
| | | |
| | | const formItems = computed(() => { |
| | | const items = [ |
| | | { label: '菜单类型', key: 'menuType', span: 24 }, |
| | | { label: t('pages.system.menu.form.menuType'), key: 'menuType', span: 24 }, |
| | | { |
| | | label: '上级菜单', |
| | | label: t('pages.system.menu.form.parentId'), |
| | | key: 'parentId', |
| | | type: 'treeselect', |
| | | span: 24, |
| | |
| | | value: 'value', |
| | | children: 'children' |
| | | }, |
| | | placeholder: '请选择上级菜单', |
| | | placeholder: t('pages.system.menu.form.placeholderParent'), |
| | | checkStrictly: true, |
| | | clearable: false, |
| | | defaultExpandAll: true |
| | | } |
| | | }, |
| | | { |
| | | label: form.menuType === 'button' ? '权限名称' : '菜单名称', |
| | | label: form.menuType === 'button' ? t('pages.system.menu.form.nameButton') : t('pages.system.menu.form.nameMenu'), |
| | | key: 'name', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | placeholder: form.menuType === 'button' ? '请输入权限名称' : '请输入菜单名称', |
| | | placeholder: form.menuType === 'button' ? t('pages.system.menu.form.placeholderButtonName') : t('pages.system.menu.form.placeholderMenuName'), |
| | | clearable: true |
| | | } |
| | | } |
| | |
| | | if (form.menuType === 'menu') { |
| | | items.push( |
| | | { |
| | | label: '路由地址', |
| | | label: t('pages.system.menu.form.route'), |
| | | key: 'route', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | placeholder: '请输入路由地址', |
| | | placeholder: t('pages.system.menu.form.placeholderRoute'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: '组件标识', |
| | | label: t('pages.system.menu.form.component'), |
| | | key: 'component', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | placeholder: '请输入组件标识', |
| | | placeholder: t('pages.system.menu.form.placeholderComponent'), |
| | | clearable: true |
| | | } |
| | | } |
| | |
| | | |
| | | items.push( |
| | | { |
| | | label: '权限标识', |
| | | label: t('pages.system.menu.form.authority'), |
| | | key: 'authority', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | placeholder: '请输入权限标识', |
| | | placeholder: t('pages.system.menu.form.placeholderAuthority'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: '图标', |
| | | label: t('pages.system.menu.form.icon'), |
| | | key: 'icon', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | placeholder: '请输入图标名称', |
| | | placeholder: t('pages.system.menu.form.placeholderIcon'), |
| | | clearable: true |
| | | } |
| | | }, |
| | | { |
| | | label: '排序', |
| | | label: t('pages.system.menu.form.sort'), |
| | | key: 'sort', |
| | | type: 'number', |
| | | span: 24, |
| | |
| | | } |
| | | }, |
| | | { |
| | | label: '状态', |
| | | label: t('pages.system.menu.form.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | span: 24, |
| | | props: { |
| | | placeholder: '请选择状态', |
| | | placeholder: t('pages.system.menu.form.placeholderStatus'), |
| | | options: [ |
| | | { label: '启用', value: 1 }, |
| | | { label: '禁用', value: 0 } |
| | | { label: t('common.status.enabled'), value: 1 }, |
| | | { label: t('common.status.disabled'), value: 0 } |
| | | ] |
| | | } |
| | | }, |
| | | { |
| | | label: '备注', |
| | | label: t('pages.system.menu.form.memo'), |
| | | key: 'memo', |
| | | type: 'input', |
| | | span: 24, |
| | | props: { |
| | | type: 'textarea', |
| | | rows: 3, |
| | | placeholder: '请输入备注', |
| | | placeholder: t('pages.system.menu.form.placeholderMemo'), |
| | | clearable: true |
| | | } |
| | | } |
| | |
| | | > |
| | | <template #left> |
| | | <ElSpace wrap> |
| | | <ElButton v-auth="'add'" @click="showDialog('add')" v-ripple>新增角色</ElButton> |
| | | <ElButton v-auth="'add'" @click="showDialog('add')" v-ripple>{{ t('pages.system.role.buttons.add') }}</ElButton> |
| | | <ElButton |
| | | v-auth="'delete'" |
| | | type="danger" |
| | |
| | | @click="handleBatchDelete" |
| | | v-ripple |
| | | > |
| | | 批量删除 |
| | | {{ t('common.actions.batchDelete') }} |
| | | </ElButton> |
| | | <span v-auth="'query'" class="inline-flex"> |
| | | <ListExportPrint |
| | |
| | | |
| | | <script setup> |
| | | import { useUserStore } from '@/store/modules/user' |
| | | import { useI18n } from 'vue-i18n' |
| | | import { |
| | | fetchExportRoleReport, |
| | | fetchDeleteRole, |
| | |
| | | buildRoleSavePayload, |
| | | buildRoleSearchParams, |
| | | createRoleSearchState, |
| | | getRoleReportTitle, |
| | | getRolePaginationKey, |
| | | normalizeRoleListRow, |
| | | ROLE_REPORT_STYLE, |
| | | ROLE_REPORT_TITLE, |
| | | resolveRoleReportColumns |
| | | } from './rolePage.helpers' |
| | | |
| | | defineOptions({ name: 'Role' }) |
| | | const { t } = useI18n() |
| | | |
| | | const searchForm = ref(createRoleSearchState()) |
| | | const showSearchBar = ref(false) |
| | | const permissionDialogVisible = ref(false) |
| | | const permissionScopeType = ref('menu') |
| | | const userStore = useUserStore() |
| | | const reportTitle = ROLE_REPORT_TITLE |
| | | const reportTitle = computed(() => getRoleReportTitle()) |
| | | const reportQueryParams = computed(() => buildRoleSearchParams(searchForm.value)) |
| | | const roleActionHandlers = { |
| | | 'scope-menu': (row) => openScopeDialog('menu', row), |
| | |
| | | saveRequest: fetchSaveRole, |
| | | updateRequest: fetchUpdateRole, |
| | | deleteRequest: fetchDeleteRole, |
| | | entityName: '角色', |
| | | entityName: t('pages.system.role.entity'), |
| | | resolveRecordLabel: (record) => record?.name || record?.code || record?.id, |
| | | refreshCreate, |
| | | refreshUpdate, |
| | |
| | | const buildPreviewDialogMeta = (rows) => { |
| | | const now = new Date() |
| | | return { |
| | | reportTitle, |
| | | reportTitle: reportTitle.value, |
| | | reportDate: now.toLocaleDateString('zh-CN'), |
| | | printedAt: now.toLocaleString('zh-CN', { hour12: false }), |
| | | operator: userStore.getUserInfo?.name || userStore.getUserInfo?.username || '', |
| | |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <ElButton @click="handleCancel">取消</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">确定</ElButton> |
| | | <ElButton @click="handleCancel">{{ t('common.cancel') }}</ElButton> |
| | | <ElButton type="primary" @click="handleSubmit">{{ t('common.confirm') }}</ElButton> |
| | | </span> |
| | | </template> |
| | | </ElDialog> |
| | |
| | | <script setup> |
| | | import ArtForm from '@/components/core/forms/art-form/index.vue' |
| | | import { buildRoleDialogModel, createRoleFormState, getRoleStatusOptions } from '../rolePage.helpers' |
| | | import { useI18n } from 'vue-i18n' |
| | | |
| | | const props = defineProps({ |
| | | visible: { required: false, default: false }, |
| | |
| | | const emit = defineEmits(['update:visible', 'submit']) |
| | | const formRef = ref() |
| | | const form = reactive(createRoleFormState()) |
| | | const { t } = useI18n() |
| | | |
| | | const isEdit = computed(() => props.dialogType === 'edit') |
| | | const dialogTitle = computed(() => (isEdit.value ? '编辑角色' : '新增角色')) |
| | | const dialogTitle = computed(() => |
| | | isEdit.value ? t('pages.system.role.dialog.editTitle') : t('pages.system.role.dialog.addTitle') |
| | | ) |
| | | |
| | | const rules = computed(() => ({ |
| | | name: [{ required: true, message: '请输入角色名称', trigger: 'blur' }] |
| | | name: [{ required: true, message: t('pages.system.role.dialog.validationName'), trigger: 'blur' }] |
| | | })) |
| | | |
| | | function createInputFormItem(label, key, placeholder, extraProps = {}, extraConfig = {}) { |
| | |
| | | } |
| | | |
| | | const formItems = computed(() => [ |
| | | createInputFormItem('角色名称', 'name', '请输入角色名称'), |
| | | createInputFormItem('角色编码', 'code', '请输入角色编码'), |
| | | createSelectFormItem('状态', 'status', '请选择状态', getRoleStatusOptions()), |
| | | createInputFormItem('备注', 'memo', '请输入备注', { type: 'textarea', rows: 3 }, { span: 24 }) |
| | | createInputFormItem( |
| | | t('pages.system.role.dialog.name'), |
| | | 'name', |
| | | t('pages.system.role.dialog.namePlaceholder') |
| | | ), |
| | | createInputFormItem( |
| | | t('pages.system.role.dialog.code'), |
| | | 'code', |
| | | t('pages.system.role.dialog.codePlaceholder') |
| | | ), |
| | | createSelectFormItem( |
| | | t('pages.system.role.dialog.status'), |
| | | 'status', |
| | | t('pages.system.role.dialog.statusPlaceholder'), |
| | | getRoleStatusOptions() |
| | | ), |
| | | createInputFormItem( |
| | | t('pages.system.role.dialog.memo'), |
| | | 'memo', |
| | | t('pages.system.role.dialog.memoPlaceholder'), |
| | | { type: 'textarea', rows: 3 }, |
| | | { span: 24 } |
| | | ) |
| | | ]) |
| | | |
| | | const resetForm = () => { |
| | |
| | | <template> |
| | | <ElDrawer |
| | | :model-value="visible" |
| | | title="角色权限" |
| | | :title="t('pages.system.role.permission.title')" |
| | | size="860px" |
| | | destroy-on-close |
| | | @update:model-value="handleVisibleChange" |
| | | @closed="handleClosed" |
| | | > |
| | | <div class="mb-4 text-sm text-[var(--art-text-secondary)]"> |
| | | 当前角色:{{ roleLabel }} |
| | | {{ t('pages.system.role.permission.currentRole') }}{{ roleLabel }} |
| | | </div> |
| | | |
| | | <ElTabs v-model="activeScopeType" class="role-scope-tabs"> |
| | |
| | | <div v-else class="space-y-3"> |
| | | <div class="flex items-center justify-between gap-3"> |
| | | <ElSpace wrap> |
| | | <ElButton @click="handleSelectAll(config.scopeType)">全选</ElButton> |
| | | <ElButton @click="handleClear(config.scopeType)">清空</ElButton> |
| | | <ElButton @click="handleSelectAll(config.scopeType)">{{ t('pages.system.role.permission.selectAll') }}</ElButton> |
| | | <ElButton @click="handleClear(config.scopeType)">{{ t('pages.system.role.permission.clear') }}</ElButton> |
| | | </ElSpace> |
| | | <ElButton type="primary" @click="handleSave(config.scopeType)">保存当前权限</ElButton> |
| | | <ElButton type="primary" @click="handleSave(config.scopeType)">{{ t('pages.system.role.permission.saveCurrent') }}</ElButton> |
| | | </div> |
| | | |
| | | <div class="flex items-center gap-3"> |
| | | <ElInput |
| | | v-model.trim="scopeState[config.scopeType].condition" |
| | | clearable |
| | | placeholder="搜索权限树" |
| | | :placeholder="t('pages.system.role.permission.searchPlaceholder')" |
| | | @clear="handleSearch(config.scopeType)" |
| | | @keyup.enter="handleSearch(config.scopeType)" |
| | | /> |
| | | <ElButton @click="handleSearch(config.scopeType)">搜索</ElButton> |
| | | <ElButton @click="handleSearch(config.scopeType)">{{ t('common.actions.search') }}</ElButton> |
| | | </div> |
| | | |
| | | <ElScrollbar height="56vh"> |
| | |
| | | <div class="flex items-center gap-2"> |
| | | <span>{{ resolveScopeNodeLabel(data) }}</span> |
| | | <ElTag v-if="data.isAuthButton" type="info" effect="plain" size="small"> |
| | | 按钮 |
| | | {{ t('pages.system.role.permission.authButton') }} |
| | | </ElTag> |
| | | </div> |
| | | </template> |
| | |
| | | } from '../rolePage.helpers' |
| | | import { fetchGetRoleScopeList, fetchGetRoleScopeTree, fetchUpdateRoleScope } from '@/api/system-manage' |
| | | import { resolveBackendMenuTitle } from '@/utils/backend-menu-title' |
| | | import { formatMenuTitle } from '@/utils/router' |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { ElMessage } from 'element-plus' |
| | | import { useI18n } from 'vue-i18n' |
| | | |
| | | const props = defineProps({ |
| | | visible: { required: false, default: false }, |
| | |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:visible', 'success']) |
| | | const { t } = useI18n() |
| | | |
| | | const scopeConfigs = ['menu', 'pda', 'matnr', 'warehouse'].map((scopeType) => getRoleScopeConfig(scopeType)) |
| | | const activeScopeType = ref(props.scopeType || 'menu') |
| | |
| | | set: (value) => emit('update:visible', value) |
| | | }) |
| | | |
| | | const roleLabel = computed(() => props.roleData?.name || props.roleData?.code || '未选择角色') |
| | | const roleLabel = computed(() => props.roleData?.name || props.roleData?.code || t('pages.system.role.permission.unselected')) |
| | | |
| | | function createScopeTabState() { |
| | | return { |
| | |
| | | Promise.all([selectionRequest, treeRequest]), |
| | | null, |
| | | { |
| | | timeoutMessage: `${config.title}加载超时,已停止等待` |
| | | timeoutMessage: t('pages.system.role.permission.scopeLoadTimeout', { title: config.title }) |
| | | } |
| | | ) |
| | | if (!guardedResult) { |
| | |
| | | state.halfCheckedKeys = [] |
| | | state.loaded = true |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || `加载${config.title}失败`) |
| | | ElMessage.error(error?.message || t('pages.system.role.permission.scopeLoadFailed', { title: config.title })) |
| | | } finally { |
| | | state.loading = false |
| | | nextTick(() => { |
| | |
| | | scopeState[scopeType].halfCheckedKeys |
| | | ) |
| | | ) |
| | | ElMessage.success('权限保存成功') |
| | | ElMessage.success(t('pages.system.role.permission.saveSuccess')) |
| | | emit('success') |
| | | visible.value = false |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || '权限保存失败') |
| | | ElMessage.error(error?.message || t('pages.system.role.permission.saveFailed')) |
| | | } |
| | | } |
| | | |
| | |
| | | if (!rawLabel) { |
| | | return '' |
| | | } |
| | | return resolveBackendMenuTitle(rawLabel) |
| | | if (activeScopeType.value === 'menu') { |
| | | const resolvedTitle = resolveBackendMenuTitle(rawLabel, data?.component || '') |
| | | return resolvedTitle ? formatMenuTitle(resolvedTitle) : '' |
| | | } |
| | | return rawLabel |
| | | } |
| | | |
| | | const handleClosed = () => { |
| | |
| | | |
| | | <script setup> |
| | | import { createRoleSearchState, getRoleStatusOptions } from '../rolePage.helpers' |
| | | import { useI18n } from 'vue-i18n' |
| | | |
| | | const props = defineProps({ |
| | | modelValue: { required: true } |
| | |
| | | |
| | | const emit = defineEmits(['update:modelValue', 'search', 'reset']) |
| | | const searchBarRef = ref() |
| | | const { t } = useI18n() |
| | | |
| | | const formData = computed({ |
| | | get: () => props.modelValue, |
| | |
| | | } |
| | | |
| | | const formItems = computed(() => [ |
| | | createInputSearchItem('角色名称', 'name', '请输入角色名称'), |
| | | createInputSearchItem('角色编码', 'code', '请输入角色编码'), |
| | | createInputSearchItem('备注', 'memo', '请输入备注'), |
| | | createInputSearchItem('关键字', 'condition', '输入关键字搜索'), |
| | | createSelectSearchItem('状态', 'status', '请选择状态', getRoleStatusOptions()) |
| | | createInputSearchItem( |
| | | t('pages.system.role.search.name'), |
| | | 'name', |
| | | t('pages.system.role.search.namePlaceholder') |
| | | ), |
| | | createInputSearchItem( |
| | | t('pages.system.role.search.code'), |
| | | 'code', |
| | | t('pages.system.role.search.codePlaceholder') |
| | | ), |
| | | createInputSearchItem( |
| | | t('pages.system.role.search.memo'), |
| | | 'memo', |
| | | t('pages.system.role.search.memoPlaceholder') |
| | | ), |
| | | createInputSearchItem( |
| | | t('pages.system.role.search.condition'), |
| | | 'condition', |
| | | t('pages.system.role.search.conditionPlaceholder') |
| | | ), |
| | | createSelectSearchItem( |
| | | t('pages.system.role.search.status'), |
| | | 'status', |
| | | t('pages.system.role.search.statusPlaceholder'), |
| | | getRoleStatusOptions() |
| | | ) |
| | | ]) |
| | | |
| | | function handleReset() { |
| | |
| | | const ROLE_STATUS_META = { |
| | | 1: { type: 'success', text: '正常', bool: true }, |
| | | 0: { type: 'danger', text: '禁用', bool: false } |
| | | } |
| | | import { $t } from '@/locales' |
| | | |
| | | const ROLE_STATUS_OPTIONS = [ |
| | | { label: '正常', value: 1 }, |
| | | { label: '禁用', value: 0 } |
| | | ] |
| | | const ROLE_STATUS_META = { |
| | | 1: { type: 'success', key: 'common.status.normal', bool: true }, |
| | | 0: { type: 'danger', key: 'common.status.disabled', bool: false } |
| | | } |
| | | |
| | | export function createRoleSearchState() { |
| | | return { |
| | |
| | | } |
| | | |
| | | export function getRoleStatusOptions() { |
| | | return ROLE_STATUS_OPTIONS.map((option) => ({ ...option })) |
| | | return [ |
| | | { label: $t('common.status.normal'), value: 1 }, |
| | | { label: $t('common.status.disabled'), value: 0 } |
| | | ] |
| | | } |
| | | |
| | | export function buildRoleSearchParams(params = {}) { |
| | |
| | | } |
| | | |
| | | const ROLE_REPORT_COLUMNS = [ |
| | | { source: 'name', label: '角色名称' }, |
| | | { source: 'code', label: '角色编码' }, |
| | | { source: 'statusText', label: '状态' }, |
| | | { source: 'memo', label: '备注' }, |
| | | { source: 'createTimeText', label: '创建时间' }, |
| | | { source: 'updateTimeText', label: '更新时间' } |
| | | { source: 'name', labelKey: 'pages.system.role.table.name' }, |
| | | { source: 'code', labelKey: 'pages.system.role.table.code' }, |
| | | { source: 'statusText', labelKey: 'pages.system.role.table.status' }, |
| | | { source: 'memo', labelKey: 'pages.system.role.table.memo' }, |
| | | { source: 'createTimeText', labelKey: 'pages.system.role.table.createTime' }, |
| | | { source: 'updateTimeText', labelKey: 'pages.system.role.table.updateTime' } |
| | | ] |
| | | |
| | | const ROLE_REPORT_SOURCE_ALIAS = { |
| | | status: 'statusText' |
| | | } |
| | | |
| | | export const ROLE_REPORT_TITLE = '角色管理报表' |
| | | export function getRoleReportTitle() { |
| | | return $t('pages.system.role.reportTitle') |
| | | } |
| | | |
| | | export const ROLE_REPORT_STYLE = { |
| | | titleAlign: 'center', |
| | |
| | | } |
| | | |
| | | export function getRoleReportColumns() { |
| | | return ROLE_REPORT_COLUMNS.map((column) => ({ ...column })) |
| | | return ROLE_REPORT_COLUMNS.map((column) => ({ |
| | | source: column.source, |
| | | label: $t(column.labelKey) |
| | | })) |
| | | } |
| | | |
| | | export function resolveRoleReportColumns(columns = []) { |
| | |
| | | const allowedColumn = allowedColumns.get(source) |
| | | return { |
| | | source, |
| | | label: column.label || allowedColumn.label |
| | | label: column.label || $t(allowedColumn.labelKey) |
| | | } |
| | | }) |
| | | .filter(Boolean) |
| | |
| | | titleLevel = ROLE_REPORT_STYLE.titleLevel |
| | | } = {}) { |
| | | return { |
| | | reportTitle: ROLE_REPORT_TITLE, |
| | | reportTitle: getRoleReportTitle(), |
| | | reportDate: previewMeta.reportDate, |
| | | printedAt: previewMeta.printedAt, |
| | | operator: previewMeta.operator, |
| | |
| | | return { |
| | | ...record, |
| | | statusBool: record.statusBool !== void 0 ? Boolean(record.statusBool) : statusMeta.bool, |
| | | statusText: statusMeta.text, |
| | | statusText: $t(statusMeta.key), |
| | | statusType: statusMeta.type, |
| | | createTimeText: normalizeText(record.createTime$ || record.createTime), |
| | | updateTimeText: normalizeText(record.updateTime$ || record.updateTime) |
| | |
| | | if (status === false || status === 0 || status === '0') { |
| | | return ROLE_STATUS_META[0] |
| | | } |
| | | return { type: 'info', text: '未知', bool: false } |
| | | return { type: 'info', key: 'common.status.unknown', bool: false } |
| | | } |
| | | |
| | | export function getRoleScopeConfig(scopeType) { |
| | | const configMap = { |
| | | menu: { |
| | | scopeType: 'menu', |
| | | title: '网页权限', |
| | | title: $t('pages.system.role.scopes.menu'), |
| | | listUrl: '/role/scope/list', |
| | | treeUrl: '/menu/tree' |
| | | }, |
| | | pda: { |
| | | scopeType: 'pda', |
| | | title: 'PDA权限', |
| | | title: $t('pages.system.role.scopes.pda'), |
| | | listUrl: '/rolePda/scope/list', |
| | | treeUrl: '/menuPda/tree' |
| | | }, |
| | | matnr: { |
| | | scopeType: 'matnr', |
| | | title: '物料权限', |
| | | title: $t('pages.system.role.scopes.matnr'), |
| | | listUrl: '/roleMatnr/scope/list', |
| | | treeUrl: '/menuMatnrGroup/tree' |
| | | }, |
| | | warehouse: { |
| | | scopeType: 'warehouse', |
| | | title: '仓库权限', |
| | | title: $t('pages.system.role.scopes.warehouse'), |
| | | listUrl: '/roleWarehouse/scope/list', |
| | | treeUrl: '/menuWarehouse/tree' |
| | | } |
| | |
| | | import { h } from 'vue' |
| | | import ArtButtonMore from '@/components/core/forms/art-button-more/index.vue' |
| | | import { ElTag } from 'element-plus' |
| | | import { $t } from '@/locales' |
| | | import { getRoleStatusMeta } from './rolePage.helpers' |
| | | |
| | | const ROLE_MORE_ACTIONS = [ |
| | | { |
| | | key: 'scope-menu', |
| | | label: '网页权限', |
| | | icon: 'ri:layout-2-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'scope-pda', |
| | | label: 'PDA权限', |
| | | icon: 'ri:smartphone-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'scope-matnr', |
| | | label: '物料权限', |
| | | icon: 'ri:archive-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'scope-warehouse', |
| | | label: '仓库权限', |
| | | icon: 'ri:store-2-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'edit', |
| | | label: '编辑角色', |
| | | icon: 'ri:edit-2-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'delete', |
| | | label: '删除角色', |
| | | icon: 'ri:delete-bin-4-line', |
| | | color: '#f56c6c', |
| | | auth: 'delete' |
| | | } |
| | | ] |
| | | function createRoleMoreActions() { |
| | | return [ |
| | | { |
| | | key: 'scope-menu', |
| | | label: $t('pages.system.role.actions.scopeMenu'), |
| | | icon: 'ri:layout-2-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'scope-pda', |
| | | label: $t('pages.system.role.actions.scopePda'), |
| | | icon: 'ri:smartphone-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'scope-matnr', |
| | | label: $t('pages.system.role.actions.scopeMatnr'), |
| | | icon: 'ri:archive-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'scope-warehouse', |
| | | label: $t('pages.system.role.actions.scopeWarehouse'), |
| | | icon: 'ri:store-2-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'edit', |
| | | label: $t('pages.system.role.actions.edit'), |
| | | icon: 'ri:edit-2-line', |
| | | auth: 'edit' |
| | | }, |
| | | { |
| | | key: 'delete', |
| | | label: $t('pages.system.role.actions.delete'), |
| | | icon: 'ri:delete-bin-4-line', |
| | | color: '#f56c6c', |
| | | auth: 'delete' |
| | | } |
| | | ] |
| | | } |
| | | |
| | | function createTextColumn(prop, label, minWidth, extra = {}) { |
| | | return { |
| | |
| | | export function createRoleTableColumns(handleActionClick) { |
| | | return [ |
| | | { type: 'selection', width: 52, fixed: 'left' }, |
| | | createTextColumn('name', '角色名称', 140), |
| | | createTextColumn('code', '角色编码', 140), |
| | | createTextColumn('memo', '备注', 180), |
| | | createTagColumn('status', '状态', 120, (row) => getRoleStatusMeta(row.statusBool ?? row.status)), |
| | | createTextColumn('updateTimeText', '更新时间', 180, { |
| | | createTextColumn('name', $t('pages.system.role.table.name'), 140), |
| | | createTextColumn('code', $t('pages.system.role.table.code'), 140), |
| | | createTextColumn('memo', $t('pages.system.role.table.memo'), 180), |
| | | createTagColumn('status', $t('pages.system.role.table.status'), 120, (row) => getRoleStatusMeta(row.statusBool ?? row.status)), |
| | | createTextColumn('updateTimeText', $t('pages.system.role.table.updateTime'), 180, { |
| | | sortable: true, |
| | | formatter: (row) => row.updateTimeText || '-' |
| | | }), |
| | | createTextColumn('createTimeText', '创建时间', 180, { |
| | | createTextColumn('createTimeText', $t('pages.system.role.table.createTime'), 180, { |
| | | sortable: true, |
| | | formatter: (row) => row.createTimeText || '-' |
| | | }), |
| | | { |
| | | prop: 'operation', |
| | | label: '操作', |
| | | label: $t('pages.system.role.table.operation'), |
| | | width: 120, |
| | | align: 'center', |
| | | fixed: 'right', |
| | | formatter: (row) => |
| | | h(ArtButtonMore, { |
| | | list: ROLE_MORE_ACTIONS, |
| | | list: createRoleMoreActions(), |
| | | onClick: (item) => handleActionClick(item, row) |
| | | }) |
| | | } |