tanlie пре 3 недеља
родитељ
комит
bf0046d1ab
5 измењених фајлова са 343 додато и 161 уклоњено
  1. 274 131
      src/mock/index.ts
  2. 31 6
      src/types/api.ts
  3. 13 2
      src/utils/api.ts
  4. 4 3
      src/utils/request.ts
  5. 21 19
      src/views/file/index.vue

+ 274 - 131
src/mock/index.ts

@@ -1,9 +1,12 @@
 import type { MockMethod } from "vite-plugin-mock";
 
+// 文件类型
+type FileType = 'image' | 'document' | 'video' | 'audio' | 'other';
+
 // 模拟聊天记录存储(内存中)
 interface ChatMessage {
   id: string;
-  role: 'user' | 'assistant';
+  role: "user" | "assistant";
   content: string;
   time: string;
 }
@@ -12,83 +15,89 @@ interface ChatMessage {
 const generateMockChatHistory = (): ChatMessage[] => {
   const history: ChatMessage[] = [
     {
-      id: '1',
-      role: 'assistant',
-      content: '您好!我是您的 AI 智能助手,有什么可以帮助您的吗?',
-      time: new Date(Date.now() - 86400000 * 2).toLocaleString()
+      id: "1",
+      role: "assistant",
+      content: "您好!我是您的 AI 智能助手,有什么可以帮助您的吗?",
+      time: new Date(Date.now() - 86400000 * 2).toLocaleString(),
     },
     {
-      id: '2',
-      role: 'user',
-      content: '如何管理系统用户?',
-      time: new Date(Date.now() - 86400000 * 2 + 60000).toLocaleString()
+      id: "2",
+      role: "user",
+      content: "如何管理系统用户?",
+      time: new Date(Date.now() - 86400000 * 2 + 60000).toLocaleString(),
     },
     {
-      id: '3',
-      role: 'assistant',
-      content: '系统用户管理在「用户管理」菜单中,您可以进行以下操作:\n1. 查看用户列表\n2. 添加新用户\n3. 编辑用户信息\n4. 禁用/启用用户账号',
-      time: new Date(Date.now() - 86400000 * 2 + 120000).toLocaleString()
+      id: "3",
+      role: "assistant",
+      content:
+        "系统用户管理在「用户管理」菜单中,您可以进行以下操作:\n1. 查看用户列表\n2. 添加新用户\n3. 编辑用户信息\n4. 禁用/启用用户账号",
+      time: new Date(Date.now() - 86400000 * 2 + 120000).toLocaleString(),
     },
     {
-      id: '4',
-      role: 'user',
-      content: '系统有哪些功能模块?',
-      time: new Date(Date.now() - 86400000).toLocaleString()
+      id: "4",
+      role: "user",
+      content: "系统有哪些功能模块?",
+      time: new Date(Date.now() - 86400000).toLocaleString(),
     },
     {
-      id: '5',
-      role: 'assistant',
-      content: '本系统包含以下功能模块:\n- 仪表盘:数据概览\n- 用户管理:系统用户管理\n- 系统管理:菜单、角色管理\n- 数据统计:报表分析\n- AI 助手:智能问答',
-      time: new Date(Date.now() - 86400000 + 60000).toLocaleString()
+      id: "5",
+      role: "assistant",
+      content:
+        "本系统包含以下功能模块:\n- 仪表盘:数据概览\n- 用户管理:系统用户管理\n- 系统管理:菜单、角色管理\n- 数据统计:报表分析\n- AI 助手:智能问答",
+      time: new Date(Date.now() - 86400000 + 60000).toLocaleString(),
     },
     {
-      id: '6',
-      role: 'user',
-      content: '如何导出数据报表?',
-      time: new Date(Date.now() - 43200000).toLocaleString()
+      id: "6",
+      role: "user",
+      content: "如何导出数据报表?",
+      time: new Date(Date.now() - 43200000).toLocaleString(),
     },
     {
-      id: '7',
-      role: 'assistant',
-      content: '导出数据报表步骤:\n1. 进入「数据统计」页面\n2. 选择查询条件\n3. 点击「导出」按钮\n4. 选择导出格式(Excel/PDF)\n5. 下载生成的报表文件',
-      time: new Date(Date.now() - 43200000 + 60000).toLocaleString()
+      id: "7",
+      role: "assistant",
+      content:
+        "导出数据报表步骤:\n1. 进入「数据统计」页面\n2. 选择查询条件\n3. 点击「导出」按钮\n4. 选择导出格式(Excel/PDF)\n5. 下载生成的报表文件",
+      time: new Date(Date.now() - 43200000 + 60000).toLocaleString(),
     },
     {
-      id: '8',
-      role: 'user',
-      content: '如何配置菜单权限?',
-      time: new Date(Date.now() - 3600000).toLocaleString()
+      id: "8",
+      role: "user",
+      content: "如何配置菜单权限?",
+      time: new Date(Date.now() - 3600000).toLocaleString(),
     },
     {
-      id: '9',
-      role: 'assistant',
-      content: '菜单权限配置在「系统管理 > 菜单管理」中:\n1. 创建菜单项\n2. 设置菜单图标和路径\n3. 为角色分配菜单权限\n4. 保存后权限即时生效',
-      time: new Date(Date.now() - 3600000 + 60000).toLocaleString()
+      id: "9",
+      role: "assistant",
+      content:
+        "菜单权限配置在「系统管理 > 菜单管理」中:\n1. 创建菜单项\n2. 设置菜单图标和路径\n3. 为角色分配菜单权限\n4. 保存后权限即时生效",
+      time: new Date(Date.now() - 3600000 + 60000).toLocaleString(),
     },
     {
-      id: '10',
-      role: 'user',
-      content: '如何修改个人资料?',
-      time: new Date(Date.now() - 1800000).toLocaleString()
+      id: "10",
+      role: "user",
+      content: "如何修改个人资料?",
+      time: new Date(Date.now() - 1800000).toLocaleString(),
     },
     {
-      id: '11',
-      role: 'assistant',
-      content: '修改个人资料:\n1. 点击右上角用户名\n2. 选择「个人中心」\n3. 编辑个人信息\n4. 点击「保存」按钮',
-      time: new Date(Date.now() - 1800000 + 60000).toLocaleString()
+      id: "11",
+      role: "assistant",
+      content:
+        "修改个人资料:\n1. 点击右上角用户名\n2. 选择「个人中心」\n3. 编辑个人信息\n4. 点击「保存」按钮",
+      time: new Date(Date.now() - 1800000 + 60000).toLocaleString(),
     },
     {
-      id: '12',
-      role: 'user',
-      content: '帮助',
-      time: new Date(Date.now() - 900000).toLocaleString()
+      id: "12",
+      role: "user",
+      content: "帮助",
+      time: new Date(Date.now() - 900000).toLocaleString(),
     },
     {
-      id: '13',
-      role: 'assistant',
-      content: '我可以帮您:\n- 解答系统使用问题\n- 提供操作指导\n- 解释功能说明\n请直接输入您的问题!',
-      time: new Date(Date.now() - 900000 + 60000).toLocaleString()
-    }
+      id: "13",
+      role: "assistant",
+      content:
+        "我可以帮您:\n- 解答系统使用问题\n- 提供操作指导\n- 解释功能说明\n请直接输入您的问题!",
+      time: new Date(Date.now() - 900000 + 60000).toLocaleString(),
+    },
   ];
   return history;
 };
