企迹(qiji) 政企周报管理系统 — v0.1

后端: FastAPI + SQLAlchemy 2.0 (async) + Alembic + MinIO + Casdoor + 企微
前端: Vue 3 + Vite + TypeScript + Element Plus + Pinia

功能清单:
- 8 张数据表自动建表 / Casdoor OIDC 登录 / 企微静默登录
- 双布局: 移动端(填报) + PC端(汇总管理)
- 拜访记录 CRUD + MinIO 照片直传 + 缩略图预览 + 同访人草稿
- 今日纪要 (6 分类) / 工作计划 / 小微商机 / 要客拜访 CRUD
- 客户档案: 备注/收支费用/联系人/归属分配/批量转移
- 客户导入导出 + 模板下载 + 搜索/分页/筛选
- 仪表盘: 四卡统计 + 填报进度 (拜访+纪要双维度)
- 周报详情: 五 Tab + 按人/客户筛选 + 时间轴
- 用户管理 / 客户经理 PC 端工作台
- 企微: 催办/公告/定时提醒 / 时区修正
- Docker 部署配置

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-23 01:35:46 +08:00
parent 2a8225c31f
commit a1886074dd
97 changed files with 8830 additions and 0 deletions
+268
View File
@@ -0,0 +1,268 @@
# 企迹 (qiji) — 政企周报管理系统 设计文档
## 项目背景
中国电信政企客户经理团队目前使用 Excel 进行周报管理,包含四个 Sheet:每日拜访记录、下周工作计划、小微业务商机跟单、要客拜访计划。现有方式存在填报效率低、无法挂载照片、汇总查看不便、考核靠人工点名扣分、客户数据无法沉淀等问题。
本系统以 FastAPI + Vue 3 构建,部署在本地服务器 + 云服务器的混合拓扑上,对接已有的 Casdoor(认证)、PostgreSQL(数据库)、MinIO(文件存储)、企业微信(消息推送与快捷入口)。
## 用户规模与角色
小型支局,约 5-8 人:3-5 名客户经理 + 1 名支局长 + 偶尔分管领导查看。
### 角色权限矩阵
| 角色 | 数据可见性 | 操作权限 |
|------|-----------|---------|
| 客户经理 | 只看自己的拜访记录、工作计划、商机、要客拜访 | 填/改/删自己的记录,上传照片,新建客户 |
| 支局长 | 全支局所有人的所有数据 | 增删改所有人记录,导出汇总,查看填报统计,手动触发催办/推送公告,管理客户档案与归属分配 |
| 分管领导 | 同支局长全量视图 | 仅查看和导出,不可编辑 |
## 技术架构
```
本地服务器(内网)
├── FastAPI (uvicorn, port 8000)
├── PostgreSQL(已有,复用)
└── MinIO(已有,复用)
云服务器
└── Vue 3 前端 (nginx, port 443, 域名)
↕ API 请求走 HTTPS → 本地服务器公网映射端口
Casdoor(已有部署,OIDC
企业微信(管理后台创建自建应用)
```
开发阶段前后端均在本地:`localhost:8000` + `localhost:5173` 联调。
### 后端:FastAPI
- 单体应用,FastAPI + SQLAlchemy (async) + Alembic 做数据迁移
- JWT 鉴权,token 签发与验证对接 Casdoor OIDC
- 文件上传:客户端获取 MinIO 预签名 URL 直传,API 只记录 object key
- 定时任务:APScheduler,每日 18:00 检查填报情况触发企微提醒
### 前端:Vue 3
- Vue 3 + Vite + TypeScript
- 组件库:Element Plus(中文生态好,表格/表单组件成熟)
- 两套适配布局:PC Web 端(支局长/分管领导汇总查看)+ 移动端(客户经理外勤快速填报,也是企微应用落地页)
### 存储:MinIO
- 组织方式:`{date}/{manager}/{uuid}.jpg`
- 单张限制 10MB,一次拜访最多 9 张
- 上传走预签名 URL,绕过 API 中转
- 查看走预签名下载 URL(有效期 1 小时)
- 缩略图由 MinIO 策略自动生成
- 删除拜访记录时同步清理关联照片
### 认证:Casdoor
- FastAPI 作为 OIDC Relying Party
- 用户在 Casdoor 已分配角色(客户经理 / 支局长 / 分管领导),JWT 携带角色信息
- 企业微信用户绑定 Casdoor 账号后,可实现企微内静默登录
## 数据模型
共 7 张核心表,全部使用 PostgreSQL。
### customers — 客户档案
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| name | VARCHAR(200) | 单位名称 |
| industry | VARCHAR(100) | 所属行业 |
| address | VARCHAR(500) | 单位地址 |
| in_use_services | TEXT | 在用业务(枚举文本) |
| monthly_fee | VARCHAR(100) | 月使用费 |
| created_by | UUID → users.id | 创建人 |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
### customer_contacts — 客户联系人
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| customer_id | UUID → customers.id | 所属客户 |
| name | VARCHAR(50) | 联系人姓名 |
| phone | VARCHAR(20) | 联系方式 |
| role_desc | VARCHAR(100) | 角色描述(如"技术对接人" |
### customer_assignments — 客户经理归属
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| customer_id | UUID → customers.id | |
| manager_id | UUID → users.id | |
| role | VARCHAR(20) | 'primary' / 'assistant' |
| assigned_at | TIMESTAMP | 分配时间 |
| assigned_by | UUID → users.id | 操作人(支局长) |
支持归属转移:支局长修改 `manager_id` 即可,历史拜访记录保留在 `visits.manager_id` 原值不变。
### visits — 每日拜访记录(对应"周报"sheet
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| customer_id | UUID → customers.id | 走访单位 |
| visit_date | DATE | 拜访日期 |
| visit_method | VARCHAR(20) | 上门/电话/微信/出差 |
| time_range | VARCHAR(30) | 如 "9:00-10:00" |
| communication_content | TEXT | 沟通内容 |
| customer_demand | TEXT | 客户需求 |
| companions | UUID[] | 同访人员 ID 数组 |
| photos | TEXT[] | MinIO object key 数组 |
| manager_id | UUID → users.id | 客户经理 |
| created_at | TIMESTAMP | |
| updated_at | TIMESTAMP | |
### work_plans — 下周工作计划
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| customer_id | UUID → customers.id | 计划走访单位 |
| plan_content | TEXT | 工作计划 |
| plan_date | DATE | 计划拜访时间 |
| manager_id | UUID → users.id | |
| status | VARCHAR(20) | 计划中/已完成/已取消 |
### mini_business — 小微业务商机(对应"小微业务"sheet
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| customer_id | UUID → customers.id | 单位名称 |
| product_type | VARCHAR(200) | 产品类型 |
| amount | VARCHAR(100) | 金额 |
| follow_up_detail | TEXT | 跟进内容具体情况 |
| status | VARCHAR(50) | 跟进状态 |
| manager_id | UUID → users.id | |
| expected_revenue_date | VARCHAR(50) | 预计列收时间 |
### key_visits — 要客拜访计划
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| customer_id | UUID → customers.id | 单位 |
| urgency_level | VARCHAR(10) | 紧急重要度:重要/一般/紧急 |
| description | TEXT | 内容描述 |
| progress_status | VARCHAR(20) | 进展状态 |
| planned_date | VARCHAR(50) | 计划拜访时间 |
| planned_visitor | VARCHAR(100) | 计划拜访人 |
| visit_target | VARCHAR(100) | 拜访对象 |
| manager_id | UUID → users.id | |
### users — 用户(对接 Casdoor
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID | 主键 |
| casdoor_id | VARCHAR(100) | Casdoor 用户 ID |
| name | VARCHAR(50) | 姓名 |
| role | VARCHAR(30) | manager / director / leader |
| department | VARCHAR(100) | 部门 |
| wecom_userid | VARCHAR(100) | 企业微信 userid |
## 核心功能设计
### 一、客户经理填报
**入口**:移动端「今日拜访」按钮 + 企微工作台菜单「今日拜访」。
**表单字段**
- 客户单位:下拉选择(仅显示自己负责的客户 + 自己新建的客户),支持搜索,支持快速新建客户
- 选择客户后自动带出联系人信息
- 拜访日期:默认今天
- 拜访方式:单选(上门 / 电话 / 微信 / 出差)
- 时间范围:两个时间选择器
- 同访人员:多选,选了谁自动在对方账号下创建一条预填草稿(沟通内容留空让对方补)
- 沟通内容:自由文本
- 客户需求:自由文本(用于汇总时的关键字提取)
- 拜访照片:最多 9 张,拍照或从相册选,走 MinIO 预签名直传
**首页状态**:显示「今天已录入 N 条」,下方为当天已填记录的摘要卡片列表。
### 二、支局长汇总视图
**仪表盘首页**
- 四张数字卡片:本周拜访次数、工作计划条数、商机跟单条数、要客拜访条数
- 填报进度条:每个客户经理的填报情况(已填/未填),未填人员红色标记 ⚠
- 快捷入口:本周周报详情、导出 Excel、历史周报
**周报详情页**:四个 Tab 对应四个业务模块
- 支持按人筛选、按客户筛选
- 时间轴模式按天分组
- 照片缩略图,点击放大查看
- 一键导出 Excel(格式与现有模板一致)
**考核与催办**
- 每日 18:00 自动检查,企微推送提醒未填报的客户经理
- 支局长可手动点击「催办」按钮,选择人员发送应用消息
- 支局长可编辑一条自定义公告,推送到全员企微
- 支局长可设置"当日最低拜访条数"阈值,低于阈值也预警
### 三、分管领导视图
与支局长相同的全量数据视图,所有编辑按钮灰色禁用。核心目标是随时打开看,首屏加载 1 秒以内。
### 四、客户档案管理
- 独立客户档案,包含单位基本信息、在用业务、月使用费、关键联系人
- 客户经理—客户归属关系(主负责 / 协办),支局长统一管理分配
- 支持批量导入:从存量收入清单 Excel 导入客户和归属关系
- 客户查重:建客户时自动提示疑似重复,支局长定期合并
- **归属转移**:客户经理离职时,支局长将客户批量转移给新同事,历史拜访记录完整保留在原客户经理名下
### 五、数据导入导出
- **导入**:上传旧周报 Excel → 系统解析 sheet → 预览匹配字段 → 确认导入;同一天同一人同一客户自动跳过不重复
- **导出**:支局长点击「导出本周周报」,生成与原 Excel 模板格式完全一致的四 sheet .xlsx 文件
## 企业微信集成
### 工作台菜单
| 菜单名称 | 跳转目标 |
|---------|---------|
| 今日拜访 | 移动端填报页 |
| 本周周报 | 支局长汇总视图 |
| 客户查询 | 客户档案搜索页 |
### 登录流程
1. 用户从企微菜单进入,前端拿企微 `code` 换取 `userid`
2. 服务端用 `userid` 查找已绑定的 Casdoor 账号
3. 已绑定:直接签发 JWT,用户无感进入系统
4. 未绑定:引导去 Casdoor 完成一次账号绑定,之后永久生效
### 消息推送
| 场景 | 方式 | 触发 |
|------|------|------|
| 每日填报提醒 | 应用消息 → 未填人员 | 每日 18:00 自动 |
| 手动催办 | 支局长选人 → 发送应用消息 | 手动 |
| 支局长公告 | 编辑公告 → 发应用消息 → 全员 | 手动 |
### 后续扩展(首期不做)
- 企微聊天侧边栏:在跟客户的聊天窗口右侧弹出拜访记录入口,自动带入客户信息
## 部署说明
1. FastAPI 后端部署于本地服务器,通过内网访问 PostgreSQL 和 MinIO
2. API 端口通过公网映射暴露给云服务器上的前端
3. Vue 前端部署于云服务器 nginxHTTPS 访问
4. 开发阶段前后端均在本地运行,联调结构与生产一致
5. Casdoor、PostgreSQL、MinIO、企业微信应用均为已有基础设施,本系统作为新接入方