chore(build): 更新.gitignore配置和清理Wails临时文件
- 添加dist/目录到.gitignore,用于排除打包输出的绿色免安装版 - 添加Wails打包过程中的临时文件和自动生成文件到.gitignore - 删除build/windows/installer/wails_tools.nsh自动生成文件 - 添加Windows安装器临时目录和Webview2安装文件到忽略列表 feat(docs): 添加万川平台对接文档和产品素材 - 创建万川平台登录到获取模型信息的流程说明文档 - 添加万川平台对接实施计划文档 - 新增产品图片、公司简介图、宣传海报、教程截图、案例展示等素材文件 refactor(runtime): 扩展通知功能类型定义 - 添加NotificationOptions接口定义 - 添加NotificationAction接口定义 - 添加NotificationCategory接口定义 - 扩展通知相关的运行时API类型声明,包括初始化、发送、注册分类等功能
272
config/docs/万川平台-登录到获取模型信息-流程说明.md
Normal file
@@ -0,0 +1,272 @@
|
||||
# 万川 AI 平台:从账号密码登录到获取模型信息
|
||||
|
||||
> 本文基于当前未提交的代码梳理,描述用户在「设置」页填入平台地址 + 账号密码后,
|
||||
> 系统如何登录、拉取模型配置并写入后端 AI 设置的完整链路。
|
||||
|
||||
## 一、整体链路总览
|
||||
|
||||
```
|
||||
用户填写平台地址 / 账号 / 密码
|
||||
│
|
||||
▼
|
||||
[1] POST /api/login ───────────────► 返回 token(缓存到 localStorage)
|
||||
│
|
||||
▼
|
||||
[2] 登录成功后并行触发:
|
||||
├─ GET /api/system/kb/relation/query 拉取岗位知识库列表
|
||||
└─ syncModel() 同步模型配置
|
||||
│
|
||||
▼
|
||||
[3] 按模型编码 code 分别拉取(携带 token):
|
||||
├─ GET /api/system/model/getByCode/generic 通用/聊天模型(必拉)
|
||||
├─ GET /api/system/model/getByCode/vision 视觉模型(可选)
|
||||
└─ GET /api/system/model/getByCode/voice 语音模型(可选)
|
||||
│
|
||||
▼
|
||||
[4] 解析 providerModels.encryptedConfig(JSON 字符串)
|
||||
→ { modelName, apiKey, endpointUrl }
|
||||
│
|
||||
▼
|
||||
[5] PUT /api/settings 写入后端 SQLite(app_settings 表)
|
||||
│
|
||||
▼
|
||||
[6] 后端聊天/视觉/语音调用时按用途读取这些配置(带回退)
|
||||
```
|
||||
|
||||
前端实现:[chatlab-web/frontend/src/api/wanchuan.js](chatlab-web/frontend/src/api/wanchuan.js)
|
||||
触发位置:[chatlab-web/frontend/src/pages/SettingsPage.jsx](chatlab-web/frontend/src/pages/SettingsPage.jsx)
|
||||
后端设置:[chatlog_fastAPI/routers/settings.py](chatlog_fastAPI/routers/settings.py)
|
||||
|
||||
---
|
||||
|
||||
## 二、第 1 步:登录获取 token
|
||||
|
||||
### 接口
|
||||
|
||||
```
|
||||
POST {platformUrl}/api/login
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
```
|
||||
|
||||
### 请求体
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "用户名",
|
||||
"password": "密码",
|
||||
"loginType": "user"
|
||||
}
|
||||
```
|
||||
|
||||
### 响应(兼容多种结构)
|
||||
|
||||
代码用以下顺序提取 token,任一命中即可:
|
||||
|
||||
```
|
||||
result.token
|
||||
result.data.token
|
||||
result.data.access_token
|
||||
result.access_token
|
||||
```
|
||||
|
||||
典型返回结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"token": "eyJhbGci...",
|
||||
"data": {
|
||||
"token": "eyJhbGci...",
|
||||
"modules": [ /* 平台模块列表,用于前端展示 */ ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### token 的存储与使用
|
||||
|
||||
- 登录成功后 token 写入 `localStorage`,key 为 `chatlab_wanchuan_token`。
|
||||
- 后续所有平台接口都带两个头(平台同时认这两种):
|
||||
```
|
||||
Authorization: Bearer {token}
|
||||
token: Bearer {token}
|
||||
```
|
||||
|
||||
对应函数:`wanchuanLogin(baseUrl, username, password)`
|
||||
([wanchuan.js:39](chatlab-web/frontend/src/api/wanchuan.js#L39))
|
||||
|
||||
---
|
||||
|
||||
## 三、第 2 步:登录的触发与自动恢复
|
||||
|
||||
登录在 [SettingsPage.jsx](chatlab-web/frontend/src/pages/SettingsPage.jsx) 的 `WanchuanPlatformForm` 组件里触发,分两种场景:
|
||||
|
||||
### 场景 A:用户点「测试连接」(`handleTestConnection`)
|
||||
|
||||
1. 调用 `wanchuanLogin()` 登录。
|
||||
2. 成功后并行执行:
|
||||
- `fetchKnowledgeBases()` 拉知识库列表
|
||||
- `syncModel()` 同步平台模型配置 → 写入后端 AI 设置
|
||||
|
||||
### 场景 B:打开设置页自动恢复(`autoLogin`)
|
||||
|
||||
- 配置(平台地址/账号/密码/已选知识库)以**后端 SQLite 为唯一数据源**,
|
||||
通过 `GET /api/settings/wanchuan` 读取,不依赖前端 origin(exe 端口变化也能恢复)。
|
||||
- 挂载时若已有保存的账号密码,自动登录并拉知识库。
|
||||
- **注意**:自动恢复时**不**自动 `syncModel`,避免覆盖用户在「AI 模型配置」里手改并保存过的值。模型同步只在用户显式操作(点「测试连接」或「从平台获取」)时进行。
|
||||
|
||||
---
|
||||
|
||||
## 四、第 3-4 步:按模型编码获取模型信息
|
||||
|
||||
这是「获取模型信息」的核心。平台按**用途**用不同的模型编码(code)区分:
|
||||
|
||||
| code | 用途 | 同步到的后端字段 |
|
||||
|-----------|------------|-----------------------------------------------|
|
||||
| `generic` | 通用/聊天 | `ai_*`(话题分析)+ `summary_*`(报告生成) |
|
||||
| `vision` | 视觉 | `vision_*`(图片/视频描述) |
|
||||
| `voice` | 语音 | `voice_*`(语音转文字) |
|
||||
|
||||
### 接口
|
||||
|
||||
```
|
||||
GET {platformUrl}/api/system/model/getByCode/{code}
|
||||
Authorization: Bearer {token}
|
||||
token: Bearer {token}
|
||||
```
|
||||
|
||||
### 响应结构
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"providerModels": {
|
||||
"modelName": "qwen-plus",
|
||||
"encryptedConfig": "{\"apiKey\":\"sk-xxx\",\"endpointUrl\":\"https://...../v1\"}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
关键点:`data.providerModels.encryptedConfig` 是一个 **JSON 字符串**,需二次 `JSON.parse` 才能拿到 `apiKey` 和 `endpointUrl`。
|
||||
|
||||
### 解析后得到
|
||||
|
||||
```js
|
||||
{
|
||||
modelName: pm.modelName, // 模型名
|
||||
apiKey: cfg.apiKey, // 来自 encryptedConfig
|
||||
endpointUrl: cfg.endpointUrl, // 来自 encryptedConfig
|
||||
}
|
||||
```
|
||||
|
||||
对应函数:`getWanchuanModelConfig(baseUrl, code)`
|
||||
([wanchuan.js:110](chatlab-web/frontend/src/api/wanchuan.js#L110))
|
||||
|
||||
错误处理:
|
||||
- HTTP 非 2xx → 抛 `获取模型[{code}]失败 HTTP {status}`(便于排查 404 路径错 / 401 token 失效)。
|
||||
- 无 `providerModels` → 抛 `平台未返回模型[{code}]配置`。
|
||||
|
||||
---
|
||||
|
||||
## 五、第 5 步:写入后端 AI 设置
|
||||
|
||||
`syncWanchuanModelToSettings()` 负责编排三次拉取并合并写入:
|
||||
|
||||
1. **generic 必拉**:拿到 `endpointUrl / apiKey / modelName` 后,同时写入两组字段:
|
||||
- 话题分析:`ai_base_url` / `ai_api_key` / `ai_model`
|
||||
- 报告生成:`summary_base_url` / `summary_api_key` / `summary_model`
|
||||
(两者同网关,但分开存便于各组独立回显与覆盖。)
|
||||
|
||||
2. **vision / voice 可选**:用 `Promise.all` 并行拉取,**失败则跳过对应字段**(`.catch(() => {})`),不打断聊天模型同步:
|
||||
- `vision_base_url` / `vision_api_key` / `vision_model`
|
||||
- `voice_base_url` / `voice_api_key` / `voice_model`
|
||||
|
||||
3. 仅写入**非空字段**;若最终 payload 为空则抛 `平台模型配置为空`。
|
||||
|
||||
4. 最后 `PUT /api/settings` 保存到后端:
|
||||
|
||||
```
|
||||
PUT /api/settings
|
||||
Content-Type: application/json
|
||||
```
|
||||
```json
|
||||
{
|
||||
"ai_base_url": "...", "ai_api_key": "...", "ai_model": "...",
|
||||
"summary_base_url": "...", "summary_api_key": "...", "summary_model": "...",
|
||||
"vision_base_url": "...", "vision_api_key": "...", "vision_model": "...",
|
||||
"voice_base_url": "...", "voice_api_key": "...", "voice_model": "..."
|
||||
}
|
||||
```
|
||||
|
||||
对应函数:`syncWanchuanModelToSettings(baseUrl, codes)`
|
||||
([wanchuan.js:151](chatlab-web/frontend/src/api/wanchuan.js#L151))
|
||||
|
||||
---
|
||||
|
||||
## 六、后端 /api/settings 的处理
|
||||
|
||||
实现在 [chatlog_fastAPI/routers/settings.py](chatlog_fastAPI/routers/settings.py)。
|
||||
|
||||
### 可编辑字段(EDITABLE_KEYS)
|
||||
|
||||
```
|
||||
ai_base_url, ai_api_key, ai_model, summary_model,
|
||||
vision_model, voice_model, topic_analysis_prompt,
|
||||
voice_base_url, voice_api_key, vision_base_url, vision_api_key,
|
||||
summary_base_url, summary_api_key
|
||||
```
|
||||
|
||||
### 密钥脱敏(SECRET_KEYS)
|
||||
|
||||
`ai_api_key / voice_api_key / vision_api_key / summary_api_key` 四个字段:
|
||||
- **GET** 返回时打码(`_mask_key`,只保留首尾、中间打 `*`)。
|
||||
- **PUT** 时若值里含 `*`,说明是 GET 返回的打码值(用户没真改),**跳过不写**,避免把真实密钥覆盖成打码串。
|
||||
|
||||
### 存储
|
||||
|
||||
所有字段以 key-value 形式存进 SQLite 的 `app_settings` 表(`INSERT ... ON CONFLICT DO UPDATE`)。
|
||||
|
||||
---
|
||||
|
||||
## 七、第 6 步:后端运行时如何使用这些配置
|
||||
|
||||
实现在 [chatlog_fastAPI/services/ai_client.py](chatlog_fastAPI/services/ai_client.py) 与
|
||||
[chatlog_fastAPI/services/runtime_settings.py](chatlog_fastAPI/services/runtime_settings.py)。
|
||||
|
||||
- `get_ai_settings()`:从 SQLite 读出全部 AI 字段(带默认值),并缓存。
|
||||
- `get_openai_client()`:聊天类调用(话题分析 / 报告 / 总结 / 对话)用全局
|
||||
`ai_base_url` + `ai_api_key`。
|
||||
- `get_client_for(purpose)`:`purpose` 为 `voice` / `vision`,
|
||||
优先用 `{purpose}_base_url` / `{purpose}_api_key`,**为空则回退**到
|
||||
`ai_base_url` / `ai_api_key`(单网关场景无需重复配。
|
||||
- 客户端按 `(base_url, api_key)` 缓存,聊天/视觉/语音可指向不同网关与密钥,
|
||||
最多累积 3 个,配置变更后自然生成新客户端。
|
||||
|
||||
---
|
||||
|
||||
## 八、相关接口速查表
|
||||
|
||||
| 步骤 | 方法 | 路径 | 用途 |
|
||||
|------|------|------|------|
|
||||
| 登录 | POST | `{platformUrl}/api/login` | 账号密码换 token |
|
||||
| 知识库 | GET | `{platformUrl}/api/system/kb/relation/query` | 拉岗位知识库列表 |
|
||||
| 模型信息 | GET | `{platformUrl}/api/system/model/getByCode/{code}` | 按 code 取模型配置 |
|
||||
| 上传 | POST | `{platformUrl}/api/system/kb/file/upload/async/{datasetId}` | 上传文件到知识库 |
|
||||
| 读平台配置 | GET | `/api/settings/wanchuan` | 后端存的平台地址/账号/密码/已选库 |
|
||||
| 存平台配置 | PUT | `/api/settings/wanchuan` | 保存平台配置 |
|
||||
| 读 AI 配置 | GET | `/api/settings` | 回显 AI 模型配置(密钥脱敏) |
|
||||
| 写 AI 配置 | PUT | `/api/settings` | 保存/同步 AI 模型配置 |
|
||||
|
||||
---
|
||||
|
||||
## 九、关键数据结构小结
|
||||
|
||||
**登录请求**:`{ username, password, loginType: "user" }`
|
||||
**登录响应取 token**:`result.token` 等多路径兜底
|
||||
**模型接口响应**:`data.providerModels.{ modelName, encryptedConfig }`
|
||||
**encryptedConfig**(JSON 字符串):`{ apiKey, endpointUrl, ... }`
|
||||
**最终归一化模型对象**:`{ modelName, apiKey, endpointUrl }`
|
||||
**写入后端的 12 个字段**:`{ai,summary,vision,voice}_{base_url,api_key,model}`
|
||||
108
config/docs/万川平台对接-实施计划.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# 万川平台对接 — 实施计划
|
||||
|
||||
> 本文为对接万川 AI 平台(登录 → 拉取模型配置)的实施计划。
|
||||
> 接口契约见同目录 [万川平台-登录到获取模型信息-流程说明.md](万川平台-登录到获取模型信息-流程说明.md)。
|
||||
|
||||
## 范围
|
||||
|
||||
### 本期做
|
||||
登录平台 → 拉模型配置 → **log 打印**。平台凭证可编辑、可持久化、可重置。
|
||||
|
||||
### 本期不做(留第二期)
|
||||
- 回填 AI 表单(`form.ai.*`)
|
||||
- 调 `SaveAutoReplyConfig` 落盘 + 推 helper 重载
|
||||
|
||||
理由:先打印确认平台返回的数据结构与解析结果正确,再接回填与保存。
|
||||
|
||||
## 架构决策
|
||||
|
||||
- **Go 只做透传代理 + 凭证存取**,不碰业务解析。仅用于绕开 WebView 的 CORS 限制。
|
||||
- **业务逻辑全在前端**:取 token、按 code 拉取、解析 `encryptedConfig`、字段映射。
|
||||
- **持久化存 `config/config.json`**(exe 同级,重启自动恢复,与浏览器无关),新增 `platformConfig` 段。不使用 localStorage。
|
||||
- ⚠️ 密码以明文存在 config.json(本地桌面工具常见做法)。如需更稳可加简单混淆,但非真加密。
|
||||
|
||||
## 一、Go 端
|
||||
|
||||
新文件:`wanchuan_proxy.go`(与 [app.go](../../app.go) 同级,main 包)。
|
||||
|
||||
### 1.1 透传代理方法(绑定到 App)
|
||||
|
||||
| 方法 | 行为 |
|
||||
|------|------|
|
||||
| `WanchuanLogin(baseUrl, username, password string) string` | POST `{baseUrl}/api/login`,body `{username, password, loginType:"user"}`;**原样返回**平台响应 JSON 字符串;日志打印(密码/token 打码) |
|
||||
| `WanchuanGetModel(baseUrl, code, token string) string` | GET `{baseUrl}/api/system/model/getByCode/{code}`;带头 `Authorization: Bearer {token}` 和 `token: Bearer {token}`;**原样返回**响应 JSON;日志打印 |
|
||||
|
||||
不解析 token、不合并字段、不存盘——平台返什么就返什么。
|
||||
|
||||
### 1.2 凭证存取方法(绑定到 App)
|
||||
|
||||
| 方法 | 行为 |
|
||||
|------|------|
|
||||
| `GetPlatformConfig() interface{}` | 读 config.json 的 `platformConfig` 段回前端 |
|
||||
| `SavePlatformConfig(jsonData string) (bool, string)` | 存 `platformConfig` 段(重置 = 存空值) |
|
||||
|
||||
### 1.3 config 结构改动
|
||||
|
||||
[config/types.go](../types.go) 新增结构并挂到 `Config`:
|
||||
|
||||
```go
|
||||
type PlatformConfig struct {
|
||||
BaseURL string `json:"baseUrl"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// Config 增加字段:
|
||||
// PlatformConfig PlatformConfig `json:"platformConfig"`
|
||||
```
|
||||
|
||||
[config/config_manager.go](../config_manager.go) 新增 `UpdatePlatformConfig`,复用现有 `SaveGlobalConfig`。
|
||||
|
||||
> 改了 App 方法后需跑 `wails dev` / `wails build` 重新生成 `frontend/wailsjs/go/main/App.js` 绑定。
|
||||
|
||||
## 二、前端
|
||||
|
||||
文件:[frontend/src/components/AutoReply.vue](../../frontend/src/components/AutoReply.vue),在 AI 配置区(`#auto-section-ai`,02)顶部新增「万川平台」卡片。
|
||||
|
||||
### 2.1 UI
|
||||
|
||||
- 输入框:平台地址 / 账号 / 密码(绑 reactive,挂载时 `GetPlatformConfig` 回填,可编辑)
|
||||
- 按钮「登录并获取模型」
|
||||
- 按钮「重置」:清空凭证(`SavePlatformConfig` 存空)后重新走一次流程
|
||||
|
||||
### 2.2 「登录并获取模型」逻辑
|
||||
|
||||
1. `SavePlatformConfig(当前输入)` 先存凭证
|
||||
2. `WanchuanLogin(url, user, pwd)` → `JSON.parse` → 多路径取 token:
|
||||
`token` / `data.token` / `data.access_token` / `access_token`
|
||||
3. 依次 `WanchuanGetModel(url, code, token)`:
|
||||
- `generic`(必拉)
|
||||
- `vision`、`voice`(可选,失败跳过)
|
||||
4. 每个响应取 `data.providerModels`,对 `encryptedConfig` 做**二次 `JSON.parse`**,
|
||||
得 `{ modelName, apiKey, endpointUrl }`
|
||||
5. **`console.log` + `LogFrontend` 打印**原始响应与解析结果 —— **到此为止。**
|
||||
|
||||
### 2.3 字段映射(供第二期参考)
|
||||
|
||||
| 万川 code | 解析字段 | AIConfig 字段 |
|
||||
|-----------|---------|---------------|
|
||||
| `generic` | endpointUrl / apiKey / modelName | `baseUrl` / `apiKey` / `model` |
|
||||
| `vision` | endpointUrl / apiKey / modelName | `visionBaseUrl` / `visionApiKey` / `visionModel` |
|
||||
| `voice` | endpointUrl / apiKey / modelName | `audioBaseUrl` / `audioApiKey` / `audioModel` |
|
||||
|
||||
(`summary_*` 无对应业务,忽略;知识库列表不拉。)
|
||||
|
||||
## 三、验证
|
||||
|
||||
- `go build` 通过;`wails dev` 起来后在 AI 配置区填真实平台地址/账号/密码,点「登录并获取模型」,
|
||||
看浏览器控制台和后端日志打印出 generic/vision/voice 的解析结果,确认 `endpointUrl/apiKey/modelName` 拿对。
|
||||
- 重启应用,确认账号密码自动回填(持久化生效)。
|
||||
- 点「重置」,确认凭证清空。
|
||||
|
||||
## 四、第二期(确认数据无误后)
|
||||
|
||||
把 2.2 第 5 步从"打印"改为:
|
||||
- 按 2.3 映射回填 `form.ai.*`
|
||||
- 调现有 `SaveAutoReplyConfig(form)` 落盘 + 推 helper 重载
|
||||
|
||||
至此 AI 配置实现平台动态下发。
|
||||
BIN
config/materials/产品图片/外观/产品全景图.jpg
Normal file
|
After Width: | Height: | Size: 1017 KiB |
BIN
config/materials/产品图片/外观/产品外观图.jpg
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
config/materials/产品图片/细节/局部放大.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
config/materials/产品图片/细节/细节特写.png
Normal file
|
After Width: | Height: | Size: 212 KiB |
BIN
config/materials/公司简介图.jpg
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
config/materials/宣传海报/产品宣传图.jpg
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
config/materials/宣传海报/小红书样式.webp
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
config/materials/宣传海报/活动海报.png
Normal file
|
After Width: | Height: | Size: 971 KiB |
BIN
config/materials/工作流图/标准作业流程.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
config/materials/教程截图/安装步骤/第一步开箱.png
Normal file
|
After Width: | Height: | Size: 231 KiB |
BIN
config/materials/教程截图/安装步骤/第三步调试.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
config/materials/教程截图/安装步骤/第二步组装.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
config/materials/案例展示/装修案例/卧室效果图.jpg
Normal file
|
After Width: | Height: | Size: 283 KiB |
BIN
config/materials/案例展示/装修案例/客厅效果图.jpg
Normal file
|
After Width: | Height: | Size: 286 KiB |
BIN
config/materials/案例展示/门店实拍.jpg
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
config/materials/联系方式卡片.png
Normal file
|
After Width: | Height: | Size: 93 KiB |