Skip to content

系统设计

架构、部署、角色体系、技术选型 + 文档索引


目录

  1. 系统概述
  2. 部署架构
  3. 用户角色体系

1. 系统概述

CodeNote 是一个二维码管理与场景化服务平台,采用三端分离架构,支持离线优先的移动端体验、强大的后端 API 服务以及完善的管理后台。

1.1 项目组成总览

仓库文档
Servergitee.com/7688/codenote-server (exp)./README.md · /reference/backend.md · /architecture/data-model.md
Admingitee.com/7688/codenote-admin (exp)./README.md · /reference/admin.md
Androidgitee.com/7688/codenote-android (exp)./README.md · /reference/android.md
官网gitee.com/7688/la998 (master)index.html(CodeNote 项目介绍页,部署 la998.com)
知识库gitee.com/7688/codenote-docs (main)VitePress 静态站,部署 blog.la998.com,聚合全部文档

2. 部署架构

2.1 整体架构图

用户 ─→ NPM (Nginx Proxy Manager, 80/443)

         ├── codenote.la998.com ──→ codenote-admin:80 (nginx 容器)
         │                              │
         │                              └── /api/ ──→ codenote-server:8080

         └── api.la998.com ────────→ codenote-server:8080

                                            └── MySQL (本地容器, 3306)

2.2 服务器环境

项目配置
部署环境阿里云服务器(Alibaba Cloud Linux),容器化部署
Docker 网络web_network(自定义网络,容器间通过名称解析)
工作目录服务器 /data/www/ 下各项目独立目录
域名配置codenote.la998.com(管理后台)
api.la998.com(API 服务)
NPM 管理81 端口 (npm.la998.com)

2.3 容器部署

容器名称镜像来源端口说明
codenote-serverregistry.cn-guangzhou.aliyuncs.com/codenote/codenote-server8080Spring Boot 应用,提供 REST API
codenote-admin静态文件(Git 拉取 dist)80Nginx 托管 Vue 前端,反向代理 /api/ 到后端
mysqlMySQL 8.03306数据库服务,本地容器部署

2.4 部署流程

后端部署:

  1. 本地构建 jar 或 Docker 镜像
  2. 推送到阿里云容器镜像服务
  3. 服务器执行 deploy.sh 拉取镜像并重启容器
  4. 健康检查验证服务状态

前端部署:

  1. 本地执行 pnpm build 构建 dist
  2. Git 提交并推送到 Gitee
  3. 服务器执行 git pull 拉取最新静态文件
  4. NPM 自动生效(无需重启)

Android 端:

  • 直接安装 APK,配置 API 地址为 https://api.la998.com
  • 支持热更新(通过应用内下载新版本)

2.5 技术栈

组件技术选型说明
Android SDK阿里云OSS SDK 2.9.18客户端直传OSS
服务端SDK阿里云STS SDK 1.1.6生成临时凭证
数据库MySQL files 表记录文件元数据
认证方式STS临时凭证15分钟有效期,AK/SK 不暴露
图片压缩ImageCompressor智能压缩,95% 压缩率

3. 用户角色体系

RBAC 化(v3.3 定稿,实施完成):角色体系已重构为通用三域 RBAC(PLATFORM/APP/ORG)。users.role / org_members.role 列已删除,权限判定统一走 rbac_user_roles + @RequirePermission 切面。以下为 RBAC 落地后的角色语义。

CodeNote 采用多层次的角色权限体系,不同端支持不同的角色类型和权限范围。

3.1 三域 RBAC 概览

权限域服务对象角色管理方预置角色
PLATFORM管理后台系统管理员(后台可完全控制)SYSTEM_ADMIN / USER_ADMIN / ORG_ADMIN(可自定义)
APPAndroid App 用户系统管理员(后台定义)USER(=全部 APP 权限点,行为不变)
ORG组织成员(scope=orgId)组织拥有者OWNER / ADMIN / MEMBER(可自定义)

判定机制JwtAuthFilter 注入 PLATFORM 域角色 → PermissionAspect 解析 @RequirePermission(域/scope/短路)→ RbacService.hasPermission(角色权限并集 + 例外授权,Caffeine 60s 缓存)。短路:ORG OWNER / PLATFORM SYSTEM_ADMIN 放行。

3.2 角色语义(RBAC 后)

