assets-ai/CLAUDE.md

10 KiB
Raw Permalink Blame History

CLAUDE.md — assets.tlyq.ai 资产管理系统

项目概述

assets-ai 是基于 Next.js + SQLite 的 IT 设备资产管理系统CMDB部署在腾讯云txjp 服务器),域名 assets.tlyq.ai。管理 GPU 服务器、存储服务器等 120+ 台设备的完整硬件信息,通过 REST API 对外服务,供 issue.tlyq.ai 等系统调用。


快速参考

属性
站点域名 assets.tlyq.ai
服务器 txjpIP: 43.133.38.210
代码路径 /root/docker/assets-ai/
本地端口 6177
容器名 assets-ai
数据库 SQLitedata/assets.db
默认账号 admin / admin123

常用命令

cd /Users/niuniu/programs/docker/assets-ai
npm run dev          # 本地开发
npm run build        # 生产构建
npm run db:init      # 初始化数据库
npm run import       # 导入设备数据

关键文件

文件 职责
next.config.ts output: 'standalone'better-sqlite3 服务端打包
Dockerfile 两阶段构建alpine builder + alpine runner
docker-compose.yml 使用 external webnet挂载 .next 从宿主机
src/middleware.ts 全局路由守卫Cookie JWT / Bearer API Key 双模式)
src/lib/db.ts SQLite 连接WAL 模式,外键开启)
src/lib/db-schema.ts 表初始化 + 默认数据admin/editor/viewer
src/lib/auth.ts JWT 签名/验证、API Key 生成/校验(自实现,未用 jsonwebtoken 包)
src/lib/permissions.ts 权限检查(按角色 JSON 匹配)
src/lib/issue-client.ts 调用 issue API 获取设备历史工单
src/lib/excel.ts Excel 模板生成 + 导入解析
src/types/index.ts User / Asset / ApiKey / PaginatedResult 等类型
src/app/api/assets/ 资产 CRUD + 批量修改 + 导入/导出 + 高级查询

数据库 Schema

表概览

表名 说明
users 用户账号username/password_hash/role
roles 角色定义name/display_name/permissions JSON
sessions 会话JWT → user_id
api_keys API KeySHA-256 hash供外部系统调用
assets 设备资产主体68 列硬件字段)
audit_logs 审计日志

assets 表核心字段

设备标识serial_number(UNIQUE)、device_type(GPU服务器/存储服务器)、device_purposeroomrack_positionnode_namebusiness_iphdm_ipmanufacturerdevice_modelstatus

CPU/内存cpu_modelcpu_generationcpu_corescpu_countcpu_threadsmemory_modelmemory_frequencymemory_unit_capacitymemory_countmemory_total

GPU/网络gpu_modelgpu_powergpu_count、NIC×3nic1/2/3_model/type/speed/count

存储/电源sys_disk_*data_disk1/2_*raid_model/spec/countpsu1/2_model/power/count

预置角色

角色 权限 说明
admin ["*"] 全部权限
editor ["assets:read","assets:write","assets:delete"] 可增删改资产,不可管理用户和 Key
viewer ["assets:read"] 只读

API 路由

认证

