Files
qiji/CLAUDE.md
T
v6ole 72fb7524f3 docs: CLAUDE.md — 更新部署架构 + 工作页客户经理列
- 新增完成项: 工作页客户经理列+汇总栏, 云端部署
- 新增部署架构章节 (FRP 隧道/前端容器/OpenResty/端口表)
- 新增设计决策 #22 (云端部署)
- 更新验证状态表 (生产 URL/FRP/容器)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-26 09:21:41 +08:00

265 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md — 企迹 (qiji) 政企周报管理系统
## 项目概述
面向中国电信政企客户经理团队,替代 Excel 的周报管理系统。覆盖每日拜访记录、下周工作计划、小微业务商机跟单、要客拜访计划四大模块。支持 PC 端(支局长/分管领导汇总查看)和移动端(客户经理外勤填报 + 企微入口)。
## 技术栈
| 层 | 技术 |
|---|------|
| 后端 | FastAPI + SQLAlchemy 2.0 (async) + Alembic |
| 数据库 | PostgreSQL (已有,复用) |
| 文件存储 | MinIO (已有,复用) |
| 认证 | Casdoor OIDC (已有) + 企业微信 OAuth |
| 前端 | Vue 3 + Vite + TypeScript + Element Plus |
| 状态管理 | Pinia |
| 定时任务 | APScheduler |
## 项目结构
```
qiji/
├── docker-compose.yml # PostgreSQL + MinIO + backend
├── 政企周报管理系统-设计文档.md # 完整设计文档
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI 入口 + lifespan + 路由挂载
│ │ ├── config.py # pydantic-settings 配置
│ │ ├── database.py # async engine + session
│ │ ├── models/ # 8 张表 (见下方数据模型)
│ │ ├── schemas/ # Pydantic 请求/响应 schema
│ │ ├── api/ # REST 路由 (12 个模块)
│ │ ├── services/ # 业务逻辑层
│ │ ├── middleware/auth.py # JWT 鉴权 + 角色权限
│ │ └── utils/security.py # JWT 签发/验证
│ ├── alembic/ # 数据库迁移
│ └── requirements.txt
├── frontend/
│ ├── src/
│ │ ├── router/index.ts # 路由 (mobile + desktop 两套布局)
│ │ ├── stores/auth.ts # Pinia 认证 store
│ │ ├── api/ # 9 个 Axios API 模块
│ │ ├── views/
│ │ │ ├── mobile/ # 移动端页面 (Home, VisitForm, ...)
│ │ │ └── desktop/ # PC 端页面 (Dashboard, WeeklyReport, ...)
│ │ └── components/ # MobileLayout + DesktopLayout
│ ├── nginx.conf # 生产 nginx 配置
│ └── Dockerfile
```
## 数据模型 (9 张 PostgreSQL 表)
| 表 | 核心字段 |
|----|---------|
| `users` | id, casdoor_id, name, role(manager/director/leader), wecom_userid |
| `customers` | id, name, industry, address, in_use_services, monthly_fee, remarks, created_by |
| `customer_contacts` | id, customer_id, name, phone, role_desc |
| `customer_assignments` | id, customer_id, manager_id, role(primary/assistant), assigned_by |
| `visits` | id, customer_id, visit_date, visit_method, time_range, visitor_name, visitor_phone, communication_content, customer_demand, companions(UUID[]), photos(TEXT[]), manager_id, edit_log(JSONB) |
| `daily_notes` | id, manager_id, note_date, category, content, time_range, edit_log(JSONB) |
| `work_plans` | id, customer_id, plan_content, plan_date, manager_id, status, edit_log(JSONB) |
| `mini_business` | id, customer_id, product_type, amount, follow_up_detail, status, manager_id, expected_revenue_date, edit_log(JSONB) |
| `key_visits` | id, customer_id, urgency_level, description, progress_status, planned_date, planned_visitor, visit_target, manager_id, edit_log(JSONB) |
## 当前进度
### 已完成 ✅
- [x] **Phase 1: 项目骨架** — 完整目录结构,FastAPI + Vue 3 均可启动/构建
- [x] **Phase 2: 数据模型** — 8 个 SQLAlchemy 模型 + Alembic 迁移配置
- [x] **Phase 3: 认证系统** — JWT + Casdoor OIDC + 企微静默登录 + 角色中间件
- [x] **Phase 4: 客户档案** — CRUD 全链路 API + PC 端管理页 + 归属分配/批量转移
- [x] **Phase 5: 拜访记录** — CRUD API + MinIO 预签名直传 + 移动端填报表单 + 移动端首页
- [x] **Phase 6: 计划/商机/要客** — 三个模块的 CRUD API + 移动端表单
- [x] **Phase 7: 仪表盘与汇总** — 四卡统计 + 填报进度 + 四 Tab 周报 + 按人/客户筛选 + 时间轴
- [x] **Phase 8: Excel 导入导出** — 导出四 sheet xlsx + 导入预览→确认→去重
- [x] **Phase 9: 企业微信** — 静默登录 + 催办/公告推送 + 每日 18:00 定时检查
- [x] **Phase 10: 部署** — Dockerfile × 2 + nginx.conf + docker-compose.yml
- [x] **Casdoor 对接** — 已配置 Casdoor OIDC,前后端 Client ID 统一,登录/回调正常
- [x] **MinIO 对接** — 已配置预签名上传/下载,bucket 就绪
- [x] **PostgreSQL 对接** — 8 张表自动创建,数据持久化正常
- [x] **用户管理** — 支局长可在 PC 端「用户管理」页面修改任意用户角色
- [x] **客户档案增强** — 详情含客户经理、点击名称查看、备注字段、收支费用(金额+单位)、联系人管理(新增/删除)、多选批量转移
- [x] **客户导入导出** — 导出含全部字段 + 模板下载 + Excel 批量导入(自动去重匹配经理)
- [x] **路由修复** — Hash 改 HTML5 History 模式,Casdoor 回调正常
- [x] **网络部署** — 后端监听 0.0.0.0:8002,前端监听 0.0.0.0:5173,防火墙已开放
- [x] **今日纪要** — 9 张表之 daily_notes,6 种分类 + 彩色标签 + 时间选择器
- [x] **客户经理 PC 端工作台** — 「我的数据」五模块 CRUD + 状态快速切换
- [x] **拜访人字段** — visits 表新增 visitor_name/visitor_phone
- [x] **时间选择器** — 全部时间范围改为 el-time-picker (is-range)
- [x] **时区统一** — 后端 today_cst() 统一用 Asia/Shanghai,前端本地格式
- [x] **UI 设计系统** — CSS 变量 + 编辑风 (ink/gold/paper) + 侧边栏折叠 + SVG 图标
- [x] **分页筛选** — 客户列表分页(25/50/100) + 行业/业务/经理/联系人/地址搜索
- [x] **权限细化** — 分管领导只读客户档案,经理可编辑自己客户但不可改经理/删除
- [x] **拜访方式/紧急度** — 统一 chip 按钮风格,各色区分
- [x] **计划拜访人多选** — 支持从系统人员多选 + 手动输入
- [x] **旧周报导入模板** — 四 Sheet Excel 模板下载 + 示例数据
- [x] **数据库迁移** — lifespan 自动 ALTER TABLE 加列 (remarks/visitor_name/visitor_phone)
- [x] **历史周报** — 周选择器翻看往周数据,历史归档只读,导出支持历史周
- [x] **图片预览** — 全屏大图查看(移动端+PC端统一),点击遮罩关闭
- [x] **PC端照片管理** — 编辑时可上传新照片、删除已有照片
- [x] **客户导入更新** — 重名客户自动更新信息而非跳过,显示逐条操作明细
- [x] **导入跳过原因** — 旧周报导入+客户导入均显示跳过/更新明细
- [x] **用户去重合并** — 4组重复用户合并,数据完整迁移
- [x] **填报进度权限** — 经理只看到自己,支局长/领导看全员
- [x] **客户经理列** — 暖灰色hash标签,每人唯一颜色
- [x] **列表序号** — 客户管理+用户管理添加序号列
- [x] **客户导入修复** — 修复 import_customers 500 错误(errors 变量未初始化)
- [x] **图片预览增强** — 适应页面/缩放/拖拽平移 + 底部工具栏(PC端+移动端统一 ImagePreview 组件)
- [x] **信息架构重组** — 周报精简为拜访+纪要两个Tab;工作计划/商机/要客独立为侧边栏「工作」分组下的独立页面;仪表盘四卡可点击跳转
- [x] **侧边栏分组** — 侧边栏分为「汇总」「工作」「管理」三个分组,JetBrains Mono 标签
- [x] **变更追踪 (edit_log)** — 5 张表新增 JSONB edit_log 列;POST 初始化创建记录;PUT 自动对比新旧值追加 diff;编辑弹窗底部展示变更时间轴(EditLogPanel.vue);表格被修改过的记录显示 🕐 时钟图标
- [x] **导入模板增强** — 客户导入失败原因明细显示
- [x] **操作精简** — 工作计划/商机/要客页面移除冗余"编辑"按钮(点击客户名已可编辑)
- [x] **客户亮灯表** — 四色覆盖矩阵(●实心圆已拜访/◐半圆临期/○空心圆未拜访/◌虚线未分配),按客户经理折叠卡片流,覆盖率进度条,红灯客户连续未拜访月份追踪,未分配客户专区,支持历史月份翻看。权限:经理只看自己,支局长/领导看全员
- [x] **AI 周报摘要** — 接入 DeepSeek V4 (OpenAI 兼容 `/v1/chat/completions`),一键生成拜访概况/客户需求/覆盖分析/下周建议四段式周报摘要,注入亮灯表覆盖数据增强分析,支局长/分管领导专用,Markdown 渲染展示,一键复制(HTTP 环境自动降级 textarea),支持配置任意 OpenAI 兼容模型
- [x] **亮灯表→周报联动** — 点击亮灯表客户卡片自动跳转周报并按客户筛选,周报筛选栏新增客户下拉
- [x] **复制功能修复** — HTTP 内网环境下 Clipboard API 不可用,降级为 textarea + execCommand
- [x] **工作页客户经理列+汇总栏** — 工作计划/商机跟单/要客拜访三个页面新增"客户经理"列(哈希色标签)+ 页面顶部汇总栏(按经理分组统计条数)
- [x] **云端部署** — FRP 隧道 `qiji-backend` (本机 8002→远程 18061),前端 Docker 容器 `qiji-frontend` (远程 18063)OpenResty 反代 `qj.dhdx.fun`,生产模式运行(去掉 --reload),SECRET_KEY 已加固,CORS 已更新
### 待完善
- [ ] 实际对接企业微信(需填写 WECOM_CORP_ID/AGENT_ID/SECRET 等)
- [ ] 前端移动端/桌面端自动适配(目前路由分两套,user-agent 判断待完善)
- [ ] 客户查重前端集成(API 已有 `/customers/check-duplicate/{name}`
- [ ] 缩略图生成策略(MinIO 端配置)
- [ ] 企微聊天侧边栏(设计文档标注为"后续扩展,首期不做")
## 验证状态
| 检查项 | 结果 |
|--------|------|
| `import app.main` | ✅ 成功 |
| `vite build` | ✅ 构建成功,输出到 `dist/` |
| 后端运行 | ✅ `http://10.10.10.14:8002`,生产模式 `http://localhost:8002/health` |
| 前端运行 | ✅ `http://10.10.10.14:5173` (dev)`https://qj.dhdx.fun` (生产) |
| PostgreSQL | ✅ `10.10.10.14:5432/qiji` |
| MinIO | ✅ `10.10.10.13:17051`bucket `qiji-photos` |
| Casdoor | ✅ `10.10.10.14:18000`,登录/回调正常 |
| FRP 隧道 | ✅ `qiji-backend` 运行中 (8002→18061) |
| 前端容器 | ✅ `qiji-frontend` 运行中 (18063→80) |
| 企微推送 | ⚠️ 待填写有效 Token/AESKey 后测试 |
| `docker-compose up` | ⚠️ 需要本地 PostgreSQL + MinIO 实例 |
## 部署架构
```
用户 → https://qj.dhdx.fun → 远程服务器(175.178.19.237)
OpenResty (80/443)
┌──────────────┴──────────────┐
▼ ▼
前端容器 FRP 隧道
qiji-frontend:18063 18061
│ │
│ frps→frpc
│ │
│ 本机后端 :8002
```
| 资源 | 位置 | 端口 |
|------|------|------|
| 后端 (uvicorn) | 本机 | 8002 |
| FRP 隧道 `qiji-backend` | 本机→远程 | 8002→18061 |
| 前端 Docker 容器 | 远程 | 18063→80 |
| OpenResty 反代 | 远程 | `/`→18063, `/api/`→18061 |
| frpc 配置 | `/opt/1panel/apps/frpc/frpc/data/frpc.toml` | Docker 容器管理 |
| 前端构建部署 | `docker build -t qiji-frontend:latest .``docker save``ssh docker load` | 本机构建,推送远程 |
## 启动命令
### 第一步:配置环境变量
```bash
# 后端
cd backend
cp .env.example .env
# 编辑 .env,填入 Casdoor/PostgreSQL/MinIO/企微 的真实连接信息
# 前端(Casdoor 登录用)
cd frontend
cat > .env << 'EOF'
VITE_CASDOOR_ENDPOINT=http://your-casdoor:18000
VITE_CASDOOR_CLIENT_ID=your-client-id
EOF
```
配置项说明:
| 配置块 | 说明 | 必须? |
|--------|------|--------|
| `DATABASE_URL` | PostgreSQL 连接串,已有基础设施填真实地址 | ✅ 必须 |
| `CASDOOR_*` | Casdoor OIDC 认证服务的地址、Client ID/Secret | ✅ 登录必须 |
| `MINIO_*` | MinIO 对象存储地址和密钥 | ✅ 照片上传必须 |
| `WECOM_*` | 企微自建应用的 Corp ID / Agent ID / Secret | ⚠️ 企微功能需要 |
| `AI_API_URL` | OpenAI 兼容 LLM API 地址 (如 `https://api.openai.com/v1/chat/completions`) | ⚠️ AI 摘要需要 |
| `AI_API_KEY` | LLM API 密钥 | ⚠️ AI 摘要需要 |
| `AI_MODEL` | 模型名称 (默认 `gpt-4o`,也支持 `deepseek-chat` 等) | ⚠️ AI 摘要需要 |
| `SECRET_KEY` | JWT 签发密钥,生产环境务必修改 | ✅ 必须 |
| `CORS_ORIGINS` | 前端地址白名单 | ✅ 必须 |
| `VITE_CASDOOR_*` | 前端登录跳转 Casdoor 所需,必须与后端一致 | ✅ 必须 |
### 第二步:启动 PostgreSQL + MinIO
如果已有可用的 PostgreSQL 和 MinIO 实例,跳过此步。否则用 docker-compose 启动:
```bash
# 在项目根目录执行
docker-compose up -d postgres minio
```
### 第三步:启动后端
```bash
cd backend
uvicorn app.main:app --reload --port 8002 --host 0.0.0.0
# 首次启动会自动创建数据库表(lifespan 中执行 Base.metadata.create_all
# API 文档 → http://localhost:8002/docs
```
### 第四步:启动前端
```bash
cd frontend
npm run dev -- --host 0.0.0.0
# 页面 → http://localhost:5173
# vite proxy 自动将 /api/* 请求转发到 localhost:8002
```
### 一键启动(生产模式)
```bash
# 项目根目录
docker-compose up -d
# 后端 :8000 + PostgreSQL :5432 + MinIO :9000 + :9001(console)
# 前端需单独部署到 nginx,见 frontend/Dockerfile + nginx.conf
```
## 关键设计决策
1. **双布局**: `/m/*` 移动端(底部 TabBar),`/*` PC 端(侧边栏菜单)
2. **照片上传**: 前端从 `/api/upload/presigned-url` 拿 PUT URL → 直传 MinIO → 表单只传 object key
3. **同访人员**: 选同访人后,后端自动创建一条内容为空的状态副本
4. **权限**: JWT payload 含 `role``RoleChecker` 做接口级鉴权,前端 Pinia store 做 UI 级控制
5. **企微静默登录**: wecom code → userid → 查 users 表 → 找到签 JWT / 未找到引导 Casdoor 绑定
6. **前后端分离开发**: `vite.config.ts` proxy 转发 `/api``localhost:8002`
7. **填报进度判断**: 今日有拜访记录 OR 今日有纪要 → 已填报(双维度考核)
8. **拜访方式颜色**: 上门(墨绿)/电话(灰蓝)/微信(翠绿)/出差(金色),卡片+表单统一
9. **纪要分类**: 行政事务/合同整理/发票处理/内部会议/培训学习/其他,单字徽章+彩色标签
10. **时间范围**: 所有表单统一用 el-time-picker is-range,存储为 HH:mm-HH:mm 格式
11. **列表操作**: 点击客户名→详情弹窗含编辑/删除按钮,移除表格操作栏
12. **侧边栏**: ink 深色渐变 + SVG 内联图标 + 可折叠(64px) + 金色装饰线
13. **客户经理列**: hash 配色标签,每人唯一颜色(8 色暖灰调)
14. **侧边栏分组**: 汇总(仪表盘/周报)、工作(工作计划/商机跟单/要客拜访)、管理(客户/用户/系统设置)三层分组,JetBrains Mono 标签
15. **周报精简**: 只保留每日拜访记录+今日纪要两个 Tab,工作计划/商机/要客独立为侧边栏项目
16. **独立工作页**: 工作计划/商机/要客各自拥有独立页面 + CRUD 弹窗 + 状态快速切换
17. **变更追踪 (edit_log)**: 5 张业务表均含 JSONB edit_log 列;POST 自动插入创建记录;PUT 自动 diff 新旧值追加变更条目(编辑人+时间+字段级 diff+原因);编辑弹窗底部折叠时间轴面板;表格 🕐 图标标记被修改过的记录
18. **图片预览**: ImagePreview.vue 统一组件,支持适应页面/缩放(0.25x~5x)/拖拽平移/滚轮缩放/键盘快捷键,PC+移动端一致体验
19. **仪表盘跳转**: 四张统计卡片可点击跳转到对应的周报/工作计划/商机/要客页面
20. **客户亮灯表**: 几何圆形图标(●实心圆已拜访/◐半圆临期/○空心圆未拜访/◌虚线未分配),按客户经理折叠卡片流(220px),覆盖率进度条,红灯卡片呼吸动画,未分配客户专区(虚线边框),默认折叠→点击展开明细,支持历史月份翻看。权限:`get_light_board(user_id, role)` — director/leader 看全员+未分配客户,manager 只看自己
21. **AI 周报摘要**: 接入 DeepSeek V4 (模型 `deepseek-v4-flash`,端点 `/v1/chat/completions`OpenAI 兼容协议)。`build_summary_prompt()` 注入拜访总览+各经理明细+客户需求汇总+纪要分类+亮灯表覆盖数据,生成四段式 Markdown。WeeklyReport.vue 集成:按钮(闪电图标)→loading 脉冲→渲染→一键复制(安全上下文检测降级)。权限:director/leader 可见按钮
22. **云端部署**: FRP 隧道 (8002→18061) + Docker 前端容器 (18063) + OpenResty 反代。frpc 由 1Panel Docker 容器管理,配置在 `/opt/1panel/apps/frpc/frpc/data/frpc.toml`。前端生产构建用 `.env.production` 指向 Casdoor 公网地址。nginx.conf 只保留 SPA fallbackAPI 路由由 OpenResty 边缘处理