docs: 同步 Docker 编排说明并补充重构计划与 UI 参考
- README 与 docker/README 更新双 compose 文件说明:docker-compose.yml 仅主应用、docker-compose.full.yml 完整栈 - 新增 docs/superpowers/plans 800 行重构实施计划,规划前后端代码体量护栏与按职责拆分路径 - 新增 docs/ui-mockups 附件关联企业版 UI 参考稿
This commit is contained in:
95
README.md
95
README.md
@@ -1,45 +1,50 @@
|
||||
# X-Financial
|
||||
|
||||
项目结构已按前后端拆开:
|
||||
|
||||
- `web/`:前端工程(当前 Vue + Vite 项目)
|
||||
- `server/`:后端工程目录
|
||||
- `docs/`:方案和阶段文档
|
||||
- `UI/`:界面参考稿
|
||||
- `document/`:业务文档
|
||||
|
||||
根目录统一环境变量:
|
||||
|
||||
- `.env`
|
||||
- `.env.example`
|
||||
|
||||
这里集中维护:
|
||||
|
||||
- 前端启动端口
|
||||
- 后端启动端口
|
||||
- PostgreSQL 连接参数
|
||||
- `DATABASE_URL`
|
||||
- `REDIS_URL`
|
||||
|
||||
从根目录统一启动:
|
||||
|
||||
```bash
|
||||
./start.sh
|
||||
```
|
||||
|
||||
可选模式:
|
||||
|
||||
```bash
|
||||
./start.sh web
|
||||
./start.sh server
|
||||
./start.sh all
|
||||
```
|
||||
|
||||
根目录 `start.sh` 是统一编排入口;前端和后端的子启动脚本分别是 `web/web_start.sh` 与 `server/server_start.sh`。
|
||||
|
||||
手动进入前端目录:
|
||||
|
||||
```bash
|
||||
cd web
|
||||
npm run dev
|
||||
```
|
||||
# X-Financial
|
||||
|
||||
项目结构已按前后端拆开:
|
||||
|
||||
- `web/`:前端工程(当前 Vue + Vite 项目)
|
||||
- `server/`:后端工程目录
|
||||
- `docs/`:方案和阶段文档
|
||||
- `UI/`:界面参考稿
|
||||
- `document/`:业务文档
|
||||
|
||||
根目录统一环境变量:
|
||||
|
||||
- `.env`
|
||||
- `.env.example`
|
||||
|
||||
这里集中维护:
|
||||
|
||||
- 前端启动端口
|
||||
- 后端启动端口
|
||||
- PostgreSQL 连接参数
|
||||
- `DATABASE_URL`
|
||||
- `REDIS_URL`
|
||||
|
||||
从根目录统一启动:
|
||||
|
||||
```bash
|
||||
./start.sh
|
||||
```
|
||||
|
||||
可选模式:
|
||||
|
||||
```bash
|
||||
./start.sh web
|
||||
./start.sh server
|
||||
./start.sh all
|
||||
```
|
||||
|
||||
根目录 `start.sh` 是统一编排入口;前端和后端的子启动脚本分别是 `web/web_start.sh` 与 `server/server_start.sh`。
|
||||
|
||||
Docker Compose 运行方式见 `docker/README.md`:
|
||||
|
||||
- `docker-compose.yml`:只启动主应用容器,适合复用已有数据库、ONLYOFFICE 等外部依赖。
|
||||
- `docker-compose.full.yml`:启动主应用、PostgreSQL、Qdrant、ONLYOFFICE 的完整本地开发栈。
|
||||
|
||||
手动进入前端目录:
|
||||
|
||||
```bash
|
||||
cd web
|
||||
npm run dev
|
||||
```
|
||||
|
||||
192
docker/README.md
192
docker/README.md
@@ -1,67 +1,127 @@
|
||||
# Docker Compose
|
||||
|
||||
This project currently uses the Vite `__setup/*` middleware during the initial setup flow.
|
||||
Because of that, the Docker deployment keeps the web frontend and FastAPI startup chain in
|
||||
the same main container and runs the existing root `start.sh`.
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Open:
|
||||
|
||||
```text
|
||||
# Docker Compose
|
||||
|
||||
X-Financial 现在按运行依赖分成两层 Docker Compose:
|
||||
|
||||
- `docker-compose.yml`:只启动主应用容器,适合已经有远端 PostgreSQL、ONLYOFFICE 或 Qdrant 的环境。
|
||||
- `docker-compose.full.yml`:启动完整本地开发栈,适合没有外部依赖、希望本机一次性跑齐所有服务的环境。
|
||||
|
||||
主应用容器仍然同时启动 Web 前端和 FastAPI 后端,并复用根目录 `start.sh`。
|
||||
项目根目录会挂载到容器内 `/app`。
|
||||
|
||||
## 轻量启动:只跑主应用
|
||||
|
||||
适合你已经有数据库和 ONLYOFFICE 的情况。
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
默认只会启动:
|
||||
|
||||
```text
|
||||
main
|
||||
```
|
||||
|
||||
打开:
|
||||
|
||||
```text
|
||||
http://<your-linux-host>:5273
|
||||
```
|
||||
|
||||
## Container Layout
|
||||
|
||||
- `main`: web + FastAPI main container
|
||||
- `onlyoffice`: ONLYOFFICE Document Server
|
||||
- `postgres`: PostgreSQL database container
|
||||
|
||||
The project root is mounted directly into the main container:
|
||||
|
||||
```text
|
||||
.:/app
|
||||
```
|
||||
|
||||
That means the container reads your existing `.env`, source code, `server/.secrets`, logs,
|
||||
and generated dependency directories directly from the mapped project folder.
|
||||
|
||||
This is a `compose`-only setup. There is no custom `Dockerfile`.
|
||||
The tradeoff is that the `main` container installs the Python runtime packages it needs
|
||||
when it starts.
|
||||
|
||||
## Persistence
|
||||
|
||||
The PostgreSQL data directory is stored in the named volume `postgres_data`.
|
||||
|
||||
## Notes
|
||||
|
||||
- Most configuration should be maintained in the project root `.env`.
|
||||
- The first `docker compose up -d` does not require an existing `.env`; the compose file
|
||||
uses built-in defaults for the PostgreSQL container and the main container database URL.
|
||||
- Docker Compose only overrides a few values that must differ inside containers:
|
||||
- `WEB_HOST=0.0.0.0`
|
||||
- `SERVER_HOST=0.0.0.0`
|
||||
- `POSTGRES_HOST=postgres`
|
||||
- `POSTGRES_PORT=5432`
|
||||
- `DATABASE_URL=...@postgres:...`
|
||||
- PostgreSQL is also published to the host by default as `127.0.0.1:55432`.
|
||||
- ONLYOFFICE is published to the host by default as `127.0.0.1:8082`.
|
||||
- First boot with `SETUP_COMPLETED=false` starts the setup UI only.
|
||||
- After you complete setup in the browser, the Vite setup bridge will start FastAPI in the
|
||||
same container using the saved runtime configuration.
|
||||
- On later restarts, `start.sh` will detect the saved setup state and start both web and
|
||||
server automatically.
|
||||
- If you access the system from another machine, make sure `CORS_ORIGINS` in `.env` includes
|
||||
the frontend address you actually use.
|
||||
- For Navicat or any host-side client, use `127.0.0.1:55432`.
|
||||
- If you need to access ONLYOFFICE from another machine, override `ONLYOFFICE_PUBLIC_URL`
|
||||
so the browser can reach the document server address you actually expose.
|
||||
- For the setup page, using `127.0.0.1` is acceptable in this Docker layout; the internal
|
||||
test bridge will resolve that back to the Docker PostgreSQL service.
|
||||
```
|
||||
|
||||
这条路径不会主动拉起本地 PostgreSQL、Qdrant 或 ONLYOFFICE。
|
||||
数据库、ONLYOFFICE 和 Qdrant 地址都从 `.env` 或外部环境变量读取。
|
||||
|
||||
常见外部依赖变量:
|
||||
|
||||
```text
|
||||
DATABASE_URL
|
||||
POSTGRES_HOST
|
||||
POSTGRES_PORT
|
||||
ONLYOFFICE_ENABLED
|
||||
ONLYOFFICE_PUBLIC_URL
|
||||
ONLYOFFICE_BACKEND_URL
|
||||
QDRANT_URL
|
||||
```
|
||||
|
||||
## 完整启动:本地全栈
|
||||
|
||||
适合没有远端数据库和 ONLYOFFICE 的情况。
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.full.yml up -d
|
||||
```
|
||||
|
||||
会启动:
|
||||
|
||||
```text
|
||||
main
|
||||
postgres
|
||||
qdrant
|
||||
onlyoffice
|
||||
```
|
||||
|
||||
本地服务端口:
|
||||
|
||||
```text
|
||||
Web: 5273
|
||||
FastAPI: 8000
|
||||
PostgreSQL: 55432 -> 5432
|
||||
Qdrant: 6333 / 6334
|
||||
ONLYOFFICE: 8082
|
||||
SSH: 2223
|
||||
```
|
||||
|
||||
完整栈会把主容器内的数据库地址指向 `postgres:5432`,
|
||||
并把 Qdrant 地址指向 `http://qdrant:6333`。
|
||||
|
||||
ONLYOFFICE 默认使用本机可访问地址:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:8082
|
||||
```
|
||||
|
||||
如果浏览器从另一台机器访问,需要覆盖:
|
||||
|
||||
```bash
|
||||
LOCAL_ONLYOFFICE_PUBLIC_URL=http://<host>:8082 \
|
||||
docker compose -f docker-compose.full.yml up -d
|
||||
```
|
||||
|
||||
如果 ONLYOFFICE 回调后端也需要外部地址,可以同时覆盖:
|
||||
|
||||
```bash
|
||||
LOCAL_ONLYOFFICE_BACKEND_URL=http://<host>:8000 \
|
||||
docker compose -f docker-compose.full.yml up -d
|
||||
```
|
||||
|
||||
## 可选:只额外启动本地 PostgreSQL
|
||||
|
||||
如果只想在轻量主容器旁边补一个本地 PostgreSQL,可以使用覆盖文件:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f docker-compose.postgres.yml up -d
|
||||
```
|
||||
|
||||
这会启动:
|
||||
|
||||
```text
|
||||
main
|
||||
postgres
|
||||
```
|
||||
|
||||
## 停止与清理
|
||||
|
||||
停止当前默认轻量栈:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
停止完整本地栈:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.full.yml down
|
||||
```
|
||||
|
||||
如需删除本地数据卷,先确认不再需要其中数据,再手动执行带 `-v` 的清理命令。
|
||||
|
||||
159
docs/superpowers/plans/2026-06-22-refactor-under-800-lines.md
Normal file
159
docs/superpowers/plans/2026-06-22-refactor-under-800-lines.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# Refactor Under 800 Lines Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Keep every Python class and every frontend core component/module under 800 lines, while deleting proven dead code and reducing avoidable runtime overhead.
|
||||
|
||||
**Architecture:** Add automated code-size guardrails first, then split oversized units by existing responsibility boundaries. Preserve public APIs wherever possible, move private helpers into focused modules, and delete code only after usage checks or tests prove it is not needed.
|
||||
|
||||
**Tech Stack:** Vue single-file components, Vite/Node test runner, Python/FastAPI service layer, pytest inside Docker container `x-financial-main`.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Guardrails
|
||||
|
||||
**Files:**
|
||||
- Create: `web/tests/code-size-limits.test.mjs`
|
||||
- Create: `server/tests/test_code_size_limits.py`
|
||||
|
||||
- [x] **Step 1: Add frontend source-unit limit test**
|
||||
|
||||
```bash
|
||||
node --test web/tests/code-size-limits.test.mjs
|
||||
```
|
||||
|
||||
Expected current result: FAIL, listing oversized files in `web/src/components`, `web/src/composables`, `web/src/utils`, and `web/src/views`.
|
||||
|
||||
- [x] **Step 2: Add backend class limit test**
|
||||
|
||||
```bash
|
||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_code_size_limits.py
|
||||
```
|
||||
|
||||
Expected current result: FAIL, listing Python classes over 800 lines.
|
||||
|
||||
|
||||
### Task 2: Backend Python Class Split
|
||||
|
||||
**Files:**
|
||||
- Modify: `server/src/app/services/user_agent_application.py`
|
||||
- Modify: `server/src/app/services/risk_rule_template_executor.py`
|
||||
- Modify: `server/src/app/services/steward_planner.py`
|
||||
- Modify: `server/src/app/services/receipt_folder.py`
|
||||
- Modify: `server/src/app/services/expense_claim_draft_flow.py`
|
||||
- Modify: `server/src/app/services/expense_claims.py`
|
||||
- Modify: `server/src/app/services/orchestrator_execution.py`
|
||||
- Modify: `server/src/app/services/finance_dashboard.py`
|
||||
- Modify: `server/src/app/services/agent_assets.py`
|
||||
- Create focused helper or mixin files under `server/src/app/services/`
|
||||
|
||||
- [ ] **Step 1: Split low-risk helper groups first**
|
||||
|
||||
Move private formatting, parsing, label, and serialization methods into helper mixins or helper modules. Keep original public classes and method names stable.
|
||||
|
||||
- [ ] **Step 2: Split domain-heavy groups**
|
||||
|
||||
Move larger responsibility groups into named mixins:
|
||||
|
||||
```text
|
||||
UserAgentApplicationMixin
|
||||
├── application fact resolution
|
||||
├── application persistence
|
||||
└── application duplicate/detail helpers
|
||||
|
||||
RiskRuleTemplateExecutor
|
||||
├── condition evaluators
|
||||
├── value resolvers
|
||||
└── date/window parsing
|
||||
|
||||
ReceiptFolderService
|
||||
├── storage/meta helpers
|
||||
├── editable field resolution
|
||||
└── train ticket extraction
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Verify backend class limit**
|
||||
|
||||
```bash
|
||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_code_size_limits.py
|
||||
```
|
||||
|
||||
Expected final result: PASS.
|
||||
|
||||
- [ ] **Step 4: Run targeted backend regression tests**
|
||||
|
||||
```bash
|
||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_user_agent_service.py server/tests/test_expense_claim_service.py server/tests/test_steward_planner.py server/tests/test_risk_rule_generation.py server/tests/test_agent_asset_service.py server/tests/test_reimbursement_endpoints.py
|
||||
```
|
||||
|
||||
Expected final result: PASS or a documented pre-existing failure with evidence.
|
||||
|
||||
|
||||
### Task 3: Frontend Source Unit Split
|
||||
|
||||
**Files:**
|
||||
- Modify: `web/src/components/business/PersonalWorkbenchAiMode.vue`
|
||||
- Modify: `web/src/views/scripts/TravelReimbursementCreateView.js`
|
||||
- Modify: `web/src/views/scripts/TravelRequestDetailView.js`
|
||||
- Modify: `web/src/views/scripts/useTravelReimbursementSubmitComposer.js`
|
||||
- Modify remaining files reported by `web/tests/code-size-limits.test.mjs`
|
||||
- Create focused modules beside the existing owners under `web/src/views/scripts/`, `web/src/components/`, `web/src/composables/`, and `web/src/utils/`
|
||||
|
||||
- [ ] **Step 1: Split pure helpers before stateful runtime code**
|
||||
|
||||
Extract pure formatting, payload normalization, label mapping, row building, and text rendering helpers. This reduces file size without changing component state ownership.
|
||||
|
||||
- [ ] **Step 2: Split composables and child components**
|
||||
|
||||
For Vue files, move stable repeated UI blocks into child components only when props/events are clear. For script modules, move independent computed builders and action helpers into colocated modules.
|
||||
|
||||
- [ ] **Step 3: Remove proven redundant frontend code**
|
||||
|
||||
Use `rg` to confirm an export, class, helper, CSS hook, or branch is unused before deleting it. If a usage is dynamic, keep it unless a regression test proves it is dead.
|
||||
|
||||
- [ ] **Step 4: Verify frontend source limit**
|
||||
|
||||
```bash
|
||||
node --test web/tests/code-size-limits.test.mjs
|
||||
```
|
||||
|
||||
Expected final result: PASS.
|
||||
|
||||
- [ ] **Step 5: Run targeted frontend regression tests**
|
||||
|
||||
```bash
|
||||
node --test web/tests/workbench-ai-mode-switch.test.mjs web/tests/expense-application-fast-preview.test.mjs web/tests/expense-profile-detail-modal.test.mjs web/tests/finance-dashboard-ranking.test.mjs
|
||||
npm --prefix web run build
|
||||
```
|
||||
|
||||
Expected final result: PASS.
|
||||
|
||||
|
||||
### Task 4: Performance And Cleanup Pass
|
||||
|
||||
**Files:**
|
||||
- Modify only files already touched by Tasks 2 and 3 unless a usage check proves a separate dead module can be removed.
|
||||
|
||||
- [ ] **Step 1: Remove repeated computation inside hot paths**
|
||||
|
||||
Cache local computed values inside functions, avoid repeated JSON/string/date parsing loops, and prefer early returns for blocked states.
|
||||
|
||||
- [ ] **Step 2: Delete redundant private helpers**
|
||||
|
||||
Delete helpers only when all of these checks are true:
|
||||
|
||||
```bash
|
||||
rg "helperName" server web
|
||||
node --test affected-web-test.mjs
|
||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q affected_server_test.py
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Final verification**
|
||||
|
||||
```bash
|
||||
node --test web/tests/code-size-limits.test.mjs
|
||||
docker exec -w /app -e SERVER_VENV_DIR=/tmp/x-financial-server-venv x-financial-main /tmp/x-financial-server-venv/bin/pytest -q server/tests/test_code_size_limits.py
|
||||
npm --prefix web run build
|
||||
```
|
||||
|
||||
Expected final result: PASS.
|
||||
BIN
docs/ui-mockups/attachment-association-enterprise-ui-v1.png
Normal file
BIN
docs/ui-mockups/attachment-association-enterprise-ui-v1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 148 KiB |
Reference in New Issue
Block a user