Browse Source

修改主题

zhangafei 3 weeks ago
parent
commit
311d8485df

+ 2 - 2
.env.development

@@ -6,10 +6,10 @@ VITE_PUBLIC_PATH = /
 
 
 # 跨域代理,您可以配置多个 ,请注意,没有换行符
-VITE_PROXY = [["/jeecgboot","http://192.168.1.53:9399"],["/upload","http://localhost:3300/upload"]]
+VITE_PROXY = [["/jeecgboot","http://192.168.1.32:9999"],["/upload","http://localhost:3300/upload"]]
 
 #后台接口全路径地址(必填)
-VITE_GLOB_DOMAIN_URL=http://192.168.1.53:9399
+VITE_GLOB_DOMAIN_URL=http://192.168.1.53:9999
 
 #后台接口父地址(必填)
 VITE_GLOB_API_URL=/jeecgboot

+ 2 - 2
src/layouts/default/menu/index.vue

@@ -12,7 +12,7 @@
   import { ScrollContainer } from '/@/components/Container';
 
   import { useGo } from '/@/hooks/web/usePage';
-  import { useGlobSetting } from "/@/hooks/setting";
+  import { useGlobSetting } from '/@/hooks/setting';
   import { useSplitMenu } from './useLayoutMenu';
   import { openWindow } from '/@/utils';
   import { propTypes } from '/@/utils/propTypes';
@@ -57,7 +57,7 @@
 
       const { prefixCls } = useDesign('layout-menu');
 
-      const glob = useGlobSetting()
+      const glob = useGlobSetting();
 
       const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
 

+ 2 - 0
src/logics/theme/updateBackground.ts

@@ -20,6 +20,7 @@ const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color';
 export function updateHeaderBgColor(color?: string) {
   const appStore = useAppStore();
   const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
+  console.log('22222222222222222222222222222', color);
   if (!color) {
     if (darkMode) {
       color = '#151515';
@@ -27,6 +28,7 @@ export function updateHeaderBgColor(color?: string) {
       color = appStore.getHeaderSetting.bgColor;
     }
   }
+  console.log('33333333333333333333333333333', color);
   // bg color
   setCssVar(HEADER_BG_COLOR_VAR, color);
 

+ 213 - 1
src/settings/designSetting.ts

@@ -45,6 +45,33 @@ export const APP_MODE_LIST: Record<string, any>[] = [
       // 特殊效果
       boxShadow: '0 4px 12px rgba(0, 40, 80, 0.3)', // 科技感投影
       boxShadowSecondary: '0 2px 8px rgba(45,140,240,0.2)', // 辅助投影
+
+      // 左侧工业控制菜单
+      components: {
+        Menu: {
+          colorItemBg: '#121A24', // 菜单背景(与全局背景一致)
+          colorItemText: '#A0AEC0', // 常规菜单文字
+          colorItemTextSelected: '#2D8CF0', // 选中项文字
+          colorItemBgSelected: '#1A233033', // 选中项背景(透明蓝)
+          colorActiveBarBorderSize: 0, // 隐藏激活条
+          itemMarginBlock: 8, // 工业级间距
+        },
+        Layout: {
+          headerBg: '#1A2330', // 顶栏背景(与主容器一致)
+          headerColor: '#E0E0E0', // 顶栏文字
+          headerPadding: '0 24px', // 紧凑式布局
+        },
+        Alert: {
+          colorSuccessBg: '#15261E', // 成功背景(深海绿)
+          colorSuccessBorder: '#2D5C4A',
+          colorInfoBg: '#0F1A2D', // 信息背景(科技蓝)
+          colorInfoBorder: '#2D3F60',
+          colorWarningBg: '#2B2315', // 警告背景(琥珀矿层)
+          colorWarningBorder: '#5C4A2D',
+          colorErrorBg: '#2A1718', // 错误背景(熔岩底层)
+          colorErrorBorder: '#5C2D2F',
+        },
+      },
     },
   },
   // 极光灰(浅色护眼主题)
@@ -85,6 +112,33 @@ export const APP_MODE_LIST: Record<string, any>[] = [
       // 特殊效果
       boxShadow: '0 4px 12px rgba(160,174,192,0.15)', // 柔和投影
       boxShadowSecondary: '0 2px 6px rgba(45,140,240,0.1)',
+
+      // 装配线风格导航系统
+      components: {
+        Menu: {
+          colorItemBg: '#F0F4F8', // 菜单背景(流水线白)
+          colorItemText: '#5A6775', // 菜单文字(工卡灰)
+          colorItemTextSelected: '#2D8CF0', // 选中状态(质检蓝)
+          colorItemBgSelected: '#EBF4FF', // 选中背景(蓝图投影)
+          colorItemBgHover: '#E3E9EF', // 悬停背景(机械阴影)
+          borderRadius: 4, // 直角工业美学
+        },
+        Layout: {
+          headerBg: '#FFFFFF', // 顶栏(纯白钣金)
+          headerColor: '#2D3748', // 顶栏文字(钢印黑)
+          headerShadow: '0 2px 8px rgba(160,174,192,0.12)', // 轻量投影
+        },
+        Alert: {
+          colorSuccessBg: '#F0F8F2', // 成功(安全通道绿)
+          colorSuccessBorder: '#B8D8C3',
+          colorInfoBg: '#F0F6FF', // 信息(工单蓝)
+          colorInfoBorder: '#B8CDF0',
+          colorWarningBg: '#FFF4E6', // 警告(润滑脂黄)
+          colorWarningBorder: '#F0D4B8',
+          colorErrorBg: '#FFEBEE', // 错误(急停红)
+          colorErrorBorder: '#F0B8C3',
+        },
+      },
     },
   },
   // 工业绿境(深绿护眼主题)
@@ -125,6 +179,32 @@ export const APP_MODE_LIST: Record<string, any>[] = [
       // 特殊效果
       boxShadow: '0 4px 12px rgba(20,60,50,0.4)', // 丛林投影
       boxShadowSecondary: '0 2px 8px rgba(67,170,139,0.25)',
+
+      components: {
+        Menu: {
+          colorItemBg: '#152021', // 森林基底背景
+          colorItemText: '#8C9E9A', // 青苔次级文字
+          colorItemTextSelected: '#2B8C75', // 选中项(矿物绿)
+          colorItemBgSelected: 'rgba(43,140,117,0.2)', // 叶绿素层
+          colorItemBgHover: '#1E2A2B33', // 夜间植被悬停
+          itemBorderRadius: 0, // 工业直角切割
+        },
+        Layout: {
+          headerBg: '#1E2A2B', // 顶栏(树皮纹理)
+          headerColor: '#D1E0DB', // 蕨类白文字
+          headerBorderBottom: '1px solid #2B8C7544', // 年轮分割线
+        },
+        Alert: {
+          colorSuccessBg: '#15261E', // 光合作用成功
+          colorSuccessBorder: '#3AA17E55',
+          colorInfoBg: '#0F2A2D', // 地下水层信息
+          colorInfoBorder: '#48A9A655',
+          colorWarningBg: '#2B2315', // 矿物氧化警告
+          colorWarningBorder: '#D4B15F55',
+          colorErrorBg: '#2A1718', // 根系腐败错误
+          colorErrorBorder: '#D9534F55',
+        },
+      },
     },
   },
   // 米白工坊(浅色极简主题)
