通用资产全生命周期管理系统框架。通过 YAML 配置定义资产字段与生命周期,支持快速适配不同业务场景。
后端: Python 3.11+ / FastAPI / SQLModel / SQLite (WAL) / Redis(可选) 前端: React 19 / TypeScript 5 / TanStack Table / Zustand / Tailwind CSS / Vite
| 模块 | 说明 |
|---|---|
| 资产管理 | 资产的完整 CRUD,支持批量导入(Excel/CSV)和导出(Excel) |
| 生命周期 | 申购 → 审批 → 入库 → 在库 → 借出 → 归还/维护 → 报废 |
| 审批流 | 普通用户提交申购,管理员审批或驳回 |
| 借还管理 | 资产在库时可借用,借出后归还;支持数量管理 |
| 全文搜索 | 基于 FTS5 + trigram 的拼音搜索,支持名称、品牌、分类、位置 |
| 实时推送 | SSE 实时推送,数据变更后无需刷新页面 |
| 多设备会话 | 支持多设备登录、会话管理和设备踢出 |
| 暗黑模式 | 完整暗色主题支持,跟随系统偏好 |
AssetManager/
├── config/
│ ├── entity.yaml # 默认实体配置
│ └── presets/ # 业务场景预设
│
├── app/
│ ├── main.py # FastAPI 入口
│ ├── database.py # SQLite WAL 配置、FTS5 虚拟表初始化
│ ├── api/
│ │ ├── assets.py # 资产 CRUD、借还、导入导出
│ │ ├── orders.py # 订单/申购审批流
│ │ ├── users.py # 用户注册、认证、会话管理
│ │ ├── announcements.py # 系统公告
│ │ ├── user_logs.py # 操作日志
│ │ ├── events.py # SSE 端点
│ │ └── deps.py # 认证依赖(含 x-auth-error-code 协议)
│ ├── models/
│ │ ├── asset.py # Asset 模型(支持拼音搜索字段)
│ │ ├── order.py # Order 模型
│ │ ├── borrow_log.py # 借还记录
│ │ └── user.py / user_session.py
│ ├── services/
│ │ ├── asset_fts.py # FTS5 搜索子查询构建
│ │ ├── pinyin_utils.py # 中文转拼音、拼音首字母
│ │ ├── sse_manager.py # SSE 连接管理、Redis fan-out
│ │ ├── sse_redis.py # Redis pub/sub 集成
│ │ ├── search_matchers.py # 三层搜索匹配器(精确/模糊/降级)
│ │ └── session_service.py # 会话缓存服务
│ ├── core/
│ │ ├── auth.py # Token 生成与验证
│ │ ├── constants.py # SSE Room/EventType 枚举
│ │ └── config.py # 环境变量配置
│ └── config/
│ └── entity_loader.py # YAML 配置加载器
│
└── frontend/src/
├── api/client.ts # Axios 拦截器(认证失效统一处理)
├── hooks/
│ ├── useTableState.tsx # 表格状态管理(搜索/筛选/分页)
│ ├── useListSSE.ts # SSE 列表订阅 + query invalidation
│ └── useSSE.ts # SSE 连接 hook
├── lib/
│ ├── authSession.ts # SSE auth.invalid 失效处理
│ ├── sseConstants.ts # 前端 SSE 常量
│ ├── sseRuntime.ts # SSE 运行时
│ └── badgeConstants.ts # 状态徽章颜色映射
├── store/
│ ├── useStore.ts # 认证状态机(含 authFlowEpoch 保护)
│ └── sseStore.ts # SSE 连接状态
├── pages/
│ ├── Dashboard.tsx # 仪表盘(待办、快捷操作)
│ ├── Assets.tsx # 资产列表(含导出按钮)
│ ├── Requests.tsx # 申购订单管理
│ ├── Import.tsx # 批量导入(服务端模板下载)
│ ├── Login.tsx # 登录页
│ ├── Layout.tsx # 响应式布局壳
│ └── ...
└── config/entity.ts # 前端实体配置类型
git clone <repo-url>
cd AssetManager
# 后端
pip install poetry && poetry install
# 前端
cd frontend && npm installcp .env.example .env
# 编辑 .env,填入 SECRET_KEY 和 DEFAULT_ADMIN_PASSWORD# 后端
poetry run uvicorn app.main:app --reload --port 8000
# 前端(新终端)
cd frontend && npm run dev访问 http://localhost:5173,使用配置的默认管理员账号登录。
config/entity.yaml 定义了资产的字段、标签和生命周期阶段。前端 frontend/src/config/entity.ts 与之保持同步。
修改 YAML 后重启后端即可生效,无需改动代码。
默认定义了 9 个阶段:request → purchasing → stock_in → in_storage → borrowed → maintenance → consumed → scrapped → rejected。每个阶段可定义 label 和可选的颜色值。
config/presets/ 目录下的 YAML 文件为预设。预设通过 deep merge 覆盖默认配置。参考 presets/equipment.yaml。
系统内置三层搜索:
- 精确匹配 — 按编号、拼音全拼、拼音首字母精确匹配
- FTS5 Trigram — 3 个字符以上触发 FTS5 trigram 索引,支持中文和 ASCII 混合
- LIKE 降级 — 短词或 FTS 不可用时使用 LIKE 降级匹配
拼音字段(名称、分类、品牌、位置)在创建/更新资产时由 pinyin_utils.compute_pinyin_fields() 自动填充。
后端采用 httpOnly Cookie 存储会话 Token。X-Auth-Error-Code 响应头携带错误类型(missing_token / invalid_token / disabled_user / session_expired 等),前端拦截器统一处理 401/403 并触发失效弹窗。
x-skip-auth-invalidation 响应头用于告知前端此次失败不应触发全局失效(用于 bootstrap 探测等场景)。
前端认证状态机包含 authFlowEpoch 机制,防止过时的 bootstrap 回调覆盖后续状态。
后端 SSE Manager 管理连接池,支持 Redis fan-out 集群部署。三个公开房间:assets、requests、dashboard。
前端 useListSSE hook 订阅指定房间事件,事件到达后自动调用 queryClient.invalidateQueries 刷新列表,无需手动刷新页面。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/assets |
分页列表(支持搜索/筛选) |
| POST | /api/assets |
创建资产 |
| GET | /api/assets/{id} |
资产详情 |
| PUT | /api/assets/{id} |
更新资产 |
| DELETE | /api/assets/{id} |
删除资产(管理员) |
| POST | /api/assets/{id}/borrow |
借用(乐观锁防并发) |
| POST | /api/assets/{id}/return |
归还 |
| GET | /api/assets/{id}/borrow-history |
借用历史(含权限控制) |
| GET | /api/assets/import/template |
下载导入模板 |
| POST | /api/assets/import |
批量导入 |
| GET | /api/assets/export |
导出 Excel |
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/orders |
订单列表 |
| POST | /api/orders |
创建订单 |
| PUT | /api/orders/{id} |
更新订单(仅待审批) |
| DELETE | /api/orders/{id} |
删除订单(仅待审批) |
| POST | /api/orders/{id}/approve |
审批通过 |
| POST | /api/orders/{id}/reject |
驳回 |
| POST | /api/orders/{id}/stockin |
入库(生成资产) |
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/users/login |
登录 |
| POST | /api/users/logout |
登出 |
| GET | /api/users/me |
当前用户 |
| GET | /api/users/ |
用户列表(管理员) |
| POST | /api/users/ |
创建用户(管理员) |
| PUT | /api/users/{id} |
更新用户(管理员) |
| DELETE | /api/users/{id} |
禁用用户(管理员) |
| GET | /api/users/me/sessions |
当前会话列表 |
| DELETE | /api/users/me/sessions/{id} |
踢出指定设备 |
| DELETE | /api/users/me/sessions |
踢出所有其他设备 |
| POST | /api/users/{id}/reset-password |
重置密码(管理员) |
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/announcements/public |
公告列表 |
| GET | /api/announcements/ |
公告管理(管理员) |
| POST | /api/announcements/ |
创建公告(管理员) |
| GET | /api/user-logs/ |
操作日志 |
| GET | /api/events |
SSE 流 |
SECRET_KEY=<随机 64 字节>
DEBUG=false
ENV=production
DATABASE_URL=sqlite:///./assetmanager.db
REDIS_URL=redis://localhost:6379/0 # 可选,SSE 集群需要
cd frontend && npm run buildpoetry run gunicorn app.main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000server {
listen 80;
server_name your-domain.com;
location / {
root /path/to/frontend/dist;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}Apache License 2.0