角色说明
SYSTEM_ADMINPLATFORM平台全部权限(短路);初始 admin 绑定不可撤销(§1.1#6)
USER_ADMIN / ORG_ADMINPLATFORM用户管理 / 组织管理相关权限(预置默认,后台可调整)
USERAPP默认角色 = 全部个人功能(决策 #1 行为不变);新注册用户自动绑定
OWNERORG组织内全部权限(短路);创建组织自动绑定;转让后旧 OWNER 降为 ADMIN(§1.2.2)
ADMINORG成员/资源管理,不可解散/转让;rbac_user_role 不可操作 OWNER 角色(防自提权)
MEMBERORG组织资源只读(资产/活动/qrcode/album 副本)+ 参与类(checkin:create、share:create、pass:read)

权限控制机制(RBAC 后):

  • JWT Token 携带用户 ID(不再写 role claim);角色每次请求从 RBAC 读取(缓存)
  • Controller 逐方法 @RequirePermission(domain, resource, action, orgIdParam, fallbackDomain)
  • 双域资源接口(asset/activity/qrcode/album):orgId 为空降级 APP 域,不回退 current_org_id(§6.1)
  • 组织资源属主语义(决策 B):组织内资源由组织角色管理(ADMIN/自定义角色可管理组织内全部资源);个人资源(org_id 空)属主私有
  • 分享 = 复制副本 + 组织接管(qr/album 副本归组织,§1.2.9)

3.3 组织角色明细(ORG 域预置矩阵)

权限OWNERADMINMEMBER
全部权限(短路)
org:read / member:read / asset:read / activity:read / qrcode:read / album:read / share:read
org:update / member:invite·update_role·remove·approve / asset:写 / activity:写 / qrcode:写 / album:upload·delete / share:delete / notification:send✗ 只读
checkin:create(参与语义,成员即可)/ share:create
pass:issue·verify·revoke仅活动创建者豁免(Service 属主判定)
org:transfer·dissolve·regenerate_code / rbac_role:*(自定义角色管理)
rbac_user_role:grant·revoke✅(不可操作 OWNER 角色)

3.4 管理后台(PLATFORM 域)

管理后台登录校验「PLATFORM 域存在任一角色」;端点权限按权限点(user:read / org:manage_member / rbac_role:* 等)逐方法控制。后台「权限管理」三页:权限点管理(无物理删除,停用代替删除)、平台角色管理(PLATFORM/APP 域 CRUD + 权限勾选)、用户授权(rbac_user_role)。

3.4b 通用动态数据模型(meta_*)

元数据驱动四层:业务对象 → 字段 → 模板 → 值。新业务只注册 meta_objects,三端配置驱动渲染,零新增表结构。表结构详见 /architecture/data-model.md,接口详见 /reference/api.md A21 节。

谁管理什么(meta_ 权限点)*:

角色可管理内容权限点
平台 SYSTEM_ADMIN一切(含对象注册 meta_object:*)PLATFORM 域 meta_* 全部
平台 BUSINESS_ADMINGLOBAL 字段/模板/绑定读写(不含对象注册)PLATFORM 域 meta_field/meta_template/meta_binding
组织 owner/admin(复用 ORG 域角色)本组织 ORG 字段库、ORG 模板(可 fork 全局)、本组织分类绑定ORG 域 meta_field/meta_template/meta_binding
组织 MEMBER只读使用,不可改模板—(MEMBER 白名单不含 meta_*)
普通用户(APP 域)个人 USER 级字段/模板/个人分类绑定APP 域 meta_field/meta_template/meta_binding

可见性合并(App 端取字段):可见字段 = 对象默认模板字段(GLOBAL) ∪ 实体绑定模板字段 ∪ 归属组织的 ORG 字段(绑定过的) ∪ 有值的字段;软删字段过滤;按绑定顺序 + 模板内 sort_order 排序,field_id 去重。

混合存储(单一写路径):8 个高频字段(品牌/型号/序列号/购买日期/购买价格/供应商/保修到期日/备注)升为 assets 固定列,定义仍在 meta_fields(entity_column 映射),值读写统一走 PUT /api/meta/.../values 由 MetaValueService 转写;扩展字段走 meta_values(EAV + value_num/value_date 冗余列)。

3.5 Android 端(移动 App)

Android 端面向普通用户(USER 角色)和组织成员,提供完整的业务功能。

角色场景说明可用功能
组织 OWNER创建或接管组织的用户可管理组织成员、共享资源、转移所有权、解散组织
组织 ADMIN被提升为管理员的用户可管理组织成员和资源,但不可解散组织
组织 MEMBER普通成员使用组织共享资源
个人用户未加入组织的独立用户所有个人业务功能

权限特点:

  • 支持多组织切换:用户可在头像下拉菜单中切换当前活跃组织
  • 离线优先:所有核心功能完全离线可用,联网后自动同步
  • 扫码智能路由:根据二维码类型自动跳转到对应业务模块
  • 数据隔离:只显示当前用户有权限访问的个人数据和组织共享数据

客户端按钮显隐映射(实施)

Android 端各页面操作按钮按 ORG 域权限点显隐——无权限不显示,不再提交后才报错。统一入口 OrgRepository.getOrgPermissions(orgId)(内部复用 GET /orgs/{id} 的 permissions 字段),权限常量集中在 OrgPerms。个人场景(无 orgId / orgId=-1)不限制;后端 @RequirePermission 仍为最终校验。

页面按钮/操作权限点
组织成员升降级 / 移除成员member:update_role / member:remove
邀请记录撤回邀请invitation:cancel
角色权限创建/编辑/删除角色rbac_role:create / update / delete
组织资产新增 / 分类管理入口asset:create / asset_category:read
资产详情编辑/流转/报废/删除/盘点asset:update / transfer / scrap / delete / inventory
资产编辑删除asset:delete
资产盘点新建盘点任务asset:inventory
资产分类管理添加/编辑/删除/排序/置顶/长按选择asset_category:create / update / delete / reorder / pin
位置管理添加/编辑/删除/排序/置顶/长按选择location:create / update / delete / reorder / pin
组织模板新建/复制/编辑/删除模板meta_template:create / update / delete
组织活动「组织活动」tab(仅 OWNER/ADMIN 可见「发起活动」)activity:create
活动编辑删除activity:delete
活动可见性公开/组织内部/仅邀请(创建/编辑页选择,个人禁组织内部)§可见性架构
组织可见性公开/内部(创建/设置页,INTERNAL 锁定 joinPolicy=INVITE)§可见性架构
发现页底部 tab:公开活动/公开组织;非成员点公开组织 → OrgPreview 申请加入(apply)无需权限(PUBLIC 资源)
通行证签发 / 核验pass:issue / pass:verify
组织分享取消共享share:delete

注:二维码域(列表/详情/批量/分类)为个人功能,无组织权限控制;组织内二维码副本在组织分享页管理(share:delete 已控)。签到(checkin:create)为参与语义,MEMBER 默认拥有,不做显隐控制。

3.4 权限继承关系

  • 用户可以同时属于多个组织,在不同组织中可以拥有不同角色
  • 组织管理员(ADMIN)拥有所有组织的查看权限,但需要加入组织才能进行操作
  • 组织 OWNER 可以转移所有权给其他成员,转移后原 OWNER 降级为 MEMBER

典型应用场景:

场景说明
设备身份用户主动选择设备登录(免注册)时自动注册账号(DEVICE identity),与手机/邮箱登录平级;一账号可绑多设备;首次进入显示登录页,不自动注册
个人用户绑定账户后的正式用户,可使用所有个人业务功能(二维码、扫码、资源等)
系统管理员全局监控系统运行状态、审计用户行为、配置系统参数

3.5 各角色可用功能明细

功能模块个人用户组织 MEMBER组织 ADMIN组织 OWNER系统管理员未登录 GUEST
二维码管理-
扫码功能-
资源管理仅查看公开
活动管理仅查看公开
签到系统仅查看公开
通行证系统仅查看公开
联系人聊天--
组织信息查看-✓(部分)-
组织资源管理--✓(需入组织)-
组织成员管理--✓(需入组织)-
转移所有权-----
解散组织-----
全局数据查看-----
管理后台登录-----

图例: ✓ = 完全可用 · ✓(部分)= 部分可见/受限访问 · - = 不可用

注意事项:

  1. 用户可以同时拥有多个角色身份
  2. 权限遵循最小权限原则,用户只能访问其有权限的资源
  3. 离线状态下,用户仍可操作本地数据,联网后自动同步到服务端并进行权限验证
  4. 所有敏感操作(删除、转移所有权、解散组织等)都需要二次确认

4. 环境与部署信息

4.1 环境要求

要求
ServerJDK 17+, MySQL 8.0, Gradle 8.x
AdminNode.js 18+, pnpm 8+
AndroidAndroid Studio Hedgehog+, JDK 17+, Android SDK 26+, Gradle 8.x

4.2 NPM 反向代理配置

登录 https://npm.la998.com 配置:

  • api.la998.com → codenote-server:8080,Advanced 添加 WebSocket 支持:
    location /ws/ {
        proxy_pass http://codenote-server:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
  • codenote.la998.com → codenote-admin:80

4.3 快速开始

bash
# Server
cd codenote-server && ./gradlew bootRun

# Admin
cd codenote-admin && pnpm install && pnpm dev

# Android
# Android Studio 打开 codenote-android/,等待 Gradle sync

5. 文档索引

每次 session 初始仅加载:/architecture/overview.md + /standards/index.md。其他文档按需读取。

文档大小加载策略说明
/architecture/overview.md~9KB初始架构、部署、角色
/standards/index.md~3KB初始跨端硬性规则
/reference/backend.md~12KB按需后端模块+Service清单
/reference/api.md~25KB按需所有 REST API 端点
/reference/android.md~37KB按需Android 页面+组件
/reference/admin.md~15KB按需Admin 页面路由
/designs/auth/user-state.md~44KB按需Session/Token 完整设计
/designs/activity.md~13KB按需活动/签到/通行证
/designs/messaging/contacts-chat.md~18KB按需通讯录/单聊/多类型消息/WS 实时(一期方案)
/designs/camera/scan-flow.md~12KB按需扫码全流程
/designs/camera/watermark-flow.md~9KB按需水印拍照流程
/designs/camera/memory.md~7KB按需相机记忆 JSON 持久化
/reference/app-update.md~11KB按需版本发布
/architecture/data-model.md~42KB按需所有 MySQL+Room 表定义
/standards/android-coding.md~22KB按需Android 编码+UI 规范
/standards/qr-display.md~2KB按需二维码渲染一致
/standards/location.md~8KB按需GPS 定位模型
/standards/camera.md~17KB按需相机架构与分层

附录:账户模型与认证体系

账户模型(身份分离后)

认证方式存储设置入口解绑入口
用户名+密码users.username + passwordset-username / password/set(两步独立)—(不可解绑,登出即退出)
邮箱user_identities(EMAIL)email-bindemail/unbind
手机user_identities(PHONE)phone-bind / verify-mobilephone/unbind
设备user_identities(DEVICE,可多条)device-login 自动登记 / 凭据登录自动登记devices/{deviceId} 移除
  • 用户名不可修改(set-username / updateProfile / admin 编辑全链路封禁)
  • 换绑 = 删旧插新,仅校验新凭证未被他人占用
  • 验证码注册用户不再自动生成 user_xxx 用户名,自动生成昵称
  • 绑定 = 给当前账号追加身份;hasRecoverableCredential = password 非空 ‖ 有 PHONE/EMAIL identity,false 时驱动设备丢失/更换提醒
  • 个性签名:users.signature VARCHAR(200),≤100 字符,updateProfile 写入,用户中心/管理后台展示
  • 昵称可修改:updateProfile 支持 nickname(≤50 字符,null 不改,空串清空);用户中心编辑资料页新增昵称输入,头像/昵称/个性签名统一入口

昵称机制

  • nickname 字段全端显示默认用它;username 仅内部逻辑可见
  • 生成:NicknameService 词库随机组合(nickname_adjectives + nickname_nouns 各 100 条,admin 可管理);空词库降级「用户+6位随机」
  • 用户可自行修改昵称:编辑资料页输入,≤50 字符,空串清空
  • 资源 assignee 快照存 nickname(assets.assignee_name)

密码体系

  • 忘记密码(公开):/api/auth/password/forgot-code + /reset,凭证须已注册,限频防轰炸
  • 修改密码(登录态):/api/auth/password/change-code + /change,原密码/手机码/邮箱码三选一
  • 改密/重置成功后 tokenVersion+1,全部旧 token 失效重新登录(JwtAuthFilter 已校验)