从0到1:志愿者小程序开发心得

背景调研

志愿者服务小程序可以使志愿服务更加有序和高效,方便志愿者参与,也方便组织方管理和组织志愿服务活动;志愿者可以方便的在手机上报名,查看记录,获取积分,了解积分排行; 同时提供积分商城模块,可以让志愿者使用通过参与活动所获得的积分来兑换各种奖励或福利.

功能规划

【用户端】
  • 活动浏览: 志愿者可以浏览各种志愿服务活动,了解项目的具体内容、时间和地点等信息。
  • 在线报名: 提供在线报名功能,志愿者可以方便地选择感兴趣的活动并提交报名申请。
  • 个人信息管理: 志愿者可以管理个人信息,包括联系方式、技能和经验等。
  • 志愿服务活动记录: 记录志愿者的活动历史,包括参与的活动、服务获取积分等。
  • 积分获取和排行榜:每次活动可以获得一定数量的积分,后台也可以手工给与特别贡献者额外积分奖励。并按积分进行排行张榜公布。
  • 积分商城: 提供各种商品或服务供志愿者兑换,可以包括礼品、优惠券、志愿者服务证书、特殊活动的参与资格等。
【管理端】
  • 活动发布:发布新的志愿服务项目,包括项目介绍、时间、地点和所需人数,完成活动获取积分数等信息。
  • 报名管理: 管理方便地查看志愿者的报名情况,确保志愿者的匹配和合格。并可以导出每次报名的Excel名单。
  • 积分商城管理:可以录入可供兑换的商品信息,并设置所需积分数。
  • 积分兑换订单:可以检索和查看用户兑换记录,并设定是否领取的状态;也可以取消某订单。
  • 用户管理:查看和检索用户资料,积分明细,并手工给与特别贡献者额外积分奖励;也可以导出用户资料为Excel。
  • 统计分析: 可以按月统计本月注册人数,活动发起数,报名人数,签到人数等 。

概要设计

在这里插入图片描述

数据库设计


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_CHECK_REASON: 'string|false|comment=审核理由',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_MAX_CNT: 'int|true|default=20|comment=人数上限 0=不限',ACTIVITY_START: 'int|false|comment=活动时间',ACTIVITY_START_DAY: 'string|false',ACTIVITY_BEGIN: 'int|true|default=0|comment=报名开始时间',ACTIVITY_STOP: 'int|true|default=0|comment=报名截止时间',ACTIVITY_ADD_MONTH: 'string|false',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_ADDRESS: 'string|false|comment=详细地址',ACTIVITY_ADDRESS_GEO: 'object|false|comment=详细地址坐标参数',ACTIVITY_QR: 'string|false',ACTIVITY_VIEW_CNT: 'int|true|default=0',ACTIVITY_JOIN_CNT: 'int|true|default=0',ACTIVITY_COMMENT_CNT: 'int|true|default=0',ACTIVITY_ADD_TIME: 'int|true',ACTIVITY_EDIT_TIME: 'int|true',ACTIVITY_ADD_IP: 'string|false',ACTIVITY_EDIT_IP: 'string|false',
};
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_CODE: 'string|true|comment=核验码15位',ACTIVITY_JOIN_IS_CHECKIN: 'int|true|default=0|comment=是否签到 0/1 ',ACTIVITY_JOIN_CHECKIN_TIME: 'int|false|default=0|签到时间',ACTIVITY_JOIN_USER_ID: 'string|true|comment=用户ID',ACTIVITY_JOIN_SCORE: 'int|true|default=0|comment=获取积分',ACTIVITY_JOIN_FORMS: 'array|true|default=[]|comment=表单',ACTIVITY_JOIN_OBJ: 'object|true|default={}',ACTIVITY_JOIN_STATUS: 'int|true|default=1|comment=状态 1=报名成功, 99=系统取消',ACTIVITY_JOIN_REASON: 'string|false|comment=取消理由',ACTIVITY_JOIN_ADD_MONTH: 'string|false',ACTIVITY_JOIN_ADD_TIME: 'int|true',ACTIVITY_JOIN_EDIT_TIME: 'int|true',ACTIVITY_JOIN_ADD_IP: 'string|false',ACTIVITY_JOIN_EDIT_IP: 'string|false',
};

核心算法