@@ -165,6 +245,32 @@ export const APP_MODE_LIST: Record<string, any>[] = [
       // 特殊效果
       boxShadow: '0 4px 12px rgba(91,124,141,0.1)', // 纸张投影
       boxShadowSecondary: '0 2px 6px rgba(123,156,189,0.08)',
+
+      components: {
+        Menu: {
+          colorItemBg: '#EBE5D8', // 亚麻布料背景
+          colorItemText: '#6B7C8D', // 蓝图标记灰
+          colorItemTextSelected: '#5B7C8D', // 选中(工程蓝图色)
+          colorItemBgSelected: '#D3DDE6', // 晒图纸选中态
+          colorItemBgHover: '#E0DCD288', // 铅笔阴影悬停
+          itemMarginBlock: 6, // 工整排版间距
+        },
+        Layout: {
+          headerBg: '#FFFFFF', // 顶栏(标准绘图纸)
+          headerColor: '#2B3945', // 机械制图黑
+          headerShadow: '0 2px 6px rgba(91,124,141,0.08)', // 丁字尺投影
+        },
+        Alert: {
+          colorSuccessBg: '#F0F5EB', // 安全工艺通过
+          colorSuccessBorder: '#7AA95C88',
+          colorInfoBg: '#EFF3F8', // 技术文档提示
+          colorInfoBorder: '#5A7D9C88',
+          colorWarningBg: '#FDF4E7', // 材料疲劳预警
+          colorWarningBorder: '#CC9B4588',
+          colorErrorBg: '#FBEAEA', // 公差超标警告
+          colorErrorBorder: '#C4554A88',
+        },
+      },
     },
   },
   // 钢坯熔炉(金属工业主题)
@@ -205,6 +311,32 @@ export const APP_MODE_LIST: Record<string, any>[] = [
       // 特殊效果
       boxShadow: '0 4px 12px rgba(12,25,40,0.35)', // 铸造投影
       boxShadowSecondary: '0 2px 8px rgba(99,179,237,0.2)', // 淬火光效
+
+      components: {
+        Menu: {
+          colorItemBg: '#1A202C', // 钢锭原料背景
+          colorItemText: '#8A95A5', // 金属冷灰
+          colorItemTextSelected: '#63B3ED', // 淬火高光蓝
+          colorItemBgSelected: 'rgba(99,179,237,0.15)', // 冷却液渗透
+          colorItemBgHover: '#2D374822', // 热轧氧化层
+          colorActiveBarWidth: 3, // 轧辊指示条
+        },
+        Layout: {
+          headerBg: '#3C4657', // 顶栏(氧化钢板)
+          headerColor: '#CBD5E0', // 机床铭牌银
+          headerBorderBottom: '3px solid #4A5568', // 重型钢梁
+        },
+        Alert: {
+          colorSuccessBg: '#1A2C28', // 淬火完成
+          colorSuccessBorder: '#68D39155',
+          colorInfoBg: '#1A2430', // 液压系统状态
+          colorInfoBorder: '#63B3ED55',
+          colorWarningBg: '#332015', // 红热警报
+          colorWarningBorder: '#F6AD5555',
+          colorErrorBg: '#2A1718', // 锻压故障
+          colorErrorBorder: '#FC818155',
+        },
+      },
     },
   },
   // 机械绿光(赛博护眼主题)
@@ -246,6 +378,33 @@ export const APP_MODE_LIST: Record<string, any>[] = [
       // 特效系统
       boxShadow: '0 8px 24px -4px rgba(0,200,155,0.25)', // 能量场投影
       boxShadowSecondary: '0 0 12px rgba(91,192,235,0.2)', // 冷却液辉光
+
+      // 全息投影导航系统
+      components: {
+        Menu: {
+          colorItemBg: 'transparent', // 透明背景(AR界面)
+          colorItemText: '#7D9BA6', // 次级信息(UI辅助线)
+          colorItemTextSelected: '#00C89B', // 选中项(全息高亮)
+          colorItemBgSelected: 'linear-gradient(90deg, rgba(0,200,155,0.1) 0%, transparent 100%)',
+          colorActiveBarWidth: 0, // 禁用传统指示条
+          itemHoverColor: '#00C89B', // 悬停流光效果
+        },
+        Layout: {
+          headerBg: 'rgba(13,31,45,0.95)', // 顶栏(玻璃质感)
+          headerColor: '#C0F0E4', // HUD显示文字
+          headerBack: 'rgba(0,200,155,0.3)', // 顶栏玻璃边框
+        },
+        Alert: {
+          colorSuccessBg: 'rgba(76,217,100,0.12)', // 数字生态提示
+          colorSuccessBorder: '#4CD96433',
+          colorInfoBg: 'rgba(91,192,235,0.12)', // 冷却系统状态
+          colorInfoBorder: '#5BC0EB33',
+          colorWarningBg: 'rgba(255,215,0,0.15)', // 过载预警
+          colorWarningBorder: '#FFD70033',
+          colorErrorBg: 'rgba(255,59,48,0.15)', // 核心熔断
+          colorErrorBorder: '#FF3B3033',
+        },
+      },
     },
   },
   // 熔岩锻炉(热力护眼主题)
