file
This commit is contained in:
@@ -59,6 +59,59 @@ export const miniApps: MockMiniApp[] = Array.from({ length: 12 }, (_, index) =>
|
||||
}
|
||||
})
|
||||
|
||||
export interface MockFile {
|
||||
id: number
|
||||
storage_key: string
|
||||
filename: string
|
||||
origin_name: string
|
||||
mime_type: string
|
||||
ext: string
|
||||
size: number
|
||||
uploader_type: 'admin' | 'ma'
|
||||
uploader_id: number
|
||||
url: string
|
||||
created_at: string
|
||||
}
|
||||
|
||||
const MIME_BY_EXT: Record<string, string> = {
|
||||
png: 'image/png',
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
gif: 'image/gif',
|
||||
pdf: 'application/pdf',
|
||||
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
txt: 'text/plain',
|
||||
}
|
||||
|
||||
const MOCK_FILE_SAMPLES = [
|
||||
{ name: '产品截图.png', ext: 'png', size: 245_000 },
|
||||
{ name: '用户头像.jpg', ext: 'jpg', size: 88_400 },
|
||||
{ name: '操作手册.pdf', ext: 'pdf', size: 1_280_000 },
|
||||
{ name: '数据报表.xlsx', ext: 'xlsx', size: 56_200 },
|
||||
{ name: '说明文档.docx', ext: 'docx', size: 33_100 },
|
||||
{ name: '日志备份.txt', ext: 'txt', size: 12_800 },
|
||||
]
|
||||
|
||||
export const files: MockFile[] = Array.from({ length: 18 }, (_, index) => {
|
||||
const id = index + 1
|
||||
const sample = MOCK_FILE_SAMPLES[index % MOCK_FILE_SAMPLES.length]
|
||||
const rand = Math.random().toString(36).slice(2, 10)
|
||||
return {
|
||||
id,
|
||||
storage_key: `2026/10/27/${rand}.${sample.ext}`,
|
||||
filename: `${rand}.${sample.ext}`,
|
||||
origin_name: sample.name,
|
||||
mime_type: MIME_BY_EXT[sample.ext] ?? 'application/octet-stream',
|
||||
ext: sample.ext,
|
||||
size: sample.size + (id % 7) * 1024,
|
||||
uploader_type: id % 3 === 0 ? 'ma' : 'admin',
|
||||
uploader_id: (id % 3) + 1,
|
||||
url: `/files/static/2026/10/27/${rand}.${sample.ext}`,
|
||||
created_at: new Date(Date.now() - id * 3_600_000).toISOString().slice(0, 19).replace('T', ' '),
|
||||
}
|
||||
})
|
||||
|
||||
export const menuRoutes = [
|
||||
{
|
||||
path: '/system',
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import {
|
||||
files,
|
||||
menuRoutes,
|
||||
miniApps,
|
||||
type MockFile,
|
||||
users,
|
||||
USER_STATUS,
|
||||
type MockMiniApp,
|
||||
@@ -197,6 +199,66 @@ export const mockRules: MockRule[] = [
|
||||
return true
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
pattern: /^\/api\/v1\/api\/admin\/files$/,
|
||||
handler: (ctx) => {
|
||||
const { keyword, uploader_type, page, size } = ctx.query
|
||||
const pageNum = toNumber(page, 1)
|
||||
const pageSize = toNumber(size, 20)
|
||||
const kw = (keyword as string) || ''
|
||||
const type = (uploader_type as string) || ''
|
||||
|
||||
const filtered = files.filter((item) => {
|
||||
if (type && item.uploader_type !== type) return false
|
||||
if (kw && !item.origin_name.includes(kw) && !item.filename.includes(kw)) return false
|
||||
return true
|
||||
})
|
||||
|
||||
const start = (pageNum - 1) * pageSize
|
||||
return { list: filtered.slice(start, start + pageSize), total: filtered.length }
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
pattern: /^\/api\/v1\/api\/admin\/files\/upload$/,
|
||||
handler: () => {
|
||||
const id = files.length + 1
|
||||
const rand = Math.random().toString(36).slice(2, 10)
|
||||
const created: MockFile = {
|
||||
id,
|
||||
storage_key: `2026/10/27/${rand}.png`,
|
||||
filename: `${rand}.png`,
|
||||
origin_name: 'mock-upload.png',
|
||||
mime_type: 'image/png',
|
||||
ext: 'png',
|
||||
size: 1024,
|
||||
uploader_type: 'admin',
|
||||
uploader_id: 1,
|
||||
url: `/files/static/2026/10/27/${rand}.png`,
|
||||
created_at: new Date().toISOString().slice(0, 19).replace('T', ' '),
|
||||
}
|
||||
files.unshift(created)
|
||||
return {
|
||||
id,
|
||||
url: created.url,
|
||||
filename: created.filename,
|
||||
origin_name: created.origin_name,
|
||||
mime_type: created.mime_type,
|
||||
size: created.size,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'DELETE',
|
||||
pattern: /^\/api\/v1\/api\/admin\/files\/(\d+)$/,
|
||||
handler: (ctx) => {
|
||||
const id = toNumber(ctx.params[0])
|
||||
const index = files.findIndex((item) => item.id === id)
|
||||
if (index > -1) files.splice(index, 1)
|
||||
return { id }
|
||||
},
|
||||
},
|
||||
{
|
||||
// 统计每个小程序的用户数(有真实用户的取真实值,其余返回稳定模拟值)
|
||||
method: 'GET',
|
||||
|
||||
+2
-1
@@ -27,6 +27,7 @@ export function mockPlugin(globalMock = false): Plugin {
|
||||
const requestUrl = new URL(req.url, 'http://localhost')
|
||||
void (async () => {
|
||||
const raw = req.method === 'GET' ? '' : await readBody(req)
|
||||
const isJsonBody = (req.headers['content-type'] ?? '').includes('application/json')
|
||||
const rule = mockRules.find(
|
||||
(item) =>
|
||||
item.method === (req.method ?? 'GET').toUpperCase() &&
|
||||
@@ -41,7 +42,7 @@ export function mockPlugin(globalMock = false): Plugin {
|
||||
url: requestUrl.pathname,
|
||||
params: matched ? matched.slice(1) : [],
|
||||
query: Object.fromEntries(requestUrl.searchParams.entries()),
|
||||
body: raw ? JSON.parse(raw) : {},
|
||||
body: raw && isJsonBody ? JSON.parse(raw) : {},
|
||||
}
|
||||
|
||||
res.setHeader('Content-Type', 'application/json;charset=utf-8')
|
||||
|
||||
Reference in New Issue
Block a user