// 获取当前活动状态getJoinStatusDesc(activity) {let timestamp = this._timestamp;if (activity.ACTIVITY_STATUS == ActivityModel.STATUS.UNUSE)return '活动停止';else if (activity.ACTIVITY_START_DAY < timeUtil.time('Y-M-D'))return '活动结束';else if (activity.ACTIVITY_BEGIN > timestamp)return '报名未开始';else if (activity.ACTIVITY_STOP <= timestamp)return '报名结束';else if (activity.ACTIVITY_MAX_CNT > 0&& activity.ACTIVITY_JOIN_CNT >= activity.ACTIVITY_MAX_CNT)return '报名已满';elsereturn '报名中';}/** 浏览信息 */async viewActivity(userId, id) {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: ActivityJoinModel.STATUS.SUCC}let activityJoin = await ActivityJoinModel.getOne(whereJoin);if (activityJoin) {activity.myActivityJoinId = activityJoin._id;activity.myActivityJoinTag = '已报名';}else {activity.myActivityJoinId = '';activity.myActivityJoinTag = '';}return activity;}/** 取得分页列表 */async getActivityList(type = 'run', {cateId, //分类查询条件search, // 搜索条件sortType, // 搜索菜单sortVal, // 搜索菜单orderBy, // 排序 page,size,isTotal = true,oldTotal}) {orderBy = orderBy || {'ACTIVITY_ORDER': 'asc','ACTIVITY_START': 'asc','ACTIVITY_ADD_TIME': 'desc'};let fields = 'ACTIVITY_ADDRESS,ACTIVITY_STOP,ACTIVITY_BEGIN,ACTIVITY_JOIN_CNT,ACTIVITY_OBJ,ACTIVITY_VIEW_CNT,ACTIVITY_TITLE,ACTIVITY_MAX_CNT,ACTIVITY_START_DAY,ACTIVITY_START,ACTIVITY_ORDER,ACTIVITY_STATUS,ACTIVITY_CATE_NAME,ACTIVITY_OBJ.cover,ACTIVITY_OBJ.score';let where = {};if (cateId && cateId !== '0') where.ACTIVITY_CATE_ID = cateId;where.ACTIVITY_STATUS = ActivityModel.STATUS.COMM; // 状态  // 进行状态let day = timeUtil.time('Y-M-D');if (type == 'run') {where.ACTIVITY_START_DAY = ['>=', day];}else {where.ACTIVITY_START_DAY = ['<', day];orderBy = {'ACTIVITY_ORDER': 'asc','ACTIVITY_START': 'desc','ACTIVITY_ADD_TIME': 'desc'};}if (util.isDefined(search) && search) {where['ACTIVITY_TITLE'] = ['like', search];} else if (sortType && util.isDefined(sortVal)) {// 搜索菜单switch (sortType) {case 'cateId': {if (sortVal) where.ACTIVITY_CATE_ID = String(sortVal);break;}case 'sort': {// 排序orderBy = this.fmtOrderBySort(sortVal, 'ACTIVITY_ADD_TIME');break;}}}let ret = await ActivityModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);if (ret) ret.type = type;return ret;}/** 取得我的报名分页列表 */async getMyActivityJoinList(userId, {search, // 搜索条件sortType, // 搜索菜单sortVal, // 搜索菜单orderBy, // 排序 page,size,isTotal = true,oldTotal}) {orderBy = orderBy || {'ACTIVITY_JOIN_ADD_TIME': 'desc'};let fields = 'ACTIVITY_JOIN_IS_CHECKIN,ACTIVITY_JOIN_REASON,ACTIVITY_JOIN_ACTIVITY_ID,ACTIVITY_JOIN_STATUS,ACTIVITY_JOIN_ADD_TIME,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 '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');}return activityJoin;}//################## 报名 // 报名 async activityJoin(userId, activityId, forms) {// 报名是否结束let whereActivity = {_id: activityId,ACTIVITY_STATUS: ActivityModel.STATUS.COMM}let activity = await ActivityModel.getOne(whereActivity);if (!activity)this.AppError('该活动不存在或者已经结束');// 是否报名开始if (activity.ACTIVITY_BEGIN > this._timestamp)this.AppError('该活动报名报名尚未开始,请耐心等待');// 是否过了报名截止期if (activity.ACTIVITY_STOP < this._timestamp)this.AppError('该活动报名已经截止,请选择其他活动');// 人数是否满if (activity.ACTIVITY_MAX_CNT > 0) {let whereCnt = {ACTIVITY_JOIN_ACTIVITY_ID: activityId,ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC}let cntJoin = await ActivityJoinModel.count(whereCnt);if (cntJoin >= activity.ACTIVITY_MAX_CNT)this.AppError('该活动报名已满,请选择其他活动');}// 自己是否已经有报名let whereMy = {ACTIVITY_JOIN_USER_ID: userId,ACTIVITY_JOIN_ACTIVITY_ID: activityId,ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC}let my = await ActivityJoinModel.getOne(whereMy);if (my) {this.AppError('您已经报名成功,无须重复报名');}// 入库let data = {ACTIVITY_JOIN_ADD_MONTH: activity.ACTIVITY_ADD_MONTH,ACTIVITY_JOIN_USER_ID: userId,ACTIVITY_JOIN_ACTIVITY_ID: activityId,ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC,ACTIVITY_JOIN_FORMS: forms,ACTIVITY_JOIN_OBJ: dataUtil.dbForms2Obj(forms),ACTIVITY_JOIN_CODE: dataUtil.genRandomIntString(15),}let activityJoinId = await ActivityJoinModel.insert(data);// 报名统计数量await this.statActivityJoin(activityId);// 月统计 let statService = new StatService();statService.statJoinMonth(activity.ACTIVITY_ADD_MONTH);return { activityJoinId }}async statActivityJoin(id) {// 报名数let where = {ACTIVITY_JOIN_ACTIVITY_ID: id,ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC}let cnt = await ActivityJoinModel.count(where);await ActivityModel.edit(id, { ACTIVITY_JOIN_CNT: cnt });}/**  报名前获取关键信息 */async detailForActivityJoin(userId, activityId) {let fields = 'ACTIVITY_JOIN_FORMS, ACTIVITY_TITLE';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 joinMy = await ActivityJoinModel.getOne(whereMy, 'ACTIVITY_JOIN_FORMS', orderByMy);let myForms = joinMy ? joinMy.ACTIVITY_JOIN_FORMS : [];if (myForms.length == 0) {let user = await UserModel.getOne({ USER_MINI_OPENID: userId, USER_STATUS: UserModel.STATUS.COMM });if (!user) this.AppError('用户异常');// 取得我的报名信息myForms = [{ mark: 'name', type: 'text', title: '姓名', val: user.USER_NAME },{ mark: 'phone', type: 'mobile', title: '手机', val: user.USER_MOBILE },]}activity.myForms = myForms;return activity;}/** 取消我的报名 只有成功可以取消 取消即为删除记录 */async cancelMyActivityJoin(userId, activityJoinId) {let where = {ACTIVITY_JOIN_USER_ID: userId,_id: activityJoinId,ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC};let activityJoin = await ActivityJoinModel.getOne(where);if (!activityJoin) {this.AppError('未找到可取消的报名记录');}if (activityJoin.ACTIVITY_JOIN_IS_CHECKIN == 1)this.AppError('该活动已经签到,无法取消');let activity = await ActivityModel.getOne(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID);if (!activity)this.AppError('该活动不存在');if (activity.ACTIVITY_STATUS == ActivityModel.STATUS.UNUSE)this.AppError('该活动已停止,不能取消');if (activity.ACTIVITY_CANCEL_SET == 0)this.AppError('该活动不能取消');if (activity.ACTIVITY_CANCEL_SET == 2 && activity.ACTIVITY_STOP < this._timestamp)this.AppError('该活动已经截止报名,不能取消');await ActivityJoinModel.del(where);// 报名数量统计await this.statActivityJoin(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID);// 月统计 let statService = new StatService();statService.statJoinMonth(activity.ACTIVITY_ADD_MONTH);}/** 用户自助签到 */async myJoinSelf(userId, activityId) {let activity = await ActivityModel.getOne({ _id: activityId, ACTIVITY_STATUS: ActivityModel.STATUS.COMM });if (!activity)return { ret: '活动不存在或者已经关闭' };if (activity.ACTIVITY_START_DAY != timeUtil.time('Y-M-D'))return { ret: '仅在活动当天可以签到,当前签到码日期是' + activity.ACTIVITY_START_DAY };let whereCheckin = {ACTIVITY_JOIN_USER_ID: userId,ACTIVITY_JOIN_ACTIVITY_ID: activityId,ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC}let activityJoin = await ActivityJoinModel.getOne(whereCheckin);let ret = '';if (!activityJoin) {ret = '您没有本次活动报名成功的记录,请在「个人中心 - 我的活动报名」查看详情~';return { ret };}if (activityJoin.ACTIVITY_JOIN_IS_CHECKIN == 1) {ret = '本次活动您已签到,无须重复签到,请在「个人中心 - 我的活动报名」查看详情~';return { ret };}let score = activity.ACTIVITY_OBJ.score;let where = {ACTIVITY_JOIN_USER_ID: userId,ACTIVITY_JOIN_IS_CHECKIN: 0,ACTIVITY_JOIN_ACTIVITY_ID: activityId,ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC}let data = {ACTIVITY_JOIN_SCORE: score,ACTIVITY_JOIN_IS_CHECKIN: 1,ACTIVITY_JOIN_CHECKIN_TIME: this._timestamp,}await ActivityJoinModel.edit(where, data);if (score > 0)ret = '签到成功,获取积分' + score + '分,请在「个人中心 - 我的活动报名」查看详情~';elseret = '签到成功,请在「个人中心 - 我的活动报名」查看详情~'// 积分let delay = async () => {const ScoreService = require('./score_service.js');let scoreService = new ScoreService();let scoreData = {oid: activityJoin._id,userId,score: score,desc: '参加活动《' + activity.ACTIVITY_TITLE + '》奖励积分'}scoreService.changeScore(null, scoreData);// 月统计 let statService = new StatService();statService.statJoinMonth(activity.ACTIVITY_ADD_MONTH);}delay();return { ret };}/** 按天获取报名项目 */async getActivityListByDay(day) {let start = timeUtil.time2Timestamp(day);let end = start + 86400 * 1000 - 1;let where = {ACTIVITY_STATUS: ActivityModel.STATUS.COMM,ACTIVITY_START: ['between', start, end],};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_START: ['>=', timeUtil.time2Timestamp(fromDay)],};let fields = 'ACTIVITY_START';let list = await ActivityModel.getAllBig(where, fields);let retList = [];for (let k = 0; k < list.length; k++) {let day = timeUtil.timestamp2Time(list[k].ACTIVITY_START, 'Y-M-D');if (!retList.includes(day)) retList.push(day);}return retList;}

