Merge branch 'dev_pro2.0' of http://114.132.189.42:9002/r/mom-pro2-before into dev_pro2.0
| | |
| | | return unitListPromise; |
| | | } |
| | | |
| | | /** 清除单位列表缓存 */ |
| | | export function clearUnitListCache() { |
| | | unitListCache = null; |
| | | } |
| | | |
| | | /** 新增/修改的表单 */ |
| | | export function useFormSchema(formApi?: VbenFormApi): VbenFormSchema[] { |
| | | return [ |
| | |
| | | import { createItem, getItem, updateItem } from '#/api/mdm/item'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useFormSchema } from '../data'; |
| | | import { useFormSchema, clearUnitListCache } from '../data'; |
| | | |
| | | defineOptions({ name: "ItemForm" }); |
| | | |
| | |
| | | return; |
| | | } |
| | | const data = modalApi.getData<MdmItemApi.Item>(); |
| | | // 清除单位缓存,确保获取最新数据 |
| | | clearUnitListCache(); |
| | | // 设置 schema(formApi 已初始化) |
| | | formApi.setState({ schema: useFormSchema(formApi) }); |
| | | if (data?.id) { |
| | |
| | | type: 'link', |
| | | icon: 'ant-design:file-protect-outlined', |
| | | auth: ['mes:wm-sales-notice:create'], |
| | | ifShow: () => row.status === 20 && row.canCreateSalesNotice, |
| | | ifShow: () => row.status === 20 && (row.canCreateSalesNotice || row.productionStatus === 1), |
| | | onClick: handleGenerateNotice.bind(null, row), |
| | | }, |
| | | { |
| | |
| | | |
| | | const isReadOnly = computed(() => props.formType === 'detail'); // 是否只读 |
| | | const title = computed(() => props.kind); // 当前媒体类型标题 |
| | | |
| | | /** 将完整 URL 转为相对路径,确保走前端代理 */ |
| | | function resolveImageUrl(url?: string): string { |
| | | if (!url) return ''; |
| | | try { |
| | | const { pathname } = new URL(url, window.location.origin); |
| | | return pathname; |
| | | } catch { |
| | | return url; |
| | | } |
| | | } |
| | | const loading = ref(false); // SIP/SOP 列表加载中 |
| | | const formOpen = ref(false); // SIP/SOP 表单是否打开 |
| | | const formLoading = ref(false); // SIP/SOP 表单提交中 |
| | |
| | | 添加 {{ title }} |
| | | </Button> |
| | | <Spin :spinning="loading"> |
| | | <div v-if="list.length > 0" class="grid grid-cols-4 gap-3"> |
| | | <div v-if="list.length > 0" class="grid grid-cols-8 gap-1"> |
| | | <Card |
| | | v-for="item in list" |
| | | :key="item.id" |
| | | hoverable |
| | | class="!w-[120px]" |
| | | :body-style="{ padding: '0px' }" |
| | | > |
| | | <Image |
| | | v-if="item.url" |
| | | :src="item.url" |
| | | class="block h-40 w-full object-cover" |
| | | :preview="{ src: item.url }" |
| | | :src="resolveImageUrl(item.url)" |
| | | class="block !h-[90px] !w-[120px] object-cover" |
| | | :preview="{ src: resolveImageUrl(item.url) }" |
| | | /> |
| | | <div |
| | | v-else |
| | | class="flex h-40 w-full items-center justify-center bg-gray-100 text-gray-400" |
| | | class="flex !h-[90px] !w-[120px] items-center justify-center bg-gray-100 text-gray-400" |
| | | > |
| | | 暂无图片 |
| | | </div> |
| | | <div class="p-3"> |
| | | <div class="mb-1 truncate text-sm font-bold">{{ item.title }}</div> |
| | | <div class="p-2"> |
| | | <div class="mb-1 truncate text-xs font-bold">{{ item.title }}</div> |
| | | <div v-if="item.description" class="truncate text-xs text-gray-500"> |
| | | {{ item.description }} |
| | | </div> |
| | |
| | | field: 'type', |
| | | title: '检测项类型', |
| | | width: 120, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_INDICATOR_TYPE }, |
| | | }, |
| | | slots: { default: 'type' }, |
| | | }, |
| | | { |
| | | field: 'level', |
| | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { message } from 'ant-design-vue'; |
| | | import { message, Tag } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { deleteDefect, exportDefect, getDefectPage } from '#/api/mes/qc/defect'; |
| | | import { DICT_TYPE } from '@vben/constants'; |
| | | import { getDictOptions } from '@vben/hooks'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useGridColumns, useGridFormSchema } from './data'; |
| | |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | const TAG_COLORS = ['blue', 'green', 'orange', 'purple', 'cyan', 'magenta', 'geekblue', 'volcano'] as const; |
| | | |
| | | const typeDictOptions = getDictOptions(DICT_TYPE.MES_INDICATOR_TYPE, 'number'); |
| | | const typeColorMap = new Map<number, string>(); |
| | | typeDictOptions.forEach((item, index) => { |
| | | typeColorMap.set(item.value as number, TAG_COLORS[index % TAG_COLORS.length]!); |
| | | }); |
| | | |
| | | function getTypeColor(type: number): string { |
| | | return typeColorMap.get(type) || 'default'; |
| | | } |
| | | |
| | | function getTypeLabel(type: number): string { |
| | | const item = typeDictOptions.find((d) => d.value === type); |
| | | return item?.label || String(type); |
| | | } |
| | | |
| | | /** 刷新表格 */ |
| | | function handleRefresh() { |
| | |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #type="{ row }"> |
| | | <Tag v-if="row.type !== undefined && row.type !== null" :color="getTypeColor(row.type)"> |
| | | {{ getTypeLabel(row.type) }} |
| | | </Tag> |
| | | </template> |
| | | <template #actions="{ row }"> |
| | | <TableAction |
| | | :actions="[ |
| | |
| | | field: 'type', |
| | | title: '检测项类型', |
| | | width: 120, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_INDICATOR_TYPE }, |
| | | }, |
| | | slots: { default: 'type' }, |
| | | }, |
| | | { |
| | | field: 'tool', |
| | |
| | | field: 'type', |
| | | title: '检测项类型', |
| | | width: 120, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_INDICATOR_TYPE }, |
| | | }, |
| | | slots: { default: 'type' }, |
| | | }, |
| | | { |
| | | field: 'tool', |
| | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart } from '@vben/utils'; |
| | | |
| | | import { message } from 'ant-design-vue'; |
| | | import { message, Tag } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | |
| | | exportIndicator, |
| | | getIndicatorPage, |
| | | } from '#/api/mes/qc/indicator'; |
| | | import { DICT_TYPE } from '@vben/constants'; |
| | | import { getDictOptions } from '@vben/hooks'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useGridColumns, useGridFormSchema } from './data'; |
| | |
| | | connectedComponent: Form, |
| | | destroyOnClose: true, |
| | | }); |
| | | |
| | | const TAG_COLORS = ['blue', 'green', 'orange', 'purple', 'cyan', 'magenta', 'geekblue', 'volcano'] as const; |
| | | |
| | | const typeDictOptions = getDictOptions(DICT_TYPE.MES_INDICATOR_TYPE, 'number'); |
| | | const typeColorMap = new Map<number, string>(); |
| | | typeDictOptions.forEach((item, index) => { |
| | | typeColorMap.set(item.value as number, TAG_COLORS[index % TAG_COLORS.length]!); |
| | | }); |
| | | |
| | | function getTypeColor(type: number): string { |
| | | return typeColorMap.get(type) || 'default'; |
| | | } |
| | | |
| | | function getTypeLabel(type: number): string { |
| | | const item = typeDictOptions.find((d) => d.value === type); |
| | | return item?.label || String(type); |
| | | } |
| | | |
| | | /** 刷新表格 */ |
| | | function handleRefresh() { |
| | |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #type="{ row }"> |
| | | <Tag v-if="row.type !== undefined && row.type !== null" :color="getTypeColor(row.type)"> |
| | | {{ getTypeLabel(row.type) }} |
| | | </Tag> |
| | | </template> |
| | | <template #actions="{ row }"> |
| | | <TableAction |
| | | :actions="[ |