删除lib问价夹,发布到npm,以npm引入代码更优雅,去除redis,快速体验

This commit is contained in:
啊平 2019-11-21 17:59:57 +08:00
parent 47ca408f5b
commit 760d867e13
18 changed files with 23 additions and 797 deletions

View File

@ -14,6 +14,14 @@ Node版后台基础框架基于[Egg.js](https://eggjs.org/zh-cn/)(阿里出品)
* 鉴权:**[egg-jwt](https://www.npmjs.com/package/egg-jwt)**
* 网络:**[axios](https://www.npmjs.com/package/axios)**
## 核心组件
独有cool-admin.com发布的npm组件
* 路由:**[egg-cool-router](https://www.npmjs.com/package/egg-cool-router)**
* 控制器:**[egg-cool-controller](https://www.npmjs.com/package/egg-cool-controller)**
* 服务层:**[egg-cool-service](https://www.npmjs.com/package/egg-cool-service)**
* 缓存:**[egg-cool-cache](https://www.npmjs.com/package/egg-cool-cache)**
* 模型:**[egg-cool-entity](https://www.npmjs.com/package/egg-cool-entity)**
## 运行
环境 `Node.js>=8.9.0` `Redis` `mysql`

View File

@ -1,11 +1,9 @@
import { BaseController } from '../lib/base/controller';
import routerDecorator from '../lib/router';
import { Context } from 'egg';
import { BaseController } from 'egg-cool-controller';
import router from 'egg-cool-router';
@routerDecorator.prefix('/user', [ 'add', 'delete', 'update', 'info', 'list', 'page' ])
@router.prefix('/user', [ 'add', 'delete', 'update', 'info', 'list', 'page' ])
export default class User extends BaseController {
constructor (ctx: Context) {
super(ctx);
init() {
this.setEntity(this.ctx.repo.User);
}
}

View File

@ -1,4 +1,4 @@
import { BaseEntity } from '../lib/base/entity';
import { BaseEntity } from 'egg-cool-entity';
import { Entity, Column } from 'typeorm';
@Entity({ name: 'user' })

View File

@ -2,36 +2,5 @@
*
*/
export default class Application {
/**
* redis保存值
* @param key
* @param value
* @param expire 单位:
*/
public static async redisSet (key, value, expire?: any) {
// @ts-ignore
const redis = this.redis;
await redis.set(key, value);
if (expire) {
await redis.expire(key, expire);
}
}
/**
* redis获得值
* @param key
*/
public static async redisGet (key) {
// @ts-ignore
return this.redis.get(key);
}
/**
* redis key
* @param key
*/
public static async redisDel (key) {
// @ts-ignore
return this.redis.del(key);
}
}

View File

@ -1,147 +0,0 @@
import { Controller, Context } from 'egg';
import routerDecorator from '../router';
import { Brackets } from 'typeorm';
// 返回参数配置
interface ResOp {
// 返回数据
data?: any;
// 是否成功
isFail?: boolean;
// 返回码
code?: number;
// 返回消息
message?: string;
}
// 分页参数配置
interface PageOp {
// 模糊查询字段
keyWordLikeFields?: string[];
// where
where?: Brackets;
// 全匹配 "=" 字段
fieldEq?: string[];
// 排序
addOrderBy?: {};
}
/**
*
*/
export abstract class BaseController extends Controller {
protected entity;
protected OpService;
protected pageOption: PageOp;
protected constructor (ctx: Context) {
super(ctx);
this.OpService = this.service.comm.data;
}
/**
*
* @param service
*/
protected setService (service) {
this.OpService = service;
}
/**
*
* @param option
*/
protected setPageOption (option: PageOp) {
this.pageOption = option;
}
/**
*
* @param entity
*/
protected setEntity (entity) {
this.entity = entity;
}
/**
*
*/
@routerDecorator.get('/page')
protected async page () {
const result = await this.OpService.page(this.ctx.query, this.pageOption, this.entity);
this.res({ data: result });
}
/**
*
*/
@routerDecorator.get('/list')
protected async list () {
const result = await this.OpService.list(this.entity);
this.res({ data: result });
}
/**
*
*/
@routerDecorator.get('/info')
protected async info () {
const result = await this.OpService.info(this.ctx.query.id, this.entity);
this.res({ data: result });
}
/**
*
*/
@routerDecorator.post('/add')
protected async add () {
await this.OpService.addOrUpdate(this.ctx.request.body, this.entity);
this.res();
}
/**
*
*/
@routerDecorator.post('/update')
protected async update () {
await this.OpService.addOrUpdate(this.ctx.request.body, this.entity);
this.res();
}
/**
*
*/
@routerDecorator.post('/delete')
protected async delete () {
await this.OpService.delete(this.ctx.request.body.ids, this.entity);
this.res();
}
/**
*
* @param op
*/
protected res (op?: ResOp) {
if (!op) {
this.ctx.body = {
code: 1000,
message: 'success',
};
return;
}
if (op.isFail) {
this.ctx.body = {
code: op.code ? op.code : 1001,
data: op.data,
message: op.message ? op.message : 'fail',
};
} else {
this.ctx.body = {
code: op.code ? op.code : 1000,
message: op.message ? op.message : 'success',
data: op.data,
};
}
}
}

View File

@ -1,14 +0,0 @@
import { PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, Index } from 'typeorm';
// 实体类基类
export abstract class BaseEntity {
// ID
@PrimaryGeneratedColumn({ type: 'bigint' })
id: number;
// 创建时间
@Index()
@CreateDateColumn()
createTime: Date;
// 更新时间
@UpdateDateColumn()
updateTime: Date;
}

View File

@ -1,256 +0,0 @@
import { Service, Context } from 'egg';
import { getManager, getConnection, Brackets } from 'typeorm';
import * as _ from 'lodash';
// 基础配置
const conf = {
size: 15,
errTips: {
noEntity: '未设置操作实体~',
},
};
/**
*
*/
export abstract class BaseService extends Service {
public sqlParams;
public constructor (ctx: Context) {
super(ctx);
this.sqlParams = [];
}
/**
* SQL并获得分页数据
* @param sql sql语句
* @param query
*/
public async sqlRenderPage (sql, query) {
const { size = conf.size, page = 1, order = 'createTime', sort = 'desc' } = query;
if (order && sort) {
if (!await this.paramSafetyCheck(order + sort)) {
throw new Error('非法传参~');
}
sql += ` ORDER BY ${ order } ${ sort }`;
}
this.sqlParams.push((page - 1) * size);
this.sqlParams.push(parseInt(size));
sql += ' LIMIT ?,? ';
let params = [];
params = params.concat(this.sqlParams);
const result = await this.nativeQuery(sql, params);
const countResult = await this.nativeQuery(this.getCountSql(sql), params);
return {
list: result,
pagination: {
page: parseInt(page),
size: parseInt(size),
total: parseInt(countResult[0] ? countResult[0].count : 0),
},
};
}
/**
*
* @param sql
* @param params
*/
public async nativeQuery (sql, params?) {
if (_.isEmpty(params)) {
params = this.sqlParams;
}
let newParams = [];
newParams = newParams.concat(params);
this.sqlParams = [];
return await this.getOrmManager().query(sql, newParams);
}
/**
*
* @param params
*/
public async paramSafetyCheck (params) {
const lp = params.toLowerCase();
return !(lp.indexOf('update') > -1 || lp.indexOf('select') > -1 || lp.indexOf('delete') > -1 || lp.indexOf('insert') > -1);
}
/**
* SQL
* @param sql
*/
public getCountSql (sql) {
sql = sql.toLowerCase();
return `select count(*) as count from (${ sql.split('limit')[0] }) a`;
}
/**
*
* @param entity
* @param query
* @param option
*/
public async page (query, option, entity) {
if (!entity) throw new Error(conf.errTips.noEntity);
const find = await this.getPageFind(query, option, entity);
return this.renderPage(await find.getManyAndCount(), query);
}
/**
*
* @param entity
*/
public async list (entity) {
if (!entity) throw new Error(conf.errTips.noEntity);
return await entity.find();
}
/**
* /
* @param entity
* @param param
*/
public async addOrUpdate (param, entity) {
if (!entity) throw new Error(conf.errTips.noEntity);
if (param.id) {
await entity.update(param.id, param);
} else {
await entity.save(param);
}
}
/**
* ID获得信息
* @param entity
* @param id id
*/
public async info (id, entity) {
if (!entity) throw new Error(conf.errTips.noEntity);
return await entity.findOne({ id });
}
/**
*
* @param entity
* @param ids
*/
public async delete (ids, entity) {
if (!entity) throw new Error(conf.errTips.noEntity);
if (ids instanceof Array) {
await entity.delete(ids);
} else {
await entity.delete(ids.split(','));
}
}
/**
* query
* @param data
* @param query
*/
public renderPage (data, query) {
const { size = conf.size, page = 1 } = query;
return {
list: data[0],
pagination: {
page: parseInt(page),
size: parseInt(size),
total: data[1],
},
};
}
/**
*
* @param entity
* @param query
* @param option
*/
public getPageFind (query, option, entity) {
let { size = conf.size, page = 1, order = 'createTime', sort = 'desc', keyWord = '' } = query;
const find = entity
.createQueryBuilder()
.take(parseInt(size))
.skip(String((page - 1) * size));
if (option) {
// 默认条件
if (option.where) {
find.where(option.where);
}
// 附加排序
if (!_.isEmpty(option.addOrderBy)) {
for (const key in option.addOrderBy) {
find.addOrderBy(key, option.addOrderBy[key].toUpperCase());
}
}
// 关键字模糊搜索
if (keyWord) {
keyWord = `%${ keyWord }%`;
find.andWhere(new Brackets(qb => {
const keyWordLikeFields = option.keyWordLikeFields;
for (let i = 0; i < option.keyWordLikeFields.length; i++) {
qb.orWhere(`${ keyWordLikeFields[i] } like :keyWord`, { keyWord });
}
}));
}
// 字段全匹配
if (!_.isEmpty(option.fieldEq)) {
for (const key of option.fieldEq) {
const c = {};
if (query[key]) {
c[key] = query[key];
find.andWhere(`${ key } = :${ key }`, c);
}
}
}
}
// 接口请求的排序
if (sort && order) {
find.addOrderBy(order, sort.toUpperCase());
}
return find;
}
/**
* sql
* @param condition
* @param sql sql语句
* @param params
*/
protected setSql (condition, sql, params?: any[]) {
let rSql = false;
if (condition || (condition === 0 && condition !== '')) {
rSql = true;
this.sqlParams = this.sqlParams.concat(params);
}
return rSql ? sql : '';
}
/**
*
*/
public getContext () {
return this.ctx;
}
/**
* ORM操作对象
*/
public getRepo () {
return this.ctx.repo;
}
/**
* ORM管理
*/
public getOrmManager () {
return getManager();
}
/**
* ORM连接类
*/
public getOrmConnection () {
return getConnection();
}
}

View File

@ -1,8 +0,0 @@
export interface Config {
resolver?: (...args: any[]) => string | number;
ttl?: number; // 缓存过期时间
url?: string; // url包含改前缀才缓存 如api请求时缓存 admin请求时不缓存
}
export declare function Cache(config?: Config): (target: object, propertyName: string, propertyDesciptor: PropertyDescriptor) => PropertyDescriptor;
export declare function ClearCache();

View File

@ -1,67 +0,0 @@
"use strict";
const DEFAULT_TTL = 600;
const REDIS_PRE = 'cache';
const _ = require('lodash');
const {Repository} = require('typeorm');
Object.defineProperty(exports, "__esModule", {
value: true
});
function Cache(config) {
if (config === void 0) {
config = {};
}
return function (target, name, propertyDesciptor) {
let prop = propertyDesciptor.value ? "value" : "get";
let originalFunction = propertyDesciptor[prop];
propertyDesciptor[prop] = async function () {
let args = [];
for (let _i = 0; _i < arguments.length; _i++) {
if (!(arguments[_i] instanceof Repository)){
args[_i] = arguments[_i];
}
}
const url = this.ctx.url;
if (config.url && _.startsWith(url, config.url) === false) {
return await originalFunction.apply(this, args)
}
let key = REDIS_PRE + ':' + target.pathName + `.${name}` + (config.resolver ?
config.resolver.apply(this, args) :
JSON.stringify(args).split(':').join('='));
const cacheValue = await this.app.redisGet(key);
if (!_.isEmpty(cacheValue)) {
return JSON.parse(cacheValue).data
} else {
let result = await originalFunction.apply(this, args);
let data = {
data: result
};
this.ctx.app.redisSet(key, JSON.stringify(data), config.ttl ? config.ttl : DEFAULT_TTL);
return result
}
};
return propertyDesciptor
};
}
exports.Cache = Cache;
function ClearCache() {
return function (target, name, propertyDesciptor) {
let prop = propertyDesciptor.value ? "value" : "get";
propertyDesciptor[prop] = async function () {
const key = REDIS_PRE + ':' + target.pathName + '*';
const keys = await this.ctx.app.redis.keys(key);
if (!_.isEmpty(keys)) {
keys.forEach(key => {
this.ctx.app.redisDel(key)
});
}
};
return propertyDesciptor
};
}
exports.ClearCache = ClearCache;

View File

@ -1,66 +0,0 @@
import { Application } from 'egg';
import { Middleware } from 'koa';
/** http装饰器方法类型 */
declare type HttpFunction = (url: string, ...beforeMiddlewares: Middleware[]) => any;
declare class RouterDecorator {
get: HttpFunction;
post: HttpFunction;
patch: HttpFunction;
del: HttpFunction;
options: HttpFunction;
put: HttpFunction;
/**
* class的prefix以及相关中间件
*
* @private
* @static
* @type {ClassPrefix}
* @memberof RouterDecorator
*/
private static __classPrefix__;
/**
* routerUrl的路由配置
*
* @private
* @static
* @type {Router}
* @memberof RouterDecorator
*/
private static __router__;
constructor ();
/** 推入路由配置 */
private __setRouter__;
/**
* Controller class的工厂函数
* controller添加prefix
*
* @param {string} prefixUrl
* @param {...Middleware[]} beforeMiddlewares
* @param {[]} baseFn pageaddupdatedeleteinfolist
* @returns
* @memberof RouterDecorator
*/
prefix (prefixUrl: string, baseFn?: any[], ...beforeMiddlewares: Middleware[]): (targetControllerClass: any) => any;
/**
*
*
* @export
* @param {Application} app eggApp实例
* @param {string} [options={ prefix: '' }] { prefix: '/api' }
*/
static initRouter (app: Application, options?: {
prefix: string;
}): void;
}
/** 暴露注册路由方法 */
export declare const initRouter: typeof RouterDecorator.initRouter;
declare const _default: RouterDecorator;
/** 暴露实例的prefix和http的各个方法 */
export default _default;

View File

@ -1,135 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", {value: true});
const _ = require('lodash');
const tslib_1 = require("tslib");
/** http方法名 */
const HTTP_METHODS = ['get', 'post', 'patch', 'del', 'options', 'put'];
let baseControllerArr = [];
class RouterDecorator {
constructor() {
HTTP_METHODS.forEach(httpMethod => {
this[httpMethod] = (url, ...beforeMiddlewares) => (target, name) => {
const routerOption = {
httpMethod,
beforeMiddlewares,
handlerName: name,
constructorFn: target.constructor,
className: target.constructor.name,
url: url
};
if (target.constructor.name === 'BaseController') {
baseControllerArr.push(routerOption)
} else {
this.__setRouter__(url, routerOption);
}
};
});
}
/** 推入路由配置 */
__setRouter__(url, routerOption) {
RouterDecorator.__router__[url] = RouterDecorator.__router__[url] || [];
RouterDecorator.__router__[url].push(routerOption);
}
/**
* 装饰Controller class的工厂函数
* 为一整个controller添加prefix
* 可以追加中间件
* @param {string} prefixUrl
* @param {...Middleware[]} beforeMiddlewares
* @param {any[]} baseFn
* @returns 装饰器函数
* @memberof RouterDecorator
*/
prefix(prefixUrl, baseFn = [], ...beforeMiddlewares) {
return function (targetControllerClass) {
RouterDecorator.__classPrefix__[targetControllerClass.name] = {
prefix: prefixUrl,
beforeMiddlewares: beforeMiddlewares,
baseFn: baseFn,
target: targetControllerClass
};
return targetControllerClass;
};
}
/**
* 注册路由
* 路由信息是通过装饰器收集的
* @export
* @param {Application} app eggApp实例
* @param {string} [options={ prefix: '' }] 举例 { prefix: '/api' }
*/
static initRouter(app, options = {prefix: ''}) {
let addUrl = [];
Object.keys(RouterDecorator.__router__).forEach(url => {
RouterDecorator.__router__[url].forEach((opt) => {
const controllerPrefixData = RouterDecorator.__classPrefix__[opt.className] || {
prefix: '',
beforeMiddlewares: [],
baseFn: [],
target: {}
};
let fullUrl = `${options.prefix}${controllerPrefixData.prefix}${url}`;
console.log(`>>>>>>>>custom register URL * ${opt.httpMethod.toUpperCase()} ${fullUrl} * ${opt.className}.${opt.handlerName}`);
if (!addUrl.includes(fullUrl)) {
app.router[opt.httpMethod](fullUrl, ...controllerPrefixData.beforeMiddlewares, ...opt.beforeMiddlewares, (ctx) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const ist = new opt.constructorFn(ctx);
yield ist[opt.handlerName](ctx);
}));
addUrl.push(fullUrl);
}
});
});
// 通用方法
const cArr = [].concat(_.uniq(baseControllerArr));
Object.keys(RouterDecorator.__classPrefix__).forEach(cl => {
const controllerPrefixData = RouterDecorator.__classPrefix__[cl] || {
prefix: '',
beforeMiddlewares: [],
baseFn: [],
target: {}
};
const setCArr = cArr.filter(c => {
if (RouterDecorator.__classPrefix__[cl].baseFn.includes(c.url.replace('/', ''))) {
return c;
}
});
setCArr.forEach(cf => {
let fullUrl = `${options.prefix}${controllerPrefixData.prefix}${cf.url}`;
console.log(`>>>>>>>>comm register URL * ${cf.httpMethod.toUpperCase()} ${fullUrl} * ${cl}.${cf.handlerName}`);
app.router[cf.httpMethod](fullUrl, ...controllerPrefixData.beforeMiddlewares, ...cf.beforeMiddlewares, (ctx) => tslib_1.__awaiter(this, void 0, void 0, function* () {
const ist = new controllerPrefixData.target(ctx);
yield ist[cf.handlerName](ctx);
}));
});
});
}
}
/**
* 记录各个class的prefix以及相关中间件
* 最后统一设置
* @private
* @static
* @type {ClassPrefix}
* @memberof RouterDecorator
*/
RouterDecorator.__classPrefix__ = {};
/**
* 记录各个routerUrl的路由配置
* 最后统一设置
* @private
* @static
* @type {Router}
* @memberof RouterDecorator
*/
RouterDecorator.__router__ = {};
/** 暴露注册路由方法 */
exports.initRouter = RouterDecorator.initRouter;
/** 暴露实例的prefix和http的各个方法 */
exports.default = new RouterDecorator();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBb0NBLGNBQWM7QUFDZCxNQUFNLFlBQVksR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFLdkUsTUFBTSxlQUFlO0lBNkJqQjtRQUNJLFlBQVksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDOUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBVyxFQUFFLEdBQUcsaUJBQStCLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBVyxFQUFFLElBQVksRUFBRSxFQUFFO2dCQUNsRyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRTtvQkFDcEIsVUFBVTtvQkFDVixpQkFBaUI7b0JBQ2pCLFdBQVcsRUFBRSxJQUFJO29CQUNqQixhQUFhLEVBQUUsTUFBTSxDQUFDLFdBQVc7b0JBQ2pDLFNBQVMsRUFBRSxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUk7aUJBQ3JDLENBQUMsQ0FBQztZQUNQLENBQUMsQ0FBQTtRQUNMLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQztJQUVELGFBQWE7SUFDTCxhQUFhLENBQUUsR0FBVyxFQUFFLFlBQTBCO1FBQzFELGVBQWUsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsZUFBZSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEUsZUFBZSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ksTUFBTSxDQUFFLFNBQWlCLEVBQUUsR0FBRyxpQkFBK0I7UUFDaEUsT0FBTyxVQUFVLHFCQUFxQjtZQUNsQyxlQUFlLENBQUMsZUFBZSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxHQUFHO2dCQUMxRCxNQUFNLEVBQUUsU0FBUztnQkFDakIsaUJBQWlCLEVBQUUsaUJBQWlCO2FBQ3ZDLENBQUM7WUFDRixPQUFPLHFCQUFxQixDQUFDO1FBQ2pDLENBQUMsQ0FBQTtJQUNMLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsVUFBVSxDQUFFLEdBQWdCLEVBQUUsT0FBTyxHQUFHLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRTtRQUNoRSxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDbEQsZUFBZSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFpQixFQUFFLEVBQUU7Z0JBQzFELE1BQU0sb0JBQW9CLEdBQUcsZUFBZSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLGlCQUFpQixFQUFFLEVBQUUsRUFBRSxDQUFDO2dCQUNySCxNQUFNLE9BQU8sR0FBRyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsb0JBQW9CLENBQUMsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDO2dCQUN4RSxPQUFPLENBQUMsR0FBRyxDQUFDLHVDQUF1QyxHQUFHLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxJQUFJLE9BQU8sTUFBTSxHQUFHLENBQUMsU0FBUyxJQUFJLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO2dCQUNwSSxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxPQUFPLEVBQUUsR0FBRyxvQkFBb0IsQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFPLEdBQUcsRUFBRSxFQUFFO29CQUNuSCxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ3ZDLE1BQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDcEMsQ0FBQyxDQUFBLENBQUMsQ0FBQztZQUNQLENBQUMsQ0FBQyxDQUFBO1FBQ04sQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDOztBQTlFRDs7Ozs7OztHQU9HO0FBQ1ksK0JBQWUsR0FBZ0IsRUFBRSxDQUFBO0FBRWhEOzs7Ozs7O0dBT0c7QUFDWSwwQkFBVSxHQUFXLEVBQUUsQ0FBQTtBQStEMUMsZUFBZTtBQUNGLFFBQUEsVUFBVSxHQUFHLGVBQWUsQ0FBQyxVQUFVLENBQUM7QUFFckQsNEJBQTRCO0FBQzVCLGtCQUFlLElBQUksZUFBZSxFQUFFLENBQUMifQ==

View File

@ -1,5 +1,5 @@
import { Application } from 'egg';
import { initRouter } from '../app/lib/router';
import { initRouter } from 'egg-cool-router';
export default (app: Application) => {
initRouter(app);

View File

@ -1,4 +1,4 @@
import { BaseService } from '../../lib/base/service';
import { BaseService } from 'egg-cool-service';
/**
*

View File

@ -1,4 +1,4 @@
import { BaseService } from '../../lib/base/service';
import { BaseService } from 'egg-cool-service';
import * as moment from 'moment';
import * as uuid from 'uuid/v1';
import axios from 'axios';

View File

@ -1,46 +0,0 @@
import { BaseService } from '../../lib/base/service';
import * as uuid from 'uuid/v1';
import * as svgCaptcha from 'svg-captcha';
import * as svgToDataURL from 'svg-to-dataurl';
/**
* Service
*/
export default class Verify extends BaseService {
/**
* svg验证码 30
* @param params type验证码类型<img src=""/>,src下直接赋值type值为 dataUrl
*/
public async captcha (params) {
const { type, width = 150, height = 50 } = params;
svgCaptcha.options.width = width;
svgCaptcha.options.height = height;
const svg = svgCaptcha.create({ color: true, background: '#fff' });
const result = {
captchaId: uuid(),
data: svg.data.replace(/\"/g, "'"),
};
if (type === 'dataUrl') {
result.data = svgToDataURL(result.data);
}
await this.app.redisSet(`verify:img:${ result.captchaId }`, svg.text.toLowerCase(), 1800);
return result;
}
/**
*
* @param captchaId ID
* @param value
*/
public async check (captchaId, value) {
const rv = await this.app.redisGet(`verify:img:${ captchaId }`);
if (!rv || !value || value.toLowerCase() !== rv) {
return false;
} else {
this.app.redisDel(`verify:img:${ captchaId }`);
return true;
}
}
}

View File

@ -52,14 +52,6 @@ export default (appInfo: EggAppInfo) => {
whitelist,
};
config.redis = {
client: {
port: 6379,
host: '127.0.0.1',
password: '',
db: 0,
},
};
// 新增特殊的业务配置
const bizConfig = {
sourceUrl: `https://github.com/eggjs/examples/tree/master/${ appInfo.name }`

View File

@ -13,10 +13,6 @@ const plugin: EggPlugin = {
enable: true,
package: 'egg-oss',
},
redis: {
enable: true,
package: 'egg-redis',
},
};
export default plugin;

View File

@ -27,16 +27,18 @@
"egg": "^2.6.1",
"egg-jwt": "^3.1.6",
"egg-oss": "^2.0.0",
"egg-redis": "^2.4.0",
"egg-scripts": "^2.6.0",
"egg-ts-typeorm": "^1.1.12",
"egg-cool-cache": "^1.2.4",
"egg-cool-controller": "^1.2.4",
"egg-cool-entity": "^1.2.3",
"egg-cool-router": "^1.2.2",
"egg-cool-service": "^1.2.2",
"ipip-ipdb": "^0.3.0",
"lodash": "^4.17.15",
"md5": "^2.2.1",
"moment": "^2.24.0",
"mysql": "^2.17.1",
"svg-captcha": "^1.4.0",
"svg-to-dataurl": "^1.0.0"
"mysql": "^2.17.1"
},
"devDependencies": {
"@types/mocha": "^2.2.40",