Commit ac28fa9d by largezhou

Merge branch 'test' into 'master' (merge request !3)

验证码,错误锁定等
parents ed852d23 93023e5c
node_modules/
app/config/localsettings.js
*.sh
\ No newline at end of file
app/front/entry/public/
......@@ -22,6 +22,12 @@ class ProductAPI extends APIBase {
let rs = await this.productpriceS.findRegionsByProductName(pname, sp)
return system.getResult(rs);
}
async findProductInfoForFt(p, q, req) {
let pname = p.productname;
let region = p.region;
let rs = await this.productpriceS.findProductInfoForFt(pname, region)
return system.getResult(rs);
}
classDesc() {
return {
groupName: "auth",
......
......@@ -6,24 +6,25 @@ const CtlBase = require("../../ctl.base");
class UserCtl extends CtlBase {
constructor() {
super("auth", CtlBase.getServiceName(UserCtl));
this.captchaSve = system.getObject("service.auth.captchaSve");
}
async logout(pobj, qobj, req) {
async logout (pobj, qobj, req) {
let rtn = await this.service.logout(pobj)
return system.getResult(rtn)
}
async pmgetUserByCode(pobj, qobj, req) {
async pmgetUserByCode (pobj, qobj, req) {
let code = pobj.code
let rtn = await this.service.pmgetUserByCode(code)
return system.getResult(rtn)
}
async loginApp(pobj, qobj, req) {
async loginApp (pobj, qobj, req) {
let appkey = pobj.fromAppKey
let uname = pobj.username
let rtn = await this.service.loginApp(appkey, uname)
return system.getResult(rtn);
}
async resetPassword(pobj, qobj, req) {
async resetPassword (pobj, qobj, req) {
try {
await this.service.resetPassword(req.xctx.username, pobj.onepassword)
return system.getResult({});
......@@ -31,15 +32,18 @@ class UserCtl extends CtlBase {
return system.getResult(null, err.message)
}
}
async allowOrNot(pobj, qobj, req) {
async allowOrNot (pobj, qobj, req) {
await this.service.updateByWhere({ isEnabled: !pobj.isEnabled }, { company_id: pobj.company_id })
return system.getResult({});
}
async allowOrNotToOne(pobj, qobj, req) {
async allowOrNotToOne (pobj, qobj, req) {
if (!pobj.isEnabled) {
await this.service.cacheManager["LoginTimesCache"].invalidate(pobj.userName)
}
await this.service.updateByWhere({ isEnabled: !pobj.isEnabled }, { id: pobj.curid })
return system.getResult({});
}
async initNewInstance(queryobj, req) {
async initNewInstance (queryobj, req) {
var rtn = {};
rtn.roles = [];
return system.getResultSuccess(rtn);
......@@ -50,11 +54,11 @@ class UserCtl extends CtlBase {
// let v = await this.smsS.sendVCode(mobile);
// return system.getResult({ vcodestr: v });
// }
async exit(pobj, qobj, req) {
async exit (pobj, qobj, req) {
}
//应用的自由用户注册,无需验证,需要前端头设置公司KEY
async pmregisterByFreeUser(p, q, req) {
async pmregisterByFreeUser (p, q, req) {
//检查是否有用户名和密码
if (!pobj.userName || !pobj.password) {
return system.getResult(null, "请检查用户名和密码是否存在")
......@@ -68,7 +72,7 @@ class UserCtl extends CtlBase {
return rtn;
}
async create(p, q, req) {
async create (p, q, req) {
//检查是否有用户名和密码
if (!p.userName) {
return system.getResult(null, "请检查用户名和密码是否存在")
......@@ -81,7 +85,7 @@ class UserCtl extends CtlBase {
//和租户绑定同一家公司
//按照用户名和密码进行注册
//控制器端检查用户名和密码非空
async registerByTantent(p, q, req) {
async registerByTantent (p, q, req) {
//检查是否有用户名和密码
if (!pobj.userName) {
return system.getResult(null, "请检查用户名和密码是否存在")
......@@ -90,7 +94,7 @@ class UserCtl extends CtlBase {
return rtn;
}
//租户用户名和密码的租户注册
async pmregister(pobj, qobj, req) {
async pmregister (pobj, qobj, req) {
//平台注册设置平台的应用ID
pobj.app_id = settings.pmappid;
//检查是否有用户名和密码
......@@ -100,19 +104,46 @@ class UserCtl extends CtlBase {
var rtn = await this.service.pmregister(pobj);
return system.getResult(rtn);
}
async pmlogin(pobj, qobj, req) {
async pmlogin (pobj, qobj, req) {
//平台注册设置平台的应用ID
let verifyres = await this.captchaSve.apiValidator({key:pobj.key,code:pobj.code});
if (verifyres.status !== 0)
return verifyres;
let rtn = await this.service.pmlogin(pobj, qobj, req);
return system.getResult(rtn);
let msg = null
if (!rtn) {//登录错误
let times = await this.service.cacheManager["LoginTimesCache"].incrAsync(pobj.userName);
if (times >= 4) {
await this.service.updateByWhere({ isEnabled: false }, { userName: pobj.userName })
msg = "登录超过4次失败,您的账户已被锁定,请联系管理员解锁."
}
} else {
await this.service.cacheManager["LoginTimesCache"].invalidate(pobj.userName)
}
return system.getResult(rtn, msg);
}
/**
* 重置密码
* @param {*} pobj
* @param {*} qobj
* @param {*} req
*/
async unlockUser (pobj, qobj, req) {
try {
await this.service.unlockUser(pobj.userName)
return system.getResult({});
} catch (err) {
return system.getResult(null, err.message)
}
}
async getUserInfo(pobj, qobj, req) {
async getUserInfo (pobj, qobj, req) {
let uname = req.xctx.username;
let rtn = await this.service.getUserInfo(uname);
return system.getResult(rtn);
}
//按照电话创建自由用户
async pmloginByVCodeForFreeUser(p, q, req) {
async pmloginByVCodeForFreeUser (p, q, req) {
if (!pobj.mobile || !pobj.vcode) {
return system.getResult(null, "请检查手机号和验证码是否存在")
}
......@@ -123,11 +154,11 @@ class UserCtl extends CtlBase {
let rtn = await this.service.pmloginByVCodeForFreeUser(p, q);
return rtn;
}
async pmloginByVCode(pobj, qobj, req) {
async pmloginByVCode (pobj, qobj, req) {
let rtn = await this.service.pmloginByVCode(pobj, qobj);
return system.getResult(rtn);
}
async pmSendVCode(pobj, qobj, req) {
async pmSendVCode (pobj, qobj, req) {
let rtn = await this.service.sendVCode(pobj, qobj);
return system.getResult(rtn);
}
......
......@@ -7,60 +7,79 @@ const CtlBase = require("../../ctl.base");
class CompanyCtl extends CtlBase {
constructor() {
super("common", CtlBase.getServiceName(CompanyCtl));
this.userSve = system.getObject("service.auth.userSve");
}
async update(p,q,req){
let u= await super.update(p,q,req)
async update(p, q, req) {
let u = await super.update(p, q, req)
//缓存失效
await this.cacheManager["CompanyCache"].invalidate(p.companykey)
let company=await this.cacheManager["CompanyCache"].cache(p.companykey)
let company = await this.cacheManager["CompanyCache"].cache(p.companykey)
return system.getResult(company)
}
async getMyApps(p,q,req){
async getMyApps(p, q, req) {
let userfind = await this.cacheManager["UserCache"].cache(p.username)
let isSuper=userfind.isSuper
if(userfind.company.appids && userfind.company.appids!=""){
let appsarray=userfind.company.appids.split(",")
let appidsquery=appsarray.map(astr=>{
let isSuper = userfind.isSuper
if (userfind.company.appids && userfind.company.appids != "") {
let appsarray = userfind.company.appids.split(",")
let appidsquery = appsarray.map(astr => {
return astr.split("|")[0]
})
let apps=await this.service.getMyApps(appidsquery,isSuper)
let apps = await this.service.getMyApps(appidsquery, isSuper)
return system.getResult(apps)
}else{
} else {
return []
}
}
async bindApps(p,q,req){
let appids=p.appids
let cmpid=p.postcmpid
let appids2=appids.map(item=>{
return item.appid+"|"+item.title
async bindApps(p, q, req) {
let appids = p.appids
let cmpid = p.postcmpid
let appids2 = appids.map(item => {
return item.appid + "|" + item.title
})
let appidstrs=appids2.join(",")
await this.service.bindApps(appidstrs,cmpid)
let appidstrs = appids2.join(",")
await this.service.bindApps(appidstrs, cmpid)
return system.getResult(appids)
}
async setOrgs(p,q,req){
async setOrgs(p, q, req) {
//let companynew=await this.service.findById(p.company_id)
let orgs=await this.service.setOrgs(p)
let orgs = await this.service.setOrgs(p)
return system.getResult(orgs)
}
async getOrgs(p,q,req){
async getOrgs(p, q, req) {
//let companynew=await this.cacheManager["CompanyCache"].cache(req.xctx.fromcompanykey)
let companynew=await this.service.findById(p.company_id)
let orgjsonstr=companynew.orgJson
let rtnjson=null
if(orgjsonstr && orgjsonstr!=""){
rtnjson=JSON.parse(companynew.orgJson)
}else{
rtnjson=[]
let companynew = await this.service.findById(p.company_id);
const userData = await this.userSve.findById(p.userid);
let orgjsonstr = companynew.orgJson;
let rtnjson = null;
if (orgjsonstr && orgjsonstr != "") {
rtnjson = JSON.parse(companynew.orgJson);
} else {
rtnjson = [];
}
if (userData) {
if (userData.isAdmin || userData.isSuper) {
return system.getResult({orgJson: rtnjson});
} else {
return system.getResult({orgJson: this.service.buildOrgs(rtnjson, userData.ptags)});
}
return system.getResult({orgJson:rtnjson})
} else {
return system.getResult({orgJson: []});
}
}
async getWatchOrgNodes(p, q, req) {
return await this.service.getWatchOrgNodes(p.company_id);
}
async refQuery(pobj, qobj, req) {
let rtn=await this.service.refQuery(pobj);
let rtn = await this.service.refQuery(pobj);
return rtn
}
}
module.exports = CompanyCtl;
var system = require("../../../system")
const http = require("http")
const querystring = require('querystring');
var settings = require("../../../../config/settings");
const CtlBase = require("../../ctl.base");
class PushCtl extends CtlBase {
constructor() {
super("common", CtlBase.getServiceName(PushCtl));
}
async findAndCountAll(pobj, qobj, req) {
let query = {
pageSize: pobj.pageInfo.pageSize,
pageIndex: pobj.pageInfo.pageNo
};
let search = pobj.search;
if (search.messageBody)
query.messageBody = search.messageBody;
if (search.identify_code)
query.identifyCode = search.identify_code;
if (search.request_id)
query.requestIdInfo = search.request_id;
let actionType;
switch (pobj.bizpath) {
case "/sysmag/pushfail":
actionType = "getPushFailureList";
break;
case "/sysmag/pusherror":
actionType = "getPushErrorList";
break
}
let rtn = await system.postJsonTypeReq(settings.pushUrl(), {
"actionType": actionType,
"actionBody": query
});
if (rtn.statusCode === 200) {
rtn = rtn.data;
if (rtn && rtn.status === 1) {
return system.getResult({
results: {
count: rtn.totalCount,
rows: rtn && rtn.data || []
}
});
} else {
return system.getResultFail(rtn && rtn.message || '请联系管理员');
}
} else {
return system.getResultFail(rtn)
}
}
async repush(pobj, qobj, req) {
let rtn = await system.postJsonTypeReq(settings.pushUrl(), {
"actionType": "pushAgainFailureLog",
"actionBody": {
id: pobj.id
}
});
if (rtn.statusCode === 200) {
return rtn.data;
} else {
return system.getResultFail(rtn)
}
}
}
module.exports = PushCtl;
const CacheBase = require("../cache.base");
const system = require("../../system");
const settings = require("../../../config/settings");
class LoginTimesCache extends CacheBase {
constructor() {
super();
}
isdebug() {
return false;
}
desc() {
return "缓存登录错误次数信息";
}
prefix() {
return "g_login_times_:"
}
async buildCacheVal(cachekey, inputkey, val, ex, ...items) {
if (val) {
return val;
}
return null;
}
async incrAsync(key) {
let cachekey = this.prefix + key
let cache = await this.getCache(key);
if (!cache) {
await this.cache(key, "0", 60)
}
return this.redisClient.incr(cachekey)
}
}
module.exports = LoginTimesCache;
\ No newline at end of file
......@@ -8,7 +8,7 @@ class UserCache extends CacheBase {
this.channelDao = system.getObject("db.common.channelDao");
}
isdebug() {
return settings.env == "dev";
return settings.env == "localhost";
}
desc() {
return "缓存本地应用对象";
......@@ -19,7 +19,7 @@ class UserCache extends CacheBase {
async buildCacheVal(cachekey, inputkey, val, ex, ...items) {
const configValue = await this.userDao.model.findAll({
where: { userName: inputkey, app_id: settings.pmappid, isEnabled: true },
attributes: ['id', 'userName', 'nickName', 'headUrl', 'jwtkey', 'jwtsecret', 'created_at', 'isSuper', 'isAdmin', 'isAllocated', 'mail', 'mobile', 'opath', 'ptags'],
attributes: ['id', 'userName', 'nickName', 'headUrl', 'jwtkey', 'jwtsecret', 'created_at', 'isSuper', 'isAdmin', 'isAllocated', 'mail', 'mobile', 'opath', 'ptags','tx_uin'],
include: [
{ model: this.db.models.company, attributes: ['id', 'name', 'companykey', 'appids', "code"], raw: true },
{ model: this.db.models.role, as: "Roles", attributes: ["id", "code"], }
......
......@@ -10,19 +10,20 @@ class VCodeCache extends CacheBase {
// isdebug() {
// return settings.env == "dev";
// }
desc() {
desc () {
return "缓存给手机发送的验证码60妙";
}
prefix() {
prefix () {
return "g_vcode_cm:"
}
async buildCacheVal(cachekey, inputkey, val, ex, ...items) {
async buildCacheVal (cachekey, inputkey, val, ex, ...items) {
//inputkey采用appkey_mobile的形式
var mobile = inputkey;
var tmplCode = val;
var signName = items ? items[0] : "";
var vcode = await this.smsUtil.getUidStr(6, 10);
if (!tmplCode && !signName) {
console.log("=============================")
this.smsUtil.sendMsg(mobile, vcode);
} //tmplCode为发送短信编码,需在阿里开通,signName为短信头描述信息,二者没有传递则用默认的发送验证码
else {
......
......@@ -9,10 +9,10 @@ class Dao {
this.model = db.models[this.modelName];
console.log(this.modelName);
}
preCreate(u) {
preCreate (u) {
return u;
}
async create(u, t) {
async create (u, t) {
var u2 = this.preCreate(u);
if (t) {
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
......@@ -26,10 +26,10 @@ class Dao {
});
}
}
static getModelName(ClassObj) {
static getModelName (ClassObj) {
return ClassObj["name"].substring(0, ClassObj["name"].lastIndexOf("Dao")).toLowerCase()
}
async refQuery(qobj) {
async refQuery (qobj) {
var w = qobj.refwhere ? qobj.refwhere : {};
if (qobj.levelinfo) {
w[qobj.levelinfo.levelfield] = qobj.levelinfo.level;
......@@ -48,7 +48,7 @@ class Dao {
return this.model.findAll({ where: w, attributes: qobj.fields });
}
}
async bulkDelete(ids, t) {
async bulkDelete (ids, t) {
if (t) {
var en = await this.model.destroy({ where: { id: { [this.db.Op.in]: ids } }, transaction: t });
return en;
......@@ -58,7 +58,7 @@ class Dao {
}
}
async bulkDeleteByWhere(whereParam, t) {
async bulkDeleteByWhere (whereParam, t) {
var en = null;
if (t != null && t != 'undefined') {
whereParam.transaction = t;
......@@ -67,7 +67,7 @@ class Dao {
return await this.model.destroy(whereParam);
}
}
async delete(qobj, t) {
async delete (qobj, t) {
var en = null
if (t != null && t != 'undefined') {
en = await this.model.findOne({ where: { id: qobj.id }, transaction: t });
......@@ -83,14 +83,14 @@ class Dao {
}
return null;
}
extraModelFilter(pobj) {
extraModelFilter (pobj) {
//return {"key":"include","value":{model:this.db.models.app}};
return null;
}
extraWhere(obj, where) {
extraWhere (obj, where) {
return where;
}
orderBy(qobj) {
orderBy (qobj) {
//return {"key":"include","value":{model:this.db.models.app}};
if (!qobj.orderInfo || qobj.orderInfo.length == 0) {
return [["created_at", "DESC"]];
......@@ -99,15 +99,17 @@ class Dao {
}
}
buildQuery(qobj) {
buildQuery (qobj) {
var linkAttrs = [];
const pageNo = qobj.pageInfo.pageNo;
const pageSize = qobj.pageInfo.pageSize;
const search = qobj.search;
var qc = {};
//设置分页查询条件
if (pageNo != -1) {
qc.limit = pageSize;
qc.offset = (pageNo - 1) * pageSize;
}
//默认的查询排序
qc.order = this.orderBy(qobj);
//构造where条件
......@@ -157,7 +159,7 @@ class Dao {
console.log(qc);
return qc;
}
buildaggs(qobj) {
buildaggs (qobj) {
var aggsinfos = [];
if (qobj.aggsinfo) {
qobj.aggsinfo.sum.forEach(aggitem => {
......@@ -171,7 +173,7 @@ class Dao {
}
return aggsinfos;
}
async findAggs(qobj, qcwhere) {
async findAggs (qobj, qcwhere) {
var aggArray = this.buildaggs(qobj);
if (aggArray.length != 0) {
qcwhere["attributes"] = {};
......@@ -190,7 +192,7 @@ class Dao {
}
}
async findAndCountAll(qobj, t) {
async findAndCountAll (qobj, t) {
var qc = this.buildQuery(qobj);
let findList = {}
let count = await this.findCount({ where: qc.where })
......@@ -203,18 +205,22 @@ class Dao {
rtn.aggresult = aggresult;
return rtn;
}
preUpdate(obj) {
preUpdate (obj) {
return obj;
}
async update(obj, tm) {
async update (obj, tm) {
var obj2 = this.preUpdate(obj);
if (tm != null && tm != 'undefined') {
return this.model.update(obj2, { where: { id: obj2.id }, transaction: tm });
await this.model.update(obj2, { where: { id: obj2.id }, transaction: tm });
let n = await this.model.findOne({ where: { id: obj2.id }, transaction: tm });
return n
} else {
return this.model.update(obj2, { where: { id: obj2.id } });
await this.model.update(obj2, { where: { id: obj2.id } });
let n = await this.model.findById(obj2.id)
return n
}
}
async bulkCreate(ids, t) {
async bulkCreate (ids, t) {
if (t != null && t != 'undefined') {
return await this.model.bulkCreate(ids, { transaction: t });
} else {
......@@ -222,7 +228,7 @@ class Dao {
}
}
async updateByWhere(setObj, whereObj, t) {
async updateByWhere (setObj, whereObj, t) {
let inWhereObj = {}
if (t && t != 'undefined') {
if (whereObj && whereObj != 'undefined') {
......@@ -236,10 +242,10 @@ class Dao {
}
return this.model.update(setObj, inWhereObj);
}
async customExecAddOrPutSql(sql, paras = null) {
async customExecAddOrPutSql (sql, paras = null) {
return this.db.query(sql, paras);
}
async customQuery(sql, paras, t) {
async customQuery (sql, paras, t) {
var tmpParas = null;//||paras=='undefined'?{type: this.db.QueryTypes.SELECT }:{ replacements: paras, type: this.db.QueryTypes.SELECT };
if (t && t != 'undefined') {
if (paras == null || paras == 'undefined') {
......@@ -254,15 +260,15 @@ class Dao {
}
return this.db.query(sql, tmpParas);
}
async findCount(whereObj = null) {
async findCount (whereObj = null) {
return this.model.count(whereObj, { logging: false }).then(c => {
return c;
});
}
async findSum(fieldName, whereObj = null) {
async findSum (fieldName, whereObj = null) {
return this.model.sum(fieldName, whereObj);
}
async getPageList(pageIndex, pageSize, whereObj = null, orderObj = null, attributesObj = null, includeObj = null) {
async getPageList (pageIndex, pageSize, whereObj = null, orderObj = null, attributesObj = null, includeObj = null) {
var tmpWhere = {};
tmpWhere.limit = pageSize;
tmpWhere.offset = (pageIndex - 1) * pageSize;
......@@ -283,20 +289,20 @@ class Dao {
}
return await this.model.findAndCountAll(tmpWhere);
}
async findOne(obj, attributes = []) {
async findOne (obj, attributes = []) {
if (attributes.length > 0) {
return this.model.findOne({ "where": obj, attributes, row: true });
} else {
return this.model.findOne({ "where": obj, row: true });
}
}
async findOneWithTm(obj, t) {
async findOneWithTm (obj, t) {
return this.model.findOne({ "where": obj, transaction: t });
}
async findById(oid) {
async findById (oid) {
return this.model.findById(oid);
}
async findAll(obj, include = [], other = {}) {
async findAll (obj, include = [], other = {}) {
return this.model.findAll({ "where": obj, include, row: true, ...other });
}
}
......
......@@ -101,6 +101,9 @@ class UserDao extends Dao {
w[strq] = { [this.db.Op.like]: "%" + search[lnkKey] + "%" };
}
qc.attributes = {
exclude: ["password", "jwtkey", "jwtsecret"]
}
return w;
}
async preUpdate(u) {
......
......@@ -45,6 +45,9 @@ module.exports = (db, DataTypes) => {
type: DataTypes.BOOLEAN,
defaultValue: false
},
last_change_date: {
type: DataTypes.DATE,
},
isSuper: {
type: DataTypes.BOOLEAN,
defaultValue: false
......@@ -75,6 +78,9 @@ module.exports = (db, DataTypes) => {
type: DataTypes.STRING,
allowNull: true,
},
tx_uin: {
type: DataTypes.STRING,
},
isDelivery: {
type: DataTypes.BOOLEAN,
defaultValue: false
......
const system = require("../../../system");
const ServiceBase = require("../../sve.base");
var settings = require("../../../../config/settings");
const uuidv4 = require('uuid/v4');
var svgCaptcha = require('svg-captcha');
class CaptchaService {
constructor() {
this.redisClient = system.getObject("util.redisClient");
}
async apiGenerate(params) {
var key = uuidv4();
var options = {
size: 4,
noise: 1,
ignoreChars: '0o1iILl'
};
options.width = this.trim(params.width) || 120;
options.height = this.trim(params.height) || 32;
options.background = this.trim(params.background) || "#E8E8E8";
var captchaPrev = this.trim(params.captchaPrev);
var expire = Number(params.expire || 3 * 60)
try {
var cap = svgCaptcha.create(options);
console.log(cap);
await this.redisClient.setWithEx(key, cap.text, expire);
return system.getResultSuccess({
key: key,
text: cap.text,
captcha: cap.data,
});
} catch (error) {
return system.getResult(null, "接口异常:" + error.message);
}
}
async apiValidator(params) {
var key = this.trim(params.key);
var code = this.trim(params.code);
var cacheCode = await this.redisClient.get(key);
if(!cacheCode) {
return system.getResult(null, "验证码已过期,请点击重试");
}
if(code.toLowerCase() != cacheCode.toLowerCase()) {
await this.redisClient.delete(key);
return system.getResult(null, "验证码输入错误,请点击重试");
}
return system.getResultSuccess(1);
}
trim(o) {
if(!o) {
return "";
}
return o.toString().trim();
}
}
module.exports = CaptchaService;
\ No newline at end of file
......@@ -134,6 +134,11 @@ class UserService extends ServiceBase {
}
});
}
async unlockUser(username) {
await this.resetPassword(username, settings.defaultpwd);
return this.dao.updateByWhere({ isEnabled: true }, { userName: username })
}
async logout(pobj) {
await this.cacheManager["UserCache"].invalidate(pobj.username);
return {}
......@@ -150,15 +155,22 @@ class UserService extends ServiceBase {
let consumer = await this.cget(UserService.consumerUrl(p.userName));
if (!consumer.data) {
return null;
} else {
console.log(JSON.stringify(consumer.data))
let password = consumer.data.tags[1].split("_")[1];
}
var rtn = {}
let u = await this.findOne({ userName: p.userName });
let inpassword = this.getEncryptStr(p.password);
if (password != inpassword) {
if (u.password != inpassword) {
return null;
}
let last = new Date(u.last_change_date).getTime();//注意月份
let differ = Date.now() - last;
let days = Math.round(differ / (24 * 60 * 60 * 1000));
if (u.last_change_date && days >= settings.changepwdcycle) {//禁用用户
await this.dao.updateByWhere({ isEnabled: false }, { userName: p.userName })
return null
} else if ((settings.changepwdcycle - 7) <= days) {
rtn.hint = "请尽快修改密码,否则会禁用您的账户"
}
var rtn = {}
return this.db.transaction(async function (t) {
//从缓存中取得
// let userfind = await self.dao.model.findOne({
......@@ -393,14 +405,18 @@ class UserService extends ServiceBase {
async getBizUserForBizChance(clientMobile, spName, productCatName, regionName) {
var self = this
clientMobile = clientMobile + "_" + spName + "_" + regionName + "_" + productCatName
console.log(`商机 缓存 key ----- ${clientMobile} `);
//按照服务商名字查询到公司,按照公司查询出users,条件是可以接受派单任务,并且技能标签含有,产品类别名称
return this.db.transaction(async function (t) {
//先检查缓存是否存在bizuser
var resultcache = await self.cacheManager["ClientBindBizUserCache"].getCache(clientMobile)
let isGoExec = false
if (!resultcache) {
isGoExec = true
isGoExec = true;
} else {
console.log(` ----- 需求 分配 缓存信息 ------- ${clientMobile}`);
console.log(resultcache);
let uname = resultcache.userName
let ucache = await self.cacheManager["UserCache"].cache(uname)
if (!ucache.isAllocated) {//解决修改为不接单
......@@ -408,15 +424,16 @@ class UserService extends ServiceBase {
await self.cacheManager["ClientBindBizUserCache"].invalidate(clientMobile)
}
}
if (isGoExec) {
let companyFind = await self.companyDao.model.findOne({
where: { name: spName }, include: [
{
model: self.db.models.user, as: "us", attributes: ['id', 'userName', 'mobile', 'isAllocated', 'opath', 'skilltags', 'regiontags', 'isAllArea', 'isSalesman', 'isDelivery'], raw: true
model: self.db.models.user, as: "us", attributes: ['id', 'userName', 'mobile', 'isAllocated', 'opath', 'skilltags', 'regiontags', 'isAllArea', 'isSalesman', 'isDelivery','tx_uin'], raw: true
}
], excludes: ['orgJson'], transaction: t
});
if (companyFind) {
console.log("getBizUserForBizChance获取服务商信息:" + JSON.stringify(companyFind));
if (isGoExec) {
let users = companyFind.us
let cansels = users.filter(u => {
if (regionName && regionName != "" && u.regiontags) {
......@@ -454,17 +471,19 @@ class UserService extends ServiceBase {
await self.cacheManager["ClientBindBizUserCache"].cache(clientMobile, tmp)
return { userInfo: tmp, comInfo: { compId: tmp.compId } };
} else {
return { userInfo: null, comInfo: { compId: tmp.compId } };
return { userInfo: null, comInfo: { compId: companyFind.id } };
}
} else {
if (resultcache) {//不继续,直接返回缓存
return { userInfo: resultcache.tmp, comInfo: { compId: companyFind.id } };
return { userInfo: resultcache, comInfo: { compId: companyFind.id } };
} else {
return { userInfo: null, comInfo: { compId: companyFind.id } };
}
}
} else {
return { userInfo: null, comInfo: null }
}
})
}
async findCostBySkuCode(skucode) {
......@@ -495,6 +514,7 @@ class UserService extends ServiceBase {
*/
async getBizUserForDelivery(xclientMobile, spName, productCatName, skucode, regionName) {
let clientMobile = 'fordeliver' + xclientMobile + "_" + spName + "_" + regionName + "_" + productCatName
console.log(`交付单缓存 key ----- ${clientMobile} `);
var self = this
//按照服务商名字查询到公司,按照公司查询出users,条件是可以接受派单任务,并且技能标签含有,产品类别名称
return this.db.transaction(async function (t) {
......@@ -503,8 +523,10 @@ class UserService extends ServiceBase {
var resultcache = await self.cacheManager["ClientBindBizUserCache"].getCache(clientMobile)
let isGoExec = false
if (!resultcache) {
isGoExec = true
isGoExec = true;
} else {
console.log(`交付单 分配 人员 缓存信息 ----- ${clientMobile} `)
console.log(resultcache);
let uname = resultcache.userName
let ucache = await self.cacheManager["UserCache"].cache(uname)
if (!ucache.isAllocated) {//解决修改为不接单
......@@ -515,12 +537,12 @@ class UserService extends ServiceBase {
let companyFind = await self.companyDao.model.findOne({
where: { name: spName }, include: [
{
model: self.db.models.user, as: "us", attributes: ['id', 'userName', 'mobile', 'isAllocated', 'opath', 'skilltags', 'regiontags', 'isAllArea', 'isSalesman', 'isDelivery'], raw: true
model: self.db.models.user, as: "us", attributes: ['id', 'userName', 'mobile', 'isAllocated', 'opath', 'skilltags', 'regiontags', 'isAllArea', 'isSalesman', 'isDelivery','tx_uin'], raw: true
}
], excludes: ['orgJson'], transaction: t
});
console.log("getBizUserForDelivery获取服务商信息:" + companyFind);
if (companyFind) {
console.log("getBizUserForDelivery获取服务商信息:" + JSON.stringify(companyFind));
if (isGoExec) {
let users = companyFind.us
let cansels = users.filter(u => {
......@@ -565,7 +587,7 @@ class UserService extends ServiceBase {
} else {
if (resultcache) {//不继续,直接返回缓存
resultcache["cost"] = costAmount
return { userInfo: resultcache.tmp, comInfo: { cost: costAmount, compId: companyFind.id } };
return { userInfo: resultcache, comInfo: { cost: costAmount, compId: companyFind.id } };
} else {
return { userInfo: null, comInfo: { cost: costAmount, compId: companyFind.id } };
}
......
const system = require("../../../system");
const ServiceBase = require("../../sve.base");
const settings = require("../../../../config/settings");
class CompanyService extends ServiceBase {
constructor() {
super("common", ServiceBase.getDaoName(CompanyService));
}
async getMyApps (appids, isSuper) {
async getMyApps(appids, isSuper) {
let appsrtn = null
if (isSuper) {
appsrtn = this.db.models.app.findAll({
where:
{
id: { [this.db.Op.ne]: settings.pmappid }
id: {[this.db.Op.ne]: settings.pmappid}
}
})
} else {
appsrtn = this.db.models.app.findAll({
where:
{
id: { [this.db.Op.in]: appids }
id: {[this.db.Op.in]: appids}
}
})
}
return appsrtn
}
async bindApps (appids, companyid) {
async bindApps(appids, companyid) {
var self = this
return this.db.transaction(async function (t) {
let u = await self.dao.update({ appids: appids, id: companyid }, t)
let u = await self.dao.update({appids: appids, id: companyid}, t)
return appids
})
}
async setOrgs (p, cmk) {
buildNoPositionNode(treejson, rtnArray) {
treejson.forEach((n) => {
if (n.children) {
this.buildNoPositionNode(n.children, rtnArray)
}
if (n.hasOwnProperty("isPosition") && !n.isPosition) {
rtnArray.push(n)
}
})
}
async getWatchOrgNodes(cmid) {
let rtn = []
let companynew = await this.findById(cmid)
let orgjsonstr = companynew.orgJson
if (orgjsonstr && orgjsonstr != "") {
let treejson = JSON.parse(companynew.orgJson)
this.buildNoPositionNode(treejson, rtn)
}
return rtn
}
async setOrgs(p, cmk) {
var self = this
let curNodeData = p.curdata
let opathstr = curNodeData.orgpath
......@@ -42,14 +68,14 @@ class CompanyService extends ServiceBase {
let oldopath = ''
if (!oldNodeData) {//如果不传老对象,表示当前操作是删除节点操作,检查是否存在用户,如果已经存在
//那么就提示不能删除
let us = await self.db.models.user.findOne({ where: { opath: { [self.db.Op.like]: `%${opathstr}%` } } })
let us = await self.db.models.user.findOne({where: {opath: {[self.db.Op.like]: `%${opathstr}%`}}})
if (us) {
let companytmp = await this.dao.model.findOne({ where: { id: p.company_id } });
return { orgJson: JSON.parse(companytmp.orgJson) }
let companytmp = await this.dao.model.findOne({where: {id: p.company_id}});
return {orgJson: JSON.parse(companytmp.orgJson)}
} else {
let u = await this.dao.update(p)
let companytmp = await this.dao.model.findOne({ where: { id: p.company_id } });
return { orgJson: JSON.parse(companytmp.orgJson) }
let companytmp = await this.dao.model.findOne({where: {id: p.company_id}});
return {orgJson: JSON.parse(companytmp.orgJson)}
}
} else {
oldopath = oldNodeData.orgpath == '' ? '123456' : oldNodeData.orgpath
......@@ -63,7 +89,10 @@ class CompanyService extends ServiceBase {
if (curNodeData) {
if (curNodeData.isPosition) {
let us = await self.db.models.user.findAll({ where: { opath: { [self.db.Op.like]: `%${oldopath}%` } }, transaction: t })
let us = await self.db.models.user.findAll({
where: {opath: {[self.db.Op.like]: `%${oldopath}%`}},
transaction: t
})
//查询出角色
let roleids = curNodeData.roles
// let rs=await self.db.models.role.findAll({where:{id:{[self.db.Op.in]:roleids},app_id:p.app_id,company_id:p.company_id},transaction:t})
......@@ -74,13 +103,16 @@ class CompanyService extends ServiceBase {
roleids.push(settings.pmroleid["pr"])
}
}
let rs = await self.db.models.role.findAll({ where: { id: { [self.db.Op.in]: roleids } }, transaction: t })
let rs = await self.db.models.role.findAll({
where: {id: {[self.db.Op.in]: roleids}},
transaction: t
})
for (let u of us) {
await u.setRoles(rs, { transaction: t })
await u.setRoles(rs, {transaction: t})
//if (opathstr != oldopath) {
u.opath = opathstr + "/" + u.userName
u.ptags = curNodeData.ptags
u.save({ transaction: t })
u.save({transaction: t})
// }
//令用户缓存失效
await self.cacheManager["UserCache"].invalidate(u.userName)
......@@ -88,12 +120,15 @@ class CompanyService extends ServiceBase {
} else {//不是岗位节点,检查修改后的路径是否和原始一致,如果不一致,那么需要查出原始的用户数据
//把原来的路径替换当前新的code
if (opathstr != oldopath) {
let us2 = await self.db.models.user.findAll({ where: { opath: { [self.db.Op.like]: `%${oldopath}%` } }, transaction: t })
let us2 = await self.db.models.user.findAll({
where: {opath: {[self.db.Op.like]: `%${oldopath}%`}},
transaction: t
})
for (let u of us2) {
let curpath = u.opath
let newpath = curpath.replace(oldNodeData.code, curNodeData.code)
u.opath = newpath
u.save({ transaction: t })
u.save({transaction: t})
//令用户缓存失效
await self.cacheManager["UserCache"].invalidate(u.userName)
}
......@@ -102,9 +137,24 @@ class CompanyService extends ServiceBase {
}
}
let companytmp = await self.dao.model.findOne({ where: { id: p.company_id }, transaction: t });
return { orgJson: JSON.parse(companytmp.orgJson) }
let companytmp = await self.dao.model.findOne({where: {id: p.company_id}, transaction: t});
return {orgJson: JSON.parse(companytmp.orgJson)}
})
}
buildOrgs(rtnjson, code) {
if (rtnjson.length > 0) {
for (let val of rtnjson) {
if (val.code === code) {
return [val]
} else {
return this.buildOrgs(val.children || [], code)
}
}
} else {
return rtnjson
}
}
}
module.exports = CompanyService;
......@@ -103,7 +103,7 @@ class ProductService extends ServiceBase {
if (productprices.length > 0) {
await self.priceDao.bulkCreate(productprices, t)
}
return {};
return currentProduct;
});
}
}
......
const system = require("../../../system");
const ServiceBase = require("../../sve.base");
const _ = require("lodash");
class ProductpriceService extends ServiceBase {
constructor() {
super("product", ServiceBase.getDaoName(ProductpriceService));
......@@ -8,7 +9,7 @@ class ProductpriceService extends ServiceBase {
* @param {*} pname 产品名称
* @param {*} spname 服务商名称
*/
async findRegionsByProductName (productname, spname) {
async findRegionsByProductName(productname, spname) {
let ps = await this.dao.model.findAll({
where: {
sptags: { [this.db.Op.like]: "%" + spname + "%" },
......@@ -53,7 +54,64 @@ class ProductpriceService extends ServiceBase {
})
return psrtn
}
async updownProduct (uid) {
/**
* 为 财税 提供 产品 详情 接口
* @param {*} productname 产品名称 小规模纳税人、一般纳税人
* @param {*} region 地区
* @param {*} spname 服务商
*/
async findProductInfoForFt(productname, region, spname = '公司宝') {
let datas = await this.dao.model.findAll({
where: {
$and: [
{
sptags: { $like: "%" + spname + "%" },
isEnabled: true,
pname: { $like: "%" + "财税服务" + "%" },
}, {
pname: { $like: "%" + "代理记账" + "%" }
}
]
},
attributes: ['pname', 'strategyitems', "hignpriceref"], // 价格、地区、skucode
raw: true
});
let result = [];
//查询出地区
let address = await this.db.models.region.findAll({ attributes: ['code', 'name'], raw: true });
for (let val of datas) {
let area = val.pname.split("~")[1].split("/");
area = area[area.length - 1];
//按照名字去取地区编码
let areaCode = address.filter(f => {
if (f.name.indexOf(area) >= 0) {
return true
} else {
return false
}
})
areaCode = `${areaCode[0].code}00`;
result.push({
area,
areaCode,
type: val.strategyitems,
price: val.hignpriceref
})
}
result = _.groupBy(result, 'type')
if (productname) {
result = result[productname];
}
if (productname && region) {
result = _.find(result, (item) => {
return item.area.indexOf(region) >= 0
})
}
return result
}
async updownProduct(uid) {
let p = await this.dao.findById(uid)
p.isEnabled = !p.isEnabled
await p.save()
......
......@@ -11,7 +11,7 @@ class ServiceBase {
this.daoName = daoName;
this.dao = system.getObject("db." + gname + "." + daoName);
this.restS = system.getObject("util.restClient");
this.md5 = require("MD5");
this.crypto = require('crypto');
}
/**
*
......@@ -25,9 +25,8 @@ class ServiceBase {
if (isComplexVerification) {
this.complexVerification(str)
}
var md5 = this.md5(str + "_" + settings.salt);
return md5.toString().toLowerCase();
let pwd = this.crypto.createHash("sha256").update(str + "_" + settings.salt, "utf8").digest("base64");
return pwd.toLowerCase();
}
complexVerification(str) {
......
......@@ -6,7 +6,8 @@ class ExecClient {
constructor() {
this.cmdPostPattern = "curl -k -H 'Content-type: application/json' -d '{data}' {url}";
this.cmdGetPattern = "curl -G -X GET '{url}'";
this.cmdPostPattern3 = "curl -k -H 'Content-type: application/json' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJvcnpaWmhXRXBKNVVFZzRZUU5uUmlyVEJXa1FQbnZ6UyIsImlhdCI6MTU5MjcwOTYzNn0.TWk_F6Tz3fRMqspoG24VSt5RiC4ldFembFYcLcAbowE' -H 'XAPPKEY: 647a68c9-da01-40d3-9763-1ffa0f64cf3f' -d '{data}' {url}";
this.cmdPostPattern3 = "curl -k -H 'Content-type: application/json' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTg0MzQ2ODcsImlzcyI6InJFRVN6TU5ZUlM2RnBWNnZlY09vdExPNWdPcUNXSmFQIiwiaWF0IjoxNTk4NDMxMDg3fQ.isQ40HqHHfJ-rTsUQOhRIdu4XCitZU-AfzeqSH4kPbQ' -H 'XAPPKEY: f6b59b74-f943-4735-bb86-e05d6b7fd78e' -d '{data}' {url}";
//this.cmdPostPattern3 = "curl -k -H 'Content-type: application/json' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJvcnpaWmhXRXBKNVVFZzRZUU5uUmlyVEJXa1FQbnZ6UyIsImlhdCI6MTU5MjcwOTYzNn0.TWk_F6Tz3fRMqspoG24VSt5RiC4ldFembFYcLcAbowE' -H 'XAPPKEY: 647a68c9-da01-40d3-9763-1ffa0f64cf3f' -d '{data}' {url}";
}
async exec(cmd) {
......
......@@ -2,6 +2,7 @@
var System = require("../../base/system");
const chnelapi = System.getObject("api.common.channels")
var channelCache = {}
module.exports = function (app) {
app.get("/autologin", (req, res, next) => {
//读取cookie,获取cookie值,
......@@ -9,6 +10,7 @@ module.exports = function (app) {
//Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImRjMmM1MzMwMjNhMTExZTlhOTU3NjliODBiNDI4Y2QxIn0.eyJpZCI6IjViZDk2MWJkZWQxN2E5MmI1MDFjZWQ0ZCIsIm5hbWUiOiLpnZLph4kxMSIsImVtcGxveWVlIjoiNWQ5ZWNlODc1Zjk3ZGQzMzEwNzI4ZjY4IiwicGhvbmUiOiI3TFlYZ29ySkdGM2hBbHdqQTZGelFnPT0iLCJvcmdpZCI6IjViY2ZlOTVjYjBhMDFmMDAwOTI4NGJjMyIsInBsYXRmb3JtIjoiZDVmYTU4Yjk3NGExMjBlZTYxMTMzM2MwMDNjOWZlYzAiLCJ1bmlvbmlkIjoib2RuWjR0OERoV1V0N0lXT09maEF0UTdqM1docyIsImp0aSI6Imo3R0hLRGFzNDEzQTQ2OGkiLCJleHAiOjE1OTYwODEzMTEsImlhdCI6MTU5NTQ3NjUxMX0.I196XbcCR3k7r1O8uwoI2HUhow0UhGHKzii5wOR39vLmuNOUatNY7ccQTCHijqysbSCePP43Iuglrl2gLQASf5uAr9uqTzhTc3O4Z5iF3oR2qR1vlBxrzTDF8xuhKHQ4tO6Hbsib0FdOYVeU8fe0g_GZiIcuYIv-f8VsiAGMF9TEES129CDwZacJfVViw4EXVnXSivAzQG4JgGSwUACvPT140bCZ1XPeHi0GXmgtEN77NjWfOGI5RYGC0Gq3CGevlSWERjb3mUscAIjoXsOxlWNwy7dc1u1A7uX1a6bUhLU1wtiQ6md4TnyeR5OdYeVqGlIe3hZGcH_E3QrQMq988Q
})
app.all("*", async function (req, res, next) {
try {
let channel = null
......@@ -34,6 +36,11 @@ module.exports = function (app) {
res.end(JSON.stringify({ status: -1, message: e }));
}
})
app.post("/login/getpiccode", async (req, res, next) => {
let captchaSve = System.getObject("service.auth.captchaSve");
let data = await captchaSve.apiGenerate({})
res.end(JSON.stringify(data));
});
app.get('/api/:gname/:qname/:method', function (req, res) {
// var classPath = req.params["qname"];
var methodName = req.params["method"];
......
......@@ -19,7 +19,8 @@ var settings = {
encrypt_key: ENVINPUT.ENCRYPT_KEY,
encrypt_secret: ENVINPUT.ENCRYPT_SECRET,
salt: "%iatpD1gcxz7iF#B",
defaultpwd: "gsb2020",
defaultpwd: "Temp123456",
changepwdcycle: 365,//密码更换周期 7天前登录提示更改密码 到期后直接禁用账户
basepath: path.normalize(path.join(__dirname, '../..')),
port: process.env.NODE_PORT || 80,
logindex: "center_manage",
......@@ -28,7 +29,14 @@ var settings = {
if (this.env == "localhost") {
var localsettings = require("./localsettings");
return localsettings.kongurl;
} else {
}
else if (this.env == "test") {
return "http://kong-dbproxy.kong-test:8001/";
}
else if (this.env == "pre") {
return "http://kong-dbproxy.kong-pre:8001/";
}
else {
return "http://kong-dbproxy.kong:8001/";
}
},
......@@ -39,6 +47,13 @@ var settings = {
return "http://icdeliver-service";
}
},
bookUrl: function () {
if (this.env == "localhost") {
return "http://192.168.1.19:8889";
} else {
return "http://icdeliver-service";
}
},
logUrl: function () {
if (this.env == "localhost") {
return "http://192.168.1.128:4019/api/queueAction/producer/springBoard";
......@@ -46,6 +61,21 @@ var settings = {
return "http://logs-sytxpublic-msgq-service/api/queueAction/producer/springBoard";
}
},
pushUrl: function () {
if (this.env == "localhost") {
return "http://192.168.18.101:4018/api/queueAction/producer/springBoard";
} else {
return "http://logs-sytxpublic-msgq-service/api/queueAction/producer/springBoard";
}
},
bpushUrl: function () {
if (this.env == "localhost") {
return "http://192.168.1.19:4018/api/queueAction/producer/springBoard";
} else {
return "http://logs-sytxpublic-msgq-service/api/queueAction/producer/springBoard";
}
},
pmappname: "center-app",
pmappid: 1,
pmcompanyid: 1,
......@@ -66,7 +96,6 @@ var settings = {
database: function () {
if (this.env == "localhost") {
var localsettings = require("./localsettings");
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>....")
return localsettings.database;
} else {
return {
......
......@@ -56,7 +56,8 @@
"sha256": "^0.2.0",
"socket.io": "^2.1.1",
"uuid": "^3.2.1",
"xml2js": "^0.4.19"
"xml2js": "^0.4.19",
"svg-captcha": "^1.4.0"
},
"devDependencies": {
"del": "^5.1.0",
......
ALTER TABLE `brg-center-manage`.`p_user`
ADD COLUMN `last_change_date` datetime NOT NULL COMMENT '最后更新时间'
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="/ccc.png">
<title></title>
<link href="/0.js" rel="prefetch"><link href="/1.js" rel="prefetch"><link href="/10.js" rel="prefetch"><link href="/11.js" rel="prefetch"><link href="/12.js" rel="prefetch"><link href="/13.js" rel="prefetch"><link href="/14.js" rel="prefetch"><link href="/15.js" rel="prefetch"><link href="/16.js" rel="prefetch"><link href="/17.js" rel="prefetch"><link href="/18.js" rel="prefetch"><link href="/19.js" rel="prefetch"><link href="/2.js" rel="prefetch"><link href="/20.js" rel="prefetch"><link href="/21.js" rel="prefetch"><link href="/22.js" rel="prefetch"><link href="/23.js" rel="prefetch"><link href="/24.js" rel="prefetch"><link href="/25.js" rel="prefetch"><link href="/26.js" rel="prefetch"><link href="/27.js" rel="prefetch"><link href="/28.js" rel="prefetch"><link href="/29.js" rel="prefetch"><link href="/3.js" rel="prefetch"><link href="/30.js" rel="prefetch"><link href="/31.js" rel="prefetch"><link href="/32.js" rel="prefetch"><link href="/33.js" rel="prefetch"><link href="/34.js" rel="prefetch"><link href="/35.js" rel="prefetch"><link href="/36.js" rel="prefetch"><link href="/37.js" rel="prefetch"><link href="/38.js" rel="prefetch"><link href="/4.js" rel="prefetch"><link href="/5.js" rel="prefetch"><link href="/6.js" rel="prefetch"><link href="/7.js" rel="prefetch"><link href="/8.js" rel="prefetch"><link href="/9.js" rel="prefetch"><link href="/app.js" rel="preload" as="script"></head>
<link href="/0.js" rel="prefetch"><link href="/1.js" rel="prefetch"><link href="/10.js" rel="prefetch"><link href="/11.js" rel="prefetch"><link href="/12.js" rel="prefetch"><link href="/13.js" rel="prefetch"><link href="/14.js" rel="prefetch"><link href="/15.js" rel="prefetch"><link href="/16.js" rel="prefetch"><link href="/17.js" rel="prefetch"><link href="/18.js" rel="prefetch"><link href="/19.js" rel="prefetch"><link href="/2.js" rel="prefetch"><link href="/20.js" rel="prefetch"><link href="/21.js" rel="prefetch"><link href="/22.js" rel="prefetch"><link href="/23.js" rel="prefetch"><link href="/24.js" rel="prefetch"><link href="/25.js" rel="prefetch"><link href="/26.js" rel="prefetch"><link href="/27.js" rel="prefetch"><link href="/28.js" rel="prefetch"><link href="/29.js" rel="prefetch"><link href="/3.js" rel="prefetch"><link href="/30.js" rel="prefetch"><link href="/31.js" rel="prefetch"><link href="/32.js" rel="prefetch"><link href="/33.js" rel="prefetch"><link href="/34.js" rel="prefetch"><link href="/35.js" rel="prefetch"><link href="/36.js" rel="prefetch"><link href="/37.js" rel="prefetch"><link href="/38.js" rel="prefetch"><link href="/39.js" rel="prefetch"><link href="/4.js" rel="prefetch"><link href="/5.js" rel="prefetch"><link href="/6.js" rel="prefetch"><link href="/7.js" rel="prefetch"><link href="/8.js" rel="prefetch"><link href="/9.js" rel="prefetch"><link href="/app.js" rel="preload" as="script"></head>
<body>
<noscript>
<strong>We're sorry but iview-admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment