Skip to content

hzb666/AssetManager

Repository files navigation

AssetManager

通用资产全生命周期管理系统框架。通过 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          # 前端实体配置类型

快速开始

1. 克隆并安装依赖

git clone <repo-url>
cd AssetManager

# 后端
pip install poetry && poetry install

# 前端
cd frontend && npm install

2. 配置环境变量

cp .env.example .env
# 编辑 .env,填入 SECRET_KEY 和 DEFAULT_ADMIN_PASSWORD

3. 启动

# 后端
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 个阶段:requestpurchasingstock_inin_storageborrowedmaintenanceconsumedscrappedrejected。每个阶段可定义 label 和可选的颜色值。

预设机制

config/presets/ 目录下的 YAML 文件为预设。预设通过 deep merge 覆盖默认配置。参考 presets/equipment.yaml

全文搜索

系统内置三层搜索:

  1. 精确匹配 — 按编号、拼音全拼、拼音首字母精确匹配
  2. FTS5 Trigram — 3 个字符以上触发 FTS5 trigram 索引,支持中文和 ASCII 混合
  3. 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 实时推送

后端 SSE Manager 管理连接池,支持 Redis fan-out 集群部署。三个公开房间:assetsrequestsdashboard

前端 useListSSE hook 订阅指定房间事件,事件到达后自动调用 queryClient.invalidateQueries 刷新列表,无需手动刷新页面。

API 概览

资产

方法 路径 说明
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 build

启动后端

poetry run gunicorn app.main:app \
    --workers 4 \
    --worker-class uvicorn.workers.UvicornWorker \
    --bind 0.0.0.0:8000

Nginx 配置参考

server {
    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

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors