zhangwencui
16 小时以前 0c85820e81bae62e8ff5f066803995dab1d3503f
Merge branch 'dev_pro2.0' of http://114.132.189.42:9002/r/mom-pro2-before into dev_pro2.0
已修改8个文件
104 ■■■■ 文件已修改
src/views/basicData/mdm/data.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/mdm/modules/form.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/erp/sale/order/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/md/item/modules/product-media-list.vue 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/qc/defect/data.ts 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/qc/defect/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/qc/indicator/data.ts 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/qc/indicator/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/mdm/data.ts
@@ -53,6 +53,11 @@
  return unitListPromise;
}
/** 清除单位列表缓存 */
export function clearUnitListCache() {
  unitListCache = null;
}
/** 新增/修改的表单 */
export function useFormSchema(formApi?: VbenFormApi): VbenFormSchema[] {
  return [
src/views/basicData/mdm/modules/form.vue
@@ -11,7 +11,7 @@
import { createItem, getItem, updateItem } from '#/api/mdm/item';
import { $t } from '#/locales';
import { useFormSchema } from '../data';
import { useFormSchema, clearUnitListCache } from '../data';
defineOptions({ name: "ItemForm" });
@@ -54,6 +54,8 @@
      return;
    }
    const data = modalApi.getData<MdmItemApi.Item>();
    // 清除单位缓存,确保获取最新数据
    clearUnitListCache();
    // 设置 schema(formApi 已初始化)
    formApi.setState({ schema: useFormSchema(formApi) });
    if (data?.id) {
src/views/erp/sale/order/index.vue
@@ -342,7 +342,7 @@
              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),
            },
            {
src/views/mes/md/item/modules/product-media-list.vue
@@ -49,6 +49,17 @@
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 表单提交中
@@ -219,27 +230,28 @@
      添加 {{ 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>
src/views/mes/qc/defect/data.ts
@@ -150,10 +150,7 @@
      field: 'type',
      title: '检测项类型',
      width: 120,
      cellRender: {
        name: 'CellDict',
        props: { type: DICT_TYPE.MES_INDICATOR_TYPE },
      },
      slots: { default: 'type' },
    },
    {
      field: 'level',
src/views/mes/qc/defect/index.vue
@@ -5,10 +5,12 @@
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';
@@ -18,6 +20,23 @@
  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() {
@@ -110,6 +129,11 @@
          ]"
        />
      </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="[
src/views/mes/qc/indicator/data.ts
@@ -186,10 +186,7 @@
      field: 'type',
      title: '检测项类型',
      width: 120,
      cellRender: {
        name: 'CellDict',
        props: { type: DICT_TYPE.MES_INDICATOR_TYPE },
      },
      slots: { default: 'type' },
    },
    {
      field: 'tool',
@@ -273,10 +270,7 @@
      field: 'type',
      title: '检测项类型',
      width: 120,
      cellRender: {
        name: 'CellDict',
        props: { type: DICT_TYPE.MES_INDICATOR_TYPE },
      },
      slots: { default: 'type' },
    },
    {
      field: 'tool',
src/views/mes/qc/indicator/index.vue
@@ -5,7 +5,7 @@
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 {
@@ -13,6 +13,8 @@
  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';
@@ -22,6 +24,23 @@
  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() {
@@ -114,6 +133,11 @@
          ]"
        />
      </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="[