UI设计

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码git地址

下载

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

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

相关文章

用23种设计模式打造一个cocos creator的游戏框架----(十九)备忘录模式

1、模式标准 模式名称&#xff1a;备忘录模式 模式分类&#xff1a;行为型 模式意图&#xff1a;在不破坏封装性的前提下捕获一个对象的内部状态&#xff0c;并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态 结构图&#xff1a; 适用于&#xff1a; …

Freemarker基本语法与案例讲解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《SpringBoot》。&#x1f3af;&#x1f3af; &…

Azure Machine Learning - 提示工程简介

OpenAI的GPT-3、GPT-3.5和GPT-4模型基于用户输入的文本提示工作。有效的提示构造是使用这些模型的关键技能&#xff0c;涉及到配置模型权重以执行特定任务。这不仅是技术操作&#xff0c;更像是一种艺术&#xff0c;需要经验和直觉。本文旨在介绍适用于所有GPT模型的提示概念和…

网络(十)ACL和NAT

前言 网络管理在生产环境和生活中&#xff0c;如何实现拒绝不希望的访问连接&#xff0c;同时又要允许正常的访问连接&#xff1f;当下公网地址消耗殆尽&#xff0c;且公网IP地址费用昂贵&#xff0c;企业访问Internet全部使用公网IP地址不够现实&#xff0c;如何让私网地址也…

