# 个人成绩管理应用 **Repository Path**: lxhtevin/gms ## Basic Information - **Project Name**: 个人成绩管理应用 - **Description**: 个人成绩管理应用 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-14 - **Last Updated**: 2026-07-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # GMS 成绩管理系统 前后端分离、模块化、开箱即用的成绩管理系统。后端基于 **.NET 10 + Furion + SqlSugar + MySQL 8**,前端基于 **TinyVue (Vue3) + Vite**。内置 RBAC + 数据权限、多租户、缓存、JWT 鉴权、审批流、ECharts BI 分析、动态 API,并为 Kafka / ELK / MQ / SSO(OIDC) / 微信登录预留了**配置化接入点**(默认关闭,无需外部服务即可启动运行)。 > ⚠️ 重要说明(务必先读) > - 本项目在**受限沙箱**中生成,**未能执行 `dotnet build` / `npm install` / 运行测试**。请在你的本机按下文步骤首次构建、运行并验证。 > - `.csproj` 使用浮动版本(如 `Furion 4.9.*`、`Microsoft.AspNetCore.Authentication.JwtBearer 10.0.*`)。若你本机 **未安装 .NET 10 SDK**,请把 `TargetFramework` 改为 `net8.0`/`net9.0` 并同步调整包版本。 > - Furion 动态 API 的装配、路由约定请在首次运行后对照 Swagger 校验(见下文「API 路由约定」)。 --- ## 技术栈 ### 后端(`backend/`) | 能力 | 选型 | |---|---| | 框架 / 动态 API / DI 扫描 / 统一返回 / 事件总线 / 远程请求 | Furion `4.9.*` | | ORM(MySQL8 + 国产/分布式库切换) | SqlSugarCore `5.1.4.*` + MySqlConnector | | 鉴权 | 标准 JWT Bearer(`Microsoft.AspNetCore.Authentication.JwtBearer`) | | 对象映射 | Mapster | | 缓存 | 内存 / Redis(`StackExchange.Redis`,按配置切换) | | 日志 → ELK | Serilog + Elasticsearch Sink(可开关) | | MQ / 流 | Confluent.Kafka(可开关,默认 Noop 生产者) | | ID 生成 | 雪花算法(自实现 `IdGen`) | | 密码哈希 | PBKDF2(内置) | ### 前端(`frontend/`) Vue 3 + Vite + TypeScript + Pinia + Vue Router(hash) + Axios + ECharts + **@opentiny/vue (TinyVue)**。内置账号密码登录与**微信公众号登录**入口(`/auth/wechat-login`,需在后端开启 `Features:WeChat`)。 --- ## 目录结构 ``` gms/ ├─ backend/ # .NET 10 后端 │ ├─ GMS.sln │ └─ src/GMS.Web/ │ ├─ Program.cs / Startup.cs # 宿主 + Furion 装配(Serilog、Inject) │ ├─ appsettings.json # 连接串 / JWT / 缓存 / 多租户 / Features 开关 │ ├─ Core/ # 基础设施 │ │ ├─ Auth/ # CurrentUser、JwtHelper、PasswordHasher │ │ ├─ Cache/ # ICacheService + Memory/Redis 实现 │ │ ├─ DataScope/ # 数据权限解析 │ │ ├─ Messaging/ # IMessageProducer(Kafka/Noop)、WeChatService │ │ ├─ Setup/ # Jwt/Cache/SqlSugar/Logging/Infrastructure/DbSeeder │ │ └─ IdGen.cs / TreeHelper.cs / Options.cs / ClaimConst.cs │ ├─ Entities/ # 实体(Base/System/Business/Enums) │ ├─ Dtos/ # 输入输出 DTO │ └─ Services/ # 动态 API(System/ 与 Business/) ├─ frontend/ # TinyVue 前端 │ └─ src/{api,store,router,layout,views,utils} └─ deploy/ ├─ docker-compose.yml # mysql + redis + backend + frontend(Kafka/ES 注释可选) └─ k8s/ # namespace/mysql/redis/backend/frontend/ingress ``` --- ## 数据模型 ### RBAC + 数据权限 - **用户 `Sys_User`** ⇄ **角色 `Sys_Role`** ⇄ **菜单/权限 `Sys_Menu`**,通过 `Sys_UserRole`、`Sys_RoleMenu` 关联。 - **组织/部门 `Sys_Org`**:数据权限的基础层级。 - **数据范围(DataScope)** 挂在角色上,取值: - `All` 全部 - `Dept` 本部门 - `DeptAndChild` 本部门及以下 - `Self` 仅本人 - `Custom` 自定义(写入 `Sys_RoleOrg`) - 业务查询(如成绩分页)在 `DataScopeService` 解析当前用户可见的 `orgIds`/`self` 后自动过滤。 ### 业务表(严格映射需求中的 F- 列) - **学期 `T_term`**:`FID` / `FBILLNO` / `FNAME` - **科目 `T_Subject`**:`FID` / `FBILLNO` / `FNAME` - **成绩 `T_score`**:`FID`、`FKtermId`、`FKSubjectId`、`Fscore`、`FDATE`、`FCREATORID`、`FCREATEDATE`、`FMODIFIERID`、`FMODIFYDATE`、`FAPPROVERID`、`FAPPROVEDATE`、`FREMARKS` - 另加平台通用列:`FTENANTID`(多租户)、`FISDELETED`(软删除)、`FAPPROVESTATUS`(审批状态)、`FCREATEORGID`(数据权限归属)。 ### 全局横切能力 - **多租户**:全局过滤器按当前租户隔离;登录接口用 `ClearFilter()` 跨租户校验。 - **软删除**:`ISoftDelete` 全局过滤器,删除即置 `FISDELETED=1`。 - **审计**:SqlSugar AOP 自动写入创建人/时间、修改人/时间。 - **审批流**:成绩状态 `Pending → Approved`,已审核不可修改;审核成功后向消息中间件投递事件(默认 Noop)。 --- ## 快速开始(本地开发) ### 前置 - .NET 10 SDK(或改 `TargetFramework` 到你已安装的版本) - Node.js 18+ - MySQL 8(可用 `deploy/docker-compose.yml` 一键起 mysql+redis) - Redis(可选,默认缓存走内存) ### 1) 启动依赖(可选,用 Docker 起 MySQL/Redis) ```bash cd deploy docker compose up -d mysql redis ``` ### 2) 运行后端 ```bash cd backend/src/GMS.Web dotnet restore dotnet run ``` - 首次启动会 **CodeFirst 建表 + 写入种子数据**(由 `appsettings.json` 的 `DbSettings:EnableCodeFirst/EnableSeed` 控制)。 - 监听 `http://localhost:5000`。 - Swagger(Furion 规范化文档):`http://localhost:5000/`(若未自动跳转,试 `/swagger` 或 `/api-docs`,以启动日志为准)。 ### 3) 运行前端 ```bash cd frontend npm install npm run dev ``` - 访问 `http://localhost:5173`,`/api` 已代理到 `http://localhost:5000`(见 `vite.config.ts`)。 ### 默认账号 ``` 账号:admin 密码:123456 ``` 种子还会创建角色(`admin` 全部数据 / `teacher` 仅本人)、组织「总校」、科目「语文/数学/英语」、两个学期。 --- ## 配置说明(`appsettings.json`) | 配置节 | 作用 | |---|---| | `ConnectionStrings:Default` | MySQL 连接串 | | `DbSettings:DbType` | 数据库类型(改为 SqlSugar 支持的类型即可切换国产/分布式库,如 `Dm`/`OpenGauss`/`PostgreSQL` 等) | | `JWTSettings` | 签发方/受众/密钥/过期分钟(**部署前务必更换 `SecretKey`**) | | `Cache:Provider` | `Memory` 或 `Redis` | | `MultiTenant` | 多租户开关与默认租户 | | `Cors:Origins` | 允许的前端来源 | | `Features:Kafka` | Kafka 生产者(默认 `false`) | | `Features:Mq` | 消息中间件开关(默认 `false`) | | `Features:Elasticsearch` | Serilog → ES 日志(ELK,默认 `false`) | | `Features:Oidc` | SSO / OIDC 单点登录接入(默认 `false`) | | `Features:WeChat` | 微信登录 AppId/Secret(默认 `false`) | > 所有 `Features` 默认关闭,因此**没有 Kafka/ES/SSO/微信服务也能完整跑起来**。需要时打开对应开关并补齐地址/密钥即可,无需改代码。 --- ## API 路由约定 动态 API 由 Furion 从 `Services/*Service : IDynamicApiController` 生成,统一前缀 `/api`。为避免 Furion 对无模板动作追加/裁剪动作名带来的歧义,**所有写操作均使用显式子路由**,与前端 `src/api/*.ts` 严格一致: | 资源 | 列表/树 | 新增 | 修改 | 删除 | 其他 | |---|---|---|---|---|---| | auth | — | — | — | — | `POST /api/auth/login`、`POST /api/auth/wechat-login`、`GET /api/auth/user-info`、`GET /api/auth/menus` | | user | `GET /api/user/page` | `POST /api/user/add` | `PUT /api/user/update` | `DELETE /api/user/{id}` | `PUT /api/user/reset-password` | | role | `GET /api/role/list` | `POST /api/role/add` | `PUT /api/role/update` | `DELETE /api/role/{id}` | `PUT /api/role/grant`、`GET /api/role/{id}/menus` | | menu | `GET /api/menu/tree` | `POST /api/menu/add` | `PUT /api/menu/update` | `DELETE /api/menu/{id}` | | | dept | `GET /api/dept/tree` | `POST /api/dept/add` | `PUT /api/dept/update` | `DELETE /api/dept/{id}` | | | term | `GET /api/term/page` | `POST /api/term/add` | `PUT /api/term/update` | `DELETE /api/term/{id}` | | | subject | `GET /api/subject/page` | `POST /api/subject/add` | `PUT /api/subject/update` | `DELETE /api/subject/{id}` | | | score | `GET /api/score/page` | `POST /api/score/add` | `PUT /api/score/update` | `DELETE /api/score/{id}` | `POST /api/score/approve` | | bi | — | — | — | — | `GET /api/bi/overview`、`GET /api/bi/subject-average`、`GET /api/bi/term-trend` | > 首次运行后请对照 Swagger 确认实际路由与上表一致;如 Furion 版本行为不同,只需调整动作上的 `[HttpPost("...")]`/`[HttpPut("...")]` 模板即可。 统一返回信封(前端 `request.ts` 已按此拆包): ```json { "statusCode": 200, "data": {}, "succeeded": true, "errors": null, "extras": null, "timestamp": 0 } ``` --- ## 部署 ### Docker Compose(推荐单机) ```bash cd deploy docker compose up -d --build ``` - 前端:`http://localhost:8080` - 后端:`http://localhost:5000` - 生产环境后端已通过环境变量指向容器内 `mysql`/`redis`,并将缓存切到 Redis。 - 需要 Kafka / ELK 时,取消 `docker-compose.yml` 底部注释的服务,并把 `backend.environment` 中对应的 `Features__*` 打开。 ### Kubernetes ```bash kubectl apply -f deploy/k8s/namespace.yaml kubectl apply -f deploy/k8s/mysql.yaml kubectl apply -f deploy/k8s/redis.yaml kubectl apply -f deploy/k8s/backend.yaml kubectl apply -f deploy/k8s/frontend.yaml kubectl apply -f deploy/k8s/ingress.yaml ``` - `ingress.yaml` 将 `/api` 转发后端、其余转发前端(未做 rewrite,`/api` 前缀原样透传)。 - 请把镜像名替换为你的镜像仓库地址,并使用 Secret 管理数据库密码与 JWT 密钥。 ### 跨平台(Windows / Linux / macOS) - **.NET** 与 **Node** 均跨平台,源码可直接在三种系统上 `dotnet run` / `npm run dev`。 - **容器化**:`backend/Dockerfile`(`mcr.microsoft.com/dotnet/aspnet:10.0`)+ `frontend/Dockerfile`(node 构建 → nginx 托管)在任意支持 Docker 的系统上一致运行。 - **发布自包含单文件**(示例): ```bash # Linux x64 dotnet publish backend/src/GMS.Web -c Release -r linux-x64 --self-contained true # Windows x64 dotnet publish backend/src/GMS.Web -c Release -r win-x64 --self-contained true # macOS (Apple Silicon) dotnet publish backend/src/GMS.Web -c Release -r osx-arm64 --self-contained true ``` --- ## 扩展点一览(黑科技接入位) | 能力 | 现状 | 如何启用 | |---|---|---| | 缓存 | ✅ 内存/Redis 已实现 | `Cache:Provider=Redis` | | 多租户 | ✅ 已实现 | `MultiTenant:Enabled=true` | | 数据校验 | ✅ DTO + Furion 友好异常 | 直接使用 `[Required]` 等特性 | | 事件总线 / 远程请求 | ✅ 走 Furion 内建 | 注入 `IEventPublisher` / `IHttpRemote` | | 审批流 | ✅ 成绩审核已实现 | `POST /api/score/approve` | | BI 分析 | ✅ 三个 ECharts 数据接口 | 前端 Dashboard 已对接 | | Kafka / MQ | 🔌 接入点(Noop) | `Features:Kafka:Enabled=true` | | ELK 日志 | 🔌 接入点 | `Features:Elasticsearch:Enabled=true` | | SSO / OIDC | 🔌 接入点 | `Features:Oidc:Enabled=true` + 配置 Authority | | 微信登录 | 🔌 接入点 | `Features:WeChat:Enabled=true` + AppId/Secret | | 国产/分布式库 | 🔌 切 DbType | `DbSettings:DbType` 改为目标库 | | 任务调度 / 打印 | 🔌 预留 | 可接入 Furion Job / 报表组件 | --- ## 首次运行检查清单 1. `dotnet build`(若版本报错,先按上文调整 `TargetFramework` 与包版本)。 2. 确认 MySQL 可连通、数据库 `gms` 自动创建、种子数据写入成功。 3. 打开 Swagger 核对路由与上表一致。 4. 用 `admin/123456` 登录前端,验证用户/角色/菜单/学期/科目/成绩 CRUD 与成绩审核、BI 看板。 5. 按需逐个打开 `Features` 开关联调 Redis/Kafka/ELK/OIDC/微信。