From 47515547b250a43779f090c0b8bbe1c53742db1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=95=8A=E5=B9=B3?= <951984189@qq.com> Date: Thu, 25 Feb 2021 18:20:52 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E8=AF=95=E6=9D=83=E9=99=90=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/app/{extend => comm}/ipipfree.ipdb | Bin src/app/{extend/helper.ts => comm/utils.ts} | 21 ++- src/app/modules/base/controller/admin/comm.ts | 12 +- src/app/modules/base/controller/admin/open.ts | 16 ++ .../modules/base/controller/admin/sys/log.ts | 28 ++- .../modules/base/controller/admin/sys/menu.ts | 2 +- .../base/controller/admin/sys/param.ts | 34 ++++ .../modules/base/controller/admin/sys/role.ts | 1 + .../modules/base/controller/admin/sys/user.ts | 9 +- src/app/modules/base/entity/sys/log.ts | 3 - src/app/modules/base/entity/sys/param.ts | 27 +++ src/app/modules/base/entity/sys/user.ts | 6 +- src/app/modules/base/middleware/authority.ts | 2 +- src/app/modules/base/middleware/log.ts | 2 +- src/app/modules/base/schedule/log.ts | 29 ++++ .../modules/base/service/sys/department.ts | 38 ++-- src/app/modules/base/service/sys/log.ts | 42 +++-- src/app/modules/base/service/sys/login.ts | 31 +++- src/app/modules/base/service/sys/menu.ts | 10 ++ src/app/modules/base/service/sys/param.ts | 61 +++++++ src/app/modules/base/service/sys/perms.ts | 12 +- src/app/modules/base/service/sys/user.ts | 162 +++++++++++++++++- src/config/config.default.ts | 6 + 24 files changed, 482 insertions(+), 74 deletions(-) rename src/app/{extend => comm}/ipipfree.ipdb (100%) rename src/app/{extend/helper.ts => comm/utils.ts} (76%) create mode 100644 src/app/modules/base/controller/admin/sys/param.ts create mode 100644 src/app/modules/base/entity/sys/param.ts create mode 100644 src/app/modules/base/schedule/log.ts create mode 100644 src/app/modules/base/service/sys/param.ts diff --git a/package.json b/package.json index d5abd54..61cdc54 100755 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dependencies": { "@midwayjs/decorator": "^2.7.5", "@midwayjs/orm": "^1.3.0", - "@midwayjs/web": "^2.3.0", + "@midwayjs/web": "^2.7.7", "egg": "^2.29.3", "egg-scripts": "^2.13.0", "egg-view-nunjucks": "^2.3.0", diff --git a/src/app/extend/ipipfree.ipdb b/src/app/comm/ipipfree.ipdb similarity index 100% rename from src/app/extend/ipipfree.ipdb rename to src/app/comm/ipipfree.ipdb diff --git a/src/app/extend/helper.ts b/src/app/comm/utils.ts similarity index 76% rename from src/app/extend/helper.ts rename to src/app/comm/utils.ts index b6027a6..d5d0a4b 100644 --- a/src/app/extend/helper.ts +++ b/src/app/comm/utils.ts @@ -1,4 +1,4 @@ -import { Provide } from '@midwayjs/decorator'; +import { Inject, Provide } from '@midwayjs/decorator'; import * as ipdb from 'ipip-ipdb'; import * as _ from 'lodash'; import { Context } from 'egg'; @@ -7,25 +7,29 @@ import { Context } from 'egg'; * 帮助类 */ @Provide() - export class Helper { +export class Utils { + + @Inject() + baseDir; + /** * 获得请求IP */ - public async getReqIP(ctx: Context) { + async getReqIP(ctx: Context) { const req = ctx.req; - return req.headers['x-forwarded-for'] || req.socket.remoteAddress + return req.headers['x-forwarded-for'] || req.socket.remoteAddress.replace('::ffff:', ''); } /** * 根据IP获得请求地址 * @param ip 为空时则为当前请求的IP地址 */ - public async getIpAddr(ctx: Context, ip?: string | string[]) { + async getIpAddr(ctx: Context, ip?: string | string[]) { try { if (!ip) { ip = await this.getReqIP(ctx); } - const bst = new ipdb.BaseStation('./ipipfree.ipdb'); + const bst = new ipdb.BaseStation(`${this.baseDir}/app/comm/ipipfree.ipdb`); const result = bst.findInfo(ip, 'CN'); const addArr: any = []; if (result) { @@ -36,6 +40,7 @@ import { Context } from 'egg'; } // @ts-ignore } catch (err) { + console.log(err) return '无法获取地址信息'; } } @@ -44,7 +49,7 @@ import { Context } from 'egg'; * 去除对象的空值属性 * @param obj */ - public async removeEmptyP(obj) { + async removeEmptyP(obj) { Object.keys(obj).forEach(key => { if (obj[key] === null || obj[key] === '' || obj[key] === 'undefined') { delete obj[key]; @@ -56,7 +61,7 @@ import { Context } from 'egg'; * 线程阻塞毫秒数 * @param ms */ - public sleep(ms) { + sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } diff --git a/src/app/modules/base/controller/admin/comm.ts b/src/app/modules/base/controller/admin/comm.ts index 3275c7f..49c3db0 100644 --- a/src/app/modules/base/controller/admin/comm.ts +++ b/src/app/modules/base/controller/admin/comm.ts @@ -1,6 +1,7 @@ -import { Provide, Inject, Get } from '@midwayjs/decorator'; +import { Provide, Inject, Get, Post, Body, ALL } from '@midwayjs/decorator'; import { Context } from 'egg'; import { CoolController, BaseController } from 'midwayjs-cool-core'; +import { BaseSysUserEntity } from '../../entity/sys/user'; import { BaseSysPermsService } from '../../service/sys/perms'; import { BaseSysUserService } from '../../service/sys/user'; @@ -28,6 +29,15 @@ export class BaseCommController extends BaseController { return this.ok(await this.baseSysUserService.person()); } + /** + * 修改个人信息 + */ + @Post('/personUpdate') + public async personUpdate(@Body(ALL) user: BaseSysUserEntity) { + await this.baseSysUserService.personUpdate(user); + return this.ok(); + } + /** * 权限菜单 */ diff --git a/src/app/modules/base/controller/admin/open.ts b/src/app/modules/base/controller/admin/open.ts index 987aa74..7222688 100644 --- a/src/app/modules/base/controller/admin/open.ts +++ b/src/app/modules/base/controller/admin/open.ts @@ -1,7 +1,9 @@ import { Provide, Body, ALL, Inject, Post, Get, Query } from '@midwayjs/decorator'; +import { Context } from 'egg'; import { CoolController, BaseController } from 'midwayjs-cool-core'; import { LoginDTO } from '../../dto/login'; import { BaseSysLoginService } from '../../service/sys/login'; +import { BaseSysParamService } from '../../service/sys/param'; /** * 不需要登录的后台接口 @@ -13,6 +15,20 @@ export class BaseSysOpenController extends BaseController { @Inject() baseSysLoginService: BaseSysLoginService; + @Inject() + baseSysParamService: BaseSysParamService; + + @Inject() + ctx: Context; + + /** + * 根据配置参数key获得网页内容(富文本) + */ + @Get('/html') + async htmlByKey(@Query() key: string) { + this.ctx.body = await this.baseSysParamService.htmlByKey(key); + } + /** * 登录 * @param login diff --git a/src/app/modules/base/controller/admin/sys/log.ts b/src/app/modules/base/controller/admin/sys/log.ts index 7b62873..023bafa 100644 --- a/src/app/modules/base/controller/admin/sys/log.ts +++ b/src/app/modules/base/controller/admin/sys/log.ts @@ -1,7 +1,8 @@ -import { Provide, Post, Inject } from '@midwayjs/decorator'; +import { Provide, Post, Inject, Body, Get } from '@midwayjs/decorator'; import { CoolController, BaseController } from 'midwayjs-cool-core'; import { BaseSysLogEntity } from '../../../entity/sys/log'; import { BaseSysUserEntity } from '../../../entity/sys/user'; +import { BaseSysConfService } from '../../../service/sys/conf'; import { BaseSysLogService } from '../../../service/sys/log'; /** @@ -24,15 +25,36 @@ import { BaseSysLogService } from '../../../service/sys/log'; export class BaseSysLogController extends BaseController { @Inject() - adminSysLogService: BaseSysLogService; + baseSysLogService: BaseSysLogService; + + @Inject() + baseSysConfService: BaseSysConfService; /** * 清空日志 */ @Post('/clear') public async clear() { - await this.adminSysLogService.clear(true); + await this.baseSysLogService.clear(true); return this.ok(); } + + /** + * 设置日志保存时间 + */ + @Post('/setKeep') + public async setKeep(@Body() value: number) { + await this.baseSysConfService.updateVaule('logKeep', value); + return this.ok(); + } + + /** + * 获得日志保存时间 + */ + @Get('/getKeep') + public async getKeep() { + return this.ok(await this.baseSysConfService.getValue('logKeep')); + } + } \ No newline at end of file diff --git a/src/app/modules/base/controller/admin/sys/menu.ts b/src/app/modules/base/controller/admin/sys/menu.ts index a7e4ccb..9f26945 100644 --- a/src/app/modules/base/controller/admin/sys/menu.ts +++ b/src/app/modules/base/controller/admin/sys/menu.ts @@ -8,7 +8,7 @@ import { BaseSysMenuService } from '../../../service/sys/menu'; */ @Provide() @CoolController({ - api: ['add', 'delete', 'update', 'list', 'page'], + api: ['add', 'delete', 'update', 'info', 'list', 'page'], entity: BaseSysMenuEntity, service: BaseSysMenuService }) diff --git a/src/app/modules/base/controller/admin/sys/param.ts b/src/app/modules/base/controller/admin/sys/param.ts new file mode 100644 index 0000000..56d7649 --- /dev/null +++ b/src/app/modules/base/controller/admin/sys/param.ts @@ -0,0 +1,34 @@ +import { Get, Inject, Provide, Query } from '@midwayjs/decorator'; +import { Context } from 'egg'; +import { CoolController, BaseController } from 'midwayjs-cool-core'; +import { BaseSysParamEntity } from '../../../entity/sys/param'; +import { BaseSysParamService } from '../../../service/sys/param'; + +/** + * 参数配置 + */ +@Provide() +@CoolController({ + api: ['add', 'delete', 'update', 'info', 'page'], + entity: BaseSysParamEntity, + pageQueryOp: { + keyWordLikeFields: ['name', 'keyName'] + } +}) +export class BaseSysParamController extends BaseController { + + @Inject() + baseSysParamService: BaseSysParamService; + + @Inject() + ctx: Context; + + /** + * 根据配置参数key获得网页内容(富文本) + */ + @Get('/html') + async htmlByKey(@Query() key: string) { + this.ctx.body = await this.baseSysParamService.htmlByKey(key); + } + +} \ No newline at end of file diff --git a/src/app/modules/base/controller/admin/sys/role.ts b/src/app/modules/base/controller/admin/sys/role.ts index b543c05..1aed75b 100644 --- a/src/app/modules/base/controller/admin/sys/role.ts +++ b/src/app/modules/base/controller/admin/sys/role.ts @@ -10,6 +10,7 @@ import { BaseSysRoleEntity } from '../../../entity/sys/role'; @CoolController({ api: ['add', 'delete', 'update', 'info', 'list', 'page'], entity: BaseSysRoleEntity, + // 新增的时候插入当前用户ID insertParam: (async (ctx: Context) => { return { userId: ctx.admin.userId diff --git a/src/app/modules/base/controller/admin/sys/user.ts b/src/app/modules/base/controller/admin/sys/user.ts index 916e672..105bcc9 100644 --- a/src/app/modules/base/controller/admin/sys/user.ts +++ b/src/app/modules/base/controller/admin/sys/user.ts @@ -9,20 +9,21 @@ import { BaseSysUserService } from '../../../service/sys/user'; @Provide() @CoolController({ api: ['add', 'delete', 'update', 'info', 'list', 'page'], - entity: BaseSysUserEntity + entity: BaseSysUserEntity, + service: BaseSysUserService }) export class BaseSysUserController extends BaseController { @Inject() - BaseSysUserService: BaseSysUserService; + baseSysUserService: BaseSysUserService; /** * 移动部门 */ @Post('/move') async move(@Body() departmentId: number, @Body() userIds: []) { - await this.BaseSysUserService.move(departmentId, userIds); - this.ok(); + await this.baseSysUserService.move(departmentId, userIds); + return this.ok(); } } \ No newline at end of file diff --git a/src/app/modules/base/entity/sys/log.ts b/src/app/modules/base/entity/sys/log.ts index 3108c2b..f2663bf 100644 --- a/src/app/modules/base/entity/sys/log.ts +++ b/src/app/modules/base/entity/sys/log.ts @@ -27,7 +27,4 @@ export class BaseSysLogEntity extends BaseEntity { @Column({ comment: '参数', nullable: true, type: 'text' }) params: string; - @Column({ comment: '响应毫秒数, 值为-1则响应不成功', default: -1 }) - ms: number; - } diff --git a/src/app/modules/base/entity/sys/param.ts b/src/app/modules/base/entity/sys/param.ts new file mode 100644 index 0000000..de38552 --- /dev/null +++ b/src/app/modules/base/entity/sys/param.ts @@ -0,0 +1,27 @@ +import { EntityModel } from '@midwayjs/orm'; +import { BaseEntity } from 'midwayjs-cool-core'; +import { Column, Index } from 'typeorm'; + +/** + * 参数配置 + */ +@EntityModel('base_sys_param') +export class BaseSysParamEntity extends BaseEntity { + + @Index() + @Column({ comment: '键位' }) + keyName: string; + + @Column({comment: '名称'}) + name: string; + + @Column({comment: '数据', type: 'text' }) + data: string; + + @Column({comment: '数据类型 0:字符串 1:数组 2:键值对', default: 0, type: 'tinyint' }) + dataType: number; + + @Column({ comment: '备注', nullable: true }) + remark: string; + +} \ No newline at end of file diff --git a/src/app/modules/base/entity/sys/user.ts b/src/app/modules/base/entity/sys/user.ts index 9ffbe3d..d9f3d49 100644 --- a/src/app/modules/base/entity/sys/user.ts +++ b/src/app/modules/base/entity/sys/user.ts @@ -38,9 +38,13 @@ export class BaseSysUserEntity extends BaseEntity { @Column({ comment: '邮箱', nullable: true }) email: string; - @Column({ comment: '备注', nullable: true, length: 500 }) + @Column({ comment: '备注', nullable: true }) remark: string; @Column({ comment: '状态 0:禁用 1:启用', default: 1, type: 'tinyint' }) status: number; + // 部门名称 + departmentName: string; + // 角色ID列表 + roleIdList: number[]; } diff --git a/src/app/modules/base/middleware/authority.ts b/src/app/modules/base/middleware/authority.ts index b3e4664..c02e64c 100644 --- a/src/app/modules/base/middleware/authority.ts +++ b/src/app/modules/base/middleware/authority.ts @@ -6,7 +6,7 @@ import * as jwt from 'jsonwebtoken'; import { Context } from 'egg'; /** - * 描述 + * 权限校验 */ @Provide() export class BaseAuthorityMiddleware implements IWebMiddleware { diff --git a/src/app/modules/base/middleware/log.ts b/src/app/modules/base/middleware/log.ts index 92f8ea2..73b9e33 100644 --- a/src/app/modules/base/middleware/log.ts +++ b/src/app/modules/base/middleware/log.ts @@ -14,7 +14,7 @@ export class BaseLogMiddleware implements IWebMiddleware { resolve() { return async (ctx: Context, next: IMidwayWebNext) => { - this.baseSysLogService.record(ctx.url.split('?')[0], ctx.req.method === 'GET' ? ctx.request.query : ctx.request.body, ctx.admin ? ctx.admin.userId : null); + this.baseSysLogService.record(ctx, ctx.url.split('?')[0], ctx.req.method === 'GET' ? ctx.request.query : ctx.request.body, ctx.admin ? ctx.admin.userId : null); await next(); }; } diff --git a/src/app/modules/base/schedule/log.ts b/src/app/modules/base/schedule/log.ts new file mode 100644 index 0000000..e255b51 --- /dev/null +++ b/src/app/modules/base/schedule/log.ts @@ -0,0 +1,29 @@ +// src/schedule/hello.ts +import { Provide, Inject, Schedule, CommonSchedule } from '@midwayjs/decorator'; +import { BaseSysLogService } from '../service/sys/log'; +import { ILogger } from '@midwayjs/logger'; + +/** + * 日志定时任务 + */ +@Provide() +@Schedule({ + cron: '0 0 0 * * *', // 每天0点执行 + type: 'worker' // 指定某一个 worker 执行 +}) +export class BaseLogSchedule implements CommonSchedule { + + @Inject() + baseSysLogService: BaseSysLogService; + + @Inject() + logger: ILogger; + + // 定时执行的具体任务 + async exec() { + this.logger.info('清除日志定时任务开始执行'); + const startTime = Date.now(); + await this.baseSysLogService.clear(); + this.logger.info(`清除日志定时任务结束,耗时:${(Date.now() - startTime)}ms`); + } +} \ No newline at end of file diff --git a/src/app/modules/base/service/sys/department.ts b/src/app/modules/base/service/sys/department.ts index a12e4e9..1fb8da1 100644 --- a/src/app/modules/base/service/sys/department.ts +++ b/src/app/modules/base/service/sys/department.ts @@ -26,25 +26,23 @@ export class BaseSysDepartmentService extends BaseService { @Inject() ctx: Context; - /** - * 获得部门菜单 - */ - async list () { - const permsDepartmentArr = await this.baseSysPermsService.departmentIds(this.ctx.admin.userId); // 部门权限 - const departments = await this.nativeQuery(` - SELECT - * - FROM - base_sys_department a - WHERE - 1 = 1 - ${ this.setSql(this.ctx.admin.userId !== '1', 'and a.id in (?)', [ !_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [ null ] ]) } - ORDER BY - a.orderNum ASC`); + /** + * 获得部门菜单 + */ + async list() { + // 部门权限 + const permsDepartmentArr = await this.baseSysPermsService.departmentIds(this.ctx.admin.userId); + + // 过滤部门权限 + const find = this.baseSysDepartmentEntity.createQueryBuilder(); + if (this.ctx.admin.username !== 'admin') find.andWhere('id in (:ids)', { ids: !_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [null] }); + find.addOrderBy('orderNum', 'ASC'); + const departments: BaseSysDepartmentEntity[] = await find.getMany(); + if (!_.isEmpty(departments)) { departments.forEach(e => { const parentMenu = departments.filter(m => { - if (e.parentId === m.id) { + if (e.parentId == m.id) { return m.name; } }); @@ -83,7 +81,7 @@ export class BaseSysDepartmentService extends BaseService { * 部门排序 * @param params */ - async order (params) { + async order(params) { for (const e of params) { await this.baseSysDepartmentEntity.update(e.id, e); } @@ -92,15 +90,15 @@ export class BaseSysDepartmentService extends BaseService { /** * 删除 */ - async delete (ids: number[]) { + async delete(ids: number[]) { let { deleteUser } = this.ctx.request.body; await this.baseSysDepartmentEntity.delete(ids); if (deleteUser) { - await this.nativeQuery('delete from base_sys_user where departmentId in (?)', [ ids ]); + await this.nativeQuery('delete from base_sys_user where departmentId in (?)', [ids]); } else { const topDepartment = await this.baseSysDepartmentEntity.createQueryBuilder().where('parentId is null').getOne(); if (topDepartment) { - await this.nativeQuery('update base_sys_user a set a.departmentId = ? where a.departmentId in (?)', [ topDepartment.id, ids ]); + await this.nativeQuery('update base_sys_user a set a.departmentId = ? where a.departmentId in (?)', [topDepartment.id, ids]); } } } diff --git a/src/app/modules/base/service/sys/log.ts b/src/app/modules/base/service/sys/log.ts index 5999c93..789263f 100644 --- a/src/app/modules/base/service/sys/log.ts +++ b/src/app/modules/base/service/sys/log.ts @@ -6,7 +6,8 @@ import { Context } from 'egg'; import * as _ from 'lodash'; import { BaseSysLogEntity } from '../../entity/sys/log'; import * as moment from 'moment'; -import { Helper } from '../../../../extend/helper'; +import { Utils } from '../../../../comm/utils'; +import { BaseSysConfService } from './conf'; /** * 描述 @@ -17,31 +18,34 @@ export class BaseSysLogService extends BaseService { @Inject() ctx: Context; - // @Inject() - // helper: Helper; + @Inject() + utils: Utils; @InjectEntityModel(BaseSysLogEntity) baseSysLogEntity: Repository; + @Inject() + baseSysConfService: BaseSysConfService; + /** * 记录 * @param url URL地址 * @param params 参数 * @param userId 用户ID */ - async record(url, params, userId) { - // const ip = await this.helper.getReqIP(this.ctx); - // const sysLog = new BaseSysLogEntity(); - // sysLog.userId = userId; - // sysLog.ip = ip; - // const ipAddrArr = new Array(); - // for (const e of ip.split(',')) ipAddrArr.push(await this.ctx.helper.getIpAddr(e)); - // sysLog.ipAddr = ipAddrArr.join(','); - // sysLog.action = url; - // if (!_.isEmpty(params)) { - // sysLog.params = JSON.stringify(params); - // } - // await this.baseSysLogEntity.insert(sysLog); + async record(context: Context, url, params, userId) { + const ip = await this.utils.getReqIP(context) + const sysLog = new BaseSysLogEntity(); + sysLog.userId = userId; + sysLog.ip = typeof ip === 'string' ? ip : ip.join(','); + const ipAddrArr = new Array(); + for (const e of sysLog.ip.split(',')) ipAddrArr.push(await await this.utils.getIpAddr(context, e)); + sysLog.ipAddr = ipAddrArr.join(','); + sysLog.action = url; + if (!_.isEmpty(params)) { + sysLog.params = JSON.stringify(params); + } + await this.baseSysLogEntity.insert(sysLog); } /** @@ -53,12 +57,12 @@ export class BaseSysLogService extends BaseService { await this.baseSysLogEntity.clear(); return; } - const keepDay = await this.ctx.service.sys.conf.getValue('logKeep'); + const keepDay = await this.baseSysConfService.getValue('logKeep'); if (keepDay) { - const beforeDate = `${moment().subtract(keepDay, 'days').format('YYYY-MM-DD')} 00:00:00`; + const beforeDate = `${moment().add(-keepDay, 'days').format('YYYY-MM-DD')} 00:00:00`; await this.baseSysLogEntity.createQueryBuilder() .where('createTime < :createTime', { createTime: beforeDate }) - await this.nativeQuery(' delete from sys_log where createTime < ? ', [beforeDate]); + await this.nativeQuery(' delete from base_sys_log where createTime < ? ', [beforeDate]); } else { await this.baseSysLogEntity.clear(); } diff --git a/src/app/modules/base/service/sys/login.ts b/src/app/modules/base/service/sys/login.ts index 14a43d2..6d66af1 100644 --- a/src/app/modules/base/service/sys/login.ts +++ b/src/app/modules/base/service/sys/login.ts @@ -48,21 +48,26 @@ export class BaseSysLoginService extends BaseService { */ async login(login: LoginDTO) { const { username, captchaId, verifyCode, password } = login; + // 校验验证码 const checkV = await this.captchaCheck(captchaId, verifyCode); if (checkV) { const user = await this.baseSysUserEntity.findOne({ username }); + // 校验用户 if (user) { + // 校验用户状态及密码 if (user.status === 0 || user.password !== md5(password)) { throw new CoolCommException('账户或密码不正确~'); } } else { throw new CoolCommException('账户或密码不正确~'); } + // 校验角色 const roleIds = await this.baseSysRoleService.getByUser(user.id); if (_.isEmpty(roleIds)) { throw new CoolCommException('该用户未设置任何角色,无法登录~'); } + // 生成token const { expire, refreshExpire } = this.coolConfig.jwt.token; const result = { expire, @@ -71,12 +76,13 @@ export class BaseSysLoginService extends BaseService { refreshToken: await this.generateToken(user, roleIds, refreshExpire, true), }; + // 将用户相关信息保存到缓存 const perms = await this.baseSysMenuService.getPerms(roleIds); const departments = await this.baseSysDepartmentService.getByRoleIds(roleIds, user.username === 'admin'); await this.coolCache.set(`admin:department:${user.id}`, JSON.stringify(departments)); await this.coolCache.set(`admin:perms:${user.id}`, JSON.stringify(perms)); - await this.coolCache.set(`admin:token:${user.id}`, result.token, expire); - await this.coolCache.set(`admin:token:refresh:${user.id}`, result.token, refreshExpire); + await this.coolCache.set(`admin:token:${user.id}`, result.token); + await this.coolCache.set(`admin:token:refresh:${user.id}`, result.token); return result; } else { @@ -162,12 +168,29 @@ export class BaseSysLoginService extends BaseService { try { const decoded = jwt.verify(token, this.coolConfig.jwt.secret); if (decoded && decoded['isRefresh']) { - return jwt.sign(decoded, + delete decoded['exp']; + delete decoded['iat']; + + const { expire, refreshExpire } = this.coolConfig.jwt.token; + decoded['isRefresh'] = false; + const result = { + expire, + token: jwt.sign(decoded, + this.coolConfig.jwt.secret, { + expiresIn: expire, + }), + refreshExpire, + refreshToken: '', + }; + decoded['isRefresh'] = true; + result.refreshToken = jwt.sign(decoded, this.coolConfig.jwt.secret, { - expiresIn: this.coolConfig.jwt.token.expire, + expiresIn: refreshExpire, }); + return result; } } catch (err) { + console.log(err); this.ctx.status = 401; this.ctx.body = { code: RESCODE.COMMFAIL, diff --git a/src/app/modules/base/service/sys/menu.ts b/src/app/modules/base/service/sys/menu.ts index f658468..a867e18 100644 --- a/src/app/modules/base/service/sys/menu.ts +++ b/src/app/modules/base/service/sys/menu.ts @@ -38,6 +38,16 @@ export class BaseSysMenuService extends BaseService { return menus; } + /** + * 修改之后 + * @param param + */ + async modifyAfter(param) { + if (param.id) { + await this.refreshPerms(param.id); + } + } + /** * 根据角色获得权限信息 * @param {[]} roleIds 数组 diff --git a/src/app/modules/base/service/sys/param.ts b/src/app/modules/base/service/sys/param.ts new file mode 100644 index 0000000..0cd3390 --- /dev/null +++ b/src/app/modules/base/service/sys/param.ts @@ -0,0 +1,61 @@ +import { Inject, Provide } from '@midwayjs/decorator'; +import { BaseService, CoolCache } from 'midwayjs-cool-core'; +import { InjectEntityModel } from '@midwayjs/orm'; +import { Repository } from 'typeorm'; +import { BaseSysParamEntity } from '../../entity/sys/param'; + +/** + * 参数配置 + */ +@Provide() +export class BaseSysParamService extends BaseService { + + @InjectEntityModel(BaseSysParamEntity) + baseSysParamEntity: Repository; + + @Inject('cool:cache') + coolCache: CoolCache; + + /** + * 根据key获得对应的参数 + * @param key + */ + async dataByKey (key) { + let result = await this.coolCache.get(`param:${ key }`); + if (result) { + result = JSON.parse(result); + if (result.dataType !== 0) { + return JSON.parse(result.data); + } else { + return result.data; + } + } + return; + } + + /** + * 根据key获得对应的网页数据 + * @param key + */ + async htmlByKey (key) { + let html = '@content'; + let result = await this.coolCache.get(`param:${ key }`); + if (result) { + result = JSON.parse(result); + html = html.replace('@content', result.data); + } else { + html = html.replace('@content', 'key notfound'); + } + return html; + } + + /** + * 重新初始化缓存 + */ + async modifyAfter () { + const params = await this.baseSysParamEntity.find(); + for (const param of params) { + await this.coolCache.set(`param:${ param.keyName }`, JSON.stringify(param)); + } + } +} \ No newline at end of file diff --git a/src/app/modules/base/service/sys/perms.ts b/src/app/modules/base/service/sys/perms.ts index 4718aed..753f045 100644 --- a/src/app/modules/base/service/sys/perms.ts +++ b/src/app/modules/base/service/sys/perms.ts @@ -3,9 +3,10 @@ import { BaseService, CoolCache } from 'midwayjs-cool-core'; import { BaseSysMenuService } from './menu'; import { BaseSysRoleService } from './role'; import { BaseSysDepartmentService } from './department'; +import { Context } from 'egg'; /** - * 描述 + * 权限 */ @Provide() export class BaseSysPermsService extends BaseService { @@ -21,6 +22,9 @@ export class BaseSysPermsService extends BaseService { @Inject() baseSysDepartmentService: BaseSysDepartmentService; + + @Inject() + ctx: Context; /** @@ -29,11 +33,11 @@ export class BaseSysPermsService extends BaseService { */ async refreshPerms(userId) { const roleIds = await this.baseSysRoleService.getByUser(userId); - const perms = await this.ctx.service.sys.menu.getPerms(roleIds); - await this.coolCache.set(`admin:perms:${userId}`, JSON.stringify(perms), this.app.config.token.expires); + const perms = await this.baseSysMenuService.getPerms(roleIds); + await this.coolCache.set(`admin:perms:${userId}`, JSON.stringify(perms)); // 更新部门权限 const departments = await this.baseSysDepartmentService.getByRoleIds(roleIds, this.ctx.admin.username === 'admin'); - await this.coolCache.set(`admin:department:${userId}`, JSON.stringify(departments), this.app.config.token.expires); + await this.coolCache.set(`admin:department:${userId}`, JSON.stringify(departments)); } /** diff --git a/src/app/modules/base/service/sys/user.ts b/src/app/modules/base/service/sys/user.ts index 87b771d..e0aacca 100644 --- a/src/app/modules/base/service/sys/user.ts +++ b/src/app/modules/base/service/sys/user.ts @@ -1,8 +1,13 @@ -import { Provide } from '@midwayjs/decorator'; -import { BaseService } from 'midwayjs-cool-core'; +import { Inject, Provide } from '@midwayjs/decorator'; +import { BaseService, CoolCache, CoolCommException } from 'midwayjs-cool-core'; import { InjectEntityModel } from '@midwayjs/orm'; import { Repository } from 'typeorm'; import { BaseSysUserEntity } from '../../entity/sys/user'; +import { BaseSysPermsService } from './perms'; +import * as _ from 'lodash'; +import { BaseSysUserRoleEntity } from '../../entity/sys/user_role'; +import * as md5 from 'md5'; +import { BaseSysDepartmentEntity } from '../../entity/sys/department'; /** * 系统用户 @@ -13,6 +18,46 @@ export class BaseSysUserService extends BaseService { @InjectEntityModel(BaseSysUserEntity) baseSysUserEntity: Repository; + @InjectEntityModel(BaseSysUserRoleEntity) + baseSysUserRoleEntity: Repository; + + @InjectEntityModel(BaseSysDepartmentEntity) + baseSysDepartmentEntity: Repository; + + @Inject('cool:cache') + coolCache: CoolCache; + + @Inject() + baseSysPermsService: BaseSysPermsService; + + /** + * 分页查询 + * @param query + */ + async page(query) { + const { keyWord, status, departmentIds = '' } = query; + const permsDepartmentArr = await this.baseSysPermsService.departmentIds(this.ctx.admin.userId); // 部门权限 + const sql = ` + SELECT + a.id,a.name,a.nickName,a.headImg,a.email,a.remark,a.status,a.createTime,a.updateTime,a.username,a.phone,a.departmentId, + GROUP_CONCAT(c.name) AS roleName, + d.name as departmentName + FROM + base_sys_user a + LEFT JOIN base_sys_user_role b ON a.id = b.userId + LEFT JOIN base_sys_role c ON b.roleId = c.id + LEFT JOIN base_sys_department d on a.departmentId = d.id + WHERE 1 = 1 + ${this.setSql(!_.isEmpty(departmentIds), 'and a.departmentId in (?)', [departmentIds])} + ${this.setSql(status, 'and a.status = ?', [status])} + ${this.setSql(keyWord, 'and (a.name LIKE ? or a.username LIKE ?)', [`%${keyWord}%`, `%${keyWord}%`])} + ${this.setSql(true, 'and a.username != ?', ['admin'])} + ${this.setSql(this.ctx.admin.username !== 'admin', 'and a.departmentId in (?)', [!_.isEmpty(permsDepartmentArr) ? permsDepartmentArr : [null]])} + GROUP BY a.id + `; + return this.sqlRenderPage(sql, query); + } + /** * 移动部门 * @param departmentId @@ -21,7 +66,7 @@ export class BaseSysUserService extends BaseService { async move(departmentId, userIds) { await this.baseSysUserEntity.createQueryBuilder() .update().set({ departmentId }) - .where('id =: (:userIds)', { userIds }) + .where('id in (:userIds)', { userIds }) .execute(); } @@ -31,4 +76,115 @@ export class BaseSysUserService extends BaseService { async person() { return await this.baseSysUserEntity.findOne({ id: this.ctx.admin.userId }) } + + /** + * 更新用户角色关系 + * @param user + */ + async updateUserRole(user) { + if (user.username === 'admin') { + throw new CoolCommException('非法操作~'); + } + await this.baseSysUserRoleEntity.delete({ userId: user.id }); + if (user.roleIdList) { + for (const roleId of user.roleIdList) { + await this.baseSysUserRoleEntity.save({ userId: user.id, roleId }); + } + } + await this.baseSysPermsService.refreshPerms(user.id); + } + + /** + * 新增 + * @param param + */ + async add(param) { + const exists = await this.baseSysUserEntity.findOne({ username: param.username }); + if (!_.isEmpty(exists)) { + throw new CoolCommException('用户名已经存在~'); + } + param.password = md5('123456'); // 默认密码 建议未改密码不能登陆 + await this.baseSysUserEntity.save(param); + await this.updateUserRole(param); + return param.id; + } + + /** + * 根据ID获得信息 + * @param id + */ + public async info (id) { + const info = await this.baseSysUserEntity.findOne({ id }); + const userRoles = await this.nativeQuery('select a.roleId from base_sys_user_role a where a.userId = ?', [ id ]); + const department = await this.baseSysDepartmentEntity.findOne({ id: info.departmentId }); + if (info) { + delete info.password; + if (userRoles) { + info.roleIdList = userRoles.map(e => { + return parseInt(e.roleId); + }); + } + } + delete info.password; + if (department) { + info.departmentName = department.name; + } + return info; + } + + /** + * 修改个人信息 + * @param param + */ + public async personUpdate (param) { + param.id = this.ctx.admin.userId; + if (!_.isEmpty(param.password)) { + param.password = md5(param.password); + const userInfo = await this.baseSysUserEntity.findOne({ id: param.id }); + if (!userInfo) { + throw new CoolCommException('用户不存在'); + } + param.passwordV = userInfo.passwordV + 1; + await this.coolCache.set(`admin:passwordVersion:${param.id}`, param.passwordV); + } else { + delete param.password; + } + await this.baseSysUserEntity.save(param); + } + + /** + * 修改 + * @param param 数据 + */ + async update(param) { + if (param.id && param.username === 'admin') { + throw new CoolCommException('非法操作~'); + } + if (!_.isEmpty(param.password)) { + param.password = md5(param.password); + const userInfo = await this.ctx.repo.sys.User.findOne({ id: param.id }); + if (!userInfo) { + throw new CoolCommException('用户不存在'); + } + param.passwordV = userInfo.passwordV + 1; + await this.coolCache.set(`admin:passwordVersion:${param.id}`, param.passwordV); + } else { + delete param.password; + } + if (param.status === 0) { + await this.forbidden(param.id); + } + await this.baseSysUserEntity.save(param); + await this.updateUserRole(param); + } + + /** + * 禁用用户 + * @param userId + */ + async forbidden(userId) { + await this.coolCache.del(`admin:token:${userId}`); + } + + } \ No newline at end of file diff --git a/src/config/config.default.ts b/src/config/config.default.ts index e1d48a8..e2a884f 100644 --- a/src/config/config.default.ts +++ b/src/config/config.default.ts @@ -74,6 +74,12 @@ export default (appInfo: EggAppInfo) => { } } + // 文件上传 + config.multipart = { + fileSize: '100mb', + mode: 'file' + }; + // 将egg日志替换成midway config.midwayFeature = { replaceEggLogger: true