# hono-flash **Repository Path**: Kuaima-tech/hono-flash ## Basic Information - **Project Name**: hono-flash - **Description**: hono-flash是hono的快速开发模板 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-02 - **Last Updated**: 2026-08-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RBAC 一体化管理平台(RBAC + CRM + 数字员工 + ChatBI) 基于 **Hono + HonoX + SQLite (Drizzle ORM)** 构建的全栈一体化管理平台,Node.js 运行时,服务端渲染 + islands 渐进增强(MPA 风格),无前端框架依赖。以 **RBAC 权限模型**为核心,延伸出 CRM 客户管理、数字员工(Agent)对话与定时任务、AI 问数(ChatBI)三大业务模块,覆盖「权限 → 数据 → 智能体」完整闭环。 ## 功能总览 | 模块 | 说明 | |---|---| | **权限中心(RBAC)** | 用户 / 角色 / 权限点(分组树)/ 部门树;**动作级(per-permission)功能权限**校验;角色继承;会话管理 | | **首页工作台** | 登录后落地页:多数字员工流式会话控制台(SSE 打字机效果、工具调用卡片、多会话管理) | | **CRM 客户管理** | 客户增删改查、阶段流转、负责人/所属部门(组织归属);持有 `crm:contact:read` 即见全部客户 | | **数字员工(Agent)** | 数据集权限模型(agent_datasets 授权 → 能力推导);LLM↔工具循环编排;多供应商模型库;每日定时任务;站内通知 | | **AI 问数(ChatBI)** | 自然语言 → DSL(JSON)→ 确定性 SQL → 只读执行 → 图表;可配置语义层(数据集 / 字段 / 指标 / 同义词) | | **导航菜单** | 数据库驱动(menus 表),侧栏与 ⌘K 命令面板共用,可按权限过滤,管理页可视化增删改排序 | ## 技术栈 | 层 | 选型 | |---|---| | 运行时 | Node.js 18+(开发验证环境 Node 22) | | Web 框架 | Hono 4.x + HonoX 0.1.x(元框架:文件路由 / SSR / islands) | | 构建 | Vite 8 + @hono/vite-build(Node 适配器,`staticRoot: ./dist`) | | UI | daisyUI 5.x(Tailwind v4 CSS 插件)+ Geist / Noto Sans SC 字体,基础字号 17px | | 主题 | light 默认 + dark 跟随系统(navbar 手动切换,localStorage 记忆) | | 交互 | HonoX islands:Chat 控制台(SSE 流式)、⌘K 命令面板、通知中心、批量操作、确认弹窗、Toast 等 | | ORM / 数据库 | Drizzle ORM + better-sqlite3(SQLite 单文件,WAL 模式,启动自动迁移) | | 认证 | Session cookie(httpOnly + SameSite=Lax,7 天过期),scrypt 密码哈希(node:crypto 零依赖) | | 安全 | @hono/csrf Origin 校验、服务端动作级权限校验、ChatBI DSL 白名单 | | 测试 | Vitest + Hono app.request() 集成测试(内存 SQLite + seed) | ## 快速开始 ```bash npm install npm run db:migrate # 建库(sqlite.db) npm run db:seed # 初始化演示数据(幂等,可重复执行) npm run dev # 启动开发服务器 http://localhost:5173 ``` 应用启动时(`app/server.ts`)会自动幂等注册:内置权限点与分组、部门树、角色权限回填、演示客户、示例数字员工、模型模板、ChatBI 语义层、默认导航菜单——新迁移 + 重启 dev 即可生效,无需手工 seed。 生产构建与运行: ```bash npm run build npm run preview # node dist/index.js,默认端口 3000(可用 PORT 覆盖) ``` ## 默认账号(演示用,生产环境务必改密) | 账号 | 密码 | 角色 | 说明 | |---|---|---|---| | admin@example.com | admin123 | admin | 系统管理员,拥有全部 26 项权限,归属华东区 | | user@example.com | user123 | user | 基线用户:仅 user:read、role:read 只读权限,归属华东团队A | | 数据助手小智 | —(数字员工,非登录账号) | — | 示例员工,已授权 contacts / users / departments 三个数据集,可查客户 / 生成日报 / AI 问数 | ## 权限模型 ### 权限点清单(26 项,按分组) | 分组 | 权限 | 说明 | |---|---|---| | 用户管理 | `user:read` / `user:create` / `user:update` / `user:delete` | 用户账户查看 / 创建 / 分配角色 / 删除 | | 角色管理 | `role:read` / `role:create` / `role:update` / `role:delete` | 角色查看 / 创建 / 编辑权限 / 删除 | | 组织管理 | `org:department:manage` | 部门树(区域 → 大区 → 团队)管理与维护 | | 客户管理 | `crm:contact:read` / `create` / `update` / `delete` / `assign` / `crm:report:view` | 客户增删改查、分配转移、CRM 报表 | | 数字员工 | `agent:read` / `create` / `update` / `delete` / `chat` / `task:view` / `schedule:manage` / `model:manage` | 员工档案、对话、任务、定时任务、模型配置 | | 问数 | `chatbi:query` / `chatbi:model:manage` | 使用 AI 问数 / 管理语义层数据模型 | | 菜单管理 | `menu:manage` | 管理导航菜单(增删改排序分组与菜单项) | ### 动作级权限校验 - **动作级(功能权限)**:路由守卫 `requirePermission(perm)`(见 `app/lib/auth/guard.tsx`),无权限返回 403 页。权限即「能否执行某操作」(如 `crm:contact:read`),不区分数据范围——持有读权限即可查看全部客户。 - **角色继承**:`role_parents` 表支持多角色继承(带环检测),`getRoleClosure()` 展开祖先链取并集。 - **内置角色**:`ensureBuiltinRolePermissions()` 幂等回填——admin 自动补挂全部新权限点;user 保持基线非特权(不挂 CRM / agent 权限)。 - **部门体系**:`departments` 表与 users / agents / contacts 的 `departmentId` 仅作组织归属展示,**不参与权限判定**。 ### 数据模型(核心表) ``` departments(部门树,parent_id,组织归属展示) users ──┬── user_roles ── roles ──┬── role_permissions ── permissions(分组树) │ └── role_parents(角色继承) ├── sessions(会话) └── contacts(CRM 客户,owner_id 负责人 / department_id 所属部门) agents(能力由 agent_datasets 授权推导)─┬─ agent_datasets(员工 → 数据集,ChatBI 语义层) ├─ agent_tasks(对话/定时任务记录) ├─ agent_schedules(每日 HH:MM 定时) ├─ ai_models(多供应商模型库) └─ conversations(每员工多会话)─ messages(user/assistant/tool) notifications(站内通知) chatbi_dataset / chatbi_dataset_field / chatbi_metric / chatbi_biz_term(问数语义层) menus(导航菜单,parent_id 自引用) ``` 外键均级联删除;被引用的角色不可删除(302 + flash 提示)。 ## 首页工作台(多 Agent 流式控制台) - `/` = 登录后落地页(`app/islands/chat-console.tsx`):左侧数字员工列表 + 右侧会话窗。 - 聊天走 `POST /chat/stream`(**SSE 流式**,协议 `meta → (token|tool_start|tool_end)* → done|error`,守卫 `agent:chat`)+ `GET /chat/history?conversationId=`;`/agents/[id]` 详情页的对话卡共用同一端点。 - **每员工多会话**:`conversations` / `messages` 表持久化(user/assistant/tool 三角色,assistant 行带 toolCalls 用于重建上下文);会话列表支持新建 / 重命名 / 清空 / 删除 / 复制文本 / 复制 Markdown。 - 客户端助手 `app/lib/chat/sse-client.ts`(fetch + ReadableStream 解析,EventSource 不支持 POST);共享渲染 `app/components/markdown.tsx`(表格 + 安全链接)。 ## 数字员工系统(Agent MVP) - **数据集权限模型(2026-08-06 起)**:数字员工不再挂角色,能力由 `agent_datasets` 授权数据集推导(`app/lib/agent/capabilities.ts`)——授权任意数据集 → `chatbi:query`(AI 问数);授权 `contacts` 客户表 → 额外 `crm:contact:read` + `crm:report:view`。**工具执行按推导出的能力校验**(`executeTool`),`chatbi_query` 还受数据集白名单约束(只能查已授权数据集,`dsl.tables ⊆ 授权集合`)。`agent_roles` / `agents.departmentId` 为废弃保留列(不再读写)。 - 表单:`/agents` 创建/编辑时勾选「可访问数据集」(来自 ChatBI 语义层),提交后 `agent_datasets` 覆盖式写入。 - 旧库自动迁移:`migrateAgentPermissions()` 启动时幂等执行——任务 creatorId 改挂 admin、`bindUserId` 置空、清理遗留 agent-* 账号。 - **编排**:`runAgentTaskStream(agent, opts, emit)` 事件流(token / tool_start / tool_end / done / error),LLM ↔ 工具循环上限 5 轮,全程写入 `agent_tasks`;非流式版 `runAgentTask` 保留给 ChatBI / 调度器。 - **模型配置(多供应商)**:`/agents/models` 管理模型库(需 `agent:model:manage`),预置 DeepSeek / OpenAI / 通义千问 / Kimi / Ollama / 自定义模板。API Key 存于 `ai_models` 表(**明文存储,已被 .gitignore 忽略,勿提交仓库**)。员工未选模型时回退环境变量 `DEEPSEEK_API_KEY`;全未配置时对话降级为本地占位回复(Ollama 本地无需 Key)。 - **内置工具**(`app/lib/agent/tools.ts`): | 工具 | 能力要求 | 说明 | |---|---|---| | `query_crm_contacts` | crm:contact:read | 查询客户列表(授权 contacts 数据集),支持姓名/公司模糊搜索 | | `get_me` | — | 返回员工自身身份信息(姓名/邮箱/状态) | | `generate_daily_report` | crm:report:view | 按阶段聚合生成客户日报 Markdown | | `send_notification` | agent:chat | 发送站内通知(notifications 表,通知中心展示) | | `chatbi_query` | chatbi:query | 问数:自然语言 → 数据,仅限已授权数据集,结论带 `/chatbi?q=` 深链 | - **定时任务**:`/agents/[id]` 页可新建「每日 HH:MM」定时任务,进程内调度器 30s 轮询到期执行(测试环境自动跳过)。 - **站内通知**:navbar 通知中心(`app/islands/notification-center.tsx`)+ `/api/notifications` 接口。 ## ChatBI(AI 问数) - **用法**:侧栏「问数」→ 输入业务问题(如「各阶段客户数」「各部门客户数」「每月新增客户数」)→ 返回表格 + ECharts 图表 + 一句结论。 - **原理**:DeepSeek 把自然语言转成 **DSL JSON**(不是 SQL)→ 后端 `validateDsl` 白名单校验 → `dslToSql` **确定性模板函数**拼 SQLite SQL → **只读连接**执行(readonly + query_only + 强制 LIMIT)→ `summarize` 生成结论 → 自动选图(时间→折线、排行→柱、阶段→饼、纯聚合→大数字)。 - **语义层**:`chatbi_dataset / chatbi_dataset_field / chatbi_metric / chatbi_biz_term` 四张表(并入主库),把物理字段翻译成业务词(如 `count(contacts.id)` →「客户数」);**敏感字段(如 phone)不注册即不可查**。 - **数据可见性**:真人问数按功能权限执行(持有 `chatbi:query` 即查询全部);**数字员工问数受数据集白名单约束**——`askChatbi(question, { allowedDatasets })` 校验 DSL 引用的数据集全部在授权集合内,实现数据域隔离。 - **数据模型配置**:`/chatbi/models`(需 `chatbi:model:manage`)网页配置语义层——数据集(注册业务表 + 关联规则)、字段语义(业务名 / 度量 / 聚合 / 敏感)、指标(表达式自动拼装)、同义词;支持**从数据库一键导入**(读 sqlite_master → 建数据集 + 自动带出字段、主键自动度量、created_at 自动识别为时间)。配置后即时生效,无需重启。 - **衔接**:`/chatbi?q=` 深链自动查询;`/chatbi/handoff` 可把问题配置为数字员工的每日定时任务(需 `agent:schedule:manage`)。 ## 导航菜单(DB 驱动) - `menus` 表(自引用 parentId 级联删):顶级行 = 分组标题,子行 = 菜单项(name / href / icon / requiredPermission / order / status)。 - `loadMenuTree(perms)`:按权限过滤 + 空分组剔除;侧栏与 ⌘K 命令面板(`app/islands/command-palette.tsx`)均消费菜单数据。 - 默认 5 组 12 项:总览(工作台 / 仪表盘)、管理(用户 / 角色 / 权限 / 部门 / 菜单)、业务(客户管理)、智能体(数字员工 / 模型配置)、分析(问数 / 数据模型)。 - `/admin/menus`(需 `menu:manage`)可增删改排序分组与菜单项;「修改密码 / 我的会话」等 SELF_LINKS 仍硬编码。 ## 安全设计 - **CSRF**:POST 校验 Origin,允许 `localhost` 任意端口 + `ALLOWED_ORIGINS` 环境变量(逗号分隔)。 - **缓存**:全局中间件对应用页面强制 `Cache-Control: no-store` + `Clear-Site-Data`,防止浏览器缓存旧数据导致列表不刷新。 - **密码**:scrypt(node:crypto),生产环境 cookie 自动加 `Secure`(`NODE_ENV=production`)。 - **ChatBI**:字段 / 表全白名单校验,LLM 无法引用未注册字段;多表 JOIN 仅限语义层声明的关联规则;`CHATBI_DATA_DB` 可指向独立数据文件库(meta/data 分库)。 - **Agent**:工具仅读 + 通知(无写库工具);能力按员工授权数据集(agent_datasets)推导校验;AI Key 明文存库但被 gitignore。 ## 环境变量 支持在项目根目录创建 **`.env`** 文件配置(已被 .gitignore 忽略;系统/命令行环境变量优先级更高,不会被 .env 覆盖)。 | 变量 | 说明 | |---|---| | `DB_FILE` | 数据库文件路径,默认 `./sqlite.db` | | `DB_LOG` | 打印后端 SQL 日志(`1`/`true`/`on` 开启,默认关闭;测试环境自动静默) | | `ALLOWED_ORIGINS` | 部署域名白名单(逗号分隔,CSRF) | | `DEEPSEEK_API_KEY` | DeepSeek API Key(员工未选模型时的兜底) | | `DEEPSEEK_BASE_URL` / `DEEPSEEK_MODEL` | DeepSeek 端点 / 模型覆盖(可选,默认模型 `deepseek-v4-flash`) | | `DEEPSEEK_THINKING` | DeepSeek 思考模式开关(默认关闭;设 `true` 开启。⚠️ 思考占用 token 且工具调用多轮需回传 reasoning_content,本项目仅支持关闭状态) | | `CHATBI_MODEL` | 问数(ChatBI)专用模型名(可选,如 `deepseek-v4-flash`;缺省用模型库第一个可用模型。注意 `deepseek-chat` 已于 2026-07-24 停用) | | `CHATBI_DATA_DB` | 问数只读数据源文件路径(可选,缺省用主库) | | `PORT` | 生产服务端口,默认 3000 | ## 常用命令 ```bash npm run db:generate # 由 schema 生成迁移文件(drizzle-kit generate) npm run db:migrate # 应用迁移(drizzle-kit migrate) npm run db:seed # 初始化/重置演示数据(幂等) npm test # 运行 vitest 集成测试 npm run build # 生产构建(client + SSR) npm run preview # 运行生产构建产物 ``` > ⚠️ 已知问题:本机 vitest 环境损坏(2026-08-04 起),最小用例也报 `Cannot read properties of undefined (reading 'config')`,与代码无关(vitest@4.1.10 已是最新)。测试代码已写好(27 个用例文件),环境修复后 `npm test` 即可跑;当前验证使用 `tsc` + `npm run build` + dev server 冒烟。 ## 生产部署注意事项 - **改密**:seed 的演示账号仅用于本地,生产部署前应通过管理界面修改密码或更换 seed。 - **CSRF 来源**:`ALLOWED_ORIGINS=https://rbac.example.com npm run preview`。 - **Cookie Secure**:`NODE_ENV=production` 时 session cookie 自动加 `Secure`(需 HTTPS)。 - **数据库**:默认 `./sqlite.db`(WAL),可用 `DB_FILE` 指定路径;启动时自动执行迁移与内置数据注册。 - **AI Key**:通过 `/agents/models` 界面配置(存库明文);或配置 `DEEPSEEK_API_KEY` 环境变量。 ## 项目结构 ``` app/ ├── server.ts # 应用入口:内置数据幂等注册 + createApp + 启动调度器 ├── client.ts # 客户端入口(honox/client createClient) ├── global.d.ts # Hono Env Variables 类型(db/user/permissions) ├── style.css # Tailwind v4 + daisyUI 入口(主题 / 17px / dark variant) ├── components/ # 共享 UI 组件库(服务端 JSX:Badge / Modal / Markdown / Pagination / Icon 等) ├── islands/ # HonoX islands(客户端交互:chat-console / chatbi-panel / command-palette / │ # notification-center / bulk-actions / permission-picker / join-rule-editor 等) ├── routes/ # 文件路由 │ ├── _renderer.tsx # 全局布局(drawer 侧栏 + navbar + ⌘K + 通知中心) │ ├── _middleware.ts # 全局中间件(injectDb / logger / CSRF / noStore) │ ├── index.tsx # 首页 = 工作台(多 Agent 流式控制台) │ ├── login.tsx / logout.tsx / _404.tsx / _error.tsx │ ├── admin/ # 管理后台:仪表盘 / 用户 / 角色 / 权限 / 部门 / 菜单 / 我的会话 / 个人资料 │ ├── crm/ # 客户管理(列表 + 详情) │ ├── agents/ # 数字员工(列表 / 详情对话 / 模型配置) │ ├── chat/ # 会话 API:stream(SSE) / history / conversations / conversation / overview │ ├── chatbi/ # 问数(面板 / query API / 数据模型 / handoff 定时推送) │ └── api/notifications.ts # 站内通知 API ├── lib/ │ ├── db/ # schema / db 单例(WAL + 自动迁移)/ seed │ ├── auth/ # password(scrypt)/ session / guard(requireAuth / requirePermission) │ ├── rbac/ # 权限常量与查询(动作级 / 角色继承)/ 菜单系统 │ ├── crm/ # 客户查询与演示数据 │ ├── agent/ # llm(SSE 流式)/ run(工具循环编排)/ tools / models / scheduler / seed │ ├── chat/ # 会话管理 / SSE 客户端 / 转录导出 │ └── chatbi/ # planner(LLM→DSL)/ dsl / sql / exec / semantic / chart / summarize / seed public/ # 静态资源(theme.js / 头像 / favicon) tests/ # vitest 集成测试(内存 SQLite + seed) drizzle/ # 迁移文件(0011 个迁移) docs/ # 产品设计文档(MVP 执行计划等) ```