4ceb5eac7e
文件结构优化: - docs/ 归档所有项目文档(PROJECT.md, PROJECT_ISSUES.md 等) - deploy/ 归档所有部署相关文件(docker-compose.prod.yml, nginx 配置等) - scripts/ 归档脚本文件(deploy.sh, rollback.sh) - tests/ 归档测试文件(test_data.php) 更新引用路径: - CLAUDE.md 更新文档路径引用 - 部署文档更新配置文件路径引用 清理文件: - 移除非必要的测试文件(TestController, 测试脚本等) - 移除重复/错误的目录 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
20 KiB
20 KiB
企业内部工具系统 - 实现计划
项目概述
开发一个企业内部工具系统平台,以出差审批为首个功能模块,后续可持续扩展新功能。系统主要支持移动 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 认证机制 |
多租户架构设计
核心概念:
- 系统不按公司隔离用户,用户全局唯一
- 用户关联所属公司,用于选择对应飞书应用配置
- 审批流程跨公司,只识别人员
- 飞书仅提供:系统入口 + 人员识别鉴权
数据模型:
-- 公司表(飞书应用配置)
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. 通用审批模块设计(独立工具)
设计理念:审批模块作为独立的通用工具,与具体业务解耦,支持多样化的审批场景
核心特性:
- ✅ 业务无关:不绑定特定业务表单和流程
- ✅ 流程灵活:支持单级、多级、会签、或签、抄送等任意组合
- ✅ 动态配置:审批流程可动态配置和调整
- ✅ 易于集成:任何业务都可快速接入审批模块
核心数据模型:
// 审批流程节点类型
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 # 状态计算
业务接入示例(出差审批):
// 业务模块只需要调用审批模块的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. 飞书集成(多应用架构)
集成要点:
后端 - 多飞书应用管理
// 飞书应用管理器
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 封装
// 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. 返回登录信息
实施步骤
阶段一:项目初始化
前端:
- 初始化 Vite + React + TypeScript 项目
- 安装 Ant Design 及相关依赖
- 配置路由、状态管理、请求库(axios + React Query)
- 配置 Tailwind CSS
后端:
- 安装 Webman 框架
- 配置 MySQL、Redis 连接
- 配置 JWT 认证
- 设置 CORS 中间件
- 创建多租户数据表(company, user, user_feishu_binding)
阶段二:工具台框架(H5)
前端:
- 实现 MobileLayout 移动端布局组件
- 实现 TabBar 底部导航栏
- 实现 Header 组件
- 创建工具台首页 Dashboard(H5 适配)
- 配置 rem 移动端适配
后端:
- 实现 /auth/login 登录接口
- 实现 /auth/feishu-login 飞书免登(多应用识别)
- 实现 /user/info 用户信息接口
- 实现 /user/menu 菜单权限接口
- 实现 FeishuAppManager 服务(多应用配置管理)
- 实现 CompanyResolveMiddleware 中间件
阶段三:独立审批模块(通用工具)
前端:
- 创建
src/modules/approval/独立模块目录 - 定义审批相关 TypeScript 类型(业务无关)
- 实现 ApprovalFlow 流程可视化组件
- 实现 ApprovalDetail 详情页(通用)
- 实现 ApprovalList 列表页(通用)
- 实现 ApprovalAction 操作组件
- 封装审批 Hooks(useApprovalSubmit, useApprovalAction)
- 提供业务接入示例
后端:
- 设计审批流程数据表(approval_flow, approval_node)
- 设计审批单数据表(approval_order, approval_record)
- 实现审批服务层逻辑(单级、多级、会签、或签)
- 确保业务无关性,通过 businessType + businessId 关联业务
- 实现审批相关 API 接口
阶段四:出差审批业务(作为审批模块的使用示例)
前端:
- 创建出差申请表单页面
- 调用审批模块的 useApprovalSubmit Hook
- 创建出差审批列表(复用审批模块组件)
- 创建出差审批详情(复用审批模块组件 + 业务表单展示)
后端:
- 设计出差数据表(business_trip, business_trip_itinerary)
- 实现出差业务逻辑(与审批解耦)
- 实现出差相关 API 接口
- 配置出差审批的默认流程模板
阶段五:飞书集成与 H5 适配(多应用架构)
前端:
- 集成飞书 JSAPI SDK
- 实现飞书免登逻辑(获取 tenant_key)
- H5 移动端样式优化
- 配置 pxtorem(750px 设计稿适配)
- 安全区域适配(刘海屏、底部横条)
- 集成 VConsole 调试工具
后端:
- 实现 FeishuService(支持多应用配置)
- 实现飞书应用配置管理接口(增删改查)
- 实现用户切换公司功能
- 实现飞书消息推送(根据用户所属公司推送)
待确认问题
- 飞书应用配置:是否有飞书应用的 App ID、App Secret?
- 权限设计:是否需要 RBAC 权限系统?
- 数据 Mock:开发阶段是否需要 Mock 数据?
- 部署环境:开发/测试/生产环境配置?
关键文件清单
前端核心文件(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)
- 运行项目:
npm run dev确保项目启动 - 路由测试:访问各个页面确保路由正常
- 审批模块测试:验证审批组件的通用性和可复用性
- H5 适配测试:
- 测试不同屏幕尺寸(375px - 768px)
- 测试刘海屏和底部横条适配
- 测试触摸手势交互
- 飞书环境测试:
- 在飞书中测试免登
- 在飞书中测试 H5 适配
- 测试多公司应用切换
- 真机测试:在真实移动设备上测试
后端验证
- 启动 Webman:
php start.php start确保服务启动 - API 测试:使用 Postman/Apifox 测试各接口
- 数据库测试:验证数据表创建和 CRUD 操作
- 认证测试:验证 JWT 认证流程
- 多租户测试:
- 测试多公司飞书应用配置
- 测试跨公司审批流程
- 飞书集成测试:验证飞书免登和消息推送