Commit 8fdc68d0 by lixinming

no message

parent 34d7e8df
...@@ -2,17 +2,16 @@ ...@@ -2,17 +2,16 @@
* 会员逻辑 * 会员逻辑
*/ */
import { MEMBERSTATE, MEMBERLEVEL, DOCUMENTTYPE, NATION, PROFCATEGORY, CODETYPE, UNITINFOTYPE, MEMBERTYPE, REGISTERFLOW, SEX, USERREGISTERSTATE, OPERATIONREHAVIOR } from "../../config/enum"; import { MEMBERSTATE, MEMBERLEVEL, DOCUMENTTYPE, NATION, PROFCATEGORY, CODETYPE, UNITINFOTYPE, MEMBERTYPE, REGISTERFLOW, SEX, USERREGISTERSTATE, OPERATIONREHAVIOR, STATE } from "../../config/enum";
import { ERRORENUM } from "../../config/errorEnum"; import { ERRORENUM } from "../../config/errorEnum";
import { TABLEENUM } from "../../data/models/model"; import { TABLEENUM } from "../../data/models/model";
import { find, findCount, findOnce, findToPage } from "../../data/select"; import { find, findCount, findOnce, findOnceToSort, findToPage, findToSort } from "../../data/select";
import { updateOneData } from "../../data/update"; import { updateOneData } from "../../data/update";
import { generateSystemId, successResult } from "../../tools/system"; import { generateSystemId, successResult } from "../../tools/system";
import { BizError } from "../../util/bizError"; import { BizError } from "../../util/bizError";
import { extractData } from "../../util/piecemeal"; import { extractData } from "../../util/piecemeal";
import { changeEnumValue, eccEnumValue } from "../../util/verificationEnum"; import { changeEnumValue, eccEnumValue } from "../../util/verificationEnum";
import * as sysTools from "../../tools/system"; import * as sysTools from "../../tools/system";
import { sendRegisterCode } from "../sms";
import { addManyData, addOneData } from "../../data/add"; import { addManyData, addOneData } from "../../data/add";
import { deleteManyData, deleteOneData } from "../../data/delete"; import { deleteManyData, deleteOneData } from "../../data/delete";
...@@ -134,35 +133,27 @@ export async function delResearch({id}) { ...@@ -134,35 +133,27 @@ export async function delResearch({id}) {
/** /**
* 会员注册的短信验证码 * 会员注册【短信验证码】 success
* @param userId * @param userId
* @param phone * @param phone
* @returns * @returns
*/ */
export async function memberRegisterSendCode({loginId, phone, codeType}) { export async function memberRegisterSendCode({phone}) {
let todayMs = sysTools.getTodayMs(); const NowMs = new Date().valueOf();
let todayCodeList = await find(TABLEENUM.验证码表, {phone}) || []; let codeSelectParam = { phone, isUse:false, type:CODETYPE.用户注册, sendMs:{"$gt":sysTools.getTodayMs()} }
// if (todayCodeList.length >= 4) throw new BizError(ERRORENUM.发送验证码次数超限制, `${loginId} 修改密码发送验证码次数超限制4`); let lastCodeInfo = await findOnceToSort(TABLEENUM.验证码表, codeSelectParam, {sendMs:-1});
if (lastCodeInfo.code) {
let sendMs = todayMs; if ( (lastCodeInfo.sendMs + (60*1000)) > NowMs ) throw new BizError(ERRORENUM.频繁操作请稍后再试);
todayCodeList.forEach(info => { /**校验今日同类型验证码次数 */
sendMs = Math.max(sendMs, info.sendMs); let todayNotUseCount = await findCount(TABLEENUM.验证码表, codeSelectParam);
}); if (todayNotUseCount >= 4) throw new BizError(ERRORENUM.发送验证码次数超限制, `${phone} 注册验证码超过限制3`);
}
let now = new Date().valueOf();
if ((now - sendMs) <= (60 * 1000) ) throw new BizError(ERRORENUM.发送验证码频率过快, `${loginId}`);
let codeId = sysTools.getSMSCodeId(loginId, todayCodeList.length||0);
let code = sysTools.getSMSCode();
//await sendRegisterCode(phone, code, codeType); //todo 发送短信
now = new Date().valueOf();
await addOneData(TABLEENUM.验证码表, {codeId, codeNum:code, sendMs:now, phone, type:codeType, isUse:true});
let dataList = {codeId} const Code = sysTools.generateSMSCode();//生成短信验证码
let addInfo = {code:Code, phone, sendMs:NowMs, type:CODETYPE.用户注册, isUse:false};
await addOneData(TABLEENUM.验证码表, addInfo);
return dataList; return {code:Code};
} }
...@@ -246,44 +237,44 @@ export async function individualMemberDetails({userId}) { ...@@ -246,44 +237,44 @@ export async function individualMemberDetails({userId}) {
/** /**
* 个人入会流程1 * 会员注册【个人会员】【流程一】success
* @param secureArgs * @param secureArgs
*/ */
export async function memberRegister1({form, codeId}) { export async function memberRegister1({form}) {
let oldData = await findOnce(TABLEENUM.用户表, {"$or":[{loginId:form.loginId}, {phone:form.phone}, {mail:form.mail}] }); let {loginId, mail, pwd, confirmation, phone, codeNum} = form;
if (oldData && oldData.userId) { const NowMs = new Date().valueOf();
if (oldData.loginId == form.loginId) throw new BizError(ERRORENUM.用户名重复, form.loginId );
if (oldData.phone == form.phone) throw new BizError(ERRORENUM.联系人手机号重复, form.phone );
if (oldData.mail == form.mail) throw new BizError(ERRORENUM.邮箱重复, form.loginId );
}
/**校验密码 */ /**校验密码 */
if (form.pwd.search(/^[A-Za-z0-9]{6,18}$/) < 0) throw new BizError(ERRORENUM.密码只能由618位字符和数字组成); if (pwd.search(/^[A-Za-z0-9]{6,18}$/) < 0) throw new BizError(ERRORENUM.密码只能由618位字符和数字组成);
if (form.pwd != form.confirmation) throw new BizError(ERRORENUM.两次密码不一致); if (pwd != confirmation) throw new BizError(ERRORENUM.两次密码不一致);
form.userId = sysTools.generateUserId(); /**校验去重 */
form.memberType = MEMBERTYPE.个人会员; let oldData = await findOnce(TABLEENUM.用户表, {"$or":[{loginId:form.loginId}, {phone:form.phone}] });
form.isAdmin = 0; if (oldData && oldData.userId) {
form.registerFlow = REGISTERFLOW.个人会员注册1; //会员注册流程状态,审核通过后修改为流程2 if (oldData.loginId == loginId) throw new BizError(ERRORENUM.用户名重复, form.loginId );
if (oldData.phone == phone) throw new BizError(ERRORENUM.联系人手机号重复, form.phone );
}
// let todayMs = sysTools.getTodayMs(); /**比对验证码 */
let codeList = await findOnce(TABLEENUM.验证码表, {codeId}); let codeInfo = await findOnceToSort(TABLEENUM.验证码表, {phone, isUse:false, type:CODETYPE.用户注册, sendMs:{"$gt":sysTools.getTodayMs() }}, {sendMs:-1});
if (!codeInfo) throw new BizError(ERRORENUM.code无效, `${phone}在注册时,code表中不存在该手机号的验证码`);
if (codeInfo != codeNum) throw new BizError(ERRORENUM.验证码错误, `${phone}不存在${codeNum}`);
if (( codeInfo.sendMs + (30 * 60 *1000) ) < NowMs ) throw new BizError(ERRORENUM.验证码过期);
let now = new Date().valueOf(); /**初始化账号信息 */
let userId = sysTools.generateUserId();//系统生成唯一id
let msg = ERRORENUM.验证码错误; let addInfo = {
if (codeList.codeNum == form.codeNum) { userId,
if (codeList.isUse) msg = ERRORENUM.验证码失效; memberType:MEMBERTYPE.个人会员,
else if ( (now - codeList.sendMs) > (30 * 60 * 1000) ) msg = ERRORENUM.验证码过期 isAdmin:STATE.,
} registerFlow:REGISTERFLOW.完成第一步,//会员注册流程状态
askForTime:NowMs,//申请时间
if (!codeId) throw new BizError(msg, `userId:${form.userId}个人入会注册流程1的code:${form.code}`); loginId, mail, pwd, phone,
/**修改验证码状态为已使用 */ };
await updateOneData(TABLEENUM.验证码表, {codeId}, {isUse:true}); await addOneData(TABLEENUM.用户表, addInfo);
await addOneData(TABLEENUM.用户表, form); await updateOneData(TABLEENUM.验证码表, {phone, code:codeNum, isUse:false }, {isUse:true});
return successResult(); return {userId}
} }
......
...@@ -260,7 +260,7 @@ export async function backInvoice({id}) { ...@@ -260,7 +260,7 @@ export async function backInvoice({id}) {
/** /**
* 发票管理-已开发票 * 发票管理-已开发票 success
* @param param0 * @param param0
*/ */
export async function InvoicedList({unitName, paymentType, isPay, pageNumber}) { export async function InvoicedList({unitName, paymentType, isPay, pageNumber}) {
......
...@@ -383,8 +383,7 @@ export enum ORDERSTATE { ...@@ -383,8 +383,7 @@ export enum ORDERSTATE {
* 验证码类型 * 验证码类型
*/ */
export enum CODETYPE { export enum CODETYPE {
单位会员注册 = 1, 用户注册 = 1
个人会员注册,
} }
...@@ -436,11 +435,10 @@ export enum SMSTYPE { ...@@ -436,11 +435,10 @@ export enum SMSTYPE {
* 会员注册流程 * 会员注册流程
*/ */
export enum REGISTERFLOW { export enum REGISTERFLOW {
单位会员注册1 = 1, 未注册 = 0,
单位会员注册2, 完成第一步,
单位会员注册3, 完成第二步,
个人会员注册1, 完成第三步
个人会员注册2
} }
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
}, },
*/ */
import { INVOICESTATUS, MEMBERSTATE, RECEIPTCONFIRMATION, REGISTERFLOW, USERREGISTERSTATE } from "../../config/enum"; import { INVOICESTATUS, MEMBERSTATE, RECEIPTCONFIRMATION, REGISTERFLOW, STATE, USERREGISTERSTATE } from "../../config/enum";
...@@ -332,17 +332,38 @@ const ModelArray = [ ...@@ -332,17 +332,38 @@ const ModelArray = [
source:TABLESOURCEENUM.mongo, source:TABLESOURCEENUM.mongo,
schema:{ schema:{
userId:{ type:'String', index:true },//唯一标识 userId:{ type:'String', index:true },//唯一标识
isAdmin:{ type:'Number', default:0},//是否是管理员 askForTime:'Number',//申请时间 第一步流程发起时间
auditTime:'Number',//审核时间 会员审核列表审核时间
joinTime:'Number',//入会时间 审核通过时间
memberType:{type:'Number'},//会员类型 MEMBERTYPE memberType:{type:'Number'},//会员类型 MEMBERTYPE
lifespanStartTime:'Number',//会员有效期开始时间 时间戳 每次缴费成功更新
lifespanEndTime:'Number',//会员有效期结束时间 时间戳 每次缴费成功更新
/**状态枚举 */
registerFlow:{type:'Number', default:REGISTERFLOW.未注册},//会员注册流程 枚举
isAdmin:{ type:'Number', default:STATE.},//是否是管理员
userRegisterState:{type:'Number', default:USERREGISTERSTATE.待审核},//用户注册状态 枚举USERREGISTERSTATE
memberState:{type:'Number', default:MEMBERSTATE.正常},//会员状态 枚举MEMBERSTATE
/**宽限期状态 */
isGracePeriod:{type:'Number', default:0},//是否宽限期 0:否, 1:是
gracePeriodEndTime:'Number',//宽限期到期时间 时间戳
/**第一步流程表单 */
loginId:{ type:'String', index:true},//用户名 可用作登陆
pwd:{ type:'String'},//密码
phone:{type:'String', index:true},//联系电话(登陆手机号) 可用作登陆
mail:{type:'String', index:true},//邮箱
/**第二步流程表单(个人) */
unitMemberType:{type: 'Number'},//单位会员类型 unitMemberType:{type: 'Number'},//单位会员类型
individualMemberType:{type: 'Number'},//个人会员类型 individualMemberType:{type: 'Number'},//个人会员类型
name:{type:'String'},//真实姓名 name:{type:'String'},//真实姓名
loginId:{ type:'String', index:true},//用户名
pwd:{ type:'String'},//密码
token:{type:'String', default:''},//token token:{type:'String', default:''},//token
tokenMs:{type:'Number', default:0},//token过期时间 tokenMs:{type:'Number', default:0},//token过期时间
phone:{type:'String', index:true},//联系电话 登陆手机号
mail:{type:'String', index:true},//邮箱
sex:'Number',//性别 枚举 sex:'Number',//性别 枚举
documentType:'Number',//证件类型 枚举 documentType:'Number',//证件类型 枚举
documentId:'String',//证件id 身份证 documentId:'String',//证件id 身份证
...@@ -355,22 +376,15 @@ const ModelArray = [ ...@@ -355,22 +376,15 @@ const ModelArray = [
photoUrl:'String',//证件照图片地址 蓝底证件照 photoUrl:'String',//证件照图片地址 蓝底证件照
workUnit:'String',//工作单位 workUnit:'String',//工作单位
workTitle:'String',//职称 workTitle:'String',//职称
userRegisterState:{type:'Number', default:USERREGISTERSTATE.待审核, index:true},//用户注册状态 枚举
registerFlow:'Number',//会员注册流程 枚举
auditTime:'Number',//审核时间
memberState:{type:'Number', default:MEMBERSTATE.正常, index:true},//会员状态 枚举
askForTime:'Number',//申请时间
joinTime:'Number',//入会时间
session:'String',//届次 session:'String',//届次
memberLevel:'Number',//会员等级、职务 枚举 memberLevel:'Number',//会员等级、职务 枚举
lifespanStartTime:'Number',//会员有效期开始时间 时间戳
lifespanEndTime:'Number',//会员有效期结束时间 时间戳
isGracePeriod:{type:'Number', default:0},//是否宽限期 0:否, 1:是
gracePeriodEndTime:'Number',//宽限期到期时间 时间戳
certificateType:'Number',//证书类型 枚举 certificateType:'Number',//证书类型 枚举
education:'Number',//学历 education:'Number',//学历
applicationForm:'String',//入会申请表 applicationForm:'String',//入会申请表
unitName:'String',//单位名称 unitName:'String',//单位名称
uscc:'String',//统一信用代码 uscc:'String',//统一信用代码
legalPerson:'String',//法人 legalPerson:'String',//法人
...@@ -439,6 +453,8 @@ const ModelArray = [ ...@@ -439,6 +453,8 @@ const ModelArray = [
loginId:{type:'String', index:true},//登陆名 loginId:{type:'String', index:true},//登陆名
phone:"String",//登陆手机号 phone:"String",//登陆手机号
paymentNum:'String',//支付单号(与订单号不一样) paymentNum:'String',//支付单号(与订单号不一样)
memberCategory:'Number',//会员类别 枚举 MEMBERTYPE
weChartPR:"String",//微信订单号 微信支付用
// membershipFeesType:'Number',//会费类别 枚举 // membershipFeesType:'Number',//会费类别 枚举
invoiceAdd:'String',//发票图片地址 invoiceAdd:'String',//发票图片地址
isFirst:{type:'Boolean', default:true},//首次订单 isFirst:{type:'Boolean', default:true},//首次订单
...@@ -448,21 +464,17 @@ const ModelArray = [ ...@@ -448,21 +464,17 @@ const ModelArray = [
confirmReceipt:{type:'Number', default:RECEIPTCONFIRMATION.待确认},//收款确认【财务核对页收款确认】 confirmReceipt:{type:'Number', default:RECEIPTCONFIRMATION.待确认},//收款确认【财务核对页收款确认】
invoiceStatus:{type:'Number', default:INVOICESTATUS.不具备开票条件, index:true},//发票状态 枚举 INVOICESTATUS 【待开发票页上传发票之后更新状态】 invoiceStatus:{type:'Number', default:INVOICESTATUS.不具备开票条件, index:true},//发票状态 枚举 INVOICESTATUS 【待开发票页上传发票之后更新状态】
advanceInvoice:{type:'Boolean', default:false},//是否提前开票 【个人列表页提交开发票按钮】 advanceInvoice:{type:'Boolean', default:false},//是否提前开票 【个人列表页提交开发票按钮】
// memberCategory:'Number',//会员类别 枚举 MEMBERTYPE
// weChartPR:"String",//微信订单号
} }
}, },
{ {
tableName:TABLEENUM.验证码表, tableName:TABLEENUM.验证码表,
source:TABLESOURCEENUM.mongo, source:TABLESOURCEENUM.mongo,
schema:{ schema:{
codeId:{type:'String', index:true}, phone:{type:'String', index:true},//电话号码
codeNum:'String', code:'String',
sendMs:'Number',//下发时间 时间戳 sendMs:{type:'Number', index:true},//下发时间 时间戳
phone:{type:'String', index:true},//用户电话 type:'Number',//验证码类型 枚举 CODETYPE
type:'Number',//验证码类型 isUse:{type:'Boolean', index:true, default:false},//是否已使用 默认false
isUse:{type:'Boolean', default:false},//是否使用 默认false
} }
}, },
{ {
......
...@@ -27,8 +27,19 @@ export async function findOnce(tableEnumValue:string, param:object, files?) { ...@@ -27,8 +27,19 @@ export async function findOnce(tableEnumValue:string, param:object, files?) {
return data; return data;
} }
export async function findOnceToSort(tableEnumValue:string, param:object, sortParam, files?) {
let data = await dataModels[tableEnumValue].findOne(param, files).sort(sortParam);
return data;
}
export async function find(tableEnumValue:string, param, files?) { export async function find(tableEnumValue:string, param, files?) {
files = files || []; files = files || [];
let data = await dataModels[tableEnumValue].find(param, files); let data = await dataModels[tableEnumValue].find(param, files);
return data; return data;
}
export async function findToSort(tableEnumValue:string, param, sortParam, files?) {
files = files || [];
let data = await dataModels[tableEnumValue].find(param, files).sort(sortParam);
return data;
} }
\ No newline at end of file
...@@ -281,15 +281,14 @@ export const Config = { ...@@ -281,15 +281,14 @@ export const Config = {
{ {
key:"form", type:"Object", sub: key:"form", type:"Object", sub:
{ {
loginId:{type:'String', desc:'用户名', notMustHave:false}, loginId:{type:'String', desc:'用户名'},
mail:{type:'String', desc:'邮箱', notMustHave:false}, mail:{type:'String', desc:'邮箱'},
pwd:{type:'String', desc:'密码', notMustHave:false}, pwd:{type:'String', desc:'密码'},
confirmation:{type:'String', desc:'确认密码', notMustHave:false}, confirmation:{type:'String', desc:'确认密码'},
phone:{type:'String', desc:'联系人手机号', notMustHave:false}, phone:{type:'String', desc:'联系人手机号'},
codeNum:{type:'String', desc:'验证码', notMustHave:false}, codeNum:{type:'String', desc:'验证码'},
} }
}, }
{key:"codeId", type:"String", desc:"验证码Id"}
], ],
bindBiz:memberBiz.memberRegister1 bindBiz:memberBiz.memberRegister1
}, },
......
...@@ -56,10 +56,10 @@ export function generateUserId() { ...@@ -56,10 +56,10 @@ export function generateUserId() {
* 获取一个随机6位数的验证码 * 获取一个随机6位数的验证码
* @returns * @returns
*/ */
export function getSMSCode() { export function generateSMSCode() {
let code = ``; let code = ``;
for (let i =0; i < 6; i++) { for (let i =0; i < 6; i++) {
code += Math.floor(Math.random() * 10) code += Math.floor(Math.random() * 10);
} }
return code; return code;
} }
...@@ -78,8 +78,7 @@ export function generateOrderId(userId:string) { ...@@ -78,8 +78,7 @@ export function generateOrderId(userId:string) {
* @returns * @returns
*/ */
export function getTodayMs() { export function getTodayMs() {
let t =`${ moment().format("YYYY-MM-DD")} 00:00:00`; return new Date(`${ moment().format("YYYY-MM-DD")} 00:00:00`).valueOf();
return new Date(t).valueOf();
} }
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