This commit is contained in:
2026-10-25 23:20:48 +08:00
parent 4e9f3dcb13
commit c178ea5160
5 changed files with 3492 additions and 37 deletions
+30 -29
View File
@@ -1,10 +1,10 @@
import { dashboardSummary, menuRoutes, USER_STATUS, users } from './data' import { dashboardSummary, menuRoutes, USER_STATUS, users, type MockUser } from './data'
export interface MockContext { export interface MockContext {
url: string url: string
params: string[] params: string[]
query: Record<string, string> query: Record<string, string>
body: Record<string, any> body: Record<string, unknown>
} }
export interface MockRule { export interface MockRule {
@@ -18,22 +18,19 @@ const toNumber = (value: unknown, fallback = 0) => {
return Number.isFinite(n) ? n : fallback return Number.isFinite(n) ? n : fallback
} }
const pickString = (value: unknown, fallback = '') => (typeof value === 'string' ? value : fallback)
export const mockRules: MockRule[] = [ export const mockRules: MockRule[] = [
{ {
method: 'POST', method: 'POST',
pattern: /^\/api\/v1\/auth\/login$/, pattern: /^\/api\/v1\/auth\/login$/,
handler: (ctx) => { handler: (ctx) => ({
const { username, password } = ctx.body accessToken: 'mock-access-token',
if (!username || !password) { refreshToken: 'mock-refresh-token',
return { code: 'A0120', msg: '用户名和密码不能为空' } tokenType: 'Bearer',
} expiresIn: 7200,
return { username: pickString(ctx.body.username, 'admin'),
accessToken: 'mock-access-token', }),
refreshToken: 'mock-refresh-token',
tokenType: 'Bearer',
expiresIn: 7200,
}
},
}, },
{ {
method: 'POST', method: 'POST',
@@ -61,17 +58,18 @@ export const mockRules: MockRule[] = [
method: 'GET', method: 'GET',
pattern: /^\/api\/v1\/users\/page$/, pattern: /^\/api\/v1\/users\/page$/,
handler: (ctx) => { handler: (ctx) => {
const { username, status, pageNum = '1', pageSize = '10' } = ctx.query const { username, status } = ctx.query
const pageNum = toNumber(ctx.query.pageNum, 1)
const pageSize = toNumber(ctx.query.pageSize, 10)
const filtered = users.filter((item) => { const filtered = users.filter((item) => {
const matchName = !username || item.username.includes(username) const matchName = !username || item.username.includes(username)
const matchStatus = !status || String(item.status) === status const matchStatus = !status || String(item.status) === status
return matchName && matchStatus return matchName && matchStatus
}) })
const start = (toNumber(pageNum, 1) - 1) * toNumber(pageSize, 10)
return { const start = (pageNum - 1) * pageSize
list: filtered.slice(start, start + toNumber(pageSize, 10)), return { list: filtered.slice(start, start + pageSize), total: filtered.length }
total: filtered.length,
}
}, },
}, },
{ {
@@ -84,17 +82,20 @@ export const mockRules: MockRule[] = [
pattern: /^\/api\/v1\/users$/, pattern: /^\/api\/v1\/users$/,
handler: (ctx) => { handler: (ctx) => {
const id = users.length + 1 const id = users.length + 1
users.unshift({ const created: MockUser = {
id, id,
username: ctx.body.username ?? `user${id}`, username: pickString(ctx.body.username, `user${id}`),
nickname: ctx.body.nickname ?? '', nickname: pickString(ctx.body.nickname),
mobile: ctx.body.mobile ?? '', mobile: pickString(ctx.body.mobile),
email: ctx.body.email ?? '', email: pickString(ctx.body.email),
status: ctx.body.status ?? USER_STATUS.ENABLED, status: toNumber(ctx.body.status, USER_STATUS.ENABLED) === 0 ? 0 : 1,
deptName: ctx.body.deptName ?? '技术部', deptName: pickString(ctx.body.deptName, '技术部'),
roleNames: ctx.body.roleNames ?? ['普通用户'], roleNames: Array.isArray(ctx.body.roleNames)
? (ctx.body.roleNames as string[])
: ['普通用户'],
createTime: new Date().toISOString(), createTime: new Date().toISOString(),
}) }
users.unshift(created)
return id return id
}, },
}, },
+3 -1
View File
@@ -44,7 +44,9 @@ export function mockPlugin(enabled = true): Plugin {
} }
res.setHeader('Content-Type', 'application/json;charset=utf-8') res.setHeader('Content-Type', 'application/json;charset=utf-8')
res.end(JSON.stringify({ code: '00000', data: rule.handler(ctx) ?? null, msg: 'success' })) res.end(
JSON.stringify({ code: '00000', data: rule.handler(ctx) ?? null, msg: 'success' }),
)
})() })()
}) })
}, },
+1 -1
View File
@@ -4,6 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"description": "Portal 后台管理系统前端", "description": "Portal 后台管理系统前端",
"packageManager": "pnpm@9.15.9",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build:prod": "vue-tsc --noEmit && vite build", "build:prod": "vue-tsc --noEmit && vite build",
@@ -31,7 +32,6 @@
"@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0", "@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-vue": "^5.1.4", "@vitejs/plugin-vue": "^5.1.4",
"autoprefixer": "^10.4.20",
"eslint": "^8.57.1", "eslint": "^8.57.1",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
+3457
View File
File diff suppressed because it is too large Load Diff
+1 -6
View File
@@ -22,12 +22,7 @@
}, },
"types": ["vite/client", "node"] "types": ["vite/client", "node"]
}, },
"include": [ "include": ["env.d.ts", "src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"],
"env.d.ts",
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.vue"
],
"exclude": ["node_modules", "dist"], "exclude": ["node_modules", "dist"],
"references": [{ "path": "./tsconfig.node.json" }] "references": [{ "path": "./tsconfig.node.json" }]
} }