172 lines
5.0 KiB
Python
172 lines
5.0 KiB
Python
"""图片:业务规则(文件落盘 + 路径写入 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("✅ 状态已更新")
|