@@ -288,6 +447,33 @@ export const APP_MODE_LIST: Record<string, any>[] = [
       // 环境特效
       boxShadow: '0 6px 20px -8px rgba(227,74,39,0.4)', // 热辐射
       boxShadowSecondary: 'inset 0 0 12px rgba(255,179,71,0.15)', // 内部高温
+
+      // 高温作业界面系统
+      components: {
+        Menu: {
+          colorItemBg: '#1A1210', // 菜单(熔炉内壁)
+          colorItemText: '#A8958C', // 菜单文字(氧化色)
+          colorItemTextSelected: '#E34A27', // 选中项(熔岩高亮)
+          colorItemBgSelected: 'rgba(227,74,39,0.15)', // 热辐射效果
+          colorItemBgHover: 'rgba(255,107,66,0.1)', // 热浪悬停
+          itemBorderRadius: 0, // 直角切割
+        },
+        Layout: {
+          headerBg: '#3D2B26', // 顶栏(锻造台)
+          headerColor: '#FFD8B1', // 高温警示文字
+          headerBorderBottom: '2px solid #5A4D48', // 铸铁分隔
+        },
+        Alert: {
+          colorSuccessBg: '#1E2F28', // 冷却完成(淬火成功)
+          colorSuccessBorder: '#3AA17E',
+          colorInfoBg: '#1A2530', // 压力数据(液压系统)
+          colorInfoBorder: '#5A7D9C',
+          colorWarningBg: '#3A231D', // 高温警告(熔炉状态)
+          colorWarningBorder: '#FFB347',
+          colorErrorBg: '#2A1718', // 紧急停机(核心故障)
+          colorErrorBorder: '#D32F2F',
+        },
+      },
     },
   },
   // 纳米灰(未来材料主题)
@@ -329,6 +515,32 @@ export const APP_MODE_LIST: Record<string, any>[] = [
       // 量子特效
       boxShadow: '0 4px 16px -6px rgba(107,124,141,0.2)', // 表面电子云
       boxShadowSecondary: '0 0 8px rgba(148,168,184,0.1)', // 隧穿效应辉光
+
+      components: {
+        Menu: {
+          colorItemBg: 'rgba(240,243,246,0.9)', // 纳米镀层玻璃
+          colorItemText: '#6B7C8D', // 原子标记灰
+          colorItemTextSelected: '#94A8B8', // 量子隧穿高亮
+          colorItemBgSelected: 'rgba(148,168,184,0.1)',
+          colorItemBgHover: 'rgba(224,230,235,0.5)', // 分子吸附效果
+          borderRadiusLG: 4, // 晶格圆角
+        },
+        Layout: {
+          headerBg: 'rgba(255,255,255,0.95)', // 顶栏(单层石墨烯)
+          headerColor: '#243140', // 碳纳米管黑
+          headerBorderBottom: '1px solid rgba(202,211,220,0.3)', // 原子力分割
+        },
+        Alert: {
+          colorSuccessBg: 'rgba(123,160,91,0.08)', // 生物涂层成功
+          colorSuccessBorder: '#7BA05B33',
+          colorInfoBg: 'rgba(148,168,184,0.08)', // 量子通信提示
+          colorInfoBorder: '#94A8B833',
+          colorWarningBg: 'rgba(212,164,24,0.1)', // 能级跃迁预警
+          colorWarningBorder: '#D4A41833',
+          colorErrorBg: 'rgba(196,85,74,0.1)', // 分子裂变警告
+          colorErrorBorder: '#C4554A33',
+        },
+      },
     },
   },
 ];
