34 changed files with 6 additions and 1770 deletions
@ -1,19 +0,0 @@ |
|||||||
/** |
|
||||||
* Mock plugin for development and production. |
|
||||||
* https://github.com/anncwb/vite-plugin-mock
|
|
||||||
*/ |
|
||||||
import { viteMockServe } from 'vite-plugin-mock' |
|
||||||
|
|
||||||
export function configMockPlugin(isBuild: boolean) { |
|
||||||
return viteMockServe({ |
|
||||||
ignore: /^\_/, |
|
||||||
mockPath: 'mock', |
|
||||||
localEnabled: !isBuild, |
|
||||||
prodEnabled: isBuild, |
|
||||||
injectCode: ` |
|
||||||
import { setupProdMockServer } from '../mock/_createProductionServer'; |
|
||||||
|
|
||||||
setupProdMockServer(); |
|
||||||
` |
|
||||||
}) |
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer' |
|
||||||
|
|
||||||
// 问题描述
|
|
||||||
// 1. `import.meta.globEager` 已被弃用, 需要升级vite版本,有兼容问题
|
|
||||||
// 2. `vite-plugin-mock` 插件问题 https://github.com/vbenjs/vite-plugin-mock/issues/56
|
|
||||||
|
|
||||||
// const modules: Record<string, any> = import.meta.glob("./**/*.ts", {
|
|
||||||
// import: "default",
|
|
||||||
// eager: true,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const mockModules = Object.keys(modules).reduce((pre, key) => {
|
|
||||||
// if (!key.includes("/_")) {
|
|
||||||
// pre.push(...(modules as Recordable)[key]);
|
|
||||||
// }
|
|
||||||
// return pre;
|
|
||||||
// }, [] as any[]);
|
|
||||||
|
|
||||||
const modules = import.meta.globEager('./**/*.ts') |
|
||||||
|
|
||||||
const mockModules: any[] = [] |
|
||||||
Object.keys(modules).forEach((key) => { |
|
||||||
if (key.includes('/_')) { |
|
||||||
return |
|
||||||
} |
|
||||||
mockModules.push(...(modules as Recordable)[key].default) |
|
||||||
}) |
|
||||||
|
|
||||||
/** |
|
||||||
* Used in a production environment. Need to manually import all modules
|
|
||||||
*/ |
|
||||||
export function setupProdMockServer() { |
|
||||||
createProdMockServer(mockModules) |
|
||||||
} |
|
@ -1,52 +0,0 @@ |
|||||||
// Interface data format used to return a unified format
|
|
||||||
import { ResultEnum } from '@/enums/httpEnum' |
|
||||||
|
|
||||||
export function resultSuccess<T = Recordable>(result: T, { message = 'ok' } = {}) { |
|
||||||
return { |
|
||||||
code: ResultEnum.SUCCESS, |
|
||||||
result, |
|
||||||
message, |
|
||||||
type: 'success' |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export function resultPageSuccess<T = any>(page: number, pageSize: number, list: T[], { message = 'ok' } = {}) { |
|
||||||
const pageData = pagination(page, pageSize, list) |
|
||||||
|
|
||||||
return { |
|
||||||
...resultSuccess({ |
|
||||||
items: pageData, |
|
||||||
total: list.length |
|
||||||
}), |
|
||||||
message |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export function resultError(message = 'Request failed', { code = ResultEnum.ERROR, result = null } = {}) { |
|
||||||
return { |
|
||||||
code, |
|
||||||
result, |
|
||||||
message, |
|
||||||
type: 'error' |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] { |
|
||||||
const offset = (pageNo - 1) * Number(pageSize) |
|
||||||
return offset + Number(pageSize) >= array.length ? array.slice(offset, array.length) : array.slice(offset, offset + Number(pageSize)) |
|
||||||
} |
|
||||||
|
|
||||||
export interface requestParams { |
|
||||||
method: string |
|
||||||
body: any |
|
||||||
headers?: { authorization?: string } |
|
||||||
query: any |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @description 本函数用于从request数据中获取token,请根据项目的实际情况修改 |
|
||||||
* |
|
||||||
*/ |
|
||||||
export function getRequestToken({ headers }: requestParams): string | undefined { |
|
||||||
return headers?.authorization |
|
||||||
} |
|
@ -1,71 +0,0 @@ |
|||||||
import { MockMethod } from 'vite-plugin-mock' |
|
||||||
import { resultSuccess, resultError } from '../_util' |
|
||||||
import { ResultEnum } from '../../src/enums/httpEnum' |
|
||||||
|
|
||||||
const userInfo = { |
|
||||||
name: 'Vben', |
|
||||||
userid: '00000001', |
|
||||||
email: 'test@gmail.com', |
|
||||||
signature: '海纳百川,有容乃大', |
|
||||||
introduction: '微笑着,努力着,欣赏着', |
|
||||||
title: '交互专家', |
|
||||||
group: '某某某事业群-某某平台部-某某技术部-UED', |
|
||||||
tags: [ |
|
||||||
{ |
|
||||||
key: '0', |
|
||||||
label: '很有想法的' |
|
||||||
}, |
|
||||||
{ |
|
||||||
key: '1', |
|
||||||
label: '专注设计' |
|
||||||
}, |
|
||||||
{ |
|
||||||
key: '2', |
|
||||||
label: '辣~' |
|
||||||
}, |
|
||||||
{ |
|
||||||
key: '3', |
|
||||||
label: '大长腿' |
|
||||||
}, |
|
||||||
{ |
|
||||||
key: '4', |
|
||||||
label: '川妹子' |
|
||||||
}, |
|
||||||
{ |
|
||||||
key: '5', |
|
||||||
label: '海纳百川' |
|
||||||
} |
|
||||||
], |
|
||||||
notifyCount: 12, |
|
||||||
unreadCount: 11, |
|
||||||
country: 'China', |
|
||||||
address: 'Xiamen City 77', |
|
||||||
phone: '0592-268888888' |
|
||||||
} |
|
||||||
|
|
||||||
export default [ |
|
||||||
{ |
|
||||||
url: '/basic-api/account/getAccountInfo', |
|
||||||
timeout: 1000, |
|
||||||
method: 'get', |
|
||||||
response: () => { |
|
||||||
return resultSuccess(userInfo) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/user/sessionTimeout', |
|
||||||
method: 'post', |
|
||||||
statusCode: 401, |
|
||||||
response: () => { |
|
||||||
return resultError() |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/user/tokenExpired', |
|
||||||
method: 'post', |
|
||||||
statusCode: 200, |
|
||||||
response: () => { |
|
||||||
return resultError('Token Expired!', { code: ResultEnum.TIMEOUT as number }) |
|
||||||
} |
|
||||||
} |
|
||||||
] as MockMethod[] |
|
@ -1,325 +0,0 @@ |
|||||||
import { MockMethod } from 'vite-plugin-mock' |
|
||||||
import { resultSuccess } from '../_util' |
|
||||||
|
|
||||||
const areaList: any[] = [ |
|
||||||
{ |
|
||||||
id: '530825900854620160', |
|
||||||
code: '430000', |
|
||||||
parentCode: '100000', |
|
||||||
levelType: 1, |
|
||||||
name: '湖南省', |
|
||||||
province: '湖南省', |
|
||||||
city: null, |
|
||||||
district: null, |
|
||||||
town: null, |
|
||||||
village: null, |
|
||||||
parentPath: '430000', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 16:33:42', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530825900883980288', |
|
||||||
code: '430100', |
|
||||||
parentCode: '430000', |
|
||||||
levelType: 2, |
|
||||||
name: '长沙市', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: null, |
|
||||||
town: null, |
|
||||||
village: null, |
|
||||||
parentPath: '430000,430100', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 16:33:42', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530825900951089152', |
|
||||||
code: '430102', |
|
||||||
parentCode: '430100', |
|
||||||
levelType: 3, |
|
||||||
name: '芙蓉区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '芙蓉区', |
|
||||||
town: null, |
|
||||||
village: null, |
|
||||||
parentPath: '430000,430100,430102', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 16:33:42', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530825901014003712', |
|
||||||
code: '430104', |
|
||||||
parentCode: '430100', |
|
||||||
levelType: 3, |
|
||||||
name: '岳麓区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '岳麓区', |
|
||||||
town: null, |
|
||||||
village: null, |
|
||||||
parentPath: '430000,430100,430104', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 16:33:42', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530825900988837888', |
|
||||||
code: '430103', |
|
||||||
parentCode: '430100', |
|
||||||
levelType: 3, |
|
||||||
name: '天心区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: null, |
|
||||||
village: null, |
|
||||||
parentPath: '430000,430100,430103', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 16:33:42', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530826672489115648', |
|
||||||
code: '430103002', |
|
||||||
parentCode: '430103', |
|
||||||
levelType: 4, |
|
||||||
name: '坡子街街道', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: null, |
|
||||||
parentPath: '430000,430100,430103,430103002', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-12-14 15:26:43', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241171607552', |
|
||||||
code: '430103002001', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '八角亭社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '八角亭社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002001', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2021-01-20 14:07:23', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241200967680', |
|
||||||
code: '430103002002', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '西牌楼社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '西牌楼社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002002', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241230327808', |
|
||||||
code: '430103002003', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '太平街社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '太平街社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002003', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241259687936', |
|
||||||
code: '430103002005', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '坡子街社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '坡子街社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002005', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241284853760', |
|
||||||
code: '430103002006', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '青山祠社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '青山祠社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002006', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241310019584', |
|
||||||
code: '430103002007', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '沙河社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '沙河社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002007', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241381322752', |
|
||||||
code: '430103002008', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '碧湘社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '碧湘社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002008', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241410682880', |
|
||||||
code: '430103002009', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '创远社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '创远社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002009', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241431654400', |
|
||||||
code: '430103002010', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '楚湘社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '楚湘社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002010', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241465208832', |
|
||||||
code: '430103002011', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '西湖社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '西湖社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002011', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241502957568', |
|
||||||
code: '430103002012', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '登仁桥社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '登仁桥社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002012', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: '530840241553289216', |
|
||||||
code: '430103002013', |
|
||||||
parentCode: '430103002', |
|
||||||
levelType: 5, |
|
||||||
name: '文庙坪社区', |
|
||||||
province: '湖南省', |
|
||||||
city: '长沙市', |
|
||||||
district: '天心区', |
|
||||||
town: '坡子街街道', |
|
||||||
village: '文庙坪社区', |
|
||||||
parentPath: '430000,430100,430103,430103002,430103002013', |
|
||||||
createTime: '2020-11-30 15:47:31', |
|
||||||
updateTime: '2020-11-30 17:30:41', |
|
||||||
customized: false, |
|
||||||
usable: true |
|
||||||
} |
|
||||||
] |
|
||||||
export default [ |
|
||||||
{ |
|
||||||
url: '/basic-api/cascader/getAreaRecord', |
|
||||||
timeout: 1000, |
|
||||||
method: 'post', |
|
||||||
response: ({ body }) => { |
|
||||||
const { parentCode } = body || {} |
|
||||||
if (!parentCode) { |
|
||||||
return resultSuccess(areaList.filter((it) => it.code === '430000')) |
|
||||||
} |
|
||||||
return resultSuccess(areaList.filter((it) => it.parentCode === parentCode)) |
|
||||||
} |
|
||||||
} |
|
||||||
] as MockMethod[] |
|
@ -1,28 +0,0 @@ |
|||||||
import { MockMethod } from 'vite-plugin-mock' |
|
||||||
import { resultSuccess } from '../_util' |
|
||||||
|
|
||||||
const demoList = (keyword, count = 20) => { |
|
||||||
const result = { |
|
||||||
list: [] as any[] |
|
||||||
} |
|
||||||
for (let index = 0; index < count; index++) { |
|
||||||
result.list.push({ |
|
||||||
name: `${keyword ?? ''}选项${index}`, |
|
||||||
id: `${index}` |
|
||||||
}) |
|
||||||
} |
|
||||||
return result |
|
||||||
} |
|
||||||
|
|
||||||
export default [ |
|
||||||
{ |
|
||||||
url: '/basic-api/select/getDemoOptions', |
|
||||||
timeout: 1000, |
|
||||||
method: 'get', |
|
||||||
response: ({ query }) => { |
|
||||||
const { keyword, count } = query |
|
||||||
console.log(keyword) |
|
||||||
return resultSuccess(demoList(keyword, count)) |
|
||||||
} |
|
||||||
} |
|
||||||
] as MockMethod[] |
|
@ -1,194 +0,0 @@ |
|||||||
import { MockMethod } from 'vite-plugin-mock' |
|
||||||
import { resultError, resultPageSuccess, resultSuccess } from '../_util' |
|
||||||
|
|
||||||
const accountList = (() => { |
|
||||||
const result: any[] = [] |
|
||||||
for (let index = 0; index < 20; index++) { |
|
||||||
result.push({ |
|
||||||
id: `${index}`, |
|
||||||
account: '@first', |
|
||||||
email: '@email', |
|
||||||
nickname: '@cname()', |
|
||||||
role: '@first', |
|
||||||
createTime: '@datetime', |
|
||||||
remark: '@cword(10,20)', |
|
||||||
'status|1': ['0', '1'] |
|
||||||
}) |
|
||||||
} |
|
||||||
return result |
|
||||||
})() |
|
||||||
|
|
||||||
const roleList = (() => { |
|
||||||
const result: any[] = [] |
|
||||||
for (let index = 0; index < 4; index++) { |
|
||||||
result.push({ |
|
||||||
id: index + 1, |
|
||||||
orderNo: `${index + 1}`, |
|
||||||
roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index], |
|
||||||
roleValue: '@first', |
|
||||||
createTime: '@datetime', |
|
||||||
remark: '@cword(10,20)', |
|
||||||
menu: [['0', '1', '2'], ['0', '1'], ['0', '2'], ['2']][index], |
|
||||||
'status|1': ['0', '1'] |
|
||||||
}) |
|
||||||
} |
|
||||||
return result |
|
||||||
})() |
|
||||||
|
|
||||||
const deptList = (() => { |
|
||||||
const result: any[] = [] |
|
||||||
for (let index = 0; index < 3; index++) { |
|
||||||
result.push({ |
|
||||||
id: `${index}`, |
|
||||||
deptName: ['华东分部', '华南分部', '西北分部'][index], |
|
||||||
orderNo: index + 1, |
|
||||||
createTime: '@datetime', |
|
||||||
remark: '@cword(10,20)', |
|
||||||
'status|1': ['0', '0', '1'], |
|
||||||
children: (() => { |
|
||||||
const children: any[] = [] |
|
||||||
for (let j = 0; j < 4; j++) { |
|
||||||
children.push({ |
|
||||||
id: `${index}-${j}`, |
|
||||||
deptName: ['研发部', '市场部', '商务部', '财务部'][j], |
|
||||||
orderNo: j + 1, |
|
||||||
createTime: '@datetime', |
|
||||||
remark: '@cword(10,20)', |
|
||||||
'status|1': ['0', '1'], |
|
||||||
parentDept: `${index}`, |
|
||||||
children: undefined |
|
||||||
}) |
|
||||||
} |
|
||||||
return children |
|
||||||
})() |
|
||||||
}) |
|
||||||
} |
|
||||||
return result |
|
||||||
})() |
|
||||||
|
|
||||||
const menuList = (() => { |
|
||||||
const result: any[] = [] |
|
||||||
for (let index = 0; index < 3; index++) { |
|
||||||
result.push({ |
|
||||||
id: `${index}`, |
|
||||||
icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index], |
|
||||||
component: 'LAYOUT', |
|
||||||
type: '0', |
|
||||||
menuName: ['Dashboard', '权限管理', '功能'][index], |
|
||||||
permission: '', |
|
||||||
orderNo: index + 1, |
|
||||||
createTime: '@datetime', |
|
||||||
'status|1': ['0', '0', '1'], |
|
||||||
children: (() => { |
|
||||||
const children: any[] = [] |
|
||||||
for (let j = 0; j < 4; j++) { |
|
||||||
children.push({ |
|
||||||
id: `${index}-${j}`, |
|
||||||
type: '1', |
|
||||||
menuName: ['菜单1', '菜单2', '菜单3', '菜单4'][j], |
|
||||||
icon: 'ion:document', |
|
||||||
permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index], |
|
||||||
component: ['/dashboard/welcome/index', '/dashboard/analysis/index', '/dashboard/workbench/index', '/dashboard/test/index'][j], |
|
||||||
orderNo: j + 1, |
|
||||||
createTime: '@datetime', |
|
||||||
'status|1': ['0', '1'], |
|
||||||
parentMenu: `${index}`, |
|
||||||
children: (() => { |
|
||||||
const children: any[] = [] |
|
||||||
for (let k = 0; k < 4; k++) { |
|
||||||
children.push({ |
|
||||||
id: `${index}-${j}-${k}`, |
|
||||||
type: '2', |
|
||||||
menuName: '按钮' + (j + 1) + '-' + (k + 1), |
|
||||||
icon: '', |
|
||||||
permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index] + ':btn' + (k + 1), |
|
||||||
component: [ |
|
||||||
'/dashboard/welcome/index', |
|
||||||
'/dashboard/analysis/index', |
|
||||||
'/dashboard/workbench/index', |
|
||||||
'/dashboard/test/index' |
|
||||||
][j], |
|
||||||
orderNo: j + 1, |
|
||||||
createTime: '@datetime', |
|
||||||
'status|1': ['0', '1'], |
|
||||||
parentMenu: `${index}-${j}`, |
|
||||||
children: undefined |
|
||||||
}) |
|
||||||
} |
|
||||||
return children |
|
||||||
})() |
|
||||||
}) |
|
||||||
} |
|
||||||
return children |
|
||||||
})() |
|
||||||
}) |
|
||||||
} |
|
||||||
return result |
|
||||||
})() |
|
||||||
|
|
||||||
export default [ |
|
||||||
{ |
|
||||||
url: '/basic-api/system/getAccountList', |
|
||||||
timeout: 100, |
|
||||||
method: 'get', |
|
||||||
response: ({ query }) => { |
|
||||||
const { page = 1, pageSize = 20 } = query |
|
||||||
return resultPageSuccess(page, pageSize, accountList) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/system/getRoleListByPage', |
|
||||||
timeout: 100, |
|
||||||
method: 'get', |
|
||||||
response: ({ query }) => { |
|
||||||
const { page = 1, pageSize = 20 } = query |
|
||||||
return resultPageSuccess(page, pageSize, roleList) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/system/setRoleStatus', |
|
||||||
timeout: 500, |
|
||||||
method: 'post', |
|
||||||
response: ({ query }) => { |
|
||||||
const { id, status } = query |
|
||||||
return resultSuccess({ id, status }) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/system/getAllRoleList', |
|
||||||
timeout: 100, |
|
||||||
method: 'get', |
|
||||||
response: () => { |
|
||||||
return resultSuccess(roleList) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/system/getDeptList', |
|
||||||
timeout: 100, |
|
||||||
method: 'get', |
|
||||||
response: () => { |
|
||||||
return resultSuccess(deptList) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/system/getMenuList', |
|
||||||
timeout: 100, |
|
||||||
method: 'get', |
|
||||||
response: () => { |
|
||||||
return resultSuccess(menuList) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/system/accountExist', |
|
||||||
timeout: 500, |
|
||||||
method: 'post', |
|
||||||
response: ({ body }) => { |
|
||||||
const { account } = body || {} |
|
||||||
if (account && account.indexOf('admin') !== -1) { |
|
||||||
return resultError('该字段不能包含admin') |
|
||||||
} else { |
|
||||||
return resultSuccess(`${account} can use`) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
] as MockMethod[] |
|
@ -1,55 +0,0 @@ |
|||||||
import { MockMethod } from 'vite-plugin-mock' |
|
||||||
import { Random } from 'mockjs' |
|
||||||
import { resultPageSuccess } from '../_util' |
|
||||||
|
|
||||||
function getRandomPics(count = 10): string[] { |
|
||||||
const arr: string[] = [] |
|
||||||
for (let i = 0; i < count; i++) { |
|
||||||
arr.push(Random.image('800x600', Random.color(), Random.color(), Random.title())) |
|
||||||
} |
|
||||||
return arr |
|
||||||
} |
|
||||||
|
|
||||||
const demoList = (() => { |
|
||||||
const result: any[] = [] |
|
||||||
for (let index = 0; index < 200; index++) { |
|
||||||
result.push({ |
|
||||||
id: `${index}`, |
|
||||||
beginTime: '@datetime', |
|
||||||
endTime: '@datetime', |
|
||||||
address: '@city()', |
|
||||||
name: '@cname()', |
|
||||||
name1: '@cname()', |
|
||||||
name2: '@cname()', |
|
||||||
name3: '@cname()', |
|
||||||
name4: '@cname()', |
|
||||||
name5: '@cname()', |
|
||||||
name6: '@cname()', |
|
||||||
name7: '@cname()', |
|
||||||
name8: '@cname()', |
|
||||||
radio1: `选项${index + 1}`, |
|
||||||
radio2: `选项${index + 1}`, |
|
||||||
radio3: `选项${index + 1}`, |
|
||||||
avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()), |
|
||||||
imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1), |
|
||||||
imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1), |
|
||||||
date: `@date('yyyy-MM-dd')`, |
|
||||||
time: `@time('HH:mm')`, |
|
||||||
'no|100000-10000000': 100000, |
|
||||||
'status|1': ['normal', 'enable', 'disable'] |
|
||||||
}) |
|
||||||
} |
|
||||||
return result |
|
||||||
})() |
|
||||||
|
|
||||||
export default [ |
|
||||||
{ |
|
||||||
url: '/basic-api/table/getDemoList', |
|
||||||
timeout: 100, |
|
||||||
method: 'get', |
|
||||||
response: ({ query }) => { |
|
||||||
const { page = 1, pageSize = 20 } = query |
|
||||||
return resultPageSuccess(page, pageSize, demoList) |
|
||||||
} |
|
||||||
} |
|
||||||
] as MockMethod[] |
|
@ -1,38 +0,0 @@ |
|||||||
import { MockMethod } from 'vite-plugin-mock' |
|
||||||
import { resultSuccess } from '../_util' |
|
||||||
|
|
||||||
const demoTreeList = (keyword) => { |
|
||||||
const result = { |
|
||||||
list: [] as Recordable[] |
|
||||||
} |
|
||||||
for (let index = 0; index < 5; index++) { |
|
||||||
const children: Recordable[] = [] |
|
||||||
for (let j = 0; j < 3; j++) { |
|
||||||
children.push({ |
|
||||||
title: `${keyword ?? ''}选项${index}-${j}`, |
|
||||||
value: `${index}-${j}`, |
|
||||||
key: `${index}-${j}` |
|
||||||
}) |
|
||||||
} |
|
||||||
result.list.push({ |
|
||||||
title: `${keyword ?? ''}选项${index}`, |
|
||||||
value: `${index}`, |
|
||||||
key: `${index}`, |
|
||||||
children |
|
||||||
}) |
|
||||||
} |
|
||||||
return result |
|
||||||
} |
|
||||||
|
|
||||||
export default [ |
|
||||||
{ |
|
||||||
url: '/basic-api/tree/getDemoOptions', |
|
||||||
timeout: 1000, |
|
||||||
method: 'get', |
|
||||||
response: ({ query }) => { |
|
||||||
const { keyword } = query |
|
||||||
console.log(keyword) |
|
||||||
return resultSuccess(demoTreeList(keyword)) |
|
||||||
} |
|
||||||
} |
|
||||||
] as MockMethod[] |
|
@ -1,270 +0,0 @@ |
|||||||
import { resultSuccess, resultError, getRequestToken, requestParams } from '../_util' |
|
||||||
import { MockMethod } from 'vite-plugin-mock' |
|
||||||
import { createFakeUserList } from './user' |
|
||||||
|
|
||||||
// single
|
|
||||||
const dashboardRoute = { |
|
||||||
path: '/dashboard', |
|
||||||
name: 'Dashboard', |
|
||||||
component: 'LAYOUT', |
|
||||||
redirect: '/dashboard/analysis', |
|
||||||
meta: { |
|
||||||
title: 'routes.dashboard.dashboard', |
|
||||||
hideChildrenInMenu: true, |
|
||||||
icon: 'bx:bx-home' |
|
||||||
}, |
|
||||||
children: [ |
|
||||||
{ |
|
||||||
path: 'analysis', |
|
||||||
name: 'Analysis', |
|
||||||
component: '/dashboard/analysis/index', |
|
||||||
meta: { |
|
||||||
hideMenu: true, |
|
||||||
hideBreadcrumb: true, |
|
||||||
title: 'routes.dashboard.analysis', |
|
||||||
currentActiveMenu: '/dashboard', |
|
||||||
icon: 'bx:bx-home' |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'workbench', |
|
||||||
name: 'Workbench', |
|
||||||
component: '/dashboard/workbench/index', |
|
||||||
meta: { |
|
||||||
hideMenu: true, |
|
||||||
hideBreadcrumb: true, |
|
||||||
title: 'routes.dashboard.workbench', |
|
||||||
currentActiveMenu: '/dashboard', |
|
||||||
icon: 'bx:bx-home' |
|
||||||
} |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
|
|
||||||
const backRoute = { |
|
||||||
path: 'back', |
|
||||||
name: 'PermissionBackDemo', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.permission.back' |
|
||||||
}, |
|
||||||
|
|
||||||
children: [ |
|
||||||
{ |
|
||||||
path: 'page', |
|
||||||
name: 'BackAuthPage', |
|
||||||
component: '/demo/permission/back/index', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.permission.backPage' |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'btn', |
|
||||||
name: 'BackAuthBtn', |
|
||||||
component: '/demo/permission/back/Btn', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.permission.backBtn' |
|
||||||
} |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
|
|
||||||
const authRoute = { |
|
||||||
path: '/permission', |
|
||||||
name: 'Permission', |
|
||||||
component: 'LAYOUT', |
|
||||||
redirect: '/permission/front/page', |
|
||||||
meta: { |
|
||||||
icon: 'carbon:user-role', |
|
||||||
title: 'routes.demo.permission.permission' |
|
||||||
}, |
|
||||||
children: [backRoute] |
|
||||||
} |
|
||||||
|
|
||||||
const levelRoute = { |
|
||||||
path: '/level', |
|
||||||
name: 'Level', |
|
||||||
component: 'LAYOUT', |
|
||||||
redirect: '/level/menu1/menu1-1', |
|
||||||
meta: { |
|
||||||
icon: 'carbon:user-role', |
|
||||||
title: 'routes.demo.level.level' |
|
||||||
}, |
|
||||||
|
|
||||||
children: [ |
|
||||||
{ |
|
||||||
path: 'menu1', |
|
||||||
name: 'Menu1Demo', |
|
||||||
meta: { |
|
||||||
title: 'Menu1' |
|
||||||
}, |
|
||||||
children: [ |
|
||||||
{ |
|
||||||
path: 'menu1-1', |
|
||||||
name: 'Menu11Demo', |
|
||||||
meta: { |
|
||||||
title: 'Menu1-1' |
|
||||||
}, |
|
||||||
children: [ |
|
||||||
{ |
|
||||||
path: 'menu1-1-1', |
|
||||||
name: 'Menu111Demo', |
|
||||||
component: '/demo/level/Menu111', |
|
||||||
meta: { |
|
||||||
title: 'Menu111' |
|
||||||
} |
|
||||||
} |
|
||||||
] |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'menu1-2', |
|
||||||
name: 'Menu12Demo', |
|
||||||
component: '/demo/level/Menu12', |
|
||||||
meta: { |
|
||||||
title: 'Menu1-2' |
|
||||||
} |
|
||||||
} |
|
||||||
] |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'menu2', |
|
||||||
name: 'Menu2Demo', |
|
||||||
component: '/demo/level/Menu2', |
|
||||||
meta: { |
|
||||||
title: 'Menu2' |
|
||||||
} |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
|
|
||||||
const sysRoute = { |
|
||||||
path: '/system', |
|
||||||
name: 'System', |
|
||||||
component: 'LAYOUT', |
|
||||||
redirect: '/system/account', |
|
||||||
meta: { |
|
||||||
icon: 'ion:settings-outline', |
|
||||||
title: 'routes.demo.system.moduleName' |
|
||||||
}, |
|
||||||
children: [ |
|
||||||
{ |
|
||||||
path: 'account', |
|
||||||
name: 'AccountManagement', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.system.account', |
|
||||||
ignoreKeepAlive: true |
|
||||||
}, |
|
||||||
component: '/demo/system/account/index' |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'account_detail/:id', |
|
||||||
name: 'AccountDetail', |
|
||||||
meta: { |
|
||||||
hideMenu: true, |
|
||||||
title: 'routes.demo.system.account_detail', |
|
||||||
ignoreKeepAlive: true, |
|
||||||
showMenu: false, |
|
||||||
currentActiveMenu: '/system/account' |
|
||||||
}, |
|
||||||
component: '/demo/system/account/AccountDetail' |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'role', |
|
||||||
name: 'RoleManagement', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.system.role', |
|
||||||
ignoreKeepAlive: true |
|
||||||
}, |
|
||||||
component: '/demo/system/role/index' |
|
||||||
}, |
|
||||||
|
|
||||||
{ |
|
||||||
path: 'menu', |
|
||||||
name: 'MenuManagement', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.system.menu', |
|
||||||
ignoreKeepAlive: true |
|
||||||
}, |
|
||||||
component: '/demo/system/menu/index' |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'dept', |
|
||||||
name: 'DeptManagement', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.system.dept', |
|
||||||
ignoreKeepAlive: true |
|
||||||
}, |
|
||||||
component: '/demo/system/dept/index' |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'changePassword', |
|
||||||
name: 'ChangePassword', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.system.password', |
|
||||||
ignoreKeepAlive: true |
|
||||||
}, |
|
||||||
component: '/demo/system/password/index' |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
|
|
||||||
const linkRoute = { |
|
||||||
path: '/link', |
|
||||||
name: 'Link', |
|
||||||
component: 'LAYOUT', |
|
||||||
meta: { |
|
||||||
icon: 'ion:tv-outline', |
|
||||||
title: 'routes.demo.iframe.frame' |
|
||||||
}, |
|
||||||
children: [ |
|
||||||
{ |
|
||||||
path: 'doc', |
|
||||||
name: 'Doc', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.iframe.doc', |
|
||||||
frameSrc: 'https://doc.vvbin.cn/' |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: 'https://doc.vvbin.cn/', |
|
||||||
name: 'DocExternal', |
|
||||||
component: 'LAYOUT', |
|
||||||
meta: { |
|
||||||
title: 'routes.demo.iframe.docExternal' |
|
||||||
} |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
|
|
||||||
export default [ |
|
||||||
{ |
|
||||||
url: '/basic-api/getMenuList', |
|
||||||
timeout: 1000, |
|
||||||
method: 'get', |
|
||||||
response: (request: requestParams) => { |
|
||||||
const token = getRequestToken(request) |
|
||||||
if (!token) { |
|
||||||
return resultError('Invalid token!') |
|
||||||
} |
|
||||||
const checkUser = createFakeUserList().find((item) => item.token === token) |
|
||||||
if (!checkUser) { |
|
||||||
return resultError('Invalid user token!') |
|
||||||
} |
|
||||||
const id = checkUser.userId |
|
||||||
let menu: Object[] |
|
||||||
switch (id) { |
|
||||||
case '1': |
|
||||||
dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[0].path |
|
||||||
menu = [dashboardRoute, authRoute, levelRoute, sysRoute, linkRoute] |
|
||||||
break |
|
||||||
case '2': |
|
||||||
dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[1].path |
|
||||||
menu = [dashboardRoute, authRoute, levelRoute, linkRoute] |
|
||||||
break |
|
||||||
default: |
|
||||||
menu = [] |
|
||||||
} |
|
||||||
|
|
||||||
return resultSuccess(menu) |
|
||||||
} |
|
||||||
} |
|
||||||
] as MockMethod[] |
|
@ -1,120 +0,0 @@ |
|||||||
import { MockMethod } from 'vite-plugin-mock' |
|
||||||
import { resultError, resultSuccess, getRequestToken, requestParams } from '../_util' |
|
||||||
|
|
||||||
export function createFakeUserList() { |
|
||||||
return [ |
|
||||||
{ |
|
||||||
userId: '1', |
|
||||||
username: 'vben', |
|
||||||
realName: 'Vben Admin', |
|
||||||
avatar: '', |
|
||||||
desc: 'manager', |
|
||||||
password: '123456', |
|
||||||
token: 'fakeToken1', |
|
||||||
homePath: '/dashboard/analysis', |
|
||||||
roles: [ |
|
||||||
{ |
|
||||||
roleName: 'Super Admin', |
|
||||||
value: 'super' |
|
||||||
} |
|
||||||
] |
|
||||||
}, |
|
||||||
{ |
|
||||||
userId: '2', |
|
||||||
username: 'test', |
|
||||||
password: '123456', |
|
||||||
realName: 'test user', |
|
||||||
avatar: '', |
|
||||||
desc: 'tester', |
|
||||||
token: 'fakeToken2', |
|
||||||
homePath: '/dashboard/workbench', |
|
||||||
roles: [ |
|
||||||
{ |
|
||||||
roleName: 'Tester', |
|
||||||
value: 'test' |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
|
|
||||||
const fakeCodeList: any = { |
|
||||||
'1': ['1000', '3000', '5000'], |
|
||||||
|
|
||||||
'2': ['2000', '4000', '6000'] |
|
||||||
} |
|
||||||
export default [ |
|
||||||
// mock user login
|
|
||||||
{ |
|
||||||
url: '/basic-api/login', |
|
||||||
timeout: 200, |
|
||||||
method: 'post', |
|
||||||
response: ({ body }) => { |
|
||||||
const { username, password } = body |
|
||||||
const checkUser = createFakeUserList().find((item) => item.username === username && password === item.password) |
|
||||||
if (!checkUser) { |
|
||||||
return resultError('Incorrect account or password!') |
|
||||||
} |
|
||||||
const { userId, username: _username, token, realName, desc, roles } = checkUser |
|
||||||
return resultSuccess({ |
|
||||||
roles, |
|
||||||
userId, |
|
||||||
username: _username, |
|
||||||
token, |
|
||||||
realName, |
|
||||||
desc |
|
||||||
}) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/getUserInfo', |
|
||||||
method: 'get', |
|
||||||
response: (request: requestParams) => { |
|
||||||
const token = getRequestToken(request) |
|
||||||
if (!token) return resultError('Invalid token') |
|
||||||
const checkUser = createFakeUserList().find((item) => item.token === token) |
|
||||||
if (!checkUser) { |
|
||||||
return resultError('The corresponding user information was not obtained!') |
|
||||||
} |
|
||||||
return resultSuccess(checkUser) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/getPermCode', |
|
||||||
timeout: 200, |
|
||||||
method: 'get', |
|
||||||
response: (request: requestParams) => { |
|
||||||
const token = getRequestToken(request) |
|
||||||
if (!token) return resultError('Invalid token') |
|
||||||
const checkUser = createFakeUserList().find((item) => item.token === token) |
|
||||||
if (!checkUser) { |
|
||||||
return resultError('Invalid token!') |
|
||||||
} |
|
||||||
const codeList = fakeCodeList[checkUser.userId] |
|
||||||
|
|
||||||
return resultSuccess(codeList) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/logout', |
|
||||||
timeout: 200, |
|
||||||
method: 'get', |
|
||||||
response: (request: requestParams) => { |
|
||||||
const token = getRequestToken(request) |
|
||||||
if (!token) return resultError('Invalid token') |
|
||||||
const checkUser = createFakeUserList().find((item) => item.token === token) |
|
||||||
if (!checkUser) { |
|
||||||
return resultError('Invalid token!') |
|
||||||
} |
|
||||||
return resultSuccess(undefined, { message: 'Token has been destroyed' }) |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
url: '/basic-api/testRetry', |
|
||||||
statusCode: 405, |
|
||||||
method: 'get', |
|
||||||
response: () => { |
|
||||||
return resultError('Error!') |
|
||||||
} |
|
||||||
} |
|
||||||
] as MockMethod[] |
|
@ -1,15 +0,0 @@ |
|||||||
# Test Server |
|
||||||
|
|
||||||
It is used to start the test interface service, which can test the upload, websocket, login and other interfaces. |
|
||||||
|
|
||||||
## Usage |
|
||||||
|
|
||||||
```bash |
|
||||||
|
|
||||||
cd ./test/server |
|
||||||
|
|
||||||
pnpm install |
|
||||||
|
|
||||||
pnpm run start |
|
||||||
|
|
||||||
``` |
|
@ -1,18 +0,0 @@ |
|||||||
import FileService from '../service/FileService' |
|
||||||
|
|
||||||
class FileController { |
|
||||||
private service: FileService = new FileService() |
|
||||||
|
|
||||||
upload = async (ctx) => { |
|
||||||
const files = ctx.request.files.file |
|
||||||
console.log(files) |
|
||||||
|
|
||||||
if (files.length === undefined) { |
|
||||||
this.service.upload(ctx, files, false) |
|
||||||
} else { |
|
||||||
this.service.upload(ctx, files, true) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default new FileController() |
|
@ -1,15 +0,0 @@ |
|||||||
import UserService from '../service/UserService' |
|
||||||
|
|
||||||
class UserController { |
|
||||||
private service: UserService = new UserService() |
|
||||||
|
|
||||||
login = async (ctx) => { |
|
||||||
ctx.body = await this.service.login() |
|
||||||
} |
|
||||||
|
|
||||||
getUserInfoById = async (ctx) => { |
|
||||||
ctx.body = await this.service.getUserInfoById() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default new UserController() |
|
@ -1,18 +0,0 @@ |
|||||||
const { name } = require('./package.json') |
|
||||||
const path = require('path') |
|
||||||
|
|
||||||
module.exports = { |
|
||||||
apps: [ |
|
||||||
{ |
|
||||||
name, |
|
||||||
script: path.resolve(__dirname, './dist/index.js'), |
|
||||||
instances: require('os').cpus().length, |
|
||||||
autorestart: true, |
|
||||||
watch: true, |
|
||||||
env_production: { |
|
||||||
NODE_ENV: 'production', |
|
||||||
PORT: 8080 |
|
||||||
} |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
@ -1,63 +0,0 @@ |
|||||||
import Koa from 'koa' |
|
||||||
import path from 'path' |
|
||||||
import Router from 'koa-router' |
|
||||||
import body from 'koa-body' |
|
||||||
import cors from 'koa2-cors' |
|
||||||
import koaStatic from 'koa-static' |
|
||||||
import websockify from 'koa-websocket' |
|
||||||
import route from 'koa-route' |
|
||||||
|
|
||||||
import AppRoutes from './routes' |
|
||||||
|
|
||||||
const PORT = 3300 |
|
||||||
|
|
||||||
const app = websockify(new Koa()) |
|
||||||
|
|
||||||
app.ws.use(function (ctx, next) { |
|
||||||
ctx.websocket.send('connection succeeded!') |
|
||||||
return next(ctx) |
|
||||||
}) |
|
||||||
|
|
||||||
app.ws.use( |
|
||||||
route.all('/test', function (ctx) { |
|
||||||
// ctx.websocket.send('Hello World');
|
|
||||||
ctx.websocket.on('message', function (message) { |
|
||||||
// do something with the message from client
|
|
||||||
|
|
||||||
if (message !== 'ping') { |
|
||||||
const data = JSON.stringify({ |
|
||||||
id: Math.ceil(Math.random() * 1000), |
|
||||||
time: new Date().getTime(), |
|
||||||
res: `${message}` |
|
||||||
}) |
|
||||||
ctx.websocket.send(data) |
|
||||||
} |
|
||||||
console.log(message) |
|
||||||
}) |
|
||||||
}) |
|
||||||
) |
|
||||||
|
|
||||||
const router = new Router() |
|
||||||
|
|
||||||
// router
|
|
||||||
AppRoutes.forEach((route) => router[route.method](route.path, route.action)) |
|
||||||
|
|
||||||
app.use(cors()) |
|
||||||
app.use( |
|
||||||
body({ |
|
||||||
encoding: 'gzip', |
|
||||||
multipart: true, |
|
||||||
formidable: { |
|
||||||
// uploadDir: path.join(__dirname, '/upload/'), // 设置文件上传目录
|
|
||||||
keepExtensions: true, |
|
||||||
maxFieldsSize: 20 * 1024 * 1024 |
|
||||||
} |
|
||||||
}) |
|
||||||
) |
|
||||||
app.use(router.routes()) |
|
||||||
app.use(router.allowedMethods()) |
|
||||||
app.use(koaStatic(path.join(__dirname))) |
|
||||||
|
|
||||||
app.listen(PORT, () => { |
|
||||||
console.log(`Application started successfully: http://localhost:${PORT}`) |
|
||||||
}) |
|
@ -1,8 +0,0 @@ |
|||||||
{ |
|
||||||
"watch": ["src"], |
|
||||||
"ext": "ts", |
|
||||||
"exec": "ts-node -r tsconfig-paths/register index.ts", |
|
||||||
"events": { |
|
||||||
"restart": "clear" |
|
||||||
} |
|
||||||
} |
|
@ -1,36 +0,0 @@ |
|||||||
{ |
|
||||||
"name": "server", |
|
||||||
"version": "1.0.0", |
|
||||||
"license": "MIT", |
|
||||||
"scripts": { |
|
||||||
"start": "nodemon", |
|
||||||
"build": "rimraf ./dist && tsup ./index.ts --dts --format cjs,esm ", |
|
||||||
"prod": "npx pm2 start ecosystem.config.js --env production", |
|
||||||
"restart": "pm2 restart ecosystem.config.js --env production", |
|
||||||
"stop": "npx pm2 stop ecosystem.config.js" |
|
||||||
}, |
|
||||||
"dependencies": { |
|
||||||
"fs-extra": "^10.0.1", |
|
||||||
"koa": "^2.13.4", |
|
||||||
"koa-body": "^4.2.0", |
|
||||||
"koa-bodyparser": "^4.3.0", |
|
||||||
"koa-route": "^3.2.0", |
|
||||||
"koa-router": "^10.1.1", |
|
||||||
"koa-static": "^5.0.0", |
|
||||||
"koa-websocket": "^6.0.0", |
|
||||||
"koa2-cors": "^2.0.6" |
|
||||||
}, |
|
||||||
"devDependencies": { |
|
||||||
"@types/koa": "^2.13.4", |
|
||||||
"@types/koa-bodyparser": "^5.0.2", |
|
||||||
"@types/koa-router": "^7.4.4", |
|
||||||
"@types/node": "^17.0.21", |
|
||||||
"nodemon": "^2.0.15", |
|
||||||
"pm2": "^5.2.0", |
|
||||||
"rimraf": "^3.0.2", |
|
||||||
"ts-node": "^10.7.0", |
|
||||||
"tsconfig-paths": "^3.14.0", |
|
||||||
"tsup": "^5.12.1", |
|
||||||
"typescript": "^4.6.2" |
|
||||||
} |
|
||||||
} |
|
@ -1,23 +0,0 @@ |
|||||||
import UserController from './controller/UserController' |
|
||||||
import FileController from './controller/FileController' |
|
||||||
|
|
||||||
export default [ |
|
||||||
// user
|
|
||||||
{ |
|
||||||
path: '/login', |
|
||||||
method: 'post', |
|
||||||
action: UserController.login |
|
||||||
}, |
|
||||||
{ |
|
||||||
path: '/getUserInfoById', |
|
||||||
method: 'get', |
|
||||||
action: UserController.getUserInfoById |
|
||||||
}, |
|
||||||
|
|
||||||
// file
|
|
||||||
{ |
|
||||||
path: '/upload', |
|
||||||
method: 'post', |
|
||||||
action: FileController.upload |
|
||||||
} |
|
||||||
] |
|
@ -1,54 +0,0 @@ |
|||||||
import path from 'path' |
|
||||||
import fs from 'fs-extra' |
|
||||||
|
|
||||||
const uploadUrl = 'http://localhost:3300/static/upload' |
|
||||||
const filePath = path.join(__dirname, '../static/upload/') |
|
||||||
|
|
||||||
fs.ensureDir(filePath) |
|
||||||
export default class UserService { |
|
||||||
async upload(ctx, files, isMultiple) { |
|
||||||
let fileReader, fileResource, writeStream |
|
||||||
|
|
||||||
const fileFunc = function (file) { |
|
||||||
fileReader = fs.createReadStream(file.path) |
|
||||||
fileResource = filePath + `/${file.name}` |
|
||||||
console.log(fileResource) |
|
||||||
|
|
||||||
writeStream = fs.createWriteStream(fileResource) |
|
||||||
fileReader.pipe(writeStream) |
|
||||||
} |
|
||||||
|
|
||||||
const returnFunc = function (flag) { |
|
||||||
if (flag) { |
|
||||||
let url = '' |
|
||||||
for (let i = 0; i < files.length; i++) { |
|
||||||
url += uploadUrl + `/${files[i].name},` |
|
||||||
} |
|
||||||
url = url.replace(/,$/gi, '') |
|
||||||
ctx.body = { |
|
||||||
url: url, |
|
||||||
code: 0, |
|
||||||
message: 'upload Success!' |
|
||||||
} |
|
||||||
} else { |
|
||||||
ctx.body = { |
|
||||||
url: uploadUrl + `/${files.name}`, |
|
||||||
code: 0, |
|
||||||
message: 'upload Success!' |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
console.log(isMultiple, files.length) |
|
||||||
|
|
||||||
if (isMultiple) { |
|
||||||
for (let i = 0; i < files.length; i++) { |
|
||||||
const f1 = files[i] |
|
||||||
fileFunc(f1) |
|
||||||
} |
|
||||||
} else { |
|
||||||
fileFunc(files) |
|
||||||
} |
|
||||||
fs.ensureDir(filePath) |
|
||||||
returnFunc(isMultiple) |
|
||||||
} |
|
||||||
} |
|
@ -1,25 +0,0 @@ |
|||||||
import { Result } from '../utils' |
|
||||||
|
|
||||||
const fakeUserInfo = { |
|
||||||
userId: '1', |
|
||||||
username: 'vben', |
|
||||||
realName: 'Vben Admin', |
|
||||||
desc: 'manager', |
|
||||||
password: '123456', |
|
||||||
token: 'fakeToken1', |
|
||||||
roles: [ |
|
||||||
{ |
|
||||||
roleName: 'Super Admin', |
|
||||||
value: 'super' |
|
||||||
} |
|
||||||
] |
|
||||||
} |
|
||||||
export default class UserService { |
|
||||||
async login() { |
|
||||||
return Result.success(fakeUserInfo) |
|
||||||
} |
|
||||||
|
|
||||||
async getUserInfoById() { |
|
||||||
return Result.success(fakeUserInfo) |
|
||||||
} |
|
||||||
} |
|
@ -1,15 +0,0 @@ |
|||||||
{ |
|
||||||
"compilerOptions": { |
|
||||||
"module": "commonjs", |
|
||||||
"declaration": false, |
|
||||||
"removeComments": true, |
|
||||||
"emitDecoratorMetadata": true, |
|
||||||
"experimentalDecorators": true, |
|
||||||
"target": "es6", |
|
||||||
"sourceMap": false, |
|
||||||
"esModuleInterop": true, |
|
||||||
"outDir": "./dist", |
|
||||||
"baseUrl": "./" |
|
||||||
}, |
|
||||||
"exclude": ["node_modules"] |
|
||||||
} |
|
@ -1,9 +0,0 @@ |
|||||||
export class Result { |
|
||||||
static success(data: any) { |
|
||||||
return { |
|
||||||
code: 0, |
|
||||||
success: true, |
|
||||||
result: data |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Reference in new issue