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>
8.5 KiB
8.5 KiB
X-Server Mobile 企业工具系统
项目概述
一个基于飞书的企业内部H5移动工具平台,采用多租户架构,支持审批流程引擎和多种业务应用。
技术栈:
- 前端:React 18 + TypeScript + Vite + Ant Design Mobile
- 后端:PHP 8.5 + Webman 2.x + MySQL + Redis
- 部署:Docker + OpenResty + frpc (开发环境)
支持语言:
- 🇨🇳 简体中文 (zh)
- 🇬🇧 English (en)
- 🇷🇺 Русский (ru)
- 🇪🇸 Español (es)
- 🇫🇷 Français (fr)
国际化 (i18n)
前端国际化
位置: frontend/src/i18n/
使用方式:
import { useTranslation } from 'react-i18next'
function MyComponent() {
const { t } = useTranslation()
return <div>{t('common.confirm')}</div>
}
切换语言:
import { showLanguageSwitcher } from '@/components/LanguageSwitcher'
// 显示语言选择弹窗
showLanguageSwitcher()
语言存储: 浏览器 localStorage,键名为 i18nextLng
后端国际化
位置: backend/lang/
使用方式:
use App\Util\Lang;
// 获取翻译
$message = Lang::get('common.confirm');
// 带参数的翻译
$message = Lang::get('approval.status', ['status' => 'pending']);
// 检查翻译是否存在
if (Lang::has('common.submit')) {
// ...
}
设置语言:
// 从请求检测语言
$locale = Lang::detectFromRequest();
Lang::setLocale($locale);
项目关键特性
1. 多租户架构
- 用户全局唯一,关联多个公司
- 租户切换功能
- 公司级数据隔离
2. 审批流程引擎
支持节点类型:
- 单人审批 (single_approve)
- 会签 (and_sign) - 所有人通过
- 或签 (or_sign) - 任一人通过
- 通知节点 (notify)
审批状态:
- pending: 待审批
- approved: 已通过
- rejected: 已拒绝
- cancelled: 已撤销
关键文件:
backend/app/Service/ApprovalService.php- 审批核心逻辑backend/app/Model/ApprovalOrder.php- 审批单模型frontend/src/modules/approval/- 前端审批模块
3. 飞书集成
飞书免登:
- 回调地址:
/api/v1/auth/feishu-login - 配置项:
FEISHU_APP_ID- 飞书应用 IDFEISHU_APP_SECRET- 飞书应用密钥FEISHU_ENCRYPT_KEY- 加密密钥FEISHU_VERIFICATION_TOKEN- 验证令牌
4. 数据库设计
核心表:
users- 用户表(全局唯一)companies- 公司表user_company- 用户公司关联表approval_flows- 审批流程定义approval_nodes- 审批节点approval_orders- 审批单approval_records- 审批记录business_trips- 出差申请business_trip_items- 出差明细
目录结构
x-server-mobile/
├── frontend/ # React 前端
│ ├── src/
│ │ ├── i18n/ # 国际化配置
│ │ │ ├── locales/ # 翻译文件
│ │ │ └── index.ts
│ │ ├── components/ # 通用组件
│ │ │ ├── layout/ # 布局组件
│ │ │ └── LanguageSwitcher/
│ │ ├── modules/ # 业务模块
│ │ │ └── approval/ # 审批模块
│ │ ├── pages/ # 页面组件
│ │ ├── stores/ # 状态管理
│ │ ├── router/ # 路由配置
│ │ └── utils/ # 工具函数
│ └── package.json
├── backend/ # PHP 后端
│ ├── app/
│ │ ├── Controller/ # 控制器
│ │ ├── Model/ # 数据模型
│ │ ├── Service/ # 业务逻辑
│ │ ├── Util/ # 工具类
│ │ │ ├── Lang.php # 国际化工具
│ │ │ └── Db.php # 数据库连接
│ │ └── Middleware/ # 中间件
│ ├── config/ # 配置文件
│ ├── lang/ # 语言文件
│ ├── database/migrations/ # 数据库迁移
│ ├── composer.json
│ └── Dockerfile
├── docker-compose.yml # Docker 编排
├── nginx/ # OpenResty 配置
├── frpc/ # frpc 配置
└── IMPLEMENTATION_PLAN.md # 实现计划
开发环境设置
端口分配
| 服务 | 端口 |
|---|---|
| Frontend (Vite) | 5173 |
| Backend (Webman) | 8787 |
| OpenResty | 8080 |
| MySQL | 3306 |
| Redis | 6379 |
环境变量
前端 (frontend/.env):
VITE_API_BASE_URL=http://localhost:8787/api/v1
后端 (backend/.env):
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=x_server_mobile
DB_USERNAME=root
DB_PASSWORD=mysql_xEsdPa
REDIS_HOST=redis
REDIS_PORT=6379
APP_DEBUG=true
# 飞书配置
FEISHU_APP_ID=cli_xxxxxxxxxxxxx
FEISHU_APP_SECRET=xxxxxxxxxxxxxxxxxxxx
FEISHU_ENCRYPT_KEY=xxxxxxxxxxxxxxxxxxxx
FEISHU_VERIFICATION_TOKEN=xxxxxxxxxxxxxxxxxxxx
反向代理配置(开发环境)
frpc 配置: frpc/frpc-dev.ini
[common]
server_addr = your-frp-server.com
server_port = 7000
token = your-frp-token
[x-server-api-dev]
type = http
local_ip = 127.0.0.1
local_port = 8080
custom_domains = api-dev.x-server.your-domain.com
OpenResty 配置: nginx/x-server-api.conf
server {
listen 8080;
server_name api.x-server.local;
location /api/ {
proxy_pass http://127.0.0.1:8787/api/;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,X-Tenant-Key';
}
}
API 接口
认证接口
POST /api/v1/auth/login- 用户名密码登录POST /api/v1/auth/feishu-login- 飞书免登
用户接口
GET /api/v1/user/info- 获取用户信息GET /api/v1/user/menu- 获取用户菜单GET /api/v1/user/companies- 获取公司列表POST /api/v1/user/switch-company- 切换公司
审批接口
GET /api/v1/approval/list- 审批列表GET /api/v1/approval/detail/{id}- 审批详情POST /api/v1/approval/submit- 提交审批POST /api/v1/approval/approve/{id}- 审批通过POST /api/v1/approval/reject/{id}- 审批拒绝POST /api/v1/approval/cancel/{id}- 撤销申请
出差接口
GET /api/v1/business-trip/list- 出差列表GET /api/v1/business-trip/detail/{id}- 出差详情POST /api/v1/business-trip/apply- 申请出差PUT /api/v1/business-trip/{id}- 更新申请
开发指南
前端开发
cd frontend
npm install # 安装依赖
npm run dev # 启动开发服务器
npm run build # 构建生产版本
后端开发
cd backend
composer install # 安装依赖
php start.php start # 启动 Webman
php start.php stop # 停止 Webman
Docker 开发
# 启动所有服务
docker compose up -d
# 仅启动后端
docker compose up -d backend
# 查看日志
docker logs x-server-backend -f
# 重启服务
docker compose restart backend
常见问题
Q: 如何添加新的翻译文本?
前端: 在 frontend/src/i18n/locales/ 对应语言的 JSON 文件中添加
{
"myModule": {
"myKey": "翻译文本"
}
}
后端: 在 backend/lang/ 对应语言的 PHP 文件中添加
return [
'myModule' => [
'myKey' => '翻译文本',
],
];
Q: 如何添加新的应用模块?
- 在
frontend/src/pages/创建新页面 - 在
frontend/src/router/index.tsx添加路由 - 在
backend/app/Controller/创建控制器 - 在
backend/config/route.php添加 API 路由
Q: 数据库连接失败怎么办?
- 检查 MySQL 容器是否运行:
docker ps | grep mysql - 检查数据库配置:
backend/.env - 检查网络连接:
docker network ls | grep 1panel-network
Q: 前端页面白屏?
- 检查浏览器控制台错误
- 检查 React 版本:确保是 18.3.1
- 检查路由配置
- 尝试清除缓存:
rm -rf frontend/node_modules/.vite
安全建议
- 生产环境务必使用 HTTPS
- 定期更新依赖包
- 配置防火墙规则
- 使用强密码
- 定期备份数据库
- 不要在代码中硬编码敏感信息
更新日志
2024-02-24
- ✅ 升级 PHP 到 8.5
- ✅ 添加 5 语言国际化支持
- ✅ 配置 Docker 开发环境
- ✅ 实现审批流程引擎基础框架
- ✅ 完成前端基础页面和路由