网站建设与代运营产品介绍,排版网页设计教程,长沙软件公司排行榜,湖南长沙旅游景点前期调研
1.数字化趋势#xff1a; 随着社会的数字化转型#xff0c;越来越多的教育机构倾向于采用数字工具来简化和优化他们的招生和报名过程。招生报名缴费小程序是应对这一趋势的一种解决方案#xff0c;可以提供高效、方便、快速的在线招生渠道。2.用户需求#xff1a…前期调研
1.数字化趋势 随着社会的数字化转型越来越多的教育机构倾向于采用数字工具来简化和优化他们的招生和报名过程。招生报名缴费小程序是应对这一趋势的一种解决方案可以提供高效、方便、快速的在线招生渠道。2.用户需求 学生和家长希望能够通过手机或电脑完成入学申请和缴费而不必亲自前往学校或教育机构填写纸质表格或排队等候。这种便捷性对于吸引更多申请者和提高报名率非常重要。3.减少错误和欺诈 使用在线报名和缴费系统可以减少手动处理和数据输入错误的风险。此外数字支付方法可以提高资金管理的透明度减少现金管理问题和欺诈风险。4.提高效率 传统的报名流程通常需要大量的人力资源和时间而自动化的招生报名缴费小程序可以大大提高效率减少了繁琐的手工工作。5.竞争优势 对于教育机构而言提供一种现代化、便捷的招生报名流程可以成为他们在竞争激烈的市场中脱颖而出的重要优势。6.数据分析和管理 数字化报名系统可以生成大量数据使教育机构能够更好地了解他们的申请者优化招生流程并进行更精确的市场营销。
综上所述招生报名缴费小程序的开发背景是满足数字化趋势、提供用户需求、提高效率、降低错误和欺诈风险并在教育市场中获得竞争优势。这种小程序为学校、大学和培训机构提供了一个现代化、便捷的方式来管理招生流程同时也为申请者提供更好的用户体验。
功能设计
招生报名缴费小程序是一个用于学校、大学、培训机构或其他教育机构的应用程序旨在帮助学生完成入学申请和支付报名费用。以下是招生报名缴费小程序可能包括的功能和组成部分
1.用户注册与登录 学生和家长需要能够创建个人账户并登录以便访问相关功能。2.招生信息浏览 提供学校或机构的招生信息包括不同课程、入学要求、截止日期等。3.在线报名表格 学生可以填写入学申请表格包括个人信息、学历背景、联系信息等。4.文件上传 允许学生上传必要的文件如身份证、学历证明、推荐信等。5.报名费计算 根据所选课程和选项自动计算报名费用并显示给用户。6.在线支付 提供各种支付选项如信用卡、支付宝、微信支付等以便用户能够方便地支付报名费用。7.报名进度追踪 学生可以查看他们的报名进度了解是否需要提供额外的信息审核状态等。8.通知和提醒 发送通知和提醒以提醒学生关于重要的报名截止日期、文件提交等事项。9.电子收据和确认信 学生完成缴费后能够获得电子收据和入学确认信。 招生报名缴费小程序的设计和开发需要充分考虑用户友好性、安全性和数据保护以确保顺畅的用户体验和数据的安全性。这样的小程序可以极大地简化招生报名过程提高效率同时提供更好的用户体验。
数据库设计 ActivityModel.DB_STRUCTURE {_pid: string|true,ACTIVITY_ID: string|true,ACTIVITY_TITLE: string|true|comment标题,ACTIVITY_STATUS: int|true|default1|comment状态 0未启用,1使用中,ACTIVITY_CATE_ID: string|true|default0|comment分类,ACTIVITY_CATE_NAME: string|false|comment分类冗余,ACTIVITY_CANCEL_SET: int|true|default1|comment取消设置 0不允,1允许,2仅截止前可取消,ACTIVITY_CHECK_SET: int|true|default0|comment审核 0不需要审核,1需要审核, ACTIVITY_MAX_CNT: int|true|default20|comment人数上限 0不限,ACTIVITY_START: int|false|comment开始时间戳,ACTIVITY_END: int|false|comment截止时间戳,ACTIVITY_START_DAY: string|false|comment开始时间,ACTIVITY_END_DAY: string|false|comment截止时间, ACTIVITY_START_MONTH: string|false|comment开始月份,ACTIVITY_END_MONTH: string|false|comment截止月份,ACTIVITY_ORDER: int|true|default9999,ACTIVITY_VOUCH: int|true|default0,ACTIVITY_FORMS: array|true|default[],ACTIVITY_OBJ: object|true|default{},ACTIVITY_JOIN_FORMS: array|true|default[], ACTIVITY_QR: string|false,ACTIVITY_VIEW_CNT: int|true|default0,ACTIVITY_COMMENT_CNT: int|true|default0,ACTIVITY_METHOD: int|true|default0|comment支付方式 0线下1线上,ACTIVITY_FEE: int|false|comment支付金额 分,ACTIVITY_JOIN_CNT: int|true|default0,ACTIVITY_PAY_CNT: int|true|default0|comment支付数,ACTIVITY_PAY_FEE: int|true|default0|comment支付额, ACTIVITY_ADD_TIME: int|true,ACTIVITY_EDIT_TIME: int|true,ACTIVITY_ADD_IP: string|false,ACTIVITY_EDIT_IP: string|false,
};// 字段前缀
ActivityModel.FIELD_PREFIX ACTIVITY_;/*** 状态 0未启用,1使用中 */
ActivityModel.STATUS {UNUSE: 0,COMM: 1
};ActivityJoinModel.DB_STRUCTURE {_pid: string|true,ACTIVITY_JOIN_ID: string|true,ACTIVITY_JOIN_ACTIVITY_ID: string|true|comment报名PK,ACTIVITY_JOIN_IS_ADMIN: int|true|default0|comment是否管理员添加 0/1,ACTIVITY_JOIN_CANCEL_TIME: int|true|default0|comment取消时间,ACTIVITY_JOIN_USER_ID: string|true|comment用户ID,ACTIVITY_JOIN_FORMS: array|true|default[]|comment表单,ACTIVITY_JOIN_OBJ: object|true|default{},ACTIVITY_JOIN_STATUS: int|true|default1|comment状态 0待审核 1报名成功, 98自己取消,99审核未过/取消,ACTIVITY_JOIN_REASON: string|false|comment审核拒绝或者取消理由,ACTIVITY_JOIN_FEE: int|true|default0|comment需支付费用 分,ACTIVITY_JOIN_PAY_TRADE_NO: string|false|comment商家订单号 32位,ACTIVITY_JOIN_PAY_STATUS: int|true|default0|comment支付状态 0未支付 1已支付 8已退款 99无需支付,ACTIVITY_JOIN_PAY_FEE: int|true|default0|comment已支付费用 分,ACTIVITY_JOIN_PAY_TIME: int|true|default0|comment支付时间,ACTIVITY_JOIN_ADD_TIME: int|true,ACTIVITY_JOIN_EDIT_TIME: int|true,ACTIVITY_JOIN_ADD_IP: string|false,ACTIVITY_JOIN_EDIT_IP: string|false,
};// 字段前缀
ActivityJoinModel.FIELD_PREFIX ACTIVITY_JOIN_;/*** 状态 0待审核 1报名成功, 99审核未过*/
ActivityJoinModel.STATUS {WAIT: 0,SUCC: 1,CANCEL: 98,ADMIN_CANCEL: 99
};ActivityJoinModel.STATUS_DESC {WAIT: 待审核,SUCC: 成功,CANCEL: 取消,ADMIN_CANCEL: 审核未过
};代码核心
async minuteJob() {console.log(### minuteJob );// 未支付的成功订单取消 let time this._timestamp - 6 * 60 * 1000;console.log(###### Begin 未支付订单6分钟后取消, time time , timeUtil.timestamp2Time(time));let where {ACTIVITY_JOIN_STATUS: [in, [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]],ACTIVITY_JOIN_PAY_STATUS: 0,ACTIVITY_JOIN_ADD_TIME: [, time],}let rows await ActivityJoinModel.getAll(where, *, {}, 3000, false);console.log(未支付订单6分钟后取消 count, rows.length);for (let k in rows) {let activityJoin rows[k];let tradeNo activityJoin.ACTIVITY_JOIN_PAY_TRADE_NO;if (!await this.fixActivityJoinPay(tradeNo, activityJoin.ACTIVITY_JOIN_ACTIVITY_ID)) {console.log(该报名记录未支付已取消并删除, activityJoin);}}console.log(###### END. 未支付订单6分钟后取消);}// 获取当前报名状态getJoinStatusDesc(activity) {let timestamp this._timestamp;if (activity.ACTIVITY_STATUS 0)return 报名停止;else if (activity.ACTIVITY_START timestamp)return 报名未开始;else if (activity.ACTIVITY_END timestamp)return 报名截止;else if (activity.ACTIVITY_MAX_CNT 0 activity.ACTIVITY_JOIN_CNT activity.ACTIVITY_MAX_CNT)return 报名已满;elsereturn 报名中;}/** 浏览信息 */async viewActivity(userId, id) {await this.fixUserActivityJoinPayRecord(userId);let fields *;let where {_id: id,ACTIVITY_STATUS: ActivityModel.STATUS.COMM}let activity await ActivityModel.getOne(where, fields);if (!activity) return null;ActivityModel.inc(id, ACTIVITY_VIEW_CNT, 1);// 判断是否有报名let whereJoin {ACTIVITY_JOIN_USER_ID: userId,ACTIVITY_JOIN_ACTIVITY_ID: id,ACTIVITY_JOIN_STATUS: [in, [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]]}let activityJoin await ActivityJoinModel.getOne(whereJoin);if (activityJoin) {activity.myActivityJoinId activityJoin._id;activity.myActivityJoinTag (activityJoin.ACTIVITY_JOIN_STATUS ActivityJoinModel.STATUS.WAIT) ? 待审核 : 已报名;if (activity.myActivityJoinTag 已报名 activityJoin.ACTIVITY_JOIN_PAY_STATUS 1) {activity.myActivityJoinTag 已报名缴费;}}else {activity.myActivityJoinId ;activity.myActivityJoinTag ;}return activity;}/** 取得分页列表 */async getActivityList({cateId, //分类查询条件search, // 搜索条件sortType, // 搜索菜单sortVal, // 搜索菜单orderBy, // 排序 page,size,isTotal true,oldTotal}) {orderBy orderBy || {ACTIVITY_ORDER: asc,ACTIVITY_ADD_TIME: desc};let fields ACTIVITY_START_MONTH,ACTIVITY_END_MONTH,ACTIVITY_START_DAY,ACTIVITY_END_DAY,ACTIVITY_JOIN_CNT,ACTIVITY_OBJ,ACTIVITY_VIEW_CNT,ACTIVITY_TITLE,ACTIVITY_MAX_CNT,ACTIVITY_START,ACTIVITY_END,ACTIVITY_ORDER,ACTIVITY_STATUS,ACTIVITY_CATE_NAME,ACTIVITY_OBJ;let where {};where.and {_pid: this.getProjectId() //复杂的查询在此处标注PID};if (cateId cateId ! 0) where.and.ACTIVITY_CATE_ID cateId;where.and.ACTIVITY_STATUS ActivityModel.STATUS.COMM; // 状态 if (util.isDefined(search) search) {where.or [{ACTIVITY_TITLE: [like, search]},];} else if (sortType util.isDefined(sortVal)) {// 搜索菜单switch (sortType) {case cateId: {if (sortVal) where.and.ACTIVITY_CATE_ID String(sortVal);break;}case sort: {// 排序orderBy this.fmtOrderBySort(sortVal, ACTIVITY_ADD_TIME);break;}case today: { //今天let time timeUtil.time(Y-M-D);where.and.ACTIVITY_START_DAY [, time];where.and.ACTIVITY_END_DAY [, time];break;}case tomorrow: { //明日let time timeUtil.time(Y-M-D, 86400);where.and.ACTIVITY_START_DAY [, time];where.and.ACTIVITY_END_DAY [, time];break;}case month: { //本月let month timeUtil.time(Y-M);where.and.ACTIVITY_START_MONTH [, month];where.and.ACTIVITY_END_MONTH [, month];break;}}}return await ActivityModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);}/** 取得我的报名分页列表 */async getMyActivityJoinList(userId, {search, // 搜索条件sortType, // 搜索菜单sortVal, // 搜索菜单orderBy, // 排序 page,size,isTotal true,oldTotal}) {await this.fixUserActivityJoinPayRecord(userId);orderBy orderBy || {ACTIVITY_JOIN_ADD_TIME: desc};let fields ACTIVITY_JOIN_PAY_STATUS,ACTIVITY_JOIN_REASON,ACTIVITY_JOIN_ACTIVITY_ID,ACTIVITY_JOIN_STATUS,ACTIVITY_JOIN_ADD_TIME,activity.ACTIVITY_END,activity.ACTIVITY_START,activity.ACTIVITY_TITLE;let where {ACTIVITY_JOIN_USER_ID: userId};if (util.isDefined(search) search) {where[activity.ACTIVITY_TITLE] {$regex: .* search,$options: i};} else if (sortType) {// 搜索菜单switch (sortType) {case timedesc: { //按时间倒序orderBy {activity.ACTIVITY_START: desc,ACTIVITY_JOIN_ADD_TIME: desc};break;}case timeasc: { //按时间正序orderBy {activity.ACTIVITY_START: asc,ACTIVITY_JOIN_ADD_TIME: asc};break;}case succ: {where.ACTIVITY_JOIN_STATUS ActivityJoinModel.STATUS.SUCC;break;}case wait: {where.ACTIVITY_JOIN_STATUS ActivityJoinModel.STATUS.WAIT;break;}case usercancel: {where.ACTIVITY_JOIN_STATUS ActivityJoinModel.STATUS.CANCEL;break;}case cancel: {where.ACTIVITY_JOIN_STATUS ActivityJoinModel.STATUS.ADMIN_CANCEL;break;}}}let joinParams {from: ActivityModel.CL,localField: ACTIVITY_JOIN_ACTIVITY_ID,foreignField: _id,as: activity,};let result await ActivityJoinModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal);return result;}/** 取得我的报名详情 */async getMyActivityJoinDetail(userId, activityJoinId) {let fields *;let where {_id: activityJoinId,ACTIVITY_JOIN_USER_ID: userId};let activityJoin await ActivityJoinModel.getOne(where, fields);if (activityJoin) {activityJoin.activity await ActivityModel.getOne(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID, ACTIVITY_TITLE,ACTIVITY_START,ACTIVITY_END);}return activityJoin;}// 修正某用户所有未支付的成功订单状态无须支付的不用处理async fixUserActivityJoinPayRecord(userId) {let where {ACTIVITY_JOIN_USER_ID: userId,ACTIVITY_JOIN_PAY_STATUS: 0,ACTIVITY_JOIN_STATUS: [in, [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]],}let list await ActivityJoinModel.getAll(where);for (let k 0; k list.length; k) {await this.fixActivityJoinPay(list[k].ACTIVITY_JOIN_PAY_TRADE_NO, list[k].ACTIVITY_JOIN_ACTIVITY_ID);}}// 修正某订单状态 仅需支付订单async fixActivityJoinPay(tradeNo, activityId) {if (!tradeNo) {// 无支付号空单 删除await ActivityJoinModel.del({ ACTIVITY_JOIN_PAY_TRADE_NO: tradeNo });// 重新统计this.statActivityJoin(activityId);return false;}let payService new PayService();if (!await payService.fixPayResult(tradeNo)) {// 关闭未支付单payService.closePay(tradeNo);// 未支付 await ActivityJoinModel.del({ ACTIVITY_JOIN_PAY_TRADE_NO: tradeNo });// 重新统计this.statActivityJoin(activityId);return false;}// 已支付let pay await PayModel.getOne({ PAY_TRADE_NO: tradeNo });if (!pay) this.AppError(支付流水异常请核查);// 更新支付信息let data {ACTIVITY_JOIN_PAY_STATUS: 1,ACTIVITY_JOIN_PAY_TRADE_NO: tradeNo,ACTIVITY_JOIN_PAY_FEE: pay.PAY_TOTAL_FEE,ACTIVITY_JOIN_PAY_TIME: pay.PAY_END_TIME,}await ActivityJoinModel.edit({ ACTIVITY_JOIN_PAY_TRADE_NO: tradeNo }, data);// 重新统计this.statActivityJoin(activityId);return true;}//################## 报名 // 报名 async prepay(userId, activityId, forms) {this.AppError([招生报名缴费]该功能暂不开放如有需要请加作者微信cclinux0730);}async statActivityJoin(activityId) {// 报名数let where {ACTIVITY_JOIN_ACTIVITY_ID: activityId,ACTIVITY_JOIN_STATUS: [in, [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]]}let cnt await ActivityJoinModel.count(where);// 已支付记录let wherePayCnt {ACTIVITY_JOIN_ACTIVITY_ID: activityId,ACTIVITY_JOIN_PAY_STATUS: 1,ACTIVITY_JOIN_STATUS: [in, [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]]}let payCnt await ActivityJoinModel.count(wherePayCnt);// 已支付金额let wherePayFee {ACTIVITY_JOIN_ACTIVITY_ID: activityId,ACTIVITY_JOIN_PAY_STATUS: 1,ACTIVITY_JOIN_STATUS: [in, [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]]}let payFee await ActivityJoinModel.sum(wherePayFee, ACTIVITY_JOIN_PAY_FEE);let data {ACTIVITY_JOIN_CNT: cnt,ACTIVITY_PAY_CNT: payCnt,ACTIVITY_PAY_FEE: payFee,}await ActivityModel.edit(activityId, data);}/** 报名前获取关键信息 */async detailForActivityJoin(userId, activityId) {await this.fixUserActivityJoinPayRecord(userId);let fields ACTIVITY_JOIN_FORMS, ACTIVITY_TITLE, ACTIVITY_FEE, ACTIVITY_METHOD;let where {_id: activityId,ACTIVITY_STATUS: ActivityModel.STATUS.COMM}let activity await ActivityModel.getOne(where, fields);if (!activity)this.AppError(该报名不存在);let whereMy {ACTIVITY_JOIN_USER_ID: userId,}let orderByMy {ACTIVITY_JOIN_ADD_TIME: desc}//***取得本人所有记录let joinList await ActivityJoinModel.getAll(whereMy, ACTIVITY_JOIN_OBJ,ACTIVITY_JOIN_FORMS, orderByMy);let addressList [];let addressList2 [];for (let k 0; k joinList.length; k) {let exist false;for (let j 0; j addressList.length; j) {if (addressList[j].name joinList[k].ACTIVITY_JOIN_OBJ.name) {exist true;break;}}if (!exist) {addressList.push(joinList[k].ACTIVITY_JOIN_OBJ);addressList2.push(joinList[k].ACTIVITY_JOIN_FORMS);}}// 取出本人最近一次的填写表单let joinMy await ActivityJoinModel.getOne(whereMy, ACTIVITY_JOIN_FORMS, orderByMy);joinMy null;let myForms joinMy ? joinMy.ACTIVITY_JOIN_FORMS : [];activity.myForms myForms;activity.addressList addressList;activity.addressList2 addressList2;activity.ACTIVITY_FEE Number(dataUtil.fmtMoney(activity.ACTIVITY_FEE / 100));return activity;}/** 取消我的报名 只有成功和待审核可以取消 */async cancelMyActivityJoin(userId, activityJoinId) {let where {_id: activityJoinId,ACTIVITY_JOIN_USER_ID: userId,ACTIVITY_JOIN_STATUS: [in, [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]] //只有成功和待审核可以取消};let activityJoin await ActivityJoinModel.getOne(where);if (!activityJoin) {this.AppError(未找到可取消的报名记录);}let activity await ActivityModel.getOne(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID);if (!activity)this.AppError(该报名不存在);if (activity.ACTIVITY_CANCEL_SET 0)this.AppError(该报名不能取消报名);if (activity.ACTIVITY_CANCEL_SET 2 activity.ACTIVITY_END this._timestamp)this.AppError(该报名已经截止无法取消);if (activityJoin.ACTIVITY_JOIN_PAY_STATUS 99) {// 无须支付// 更新记录 let data {ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.CANCEL,ACTIVITY_JOIN_CANCEL_TIME: this._timestamp,}await ActivityJoinModel.edit(activityJoinId, data);}else {let tradeNo activityJoin.ACTIVITY_JOIN_PAY_TRADE_NO;if (!await this.fixActivityJoinPay(tradeNo, activityJoin.ACTIVITY_JOIN_ACTIVITY_ID)) {this.AppError(该报名记录未支付已取消并删除);}let payService new PayService();await payService.refundPay(tradeNo, 用户取消报名);// 更新记录 let data {ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.CANCEL,ACTIVITY_JOIN_CANCEL_TIME: this._timestamp,ACTIVITY_JOIN_PAY_STATUS: 8,}await ActivityJoinModel.edit(activityJoinId, data);}// 统计await this.statActivityJoin(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID);}/** 按天获取报名项目 */async getActivityListByDay(day) {let where {ACTIVITY_START_DAY: [, day],ACTIVITY_END_DAY: [, day]};let orderBy {ACTIVITY_ORDER: asc,ACTIVITY_ADD_TIME: desc};let fields ACTIVITY_TITLE,ACTIVITY_START,ACTIVITY_OBJ.cover;let list await ActivityModel.getAll(where, fields, orderBy);let retList [];for (let k 0; k list.length; k) {let node {};node.timeDesc timeUtil.timestamp2Time(list[k].ACTIVITY_START, h:m);node.title list[k].ACTIVITY_TITLE;node.pic list[k].ACTIVITY_OBJ.cover[0];node._id list[k]._id;retList.push(node);}return retList;}/*** 获取从某天开始可报名的日期* param {*} fromDay 日期 Y-M-D*/async getActivityHasDaysFromDay(fromDay) {let where {ACTIVITY_STATUS: 1,//ACTIVITY_START_DAY: [, fromDay],ACTIVITY_END_DAY: [, fromDay]};let fields ACTIVITY_START_DAY,ACTIVITY_END_DAY;let list await ActivityModel.getAllBig(where, fields);if (list.length 0) return;let min await ActivityModel.min(where, ACTIVITY_START_DAY);let max await ActivityModel.max(where, ACTIVITY_END_DAY);let minTimestamp timeUtil.time2Timestamp(min);let maxTimestamp timeUtil.time2Timestamp(max);let retList [];for (let n minTimestamp; n maxTimestamp; n 86400 * 1000) {let day timeUtil.timestamp2Time(n, Y-M-D);if (day fromDay) continue;for (let k 0; k list.length; k) {if (day list[k].ACTIVITY_START_DAY day list[k].ACTIVITY_END_DAY) {if (!retList.includes(day)) retList.push(day);break;}}}return retList;}管理系统 用户系统设计 代码下载git
下载地址