登录逻辑v2.1LDAP 优先 + 本地密码缓存回退 + localadmin 应急用户。 登录成功签发两个 cookiesession_assets(本地 JWT24h+ tlyq_session(共享 JWT7 天domain=.tlyq.ai。 中间件优先检查 tlyq_session,回退 session_assetsgetSession() 每次验证时检查 LLDAP 用户是否存在(已删除则清除 cookie 踢出)。

方法 路径 说明
POST /api/auth/login 登录LDAP 优先 + 本地回退)
POST /api/auth/logout 登出(清除两个 cookie
GET /api/auth/me 当前用户信息
GET /api/internal/roles 内部 API返回角色列表x-internal-key 鉴权)

资产

方法 路径 说明
GET /api/assets 资产列表(分页/搜索/高级筛选/sort
POST /api/assets 创建设备
GET /api/assets/[id] 设备详情
PUT /api/assets/[id] 更新设备
DELETE /api/assets/[id] 删除设备
POST /api/assets/batch 批量修改(仅允许部分字段,见下方限制)
POST /api/assets/import Excel 模板导入(按 SN 匹配新增/更新)
GET /api/assets/export 导出 Excel
GET /api/assets/field-values 获取字段可选值(筛选下拉用)

GET /api/assets 高级查询

参数 说明
search 全文搜索SN、节点名、IP、型号、厂商
filter_<field> 精确筛选(可多次使用实现 IN 筛选)
filters JSON 数组:[{field, op, value}]op 支持 contains/equals/starts_with/ends_with/not_empty/empty
sortKey / sortOrder 排序字段

统计 / API Key / 用户

方法 路径 说明
GET /api/stats 资产概览(总数/按状态/按类型/按厂商/按机房/保修预警)
GET/POST /api/api-keys Key 列表 / 创建(仅显示一次)
DELETE /api/api-keys/[id] 删除 Key
GET/POST /api/users 用户列表/创建
GET/PUT/DELETE /api/users/[id] 单个用户操作

认证机制

  • Web UIv2.1middleware.ts 优先检查 tlyq_session(共享 JWTOA 统一签发)→ 回退 session_assets(本地 JWTgetSession() 每次请求时检查 LLDAP 用户是否存在,已删除则清除 cookie 踢出
  • localadmin:纯本地 BCrypt 认证,不依赖 LLDAP用于 LLDAP 故障时应急登录DB 预置admin 角色)
  • API Keyv2.2middleware.ts 检查 ALLOWED_API_KEYS 环境变量(逗号分隔明文 key无效 key 在中间件层直接返回 401。注意middleware 运行在 Edge Runtime不能使用 better-sqlite3DB 级别的 key 验证由 route handler 中的 auth.ts verifyApiKey() 进行(查 api_keys 表 SHA-256 hash支持 last_used_at 追踪和 permissions 控制)。外部系统调用本系统 API 时key 必须注册在 ALLOWED_API_KEYS

环境配置

本地与云端差异

环境变量 本地开发 云服务器txjp 说明
ISSUE_API_URL http://localhost:6176/api http://issue-ai:3000/api 调用 issue API 地址
ISSUE_API_KEY 本地 issue-ai 生成 云上 issue-ai 生成 每个环境独立,不可跨环境使用
NEXT_PUBLIC_ISSUE_URL http://localhost:6176/tickets https://issue.tlyq.ai 前端跳转链接(构建时内嵌)
ALLOWED_API_KEYS issue-ai 调用本系统时需要的 Key 云上 issue-ai 生成的 Key 仅 issue→assets 方向需要
JWT_SECRET dev-secret-key-local ${ASSETS_JWT_SECRET} 生产必须强密钥
DATABASE_PATH ./data/assets.db /app/data/assets.db Docker volume 挂载
Cookie 名 session_assets session_assets 本地两系统用不同名防 localhost 域冲突

.env.local 示例

DATABASE_PATH=./data/assets.db
JWT_SECRET=dev-secret-key-local
NODE_ENV=development
ISSUE_API_URL=http://localhost:6176/api
ISSUE_API_KEY=ak_<32字节十六进制>
NEXT_PUBLIC_ISSUE_URL=http://localhost:6176/tickets

与 issue.tlyq.ai 的联动

assets-ai  ──→  GET {ISSUE_API_URL}/tickets/by-asset?ip=xxx  (Authorization: Bearer {ISSUE_API_KEY})
issue-ai   ──→  GET {ASSETS_API_URL}/assets?search=IP         (Authorization: Bearer {ASSETS_API_KEY})
  • assets → issuesrc/lib/issue-client.ts):资产详情页展示历史工单,优先 ISSUE_API_KEY回退用户 Cookie
  • API Key 配置:在 issue-ai /settings/api-keys 创建 Key → 写入 assets-ai 的 ISSUE_API_KEY

详见 issue-ai CLAUDE.md


批量编辑限制

POST /api/assets/batch 仅允许修改以下字段(安全考虑):

device_type, device_purpose, room, rack_position, status,
manufacturer, device_model, warranty_date

IP、序列号、硬件配置等必须通过单台编辑接口逐一修改。


Docker 部署

txjp 服务器
├── assets-ai容器              ← Next.js standalone监听 3000
├── nginx-ai                       ← 反向代理 assets.tlyq.ai → assets-ai:3000
└── webnetexternal             ← 共享网络

部署:bash deploy-ai.sh → 选择 5。源码打包上传 → 服务器 npm install + npm run build.next 挂载进容器生效。--force 强制重建,--restart 仅重启。

生产环境变量

DATABASE_PATH=/app/data/assets.db
JWT_SECRET=<线上密钥>
NODE_ENV=production
NEXT_PUBLIC_ISSUE_URL=https://issue.tlyq.ai/tickets

NEXT_PUBLIC_ISSUE_URLdeploy-ai.sh 在构建前自动写入服务器 .env



开发规范

  • 新增 API:在 src/app/api/ 下创建路由 → 顶部调用 initDatabase()getCurrentUser() 验证
  • 新增页面:在 src/app/(app)/ 下创建 → 布局由 (app)/layout.tsx 提供
  • 日期处理(时区规范):整个系统统一使用 UTC+8北京时间。两处必须遵守
    1. JavaScript/TypeScript:禁止使用 Date.toISOString() 格式化本地日期。toISOString() 返回 UTC 时间在中国时区UTC+8new Date('2026-04-01T00:00:00').toISOString() 会返回 "2026-03-31T16:00:00.000Z",日期偏移一天。应使用本地时间方法拼接:${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}
    2. SQLite:所有 datetime('now') 必须写成 datetime('now', '+8 hours'),包括 CREATE TABLE 的 DEFAULT 值、UPDATE/SET 语句、以及查询条件中的时间比较。禁止使用不含时区偏移的 datetime('now')

Git Tag 规范

使用日期版本号 vYYYY.MM.DD(如 v2026.05.18)。提交后打 tag 再推送:

git tag v$(date +%Y.%m.%d) && git push origin main && git push origin v$(date +%Y.%m.%d)

同一天多次提交只打一个 tag。详见根目录 CLAUDE.md


故障排查

# 容器日志
ssh txjp "docker logs assets-ai"

# 数据库初始化
ssh txjp "docker exec assets-ai node -e \"require('./scripts/init-db.js')\""

# 重建镜像(不常用,.next 挂载已覆盖日常更新)
ssh txjp "cd /root/docker/assets-ai && docker compose down && docker compose build --no-cache && docker compose up -d"