@@ -158,6 +167,18 @@ export default [
         code: 200,
         message: "success",
         data: [
+          {
+            id: "5",
+            name: "AI 助手",
+            path: "/ai-chat",
+            icon: "ChatDotRound",
+          },
+          {
+            id: "6",
+            name: "文件管理",
+            path: "/file",
+            icon: "Folder",
+          },
           {
             id: "1",
             name: "仪表盘",
@@ -196,18 +217,6 @@ export default [
             path: "/statistics",
             icon: "TrendCharts",
           },
-          {
-            id: "5",
-            name: "AI 助手",
-            path: "/ai-chat",
-            icon: "ChatDotRound",
-          },
-          {
-            id: "6",
-            name: "文件管理",
-            path: "/file",
-            icon: "Folder",
-          },
         ],
       };
     },
@@ -276,8 +285,8 @@ export default [
           total,
           page,
           size,
-          hasMore: end < total
-        }
+          hasMore: end < total,
+        },
       };
     },
   },
@@ -291,17 +300,22 @@ export default [
 
       // AI 回复知识库
       const knowledgeBase: Record<string, string> = {
-        "如何管理系统用户?": "系统用户管理在「用户管理」菜单中,您可以进行以下操作:\n1. 查看用户列表\n2. 添加新用户\n3. 编辑用户信息\n4. 禁用/启用用户账号",
-        "如何配置菜单权限?": "菜单权限配置在「系统管理 > 菜单管理」中:\n1. 创建菜单项\n2. 设置菜单图标和路径\n3. 为角色分配菜单权限\n4. 保存后权限即时生效",
-        "系统有哪些功能模块?": "本系统包含以下功能模块:\n- 仪表盘:数据概览\n- 用户管理:系统用户管理\n- 系统管理:菜单、角色管理\n- 数据统计:报表分析\n- AI 助手:智能问答",
-        "如何导出数据报表?": "导出数据报表步骤:\n1. 进入「数据统计」页面\n2. 选择查询条件\n3. 点击「导出」按钮\n4. 选择导出格式(Excel/PDF)\n5. 下载生成的报表文件",
-        "如何修改个人资料?": "修改个人资料:\n1. 点击右上角用户名\n2. 选择「个人中心」\n3. 编辑个人信息\n4. 点击「保存」按钮",
-        "你好": "您好!很高兴为您服务,请问有什么可以帮助您的?",
-        "帮助": "我可以帮您:\n- 解答系统使用问题\n- 提供操作指导\n- 解释功能说明\n请直接输入您的问题!"
+        "如何管理系统用户?":
+          "系统用户管理在「用户管理」菜单中,您可以进行以下操作:\n1. 查看用户列表\n2. 添加新用户\n3. 编辑用户信息\n4. 禁用/启用用户账号",
+        "如何配置菜单权限?":
+          "菜单权限配置在「系统管理 > 菜单管理」中:\n1. 创建菜单项\n2. 设置菜单图标和路径\n3. 为角色分配菜单权限\n4. 保存后权限即时生效",
+        "系统有哪些功能模块?":
+          "本系统包含以下功能模块:\n- 仪表盘:数据概览\n- 用户管理:系统用户管理\n- 系统管理:菜单、角色管理\n- 数据统计:报表分析\n- AI 助手:智能问答",
+        "如何导出数据报表?":
+          "导出数据报表步骤:\n1. 进入「数据统计」页面\n2. 选择查询条件\n3. 点击「导出」按钮\n4. 选择导出格式(Excel/PDF)\n5. 下载生成的报表文件",
+        "如何修改个人资料?":
+          "修改个人资料:\n1. 点击右上角用户名\n2. 选择「个人中心」\n3. 编辑个人信息\n4. 点击「保存」按钮",
+        你好: "您好!很高兴为您服务,请问有什么可以帮助您的?",
+        帮助: "我可以帮您:\n- 解答系统使用问题\n- 提供操作指导\n- 解释功能说明\n请直接输入您的问题!",
       };
 
       // 查找回复
-      let reply = '';
+      let reply = "";
       for (const key in knowledgeBase) {
         if (question.includes(key) || key.includes(question)) {
           reply = knowledgeBase[key];
@@ -317,7 +331,7 @@ export default [
       return {
         code: 200,
         message: "success",
-        data: { reply }
+        data: { reply },
       };
     },
   },
@@ -328,22 +342,27 @@ export default [
     method: "get",
     rawResponse: async (req, res) => {
       // 从 query 参数获取问题
-      const url = new URL(req.url || '', `http://${req.headers.host}`);
-      const question = url.searchParams.get('question') || '';
+      const url = new URL(req.url || "", `http://${req.headers.host}`);
+      const question = url.searchParams.get("question") || "";
 
       // AI 回复知识库
       const knowledgeBase: Record<string, string> = {
-        "如何管理系统用户?": "系统用户管理在「用户管理」菜单中,您可以进行以下操作:\n1. 查看用户列表\n2. 添加新用户\n3. 编辑用户信息\n4. 禁用/启用用户账号",
-        "如何配置菜单权限?": "菜单权限配置在「系统管理 > 菜单管理」中:\n1. 创建菜单项\n2. 设置菜单图标和路径\n3. 为角色分配菜单权限\n4. 保存后权限即时生效",
-        "系统有哪些功能模块?": "本系统包含以下功能模块:\n- 仪表盘:数据概览\n- 用户管理:系统用户管理\n- 系统管理:菜单、角色管理\n- 数据统计:报表分析\n- AI 助手:智能问答",
-        "如何导出数据报表?": "导出数据报表步骤:\n1. 进入「数据统计」页面\n2. 选择查询条件\n3. 点击「导出」按钮\n4. 选择导出格式(Excel/PDF)\n5. 下载生成的报表文件",
-        "如何修改个人资料?": "修改个人资料:\n1. 点击右上角用户名\n2. 选择「个人中心」\n3. 编辑个人信息\n4. 点击「保存」按钮",
-        "你好": "您好!很高兴为您服务,请问有什么可以帮助您的?",
-        "帮助": "我可以帮您:\n- 解答系统使用问题\n- 提供操作指导\n- 解释功能说明\n请直接输入您的问题!"
+        "如何管理系统用户?":
+          "系统用户管理在「用户管理」菜单中,您可以进行以下操作:\n1. 查看用户列表\n2. 添加新用户\n3. 编辑用户信息\n4. 禁用/启用用户账号",
+        "如何配置菜单权限?":
+          "菜单权限配置在「系统管理 > 菜单管理」中:\n1. 创建菜单项\n2. 设置菜单图标和路径\n3. 为角色分配菜单权限\n4. 保存后权限即时生效",
+        "系统有哪些功能模块?":
+          "本系统包含以下功能模块:\n- 仪表盘:数据概览\n- 用户管理:系统用户管理\n- 系统管理:菜单、角色管理\n- 数据统计:报表分析\n- AI 助手:智能问答",
+        "如何导出数据报表?":
+          "导出数据报表步骤:\n1. 进入「数据统计」页面\n2. 选择查询条件\n3. 点击「导出」按钮\n4. 选择导出格式(Excel/PDF)\n5. 下载生成的报表文件",
+        "如何修改个人资料?":
+          "修改个人资料:\n1. 点击右上角用户名\n2. 选择「个人中心」\n3. 编辑个人信息\n4. 点击「保存」按钮",
+        你好: "您好!很高兴为您服务,请问有什么可以帮助您的?",
+        帮助: "我可以帮您:\n- 解答系统使用问题\n- 提供操作指导\n- 解释功能说明\n请直接输入您的问题!",
       };
 
       // 查找回复
-      let reply = '';
+      let reply = "";
       for (const key in knowledgeBase) {
         if (question.includes(key) || key.includes(question)) {
           reply = knowledgeBase[key];
@@ -357,21 +376,21 @@ export default [
       }
 
       // 设置 SSE 响应头
-      res.setHeader('Content-Type', 'text/event-stream');
-      res.setHeader('Cache-Control', 'no-cache');
-      res.setHeader('Connection', 'keep-alive');
+      res.setHeader("Content-Type", "text/event-stream");
+      res.setHeader("Cache-Control", "no-cache");
+      res.setHeader("Connection", "keep-alive");
 
       // 流式发送回复,每个字延迟 50ms
-      const chars = reply.split('');
+      const chars = reply.split("");
       for (let i = 0; i < chars.length; i++) {
         const data = {
           content: chars[i],
           index: i,
           total: chars.length,
-          done: i === chars.length - 1
+          done: i === chars.length - 1,
         };
         res.write(`data: ${JSON.stringify(data)}\n\n`);
-        await new Promise(resolve => setTimeout(resolve, 50));
+        await new Promise((resolve) => setTimeout(resolve, 50));
       }
 
       res.end();
@@ -387,28 +406,147 @@ export default [
     response: ({ query }) => {
       const page = parseInt(query.page as string) || 1;
       const size = parseInt(query.size as string) || 10;
-      const filename = (query.filename as string) || '';
-      const fileType = (query.fileType as string) || '';
-
-      // 模拟文件数据
-      const allFiles = [
-        { id: '1', filename: '项目需求文档.pdf', fileType: 'document', size: 2048576, uploader: '张三', uploadTime: '2026-03-15 10:30:00', url: '' },
-        { id: '2', filename: '产品原型图.png', fileType: 'image', size: 512000, uploader: '李四', uploadTime: '2026-03-15 09:15:00', url: 'https://via.placeholder.com/800x600.png?text=Product+Prototype' },
-        { id: '3', filename: '会议记录.docx', fileType: 'document', size: 102400, uploader: '王五', uploadTime: '2026-03-14 16:45:00', url: '' },
-        { id: '4', filename: '演示视频.mp4', fileType: 'video', size: 52428800, uploader: '赵六', uploadTime: '2026-03-14 14:20:00', url: '' },
-        { id: '5', filename: '背景音乐.mp3', fileType: 'audio', size: 3145728, uploader: '孙七', uploadTime: '2026-03-13 11:00:00', url: '' },
-        { id: '6', filename: '数据库备份.sql', fileType: 'other', size: 10485760, uploader: '张三', uploadTime: '2026-03-13 09:30:00', url: '' },
-        { id: '7', filename: '系统架构图.jpg', fileType: 'image', size: 1536000, uploader: '李四', uploadTime: '2026-03-12 15:20:00', url: 'https://via.placeholder.com/800x600.png?text=Architecture' },
-        { id: '8', filename: 'API文档.pdf', fileType: 'document', size: 3145728, uploader: '王五', uploadTime: '2026-03-12 10:00:00', url: '' },
-        { id: '9', filename: '测试报告.xlsx', fileType: 'document', size: 512000, uploader: '赵六', uploadTime: '2026-03-11 16:30:00', url: '' },
-        { id: '10', filename: '部署脚本.sh', fileType: 'other', size: 10240, uploader: '孙七', uploadTime: '2026-03-11 09:00:00', url: '' },
-        { id: '11', filename: '用户手册.pdf', fileType: 'document', size: 4194304, uploader: '张三', uploadTime: '2026-03-10 14:00:00', url: '' },
-        { id: '12', filename: '团队合影.jpg', fileType: 'image', size: 2621440, uploader: '李四', uploadTime: '2026-03-10 10:30:00', url: 'https://via.placeholder.com/800x600.png?text=Team+Photo' },
+      const filename = (query.filename as string) || "";
+      const fileType = (query.fileType as string) || "";
+
+      // 模拟文件数据(与后端数据结构一致)
+      const allFiles: Array<{
+        id: string;
+        filename: string;
+        suffix: string;
+        fileType: FileType;
+        url: string;
+        size: number;
+        createdBy: string;
+        createTime: string;
+      }> = [
+        {
+          id: "1",
+          filename: "项目需求文档.pdf",
+          suffix: ".pdf",
+          fileType: "document",
+          url: "",
+          size: 2048576,
+          createdBy: "张三",
+          createTime: "2026-03-15 10:30:00",
+        },
+        {
+          id: "2",
+          filename: "产品原型图.png",
+          suffix: ".png",
+          fileType: "image",
+          url: "https://via.placeholder.com/800x600.png?text=Product+Prototype",
+          size: 512000,
+          createdBy: "李四",
+          createTime: "2026-03-15 09:15:00",
+        },
+        {
+          id: "3",
+          filename: "会议记录.docx",
+          suffix: ".docx",
+          fileType: "document",
+          url: "",
+          size: 102400,
+          createdBy: "王五",
+          createTime: "2026-03-14 16:45:00",
+        },
+        {
+          id: "4",
+          filename: "演示视频.mp4",
+          suffix: ".mp4",
+          fileType: "video",
+          url: "",
+          size: 52428800,
+          createdBy: "赵六",
+          createTime: "2026-03-14 14:20:00",
+        },
+        {
+          id: "5",
+          filename: "背景音乐.mp3",
+          suffix: ".mp3",
+          fileType: "audio",
+          url: "",
+          size: 3145728,
+          createdBy: "孙七",
+          createTime: "2026-03-13 11:00:00",
+        },
+        {
+          id: "6",
+          filename: "数据库备份.sql",
+          suffix: ".sql",
+          fileType: "other",
+          url: "",
+          size: 10485760,
+          createdBy: "张三",
+          createTime: "2026-03-13 09:30:00",
+        },
+        {
+          id: "7",
+          filename: "系统架构图.jpg",
+          suffix: ".jpg",
+          fileType: "image",
+          url: "https://via.placeholder.com/800x600.png?text=Architecture",
+          size: 1536000,
+          createdBy: "李四",
+          createTime: "2026-03-12 15:20:00",
+        },
+        {
+          id: "8",
+          filename: "API文档.pdf",
+          suffix: ".pdf",
+          fileType: "document",
+          url: "",
+          size: 3145728,
+          createdBy: "王五",
+          createTime: "2026-03-12 10:00:00",
+        },
+        {
+          id: "9",
+          filename: "测试报告.xlsx",
+          suffix: ".xlsx",
+          fileType: "document",
+          url: "",
+          size: 512000,
+          createdBy: "赵六",
+          createTime: "2026-03-11 16:30:00",
+        },
+        {
+          id: "10",
+          filename: "部署脚本.sh",
+          suffix: ".sh",
+          fileType: "other",
+          url: "",
+          size: 10240,
+          createdBy: "孙七",
+          createTime: "2026-03-11 09:00:00",
+        },
+        {
+          id: "11",
+          filename: "用户手册.pdf",
+          suffix: ".pdf",
+          fileType: "document",
+          url: "",
+          size: 4194304,
+          createdBy: "张三",
+          createTime: "2026-03-10 14:00:00",
+        },
+        {
+          id: "12",
+          filename: "团队合影.jpg",
+          suffix: ".jpg",
+          fileType: "image",
+          url: "https://via.placeholder.com/800x600.png?text=Team+Photo",
+          size: 2621440,
+          createdBy: "李四",
+          createTime: "2026-03-10 10:30:00",
+        },
       ];
 
       // 筛选
-      let filteredFiles = allFiles.filter(file => {
-        const matchName = filename ? file.filename.toLowerCase().includes(filename.toLowerCase()) : true;
+      let filteredFiles = allFiles.filter((file) => {
+        const matchName = filename
+          ? file.filename.toLowerCase().includes(filename.toLowerCase())
+          : true;
         const matchType = fileType ? file.fileType === fileType : true;
         return matchName && matchType;
       });
@@ -417,17 +555,17 @@ export default [
       const total = filteredFiles.length;
       const start = (page - 1) * size;
       const end = start + size;
-      const list = filteredFiles.slice(start, end);
+      const records = filteredFiles.slice(start, end);
 
       return {
         code: 200,
-        message: "success",
+        msg: "success",
         data: {
-          list,
+          records,
           total,
-          page,
-          size
-        }
+          current: page,
+          size,
+        },
       };
     },
   },
@@ -437,18 +575,20 @@ export default [
     url: "/api/file/upload",
     method: "post",
     response: () => {
+      // 模拟文件上传返回
       return {
         code: 200,
-        message: "上传成功",
+        msg: "success",
         data: {
           id: String(Date.now()),
-          filename: '新上传文件.pdf',
-          fileType: 'document',
+          filename: "新上传文件.pdf",
+          suffix: ".pdf",
+          fileType: "document" as FileType,
+          url: "",
           size: 1024000,
-          uploader: 'admin',
-          uploadTime: new Date().toLocaleString(),
-          url: ''
-        }
+          createdBy: "admin",
+          createTime: new Date().toISOString().replace("T", " ").slice(0, 19),
+        },
       };
     },
   },
@@ -461,7 +601,7 @@ export default [
       return {
         code: 200,
         message: "删除成功",
-        data: null
+        data: null,
       };
     },
   },
@@ -471,13 +611,16 @@ export default [
     url: "/api/file/download",
     method: "get",
     rawResponse: async (req, res) => {
-      const url = new URL(req.url || '', `http://${req.headers.host}`);
-      const id = url.searchParams.get('id') || 'unknown';
+      const url = new URL(req.url || "", `http://${req.headers.host}`);
+      const id = url.searchParams.get("id") || "unknown";
       const filename = `file_${id}.txt`;
 
-      res.setHeader('Content-Type', 'application/octet-stream');
-      res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
-      res.write('This is a mock file content for download.');
+      res.setHeader("Content-Type", "application/octet-stream");
+      res.setHeader(
+        "Content-Disposition",
+        `attachment; filename="${filename}"`,
+      );
+      res.write("This is a mock file content for download.");
       res.end();
     },
   },

+ 31 - 6
src/types/api.ts

@@ -14,11 +14,11 @@ export interface PageParams {
   order?: 'asc' | 'desc'
 }
 
-// 分页响应数据
+// 分页响应数据(后端格式)
 export interface PageResult<T = any> {
-  list: T[]
+  records: T[]
   total: number
-  page: number
+  current: number
   size: number
 }
 
@@ -28,12 +28,37 @@ export interface ListResult<T = any> {
   total: number
 }
 
+// 文件类型枚举
+export type FileType = 'image' | 'document' | 'video' | 'audio' | 'other'
+
+// 文件项
+export interface FileItem {
+  id: string
+  filename: string
+  suffix: string
+  fileType: FileType
+  url: string
+  size: number
+  createdBy: string
+  createTime: string
+}
+
 // 文件上传响应
 export interface UploadResult {
+  id: string
+  filename: string
+  suffix: string
+  fileType: FileType
   url: string
-  name: string
-  size?: number
-  type?: string
+  size: number
+  createdBy: string
+  createTime: string
+}
+
+// 文件查询参数
+export interface FileQueryParams extends PageParams {
+  filename?: string
+  fileType?: FileType | ''
 }
 
 // 请求配置扩展

+ 13 - 2
src/utils/api.ts

@@ -1,5 +1,6 @@
 import { http } from './request'
 import type { UserInfo, MenuItem } from '@/types/menu'
+import type { FileItem, UploadResult, PageResult, FileQueryParams } from '@/types/api'
 
 // 用户相关 API
 export const userApi = {
@@ -54,14 +55,24 @@ export const menuApi = {
 
 // 文件相关 API
 export const fileApi = {
+  // 获取文件列表
+  getList(params: FileQueryParams) {
+    return http.get<PageResult<FileItem>>('/file/list', params)
+  },
+
   // 上传文件
   upload(file: File) {
-    return http.upload<{ url: string; name: string }>('/upms/file/upload', file)
+    return http.upload<UploadResult>('/file/upload', file)
   },
 
   // 下载文件
   download(fileId: string, filename?: string) {
-    return http.download('/upms/file/download', { fileId }, filename)
+    return http.download('/file/download', { id: fileId }, filename)
+  },
+
+  // 删除文件
+  delete(fileId: string) {
+    return http.delete<void>('/file/delete', { id: fileId })
   }
 }
 

+ 4 - 3
src/utils/request.ts

@@ -87,10 +87,11 @@ request.interceptors.response.use(
     const { data } = response
 
     // 根据后端返回的 code 判断请求是否成功
-    // 这里假设后端返回格式: { code: number, data: any, message: string }
+    // 后端返回格式: { code: number, data: any, message?: string, msg?: string }
+    const errorMsg = data.message || data.msg || '请求失败'
     if (data.code !== 200) {
       // 处理业务错误
-      ElMessage.error(data.message || '请求失败')
+      ElMessage.error(errorMsg)
 
       // token 过期处理
       if (data.code === 401) {
@@ -99,7 +100,7 @@ request.interceptors.response.use(
         window.location.href = '/login'
       }
 
-      return Promise.reject(new Error(data.message || '请求失败'))
+      return Promise.reject(new Error(errorMsg))
     }
 
     return data.data

+ 21 - 19
src/views/file/index.vue

@@ -70,8 +70,8 @@
             {{ formatFileSize(row.size) }}
           </template>
         </el-table-column>
-        <el-table-column prop="uploader" label="上传者" width="120" />
-        <el-table-column prop="uploadTime" label="上传时间" width="180" />
+        <el-table-column prop="createdBy" label="上传者" width="120" />
+        <el-table-column prop="createTime" label="上传时间" width="180" />
         <el-table-column label="操作" width="200" fixed="right">
           <template #default="{ row }">
             <el-button type="primary" link @click="handleDownload(row)">下载</el-button>
@@ -152,14 +152,15 @@ import { ref, reactive, computed } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { Upload, UploadFilled, Document, Picture, VideoCamera, Headset, Files } from '@element-plus/icons-vue'
 import type { UploadFile, UploadInstance } from 'element-plus'
-import { http } from '@/utils/request'
+import { fileApi } from '@/utils/api'
+import type { FileItem, FileType } from '@/types/api'
 
 const loading = ref(false)
 const uploadDialogVisible = ref(false)
 const previewDialogVisible = ref(false)
 const previewUrl = ref('')
 const previewType = ref('')
-const currentFile = ref<any>(null)
+const currentFile = ref<FileItem | null>(null)
 const uploadRef = ref<UploadInstance>()
 const fileList = ref<UploadFile[]>([])
 
@@ -181,11 +182,11 @@ const pageInfo = reactive({
   total: 0
 })
 
-const tableData = ref<any[]>([])
+const tableData = ref<FileItem[]>([])
 
 // 获取文件图标
-const getFileIcon = (fileType: string) => {
-  const iconMap: Record<string, any> = {
+const getFileIcon = (fileType: FileType) => {
+  const iconMap: Record<FileType, any> = {
     image: Picture,
     document: Document,
     video: VideoCamera,
@@ -196,8 +197,8 @@ const getFileIcon = (fileType: string) => {
 }
 
 // 获取文件类型标签样式
-const getFileTypeTag = (fileType: string) => {
-  const typeMap: Record<string, any> = {
+const getFileTypeTag = (fileType: FileType) => {
+  const typeMap: Record<FileType, any> = {
     image: 'success',
     document: 'primary',
     video: 'warning',
@@ -208,8 +209,8 @@ const getFileTypeTag = (fileType: string) => {
 }
 
 // 获取文件类型文本
-const getFileTypeText = (fileType: string) => {
-  const textMap: Record<string, string> = {
+const getFileTypeText = (fileType: FileType) => {
+  const textMap: Record<FileType, string> = {
     image: '图片',
     document: '文档',
     video: '视频',
@@ -243,12 +244,13 @@ const handleReset = () => {
 const fetchFileList = async () => {
   loading.value = true
   try {
-    const res = await http.get<{ list: any[], total: number }>('/file/list', {
+    const res = await fileApi.getList({
       page: pageInfo.page,
       size: pageInfo.pageSize,
-      ...searchForm
+      filename: searchForm.filename,
+      fileType: searchForm.fileType || undefined
     })
-    tableData.value = res.list
+    tableData.value = res.records
     pageInfo.total = res.total
   } catch (error) {
     console.error('获取文件列表失败:', error)
@@ -281,8 +283,8 @@ const handleUploadError = (error: any) => {
   ElMessage.error('上传失败,请重试')
 }
 
-const handleDownload = (row: any) => {
-  http.download('/file/download', { id: row.id }, row.filename)
+const handleDownload = (row: FileItem) => {
+  fileApi.download(row.id, row.filename)
     .then(() => {
       ElMessage.success('开始下载')
     })
@@ -291,7 +293,7 @@ const handleDownload = (row: any) => {
     })
 }
 
-const handlePreview = (row: any) => {
+const handlePreview = (row: FileItem) => {
   currentFile.value = row
   if (row.fileType === 'image') {
     previewType.value = 'image'
@@ -303,14 +305,14 @@ const handlePreview = (row: any) => {
   }
 }
 
-const handleDelete = (row: any) => {
+const handleDelete = (row: FileItem) => {
   ElMessageBox.confirm(`确定要删除文件 "${row.filename}" 吗?`, '提示', {
     confirmButtonText: '确定',
     cancelButtonText: '取消',
     type: 'warning'
   }).then(async () => {
     try {
-      await http.delete('/file/delete', { id: row.id })
+      await fileApi.delete(row.id)
       ElMessage.success('删除成功')
       fetchFileList()
     } catch (error) {