@@ -336,7 +548,7 @@ export const APP_MODE_LIST: Record<string, any>[] = [
 // app theme preset color
 export const APP_PRESET_COLOR_LIST: string[] = [
   '#0960bd',
-  '#1890ff',
+  '#ff00ff',
   '#009688',
   '#536dfe',
   '#ff5c93',

+ 63 - 0
src/views/equipmentLifecycle/device/bom/DeviceMaterialRelation.api.ts

@@ -0,0 +1,63 @@
+import { defHttp } from '/@/utils/http/axios';
+import { useMessage } from '/@/hooks/web/useMessage';
+
+const { createConfirm } = useMessage();
+
+enum Api {
+  list = '/deviceInfo/deviceMaterialRelation/list',
+  save = '/deviceInfo/deviceMaterialRelation/add',
+  edit = '/deviceInfo/deviceMaterialRelation/edit',
+  deleteOne = '/deviceInfo/deviceMaterialRelation/delete',
+  deleteBatch = '/deviceInfo/deviceMaterialRelation/deleteBatch',
+  importExcel = '/deviceInfo/deviceMaterialRelation/importExcel',
+  exportXls = '/deviceInfo/deviceMaterialRelation/exportXls',
+}
+/**
+ * 导出api
+ * @param params
+ */
+export const getExportUrl = Api.exportXls;
+/**
+ * 导入api
+ */
+export const getImportUrl = Api.importExcel;
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) => defHttp.get({ url: Api.list, params });
+
+/**
+ * 删除单个
+ */
+export const deleteOne = (params, handleSuccess) => {
+  return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
+    handleSuccess();
+  });
+};
+/**
+ * 批量删除
+ * @param params
+ */
+export const batchDelete = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认删除',
+    content: '是否删除选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
+        handleSuccess();
+      });
+    },
+  });
+};
+/**
+ * 保存或者更新
+ * @param params
+ */
+export const saveOrUpdate = (params, isUpdate) => {
+  const url = isUpdate ? Api.edit : Api.save;
+  return defHttp.post({ url: url, params });
+};

+ 131 - 0
src/views/equipmentLifecycle/device/bom/DeviceMaterialRelation.data.ts

@@ -0,0 +1,131 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+//列表数据
+export const columns: BasicColumn[] = [
+  {
+    title: '设备编号',
+    align: 'center',
+    dataIndex: 'deviceNumber',
+  },
+  {
+    title: '物料规格型号',
+    align: 'center',
+    dataIndex: 'materialSpecModel',
+  },
+  {
+    title: '物料名称',
+    align: 'center',
+    dataIndex: 'materialName',
+  },
+  {
+    title: '物料编号',
+    align: 'center',
+    dataIndex: 'materialNumber',
+  },
+  {
+    title: '分类',
+    align: 'center',
+    dataIndex: 'classification',
+  },
+  {
+    title: '更换周期',
+    align: 'center',
+    dataIndex: 'replacementCycle',
+  },
+  {
+    title: '需求量',
+    align: 'center',
+    dataIndex: 'demandAmount',
+  },
+  {
+    title: '单位',
+    align: 'center',
+    dataIndex: 'unit',
+  },
+  {
+    title: '日期',
+    align: 'center',
+    dataIndex: 'createDate',
+  },
+];
+//查询数据
+export const searchFormSchema: FormSchema[] = [];
+//表单数据
+export const formSchema: FormSchema[] = [
+  {
+    label: '设备编号',
+    field: 'deviceNumber',
+    component: 'Input',
+    dynamicRules: () => {
+      return [{ required: true, message: '请输入设备编号!' }];
+    },
+  },
+  {
+    label: '物料规格型号',
+    field: 'materialSpecModel',
+    component: 'Input',
+  },
+  {
+    label: '物料名称',
+    field: 'materialName',
+    component: 'Input',
+  },
+  {
+    label: '物料编号',
+    field: 'materialNumber',
+    component: 'Input',
+  },
+  {
+    label: '分类',
+    field: 'classification',
+    component: 'Input',
+  },
+  {
+    label: '更换周期',
+    field: 'replacementCycle',
+    component: 'Input',
+  },
+  {
+    label: '需求量',
+    field: 'demandAmount',
+    component: 'InputNumber',
+  },
+  {
+    label: '单位',
+    field: 'unit',
+    component: 'Input',
+  },
+  // TODO 主键隐藏字段,目前写死为ID
+  {
+    label: '',
+    field: 'id',
+    component: 'Input',
+    show: false,
+  },
+];
+
+// 高级查询数据
+export const superQuerySchema = {
+  createDate: { title: '日期', order: 0, view: 'datetime', type: 'string' },
+  serialNumber: { title: '序号', order: 1, view: 'number', type: 'number' },
+  deviceNumber: { title: '设备编号', order: 2, view: 'text', type: 'string' },
+  deviceName: { title: '设备名称', order: 3, view: 'text', type: 'string' },
+  deviceCategory: { title: '设备类别', order: 4, view: 'text', type: 'string' },
+  deviceSpecModel: { title: '设备规格型号', order: 5, view: 'text', type: 'string' },
+  materialSpecModel: { title: '物料规格型号', order: 6, view: 'text', type: 'string' },
+  materialName: { title: '物料名称', order: 7, view: 'text', type: 'string' },
+  materialNumber: { title: '物料编号', order: 8, view: 'text', type: 'string' },
+  classification: { title: '分类', order: 9, view: 'text', type: 'string' },
+  replacementCycle: { title: '更换周期', order: 10, view: 'text', type: 'string' },
+  demandAmount: { title: '需求量', order: 11, view: 'number', type: 'number' },
+  unit: { title: '单位', order: 12, view: 'text', type: 'string' },
+};
+
+/**
+ * 流程表单调用这个方法获取formSchema
+ * @param param
+ */
+export function getBpmFormSchema(_formData): FormSchema[] {
+  // 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
+  return formSchema;
+}

