新增前端vue
This commit is contained in:
4
web-vue/packages/tests/src/config/index.ts
Normal file
4
web-vue/packages/tests/src/config/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
host: 'localhost',
|
||||
port: 3300,
|
||||
};
|
||||
15
web-vue/packages/tests/src/controller/FileController.ts
Normal file
15
web-vue/packages/tests/src/controller/FileController.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import FileService from '../service/FileService';
|
||||
import { router } from '../router';
|
||||
|
||||
const service: FileService = new FileService();
|
||||
|
||||
router.post('/menuRoute', async (ctx) => {
|
||||
const files: any = ctx.request.files.file;
|
||||
console.log(files);
|
||||
|
||||
if (files.length === undefined) {
|
||||
service.upload(ctx, files, false);
|
||||
} else {
|
||||
service.upload(ctx, files, true);
|
||||
}
|
||||
});
|
||||
8
web-vue/packages/tests/src/controller/MenuController.ts
Normal file
8
web-vue/packages/tests/src/controller/MenuController.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import MenuService from '../service/MenuService';
|
||||
import { router } from '../router';
|
||||
|
||||
const service: MenuService = new MenuService();
|
||||
|
||||
router.get('/menuRoute', async (ctx) => {
|
||||
ctx.body = await service.menuRoute(ctx);
|
||||
});
|
||||
12
web-vue/packages/tests/src/controller/UserController.ts
Normal file
12
web-vue/packages/tests/src/controller/UserController.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import UserService from '../service/UserService';
|
||||
import { router } from '../router';
|
||||
|
||||
const service: UserService = new UserService();
|
||||
|
||||
router.get('/login', async (ctx) => {
|
||||
ctx.body = await service.login(ctx);
|
||||
});
|
||||
|
||||
router.get('/index', async (ctx) => {
|
||||
ctx.body = await service.index(ctx);
|
||||
});
|
||||
20
web-vue/packages/tests/src/index.ts
Normal file
20
web-vue/packages/tests/src/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import path from 'path';
|
||||
import Koa from 'koa';
|
||||
import koaStatic from 'koa-static';
|
||||
import koaWebsocket from 'koa-websocket';
|
||||
import websocket from './ws';
|
||||
import config from './config';
|
||||
import router from './router';
|
||||
import './router/routes';
|
||||
|
||||
const app = koaWebsocket(new Koa());
|
||||
|
||||
websocket(app);
|
||||
|
||||
router(app);
|
||||
|
||||
app.use(koaStatic(path.join(__dirname, '../')));
|
||||
|
||||
app.listen(config.port, () => {
|
||||
console.log(`Application started successfully: http://${config.host}:${config.port}`);
|
||||
});
|
||||
29
web-vue/packages/tests/src/router/index.ts
Normal file
29
web-vue/packages/tests/src/router/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import Router from 'koa-router';
|
||||
// import routes from './routes';
|
||||
import cors from 'koa2-cors';
|
||||
import body from 'koa-body';
|
||||
|
||||
const router = new Router();
|
||||
|
||||
function initRouter(app: any): Router<any, any> {
|
||||
// routes.forEach((route) => router[route.method](route.path, route.action));
|
||||
app.use(cors());
|
||||
app.use(
|
||||
body({
|
||||
encoding: 'gzip',
|
||||
multipart: true,
|
||||
formidable: {
|
||||
// uploadDir: path.join(__dirname, '../../static/upload/'), // 设置文件上传目录
|
||||
keepExtensions: true,
|
||||
maxFieldsSize: 20 * 1024 * 1024,
|
||||
},
|
||||
}),
|
||||
);
|
||||
app.use(router.routes());
|
||||
app.use(router.allowedMethods());
|
||||
return router;
|
||||
}
|
||||
|
||||
export { router };
|
||||
|
||||
export default initRouter;
|
||||
3
web-vue/packages/tests/src/router/routes.ts
Normal file
3
web-vue/packages/tests/src/router/routes.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import '../controller/UserController';
|
||||
import '../controller/MenuController';
|
||||
import '../controller/FileController';
|
||||
56
web-vue/packages/tests/src/service/FileService.ts
Normal file
56
web-vue/packages/tests/src/service/FileService.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import config from '../config';
|
||||
|
||||
const uploadUrl = `http://${config.host}:${config.port}/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);
|
||||
}
|
||||
}
|
||||
261
web-vue/packages/tests/src/service/MenuService.ts
Normal file
261
web-vue/packages/tests/src/service/MenuService.ts
Normal file
@@ -0,0 +1,261 @@
|
||||
import { Result } from '../utils';
|
||||
import { fakeUserList } from './UserService';
|
||||
|
||||
// single
|
||||
const dashboardRoute = {
|
||||
path: '/dashboard',
|
||||
name: 'Dashboard',
|
||||
component: 'LAYOUT',
|
||||
redirect: '/dashboard/analysis',
|
||||
meta: {
|
||||
title: 'routes.dashboard.dashboard',
|
||||
hideChildrenInMenu: true,
|
||||
icon: 'i-bx:bx-home',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'analysis',
|
||||
name: 'Analysis',
|
||||
component: '/dashboard/analysis/index',
|
||||
meta: {
|
||||
hideMenu: true,
|
||||
hideBreadcrumb: true,
|
||||
title: 'routes.dashboard.analysis',
|
||||
currentActiveMenu: '/dashboard',
|
||||
icon: 'i-bx:bx-home',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'workbench',
|
||||
name: 'Workbench',
|
||||
component: '/dashboard/workbench/index',
|
||||
meta: {
|
||||
hideMenu: true,
|
||||
hideBreadcrumb: true,
|
||||
title: 'routes.dashboard.workbench',
|
||||
currentActiveMenu: '/dashboard',
|
||||
icon: 'i-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: 'i-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: 'i-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: 'i-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: 'i-ion:tv-outline',
|
||||
title: 'routes.demo.iframe.frame',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'doc',
|
||||
name: 'Doc',
|
||||
meta: {
|
||||
title: 'routes.demo.iframe.doc',
|
||||
frameSrc: 'https://vvbin.cn/doc-next/',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'https://vvbin.cn/doc-next/',
|
||||
name: 'DocExternal',
|
||||
component: 'LAYOUT',
|
||||
meta: {
|
||||
title: 'routes.demo.iframe.docExternal',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default class MenuService {
|
||||
async menuRoute(ctx) {
|
||||
const { token } = ctx.request.query;
|
||||
if (!token) return Result.error('Invalid token');
|
||||
const checkUser = fakeUserList.find((item) => item.token === token);
|
||||
if (!checkUser) {
|
||||
return Result.error('Invalid user token!');
|
||||
}
|
||||
const id = checkUser.userCode;
|
||||
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 Result.success(menu);
|
||||
}
|
||||
}
|
||||
68
web-vue/packages/tests/src/service/UserService.ts
Normal file
68
web-vue/packages/tests/src/service/UserService.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { Result } from '../utils';
|
||||
|
||||
export const fakeUserList: any = [
|
||||
{
|
||||
userCode: '1',
|
||||
username: 'c3lzdGVt',
|
||||
password: 'YWRtaW4=',
|
||||
userName: 'ThinkGem',
|
||||
avatarUrl: 'https://q1.qlogo.cn/g?b=qq&nk=190848757&s=640',
|
||||
remarks: 'manager',
|
||||
token: 'fakeToken1',
|
||||
roleList: [
|
||||
{
|
||||
roleName: 'Super Admin',
|
||||
roleCode: 'super',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
userCode: '2',
|
||||
username: 'test',
|
||||
password: '123456',
|
||||
userName: 'TestUser',
|
||||
avatarUrl: 'https://q1.qlogo.cn/g?b=qq&nk=339449197&s=640',
|
||||
remarks: 'tester',
|
||||
token: 'fakeToken2',
|
||||
roleList: [
|
||||
{
|
||||
roleName: 'Tester',
|
||||
roleCode: 'test',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const fakeCodeList: any = {
|
||||
'1': ['1000', '3000', '5000'],
|
||||
'2': ['2000', '4000', '6000'],
|
||||
};
|
||||
|
||||
export default class UserService {
|
||||
async login(ctx) {
|
||||
const { username, password } = ctx.request.query;
|
||||
const checkUser = fakeUserList.find((item) => item.username === username && password === item.password);
|
||||
if (!checkUser) {
|
||||
return Result.error('Incorrect account or password!');
|
||||
}
|
||||
const { userCode, username: _username, token, realName, desc, roles } = checkUser;
|
||||
return Result.success({
|
||||
roles,
|
||||
userCode,
|
||||
username: _username,
|
||||
token,
|
||||
realName,
|
||||
desc,
|
||||
});
|
||||
}
|
||||
|
||||
async index(ctx) {
|
||||
const { token } = ctx.request.query;
|
||||
if (!token) return Result.error('Invalid token');
|
||||
const checkUser = fakeUserList.find((item) => item.token === token);
|
||||
if (!checkUser) {
|
||||
return Result.error('The corresponding user information was not obtained!');
|
||||
}
|
||||
return Result.success(fakeUserList);
|
||||
}
|
||||
}
|
||||
16
web-vue/packages/tests/src/utils/index.ts
Normal file
16
web-vue/packages/tests/src/utils/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export class Result {
|
||||
static success(data: any) {
|
||||
return {
|
||||
code: 0,
|
||||
success: true,
|
||||
result: data,
|
||||
};
|
||||
}
|
||||
static error(data: any) {
|
||||
return {
|
||||
code: 0,
|
||||
success: false,
|
||||
result: data,
|
||||
};
|
||||
}
|
||||
}
|
||||
28
web-vue/packages/tests/src/ws/index.ts
Normal file
28
web-vue/packages/tests/src/ws/index.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import route from 'koa-route';
|
||||
|
||||
function initWebsocket(app: any) {
|
||||
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);
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export default initWebsocket;
|
||||
Reference in New Issue
Block a user