招生报名缴费小程序开发笔记(上)

前期调研

  • 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|default=1|comment=状态 0=未启用,1=使用中',ACTIVITY_CATE_ID: 'string|true|default=0|comment=分类',ACTIVITY_CATE_NAME: 'string|false|comment=分类冗余',ACTIVITY_CANCEL_SET: 'int|true|default=1|comment=取消设置 0=不允,1=允许,2=仅截止前可取消',ACTIVITY_CHECK_SET: 'int|true|default=0|comment=审核 0=不需要审核,1=需要审核', ACTIVITY_MAX_CNT: 'int|true|default=20|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|default=9999',ACTIVITY_VOUCH: 'int|true|default=0',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|default=0',ACTIVITY_COMMENT_CNT: 'int|true|default=0',ACTIVITY_METHOD: 'int|true|default=0|comment=支付方式 0=线下,1=线上',ACTIVITY_FEE: 'int|false|comment=支付金额 分',ACTIVITY_JOIN_CNT: 'int|true|default=0',ACTIVITY_PAY_CNT: 'int|true|default=0|comment=支付数',ACTIVITY_PAY_FEE: 'int|true|default=0|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|default=0|comment=是否管理员添加 0/1',ACTIVITY_JOIN_CANCEL_TIME: 'int|true|default=0|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|default=1|comment=状态  0=待审核 1=报名成功, 98=自己取消,99=审核未过/取消',ACTIVITY_JOIN_REASON: 'string|false|comment=审核拒绝或者取消理由',ACTIVITY_JOIN_FEE: 'int|true|default=0|comment=需支付费用 分',ACTIVITY_JOIN_PAY_TRADE_NO: 'string|false|comment=商家订单号 32位',ACTIVITY_JOIN_PAY_STATUS: 'int|true|default=0|comment=支付状态 0=未支付 1=已支付 8=已退款 99=无需支付',ACTIVITY_JOIN_PAY_FEE: 'int|true|default=0|comment=已支付费用 分',ACTIVITY_JOIN_PAY_TIME: 'int|true|default=0|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

下载地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/174017.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

进行商城的测试用例设计思路是什么?

进行商城的测试用例设计时&#xff0c;可以考虑以下思路&#xff1a; 1. 功能测试&#xff1a;测试商城的基本功能是否正常工作&#xff0c;包括用户注册、登录、浏览商品、搜索商品、添加商品到购物车、下单、支付等。 2. 数据验证测试&#xff1a;验证商城中的数据是否正确…

HarmonyOS 快速入门TypeScript

1.什么是TypeScript&#xff0c;它和JavaScript&#xff0c;ArkTs有什么区别 ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript&#xff08;简称TS&#xff09;的基础上&#xff0c;匹配ArkUI框架&#xff0c;扩展了声明式UI、状态管理等相应的能力&#xff0c;让开发…

jenkins自动化操作步骤(gitblit)

1、登陆地址&#xff1a; http://xxxxxxxxx.org:xxxx/ admin/xxxx 2、创建任务 选择构建一个maven项目 3、配置 最多只保留一天一个任务 选择git仓库和账号密码 选择代码对应分支 build项&#xff1a; 1&#xff09;使用父项目的pom文件&#xff1a;k56-boot/pom.xml 2&…

《python语言程序设计》(2018版)第5章编程题 第41题第3次路过。总结一下。没有走完的路

这道题最大的需要就是能够进行两个数值的对比&#xff0c;同时还能让更多的数值依次进入到对比中。 这道题的解题版本 这个版本只是能统计出谁是最大数。但是无法统计最大数出现了多少次。 number "" count 0 data_number 0 while number ! 0:number eval(inpu…

Babylonjs学习笔记(五)——创建PBR材质

书接上回&#xff0c;这里讨论PBR材质&#xff01;&#xff01;&#xff01; // 创建天空盒/* */const createSkyBox (scene:Scene):void>{const envTex CubeTexture.CreateFromPrefilteredData(./env/environment.env,scene)scene.environmentTexture envTex;scene.cre…

基于元模型优化算法的主从博弈多虚拟电厂动态定价和能量管理MATLAB程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 参考文献&#xff1a; 基于元模型优化算法的主从博弈多虚拟电厂动态定价和能量管理_董雷 仿真平台&#xff1a; MATLABcplex 主要内容&#xff1a; 主要为多虚拟电厂/微网的优化调度策略&#xff0c;模型…

Stable Diffusion AI绘图

提示词&#xff1a; masterpiece, best quality, 1girl, (anime), (manga), (2D), half body, perfect eyes, both eyes are the same, Global illumination, soft light, dream light, digital painting, extremely detailed CGI anime, hd, 2k, 4k background 反向提示词&…