+ 70 - 0
src/views/equipmentLifecycle/device/bom/components/DeviceMaterialRelationForm.vue

@@ -0,0 +1,70 @@
+<template>
+  <div style="min-height: 400px">
+    <BasicForm @register="registerForm" />
+    <div style="width: 100%; text-align: center" v-if="!formDisabled">
+      <a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 交</a-button>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+  import { BasicForm, useForm } from '/@/components/Form/index';
+  import { computed, defineComponent } from 'vue';
+  import { defHttp } from '/@/utils/http/axios';
+  import { propTypes } from '/@/utils/propTypes';
+  import { getBpmFormSchema } from '../DeviceMaterialRelation.data';
+  import { saveOrUpdate } from '../DeviceMaterialRelation.api';
+
+  export default defineComponent({
+    name: 'DeviceMaterialRelationForm',
+    components: {
+      BasicForm,
+    },
+    props: {
+      formData: propTypes.object.def({}),
+      formBpm: propTypes.bool.def(true),
+    },
+    setup(props) {
+      const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
+        labelWidth: 150,
+        schemas: getBpmFormSchema(props.formData),
+        showActionButtonGroup: false,
+        baseColProps: { span: 24 },
+      });
+
+      const formDisabled = computed(() => {
+        if (props.formData.disabled === false) {
+          return false;
+        }
+        return true;
+      });
+
+      let formData = {};
+      const queryByIdUrl = '/deviceInfo/deviceMaterialRelation/queryById';
+      async function initFormData() {
+        let params = { id: props.formData.dataId };
+        const data = await defHttp.get({ url: queryByIdUrl, params });
+        formData = { ...data };
+        //设置表单的值
+        await setFieldsValue(formData);
+        //默认是禁用
+        await setProps({ disabled: formDisabled.value });
+      }
+
+      async function submitForm() {
+        let data = getFieldsValue();
+        let params = Object.assign({}, formData, data);
+        console.log('表单数据', params);
+        await saveOrUpdate(params, true);
+      }
+
+      initFormData();
+
+      return {
+        registerForm,
+        formDisabled,
+        submitForm,
+      };
+    },
+  });
+</script>

+ 78 - 0
src/views/equipmentLifecycle/device/bom/components/DeviceMaterialRelationModal.vue

