168 lines
7.2 KiB
Markdown
168 lines
7.2 KiB
Markdown
---
|
||
name: "tab"
|
||
description: "管理 tab 项目数据库(本地 MySQL tab 库)。新增/去重 engine 引擎、website 站点、website_type 站点类型数据,以及启用/禁用(status 切换)。"
|
||
---
|
||
|
||
# Tab — 项目数据库管理
|
||
|
||
管理本地 MySQL `tab` 数据库中的三张表:`engine`(引擎)、`website`(站点)、`website_type`(站点类型)。初版职责:**新增(含去重)+ 启用/禁用**。查询/修改/删除后续扩展。
|
||
|
||
## 数据库连接
|
||
|
||
连接库名「**tab**」:
|
||
|
||
```bash
|
||
python3 /home/yangxuan/.openclaw/workspace/skills/db-query/scripts/db_query.py --database "tab" --query "<SQL>"
|
||
```
|
||
|
||
- 本地 Docker MySQL(127.0.0.1:3306),user=root,密码已配置
|
||
- 凭据不直连,统一走 db-query 脚本
|
||
- 注意:`order` 是保留字,涉及时必须用反引号 `` `order` ``
|
||
|
||
## 表结构(三张)
|
||
|
||
### engine — 引擎
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | varchar(32) PK | 唯一 id,UUID() |
|
||
| status | tinyint | 0有效 1无效(禁用改此字段) |
|
||
| title | varchar(500) NOT NULL | 标题(必填) |
|
||
| description | varchar(200) | 描述(必填) |
|
||
| icon | varchar(500) NOT NULL | 图标(自动取 favicon) |
|
||
| url | varchar(500) NOT NULL | 链接(必填) |
|
||
| click | int default 0 | 点击 |
|
||
| deleted | bit default 0 | 是否删除 |
|
||
| create_time / update_time | datetime | 审计,NOW() 自动 |
|
||
| creator / updater | varchar(64) | 审计,自动填 |
|
||
| tenant_id | bigint default 0 | 自动填 0 |
|
||
|
||
### website — 站点
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | varchar(32) PK | UUID() |
|
||
| status | tinyint | 0有效 1无效(禁用改此) |
|
||
| type_id | int | 站点类型 id(**必填**,关联 website_type.id) |
|
||
| title | varchar(500) NOT NULL | 标题(必填) |
|
||
| description | varchar(200) | 描述(必填) |
|
||
| `` `order` `` | int default 0 | 排序(反引号!) |
|
||
| icon | varchar(500) NOT NULL | 图标(自动取 favicon) |
|
||
| url | varchar(500) NOT NULL | 链接(必填) |
|
||
| click | int default 0 | 点击 |
|
||
| deleted | bit default 0 | 是否删除 |
|
||
| create_time / update_time | datetime(6) | 审计,NOW(6) 自动 |
|
||
| creator / updater | varchar(64) | 审计,自动填 |
|
||
| tenant_id | bigint default 0 | 自动填 0 |
|
||
|
||
### website_type — 站点类型
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | int auto_increment PK | 自增 |
|
||
| status | tinyint | 0有效 1无效(禁用改此) |
|
||
| title | varchar(200) NOT NULL | 类型名(必填,**去重依据**) |
|
||
| icon | varchar(200) NOT NULL | 图标 |
|
||
| description | varchar(200) | 描述(必填) |
|
||
| `` `order` `` | int default 0 | 排序(反引号!) |
|
||
| deleted | bit default 0 | 是否删除 |
|
||
| create_time / update_time | datetime(6) | 审计,NOW(6) 自动 |
|
||
| creator / updater | varchar(64) | 审计,自动填 |
|
||
| tenant_id | bigint default 0 | 自动填 0 |
|
||
|
||
## 通用规范
|
||
|
||
- **审计字段自动生成**:id(UUID() 32位无横线)、create_time/update_time(NOW()/NOW(6))、creator/updater(填 `system`)、tenant_id(`0`)、click(默认 0)、deleted(默认 0)。用户无需提供。
|
||
- **必填(用户提供)**:title、url、description(三表 title 必填;engine/website 的 url+description 必填;website_type 的 title+description 必填)。
|
||
- `type_id`(website 表):**必填**,且必须是 website_type 表中**已存在且有效(status=0,deleted=0)**的 id。新增站点前须先校验。
|
||
- **全程中文交互**。
|
||
- 所有写入通过 db-query 脚本执行。
|
||
|
||
## favicon 获取(icon 自动)
|
||
|
||
新增 engine/website 时,`icon` 字段由 agent 根据用户提供的 `url` **自动获取 favicon**:
|
||
|
||
1. **先尝试直接访问**:`https://<域名>/favicon.ico`
|
||
- 域名 = URL 的主机部分(去协议、去路径,如 `https://www.doubao.com/chat` → `www.doubao.com`)
|
||
2. **失败则用 icon.horse**:`https://icon.horse/icon/<域名>`
|
||
- 直接访问返回非图片(content-type 非 image/*)或超时/失败时用此兜底
|
||
|
||
实现示例(python 判优先级):
|
||
```python
|
||
import urllib.request, re
|
||
from urllib.parse import urlparse
|
||
|
||
def get_favicon(url):
|
||
host = urlparse(url).netloc # 如 www.doubao.com
|
||
candidates = [
|
||
f"https://{host}/favicon.ico",
|
||
f"https://icon.horse/icon/{host}",
|
||
]
|
||
for c in candidates:
|
||
try:
|
||
req = urllib.request.Request(c, method="HEAD", headers={"User-Agent":"Mozilla/5.0"})
|
||
with urllib.request.urlopen(req, timeout=8) as r:
|
||
ct = r.headers.get("Content-Type","")
|
||
if "image" in ct or c.endswith(".ico"):
|
||
return c
|
||
except Exception:
|
||
continue
|
||
return candidates[-1] # 兜底 icon.horse
|
||
```
|
||
> 若网络受限无法访问,直接返回 `https://icon.horse/icon/<域名>` 并告知用户。
|
||
> 用户已显式提供 icon 时,优先用用户提供的值。
|
||
|
||
## 操作规范
|
||
|
||
### 1. 新增引擎(engine)
|
||
去重:先查 `SELECT id,url FROM engine WHERE deleted=0 AND url='<url>'`,**已存在则告知用户并停止**,不重复插入。
|
||
|
||
```sql
|
||
INSERT INTO engine
|
||
(id, status, title, description, icon, url, click, deleted, create_time, update_time, creator, updater, tenant_id)
|
||
VALUES
|
||
(UUID(), 0, '<title>', '<desc>', '<icon>', '<url>', 0, b'0', NOW(), NOW(), 'system', 'system', 0);
|
||
```
|
||
|
||
### 2. 新增站点(website)
|
||
- 先去重:`SELECT id,url FROM website WHERE deleted=0 AND url='<url>'`,存在则停止。
|
||
- 先校验 type_id:`SELECT id FROM website_type WHERE id=<type_id> AND status=0 AND deleted=0`,不存在则报错,让用户提供有效类型。
|
||
|
||
```sql
|
||
INSERT INTO website
|
||
(id, status, type_id, title, click, description, `order`, icon, url,
|
||
create_time, update_time, creator, updater, deleted, tenant_id)
|
||
VALUES
|
||
(UUID(), 0, <type_id>, '<title>', 0, '<desc>', 0, '<icon>', '<url>',
|
||
NOW(6), NOW(6), 'system', 'system', b'0', 0);
|
||
```
|
||
|
||
### 3. 新增站点类型(website_type)
|
||
去重:`SELECT id,title FROM website_type WHERE deleted=0 AND title='<title>'`,存在则停止。
|
||
|
||
```sql
|
||
INSERT INTO website_type
|
||
(id, status, title, icon, description, `order`, create_time, update_time, creator, updater, deleted, tenant_id)
|
||
VALUES
|
||
(NULL, 0, '<title>', '<icon>', '<desc>', 0, NOW(6), NOW(6), 'system', 'system', b'0', 0);
|
||
```
|
||
> id 为自增,传 NULL 即可。icon 可让用户提供,或用默认图标。
|
||
|
||
### 4. 启用 / 禁用(三表通用)
|
||
语义:只改 `status` 字段,不动 deleted。
|
||
- **禁用** = `status=1`
|
||
- **启用** = `status=0`
|
||
|
||
按唯一标识定位(engine/website 用 id,website_type 可用 id 或 title):
|
||
```sql
|
||
-- 禁用示例(engine)
|
||
UPDATE engine SET status=1, update_time=NOW(), updater='system' WHERE id='<id>';
|
||
-- 启用
|
||
UPDATE engine SET status=0, update_time=NOW(), updater='system' WHERE id='<id>';
|
||
```
|
||
> 操作前先 SELECT 确认目标存在并展示给用户确认;禁用后告知用户当前状态。
|
||
|
||
## 红线
|
||
- **去重**:任何新增前先查重,命中即停止并告知。
|
||
- **type_id 必填且有效**:站点新增必须有合法 type_id。
|
||
- **写入前先 SELECT 确认**,避免误操作。
|
||
- 任何批量/删除类操作前,向杨轩展示精确清单并确认。
|
||
- 审计字段自动生成,不依赖用户输入。
|