diff --git a/README.md b/README.md index f0e7c06..9398d82 100644 --- a/README.md +++ b/README.md @@ -1,193 +1,126 @@ # 班级盒子 -班级盒子是一个面向班级场景的微信小程序,用于统一发布和查看考试、作业、活动、通知、资料等班级事项。 +班级盒子是一个面向班级日常事务的微信小程序。它把考试安排、作业信息、活动通知、班级公告、资料链接等内容集中到一个地方,让同学不用再从聊天记录里反复翻找重要信息。 -本仓库是开源副本,不包含正式项目的真实 AppID、云环境 ID、订阅消息模板 ID、openid、班级成员名单、管理员邀请码或云文件地址。 +这个项目适合班级、社团、学习小组或课程团队使用:管理员负责发布和维护事项,成员完成身份认证后即可查看、收藏和订阅提醒。 -## 项目背景 +## 它能解决什么 -这个项目最初用于解决班级通知分散在聊天记录中、不方便查找和整理的问题。开源版本保留了事项管理、成员认证、权限控制和订阅提醒等主要功能,并移除了真实班级数据与运行配置。 +班级信息常常散落在群聊、私聊、文件和截图里。时间一久,考试时间、作业截止日期、活动地点、通知原文都容易被新的消息淹没。 -## 快速开始 +班级盒子提供一个更稳定的入口: -### 1. 前置要求 +- 重要事项统一发布,按类型整理。 +- 每条事项有清晰的时间、地点、课程/活动名称和详细说明。 +- 支持图片、附件和外部链接,资料不再只靠聊天记录转发。 +- 成员可以收藏事项,也可以订阅下一次通知提醒。 +- 管理员可以编辑、删除、置顶自己有权限管理的内容。 -- 微信开发者工具 -- 自己的微信小程序 AppID -- 云开发环境 - -### 2. 克隆项目 - -```bash -git clone https://github.com/Cheems-sudo/Class-Box.git -cd Class-Box -``` - -### 3. 配置文件 - -复制配置文件模板: - -```bash -cp project.config.example.json project.config.json -cp miniprogram/config.example.js miniprogram/config.js -cp cloudfunctions/sendNoticeMessage/config.example.js cloudfunctions/sendNoticeMessage/config.js -cp cloudfunctions/saveNoticeSubscriber/config.example.js cloudfunctions/saveNoticeSubscriber/config.js -``` - -然后编辑这些文件,填入自己的: - -- AppID -- 云环境 ID -- 订阅消息模板 ID - -### 4. 部署 - -1. 在微信开发者工具中打开此项目。 -2. 进入“云开发” → “云函数”。 -3. 右键 `cloudfunctions` 文件夹,选择“增量上传并部署”,部署所有云函数。 -4. 创建数据库集合,见 `docs/database.md` 了解详情。 -5. 点击“预览”在微信中测试。 - -详细步骤见 `docs/deploy.md`。 +## 主要功能 -## 功能特性 +- 班级事项:发布、查看、编辑、删除、置顶。 +- 分类管理:考试安排、作业信息、活动信息、班级通知、其他。 +- 资料补充:支持图片、附件和链接。 +- 收藏列表:保存自己关心的事项。 +- 消息提醒:通过微信订阅消息提醒下一条通知。 +- 身份认证:只允许班级成员进入主要功能。 +- 权限管理:普通成员、管理员、超级管理员分层使用。 +- 安全校验:发布和编辑内容会经过内容安全检测。 +- 操作记录:关键操作会写入日志,便于后续追踪。 -- 班级事项发布、编辑、删除和查看。 -- 按考试安排、作业信息、活动信息、班级通知、其他等类型管理事项。 -- 图片、附件和链接支持。 -- 收藏事项。 -- 首页和事项详情支持好友分享与朋友圈分享。 -- 订阅消息提醒。 -- 班级成员身份认证。 -- 管理员和超级管理员权限体系。 -- 管理员/超级管理员邀请码为一次性使用。 -- 发布事项通过 `createNotice` 云函数完成,避免前端直接写入关键集合。 -- 发布/编辑内容进行内容安全检测。 -- 图片内容安全检测。 -- 关键操作日志记录。 -- 敏感操作通过云函数进行权限校验。 +## 使用角色 -## 权限角色 - -- 未认证用户:只能进行班级身份认证,不能正常使用主要功能。 -- 已认证普通用户:可以查看事项、收藏事项、订阅提醒。 -- 已认证管理员:可以发布事项,并管理自己发布的事项。 -- 已认证超级管理员:可以管理所有事项。 - -## 云函数 - -当前项目使用以下云函数: - -| 云函数 | 说明 | +| 角色 | 可以做什么 | | --- | --- | -| `applyAdminInvite` | 处理一次性管理员/超级管理员邀请码 | -| `checkAdmin` | 判断当前用户身份、认证状态和权限 | -| `contentSecurityCheck` | 对文本、图片等内容进行安全检测 | -| `createNotice` | 通过云函数创建事项,避免前端直接写入关键集合 | -| `deleteNotice` | 删除事项,并进行权限校验 | -| `saveNoticeSubscriber` | 校验当前用户并保存订阅授权,避免前端直接写入订阅集合 | -| `sendNoticeMessage` | 发送订阅消息提醒 | -| `updateNotice` | 编辑事项,并进行权限校验 | -| `updateNoticePin` | 更新事项置顶状态,并进行权限校验 | -| `verifyMember` | 班级成员身份认证 | - -说明:发布、编辑、删除、置顶和管理员授权等关键业务操作均由对应业务云函数完成权限校验,并在业务成功后直接记录操作日志。 +| 未认证用户 | 只能进行班级身份认证 | +| 已认证成员 | 查看事项、收藏事项、订阅提醒 | +| 管理员 | 发布事项,管理自己发布的事项 | +| 超级管理员 | 管理所有事项和关键内容 | -## 配置 +## 页面概览 -### 敏感信息 +- 首页:浏览和筛选班级事项。 +- 详情页:查看事项内容、图片、附件、链接,并进行收藏。 +- 发布页:管理员发布或编辑事项。 +- 我的:查看身份状态、订阅提醒、进入收藏和我的发布。 +- 成员认证:填写姓名和学号完成班级身份认证。 +- 管理员认证:通过一次性邀请码开通管理员权限。 -本仓库不包含真实的 AppID、云环境 ID、邀请码等敏感信息。如需自行部署,请参考 `docs/security.md` 的“不应提交的内容”章节。 +## 自行部署 -### 配置文件 +本仓库是开源版本,不包含正式项目的真实 AppID、云环境 ID、订阅消息模板 ID、openid、班级成员名单、管理员邀请码或云文件地址。 -复制并填写以下配置文件: +如果你想部署自己的班级盒子,需要准备: -1. **`project.config.json`** - 微信开发者工具配置 - - 源文件:`project.config.example.json` - - 需填写:`appid`(你的小程序 AppID) +- 微信开发者工具 +- 微信小程序 AppID +- 微信云开发环境 +- 订阅消息模板 +- 班级成员名单 +- 管理员或超级管理员邀请码 -2. **`miniprogram/config.js`** - 小程序配置 - - 源文件:`miniprogram/config.example.js` - - 需填写:`envId`(云开发环境 ID)、`subscribeTemplateId`(订阅消息模板 ID) +快速步骤: -3. **`cloudfunctions/sendNoticeMessage/config.js`** - 消息发送配置 - - 源文件:`cloudfunctions/sendNoticeMessage/config.example.js` - - 需填写:订阅消息相关配置 +```bash +git clone https://github.com/Cheems-sudo/Class-Box.git +cd Class-Box +cp project.config.example.json project.config.json +cp miniprogram/config.example.js miniprogram/config.js +cp cloudfunctions/sendNoticeMessage/config.example.js cloudfunctions/sendNoticeMessage/config.js +cp cloudfunctions/saveNoticeSubscriber/config.example.js cloudfunctions/saveNoticeSubscriber/config.js +``` -4. **`cloudfunctions/saveNoticeSubscriber/config.js`** - 订阅保存配置 - - 源文件:`cloudfunctions/saveNoticeSubscriber/config.example.js` - - 需填写:与前端一致的订阅消息模板 ID +然后在这些本地配置文件中填入自己的 AppID、云环境 ID 和订阅消息模板 ID,再使用微信开发者工具打开项目并部署云函数。 -### 不要提交以下文件 +完整部署步骤见 [docs/deploy.md](docs/deploy.md)。 -- `project.private.config.json` -- `project.config.json` -- `miniprogram/config.js` -- `cloudfunctions/sendNoticeMessage/config.js` -- `cloudfunctions/saveNoticeSubscriber/config.js` +## 数据与安全 -这些文件已在 `.gitignore` 中,Git 会自动忽略它们。 +班级盒子依赖微信云开发数据库。你需要自行创建以下集合: -## 文档 +- `notices` +- `users` +- `admin_invite_codes` +- `class_members` +- `subscribers` +- `favorites` +- `security_counters` +- `operation_logs` -- **快速开始**:见上方“快速开始”章节 -- **部署指南**:`docs/deploy.md` - 详细的部署步骤 -- **数据库设计**:`docs/database.md` - 8 个集合的字段说明和示例数据 -- **数据库权限**:`docs/database-permissions.md` - 各集合的最小权限建议 -- **安全建议**:`docs/security.md` - 开源和运营时的安全注意事项 +数据库字段说明见 [docs/database.md](docs/database.md),权限建议见 [docs/database-permissions.md](docs/database-permissions.md)。 -## 当前限制 +部署前的隐私和权限配置建议见 [docs/security.md](docs/security.md)。 -- 项目依赖微信云开发,不能脱离微信开发者工具直接运行。 -- 班级成员名单和管理员邀请码需要部署者自行导入。 -- 订阅消息模板字段需要与 `sendNoticeMessage` 中的数据结构保持一致。 -- 当前自动化检查以语法、配置和敏感信息扫描为主,页面交互仍需在微信开发者工具中测试。 +## 技术说明 -## 项目结构 +项目由微信小程序前端和微信云函数组成。 ```text -cloudfunctions/ # 云函数后端(10个) -├── checkAdmin/ # 检查用户权限和认证状态 -├── createNotice/ # 创建班级事项 -├── updateNotice/ # 编辑班级事项 -├── updateNoticePin/ # 更新事项置顶状态 -├── deleteNotice/ # 删除班级事项 -├── verifyMember/ # 班级成员身份认证 -├── contentSecurityCheck/ # 内容安全检测(文本+图片) -├── saveNoticeSubscriber/ # 保存当前用户的订阅授权 -├── sendNoticeMessage/ # 发送订阅消息通知 -└── applyAdminInvite/ # 处理管理员邀请码 - -miniprogram/ # 小程序前端 -├── pages/ # 8个页面 -│ ├── index/ # 首页 - 事项列表 -│ ├── detail/ # 详情 - 事项详细信息 -│ ├── publish/ # 发布 - 创建/编辑事项(需要管理员权限) -│ ├── my/ # 我的 - 用户信息、权限设置 -│ ├── my-posts/ # 我的发布 - 管理自己发布的事项 -│ ├── favorites/ # 收藏 - 收藏的事项 -│ ├── member-verify/ # 成员认证 - 班级身份认证 -│ └── admin-auth/ # 管理员认证 - 使用邀请码成为管理员 -├── components/ # 可复用组件 -│ └── cloudTipModal/ # 云操作提示框 -├── app.js # 小程序全局配置和初始化 -└── config.example.js # 配置文件模板 - -docs/ # 文档 -├── deploy.md # 部署指南 -├── database.md # 数据库集合说明 -└── security.md # 安全注意事项 +miniprogram/ # 小程序页面、样式和配置 +cloudfunctions/ # 权限校验、事项管理、订阅提醒等云函数 +docs/ # 部署、数据库和安全文档 ``` -## 贡献 +主要云函数包括: -发现问题可以直接提交 Issue。准备修改代码时,请先阅读 `CONTRIBUTING.md`。 +- `checkAdmin`:检查当前用户认证状态和权限。 +- `verifyMember`:完成班级成员身份认证。 +- `createNotice` / `updateNotice` / `deleteNotice`:管理事项。 +- `updateNoticePin`:更新置顶状态。 +- `contentSecurityCheck`:内容安全检测。 +- `saveNoticeSubscriber` / `sendNoticeMessage`:保存订阅授权并发送提醒。 +- `applyAdminInvite`:处理管理员邀请码。 -## 许可证 +## 当前限制 -本项目采用 MIT 许可证。详见 `LICENSE` 文件。 +- 项目依赖微信小程序和微信云开发环境。 +- 页面交互需要在微信开发者工具或真机中测试。 +- 班级成员名单、邀请码和订阅消息模板需要部署者自行配置。 ## 反馈 -- 问题与建议:[GitHub Issues](https://github.com/Cheems-sudo/Class-Box/issues) +如果你发现问题,或有适合班级场景的新想法,可以在 GitHub Issues 中提出。 + +## 许可证 + +本项目采用 MIT 许可证。详见 [LICENSE](LICENSE)。 diff --git a/docs/security.md b/docs/security.md index 9253946..c537f17 100644 --- a/docs/security.md +++ b/docs/security.md @@ -1,39 +1,32 @@ -# 开源安全注意事项 +# 安全与隐私建议 -本仓库是班级盒子的开源副本,不能包含正式项目或真实班级环境的敏感信息。 +班级盒子会处理班级成员身份、通知内容、收藏记录、订阅授权和管理员权限。自行部署时,建议把它当作一个真实班级系统来配置,而不只是一个演示小程序。 -## 不应提交的内容 +这份文档面向部署者和运营者,重点说明哪些数据需要保护、哪些操作必须走云函数、日志应该如何脱敏,以及哪些配置不能公开。 -开源仓库不得包含: +## 需要重点保护的数据 -- 真实 AppID -- 真实云环境 ID -- 真实订阅消息模板 ID -- openid -- unionid -- 真实学生姓名 -- 真实学生学号 -- 真实管理员邀请码 -- 真实超级管理员邀请码 -- `cloud://` 文件地址 -- `access_token` -- `secret` -- `key` -- `password` -- `token` +以下数据不应公开,也不应出现在仓库、截图、日志或演示数据中: -如需展示结构,请使用 `example`、`your-*`、`openid_example` 等占位值。 +- 小程序 AppID、云环境 ID、订阅消息模板 ID。 +- 用户 openid、unionid。 +- 真实学生姓名和学号。 +- 管理员和超级管理员邀请码。 +- `cloud://` 云文件地址和云存储 fileID。 +- `access_token`、`secret`、`key`、`password`、`token` 等凭据。 -## 配置文件 +如需展示示例,请使用 `example`、`your-*`、`openid_example` 这类占位值。 -只提交 example 配置: +## 本地配置文件 + +仓库只应提交 example 配置: - `project.config.example.json` - `miniprogram/config.example.js` - `cloudfunctions/sendNoticeMessage/config.example.js` - `cloudfunctions/saveNoticeSubscriber/config.example.js` -不要提交真实配置: +以下文件只属于本地部署环境,不应提交: - `project.private.config.json` - `project.config.json` @@ -41,19 +34,24 @@ - `cloudfunctions/sendNoticeMessage/config.js` - `cloudfunctions/saveNoticeSubscriber/config.js` -## 运行安全建议 +这些文件已写入 `.gitignore`,正常情况下 Git 会自动忽略。 + +## 权限边界 + +不要只依赖前端判断权限。前端可以决定按钮是否显示,但不能作为安全边界。 -- 不要只依赖前端判断权限。 -- 发布、编辑、删除等关键操作应通过云函数执行。 -- 内容安全检测应在云函数侧完成。 -- 图片上传应进行图片内容安全检测。 -- 操作日志不应记录真实敏感内容原文。 -- 不要记录完整邀请码。 -- 不要在 `console.log` / `console.error` 中输出完整 `event`。 -- `security_counters` 和 `operation_logs` 不应允许普通用户直接写入。 -- `subscribers` 不应允许普通用户直接读写,订阅授权通过云函数保存。 -- 数据库权限应尽量收紧。 -- 邀请码应设置过期时间,并且只能使用一次。 +以下操作应始终通过云函数完成: + +- 成员身份认证。 +- 管理员邀请码校验。 +- 发布事项。 +- 编辑事项。 +- 删除事项。 +- 更新置顶状态。 +- 保存订阅授权。 +- 发送订阅消息。 + +普通用户不应直接写入 `notices`、`subscribers`、`security_counters`、`operation_logs` 等关键集合。数据库权限建议见 [database-permissions.md](database-permissions.md)。 ## 数据库安全 @@ -62,56 +60,63 @@ - `class_members`:包含班级成员姓名、学号和绑定状态。 - `users`:包含用户 openid、认证状态和权限角色。 - `admin_invite_codes`:包含管理员/超级管理员邀请码。 -- `security_counters`:包含安全计数和失败记录。 +- `subscribers`:包含订阅消息授权记录。 +- `security_counters`:包含频率限制计数和失败记录。 - `operation_logs`:包含关键操作日志。 -普通用户不应直接写入 `subscribers`、`security_counters` 和 `operation_logs`。管理员授权、发布、编辑、删除等敏感操作应由云函数进行权限校验后执行。具体权限目标见 `docs/database-permissions.md`。 +建议做法: + +- `class_members` 和 `admin_invite_codes` 不对普通用户开放直接读写。 +- `subscribers` 只通过 `saveNoticeSubscriber` 写入。 +- `security_counters` 只由云函数维护。 +- `operation_logs` 只由云函数写入,普通用户不可直接读取。 +- 根据运营需要定期清理过期的 `security_counters` 和历史 `operation_logs`。 ## 邀请码安全 -- 邀请码只应在云数据库中保存和校验。 -- 邀请码应设置 `expiredAt`。 -- 邀请码使用后必须标记为 `used: true`。 -- 操作日志中不要保存完整邀请码。 -- 如需记录授权来源,只记录 `codePrefix`、角色、成功/失败状态和失败原因。 +管理员邀请码相当于提权凭证,应按敏感数据处理。 + +建议: + +- 邀请码只保存在云数据库中,并通过云函数校验。 +- 邀请码设置 `expiredAt`。 +- 邀请码使用后立即标记为 `used: true`。 +- 不在前端、日志或报错信息中展示完整邀请码。 +- 如需记录授权来源,只记录角色、成功/失败状态、失败原因和脱敏后的 `codePrefix`。 ## 日志安全 日志用于排查问题和审计关键操作,但不应成为敏感信息泄露点。 -建议: +建议不要记录: + +- 完整请求 `event`。 +- 事项正文原文。 +- 真实姓名和学号。 +- 附件 fileID 或 `cloud://` 地址。 +- 完整邀请码。 +- 真实配置值。 -- 不记录完整请求 `event`。 -- 不记录事项正文原文。 -- 不在操作日志中重复保存姓名和学号。 -- 不记录附件 `fileID` 或云文件地址。 -- 不记录完整邀请码。 -- 不记录真实配置值。 -- 错误日志只记录错误类型、错误码、操作类型和脱敏后的上下文。 -- 为操作日志设置合理的保留周期,过期后及时清理。 +错误日志建议只记录错误类型、错误码、操作类型和脱敏后的上下文。 ## 内容安全 -发布和编辑事项时应在云函数侧执行内容安全检测: +发布和编辑事项时,应在云函数侧执行内容安全检测。前端检测只能优化体验,不能作为唯一安全边界。 -- 文本内容检测。 -- 链接标题和链接地址检测。 -- 图片文件内容检测。 -- 图片和附件名称检测。 +建议检测: -前端检测只能作为用户体验优化,不能作为唯一安全边界。 +- 标题和正文。 +- 链接标题和链接地址。 +- 图片内容。 +- 图片和附件名称。 -## 开源前检查清单 +## 发布前检查 -发布或同步到开源仓库前,建议检查: +部署或公开分享项目前,建议检查: -1. 搜索真实 AppID。 -2. 搜索真实云环境 ID。 -3. 搜索真实订阅消息模板 ID。 -4. 搜索 openid / unionid。 -5. 搜索真实学生姓名和学号。 -6. 搜索真实邀请码。 -7. 搜索 `cloud://` 和云存储 fileID。 -8. 搜索 `access_token`、`secret`、`key`、`password`、`token`。 -9. 确认真实配置文件没有被 Git 跟踪。 -10. 确认 README 和 docs 中只使用假数据或 example 数据。 +- 真实配置文件没有被 Git 跟踪。 +- README 和 docs 中只使用占位数据。 +- 仓库中没有真实 AppID、云环境 ID、模板 ID。 +- 仓库中没有真实 openid、学生信息、邀请码。 +- 仓库中没有 `cloud://` 文件地址或云存储 fileID。 +- 数据库权限已经按最小权限配置,并用普通用户账号测试过。 \ No newline at end of file diff --git a/miniprogram/components/cloudTipModal/index.js b/miniprogram/components/cloudTipModal/index.js deleted file mode 100644 index 8e75cc0..0000000 --- a/miniprogram/components/cloudTipModal/index.js +++ /dev/null @@ -1,28 +0,0 @@ -Component({ - - /** - * 页面的初始数据 - */ - data: { - showTip: false, - }, - properties: { - showTipProps: Boolean, - title:String, - content:String - }, - observers: { - showTipProps: function(showTipProps) { - this.setData({ - showTip: showTipProps - }); - } - }, - methods: { - onClose(){ - this.setData({ - showTip: !this.data.showTip - }); - }, - } -}); diff --git a/miniprogram/components/cloudTipModal/index.json b/miniprogram/components/cloudTipModal/index.json deleted file mode 100644 index ee2988f..0000000 --- a/miniprogram/components/cloudTipModal/index.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "usingComponents": {}, - "component": true -} diff --git a/miniprogram/components/cloudTipModal/index.wxml b/miniprogram/components/cloudTipModal/index.wxml deleted file mode 100644 index b5b6700..0000000 --- a/miniprogram/components/cloudTipModal/index.wxml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - {{title}} - {{content}} - - diff --git a/miniprogram/components/cloudTipModal/index.wxss b/miniprogram/components/cloudTipModal/index.wxss deleted file mode 100644 index 862f70c..0000000 --- a/miniprogram/components/cloudTipModal/index.wxss +++ /dev/null @@ -1,60 +0,0 @@ -.install_tip_back { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: rgba(0,0,0,0.4); - z-index: 1; -} -.install_tip_close{ - position:absolute; - right: 10rpx; - top: 10rpx; - width: 32px; - height: 32px; - /* background-color: red; */ -} -.install_tip_detail { - position: fixed; - background-color: white; - right: 0; - bottom: 0; - left: 0; - border-radius: 40rpx 40rpx 0 0; - padding: 50rpx 50rpx 100rpx 50rpx; - z-index: 9; -} - -.install_tip_detail_title { - font-weight: 400; - font-size: 40rpx; - text-align: center; -} - -.install_tip_detail_tip { - font-size: 25rpx; - color: rgba(0,0,0,0.4); - margin-top: 20rpx; - text-align: left; -} -.install_tip_detail_buttons { - padding-top: 50rpx; - display: flex; -} -.install_tip_detail_button { - color: #07C160; - font-weight: 500; - background-color: rgba(0,0,0,0.1); - width: 40%; - text-align: center; - /* height: 90rpx; */ - /* line-height: 90rpx; */ - border-radius: 10rpx; - margin: 0 auto; -} - -.install_tip_detail_button_primary { - background-color: #07C160; - color: #fff; -} \ No newline at end of file diff --git a/miniprogram/envList.js b/miniprogram/envList.js deleted file mode 100644 index e9a169e..0000000 --- a/miniprogram/envList.js +++ /dev/null @@ -1,6 +0,0 @@ -const envList = []; -const isMac = false; -module.exports = { - envList, - isMac -}; diff --git a/miniprogram/images/icons/close.png b/miniprogram/images/icons/close.png deleted file mode 100644 index 18f01a2..0000000 Binary files a/miniprogram/images/icons/close.png and /dev/null differ diff --git a/project.config.example.json b/project.config.example.json index 39e022d..8dd3f7f 100644 --- a/project.config.example.json +++ b/project.config.example.json @@ -47,7 +47,6 @@ "appid": "your-wechat-appid", "projectname": "class-box", "libVersion": "2.20.1", - "cloudfunctionTemplateRoot": "cloudfunctionTemplate/", "condition": { "search": { "list": [] @@ -62,13 +61,7 @@ "list": [] }, "miniprogram": { - "list": [ - { - "id": -1, - "name": "db guide", - "pathName": "pages/databaseGuide/databaseGuide" - } - ] + "list": [] } }, "compileType": "miniprogram",