Add OpenClaw skills, platform kit, and template docs
Made-with: Cursor
This commit is contained in:
171
content-manager/content_manager/services/image_service.py
Normal file
171
content-manager/content_manager/services/image_service.py
Normal file
@@ -0,0 +1,171 @@
|
||||
"""图片:业务规则(文件落盘 + 路径写入 images 表)。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from content_manager.config import get_skill_data_dir, resolve_stored_path
|
||||
from content_manager.db import images_repository as ir
|
||||
from content_manager.db.connection import get_conn, init_db
|
||||
from content_manager.services import file_store
|
||||
from content_manager.util.timeutil import now_unix, unix_to_iso
|
||||
|
||||
|
||||
def _row_to_public_dict(row: tuple) -> Dict[str, Any]:
|
||||
rid, file_path, title, status, source, account_id, error_msg, extra_json, cat, uat = row
|
||||
abs_path = resolve_stored_path(str(file_path))
|
||||
d: Dict[str, Any] = {
|
||||
"id": int(rid),
|
||||
"kind": "image",
|
||||
"file_path": file_path,
|
||||
"absolute_path": abs_path,
|
||||
"title": title,
|
||||
"status": status or "draft",
|
||||
"source": source or "manual",
|
||||
"account_id": account_id,
|
||||
"error_msg": error_msg,
|
||||
"created_at": unix_to_iso(cat),
|
||||
"updated_at": unix_to_iso(uat),
|
||||
}
|
||||
if extra_json:
|
||||
try:
|
||||
ex = json.loads(extra_json)
|
||||
if isinstance(ex, dict):
|
||||
d["extra"] = ex
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
return d
|
||||
|
||||
|
||||
def cmd_add(src_file: str, title: Optional[str] = None, source: str = "manual") -> None:
|
||||
init_db()
|
||||
src_file = os.path.abspath(src_file.strip())
|
||||
if not os.path.isfile(src_file):
|
||||
print(f"❌ 找不到文件:{src_file}")
|
||||
sys.exit(1)
|
||||
skill_data = get_skill_data_dir()
|
||||
ts = now_unix()
|
||||
conn = get_conn()
|
||||
try:
|
||||
new_id = ir.insert_row(
|
||||
conn,
|
||||
file_path="",
|
||||
title=(title or "").strip() or None,
|
||||
status="draft",
|
||||
source=source,
|
||||
account_id=None,
|
||||
error_msg=None,
|
||||
extra_json=None,
|
||||
created_at=ts,
|
||||
updated_at=ts,
|
||||
)
|
||||
rel, _abs = file_store.copy_into_skill_data(skill_data, "images", new_id, src_file)
|
||||
ir.update_file_path(conn, new_id, rel, now_unix())
|
||||
conn.commit()
|
||||
except Exception:
|
||||
conn.rollback()
|
||||
raise
|
||||
finally:
|
||||
conn.close()
|
||||
print(f"✅ 已新增图片 id={new_id} | 路径:{rel}")
|
||||
|
||||
|
||||
def cmd_get(image_id: str) -> None:
|
||||
init_db()
|
||||
if not str(image_id).strip().isdigit():
|
||||
print("❌ 图片 id 必须是纯数字。请先 image list 查看。")
|
||||
sys.exit(1)
|
||||
iid = int(image_id)
|
||||
conn = get_conn()
|
||||
try:
|
||||
row = ir.fetch_by_id(conn, iid)
|
||||
finally:
|
||||
conn.close()
|
||||
if not row:
|
||||
print("❌ 没有这条图片记录。")
|
||||
sys.exit(1)
|
||||
print(json.dumps(_row_to_public_dict(row), ensure_ascii=False))
|
||||
|
||||
|
||||
def cmd_list(limit: int = 20, max_chars: int = 80) -> None:
|
||||
init_db()
|
||||
conn = get_conn()
|
||||
try:
|
||||
rows = ir.list_recent(conn, limit)
|
||||
finally:
|
||||
conn.close()
|
||||
if not rows:
|
||||
print("暂无图片")
|
||||
return
|
||||
|
||||
def trunc(s: str) -> str:
|
||||
if not s:
|
||||
return ""
|
||||
return s if len(s) <= max_chars else s[:max_chars] + "..."
|
||||
|
||||
sep = "_" * 39
|
||||
for idx, r in enumerate(rows):
|
||||
rid, file_path, title, status, source, account_id, error_msg, extra_json, cat, uat = r
|
||||
print(f"id:{rid}")
|
||||
print(f"file_path:{trunc(str(file_path or ''))}")
|
||||
print(f"title:{title or ''}")
|
||||
print(f"status:{status or ''}")
|
||||
print(f"source:{source or ''}")
|
||||
print(f"account_id:{account_id or ''}")
|
||||
print(f"error_msg:{error_msg or ''}")
|
||||
print(f"created_at:{unix_to_iso(cat) or ''}")
|
||||
print(f"updated_at:{unix_to_iso(uat) or ''}")
|
||||
if idx != len(rows) - 1:
|
||||
print(sep)
|
||||
print()
|
||||
|
||||
|
||||
def cmd_delete(image_id: str) -> None:
|
||||
init_db()
|
||||
if not str(image_id).strip().isdigit():
|
||||
print("❌ 图片 id 必须是纯数字。")
|
||||
sys.exit(1)
|
||||
iid = int(image_id)
|
||||
skill_data = get_skill_data_dir()
|
||||
conn = get_conn()
|
||||
try:
|
||||
row = ir.fetch_by_id(conn, iid)
|
||||
if not row:
|
||||
print("❌ 没有 id 为 {} 的图片记录。".format(iid))
|
||||
sys.exit(1)
|
||||
rel = row[1]
|
||||
n = ir.delete_by_id(conn, iid)
|
||||
if n == 0:
|
||||
sys.exit(1)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
file_store.remove_files_for_relative_path(skill_data, str(rel))
|
||||
print(f"✅ 已删除图片 id={iid}")
|
||||
|
||||
|
||||
def cmd_feedback(
|
||||
image_id: str,
|
||||
status: str,
|
||||
account_id: Optional[str] = None,
|
||||
error_msg: Optional[str] = None,
|
||||
) -> None:
|
||||
init_db()
|
||||
if not str(image_id).strip().isdigit():
|
||||
print("❌ 图片 id 必须是纯数字。")
|
||||
sys.exit(1)
|
||||
iid = int(image_id)
|
||||
ts = now_unix()
|
||||
conn = get_conn()
|
||||
try:
|
||||
if ir.fetch_by_id(conn, iid) is None:
|
||||
print("❌ 没有 id 为 {} 的图片记录。".format(iid))
|
||||
sys.exit(1)
|
||||
ir.update_feedback(conn, iid, status, account_id, error_msg, ts)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
print("✅ 状态已更新")
|
||||
Reference in New Issue
Block a user