diff --git a/AGENTS.md b/AGENTS.md index 84acba1..bad8ea8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,24 @@ # AGENTS.md — ClassHelper(Class Helper) 本文件写给在本仓库里干活的 AI 编码代理。先读这里,再动代码。 + +**2026-10-16 更新**:当前仓库位于 `F:\ClassHelper`,F 盘可用。ClassIsland 联动插件、设备令牌、提醒通道与镜像接口已退役;离线课表 JSON 导入和界面设计参考保留。下文历史联动部署记录不再适用。 +客户端维护只走 `/api/clients/*`,页面为 `ClientsView.vue`;默认权限按数据库中对应角色的默认组生效。 +**2026-10-17 更新**:日常 `verify:desktop` / `verify:packaged` 默认是后台快速检查,不创建可见灵动岛或托盘; +完整桌面动画、透明度与截图验收必须显式加 `--visual`(`pnpm verify:desktop:visual`)。 +下文关于置顶验证窗口、鼠标穿透与截图时序的历史约定仅适用于视觉模式。不要为了日常修改反复占用用户桌面。 +联网冒烟显式启用,使用临时教师和班级;禁止回退到真实班级、重置其密码或向其发送测试通知。 + +本次 PowerShell 会话的 PATH 不含 pnpm:需要先把 `C:\Users\hck16\AppData\Local\deepseek-harness\bin` +加到 PATH 前面,再按下文设置 `DSH_NODE` 和 `DSH_PNPM_BIN`。Git Bash 外层找不到 pnpm 时可执行: + +```bash +export DSH_NODE='D:\Node.js\node.exe' +export DSH_PNPM_BIN='C:\Users\hck16\AppData\Local\node\corepack\v1\pnpm\11.8.0\bin\pnpm.cjs' +node "C:/Users/hck16/AppData/Local/node/corepack/v1/pnpm/11.8.0/bin/pnpm.cjs" typecheck +``` + +外层直接调用用于解决找不到命令;环境变量让内部嵌套的 pnpm 仍使用真实运行时。 文中「本机环境」「已知坑」两节按**实测**写成;若与本机现状不符,以本机实测为准并顺手改掉这里。 --- @@ -9,13 +27,12 @@ 班级信息管理系统,**pnpm monorepo**,一份代码产出多个交付物: -| 交付物 | 位置 | 形态 | -| -------------------- | ----------------------------- | ------------------------------------------------------------------------------ | -| 后端服务 | `packages/server` | Express 5 + Prisma 7 + Socket.IO,`/api` 前缀 | -| Web 管理端 | `packages/web-admin` | Vue 3 + Vite + Element Plus(教师/管理员用,PWA 可安装) | -| 桌面客户端 | `packages/desktop-client` | Electron + Vue 3(学生用,含「灵动岛」浮窗) | -| 共享契约 | `packages/shared` | 三端共用的类型 / 常量 / 权限 / 工具函数 | -| ClassIsland 联动插件 | `packages/classisland-plugin` | .NET 8 / C#(装在教室的 ClassIsland 上:上报课表与上课状态、弹出老师发的提醒) | +| 交付物 | 位置 | 形态 | +| ---------- | ------------------------- | -------------------------------------------------------- | +| 后端服务 | `packages/server` | Express 5 + Prisma 7 + Socket.IO,`/api` 前缀 | +| Web 管理端 | `packages/web-admin` | Vue 3 + Vite + Element Plus(教师/管理员用,PWA 可安装) | +| 桌面客户端 | `packages/desktop-client` | Electron + Vue 3(学生用,含「灵动岛」浮窗) | +| 共享契约 | `packages/shared` | 三端共用的类型 / 常量 / 权限 / 工具函数 | 核心链路: @@ -28,9 +45,6 @@ ▼ Socket.IO ──► class:{classId} 房间 ──► 学生桌面客户端实时更新 UI -ClassIsland(教室机器)──► ClassHelper 联动插件 ──► /api/integrations/classisland/*(设备令牌鉴权) - ▲ │ - └──── 老师下发的提醒(上报返回值里顺带带回)◄┘ ``` - 远端:`LoveChengke/ClassHelper`(仓库名大小写不敏感,本地 remote 存的是小写 `classhelper.git`) @@ -137,7 +151,7 @@ packages/server/ password schemas session term version(读 package.json) web-static src/middleware/ auth validate error security src/realtime/ socket.ts(房间)+ bus.ts(事件总线) - src/modules/ 21 个功能模块 + registry.ts + module.types.ts + src/modules/ 20 个功能模块 + registry.ts + module.types.ts (含 archives 毕业归档、term 学期周次、permissions 权限组、 clients 客户端心跳与远控、system 开发者模式/开机自启、ai 大模型助手) packages/web-admin/src/ api stores router layouts views(18) components(5) composables styles config.ts @@ -150,37 +164,27 @@ packages/desktop-client/ src/renderer/ ClassHelper 班级端渲染进程:api / cache(IndexedDB) / stores / views / island / router src/types/desktop.d.ts 主进程 ↔ 渲染进程契约 scripts/ build-main / dev / smoke / dist-win -packages/classisland-plugin/ .NET 8 插件(独立于 pnpm workspace,不参与 pnpm install) - manifest.yml 清单:id=classhelper.classisland.bridge / apiVersion=2.0.0.0 / version=1.2.0.0 - ClassHelper.ClassIslandPlugin.csproj(TargetFramework=net8.0) - src/Plugin.cs 入口:读配置 → 注册提醒提供方 / 设置页 / BridgeService - src/Models/PluginSettings.cs - src/Services/ BridgeService(上报·接收·镜像)/ ScheduleMapper / ClassPlanWriter - ClassHelperNotificationProvider(把提醒显示到 ClassIsland 上) - src/Views/BridgeSettingsPage.axaml(.cs):Avalonia 设置页 - src/Interop/ClassHelperClient.cs:HTTP 客户端 + 与服务端逐个字段对齐的 DTO - scripts/ build.mjs(编译 / 打包 .cipx)/ verify.mjs(静态契约校验,实测 74 项) ``` --- ## 3. 本机环境(2026-09-30 实测) -| 项 | 状态 | -| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Node | **v22.15.0**(`D:\Node.js\node.exe`;根 `engines` 要求 ≥ 20.19,Prisma 7 的 engine 约束是 `^20.19 \|\| ^22.12 \|\| >=24.0`,v22.15 都满足) | +| 项 | 状态 | +| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Node | **v22.15.0**(`D:\Node.js\node.exe`;根 `engines` 要求 ≥ 20.19,Prisma 7 的 engine 约束是 `^20.19 \|\| ^22.12 \|\| >=24.0`,v22.15 都满足) | | pnpm | 11.8.0(`packageManager` 锁定 11.8.0)。本机可用的本体在 `C:\Users\hck16\AppData\Local\node\corepack\v1\pnpm\11.8.0\bin\pnpm.cjs`;PATH 里那个 `pnpm.ps1` 是 DSH 桌面端的转发壳,**别绕它**(见下) | -| npm registry | `https://registry.npmjs.org/`(仓库内无 `.npmrc`,取全局配置) | -| 依赖 | 已装(707 包,`pnpm install` 实测 2m45s) | -| 后端 `.env` | 已由 `.env.example` 生成(**gitignored**),`JWT_SECRET` 为本机随机值,`TERM_START_DATE=2026-09-07` | -| Prisma Client | 已生成到 `packages/server/src/generated/prisma`(gitignored) | -| 数据库 | SQLite `packages/server/prisma/dev.db`:10 个迁移已应用、种子已写入(用户 18 / 班级 3 / 课程 54 / 课表 93 / 作业 15 / 通知 12 / 成绩 90) | -| `shared/dist` | 已构建(`pnpm build:shared`)—— **它是三端与 seed 的前置产物,缺了会 `ERR_MODULE_NOT_FOUND`** | -| Electron 二进制 | 已手动装好(`node_modules/.pnpm/electron@44.3.0/node_modules/electron/dist/electron.exe`,246 MB) | -| .NET SDK | ✅ **8.0.425**(`C:\Program Files\dotnet\sdk`,`dotnet --list-sdks` 有输出)⇒ 插件可编译/打包;**别再照旧文档说"没装"**(`dotnet` 在 PATH 里,`--list-sdks` 才是权威判据) | -| ClassIsland | **2.1.0.1,装在 `D:\Classisland`**(启动器 `D:\Classisland\ClassIsland.exe`,实际进程 `D:\Classisland\app-2.1.0.1-0\ClassIsland.Desktop.exe`) | -| ClassIsland 数据 | 数据根 **`D:\Classisland\data`**:`Config/`、`Profiles/`、`Plugins/`(当前为空,尚未装本插件)、`Logs/`、`Cache/`、`Settings.json` | -| 桌面会话 | 有(`ClassIsland.Desktop.exe` 跑在 session 1);**Electron GUI 在 AI 会话里也能跑**(需先修完整性标签,见 §7 第 7 条) | +| npm registry | `https://registry.npmjs.org/`(仓库内无 `.npmrc`,取全局配置) | +| 依赖 | 已装(707 包,`pnpm install` 实测 2m45s) | +| 后端 `.env` | 已由 `.env.example` 生成(**gitignored**),`JWT_SECRET` 为本机随机值,`TERM_START_DATE=2026-09-07` | +| Prisma Client | 已生成到 `packages/server/src/generated/prisma`(gitignored) | +| 数据库 | SQLite `packages/server/prisma/dev.db`:10 个迁移已应用、种子已写入(用户 18 / 班级 3 / 课程 54 / 课表 93 / 作业 15 / 通知 12 / 成绩 90) | +| `shared/dist` | 已构建(`pnpm build:shared`)—— **它是三端与 seed 的前置产物,缺了会 `ERR_MODULE_NOT_FOUND`** | +| Electron 二进制 | 已手动装好(`node_modules/.pnpm/electron@44.3.0/node_modules/electron/dist/electron.exe`,246 MB) | +| .NET SDK | ✅ **8.0.425**(`C:\Program Files\dotnet\sdk`,`dotnet --list-sdks` 有输出)⇒ 插件可编译/打包;**别再照旧文档说"没装"**(`dotnet` 在 PATH 里,`--list-sdks` 才是权威判据) | +| ClassIsland | **2.1.0.1,装在 `D:\Classisland`**(启动器 `D:\Classisland\ClassIsland.exe`,实际进程 `D:\Classisland\app-2.1.0.1-0\ClassIsland.Desktop.exe`) | +| ClassIsland 数据 | 数据根 **`D:\Classisland\data`**:`Config/`、`Profiles/`、`Plugins/`(当前为空,尚未装本插件)、`Logs/`、`Cache/`、`Settings.json` | +| 桌面会话 | 有(`ClassIsland.Desktop.exe` 跑在 session 1);**Electron GUI 在 AI 会话里也能跑**(需先修完整性标签,见 §7 第 7 条) | > **旧文档里的 `F:\classisland` / `F:\data` 已失效**:本机只有 `C:` 与 `D:`,`F:` 盘不存在。 > 另有一份旧副本在 `C:\Users\胡\Desktop\classisland`(数据在它自己的 `data/` 下,2026-09-18 用过),当前以 `D:\Classisland` 为准。 @@ -218,10 +222,10 @@ packages/classisland-plugin/ .NET 8 插件(独立于 pnpm workspace,不参 `typecheck` 报出 `[pnpm] pnpm not found`。要么别设,要么先 `Remove-Item Env:DSH_PNPM`。 - 也不要用 `node - @@ -564,7 +597,7 @@ onUnmounted(() => { diff --git a/packages/web-admin/src/views/PermissionsView.vue b/packages/web-admin/src/views/PermissionsView.vue index 42fd4de..30b8983 100644 --- a/packages/web-admin/src/views/PermissionsView.vue +++ b/packages/web-admin/src/views/PermissionsView.vue @@ -254,7 +254,7 @@ const assignDialog = reactive({ }); function openAssign(member: PermissionMemberDto): void { - if (member.fixed) return; // 管理员固定拥有全部权限(服务端同样 400) + if (member.fixed) return; assignDialog.member = member; assignDialog.groupIds = [...member.groupIds]; assignDialog.visible = true; @@ -301,12 +301,10 @@ async function submitAssign(): Promise { (服务端 lib/permissions.ts 的 loadEffectivePermissions)。 --> - + @@ -324,7 +322,9 @@ async function submitAssign(): Promise {
新建权限组 - 内置权限组由系统预置,可以改名与调整权限,但不能删除。 + + 默认权限组可改名与调整权限,修改后对未分组账号立即生效;内置组不能删除。 +
@@ -345,7 +345,9 @@ async function submitAssign(): Promise { @@ -370,7 +372,7 @@ async function submitAssign(): Promise {
- 只列出管理员与教师账号;管理员固定拥有全部权限,不能被分配权限组。 + 只列出管理员与教师账号;管理员始终保留权限与系统管理入口,可调整默认组或分配其他权限组。
@@ -402,7 +404,7 @@ async function submitAssign(): Promise {