在Go项目中二次封装Kafka客户端功能

1.摘要 在上一章节中,我利用Docker快速搭建了一个Kafka服务,并测试成功Kafka生产者和消费者功能,本章内容尝试在Go项目中对Kafka服务进行封装调用, 实现从Kafka自动接收消息并消费。 在本文中使用了Kafka的一个高性能开源库Sarama, Sarama是一个遵循MIT许可协议的Apache Kafk…

Flask路由机制分析之二

一、前言 上篇 《Flask 路由机制分析之一》主要讲了Python函数的特性以及装饰器的基本概念&#xff0c;这节我们具体分析一下路由内部机制&#xff0c;Flask路由依赖于werkzegu的routing模块来实现。 二、werkzegu的routing模块介绍 Werkzegu库的routing模块主要功能在于URL…

PDF 文档处理:使用 Java 对比 PDF 找出内容差异

不论是在团队写作还是在个人工作中&#xff0c;PDF 文档往往会经过多次修订和更新。掌握 PDF 文档内容的变化对于管理文档有极大的帮助。通过对比 PDF 文档&#xff0c;用户可以快速找出文档增加、删除和修改的内容&#xff0c;更好地了解文档的演变过程&#xff0c;轻松地管理…

大数据Flink(一百零五):SQL性能调优

文章目录 SQL性能调优 一、 ​​​​​​​MiniBatch 聚合

企业如何安全跨国传输30T文件数据

对于一些对数据敏感性比较高的企业&#xff0c;如IT企业和国企等&#xff0c;跨国数据传输是当今企业面临的一个重要挑战&#xff0c;尤其是当数据量达到30T这样的规模时&#xff0c;如何保证数据的速度、安全和合规性&#xff0c;就成为了企业必须考虑的问题。本文将从以下几个…

计算机毕业设计选题推荐-周边美食推荐微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

大数据-Storm流式框架(八)---Storm案例

中国移动项目部署文档 一、项目架构 二、启动集群 1、启动Zookeeper集群 2、启动Hbase&#xff08;完全分布式需要先启动Hadoop集群&#xff09; 在conf/hbase-env.sh中设置JAVA_HOME 在conf/hbase-site.xml中&#xff0c;仅需要指定hbase和zookeeper写数据的本地路径。默…

2023 年值得关注的国外网络安全初创公司

网络安全初创公司试图解决的问题往往有点超前于主流。他们可以比大多数老牌公司更快地填补空白或新兴需求。初创公司通常可以更快地创新&#xff0c;因为它们不受安装基础的限制。 当然&#xff0c;缺点是初创公司往往缺乏资源和成熟度。公司致力于初创公司的产品或平台是有风…

Spring Web MVC入门

一&#xff1a;了解Spring Web MVC (1)关于Java开发 &#x1f31f;Java开发大多数场景是业务开发 比如说京东的业务就是电商卖货、今日头条的业务就推送新闻&#xff1b;快手的业务就是短视频推荐 (2)Spring Web MVC的简单理解 &#x1f497;Spring Web MVC&#xff1a;如何使…

缓解大模型幻觉问题的解决方案

本文记录大模型幻觉问题的相关内容。 参考&#xff1a;Mitigating LLM Hallucinations: a multifaceted approach 地址&#xff1a;https://amatriain.net/blog/hallucinations &#xff08;图&#xff1a;解决大模型幻觉的不同方式&#xff09; 什么是幻觉&#xff1f; 幻觉…

常见面试题-MySQL专栏(一)

为什么 mysql 删了行记录&#xff0c;反而磁盘空间没有减少&#xff1f; 答&#xff1a; 在 mysql 中&#xff0c;当使用 delete 删除数据时&#xff0c;mysql 会将删除的数据标记为已删除&#xff0c;但是并不去磁盘上真正进行删除&#xff0c;而是在需要使用这片存储空间时&…

Linux之线程池

线程池 线程池概念线程池的应用场景线程池实现原理单例模式下线程池实现STL、智能指针和线程安全其他常见的各种锁 线程池概念 线程池&#xff1a;一种线程使用模式。 线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待…

如何在Node.js中使用环境变量或命令行参数来设置HTTP爬虫ip?

首先&#xff0c;定义问题&#xff1a;在 Node.js 应用程序中&#xff0c;我们可以通过环境变量或命令行参数来设置HTTP爬虫ip&#xff0c;以便在发送请求时使用这些HTTP爬虫ip。 亲身经验&#xff1a;我曾经需要为一个项目设置HTTP爬虫ip&#xff0c;以便在发送请求时使用这些…