修改代码格式;

数据库查询加 lean 判断;
其它内容微调。
This commit is contained in:
liangtongchuan
2020-08-27 20:01:40 +08:00
parent 940879016f
commit c53db8634d
17 changed files with 710 additions and 323 deletions
+2 -2
View File
@@ -8,5 +8,5 @@ export const ENCRYPT_KEY = 'fiqaxijabbantusmprc234fj';
export const AUTH_SMS_CNT_PER_DAY = 8;
export const COUNTER = {
UID: 'uid'
}
UID: 'uid',
};
+10 -10
View File
@@ -4,14 +4,14 @@ import { GameModel } from '../db/Game';
import { Controller } from 'egg';
export default class GameController extends Controller {
public async getServerList() {
const { ctx } = this;
const { serverType } = ctx.request.body;
let serverList: Array<any> = await GameModel.getServerListByType(serverType);
if (serverList && serverList.length > 0) {
ctx.body = {status: STATUS_SUC.code, data: { serverList }};
} else {
ctx.body = ctx.service.utils.exceptionResult(SERVER_NOT_FOUND);
}
public async getServerList() {
const { ctx } = this;
const { serverType } = ctx.request.body;
const serverList: Array<any> = await GameModel.getServerListByType(serverType);
if (serverList && serverList.length > 0) {
ctx.body = { status: STATUS_SUC.code, data: { serverList } };
} else {
ctx.body = ctx.service.utils.exceptionResult(SERVER_NOT_FOUND);
}
}
}
}
+5 -5
View File
@@ -3,13 +3,13 @@ import { prop, pre } from '@typegoose/typegoose';
/**
* BaseModel
*/
@pre<BaseModel>('save', function (next) {
@pre<BaseModel>('save', function(next) {
if (!this.createdAt || this.isNew) {
this.createdAt = this.updatedAt = new Date()
this.createdAt = this.updatedAt = new Date();
} else {
this.updatedAt = new Date()
this.updatedAt = new Date();
}
next()
next();
})
export default class BaseModel {
@@ -21,4 +21,4 @@ export default class BaseModel {
@prop()
updatedAt: Date
}
}
+9 -9
View File
@@ -2,21 +2,21 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop } from '@typegoose/typegoose';
/**
* 短信字段接口
* 自增 ID
*/
@index({ name: 1 })
export default class Counter extends BaseModel {
@prop({ required: true })
name: string;
@prop({ required: true })
name: string;
@prop({ required: true, default: 1 })
seq: number;
@prop({ required: true, default: 1 })
seq: number;
public static async getNewCounter(name: string) {
const counter = await CounterModel.findOneAndUpdate({name}, {$inc: {seq: 1}}, {new: true, upsert: true}).lean();
return counter?.seq;
}
public static async getNewCounter(name: string, lean = true) {
const counter = await CounterModel.findOneAndUpdate({ name }, { $inc: { seq: 1 } }, { new: true, upsert: true }).lean(lean);
return counter?.seq;
}
}
+37 -33
View File
@@ -3,68 +3,72 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop } from '@typegoose/typegoose';
class ServerInfo {
@prop({ required: true})
name: string;
@prop({ required: true })
name: string;
@prop({ required: true})
host: string;
@prop({ required: true })
host: string;
@prop({ required: false})
port: number;
@prop({ required: false })
port: number;
@prop({ required: true})
status: number;
@prop({ required: true })
status: number;
@prop({ required: true})
createTime: Date;
@prop({ required: true })
createTime: Date;
@prop({ required: true})
serverType: string;
@prop({ required: true })
serverType: string;
}
/**
* 用户字段接口
* 游戏字段接口
*/
@index({ id: 1 })
export default class Game extends BaseModel {
@prop({ required: true})
@prop({ required: true })
id: number;
@prop({ required: true})
@prop({ required: true })
name: string;
@prop({ required: true})
@prop({ required: true })
nameEn: string;
@prop({ required: true})
@prop({ required: true })
des: string;
@prop({ required: true})
@prop({ required: true })
serverList: Array<ServerInfo>;
@prop({ required: true})
@prop({ required: true })
iconUrl: string;
@prop({ required: true})
@prop({ required: true })
version: string;
@prop({ required: true})
@prop({ required: true })
versionCode: number;
public static async getServerListByType(serverType: string) {
let game = await GameModel.findOne().lean();
if (!game) {
const serverInfo: ServerInfo = {name: '常山少年', host: 'pinus_test.trgame.cn', port: 3014, status: 1, createTime: new Date(), serverType: 'official'};
const iconUrl = `https://download.tgamebox.cn/avatar/${APP_ID}/1.png`;
game = await GameModel.findOneAndUpdate({}, {id: 1, name: '赵云传', nameEn: 'zyz', des: '牛逼的战棋', iconUrl, version: '0.0.1', versionCode: 1, $push: {serverList: serverInfo}}, {upsert: true, new: true}).lean();
}
let serverList: Array<ServerInfo> = game ? game.serverList : [];
serverList = serverList.filter(item => { return item.serverType === serverType; })
return serverList;
let game = await GameModel.findOne().lean();
if (!game) {
const serverInfo: ServerInfo = { name: '常山少年', host: 'pinus_test.trgame.cn', port: 3014, status: 1, createTime: new Date(), serverType: 'official' };
const iconUrl = `https://download.tgamebox.cn/avatar/${APP_ID}/1.png`;
game = await GameModel.findOneAndUpdate(
{},
{ id: 1, name: '赵云传', nameEn: 'zyz', des: '牛逼的战棋', iconUrl, version: '0.0.1', versionCode: 1, $push: { serverList: serverInfo } },
{ upsert: true, new: true },
).lean();
}
console.log(serverType, game);
let serverList: Array<ServerInfo> = game ? game.serverList : [];
serverList = serverList.filter(item => { return item.serverType === serverType; });
console.log(serverType, serverList);
return serverList;
}
//#endregion
}
export const GameModel = getModelForClass(Game);
export const GameModel = getModelForClass(Game);
+42 -40
View File
@@ -8,55 +8,57 @@ const moment = require('moment');
@index({ tel: 1 })
export default class Sms extends BaseModel {
@prop({ required: true })
tel: string;
@prop({ required: true })
tel: string;
@prop({ required: true })
telHash: string;
@prop({ required: true })
telHash: string;
@prop({ required: true })
code: string;
@prop({ required: true })
code: string;
@prop({ required: true })
used: boolean;
@prop({ required: true })
used: boolean;
@prop({ required: true })
updateTime: Date;
@prop({ required: true })
updateTime: Date;
@prop({ required: true })
countToday: number;
@prop({ required: true })
countToday: number;
public static async findByTel(tel: string) {
let sms = await smsModel.findOne({ tel }).lean();
return sms;
public static async findByTel(tel: string, lean = true) {
const sms = await smsModel.findOne({ tel }).lean(lean);
return sms;
}
public static async updateByTel(tel: string, code: string, used: boolean, updateTime: Date, countToday: number, lean = true) {
await smsModel.findOneAndUpdate({ tel }, { code, used, updateTime, countToday }, { upsert: true }).lean(lean);
}
public static async validateSms(tel: string, code: string, lean = true) {
const record = await smsModel.findOneAndUpdate({ tel, code, used: false }, { used: true }).lean(lean);
return !!record;
}
public async timeLimit(interval: number) {
if (Date.now() > this.updateTime.getTime() + interval) {
return false;
}
return true;
}
public static async updateByTel(tel: string, code: string, used: boolean, updateTime: Date, countToday: number) {
await smsModel.findOneAndUpdate({tel}, {code, used, updateTime, countToday}, {upsert: true});
public async cntLimit(cnt: number) {
console.log('hasSendToday:', this.hasSendToday());
if (await this.hasSendToday() && this.countToday >= cnt) {
return true;
}
return false;
}
public static async validateSms(tel: string, code: string) {
const record = await smsModel.findOneAndUpdate({tel, code, used: false}, {used: true});
return !!record;
}
public async timeLimit(interval: number) {
if (this.updateTime.getTime() > Date.now() - interval) {
return true;
}
return false;
}
public async cntLimit(cnt: number) {
if (this.hasSendToday() && this.countToday >= cnt) {
return true;
}
return false;
}
public async hasSendToday() {
return moment(this.updateTime).format("YYYY-MM-DD") === moment(Date.now()).format("YYYY-MM-DD");
}
public async hasSendToday() {
console.log(moment(this.updateTime).format('YYYY-MM-DD'), moment(Date.now()).format('YYYY-MM-DD'));
return moment(this.updateTime).format('YYYY-MM-DD') === moment(Date.now()).format('YYYY-MM-DD');
}
}
export const smsModel = getModelForClass(Sms);
export const smsModel = getModelForClass(Sms);
+22 -27
View File
@@ -10,70 +10,65 @@ import { index, getModelForClass, prop } from '@typegoose/typegoose';
@index({ uid: 1 })
export default class User extends BaseModel {
@prop({ required: true})
@prop({ required: true })
uid: number;
@prop({ required: true})
@prop({ required: true })
username: string;
@prop({ required: true})
@prop({ required: true })
token: string;
@prop({ required: true})
@prop({ required: true })
tel: string;
@prop({ required: true})
@prop({ required: true })
telHash: string;
@prop({ required: true})
@prop({ required: true })
lastLoginTime: Date;
@prop({ required: true})
@prop({ required: true })
createTime: Date;
// 平台:ios, android, web, pc
@prop({ required: true})
@prop({ required: true })
platform: string;
@prop({ required: true})
@prop({ required: true })
pkgName: string;
// 服务器类型:official, channel, ios, oversea
@prop({ required: true})
@prop({ required: true })
serverType: string;
public static async createUser() {
}
public static async updateToken(tel: string, token: string, platform: string, pkgName: string, serverType: string) {
let user = await UserModel.findOne({tel}).lean();
public static async updateToken(tel: string, token: string, platform: string, pkgName: string, serverType: string, lean = true) {
let user = await UserModel.findOne({ tel }).lean();
const curTime: Date = new Date();
let update = {};
if (!user) {
const uid = await CounterModel.getNewCounter(COUNTER.UID);
update = Object.assign(update, {platform, pkgName, serverType, createTime: curTime, uid, username: `用户${uid}`});
update = Object.assign(update, { platform, pkgName, serverType, createTime: curTime, uid, username: `用户${uid}` });
}
update = Object.assign(update, {token, lastLoginTime: curTime});
user = await UserModel.findOneAndUpdate({tel}, update, {upsert: true, new: true}).lean();
update = Object.assign(update, { token, lastLoginTime: curTime });
user = await UserModel.findOneAndUpdate({ tel }, update, { upsert: true, new: true }).lean(lean);
return user;
}
public static async findUserByToken(token: string) {
const user = await UserModel.findOne({token}).select('uid token').lean();
public static async findUserByToken(token: string, lean = true) {
const user = await UserModel.findOne({ token }).select('uid token').lean(lean);
return user;
}
public static async findUserByTel(tel: string) {
const user = await UserModel.findOne({tel}).select('uid tel').lean();
public static async findUserByTel(tel: string, lean = true) {
const user = await UserModel.findOne({ tel }).select('uid tel').lean(lean);
return user;
}
public static async findUserByUid(uid: number) {
const user = await UserModel.findOne({uid}).select('uid tel').lean();
public static async findUserByUid(uid: number, lean = true) {
const user = await UserModel.findOne({ uid }).select('uid tel').lean(lean);
return user;
}
//#endregion
}
export const UserModel = getModelForClass(User);
export const UserModel = getModelForClass(User);
+14 -12
View File
@@ -5,14 +5,14 @@ const isJSON = require('koa-is-json');
function aesEncrypt(data, key, iv) {
const cipher = crypto.createCipheriv('aes-192-cbc', key, iv);
var crypted = cipher.update(data, 'utf8', 'hex');
let crypted = cipher.update(data, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
}
function aesDecrypt(data, key, iv) {
const decipher = crypto.createDecipheriv('aes-192-cbc', key, iv);
var decrypted = decipher.update(data, 'hex', 'utf8');
let decrypted = decipher.update(data, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
@@ -20,29 +20,31 @@ function aesDecrypt(data, key, iv) {
module.exports = options => {
return async function parmsDecode(ctx: Context, next) {
if (options.threshold && ctx.length < options.threshold) return;
let reqBody = ctx.request.body;
if (!reqBody.data) return;
const reqBody = ctx.request.body;
if (isJSON(reqBody)) {
let encodeStr = aesEncrypt(JSON.stringify(reqBody), ENCRYPT_KEY, ENCRYPT_IV);
const encodeStr = aesEncrypt(JSON.stringify(reqBody), ENCRYPT_KEY, ENCRYPT_IV);
console.log(`encoded str: ${encodeStr}`);
}
if (!reqBody.data) return;
let decodeStr = aesDecrypt(reqBody.data, ENCRYPT_KEY, ENCRYPT_IV);
const decodeStr = aesDecrypt(reqBody.data, ENCRYPT_KEY, ENCRYPT_IV);
ctx.logger.debug('decoded str:', decodeStr);
try {
ctx.request.body = JSON.parse(decodeStr);
console.log('req body', ctx.request.body);
} catch (e) {
console.error('parms parse err');
}
await next();
let resBody = ctx.body;
const resBody = ctx.body;
console.log('return value:', resBody);
if (isJSON(resBody)) {
ctx.body = {result: aesEncrypt(JSON.stringify(resBody), ENCRYPT_KEY, ENCRYPT_IV)};
ctx.body = { result: aesEncrypt(JSON.stringify(resBody), ENCRYPT_KEY, ENCRYPT_IV) };
} else {
ctx.body = {result: aesEncrypt(JSON.stringify({status: 3, data: 'internal err'}), ENCRYPT_KEY, ENCRYPT_IV)};
ctx.body = { result: aesEncrypt(JSON.stringify({ status: 3, data: 'internal err' }), ENCRYPT_KEY, ENCRYPT_IV) };
}
}
}
};
};
+15 -14
View File
@@ -1,19 +1,20 @@
import { STATUS_TOKEN_ERR, STATUS_WRONG_PARMS } from './../../../shared/statusCode';
import { UserModel } from './../db/User';
import { Context } from 'egg';
module.exports = () => {
return async function tokenParser(ctx: Context, next) {
if (!ctx.request.body || !ctx.request.body.token) {
ctx.body = ctx.service.utils.exceptionResult(STATUS_WRONG_PARMS);
return;
}
const user = await UserModel.findUserByToken(ctx.request.body.token);
if (!user) {
console.log('token invalid');
ctx.body = ctx.service.utils.exceptionResult(STATUS_TOKEN_ERR);
return;
}
await next();
return async function tokenParser(ctx, next) {
if (!ctx.request.body || !ctx.request.body.token) {
console.error('token not found');
ctx.body = ctx.service.utils.exceptionResult(STATUS_WRONG_PARMS);
return;
}
}
const user = await UserModel.findUserByToken(ctx.request.body.token);
if (!user) {
console.error('token invalid');
ctx.body = ctx.service.utils.exceptionResult(STATUS_TOKEN_ERR);
return;
}
await next();
};
};
+83 -72
View File
@@ -9,84 +9,95 @@ const _ = require('underscore');
*/
export default class Auth extends Service {
public checkTelNo(telNo) {
if (!_.isString(telNo)) {
return {status: 1, data: '参数类型错误'};
}
if (telNo.length !== 11) {
return {status: 1, data: '手机号长度错误'};
}
return {status: 0, data: '手机号合法'};
public checkTelNo(telNo) {
if (!_.isString(telNo)) {
return { status: 1, data: '参数类型错误' };
}
if (telNo.length !== 11) {
return { status: 1, data: '手机号长度错误' };
}
return { status: 0, data: '手机号合法' };
}
async sendSmsCodeByGuodu(tel, code) {
const ctx = this.ctx;
const url = `http://221.179.172.68:8000/QxtSms/QxtFirewall?OperID=bantu3&OperPass=c8XcTffG&DesMobile=${tel}&Content=${encodeURIComponent(`【同人游戏】验证码${code},您正在登录赵云传,若非本人操作,请勿泄露`)}&Content_Code=1`;
const result = await ctx.curl(url, {
method: 'GET',
});
return result.data;
}
testLimit(sms, interval) {
if (sms.updateTime.getTime() > Date.now() - interval) {
return true;
}
return false;
}
/**
* 用户获取手机验证码
* @param telNo - 用户手机号
*/
public async getSms(tel: string) {
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify;
}
async sendSmsCodeByGuodu(tel, code) {
const ctx = this.ctx;
let url = `http://221.179.172.68:8000/QxtSms/QxtFirewall?OperID=bantu3&OperPass=c8XcTffG&DesMobile=${tel}&Content=${encodeURIComponent(`【同人游戏】验证码${code},您正在登录赵云传,若非本人操作,请勿泄露`)}&Content_Code=1`
const result = await ctx.curl(url, {
method: 'GET',
});
return result.data;
const sms = await smsModel.findByTel(tel, false);
if (sms) {
if (await sms.timeLimit(10000)) {
return this.ctx.service.utils.exceptionResult(SMS_IN_60S);
}
if (await sms.cntLimit(8)) {
return this.ctx.service.utils.exceptionResult(SMS_CNT_LIMIT);
}
}
/**
* 用户获取手机验证码
* @param telNo - 用户手机号
*/
public async getSms(tel: string) {
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify;
}
let sms = await smsModel.findByTel(tel);
if (!!sms) {
if (sms.timeLimit(60000)) {
return this.ctx.service.utils.exceptionResult(SMS_IN_60S);
}
if (sms.cntLimit(8)) {
return this.ctx.service.utils.exceptionResult(SMS_CNT_LIMIT);
}
}
let code: string = '';
if (!sms || !sms.used) {
code = this.ctx.service.utils.generateNum(6);
} else {
code = sms.code;
}
await this.sendSmsCodeByGuodu(tel, code);
await smsModel.updateByTel(tel, code, false, new Date(), sms?.hasSendToday() ? sms.countToday + 1 : 1);
return this.ctx.service.utils.exceptionResult(STATUS_SUC);
let code = '';
if (!sms || !sms.used) {
code = this.ctx.service.utils.generateNum(6);
} else {
code = sms.code;
}
/**
* 用户获取到手机验证码之后发送验证登录请求
* @param telNo 登录手机号
* @param code 登录验证码
*/
public async smsLogin(tel: string, code: string, platform: string, pkgName: string, serverType: string) {
const ctx = this.ctx;
// 参数检查
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify;
}
if (!_.isString(code) || code.length !== 6) {
return ctx.service.utils.exceptionResult(STATUS_WRONG_PARMS);
}
const smsResult = await this.sendSmsCodeByGuodu(tel, code);
console.log(smsResult);
await smsModel.updateByTel(tel, code, false, new Date(), sms?.hasSendToday() ? sms.countToday + 1 : 1);
return this.ctx.service.utils.exceptionResult(STATUS_SUC);
}
// 手机验证码核验
const smsValid: boolean = await smsModel.validateSms(tel, code);
if (!smsValid) {
return ctx.service.utils.exceptionResult(SMS_INVALID);
}
// 用户注册登录
const token = ctx.service.utils.generateStr(256);
const user = await UserModel.updateToken(tel, token, platform, pkgName, serverType);
return {status: STATUS_SUC, data: { token, uid: user?.uid }};
/**
* 用户获取到手机验证码之后发送验证登录请求
* @param tel 登录手机号
* @param code 登录验证码
* @param platform 平台
* @param pkgName 包名
* @param serverType 服务器类型
*/
public async smsLogin(tel: string, code: string, platform: string, pkgName: string, serverType: string) {
const ctx = this.ctx;
// 参数检查
const telVerify = this.checkTelNo(tel);
if (telVerify.status !== 0) {
return telVerify;
}
if (!_.isString(code) || code.length !== 6) {
return ctx.service.utils.exceptionResult(STATUS_WRONG_PARMS);
}
// 手机验证码核验
const smsValid: boolean = await smsModel.validateSms(tel, code);
if (!smsValid) {
return ctx.service.utils.exceptionResult(SMS_INVALID);
}
// 用户注册登录
const token = ctx.service.utils.generateStr(256);
const user = await UserModel.updateToken(tel, token, platform, pkgName, serverType);
return { status: STATUS_SUC, data: { token, uid: user?.uid } };
}
}
+73 -72
View File
@@ -6,81 +6,82 @@ const crypto = require('crypto');
*/
export default class TurboCore extends Service {
/**
* 用户获取手机验证码
* @param telNo - 用户手机号
*/
/**
* 用户获取手机验证码
* @param telNo - 用户手机号
*/
public async getSms(telNo: string) {
const ctx = this.ctx;
let body = {
telNo
};
const result = await ctx.curl(`${TURBO_CORE_URL}/user/getSms`, {
method: 'POST',
contentType: 'json',
headers: {
'AppId': APP_ID,
'sign': this.getTurboSign( body, TURBO_PARM_SECRET)
},
data: body,
dataType: 'json',
});
return result.data;
}
public async getSms(telNo: string) {
const ctx = this.ctx;
const body = {
telNo,
};
const result = await ctx.curl(`${TURBO_CORE_URL}/user/getSms`, {
method: 'POST',
contentType: 'json',
headers: {
AppId: APP_ID,
sign: this.getTurboSign(body, TURBO_PARM_SECRET),
},
data: body,
dataType: 'json',
});
return result.data;
}
/**
* 用户获取到手机验证码之后发送验证登录请求
* @param telNo 登录手机号
* @param code 登录验证码
*/
public async smsLogin(telNo: string, code: string) {
const ctx = this.ctx;
let body = {
telNo, code
};
const result = await ctx.curl(`${TURBO_CORE_URL}/user/getSms`, {
method: 'POST',
contentType: 'json',
headers: {
'AppId': APP_ID,
'sign': this.getTurboSign( body, TURBO_PARM_SECRET)
},
data: body,
dataType: 'json',
});
return result.data;
}
/**
* 用户获取到手机验证码之后发送验证登录请求
* @param telNo 登录手机号
* @param code 登录验证码
*/
public async smsLogin(telNo: string, code: string) {
const ctx = this.ctx;
const body = {
telNo, code,
};
const result = await ctx.curl(`${TURBO_CORE_URL}/user/getSms`, {
method: 'POST',
contentType: 'json',
headers: {
AppId: APP_ID,
sign: this.getTurboSign(body, TURBO_PARM_SECRET),
},
data: body,
dataType: 'json',
});
return result.data;
}
/**
* 获取多宝规则下的参数签名
* @param params 参数列表
* @param secret 密钥
*/
private getTurboSign(params, secret) {
let paramsString = this.joinParamsStr(params);
let stringToSign = paramsString;
if (secret) {
stringToSign = `${stringToSign}&secret=${secret}`;
return crypto.createHmac('sha256', secret)
.update(stringToSign)
.digest('hex');
} else {
return null;
}
}
/**
* 获取多宝规则下的参数签名
* @param params 参数列表
* @param secret 密钥
*/
private getTurboSign(params, secret) {
const paramsString = this.joinParamsStr(params);
let stringToSign = paramsString;
/**
* 将参数组合成字符串
* @param params 参数列表
*/
private joinParamsStr(params) {
let signString = Object.keys(params).filter(function (key) {
return params[key] !== undefined && params[key] !== '' && ['pfx', 'partner_key', 'sign', 'key'].indexOf(key) < 0;
}).sort().map(function (key) {
return key + '=' + params[key];
}).join("&");
return signString;
if (secret) {
stringToSign = `${stringToSign}&secret=${secret}`;
return crypto.createHmac('sha256', secret)
.update(stringToSign)
.digest('hex');
}
return null;
}
/**
* 将参数组合成字符串
* @param params 参数列表
*/
private joinParamsStr(params) {
const signString = Object.keys(params).filter(function(key) {
return params[key] !== undefined && params[key] !== '' && [ 'pfx', 'partner_key', 'sign', 'key' ].indexOf(key) < 0;
}).sort()
.map(function(key) {
return key + '=' + params[key];
})
.join('&');
return signString;
}
}
+22 -22
View File
@@ -4,29 +4,29 @@ const csprng = require('csprng');
* Utils Service
*/
export default class Utils extends Service {
/**
* 生成 len 长度的随机字符串
* @param len 长度
* @param radix 基数
*/
public generateStr(len: number, radix: number = 36) {
return csprng(len, radix);
}
/**
* 生成 len 长度的随机字符串
* @param len 长度
* @param radix 基数
*/
public generateStr(len: number, radix = 36) {
return csprng(len, radix);
}
/**
* 生成指定长度的随机数
* @param len 随机数长度
*/
public generateNum(len: number) {
let code = "";
for (let i = 0; i < len; i++) {
code += parseInt(`${Math.random() * 10}`);
}
return code;
/**
* 生成指定长度的随机数
* @param len 随机数长度
*/
public generateNum(len: number) {
let code = '';
for (let i = 0; i < len; i++) {
code += parseInt(`${Math.random() * 10}`);
}
return code;
}
public exceptionResult(status) {
const { code, simStr} = status;
return {status: code, data: simStr};
}
public exceptionResult(status) {
const { code, simStr } = status;
return { status: code, data: simStr };
}
}