1. 页面概览
数据源管理页(路由 /datasources)属于 AIP「Action 栏目」,管理平台接入的外部数据源:列表展示(ID/名称/类型/可见性/描述/连接信息),支持新建、编辑、测试连接、导入元数据、作用域编辑(仅管理员)与删除;连接参数存于 connection_config,密码不回显。
一句话总结:AIP 数据源 CRUD + 测试连接 + 元数据导入 + 作用域(可见性/授权清单)管理页,对接后端
/datasources 系列接口。2. 访问入口
- 路由与菜单:路由
/datasources(nameDataSources),挂 ActionLayout(左侧菜单「数据源管理」),Action 工作台首页卡片也可进入;源码action/web/src/views/DataSourcesPage.vue。 - 认证与权限:路由
meta.requiresAuth = true,需先登录 AIP(aip_token);后端接口挂 protected 组(仅 JWT;非管理员也可增删改)。列表只显示当前用户可见的数据源(D9 作用域过滤);「作用域」按钮为管理员专属(前端按aip_is_admin隐藏,后端 admin 组 + 服务层二次校验)。 - 端口与 API 前缀:AIP 18080;API 前缀
/aip-api/v1(aipClient,/datasources系列)。
3. 界面布局
┌──────────────────────────────────────────────┐ │ ① 页头:数据源管理 + [新建数据源/收起表单] │ │ ② 操作结果提示条(alert,可关闭) │ │ ③ 新建/编辑表单卡 + [创建/更新数据源][取消] │ │ 名称*/类型*/主机/端口/数据库名/用户名/密码/描述 │ │ ④ 数据源列表卡(加载中 / 空态 / 表格) │ │ ID·名称·类型·可见性标签·描述·连接信息·操作 │ │ ⑤ 作用域弹窗(仅管理员):可见性/授权角色/授权用户│ │ ⑥ 结果弹窗(测试连接/导入元数据 JSON) │ └──────────────────────────────────────────────┘
各板块职责:
- ① 页头:标题 + 「新建数据源」切换表单显隐(表单已开时变「收起表单」)。
- ③ 新建/编辑表单:编辑时标题变「编辑数据源」、提交按钮变「更新数据源」;取消即收起。
- ④ 列表:加载中显示「加载中...」,空数据显示「暂无数据源,请点击"新建数据源"添加。」;行内操作:测试连接 / 导入元数据 / 编辑 / 作用域(管理员) / 删除。可见性列以彩色标签展示
public 全员/team 指定角色/private 仅创建者。 - ⑤ 作用域弹窗(
scopeModal):管理员调整可见性并勾选授权角色/用户;team时至少需选一个角色或用户(前端先校验,后端再校验)。 - ⑥ 结果弹窗:
modal-overlay遮罩 +modal-card,展示测试连接/导入元数据接口返回的 JSON;点「关闭」或遮罩空白处关闭。
4. 交互元素
| 控件 | 位置 | 含义与作用 |
|---|---|---|
| 「新建数据源」/「收起表单」 | 页头 | 切换表单显隐(showCreateForm) |
| 数据源名称 * | 表单 | 必填;占位 如 sales_data_warehouse |
| 数据库类型 * | 表单 | 必填下拉:PostgreSQL(POSTGRESQL)/MySQL(MYSQL)/SQLite(SQLITE)/SQL Server(SQLSERVER) |
| 主机地址 / 端口 / 数据库名 / 用户名 | 表单 | 连接参数;占位 localhost / 5432 / chatbi_forge_dev / postgres;端口为 number 类型 |
| 密码 | 表单 | type=password,占位「输入密码」;编辑时不回填,留空表示不修改 |
| 描述 | 表单 | textarea(2 行),占位「数据源的简单描述...」 |
| 「创建数据源」/「更新数据源」 | 表单 | 提交;提交中显示「提交中...」并禁用;成功后 alert 成功并刷新列表 |
| 「取消」 | 表单 | resetForm(清空表单、关闭表单) |
| 「测试连接」 | 列表行 | 用当前数据源配置调用 /datasources/:id/test,结果以 JSON 弹窗展示;连接失败时后端仍返回 200 + success:false(同样以结果弹窗展示完整错误信息),仅请求本身异常(网络/4xx/5xx)才走 alert |
| 「导入元数据」 | 列表行 | 调用 /datasources/:id/import-metadata,结果以 JSON 弹窗展示 |
| 「编辑」 | 列表行 | 回填表单进入编辑态(标题「编辑数据源」);不回显/不提交作用域字段(作用域改动走弹窗,避免普通用户误触 403) |
| 「作用域」(仅管理员) | 列表行 | 打开作用域弹窗:可见性下拉(public/team/private)+ 多选授权角色(/roles)+ 多选授权用户(/users);保存调用 PUT /datasources/:id/scope |
| 可见性标签 | 列表列 | public 全员(绿)/ team 指定角色(琥珀)/ private 仅创建者(红);取自响应的 visibility 字段(空值当 public) |
| 「删除」 | 列表行 | confirm 确认「确定要删除数据源"xx"吗?此操作不可撤销。」后调用 DELETE |
5. 后端关联
5.1 API 端点
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /aip-api/v1/datasources | 数据源列表(响应 {data_sources: [...]}) |
| POST | /aip-api/v1/datasources | 创建数据源(201 返回数据源) |
| GET | /aip-api/v1/datasources/:id | 单个数据源 |
| PUT | /aip-api/v1/datasources/:id | 更新数据源(name/type 必填且 type 为合法枚举) |
| DELETE | /aip-api/v1/datasources/:id | 删除数据源(响应 {deleted}) |
| POST | /aip-api/v1/datasources/:id/test | 测试连接(body 为 name/type/connection_config) |
| POST | /aip-api/v1/datasources/:id/import-metadata | 导入元数据 |
| PUT | /aip-api/v1/datasources/:id/scope | 作用域更新(admin 组):{visibility, allowed_roles, allowed_users},返回更新后的数据源 |
| GET | /aip-api/v1/roles / /aip-api/v1/users | 作用域弹窗下拉数据(admin 组;仅管理员打开弹窗时调用) |
5.2 请求体结构
创建/更新 payload 形如 {name, type, connection_config:{host, port, user, password, database, description, active}}(active 恒为 true);可选作用域字段 visibility / allowed_roles / allowed_users(仅管理员可提交实际变更,普通用户提交不一致取值 → 403)。
5.3 关键机制
- 作用域过滤(D9):
GET /datasources只返回调用者可见子集(public + 自己创建的 + 授权清单命中),前端无需再过滤;第三方私有源不出现在列表,直接GET /datasources/:id返回 404。 - 任务化导入元数据:
import-metadata为 V5 Stage 0 任务化端点(submitAndWaitTask):快路径窗口内完成返回旧同步响应语义(旧字段 +task_id),超时返回 HTTP 202{task_id, status: running, type},进度经GET /tasks/:id轮询;页面不主动轮询。 - 可选 AI 描述:导入端点支持
?ai_generate_descriptions=true调用 LLM 生成表/列业务描述,页面默认不传(false,仅复制外部表结构)。 - 错误口径:失败响应统一
{error: "..."};前端 alert 展示err.response?.data?.error || err.message。
6. 权限与安全
- 进入页面需 AIP 登录(路由 requiresAuth,Bearer aip_token,aipClient 自动附带)。
- 后端数据源接口属 protected 组仅 JWT 校验(DS-24 契约:非 admin 也可更新/删除/导入),页面无角色限制。
- 作用域(D9):
PUT /datasources/:id/scope挂 admin 组,页面「作用域」按钮仅当localStorage.aip_is_admin === '1'时渲染;普通用户即使直接调接口也会被 403(adminMiddleware)与 403(服务层纵深防御)双重拒绝。管理员可收紧为team/private,普通用户不可自我提权(提交与库中不一致的作用域取值一律 403)。 - 删除有
confirm二次确认;提交中submitting置位防连点。 - 密码不回显、不回填(编辑时密码留空);连接信息仅展示 host:port/database。
7. 常见问题与排错
- 「测试连接」失败:数据库不可达或账号密码错误。核对 host/port/user/password 与防火墙;SQLite 类型确认文件路径/权限。
- 「导入元数据」无响应或只有 task_id:快路径窗口内未完成会返回 202
{task_id}。用GET /aip-api/v1/tasks/:id轮询进度;失败查数据源连接与后端日志。 - 创建/更新报 400:
name、type必填,且type必须是 POSTGRESQL/MYSQL/SQLITE/SQLSERVER 之一。 - 页面 401 跳登录:token 过期。重新登录 AIP 后返回本页。
8. 已知缺陷与边界
| 项 | 说明 |
|---|---|
| 编辑密码不回填 | 编辑后不保存密码则保持原值(留空不修改) |
| 非管理员可写 | 数据源接口仅 JWT 保护,普通账号也可增删改(DS-24 既有契约,未在 D9 变更) |
| 无 AI 描述开关 | 页面未暴露 ai_generate_descriptions,默认不生成 AI 描述 |
| 列表本地分页 | 后端 /datasources 仍为一次性取前 100 条,页面按 10 条/页本地切片(D9 未改分页协议) |
作用域弹窗不回显 allowed_* 的失效项 | 授权用户下拉取自 /users(分页/上限由该接口决定),已删除用户的 ID 仍在白名单中但不会再命中 |
注:列表无分页(后端固定取前 100 条,页面无分页控件)已于 2026-09-06 修复(本地分页)。
注:导入任务化不轮询终态(202 时需手动查任务)已于 2026-09-06 修复(轮询 /tasks/:id 至终态并提示)。
注(2026-09-17):D9 新增可见性列与作用域弹窗;越权访问单对象端点统一 404(不泄露存在性),列表端点过滤。