From 52e392f831c97dd540bf2506d0f0a1ff2b51dd2c Mon Sep 17 00:00:00 2001 From: 12451 <12451@example.com> Date: Thu, 2 Jul 2026 19:44:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E5=B7=A5=E5=85=B7tools/db.py=EF=BC=8C=E6=9B=B4?= =?UTF-8?q?=E6=96=B0AGENTS.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 26 ++++++++++- tools/db.py | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 tools/db.py diff --git a/AGENTS.md b/AGENTS.md index 014ef11..c3f6722 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,10 +32,13 @@ D:\charging-cabinet\ │ ├── nginx/ # Nginx配置 │ ├── *.service # systemd服务单元 │ └── deploy-*.sh # 部署脚本 +├── tools/ # 开发工具 +│ └── db.py # 数据库工具 ├── software/ │ ├── api-server/ # Rust API服务 │ ├── device-server/ # Rust TCP设备服务 -│ └── web/ # React前端 +│ ├── h5/ # H5用户端(移动端) +│ └── web/ # React前端(WEB管理端) ├── hardware/ # 硬件资料(原理图/PCB等) └── test/ # 测试用例/报告 ``` @@ -98,6 +101,27 @@ Redis: 10.8.0.252:6379 - systemd自启,`Restart=always` 自动恢复 - 本地直连 `10.8.0.252`,无需SSH隧道 +### 数据库工具 + +本地可直接访问数据库(通过ZeroTier),使用 `tools/db.py`: + +```bash +# 列出所有表 +python tools/db.py tables + +# 统计各表数据量 +python tools/db.py count + +# 执行查询 +python tools/db.py query "SELECT * FROM users" + +# 执行写入 +python tools/db.py exec "UPDATE users SET status=1 WHERE id=1" + +# 导入SQL文件 +python tools/db.py import data.sql +``` + ### 证书 - 阿里云免费SSL证书(acme.sh自动续期) diff --git a/tools/db.py b/tools/db.py new file mode 100644 index 0000000..6f049ec --- /dev/null +++ b/tools/db.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +""" +PMS 数据库工具 +用法: + python tools/db.py import # 导入SQL文件 + python tools/db.py query # 执行查询 + python tools/db.py exec # 执行写入 + python tools/db.py tables # 列出所有表 + python tools/db.py count # 统计各表数据量 +""" + +import sys +import pymysql + +# 数据库配置 +DB_CONFIG = { + 'host': '10.8.0.252', + 'user': 'root', + 'password': 'Hbhyg731024@', + 'database': 'pms', + 'charset': 'utf8mb4', +} + +def get_conn(): + return pymysql.connect(**DB_CONFIG) + +def import_sql(filepath): + """导入SQL文件""" + with open(filepath, 'r', encoding='utf-8') as f: + sql = f.read() + + conn = get_conn() + cur = conn.cursor() + + # 按分号分割SQL语句 + statements = [s.strip() for s in sql.split(';') if s.strip()] + + success = 0 + fail = 0 + for stmt in statements: + try: + cur.execute(stmt) + success += 1 + except Exception as e: + print(f" ✗ 失败: {str(e)[:80]}") + fail += 1 + + conn.commit() + conn.close() + print(f"导入完成: 成功 {success}, 失败 {fail}") + +def query(sql): + """执行查询""" + conn = get_conn() + cur = conn.cursor() + cur.execute(sql) + columns = [desc[0] for desc in cur.description] + rows = cur.fetchall() + conn.close() + + if not rows: + print("无数据") + return + + # 打印表头 + print('\t'.join(columns)) + print('-' * 50) + for row in rows: + print('\t'.join(str(v) for v in row)) + +def execute(sql): + """执行写入""" + conn = get_conn() + cur = conn.cursor() + try: + cur.execute(sql) + conn.commit() + print(f"执行成功, 影响行数: {cur.rowcount}") + except Exception as e: + print(f"执行失败: {e}") + conn.rollback() + finally: + conn.close() + +def tables(): + """列出所有表""" + query("SHOW TABLES") + +def count(): + """统计各表数据量""" + conn = get_conn() + cur = conn.cursor() + cur.execute("SHOW TABLES") + tables = [row[0] for row in cur.fetchall()] + + print("表名\t\t数据量") + print("-" * 30) + for t in tables: + cur.execute(f"SELECT COUNT(*) FROM `{t}`") + cnt = cur.fetchone()[0] + print(f"{t}\t{cnt}") + conn.close() + +def main(): + if len(sys.argv) < 2: + print(__doc__) + return + + cmd = sys.argv[1] + + if cmd == 'import' and len(sys.argv) >= 3: + import_sql(sys.argv[2]) + elif cmd == 'query' and len(sys.argv) >= 3: + query(' '.join(sys.argv[2:])) + elif cmd == 'exec' and len(sys.argv) >= 3: + execute(' '.join(sys.argv[2:])) + elif cmd == 'tables': + tables() + elif cmd == 'count': + count() + else: + print(__doc__) + +if __name__ == '__main__': + main()