Files

602 lines
20 KiB
Markdown
Raw Permalink Normal View History

# 企业内部工具系统 - 实现计划
## 项目概述
开发一个企业内部工具系统平台,以出差审批为首个功能模块,后续可持续扩展新功能。系统主要支持移动 H5,嵌入飞书应用中使用。
### 核心目标
- **H5 移动端优先**:专注于移动端体验,PC 端后期扩展
- 从工具台层面设计可扩展的页面结构
- **审批模块作为独立通用工具**:支持多样化审批场景,业务可复用
- 良好的飞书集成能力(多公司、多应用架构)
---
## 技术方案
### 技术架构
#### 前端技术栈(H5 移动端)
| 技术 | 用途 | 说明 |
|------|------|------|
| React 18 | 前端框架 | 配合 TypeScript |
| Ant Design Mobile | UI 组件库 | 移动端组件库 |
| Vant | 补充组件 | 必要时补充使用 |
| Vite | 构建工具 | 快速开发体验 |
| React Router | 路由管理 | 支持多页面应用 |
| Zustand / Jotai | 状态管理 | 轻量级方案 |
| React Query | 数据请求 | 服务端状态管理 |
| PostCSS + pxtorem | 移动端适配 | rem 转换 |
| VConsole | 调试工具 | 移动端调试 |
#### 后端技术栈
| 技术 | 用途 | 说明 |
|------|------|------|
| Webman | PHP 框架 | 高性能常驻内存框架 |
| MySQL | 数据库 | 关系型数据库 |
| Redis | 缓存 | 会话、缓存存储 |
| JWT | 认证 | Token 认证机制 |
### 多租户架构设计
**核心概念**:
- 系统**不按公司隔离用户**,用户全局唯一
- 用户关联所属公司,用于选择对应飞书应用配置
- 审批流程跨公司,只识别人员
- 飞书仅提供:系统入口 + 人员识别鉴权
**数据模型**:
```sql
-- 公司表(飞书应用配置)
CREATE TABLE company (
id BIGINT PRIMARY KEY,
name VARCHAR(100),
feishu_app_id VARCHAR(100),
feishu_app_secret VARCHAR(255),
feishu_tenant_key VARCHAR(100),
status TINYINT DEFAULT 1
);
-- 用户表(全局用户)
CREATE TABLE user (
id BIGINT PRIMARY KEY,
company_id BIGINT, -- 所属公司
feishu_user_id VARCHAR(100), -- 飞书用户ID
feishu_union_id VARCHAR(100),-- 飞书UnionID(跨应用唯一)
name VARCHAR(50),
email VARCHAR(100),
phone VARCHAR(20),
avatar VARCHAR(255),
status TINYINT DEFAULT 1
);
-- 用户与飞书应用关联(支持用户切换不同公司应用)
CREATE TABLE user_feishu_binding (
id BIGINT PRIMARY KEY,
user_id BIGINT,
company_id BIGINT,
feishu_open_id VARCHAR(100),
created_at TIMESTAMP
);
```
### 项目目录结构(前后端分离)
```
x-server-mobile/ # 项目根目录
├── frontend/ # 前端项目(React + Vite)
│ ├── src/
│ │ ├── components/ # 通用组件
│ │ │ ├── approval/ # 审批组件(可复用)
│ │ │ ├── layout/ # 布局组件
│ │ │ └── common/ # 通用组件
│ │ ├── pages/ # 页面
│ │ │ ├── dashboard/ # 工具台首页
│ │ │ ├── business-trip/ # 出差审批
│ │ │ └── profile/ # 个人中心
│ │ ├── hooks/ # 自定义 Hooks
│ │ ├── services/ # API 服务
│ │ ├── stores/ # 状态管理
│ │ ├── utils/ # 工具函数
│ │ ├── types/ # TypeScript 类型
│ │ └── config/ # 配置文件
│ ├── public/
│ ├── package.json
│ └── vite.config.ts
│
└── backend/ # 后端项目(Webman)
├── app/
│ ├── controller/
│ ├── model/
│ ├── service/
│ ├── middleware/
│ └── util/
├── config/
├── routes/
├── support/
├── composer.json
└── start.php
```
### 后端项目结构(Webman)
```
backend/
├── app/
│ ├── controller/
│ │ ├── ApprovalController.php # 审批控制器
│ │ ├── BusinessTripController.php # 出差审批控制器
│ │ ├── UserController.php # 用户控制器
│ │ ├── CompanyController.php # 公司管理控制器
│ │ └── BaseController.php # 基础控制器
│ ├── model/
│ │ ├── Approval.php # 审批模型
│ │ ├── ApprovalNode.php # 审批节点模型
│ │ ├── BusinessTrip.php # 出差模型
│ │ ├── User.php # 用户模型
│ │ ├── Company.php # 公司模型
│ │ └── UserFeishuBinding.php # 用户飞书绑定模型
│ ├── service/
│ │ ├── ApprovalService.php # 审批服务
│ │ ├── FeishuService.php # 飞书服务(多应用)
│ │ ├── FeishuAppManager.php # 飞书应用配置管理
│ │ ├── UserService.php # 用户服务
│ │ └── CompanyService.php # 公司服务
│ ├── middleware/
│ │ ├── AuthMiddleware.php # 认证中间件
│ │ ├── CompanyResolveMiddleware.php # 公司识别中间件
│ │ └── CorsMiddleware.php # 跨域中间件
│ └── util/
│ ├── JwtUtil.php # JWT工具
│ └── Response.php # 响应封装
├── config/
│ ├── route.php # 路由配置
│ ├── database.php # 数据库配置
│ ├── redis.php # Redis配置
│ └── feishu.php # 飞书应用配置模板
├── routes/
│ └── api.php # API路由定义
└── support/
└── Bootstrap.php # 启动文件
```
### API 接口设计
#### 通用 API 规范
```
基础URL: /api/v1
响应格式:
{
"code": 0, // 0表示成功
"message": "success",
"data": {}
}
```
#### 审批相关接口
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /approval/list | 获取审批列表 |
| GET | /approval/detail/:id | 获取审批详情 |
| POST | /approval/submit | 提交审批申请 |
| POST | /approval/approve/:id | 审批通过 |
| POST | /approval/reject/:id | 审批拒绝 |
| POST | /approval/cancel/:id | 撤销申请 |
| GET | /approval/flow/:type | 获取审批流程配置 |
#### 出差审批接口
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /business-trip/list | 获取出差列表 |
| GET | /business-trip/detail/:id | 获取出差详情 |
| POST | /business-trip/apply | 提交出差申请 |
| PUT | /business-trip/:id | 更新出差申请(草稿状态) |
#### 用户认证接口(多飞书应用)
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /auth/login | 用户登录 |
| POST | /auth/feishu-login | 飞书免登(自动识别公司应用) |
| GET | /user/info | 获取用户信息 |
| GET | /user/menu | 获取用户菜单权限 |
| GET | /user/companies | 获取用户可切换的公司列表 |
| POST | /user/switch-company | 切换当前公司 |
#### 飞书应用管理接口(管理端)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /admin/company/list | 获取公司列表 |
| POST | /admin/company/add | 添加公司飞书应用配置 |
| PUT | /admin/company/:id | 更新公司飞书配置 |
| DELETE | /admin/company/:id | 删除公司配置 |
---
## 功能模块设计
### 1. 工具台架构(Dashboard - H5 移动端)
**设计理念**:工具台作为统一入口,支持模块化扩展,专注于移动端体验
```
工具台首页(H5)
├── 顶部导航栏
│ ├── Logo + 系统名称
│ ├── 搜索框(全局搜索)
│ ├── 通知图标
│ └── 用户头像
├── 主内容区
│ ├── 待办事项卡片(横向滚动)
│ ├── 快捷入口(九宫格/宫格)
│ ├── 数据统计卡片
│ └── 最新动态列表
└── 底部导航栏(TabBar)
├── 首页
├── 应用(宫格展开所有工具)
├── 消息
└── 我的
```
**移动端适配要点**:
- 使用 TabBar 替代侧边栏(符合移动端习惯)
- 750px 设计稿 → rem 自适应转换
- 触摸手势支持(下拉刷新、上拉加载)
- 安全区域适配(刘海屏、底部横条)
**关键文件**:
- `src/pages/dashboard/index.tsx` - 工具台主页
- `src/components/layout/MobileLayout.tsx` - 移动端主布局
- `src/components/layout/TabBar.tsx` - 底部导航栏
- `src/components/layout/Header.tsx` - 顶部栏
### 2. 通用审批模块设计(独立工具)
**设计理念**:审批模块作为独立的通用工具,与具体业务解耦,支持多样化的审批场景
**核心特性**:
- ✅ 业务无关:不绑定特定业务表单和流程
- ✅ 流程灵活:支持单级、多级、会签、或签、抄送等任意组合
- ✅ 动态配置:审批流程可动态配置和调整
- ✅ 易于集成:任何业务都可快速接入审批模块
**核心数据模型**:
```typescript
// 审批流程节点类型
enum ApprovalNodeType {
APPROVER = 'approver', // 审批人(单人)
AND_APPROVE = 'and_approve', // 会签(需所有人通过)
OR_APPROVE = 'or_approve', // 或签(任一人通过)
NOTIFY = 'notify' // 抄送(通知用)
}
// 审批单状态
enum ApprovalStatus {
DRAFT = 'draft', // 草稿
PENDING = 'pending', // 审批中
APPROVED = 'approved', // 已通过
REJECTED = 'rejected', // 已拒绝
CANCELLED = 'cancelled' // 已撤销
}
// 审批流程配置(业务无关)
interface ApprovalFlow {
id: string;
businessType: string; // 业务类型标识(如:business-trip, purchase)
name: string;
nodes: ApprovalNode[]; // 流程节点
}
// 审批节点
interface ApprovalNode {
id: string;
type: ApprovalNodeType;
approvers: User[]; // 审批人列表
order: number; // 节点顺序
conditions?: any; // 条件判断(可选,用于条件分支)
}
// 审批单(业务通用)
interface ApprovalOrder {
id: string;
businessType: string; // 业务类型
businessId: string; // 业务单据ID
title: string; // 审批标题
applicant: User; // 申请人
status: ApprovalStatus;
currentNodes: string[]; // 当前待审批节点ID
flowId: string; // 使用的流程ID
formData: any; // 业务表单数据(JSON存储)
attachments: Attachment[]; // 附件
timeline: ApprovalTimeline[]; // 审批轨迹
}
```
**审批模块架构**:
```
src/modules/approval/ # 审批模块(独立)
├── components/ # UI组件
│ ├── ApprovalFlow.tsx # 流程可视化
│ ├── ApprovalDetail.tsx # 审批详情
│ ├── ApprovalList.tsx # 审批列表
│ └── ApprovalAction.tsx # 审批操作
├── hooks/ # 自定义Hooks
│ ├── useApprovalSubmit.ts # 提交审批
│ ├── useApprovalAction.ts # 审批操作
│ └── useApprovalList.ts # 获取列表
├── services/ # API服务
│ └── approval.ts
├── types/ # 类型定义
│ └── index.ts
└── utils/ # 工具函数
├── flowParser.ts # 流程解析
└── statusCalculator.ts # 状态计算
```
**业务接入示例(出差审批)**:
```typescript
// 业务模块只需要调用审批模块的Hook
import { useApprovalSubmit } from '@/modules/approval/hooks'
function BusinessTripApply() {
const { submitApproval } = useApprovalSubmit('business-trip')
const handleSubmit = async (formData: BusinessTripFormData) => {
// 1. 先保存业务数据
const businessTripId = await saveBusinessTrip(formData)
// 2. 提交审批(传入业务类型和业务ID)
await submitApproval({
businessId: businessTripId,
title: `出差申请 - ${formData.destination}`,
formData: formData,
flowType: 'default' // 使用的流程模板
})
}
}
```
### 3. 出差审批模块
**页面结构**:
```
出差审批
├── 申请列表页
│ ├── 我发起的
│ ├── 待我审批
│ ├── 我已审批
│ └── 抄送我的
├── 申请表单页
│ ├── 基本信息(出差事由、时间、地点)
│ ├── 行程明细
│ ├── 费用预算
│ └── 附件上传
└── 审批详情页
├── 表单内容展示
├── 流程进度可视化
├── 审批历史
└── 操作按钮
```
**关键文件**:
- `src/pages/business-trip/list.tsx` - 列表页
- `src/pages/business-trip/apply.tsx` - 申请表单
- `src/pages/business-trip/detail.tsx` - 详情页
- `src/pages/business-trip/types.ts` - 出差相关类型
### 4. 飞书集成(多应用架构)
**集成要点**:
#### 后端 - 多飞书应用管理
```php
// 飞书应用管理器
class FeishuAppManager
{
// 根据飞书租户Key获取公司配置
public function getCompanyByTenantKey(string $tenantKey): Company
{
// 从数据库查询对应的飞书应用配置
}
// 获取指定公司的飞书 access_token
public function getAccessToken(int $companyId): string
{
// 缓存 access_token,过期自动刷新
}
// 根据用户ID获取其所属公司的飞书配置
public function getUserFeishuConfig(int $userId): array
{
// 返回用户所属公司的飞书 AppID、AppSecret 等
}
}
```
#### 前端 - 飞书 SDK 封装
```typescript
// src/utils/feishu.ts
export const FeishuSDK = {
// 获取免登授权码
getAuthCode: () => { /* ... */ },
// 判断是否在飞书环境
isFeishuEnv: () => { /* ... */ },
// 获取当前租户信息(用于后端识别公司)
getTenantContext: () => {
// 从飞书容器获取 tenant_key 或其他标识
}
}
```
#### 飞书免登流程(多应用)
```
1. 用户在飞书中打开应用
2. 前端获取 auth_code 和 tenant_key
3. 调用后端 /auth/feishu-login
4. 后端根据 tenant_key 查询对应公司配置
5. 使用该公司的 AppSecret 换取用户信息
6. 生成 JWT Token(包含 user_id 和 company_id)
7. 返回登录信息
```
---
## 实施步骤
### 阶段一:项目初始化
**前端:**
1. 初始化 Vite + React + TypeScript 项目
2. 安装 Ant Design 及相关依赖
3. 配置路由、状态管理、请求库(axios + React Query)
4. 配置 Tailwind CSS
**后端:**
1. 安装 Webman 框架
2. 配置 MySQL、Redis 连接
3. 配置 JWT 认证
4. 设置 CORS 中间件
5. **创建多租户数据表(company, user, user_feishu_binding)**
### 阶段二:工具台框架(H5)
**前端:**
1. 实现 MobileLayout 移动端布局组件
2. 实现 TabBar 底部导航栏
3. 实现 Header 组件
4. 创建工具台首页 Dashboard(H5 适配)
5. 配置 rem 移动端适配
**后端:**
1. 实现 /auth/login 登录接口
2. **实现 /auth/feishu-login 飞书免登(多应用识别)**
3. 实现 /user/info 用户信息接口
4. 实现 /user/menu 菜单权限接口
5. **实现 FeishuAppManager 服务(多应用配置管理)**
6. **实现 CompanyResolveMiddleware 中间件**
### 阶段三:独立审批模块(通用工具)
**前端:**
1. 创建 `src/modules/approval/` 独立模块目录
2. 定义审批相关 TypeScript 类型(业务无关)
3. 实现 ApprovalFlow 流程可视化组件
4. 实现 ApprovalDetail 详情页(通用)
5. 实现 ApprovalList 列表页(通用)
6. 实现 ApprovalAction 操作组件
7. **封装审批 Hooks(useApprovalSubmit, useApprovalAction)**
8. **提供业务接入示例**
**后端:**
1. 设计审批流程数据表(approval_flow, approval_node)
2. 设计审批单数据表(approval_order, approval_record)
3. 实现审批服务层逻辑(单级、多级、会签、或签)
4. **确保业务无关性,通过 businessType + businessId 关联业务**
5. 实现审批相关 API 接口
### 阶段四:出差审批业务(作为审批模块的使用示例)
**前端:**
1. 创建出差申请表单页面
2. **调用审批模块的 useApprovalSubmit Hook**
3. 创建出差审批列表(复用审批模块组件)
4. 创建出差审批详情(复用审批模块组件 + 业务表单展示)
**后端:**
1. 设计出差数据表(business_trip, business_trip_itinerary)
2. 实现出差业务逻辑(与审批解耦)
3. 实现出差相关 API 接口
4. **配置出差审批的默认流程模板**
### 阶段五:飞书集成与 H5 适配(多应用架构)
**前端:**
1. 集成飞书 JSAPI SDK
2. 实现飞书免登逻辑(获取 tenant_key)
3. **H5 移动端样式优化**
4. **配置 pxtorem(750px 设计稿适配)**
5. **安全区域适配(刘海屏、底部横条)**
6. 集成 VConsole 调试工具
**后端:**
1. **实现 FeishuService(支持多应用配置)**
2. **实现飞书应用配置管理接口(增删改查)**
3. **实现用户切换公司功能**
4. **实现飞书消息推送(根据用户所属公司推送)**
---
## 待确认问题
1. **飞书应用配置**:是否有飞书应用的 App ID、App Secret?
2. **权限设计**:是否需要 RBAC 权限系统?
3. **数据 Mock**:开发阶段是否需要 Mock 数据?
4. **部署环境**:开发/测试/生产环境配置?
---
## 关键文件清单
### 前端核心文件(H5)
| 文件路径 | 说明 |
|---------|------|
| `src/App.tsx` | 应用入口 |
| `src/main.tsx` | React 挂载点 |
| `src/router/index.tsx` | 路由配置 |
| `src/components/layout/MobileLayout.tsx` | 移动端主布局 |
| `src/components/layout/TabBar.tsx` | 底部导航栏 |
| `src/components/layout/Header.tsx` | 顶部栏 |
| `src/pages/dashboard/index.tsx` | 工具台首页 |
| `src/modules/approval/` | **审批模块(独立)** |
| `src/pages/business-trip/` | 出差审批业务 |
| `src/services/api.ts` | API 基础配置 |
| `src/utils/feishu.ts` | 飞书 SDK 封装 |
| `src/config/rem.ts` | rem 转换配置 |
| `package.json` | 项目依赖 |
| `vite.config.ts` | Vite 配置 |
| `tsconfig.json` | TypeScript 配置 |
| `postcss.config.js` | PostCSS 配置(pxtorem) |
### 后端核心文件
| 文件路径 | 说明 |
|---------|------|
| `app/controller/BaseController.php` | 基础控制器 |
| `app/controller/ApprovalController.php` | 审批控制器 |
| `app/controller/BusinessTripController.php` | 出差审批控制器 |
| `app/controller/UserController.php` | 用户控制器 |
| `app/model/Approval.php` | 审批模型 |
| `app/model/ApprovalNode.php` | 审批节点模型 |
| `app/service/ApprovalService.php` | 审批服务 |
| `app/service/FeishuService.php` | 飞书服务 |
| `app/middleware/AuthMiddleware.php` | 认证中间件 |
| `config/route.php` | 路由配置 |
| `config/database.php` | 数据库配置 |
| `routes/api.php` | API 路由定义 |
---
## 验证计划
### 前端验证(H5)
1. **运行项目**:`npm run dev` 确保项目启动
2. **路由测试**:访问各个页面确保路由正常
3. **审批模块测试**:验证审批组件的通用性和可复用性
4. **H5 适配测试**:
- 测试不同屏幕尺寸(375px - 768px)
- 测试刘海屏和底部横条适配
- 测试触摸手势交互
5. **飞书环境测试**:
- 在飞书中测试免登
- 在飞书中测试 H5 适配
- 测试多公司应用切换
6. **真机测试**:在真实移动设备上测试
### 后端验证
1. **启动 Webman**:`php start.php start` 确保服务启动
2. **API 测试**:使用 Postman/Apifox 测试各接口
3. **数据库测试**:验证数据表创建和 CRUD 操作
4. **认证测试**:验证 JWT 认证流程
5. **多租户测试**:
- 测试多公司飞书应用配置
- 测试跨公司审批流程
6. **飞书集成测试**:验证飞书免登和消息推送