mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-23 23:01:21 +08:00
优化api接口说明
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -57,4 +57,5 @@ Thumbs.db
|
||||
|
||||
wcdb/
|
||||
*info
|
||||
*.md
|
||||
概述.md
|
||||
chatlab-format.md
|
||||
|
||||
16
README.md
16
README.md
@@ -38,6 +38,22 @@ WeFlow 是一个**完全本地**的微信**实时**聊天记录查看、分析
|
||||
- 统计分析与群聊画像
|
||||
- 年度报告与可视化概览
|
||||
- 导出聊天记录为 HTML 等格式
|
||||
- HTTP API 接口(供开发者集成)
|
||||
|
||||
|
||||
## HTTP API
|
||||
|
||||
> [!WARNING]
|
||||
> 此功能目前处于早期阶段,接口可能会有变动,请等待后续更新完善。
|
||||
|
||||
WeFlow 提供本地 HTTP API 服务,支持通过接口查询消息数据,可用于与其他工具集成或二次开发。
|
||||
|
||||
- **启用方式**:设置 → API 服务 → 启动服务
|
||||
- **默认端口**:5031
|
||||
- **访问地址**:`http://127.0.0.1:5031`
|
||||
- **支持格式**:原始 JSON 或 [ChatLab](https://chatlab.fun/) 标准格式
|
||||
|
||||
📖 完整接口文档:[docs/HTTP-API.md](docs/HTTP-API.md)
|
||||
|
||||
|
||||
## 快速开始
|
||||
|
||||
312
docs/HTTP-API.md
Normal file
312
docs/HTTP-API.md
Normal file
@@ -0,0 +1,312 @@
|
||||
# WeFlow HTTP API 接口文档
|
||||
|
||||
WeFlow 提供 HTTP API 服务,支持通过 HTTP 接口查询消息数据,支持 [ChatLab](https://github.com/nichuanfang/chatlab-format) 标准化格式输出。
|
||||
|
||||
## 启用 API 服务
|
||||
|
||||
在设置页面 → API 服务 → 点击「启动服务」按钮。
|
||||
|
||||
默认端口:`5031`
|
||||
|
||||
## 基础地址
|
||||
|
||||
```
|
||||
http://127.0.0.1:5031
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 接口列表
|
||||
|
||||
### 1. 健康检查
|
||||
|
||||
检查 API 服务是否正常运行。
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /health
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"status": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 获取消息列表
|
||||
|
||||
获取指定会话的消息,支持 ChatLab 格式输出。
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/v1/messages
|
||||
```
|
||||
|
||||
**参数**
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| `talker` | string | ✅ | 会话 ID(wxid 或群 ID) |
|
||||
| `limit` | number | ❌ | 返回数量限制,默认 100 |
|
||||
| `offset` | number | ❌ | 偏移量,用于分页,默认 0 |
|
||||
| `start` | string | ❌ | 开始时间,格式 YYYYMMDD |
|
||||
| `end` | string | ❌ | 结束时间,格式 YYYYMMDD |
|
||||
| `chatlab` | string | ❌ | 设为 `1` 则输出 ChatLab 格式 |
|
||||
| `format` | string | ❌ | 输出格式:`json`(默认)或 `chatlab` |
|
||||
|
||||
**示例请求**
|
||||
|
||||
```bash
|
||||
# 获取消息(原始格式)
|
||||
GET http://127.0.0.1:5031/api/v1/messages?talker=wxid_xxx&limit=50
|
||||
|
||||
# 获取消息(ChatLab 格式)
|
||||
GET http://127.0.0.1:5031/api/v1/messages?talker=wxid_xxx&chatlab=1
|
||||
|
||||
# 带时间范围查询
|
||||
GET http://127.0.0.1:5031/api/v1/messages?talker=wxid_xxx&start=20260101&end=20260205&limit=100
|
||||
```
|
||||
|
||||
**响应(原始格式)**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"talker": "wxid_xxx",
|
||||
"count": 50,
|
||||
"hasMore": true,
|
||||
"messages": [
|
||||
{
|
||||
"localId": 123,
|
||||
"talker": "wxid_xxx",
|
||||
"type": 1,
|
||||
"content": "消息内容",
|
||||
"createTime": 1738713600000,
|
||||
"isSelf": false,
|
||||
"sender": "wxid_sender"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**响应(ChatLab 格式)**
|
||||
```json
|
||||
{
|
||||
"chatlab": {
|
||||
"version": "0.0.2",
|
||||
"exportedAt": 1738713600000,
|
||||
"generator": "WeFlow",
|
||||
"description": "Exported from WeFlow"
|
||||
},
|
||||
"meta": {
|
||||
"name": "会话名称",
|
||||
"platform": "wechat",
|
||||
"type": "private",
|
||||
"ownerId": "wxid_me"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
"platformId": "wxid_xxx",
|
||||
"accountName": "用户名",
|
||||
"groupNickname": "群昵称"
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"sender": "wxid_xxx",
|
||||
"accountName": "用户名",
|
||||
"timestamp": 1738713600000,
|
||||
"type": 0,
|
||||
"content": "消息内容"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 获取会话列表
|
||||
|
||||
获取所有会话列表。
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/v1/sessions
|
||||
```
|
||||
|
||||
**参数**
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| `keyword` | string | ❌ | 搜索关键词,匹配会话名或 ID |
|
||||
| `limit` | number | ❌ | 返回数量限制,默认 100 |
|
||||
|
||||
**示例请求**
|
||||
```bash
|
||||
GET http://127.0.0.1:5031/api/v1/sessions
|
||||
|
||||
GET http://127.0.0.1:5031/api/v1/sessions?keyword=工作群&limit=20
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"count": 50,
|
||||
"total": 100,
|
||||
"sessions": [
|
||||
{
|
||||
"username": "wxid_xxx",
|
||||
"displayName": "用户名",
|
||||
"lastMessage": "最后一条消息",
|
||||
"lastTime": 1738713600000,
|
||||
"unreadCount": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 获取联系人列表
|
||||
|
||||
获取所有联系人信息。
|
||||
|
||||
**请求**
|
||||
```
|
||||
GET /api/v1/contacts
|
||||
```
|
||||
|
||||
**参数**
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| `keyword` | string | ❌ | 搜索关键词 |
|
||||
| `limit` | number | ❌ | 返回数量限制,默认 100 |
|
||||
|
||||
**示例请求**
|
||||
```bash
|
||||
GET http://127.0.0.1:5031/api/v1/contacts
|
||||
|
||||
GET http://127.0.0.1:5031/api/v1/contacts?keyword=张三
|
||||
```
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"count": 50,
|
||||
"contacts": [
|
||||
{
|
||||
"userName": "wxid_xxx",
|
||||
"alias": "微信号",
|
||||
"nickName": "昵称",
|
||||
"remark": "备注名"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ChatLab 格式说明
|
||||
|
||||
ChatLab 是一种标准化的聊天记录交换格式,版本 0.0.2。
|
||||
|
||||
### 消息类型映射
|
||||
|
||||
| ChatLab Type | 值 | 说明 |
|
||||
|--------------|-----|------|
|
||||
| TEXT | 0 | 文本消息 |
|
||||
| IMAGE | 1 | 图片 |
|
||||
| VOICE | 2 | 语音 |
|
||||
| VIDEO | 3 | 视频 |
|
||||
| FILE | 4 | 文件 |
|
||||
| EMOJI | 5 | 表情 |
|
||||
| LINK | 7 | 链接 |
|
||||
| LOCATION | 8 | 位置 |
|
||||
| RED_PACKET | 20 | 红包 |
|
||||
| TRANSFER | 21 | 转账 |
|
||||
| CALL | 23 | 通话 |
|
||||
| SYSTEM | 80 | 系统消息 |
|
||||
| RECALL | 81 | 撤回消息 |
|
||||
| OTHER | 99 | 其他 |
|
||||
|
||||
---
|
||||
|
||||
## 使用示例
|
||||
|
||||
### PowerShell
|
||||
|
||||
```powershell
|
||||
# 健康检查
|
||||
Invoke-RestMethod http://127.0.0.1:5031/health
|
||||
|
||||
# 获取会话列表
|
||||
Invoke-RestMethod http://127.0.0.1:5031/api/v1/sessions
|
||||
|
||||
# 获取消息
|
||||
Invoke-RestMethod "http://127.0.0.1:5031/api/v1/messages?talker=wxid_xxx&limit=10"
|
||||
|
||||
# 获取 ChatLab 格式
|
||||
Invoke-RestMethod "http://127.0.0.1:5031/api/v1/messages?talker=wxid_xxx&chatlab=1" | ConvertTo-Json -Depth 10
|
||||
```
|
||||
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
# 健康检查
|
||||
curl http://127.0.0.1:5031/health
|
||||
|
||||
# 获取会话列表
|
||||
curl http://127.0.0.1:5031/api/v1/sessions
|
||||
|
||||
# 获取消息(ChatLab 格式)
|
||||
curl "http://127.0.0.1:5031/api/v1/messages?talker=wxid_xxx&chatlab=1"
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
BASE_URL = "http://127.0.0.1:5031"
|
||||
|
||||
# 获取会话列表
|
||||
sessions = requests.get(f"{BASE_URL}/api/v1/sessions").json()
|
||||
print(sessions)
|
||||
|
||||
# 获取消息
|
||||
messages = requests.get(f"{BASE_URL}/api/v1/messages", params={
|
||||
"talker": "wxid_xxx",
|
||||
"limit": 100,
|
||||
"chatlab": 1
|
||||
}).json()
|
||||
print(messages)
|
||||
```
|
||||
|
||||
### JavaScript / Node.js
|
||||
|
||||
```javascript
|
||||
const BASE_URL = "http://127.0.0.1:5031";
|
||||
|
||||
// 获取会话列表
|
||||
const sessions = await fetch(`${BASE_URL}/api/v1/sessions`).then(r => r.json());
|
||||
console.log(sessions);
|
||||
|
||||
// 获取消息(ChatLab 格式)
|
||||
const messages = await fetch(`${BASE_URL}/api/v1/messages?talker=wxid_xxx&chatlab=1`)
|
||||
.then(r => r.json());
|
||||
console.log(messages);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. API 仅监听本地地址 `127.0.0.1`,不对外网开放
|
||||
2. 需要先连接数据库才能查询数据
|
||||
3. 时间参数格式为 `YYYYMMDD`(如 20260205)
|
||||
4. 支持 CORS,可从浏览器前端直接调用
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "weflow",
|
||||
"version": "1.5.2",
|
||||
"version": "1.5.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "weflow",
|
||||
"version": "1.5.2",
|
||||
"version": "1.5.3",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^12.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "weflow",
|
||||
"version": "1.5.2",
|
||||
"version": "1.5.3",
|
||||
"description": "WeFlow",
|
||||
"main": "dist-electron/main.js",
|
||||
"author": "cc",
|
||||
|
||||
@@ -1191,6 +1191,109 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 通用弹窗覆盖层
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
// API 警告弹窗
|
||||
.api-warning-modal {
|
||||
width: 420px;
|
||||
background: var(--bg-primary);
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2);
|
||||
animation: slideUp 0.25s ease;
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 20px 24px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
|
||||
svg {
|
||||
color: var(--warning, #f59e0b);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px 24px;
|
||||
|
||||
.warning-text {
|
||||
margin: 0 0 16px;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.warning-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
.warning-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.5;
|
||||
|
||||
.bullet {
|
||||
color: var(--warning, #f59e0b);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
padding: 16px 24px;
|
||||
border-top: 1px solid var(--border-color);
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 协议弹窗
|
||||
.agreement-overlay {
|
||||
@@ -1857,6 +1960,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
// API 地址显示样式
|
||||
.api-url-display {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 8px;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
font-family: 'SF Mono', 'Consolas', monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// API 服务设置样式
|
||||
.status-badge {
|
||||
display: inline-flex;
|
||||
|
||||
@@ -143,6 +143,7 @@ function SettingsPage() {
|
||||
const [httpApiPort, setHttpApiPort] = useState(5031)
|
||||
const [httpApiRunning, setHttpApiRunning] = useState(false)
|
||||
const [isTogglingApi, setIsTogglingApi] = useState(false)
|
||||
const [showApiWarning, setShowApiWarning] = useState(false)
|
||||
|
||||
const isClearingCache = isClearingAnalyticsCache || isClearingImageCache || isClearingAllCache
|
||||
|
||||
@@ -1861,21 +1862,37 @@ function SettingsPage() {
|
||||
// HTTP API 服务控制
|
||||
const handleToggleApi = async () => {
|
||||
if (isTogglingApi) return
|
||||
|
||||
// 启动时显示警告弹窗
|
||||
if (!httpApiRunning) {
|
||||
setShowApiWarning(true)
|
||||
return
|
||||
}
|
||||
|
||||
setIsTogglingApi(true)
|
||||
try {
|
||||
if (httpApiRunning) {
|
||||
await window.electronAPI.http.stop()
|
||||
setHttpApiRunning(false)
|
||||
showMessage('API 服务已停止', true)
|
||||
await window.electronAPI.http.stop()
|
||||
setHttpApiRunning(false)
|
||||
showMessage('API 服务已停止', true)
|
||||
} catch (e: any) {
|
||||
showMessage(`操作失败: ${e}`, false)
|
||||
} finally {
|
||||
setIsTogglingApi(false)
|
||||
}
|
||||
}
|
||||
|
||||
// 确认启动 API 服务
|
||||
const confirmStartApi = async () => {
|
||||
setShowApiWarning(false)
|
||||
setIsTogglingApi(true)
|
||||
try {
|
||||
const result = await window.electronAPI.http.start(httpApiPort)
|
||||
if (result.success) {
|
||||
setHttpApiRunning(true)
|
||||
if (result.port) setHttpApiPort(result.port)
|
||||
showMessage(`API 服务已启动,端口 ${result.port}`, true)
|
||||
} else {
|
||||
const result = await window.electronAPI.http.start(httpApiPort)
|
||||
if (result.success) {
|
||||
setHttpApiRunning(true)
|
||||
if (result.port) setHttpApiPort(result.port)
|
||||
showMessage(`API 服务已启动,端口 ${result.port}`, true)
|
||||
} else {
|
||||
showMessage(`启动失败: ${result.error}`, false)
|
||||
}
|
||||
showMessage(`启动失败: ${result.error}`, false)
|
||||
}
|
||||
} catch (e: any) {
|
||||
showMessage(`操作失败: ${e}`, false)
|
||||
@@ -1893,113 +1910,93 @@ function SettingsPage() {
|
||||
const renderApiTab = () => (
|
||||
<div className="tab-content">
|
||||
<div className="form-group">
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div>
|
||||
<label>HTTP API 服务</label>
|
||||
<span className="form-hint">启用后可通过 HTTP 接口查询消息数据</span>
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<span className={`status-badge ${httpApiRunning ? 'running' : 'stopped'}`}>
|
||||
{httpApiRunning ? '运行中' : '已停止'}
|
||||
</span>
|
||||
<button
|
||||
className={`btn ${httpApiRunning ? 'btn-danger' : 'btn-primary'}`}
|
||||
onClick={handleToggleApi}
|
||||
<label>HTTP API 服务</label>
|
||||
<span className="form-hint">启用后可通过 HTTP 接口查询消息数据(仅限本机访问)</span>
|
||||
<div className="log-toggle-line">
|
||||
<span className="log-status">
|
||||
{httpApiRunning ? '运行中' : '已停止'}
|
||||
</span>
|
||||
<label className="switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={httpApiRunning}
|
||||
onChange={handleToggleApi}
|
||||
disabled={isTogglingApi}
|
||||
>
|
||||
{isTogglingApi ? '处理中...' : (httpApiRunning ? '停止服务' : '启动服务')}
|
||||
</button>
|
||||
</div>
|
||||
/>
|
||||
<span className="switch-slider" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="divider" />
|
||||
|
||||
<div className="form-group">
|
||||
<label>服务端口</label>
|
||||
<span className="form-hint">API 服务监听的端口号</span>
|
||||
<div style={{ display: 'flex', gap: 10, marginTop: 10 }}>
|
||||
<input
|
||||
type="number"
|
||||
className="field-input"
|
||||
value={httpApiPort}
|
||||
onChange={(e) => setHttpApiPort(parseInt(e.target.value, 10) || 5031)}
|
||||
disabled={httpApiRunning}
|
||||
style={{ width: 120 }}
|
||||
min={1024}
|
||||
max={65535}
|
||||
/>
|
||||
<span className="form-hint" style={{ alignSelf: 'center' }}>
|
||||
{httpApiRunning ? '停止服务后可修改端口' : '建议使用 1024-65535 之间的端口'}
|
||||
</span>
|
||||
</div>
|
||||
<span className="form-hint">API 服务监听的端口号(1024-65535)</span>
|
||||
<input
|
||||
type="number"
|
||||
className="field-input"
|
||||
value={httpApiPort}
|
||||
onChange={(e) => setHttpApiPort(parseInt(e.target.value, 10) || 5031)}
|
||||
disabled={httpApiRunning}
|
||||
style={{ width: 120 }}
|
||||
min={1024}
|
||||
max={65535}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="divider" />
|
||||
|
||||
<div className="form-group">
|
||||
<label>API 地址</label>
|
||||
<span className="form-hint">使用以下地址访问 API</span>
|
||||
<div style={{ display: 'flex', gap: 10, marginTop: 10, alignItems: 'center' }}>
|
||||
<code className="api-url">http://127.0.0.1:{httpApiPort}</code>
|
||||
<button className="btn btn-secondary btn-sm" onClick={handleCopyApiUrl}>
|
||||
<Copy size={14} /> 复制
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="divider" />
|
||||
|
||||
<div className="form-group">
|
||||
<label>接口文档</label>
|
||||
<span className="form-hint">支持的 API 接口列表</span>
|
||||
<div className="api-docs" style={{ marginTop: 12 }}>
|
||||
<div className="api-item">
|
||||
<div className="api-endpoint">
|
||||
<span className="method get">GET</span>
|
||||
<code>/api/v1/messages</code>
|
||||
</div>
|
||||
<p className="api-desc">获取消息列表,支持 ChatLab 格式输出</p>
|
||||
<div className="api-params">
|
||||
<span className="param"><code>talker</code> - 会话ID(必填)</span>
|
||||
<span className="param"><code>limit</code> - 数量限制</span>
|
||||
<span className="param"><code>start</code> - 开始时间 (YYYYMMDD)</span>
|
||||
<span className="param"><code>end</code> - 结束时间 (YYYYMMDD)</span>
|
||||
<span className="param"><code>chatlab=1</code> - 输出 ChatLab 格式</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="api-item">
|
||||
<div className="api-endpoint">
|
||||
<span className="method get">GET</span>
|
||||
<code>/api/v1/sessions</code>
|
||||
</div>
|
||||
<p className="api-desc">获取会话列表</p>
|
||||
</div>
|
||||
<div className="api-item">
|
||||
<div className="api-endpoint">
|
||||
<span className="method get">GET</span>
|
||||
<code>/api/v1/contacts</code>
|
||||
</div>
|
||||
<p className="api-desc">获取联系人列表</p>
|
||||
</div>
|
||||
<div className="api-item">
|
||||
<div className="api-endpoint">
|
||||
<span className="method get">GET</span>
|
||||
<code>/health</code>
|
||||
</div>
|
||||
<p className="api-desc">健康检查</p>
|
||||
{httpApiRunning && (
|
||||
<div className="form-group">
|
||||
<label>API 地址</label>
|
||||
<span className="form-hint">使用以下地址访问 API</span>
|
||||
<div className="api-url-display">
|
||||
<input
|
||||
type="text"
|
||||
className="field-input"
|
||||
value={`http://127.0.0.1:${httpApiPort}`}
|
||||
readOnly
|
||||
/>
|
||||
<button className="btn btn-secondary" onClick={handleCopyApiUrl} title="复制">
|
||||
<Copy size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="divider" />
|
||||
|
||||
<div className="form-group">
|
||||
<label>示例请求</label>
|
||||
<div className="code-block" style={{ marginTop: 10 }}>
|
||||
<code>GET http://127.0.0.1:{httpApiPort}/api/v1/messages?talker=wxid_xxx&limit=100&chatlab=1</code>
|
||||
{/* API 安全警告弹窗 */}
|
||||
{showApiWarning && (
|
||||
<div className="modal-overlay" onClick={() => setShowApiWarning(false)}>
|
||||
<div className="api-warning-modal" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="modal-header">
|
||||
<ShieldCheck size={20} />
|
||||
<h3>安全提示</h3>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<p className="warning-text">启用 HTTP API 服务后,本机上的其他程序可通过接口访问您的聊天记录数据。</p>
|
||||
<div className="warning-list">
|
||||
<div className="warning-item">
|
||||
<span className="bullet">•</span>
|
||||
<span>请确保您了解此功能的用途</span>
|
||||
</div>
|
||||
<div className="warning-item">
|
||||
<span className="bullet">•</span>
|
||||
<span>不要在公共或不信任的网络环境下使用</span>
|
||||
</div>
|
||||
<div className="warning-item">
|
||||
<span className="bullet">•</span>
|
||||
<span>此功能仅供高级用户或开发者使用</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-secondary" onClick={() => setShowApiWarning(false)}>
|
||||
取消
|
||||
</button>
|
||||
<button className="btn btn-primary" onClick={confirmStartApi}>
|
||||
确认启动
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user