前端面试(5)

1、移动端适配 1.1、设置meta缩放比例&#xff0c;将设备窗口调整为设计图大小。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,initial-sc…

基于ssm的简单学校课程管理系统的设计与实现(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于ssm的简单学校课程管…

C++之程序生成

一、C的发展史 截止到2023年12月&#xff0c;C已经更新了很多版本&#xff0c;并在每个版本中修复了bug和添加了新的特性&#xff0c;ISO C委员会每三年会对C进行一次更新&#xff1a; C98&#xff1a;于1998年发布&#xff0c;是最早的国际标准化版本。它包含了面向对象编程…

可替代LM5145,5.5V-100V Vin同步降压控制器_SCT82A30

SCT82A30是一款100V电压模式控制同步降压控制器&#xff0c;具有线路前馈。40ns受控高压侧MOSFET的最小导通时间支持高转换比&#xff0c;实现从48V输入到低压轨的直接降压转换&#xff0c;降低了系统复杂性和解决方案成本。如果需要&#xff0c;在低至6V的输入电压下降期间&am…

GMP原理与调度

GMP是Go语言运行时(runtime)层面的实现,是go语言自己实现的一套调度系统,区别于操作系统调度OS线程 Golang"调度器"的由来 单进程时代不需要调度器 我们知道,一切的软件都是跑在操作系统上,真正用来干活(计算)的是CPU,早期的操作系统每个程序就是一个进程,直到一个…

Yapi详细安装过程(亲测可用)

1. 前置条件 1、Git 2、NodeJs&#xff08;7.6&#xff09; 3、Mongodb&#xff08;2.6&#xff09; 2. NodeJs的安装 1、获取资源 curl -sL https://rpm.nodesource.com/setup_8.x | bash - 2、安装NodeJS yum install -y nodejs 3、查看NodeJs和Npm node -v npm -v…

学习MS Dynamics AX 2012编程开发 2. X++语言

X是用于构建Dynamics AX功能的编程语言。X是一种与C类似的面向对象编程语言。 完成本章后&#xff0c;您将能够理解X语言&#xff1b;您将知道可用的数据类型是什么&#xff0c;如何创建各种循环&#xff0c;如何比较和操作变量&#xff0c;在哪里可以找到预定义的函数&#x…

LCR 181. 字符串中的单词反转

解题思路&#xff1a; class Solution {public String reverseMessage(String message) {message message.trim(); // 删除首尾空格int j message.length() - 1, i j;StringBuilder res new StringBuilder();while (i > 0) {while (i >…