@@ -0,0 +1,78 @@
+<template>
+  <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
+    <BasicForm @register="registerForm" name="DeviceMaterialRelationForm" />
+  </BasicModal>
+</template>
+
+<script lang="ts" setup>
+  import { ref, computed, unref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { BasicForm, useForm } from '/@/components/Form/index';
+  import { formSchema } from '../DeviceMaterialRelation.data';
+  import { saveOrUpdate } from '../DeviceMaterialRelation.api';
+  import { CustomScrollOptions } from '/@/views/equipmentLifecycle/common.types';
+  // Emits声明
+  const emit = defineEmits(['register', 'success']);
+  const isUpdate = ref(true);
+  const isDetail = ref(false);
+  //表单配置
+  const [registerForm, { setProps, resetFields, setFieldsValue, validate, scrollToField }] = useForm({
+    labelWidth: 150,
+    schemas: formSchema,
+    showActionButtonGroup: false,
+    baseColProps: { span: 24 },
+  });
+  //表单赋值
+  const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
+    //重置表单
+    await resetFields();
+    setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter });
+    isUpdate.value = !!data?.isUpdate;
+    isDetail.value = !!data?.showFooter;
+    if (unref(isUpdate)) {
+      //表单赋值
+      await setFieldsValue({
+        ...data.record,
+      });
+    }
+    // 隐藏底部时禁用整个表单
+    setProps({ disabled: !data?.showFooter });
+  });
+  //设置标题
+  const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(isDetail) ? '详情' : '编辑'));
+  //表单提交事件
+  async function handleSubmit() {
+    try {
+      let values = await validate();
+      setModalProps({ confirmLoading: true });
+      //提交表单
+      await saveOrUpdate(values, isUpdate.value);
+      //关闭弹窗
+      closeModal();
+      //刷新列表
+      emit('success');
+    } catch (error: any) {
+      // 使用类型守卫检查 error 是否包含 errorFields 属性
+      if (error && Array.isArray(error.errorFields)) {
+        const firstField = error.errorFields[0];
+        if (firstField) {
+          scrollToField(firstField.name, { behavior: 'smooth', block: 'center' } as CustomScrollOptions);
+        }
+      }
+      return Promise.reject(error);
+    } finally {
+      setModalProps({ confirmLoading: false });
+    }
+  }
+</script>
+
+<style lang="less" scoped>
+  /** 时间和数字输入框样式 */
+  :deep(.ant-input-number) {
+    width: 100%;
+  }
+
+  :deep(.ant-calendar-picker) {
+    width: 100%;
+  }
+</style>

+ 193 - 2
src/views/equipmentLifecycle/device/bom/index.vue

@@ -1,4 +1,195 @@
 <template>
-  <div class="app-container"> bom </div>
+  <div>
+    <!--引用表格-->
+    <BasicTable @register="registerTable" :rowSelection="rowSelection">
+      <!--插槽:table标题-->
+      <template #tableTitle>
+        <a-button type="primary" v-auth="'deviceInfo:device_material_relation:add'" @click="handleAdd" preIcon="ant-design:plus-outlined">
+          新增</a-button
+        >
+        <a-button type="primary" v-auth="'deviceInfo:device_material_relation:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls">
+          导出</a-button
+        >
+        <j-upload-button
+          type="primary"
+          v-auth="'deviceInfo:device_material_relation:importExcel'"
+          preIcon="ant-design:import-outlined"
+          @click="onImportXls"
+          >导入</j-upload-button
+        >
+        <a-dropdown v-if="selectedRowKeys.length > 0">
+          <template #overlay>
+            <a-menu>
+              <a-menu-item key="1" @click="batchHandleDelete">
+                <Icon icon="ant-design:delete-outlined" />
+                删除
+              </a-menu-item>
+            </a-menu>
+          </template>
+          <a-button v-auth="'deviceInfo:device_material_relation:deleteBatch'"
+            >批量操作
+            <Icon icon="mdi:chevron-down" />
+          </a-button>
+        </a-dropdown>
+        <!-- 高级查询 -->
+        <super-query :config="superQueryConfig" @search="handleSuperQuery" />
+      </template>
+      <!--操作栏-->
+      <template #action="{ record }">
+        <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
+      </template>
+      <!--字段回显插槽-->
+      <!-- <template v-slot:bodyCell="{ column, record, index, text }"> </template> -->
+    </BasicTable>
+    <!-- 表单区域 -->
+    <DeviceMaterialRelationModal @register="registerModal" @success="handleSuccess" />
+  </div>
 </template>
