From 1bcc0facd2427ee46054d36b5585f82033d54e67 Mon Sep 17 00:00:00 2001 From: chiguyong Date: Sun, 22 Mar 2026 01:25:11 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20-=20API=E5=93=8D=E5=BA=94=E5=B5=8C?= =?UTF-8?q?=E5=A5=97=E7=BB=93=E6=9E=84=E3=80=81=E8=B7=AF=E7=94=B1=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC=E3=80=81CORS=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 关键修复: - stores/user.ts: API响应是{code,message,data{}}结构,使用res.data.data获取token - Login.vue: 使用window.location.href替代router.push进行跳转 - router/index.ts: 修复路由守卫isLoggedIn检查逻辑 - utils/request.ts: baseURL改为绝对路径http://localhost:8080/api - 新增dev-server.mjs: 带API代理的开发服务器(兼容ClashX) - package.json: 添加dev:simple脚本 - 新增组件库: TableCard、Pagination、PermissionTree等 - 新增页面: Audit、UserDetail 已知问题修复: - Vite dev server与ClashX代理冲突问题 Co-authored-by: Trae AI --- dev-server.mjs | 95 +++ package-lock.json | 422 ++++++----- package.json | 9 +- src/api/permission.ts | 26 + src/api/role.ts | 22 +- src/api/user.ts | 34 +- src/components/Card/index.vue | 59 ++ src/components/DescriptionList/index.vue | 27 + src/components/EmailItem/index.vue | 39 + src/components/EmptyState/index.vue | 74 ++ src/components/ErrorState/index.vue | 81 ++ src/components/FilterBar/index.vue | 43 ++ src/components/LoadingState/index.vue | 47 ++ src/components/PageHeader/index.vue | 101 +++ src/components/Pagination/index.vue | 56 ++ src/components/PasswordItem/index.vue | 93 +++ src/components/PermissionTree/index.vue | 112 +++ src/components/PhoneItem/index.vue | 40 + src/components/ProfileCard/index.vue | 58 ++ src/components/ProjectSelect/index.vue | 67 ++ src/components/RoleSelect/index.vue | 66 ++ src/components/StatCard/index.vue | 106 +++ src/components/StatusSelect/index.vue | 35 + src/components/StatusTag/index.vue | 57 ++ src/components/TableActions/index.vue | 92 +++ src/components/TableCard/index.vue | 59 ++ src/components/TableToolbar/index.vue | 51 ++ src/components/UserSelect/index.vue | 72 ++ src/components/index.ts | 65 ++ src/main.ts | 1 + src/router/index.ts | 8 +- src/stores/user.ts | 38 +- src/styles/COMPONENT_SPEC.md | 895 +++++++++++++++++++++++ src/styles/DESIGN_SPEC.md | 360 +++++++++ src/styles/common.css | 76 ++ src/styles/page-common.css | 249 +++++++ src/utils/request.ts | 4 +- src/views/Dashboard.vue | 192 ++++- src/views/Layout.vue | 26 +- src/views/auth/Login.vue | 208 +++++- src/views/project/List.vue | 251 +++++-- src/views/system/Audit.vue | 200 +++++ src/views/system/Permissions.vue | 288 +++++++- src/views/system/Roles.vue | 270 +++++-- src/views/system/UserDetail.vue | 357 +++++++++ src/views/system/Users.vue | 297 ++++++-- src/vite-env.d.ts | 9 + vite.config.ts | 3 +- 48 files changed, 5327 insertions(+), 513 deletions(-) create mode 100644 dev-server.mjs create mode 100644 src/api/permission.ts create mode 100644 src/components/Card/index.vue create mode 100644 src/components/DescriptionList/index.vue create mode 100644 src/components/EmailItem/index.vue create mode 100644 src/components/EmptyState/index.vue create mode 100644 src/components/ErrorState/index.vue create mode 100644 src/components/FilterBar/index.vue create mode 100644 src/components/LoadingState/index.vue create mode 100644 src/components/PageHeader/index.vue create mode 100644 src/components/Pagination/index.vue create mode 100644 src/components/PasswordItem/index.vue create mode 100644 src/components/PermissionTree/index.vue create mode 100644 src/components/PhoneItem/index.vue create mode 100644 src/components/ProfileCard/index.vue create mode 100644 src/components/ProjectSelect/index.vue create mode 100644 src/components/RoleSelect/index.vue create mode 100644 src/components/StatCard/index.vue create mode 100644 src/components/StatusSelect/index.vue create mode 100644 src/components/StatusTag/index.vue create mode 100644 src/components/TableActions/index.vue create mode 100644 src/components/TableCard/index.vue create mode 100644 src/components/TableToolbar/index.vue create mode 100644 src/components/UserSelect/index.vue create mode 100644 src/components/index.ts create mode 100644 src/styles/COMPONENT_SPEC.md create mode 100644 src/styles/DESIGN_SPEC.md create mode 100644 src/styles/common.css create mode 100644 src/styles/page-common.css create mode 100644 src/views/system/Audit.vue create mode 100644 src/views/system/UserDetail.vue create mode 100644 src/vite-env.d.ts diff --git a/dev-server.mjs b/dev-server.mjs new file mode 100644 index 00000000..f1e249e7 --- /dev/null +++ b/dev-server.mjs @@ -0,0 +1,95 @@ +import http from 'http'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const DIST_DIR = path.join(__dirname, 'dist'); +const PORT = 5175; +const API_TARGET = 'http://localhost:8080'; + +const MIME_TYPES = { + '.html': 'text/html', + '.js': 'application/javascript', + '.css': 'text/css', + '.json': 'application/json', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.svg': 'image/svg+xml', + '.ico': 'image/x-icon', +}; + +function proxyRequest(req, res) { + const url = API_TARGET + req.url; + console.log(`[Proxy] ${req.method} ${req.url} -> ${url}`); + + const options = { + hostname: 'localhost', + port: 8080, + path: req.url, + method: req.method, + headers: req.headers, + }; + + const proxyReq = http.request(options, (proxyRes) => { + res.writeHead(proxyRes.statusCode, proxyRes.headers); + proxyRes.pipe(res); + }); + + proxyReq.on('error', (err) => { + console.error(`[Proxy Error] ${err.message}`); + res.writeHead(502, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Proxy error', message: err.message })); + }); + + req.pipe(proxyReq); +} + +const server = http.createServer((req, res) => { + console.log(`${new Date().toISOString()} ${req.method} ${req.url}`); + + // CORS headers + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); + + if (req.method === 'OPTIONS') { + res.writeHead(204); + res.end(); + return; + } + + // Proxy API requests + if (req.url.startsWith('/api')) { + proxyRequest(req, res); + return; + } + + let filePath = path.join(DIST_DIR, req.url === '/' ? 'index.html' : req.url); + + // SPA fallback - 如果文件不存在,返回 index.html + if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) { + filePath = path.join(DIST_DIR, 'index.html'); + } + + const ext = path.extname(filePath); + const contentType = MIME_TYPES[ext] || 'application/octet-stream'; + + try { + const content = fs.readFileSync(filePath); + res.writeHead(200, { + 'Content-Type': contentType, + 'Cache-Control': 'no-cache' + }); + res.end(content); + } catch (err) { + res.writeHead(404); + res.end('Not Found'); + } +}); + +server.listen(PORT, '127.0.0.1', () => { + console.log(`Dev server running at http://127.0.0.1:${PORT}/`); + console.log(`Serving: ${DIST_DIR}`); + console.log(`API proxy: -> ${API_TARGET}`); +}); diff --git a/package-lock.json b/package-lock.json index 36054270..7fc7d703 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,9 +17,9 @@ "devDependencies": { "@playwright/test": "^1.42.0", "@types/node": "^20.0.0", - "@vitejs/plugin-vue": "^5.0.0", + "@vitejs/plugin-vue": "^5.2.1", "typescript": "^5.4.0", - "vite": "^5.2.0", + "vite": "^5.2.14", "vitest": "^1.4.0", "vue-tsc": "^2.0.0" } @@ -129,9 +129,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", "cpu": [ "ppc64" ], @@ -146,9 +146,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -163,9 +163,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -180,9 +180,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -197,9 +197,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -214,9 +214,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -231,9 +231,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -248,9 +248,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -265,9 +265,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -282,9 +282,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -299,9 +299,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -316,9 +316,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -333,9 +333,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -350,9 +350,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -367,9 +367,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -384,9 +384,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -401,9 +401,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -418,9 +418,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -435,9 +435,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -452,9 +452,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -469,9 +469,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -486,9 +486,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -503,9 +503,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -555,9 +555,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.1.tgz", + "integrity": "sha512-xB0b51TB7IfDEzAojXahmr+gfA00uYVInJGgNNkeQG6RPnCPGr7udsylFLTubuIUSRE6FkcI1NElyRt83PP5oQ==", "cpu": [ "arm" ], @@ -569,9 +569,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.1.tgz", + "integrity": "sha512-XOjPId0qwSDKHaIsdzHJtKCxX0+nH8MhBwvrNsT7tVyKmdTx1jJ4XzN5RZXCdTzMpufLb+B8llTC0D8uCrLhcw==", "cpu": [ "arm64" ], @@ -583,9 +583,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.1.tgz", + "integrity": "sha512-vQuRd28p0gQpPrS6kppd8IrWmFo42U8Pz1XLRjSZXq5zCqyMDYFABT7/sywL11mO1EL10Qhh7MVPEwkG8GiBeg==", "cpu": [ "arm64" ], @@ -597,9 +597,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.1.tgz", + "integrity": "sha512-x6VG6U29+Ivlnajrg1IHdzXeAwSoEHBFVO+CtC9Brugx6de712CUJobRUxsIA0KYrQvCmzNrMPFTT1A4CCqNTg==", "cpu": [ "x64" ], @@ -611,9 +611,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.1.tgz", + "integrity": "sha512-Sgi0Uo6t1YCHJMNO3Y8+bm+SvOanUGkoZKn/VJPwYUe2kp31X5KnXmzKd/NjW8iA3gFcfNZ64zh14uOGrIllCQ==", "cpu": [ "arm64" ], @@ -625,9 +625,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.1.tgz", + "integrity": "sha512-AM4xnwEZwukdhk7laMWfzWu9JGSVnJd+Fowt6Fd7QW1nrf3h0Hp7Qx5881M4aqrUlKBCybOxz0jofvIIfl7C5g==", "cpu": [ "x64" ], @@ -639,9 +639,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.1.tgz", + "integrity": "sha512-KUizqxpwaR2AZdAUsMWfL/C94pUu7TKpoPd88c8yFVixJ+l9hejkrwoK5Zj3wiNh65UeyryKnJyxL1b7yNqFQA==", "cpu": [ "arm" ], @@ -653,9 +653,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.1.tgz", + "integrity": "sha512-MZoQ/am77ckJtZGFAtPucgUuJWiop3m2R3lw7tC0QCcbfl4DRhQUBUkHWCkcrT3pqy5Mzv5QQgY6Dmlba6iTWg==", "cpu": [ "arm" ], @@ -667,9 +667,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.1.tgz", + "integrity": "sha512-Sez95TP6xGjkWB1608EfhCX1gdGrO5wzyN99VqzRtC17x/1bhw5VU1V0GfKUwbW/Xr1J8mSasoFoJa6Y7aGGSA==", "cpu": [ "arm64" ], @@ -681,9 +681,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.1.tgz", + "integrity": "sha512-9Cs2Seq98LWNOJzR89EGTZoiP8EkZ9UbQhBlDgfAkM6asVna1xJ04W2CLYWDN/RpUgOjtQvcv8wQVi1t5oQazA==", "cpu": [ "arm64" ], @@ -695,9 +695,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.1.tgz", + "integrity": "sha512-n9yqttftgFy7IrNEnHy1bOp6B4OSe8mJDiPkT7EqlM9FnKOwUMnCK62ixW0Kd9Clw0/wgvh8+SqaDXMFvw3KqQ==", "cpu": [ "loong64" ], @@ -709,9 +709,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.1.tgz", + "integrity": "sha512-SfpNXDzVTqs/riak4xXcLpq5gIQWsqGWMhN1AGRQKB4qGSs4r0sEs3ervXPcE1O9RsQ5bm8Muz6zmQpQnPss1g==", "cpu": [ "loong64" ], @@ -723,9 +723,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.1.tgz", + "integrity": "sha512-LjaChED0wQnjKZU+tsmGbN+9nN1XhaWUkAlSbTdhpEseCS4a15f/Q8xC2BN4GDKRzhhLZpYtJBZr2NZhR0jvNw==", "cpu": [ "ppc64" ], @@ -737,9 +737,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.1.tgz", + "integrity": "sha512-ojW7iTJSIs4pwB2xV6QXGwNyDctvXOivYllttuPbXguuKDX5vwpqYJsHc6D2LZzjDGHML414Tuj3LvVPe1CT1A==", "cpu": [ "ppc64" ], @@ -751,9 +751,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.1.tgz", + "integrity": "sha512-FP+Q6WTcxxvsr0wQczhSE+tOZvFPV8A/mUE6mhZYFW9/eea/y/XqAgRoLLMuE9Cz0hfX5bi7p116IWoB+P237A==", "cpu": [ "riscv64" ], @@ -765,9 +765,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.1.tgz", + "integrity": "sha512-L1uD9b/Ig8Z+rn1KttCJjwhN1FgjRMBKsPaBsDKkfUl7GfFq71pU4vWCnpOsGljycFEbkHWARZLf4lMYg3WOLw==", "cpu": [ "riscv64" ], @@ -779,9 +779,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.1.tgz", + "integrity": "sha512-EZc9NGTk/oSUzzOD4nYY4gIjteo2M3CiozX6t1IXGCOdgxJTlVu/7EdPeiqeHPSIrxkLhavqpBAUCfvC6vBOug==", "cpu": [ "s390x" ], @@ -793,9 +793,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.1.tgz", + "integrity": "sha512-NQ9KyU1Anuy59L8+HHOKM++CoUxrQWrZWXRik4BJFm+7i5NP6q/SW43xIBr80zzt+PDBJ7LeNmloQGfa0JGk0w==", "cpu": [ "x64" ], @@ -807,9 +807,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.1.tgz", + "integrity": "sha512-GZkLk2t6naywsveSFBsEb0PLU+JC9ggVjbndsbG20VPhar6D1gkMfCx4NfP9owpovBXTN+eRdqGSkDGIxPHhmQ==", "cpu": [ "x64" ], @@ -821,9 +821,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.1.tgz", + "integrity": "sha512-1hjG9Jpl2KDOetr64iQd8AZAEjkDUUK5RbDkYWsViYLC1op1oNzdjMJeFiofcGhqbNTaY2kfgqowE7DILifsrA==", "cpu": [ "x64" ], @@ -835,9 +835,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.1.tgz", + "integrity": "sha512-ARoKfflk0SiiYm3r1fmF73K/yB+PThmOwfWCk1sr7x/k9dc3uGLWuEE9if+Pw21el8MSpp3TMnG5vLNsJ/MMGQ==", "cpu": [ "arm64" ], @@ -849,9 +849,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.1.tgz", + "integrity": "sha512-oOST61G6VM45Mz2vdzWMr1s2slI7y9LqxEV5fCoWi2MDONmMvgsJVHSXxce/I2xOSZPTZ47nDPOl1tkwKWSHcw==", "cpu": [ "arm64" ], @@ -863,9 +863,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.1.tgz", + "integrity": "sha512-x5WgLi5dWpRz7WclKBGEF15LcWTh0ewrHM6Cq4A+WUbkysUMZNeqt05bwPonOQ3ihPS/WMhAZV5zB1DfnI4Sxg==", "cpu": [ "ia32" ], @@ -877,9 +877,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.1.tgz", + "integrity": "sha512-wS+zHAJRVP5zOL0e+a3V3E/NTEwM2HEvvNKoDy5Xcfs0o8lljxn+EAFPkUsxihBdmDq1JWzXmmB9cbssCPdxxw==", "cpu": [ "x64" ], @@ -891,9 +891,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.1.tgz", + "integrity": "sha512-rhHyrMeLpErT/C7BxcEsU4COHQUzHyrPYW5tOZUeUhziNtRuYxmDWvqQqzpuUt8xpOgmbKa1btGXfnA/ANVO+g==", "cpu": [ "x64" ], @@ -939,9 +939,9 @@ } }, "node_modules/@vitejs/plugin-vue": { - "version": "5.2.4", - "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", - "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz", + "integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==", "dev": true, "license": "MIT", "engines": { @@ -1610,9 +1610,9 @@ } }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1623,29 +1623,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/estree-walker": { @@ -2336,9 +2336,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "version": "4.59.1", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.59.1.tgz", + "integrity": "sha512-iZKH8BeoCwTCBTZBZWQQMreekd4mdomwdjIQ40GC1oZm6o+8PnNMIxFOiCsGMWeS8iDJ7KZcl7KwmKk/0HOQpA==", "dev": true, "license": "MIT", "dependencies": { @@ -2352,31 +2352,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", + "@rollup/rollup-android-arm-eabi": "4.59.1", + "@rollup/rollup-android-arm64": "4.59.1", + "@rollup/rollup-darwin-arm64": "4.59.1", + "@rollup/rollup-darwin-x64": "4.59.1", + "@rollup/rollup-freebsd-arm64": "4.59.1", + "@rollup/rollup-freebsd-x64": "4.59.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.1", + "@rollup/rollup-linux-arm-musleabihf": "4.59.1", + "@rollup/rollup-linux-arm64-gnu": "4.59.1", + "@rollup/rollup-linux-arm64-musl": "4.59.1", + "@rollup/rollup-linux-loong64-gnu": "4.59.1", + "@rollup/rollup-linux-loong64-musl": "4.59.1", + "@rollup/rollup-linux-ppc64-gnu": "4.59.1", + "@rollup/rollup-linux-ppc64-musl": "4.59.1", + "@rollup/rollup-linux-riscv64-gnu": "4.59.1", + "@rollup/rollup-linux-riscv64-musl": "4.59.1", + "@rollup/rollup-linux-s390x-gnu": "4.59.1", + "@rollup/rollup-linux-x64-gnu": "4.59.1", + "@rollup/rollup-linux-x64-musl": "4.59.1", + "@rollup/rollup-openbsd-x64": "4.59.1", + "@rollup/rollup-openharmony-arm64": "4.59.1", + "@rollup/rollup-win32-arm64-msvc": "4.59.1", + "@rollup/rollup-win32-ia32-msvc": "4.59.1", + "@rollup/rollup-win32-x64-gnu": "4.59.1", + "@rollup/rollup-win32-x64-msvc": "4.59.1", "fsevents": "~2.3.2" } }, @@ -2568,15 +2568,15 @@ "license": "MIT" }, "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "version": "5.2.14", + "resolved": "https://registry.npmmirror.com/vite/-/vite-5.2.14.tgz", + "integrity": "sha512-TFQLuwWLPms+NBNlh0D9LZQ+HXW471COABxw/9TEUBrjuHMo9BrYBPrN/SYAwIuVL+rLerycxiLT41t4f5MZpA==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" }, "bin": { "vite": "bin/vite.js" @@ -2595,7 +2595,6 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", - "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -2613,9 +2612,6 @@ "sass": { "optional": true }, - "sass-embedded": { - "optional": true - }, "stylus": { "optional": true }, diff --git a/package.json b/package.json index 025db0d6..7d2ca9e6 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "type": "module", "scripts": { "dev": "vite", + "dev:simple": "node dev-server.mjs", "build": "vue-tsc -b && vite build", "preview": "vite preview", "test": "vitest", @@ -17,12 +18,12 @@ "vue-router": "^4.3.0" }, "devDependencies": { + "@playwright/test": "^1.42.0", "@types/node": "^20.0.0", - "@vitejs/plugin-vue": "^5.0.0", + "@vitejs/plugin-vue": "^5.2.1", "typescript": "^5.4.0", - "vite": "^5.2.0", + "vite": "^5.2.14", "vitest": "^1.4.0", - "vue-tsc": "^2.0.0", - "@playwright/test": "^1.42.0" + "vue-tsc": "^2.0.0" } } diff --git a/src/api/permission.ts b/src/api/permission.ts new file mode 100644 index 00000000..ce3a68e2 --- /dev/null +++ b/src/api/permission.ts @@ -0,0 +1,26 @@ +import request from '@/utils/request' +import type { Permission } from '@/types' + +export const getPermissions = () => { + return request.get('/api/permissions') +} + +export const getPermission = (id: string) => { + return request.get(`/api/permissions/${id}`) +} + +export const createPermission = (data: Partial) => { + return request.post('/api/permissions', data) +} + +export const updatePermission = (id: string, data: Partial) => { + return request.put(`/api/permissions/${id}`, data) +} + +export const deletePermission = (id: string) => { + return request.delete(`/api/permissions/${id}`) +} + +export const getPermissionsByModule = (module: string) => { + return request.get(`/api/permissions/module/${module}`) +} diff --git a/src/api/role.ts b/src/api/role.ts index e8c445a5..b8a77bea 100644 --- a/src/api/role.ts +++ b/src/api/role.ts @@ -2,29 +2,37 @@ import request from '@/utils/request' import type { Role } from '@/types' export const getRoles = () => { - return request.get('/roles') + return request.get('/api/roles') } export const getRole = (id: string) => { - return request.get(`/roles/${id}`) + return request.get(`/api/roles/${id}`) } export const getRolesByProject = (projectId: string) => { - return request.get(`/roles/project/${projectId}`) + return request.get(`/api/roles/project/${projectId}`) } export const createRole = (data: Partial) => { - return request.post('/roles', data) + return request.post('/api/roles', data) } export const updateRole = (id: string, data: Partial) => { - return request.put(`/roles/${id}`, data) + return request.put(`/api/roles/${id}`, data) } export const deleteRole = (id: string) => { - return request.delete(`/roles/${id}`) + return request.delete(`/api/roles/${id}`) } export const assignPermissions = (roleId: string, permissionIds: string[]) => { - return request.post(`/roles/${roleId}/permissions`, permissionIds) + return request.post(`/api/roles/${roleId}/permissions`, permissionIds) +} + +export const getUserRoles = (userId: string) => { + return request.get(`/api/users/${userId}/roles`) +} + +export const removeRoleFromUser = (userId: string, roleId: string) => { + return request.delete(`/api/users/${userId}/roles/${roleId}`) } diff --git a/src/api/user.ts b/src/api/user.ts index 0ce8c2c6..f35cdf2b 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -2,29 +2,49 @@ import request from '@/utils/request' import type { User } from '@/types' export const getUsers = () => { - return request.get('/users') + return request.get('/api/users') } export const getUser = (id: string) => { - return request.get(`/users/${id}`) + return request.get(`/api/users/${id}`) } export const createUser = (data: Partial) => { - return request.post('/users', data) + return request.post('/api/users', data) } export const updateUser = (id: string, data: Partial) => { - return request.put(`/users/${id}`, data) + return request.put(`/api/users/${id}`, data) } export const deleteUser = (id: string) => { - return request.delete(`/users/${id}`) + return request.delete(`/api/users/${id}`) } export const updatePassword = (id: string, oldPassword: string, newPassword: string) => { - return request.put(`/users/${id}/password`, { oldPassword, newPassword }) + return request.put(`/api/users/${id}/password`, { oldPassword, newPassword }) } export const assignRoles = (userId: string, roleIds: string[]) => { - return request.post(`/users/${userId}/roles`, roleIds) + return request.post(`/api/users/${userId}/roles`, roleIds) +} + +export interface UserProject { + id: string + userId: string + projectId: string + roleInProject: 'leader' | 'member' | 'viewer' + joinedAt: string +} + +export const getUserProjects = (userId: string) => { + return request.get(`/api/users/${userId}/projects`) +} + +export const addUserToProject = (userId: string, projectId: string, roleInProject: string) => { + return request.post(`/api/users/${userId}/projects`, { projectId, roleInProject }) +} + +export const removeUserFromProject = (userId: string, projectId: string) => { + return request.delete(`/api/users/${userId}/projects/${projectId}`) } diff --git a/src/components/Card/index.vue b/src/components/Card/index.vue new file mode 100644 index 00000000..3ddccc9d --- /dev/null +++ b/src/components/Card/index.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/components/DescriptionList/index.vue b/src/components/DescriptionList/index.vue new file mode 100644 index 00000000..2a37ff75 --- /dev/null +++ b/src/components/DescriptionList/index.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/src/components/EmailItem/index.vue b/src/components/EmailItem/index.vue new file mode 100644 index 00000000..d1b064ca --- /dev/null +++ b/src/components/EmailItem/index.vue @@ -0,0 +1,39 @@ + + + diff --git a/src/components/EmptyState/index.vue b/src/components/EmptyState/index.vue new file mode 100644 index 00000000..e67ef79c --- /dev/null +++ b/src/components/EmptyState/index.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/src/components/ErrorState/index.vue b/src/components/ErrorState/index.vue new file mode 100644 index 00000000..59fb4a09 --- /dev/null +++ b/src/components/ErrorState/index.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/src/components/FilterBar/index.vue b/src/components/FilterBar/index.vue new file mode 100644 index 00000000..832269dd --- /dev/null +++ b/src/components/FilterBar/index.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/components/LoadingState/index.vue b/src/components/LoadingState/index.vue new file mode 100644 index 00000000..2b464eba --- /dev/null +++ b/src/components/LoadingState/index.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/src/components/PageHeader/index.vue b/src/components/PageHeader/index.vue new file mode 100644 index 00000000..4e03042c --- /dev/null +++ b/src/components/PageHeader/index.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue new file mode 100644 index 00000000..26516b4f --- /dev/null +++ b/src/components/Pagination/index.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/components/PasswordItem/index.vue b/src/components/PasswordItem/index.vue new file mode 100644 index 00000000..c810660f --- /dev/null +++ b/src/components/PasswordItem/index.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/src/components/PermissionTree/index.vue b/src/components/PermissionTree/index.vue new file mode 100644 index 00000000..f51da332 --- /dev/null +++ b/src/components/PermissionTree/index.vue @@ -0,0 +1,112 @@ + + + diff --git a/src/components/PhoneItem/index.vue b/src/components/PhoneItem/index.vue new file mode 100644 index 00000000..0245c7b4 --- /dev/null +++ b/src/components/PhoneItem/index.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/components/ProfileCard/index.vue b/src/components/ProfileCard/index.vue new file mode 100644 index 00000000..02e0b9ef --- /dev/null +++ b/src/components/ProfileCard/index.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/components/ProjectSelect/index.vue b/src/components/ProjectSelect/index.vue new file mode 100644 index 00000000..dde7694b --- /dev/null +++ b/src/components/ProjectSelect/index.vue @@ -0,0 +1,67 @@ + + + diff --git a/src/components/RoleSelect/index.vue b/src/components/RoleSelect/index.vue new file mode 100644 index 00000000..5c2df600 --- /dev/null +++ b/src/components/RoleSelect/index.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/components/StatCard/index.vue b/src/components/StatCard/index.vue new file mode 100644 index 00000000..e1accb01 --- /dev/null +++ b/src/components/StatCard/index.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/src/components/StatusSelect/index.vue b/src/components/StatusSelect/index.vue new file mode 100644 index 00000000..30146c75 --- /dev/null +++ b/src/components/StatusSelect/index.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/components/StatusTag/index.vue b/src/components/StatusTag/index.vue new file mode 100644 index 00000000..1e7908fc --- /dev/null +++ b/src/components/StatusTag/index.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/components/TableActions/index.vue b/src/components/TableActions/index.vue new file mode 100644 index 00000000..04e8eede --- /dev/null +++ b/src/components/TableActions/index.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/src/components/TableCard/index.vue b/src/components/TableCard/index.vue new file mode 100644 index 00000000..14d8b364 --- /dev/null +++ b/src/components/TableCard/index.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/components/TableToolbar/index.vue b/src/components/TableToolbar/index.vue new file mode 100644 index 00000000..acd139d1 --- /dev/null +++ b/src/components/TableToolbar/index.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/src/components/UserSelect/index.vue b/src/components/UserSelect/index.vue new file mode 100644 index 00000000..399d2b2a --- /dev/null +++ b/src/components/UserSelect/index.vue @@ -0,0 +1,72 @@ + + + diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 00000000..252be1e9 --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,65 @@ +/** + * Ether Admin 组件库 + * + * 基础组件: + * - PageHeader: 页面标题区 + * - Card: 通用卡片 + * - TableCard: 表格卡片 + * - StatCard: 统计卡片 + * - FilterBar: 筛选栏 + * - StatusTag: 状态标签 + * + * 状态组件: + * - EmptyState: 空状态 + * - ErrorState: 错误状态 + * - LoadingState: 加载状态 + * + * 表格组件: + * - TableToolbar: 表格工具栏 + * - TableActions: 表格行操作 + * - Pagination: 分页器 + * + * 业务组件: + * - UserSelect: 用户选择器 + * - RoleSelect: 角色选择器 + * - ProjectSelect: 项目选择器 + * - StatusSelect: 状态选择器 + * - PhoneItem: 手机号表单项 + * - EmailItem: 邮箱表单项 + * - PasswordItem: 密码表单项(含强度) + * - DescriptionList: 描述列表 + * - ProfileCard: 个人资料卡片 + */ + +// 基础组件 +export { default as PageHeader } from './PageHeader/index.vue' +export { default as Card } from './Card/index.vue' +export { default as TableCard } from './TableCard/index.vue' +export { default as StatCard } from './StatCard/index.vue' +export { default as FilterBar } from './FilterBar/index.vue' +export { default as StatusTag } from './StatusTag/index.vue' + +// 状态组件 +export { default as EmptyState } from './EmptyState/index.vue' +export { default as ErrorState } from './ErrorState/index.vue' +export { default as LoadingState } from './LoadingState/index.vue' + +// 表格组件 +export { default as TableToolbar } from './TableToolbar/index.vue' +export { default as TableActions } from './TableActions/index.vue' +export { default as Pagination } from './Pagination/index.vue' + +// 业务组件 - 选择器 +export { default as UserSelect } from './UserSelect/index.vue' +export { default as RoleSelect } from './RoleSelect/index.vue' +export { default as ProjectSelect } from './ProjectSelect/index.vue' +export { default as StatusSelect } from './StatusSelect/index.vue' + +// 业务组件 - 表单项 +export { default as PhoneItem } from './PhoneItem/index.vue' +export { default as EmailItem } from './EmailItem/index.vue' +export { default as PasswordItem } from './PasswordItem/index.vue' + +// 业务组件 - 详情 +export { default as DescriptionList } from './DescriptionList/index.vue' +export { default as ProfileCard } from './ProfileCard/index.vue' diff --git a/src/main.ts b/src/main.ts index 97aaa976..76ab60af 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,7 @@ import 'ant-design-vue/dist/reset.css' import App from './App.vue' import router from './router' import './style.css' +import './styles/page-common.css' const app = createApp(App) diff --git a/src/router/index.ts b/src/router/index.ts index 5c3bc6fa..c1adaebe 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -39,6 +39,12 @@ const router = createRouter({ component: () => import('@/views/system/Permissions.vue'), meta: { title: '权限管理' } }, + { + path: 'system/audit', + name: 'Audit', + component: () => import('@/views/system/Audit.vue'), + meta: { title: '审计日志' } + }, { path: 'project/list', name: 'ProjectList', @@ -50,7 +56,7 @@ const router = createRouter({ ] }) -router.beforeEach((to, from, next) => { +router.beforeEach((to, _from, next) => { const userStore = useUserStore() if (to.path !== '/login' && !userStore.isLoggedIn()) { next('/login') diff --git a/src/stores/user.ts b/src/stores/user.ts index 138ae459..acd37461 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -9,12 +9,18 @@ export const useUserStore = defineStore('user', () => { const login = async (data: LoginRequest) => { const res = await loginApi(data) - token.value = res.data.token - userInfo.value = { - username: res.data.username, - realName: res.data.realName + const loginData = res.data.data + if (!loginData?.token) { + throw new Error('登录失败:未获取到token') } - localStorage.setItem('token', res.data.token) + const newToken = loginData.token + token.value = newToken + userInfo.value = { + username: loginData.username, + realName: loginData.realName + } + localStorage.setItem('token', newToken) + localStorage.setItem('userInfo', JSON.stringify(userInfo.value)) } const logout = async () => { @@ -22,9 +28,29 @@ export const useUserStore = defineStore('user', () => { token.value = '' userInfo.value = null localStorage.removeItem('token') + localStorage.removeItem('userInfo') } - const isLoggedIn = () => !!token.value + const isLoggedIn = () => { + const storedToken = localStorage.getItem('token') + if (!storedToken || storedToken === 'null' || storedToken === 'undefined') { + return false + } + const parts = storedToken.split('.') + if (parts.length !== 3) { + return false + } + try { + const payload = JSON.parse(atob(parts[1])) + if (payload.exp && payload.exp * 1000 < Date.now()) { + logout() + return false + } + } catch { + return false + } + return true + } return { token, diff --git a/src/styles/COMPONENT_SPEC.md b/src/styles/COMPONENT_SPEC.md new file mode 100644 index 00000000..6c677673 --- /dev/null +++ b/src/styles/COMPONENT_SPEC.md @@ -0,0 +1,895 @@ +# Ether 组件库规范 + +## 目录 +1. [业务组件](#业务组件) +2. [状态场景](#状态场景) +3. [交互规范](#交互规范) + +--- + +## 业务组件 + +### 1. Select 选择器 + +#### UserSelect 用户选择器 +```vue + + + +``` + +#### RoleSelect 角色选择器 +```vue + +``` + +#### ProjectSelect 项目选择器 +```vue + +``` + +#### StatusSelect 状态选择器 +```vue + +``` + +--- + +### 2. FormItem 表单项 + +#### PhoneItem 手机号表单项 +```vue + + + +``` + +#### EmailItem 邮箱表单项 +```vue + + + +``` + +#### PasswordItem 密码表单项 +```vue + + + +``` + +--- + +### 3. Table 表格增强 + +#### Pagination 分页器 +```vue + +``` + +#### TableToolbar 表格工具栏 +```vue + +``` + +#### TableActions 行操作 +```vue + +``` + +--- + +### 4. Detail 详情组件 + +#### DescriptionList 描述列表 +```vue + +``` + +#### ProfileCard 个人资料卡片 +```vue + +``` + +--- + +## 状态场景 + +### 1. 空状态 EmptyState + +```vue + + + + + +``` + +**使用场景:** +| 场景 | 图标 | 标题 | 描述 | 操作 | +|------|------|------|------|------| +| 列表无数据 | InboxOutlined | 暂无数据 | - | 可选:立即添加 | +| 搜索无结果 | SearchOutlined | 未找到结果 | 请尝试其他关键词 | 可选:清除筛选 | +| 无权限 | LockOutlined | 无访问权限 | 您没有访问该页面的权限 | 可选:申请权限 | + +--- + +### 2. 加载状态 LoadingState + +#### Skeleton 骨架屏 +```vue + +``` + +**骨架屏使用场景:** +- 页面首次加载 +- 数据量较大的列表 +- 表单页面 + +#### Spin 加载中 +```vue + + + +``` + +**Spin 使用场景:** +- 按钮加载状态 +- 抽屉/弹窗内容加载 +- 局部操作加载 + +--- + +### 3. 错误状态 ErrorState + +```vue + +``` + +**错误状态类型:** +| 类型 | 图标 | 标题 | 描述示例 | +|------|------|------|----------| +| 网络错误 | WifiOutlined | 网络连接失败 | 请检查网络后重试 | +| 服务器错误 | ServerOutlined | 服务异常 | 请稍后重试或联系管理员 | +| 权限不足 | LockOutlined | 无权限访问 | 您没有权限执行此操作 | +| 404 | FileSearchOutlined | 页面不存在 | 请检查URL是否正确 | +| 操作失败 | CloseCircleOutlined | 操作失败 | {{ errorMessage }} | + +--- + +### 4. 成功反馈 SuccessState + +```vue + +``` + +**使用场景:** +- 操作成功确认 +- 提交成功反馈 + +--- + +### 5. 确认对话框 ConfirmDialog + +```vue + + + +``` + +**类型对应:** +| 类型 | 图标 | 颜色 | 用途 | +|------|------|------|------| +| info | InfoCircleOutlined | #1890FF | 一般信息确认 | +| success | CheckCircleOutlined | #52C41A | 成功确认 | +| warning | WarningOutlined | #FAAD14 | 警告确认 | +| error | CloseCircleOutlined | #F5222D | 错误确认 | +| danger | ExclamationCircleOutlined | #F5222D | 危险操作确认 | + +--- + +## 交互规范 + +### 1. 过渡动画 + +#### 时长规范 +| 类型 | 时长 | 用途 | +|------|------|------| +| 快速 | 150ms | 微交互、hover效果 | +| 正常 | 200ms | 一般状态变化 | +| 缓慢 | 300ms | 页面过渡、模态框 | +| 渐入 | 400ms | 内容加载、列表展开 | + +#### 缓动函数 +```css +/* 标准缓出 - 推荐用于大部分动画 */ +transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + +/* 进入动画 */ +transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + +/* 退出动画 */ +transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +``` + +#### 抽屉过渡 +```vue + +``` + +--- + +### 2. 手势交互 + +#### 滑动操作 +```vue + +``` + +**使用场景:** +- 移动端列表项操作 +- 审批流程滑动操作 + +#### 下拉刷新 +```vue + +``` + +--- + +### 3. 快捷键规范 + +| 快捷键 | 动作 | 场景 | +|--------|------|------| +| Enter | 提交/确认 | 表单、对话框 | +| Escape | 取消/关闭 | 模态框、抽屉 | +| Ctrl+S | 保存 | 表单编辑页 | +| Ctrl+R | 刷新 | 列表页 | +| Ctrl+F | 聚焦搜索 | 列表页 | +| Ctrl+N | 新增 | 列表页 | + +--- + +### 4. 触控反馈 + +#### 按压状态 +```css +.button:active { + opacity: 0.8; + transform: scale(0.98); +} +``` + +#### 列表项触控 +```css +.list-item:active { + background-color: #f0f0f0; +} + +.list-item { + min-height: 44px; /* 触控友好高度 */ + padding: 12px 16px; +} +``` + +--- + +### 5. 表单交互 + +#### 实时校验 +```vue + +``` + +#### 错误提示位置 +- 输入框下方 +- 红色文字 +- 12px 字号 +- 8px 上边距 + +--- + +### 6. 通知提示 + +#### Message 消息提示 +| 类型 | 用途 | 时长 | +|------|------|------| +| success | 操作成功 | 3s | +| error | 操作失败 | 无限制(需手动关闭) | +| warning | 警告信息 | 4s | +| info | 一般信息 | 3s | + +#### Notification 通知 +- 右上角弹出 +- 右上角关闭 +- 自动隐藏(info/success: 4s, warning: 6s, error: 不自动关闭) + +--- + +### 7. 触控 vs 鼠标交互差异 + +| 元素 | 鼠标场景 | 触控场景 | +|------|----------|----------| +| 按钮 hover | 显示 hover 效果 | 不显示 | +| 下拉菜单 | hover 展开 | 点击展开 | +| 表格排序 | 点击表头 | 点击表头 | +| 卡片详情 | hover 显示操作 | 点击进入详情 | +| 删除确认 | 可直接点击 | 必须确认 | + +--- + +### 8. 无障碍规范 + +#### 焦点管理 +```vue + + + + +``` + +#### ARIA 标签 +```vue +删除 + + + + +``` + +#### 对比度 +- 正文文字:≥ 4.5:1 +- 大文字(≥18px):≥ 3:1 +- 图形和 UI 组件:≥ 3:1 + +--- + +## 组件开发模板 + +```vue + + + + + + + +``` + +## 组件发布检查清单 + +- [ ] TypeScript 类型定义完整 +- [ ] Props 有默认值和类型 +- [ ] Emits 有 TypeScript 类型 +- [ ] 样式已 scoped +- [ ] 有组件文档注释 +- [ ] 支持 v-model(如果适用) +- [ ] 已在 index.ts 导出 +- [ ] 已在 CLAUDE.md 记录 + +--- + +## 组件扩展计划 + +### 选择器组件 + +#### UserSelect 用户选择器 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 本地搜索 | filter-option | +| ✅ 已支持 | 多选模式 | multiple prop | +| ✅ 已支持 | 禁用状态 | disabled prop | +| 🔲 待开发 | 远程搜索 | remote-search prop | +| 🔲 待开发 | 分组展示 | group prop | +| 🔲 待开发 | 树形数据 | treeData prop | +| 🔲 待开发 | 懒加载 | lazy-load prop | +| 🔲 待开发 | 允许创建 | allow-create prop | + +#### RoleSelect 角色选择器 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 多选模式 | multiple prop | +| ✅ 已支持 | 禁用状态 | disabled prop | +| 🔲 待开发 | 角色类型筛选 | type prop | +| 🔲 待开发 | 树形角色 | treeData prop | +| 🔲 待开发 | 懒加载 | lazy-load prop | + +#### ProjectSelect 项目选择器 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 搜索功能 | show-search | +| ✅ 已支持 | 单选模式 | - | +| 🔲 待开发 | 多选模式 | multiple prop | +| 🔲 待开发 | 区域筛选 | region prop | +| 🔲 待开发 | 懒加载 | lazy-load prop | + +#### StatusSelect 状态选择器 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 默认选项 | ACTIVE/LOCKED/DISABLED | +| ✅ 已支持 | 自定义选项 | options prop | +| 🔲 待开发 | 颜色配置 | color-map prop | +| 🔲 待开发 | 禁用状态 | disabled prop | +| 🔲 待开发 | 状态组 | groups prop | + +--- + +### 表单组件 + +#### PhoneItem 手机号表单项 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 11位验证 | 1开头的数字 | +| ✅ 已支持 | 最大长度 | maxlength=11 | +| ✅ 已支持 | 标签配置 | label prop | +| 🔲 待开发 | 前缀选择 | country-code prop | +| 🔲 待开发 | 实时格式化 | format prop | +| 🔲 待开发 | 自动补全 | autocomplete | + +#### EmailItem 邮箱表单项 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 邮箱格式验证 | type: email | +| ✅ 已支持 | 标签配置 | label prop | +| 🔲 待开发 | 域名白名单 | allowed-domains | +| 🔲 待开发 | 自动补全 | autocomplete | + +#### PasswordItem 密码表单项 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 强度指示器 | show-strength | +| ✅ 已支持 | 弱/中/强/很强 | 4级强度 | +| ✅ 已支持 | 标签配置 | label prop | +| 🔲 待开发 | 强度规则配置 | strength-rules | +| 🔲 待开发 | 显示/隐藏切换 | visibility-toggle | +| 🔲 待开发 | 密码生成器 | generator prop | + +--- + +### 表格增强组件 + +#### Pagination 分页器 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 页码切换 | v-model:current | +| ✅ 已支持 | 每页条数 | v-model:pageSize | +| ✅ 已支持 | 总数显示 | show-total | +| ✅ 已支持 | sizeChanger | show-size-changer | +| 🔲 待开发 | 快速跳转 | show-quick-jumper | +| 🔲 待开发 | 简洁模式 | simple prop | +| 🔲 待开发 | 受控模式 | controlled | + +#### TableToolbar 表格工具栏 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 刷新按钮 | showRefresh | +| ✅ 已支持 | 导出按钮 | showExport | +| ✅ 已支持 | 左侧插槽 | #left | +| ✅ 已支持 | 右侧插槽 | #right | +| 🔲 待开发 | 列配置 | column-setting | +| 🔲 待开发 | 密度切换 | density-switcher | +| 🔲 待开发 | 全屏切换 | fullscreen | + +#### TableActions 表格行操作 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 编辑按钮 | showEdit | +| ✅ 已支持 | 删除按钮 | showDelete | +| ✅ 已支持 | 自定义操作 | actions prop | +| ✅ 已支持 | 删除确认 | Popconfirm | +| 🔲 待开发 | 更多操作 | more-actions dropdown | +| 🔲 待开发 | 成功反馈 | success-message | +| 🔲 待开发 | 二次确认配置 | confirm-title/description | + +--- + +### 详情组件 + +#### DescriptionList 描述列表 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 多列布局 | column prop | +| ✅ 已支持 | 边框样式 | bordered | +| ✅ 已支持 | 尺寸配置 | size prop | +| 🔲 待开发 | 响应式列数 | responsive prop | +| 🔲 待开发 | 可编辑模式 | editable prop | +| 🔲 待开发 | 折叠展示 | collapsible | +| 🔲 待开发 | 标签-内容对齐 | labelAlign | + +#### ProfileCard 个人资料卡片 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 头像展示 | avatar prop | +| ✅ 已支持 | 名称展示 | name prop | +| ✅ 已支持 | 角色展示 | role prop | +| ✅ 已支持 | 扩展插槽 | #extra | +| 🔲 待开发 | 头像尺寸 | size prop | +| 🔲 待开发 | 联系方式 | contact prop | +| 🔲 待开发 | 操作按钮 | actions prop | +| 🔲 待开发 | 背景配置 | background prop | + +--- + +### 状态组件 + +#### EmptyState 空状态 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 默认空状态 | InboxOutlined | +| ✅ 已支持 | 搜索无结果 | SearchOutlined | +| ✅ 已支持 | 无权限 | LockOutlined | +| ✅ 已支持 | 操作按钮 | actionText | +| 🔲 待开发 | 自定义图标 | icon slot | +| 🔲 待开发 | 图片模式 | image prop | + +#### ErrorState 错误状态 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 网络错误 | WifiOutlined | +| ✅ 已支持 | 服务器错误 | CloudServerOutlined | +| ✅ 已支持 | 404 | FileSearchOutlined | +| ✅ 已支持 | 操作失败 | CloseCircleOutlined | +| ✅ 已支持 | 重试按钮 | showRetry | +| ✅ 已支持 | 返回按钮 | showBack | +| 🔲 待开发 | 自定义图标 | icon slot | + +#### LoadingState 加载状态 +| 状态 | 功能 | 说明 | +|------|------|------| +| ✅ 已支持 | 全屏加载 | fullscreen prop | +| ✅ 已支持 | 局部加载 | - | +| 🔲 待开发 | 骨架屏 | skeleton prop | +| 🔲 待开发 | 进度显示 | progress prop | +| 🔲 待开发 | 加载文案 | text prop | + +--- + +### 扩展优先级说明 + +| 优先级 | 标记 | 说明 | +|--------|------|------| +| P0 | 🔴 紧急 | 影响核心流程,必须尽快实现 | +| P1 | 🟡 重要 | 提升效率,尽快安排 | +| P2 | 🔵 一般 | 锦上添花,按需实现 | +| P3 | ⚪ 考察 | 考虑中,暂不实现 | + +--- + +### 升级流程 + +1. **需求提出** → 在对应组件的扩展计划中新增条目 +2. **评审确认** → 确认是否真的需要,还是抽象过度 +3. **实现开发** → 参考组件开发模板 +4. **文档更新** → 更新扩展计划状态 + 更新使用示例 +5. **发布记录** → 在 CHANGELOG 中记录 diff --git a/src/styles/DESIGN_SPEC.md b/src/styles/DESIGN_SPEC.md new file mode 100644 index 00000000..23d0f705 --- /dev/null +++ b/src/styles/DESIGN_SPEC.md @@ -0,0 +1,360 @@ +# Ether 智慧物业管理平台 - 设计规范 + +## 目录 +1. [设计原则](#设计原则) +2. [色彩系统](#色彩系统) +3. [字体系统](#字体系统) +4. [间距系统](#间距系统) +5. [圆角系统](#圆角系统) +6. [阴影系统](#阴影系统) +7. [页面布局](#页面布局) +8. [PC端组件规范](#pc端组件规范) +9. [移动端组件规范](#移动端组件规范) +10. [登录页设计规范](#登录页设计规范) + +--- + +## 设计原则 + +### 核心原则 +1. **专业严谨**:适合物业管理行业的正式感 +2. **效率优先**:减少操作步骤,优化工作流程 +3. **一致性**:统一组件样式和交互模式 +4. **可访问性**:考虑长时间使用的舒适度 + +### 视觉原则 +- 简洁清晰,层次分明 +- 信息密度适中 +- 交互不打断工作流 + +--- + +## 色彩系统 + +### 主色 +| 名称 | 色值 | 用途 | +|------|------|------| +| 主色 | `#1890FF` | 按钮、链接、图标高亮 | +| 主色深 | `#096DD9` | 按钮 hover、渐变 | +| 主色浅 | `#40A9FF` | hover 状态 | + +### 状态色 +| 名称 | 色值 | 用途 | +|------|------|------| +| 成功 | `#52C41A` | 成功状态、正常状态 | +| 警告 | `#FAAD14` | 警告状态 | +| 错误 | `#F5222D` | 错误状态、删除按钮 | +| 锁定 | `#FF4D4F` | 数字徽章 | + +### 中性色 +| 名称 | 色值 | 用途 | +|------|------|------| +| 标题文字 | `#1A1A1A` | 一级标题 | +| 正文文字 | `#262626` | 二级标题、正文 | +| 次要文字 | `#595959` | 辅助说明 | +| 占位文字 | `#8C8C8C` | 标签、占位符 | +| 禁用文字 | `#BFBFBF` | 禁用状态 | +| 边框 | `#E8E8E8` | 卡片边框、分隔线 | +| 背景灰 | `#F0F0F0` | 表格斑马线 | +| 页面背景 | `#F5F7FA` | 页面背景 | +| 卡片背景 | `#FFFFFF` | 卡片、表格 | + +--- + +## 字体系统 + +### PC端 +| 名称 | 字号 | 字重 | 用途 | +|------|------|------|------| +| 页面标题 | 20px | 500 | 页面大标题 | +| 卡片标题 | 16px | 500 | 卡片标题 | +| 正文 | 14px | 400 | 正文内容 | +| 辅助文字 | 13px | 400 | 辅助说明 | +| 标签 | 12px | 400 | 小标签、时间 | + +### 移动端 +| 名称 | 字号 | 字重 | 用途 | +|------|------|------|------| +| 页面标题 | 18px | 600 | 页面大标题 | +| 卡片标题 | 15px | 500 | 卡片标题 | +| 正文 | 14px | 400 | 正文内容 | +| 辅助文字 | 12px | 400 | 辅助说明 | +| 标签 | 11px | 400 | 小标签 | + +### 字体规范 +- 主字体:系统默认字体栈 `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial` +- 英文字体:`'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto` +- 行高:1.5 倍字号 + +--- + +## 间距系统 + +### PC端 +| 名称 | 间距 | 用途 | +|------|------|------| +| xs | 4px | 紧凑间距 | +| sm | 8px | 元素内间距 | +| md | 16px | 组件间距 | +| lg | 24px | 区块间距 | +| xl | 32px | 大区块间距 | +| xxl | 48px | 页面边距 | + +### 移动端 +| 名称 | 间距 | 用途 | +|------|------|------| +| xs | 4px | 紧凑间距 | +| sm | 8px | 元素内间距 | +| md | 12px | 组件间距 | +| lg | 16px | 区块间距 | +| xl | 24px | 大区块间距 | + +--- + +## 圆角系统 + +| 名称 | 大小 | 用途 | +|------|------|------| +| 小圆角 | 4px | 按钮、输入框、标签 | +| 中圆角 | 8px | 卡片、面板 | +| 大圆角 | 12px | 模态框、抽屉 | +| 全圆角 | 50% | 头像、徽章 | + +--- + +## 阴影系统 + +### PC端 +| 名称 | 样式 | 用途 | +|------|------|------| +| 无阴影 | `none` | 默认扁平 | +| 悬浮阴影 | `0 4px 12px rgba(24, 144, 255, 0.15)` | 卡片 hover | +| 登录卡片 | `0 4px 24px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04)` | 登录卡片 | + +### 移动端 +| 名称 | 样式 | 用途 | +|------|------|------| +| 无阴影 | `none` | 默认扁平 | +| 轻阴影 | `0 2px 8px rgba(0, 0, 0, 0.08)` | 卡片悬浮 | + +--- + +## 页面布局 + +### PC端 Layout +``` +┌─────────────────────────────────────────┐ +│ Sidebar (200px) │ Header (64px) │ +│ - Logo ├────────────────────┤ +│ - Navigation │ │ +│ │ Content Area │ +│ │ - Page Header │ +│ │ - Filter Bar │ +│ │ - Table/Card │ +│ │ │ +└─────────────────────┴────────────────────┘ +``` + +### 移动端 Layout +``` +┌─────────────────────┐ +│ Header (44px) │ +├─────────────────────┤ +│ │ +│ Content Area │ +│ - Full Width │ +│ - Pull to Refresh │ +│ │ +├─────────────────────┤ +│ Tab Bar (可选) │ +└─────────────────────┘ +``` + +--- + +## PC端组件规范 + +### 页面结构 +```html +
+ + +
+ +
+ +
+ +
+
+``` + +### 页面标题区 +- `.page-header`: flex, space-between, align-items: center, margin-bottom: 24px +- `.page-title`: font-size: 20px, font-weight: 500, color: #262626 +- `.page-header-actions`: flex, gap: 12px + +### 筛选栏 +- `.filter-bar`: padding: 16px, background: #fafafa, border-radius: 8px +- 使用 `` 组件,wrap: true + +### 卡片 +- `.card`: padding: 24px, background: #fff, border: 1px solid #e8e8e8, border-radius: 8px +- `.card-title`: font-size: 16px, font-weight: 500, color: #262626, margin-bottom: 20px + +### 表格卡片 +- `.table-card`: padding: 24px, background: #fff, border: 1px solid #e8e8e8, border-radius: 8px + +### 统计卡片 +- `.stats-row`: display: grid, grid-template-columns: repeat(4, 1fr), gap: 24px +- `.stat-card`: padding: 24px, background: #fff, border: 1px solid #e8e8e8, border-radius: 8px + +### 抽屉 +- 宽度:默认 480px,宽版 640px +- 放置:右侧 +- 头部:56px 高度,底部边框 +- 底部:56px 高度,顶部边框,按钮右对齐 + +### 按钮 +- Primary: background: #1890FF, color: #fff, border-radius: 4px +- Default: background: #fff, border: 1px solid #d9d9d9 +- Text: background: transparent, color: #595959 +- Danger: color: #FF4D4F +- 高度:32px(默认)、40px(大按钮)、24px(小按钮) +- 图标按钮:使用 `