-<script setup lang="ts"></script>
+
+<script lang="ts" name="deviceInfo-deviceMaterialRelation" setup>
+  import { reactive } from 'vue';
+  import { BasicTable, TableAction } from '/@/components/Table';
+  import { useModal } from '/@/components/Modal';
+  import { useListPage } from '/@/hooks/system/useListPage';
+  import DeviceMaterialRelationModal from './components/DeviceMaterialRelationModal.vue';
+  import { columns, searchFormSchema, superQuerySchema } from './DeviceMaterialRelation.data';
+  import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './DeviceMaterialRelation.api';
+
+  const queryParam = reactive<any>({});
+  //注册model
+  const [registerModal, { openModal }] = useModal();
+  //注册table数据
+  const { tableContext, onExportXls, onImportXls } = useListPage({
+    tableProps: {
+      title: '设备物料BOM',
+      api: list,
+      columns,
+      canResize: false,
+      formConfig: {
+        //labelWidth: 120,
+        schemas: searchFormSchema,
+        autoSubmitOnEnter: true,
+        showAdvancedButton: true,
+        fieldMapToNumber: [],
+        fieldMapToTime: [],
+      },
+      actionColumn: {
+        width: 120,
+        fixed: 'right',
+      },
+      beforeFetch: (params) => {
+        return Object.assign(params, queryParam);
+      },
+    },
+    exportConfig: {
+      name: '设备物料BOM',
+      url: getExportUrl,
+      params: queryParam,
+    },
+    importConfig: {
+      url: getImportUrl,
+      success: handleSuccess,
+    },
+  });
+
+  const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
+
+  // 高级查询配置
+  const superQueryConfig = reactive(superQuerySchema);
+
+  /**
+   * 高级查询事件
+   */
+  function handleSuperQuery(params) {
+    Object.keys(params).map((k) => {
+      queryParam[k] = params[k];
+    });
+    reload();
+  }
+  /**
+   * 新增事件
+   */
+  function handleAdd() {
+    openModal(true, {
+      isUpdate: false,
+      showFooter: true,
+    });
+  }
+  /**
+   * 编辑事件
+   */
+  function handleEdit(record: Recordable) {
+    openModal(true, {
+      record,
+      isUpdate: true,
+      showFooter: true,
+    });
+  }
+  /**
+   * 详情
+   */
+  function handleDetail(record: Recordable) {
+    openModal(true, {
+      record,
+      isUpdate: true,
+      showFooter: false,
+    });
+  }
+  /**
+   * 删除事件
+   */
+  async function handleDelete(record) {
+    await deleteOne({ id: record.id }, handleSuccess);
+  }
+  /**
+   * 批量删除事件
+   */
+  async function batchHandleDelete() {
+    await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
+  }
+  /**
+   * 成功回调
+   */
+  function handleSuccess() {
+    (selectedRowKeys.value = []) && reload();
+  }
+  /**
+   * 操作栏
+   */
+  function getTableAction(record) {
+    return [
+      {
+        label: '编辑',
+        onClick: handleEdit.bind(null, record),
+        auth: 'deviceInfo:device_material_relation:edit',
+      },
+    ];
+  }
+  /**
+   * 下拉操作栏
+   */
+  function getDropDownAction(record) {
+    return [
+      {
+        label: '详情',
+        onClick: handleDetail.bind(null, record),
+      },
+      {
+        label: '删除',
+        popConfirm: {
+          title: '是否确认删除',
+          confirm: handleDelete.bind(null, record),
+          placement: 'topLeft',
+        },
+        auth: 'deviceInfo:device_material_relation:delete',
+      },
+    ];
+  }
+</script>
+
+<style lang="less" scoped>
+  :deep(.ant-picker),
+  :deep(.ant-input-number) {
+    width: 100%;
+  }
+</style>