diff --git a/.codebuddy/skills/crmeb-complete/README.md b/.codebuddy/skills/crmeb-complete/README.md new file mode 100644 index 000000000..6f9448802 --- /dev/null +++ b/.codebuddy/skills/crmeb-complete/README.md @@ -0,0 +1,246 @@ +# CRMEB电商系统Skill包 + +## 📦 包说明 + +这是一个完整的CRMEB开源电商系统开发指南Skill包,旨在帮助开发者快速理解、上手和开发CRMEB项目。 + +## 🎯 适用人群 + +- **新手开发者**:快速了解CRMEB项目架构和开发流程 +- **后端开发者**:学习ThinkPHP 6后端开发规范 +- **前端开发者**:学习管理端和移动端开发 +- **全栈开发者**:掌握完整的电商系统开发 +- **项目经理**:了解项目结构和技术栈 + +## 📚 包含内容 + +### 主文档 + +- **[SKILL.md](./SKILL.md)** - 主Skill文件,项目概览和快速参考 + - 项目概述和架构 + - 目录结构详解 + - 核心业务模块介绍 + - 开发规范和最佳实践 + - 常用命令速查 + - 环境配置指南 + +### 参考文档 + +- **[references/quick_start.md](./references/quick_start.md)** - 快速开始指南 + - Docker一键部署 + - 手动安装步骤 + - 环境配置详解 + - 常见问题排查 + +- **[references/api_flow.md](./references/api_flow.md)** - API请求流程详解 + - API生命周期 + - 请求处理流程 + - 统一响应格式 + - 认证与授权 + - 参数验证 + - 错误处理 + - 性能优化 + +- **[references/code_style.md](./references/code_style.md)** - 代码规范 + - 命名规范 + - 代码分层规范 + - 控制器层规范 + - 服务层规范 + - DAO层规范 + - 模型层规范 + - 注释规范 + +- **[references/db_design.md](./references/db_design.md)** - 数据库设计规范 + - 表命名规范 + - 字段命名规范 + - 索引设计 + - 关联关系设计 + - 数据迁移 + +- **[references/system_config.md](./references/system_config.md)** - 系统配置详解 + - 应用配置 + - 数据库配置 + - Redis配置 + - 队列配置 + - Workerman配置 + - 第三方服务配置 + +- **[references/mcp_integration.md](./references/mcp_integration.md)** - MCP接口集成 + - MCP接口说明 + - 调用方式 + - 示例代码 + +## 🚀 快速开始 + +### 方式一:使用Docker(推荐) + +```bash +# 1. 克隆项目 +git clone https://gitee.com/ZhongBangKeJi/CRMEB.git +cd CRMEB + +# 2. 启动服务 +docker-compose up -d + +# 3. 访问系统 +# 后台:http://localhost:8011/admin (admin/crmeb.com) +# 前台:http://localhost:8011 +``` + +详细步骤请查看:[references/quick_start.md](./references/quick_start.md) + +### 方式二:手动安装 + +```bash +# 1. 克隆项目 +git clone https://gitee.com/ZhongBangKeJi/CRMEB.git +cd CRMEB + +# 2. 安装依赖 +cd crmeb && composer install +cd ../template/admin && npm install +cd ../uni-app && npm install + +# 3. 配置环境 +cp crmeb/.env.example crmeb/.env +# 编辑.env文件,配置数据库和Redis + +# 4. 导入数据库 +mysql -u root -p crmeb < database.sql + +# 5. 启动服务 +# 后端:配置Nginx/Apache,指向crmeb/public +# 队列:php think queue:listen --queue +# 前端:npm run dev/build +``` + +详细步骤请查看:[references/quick_start.md](./references/quick_start.md) + +## 📖 学习路径 + +### 阶段一:项目了解(10分钟) + +1. 阅读 [SKILL.md](./SKILL.md) 的"项目概述"章节 +2. 了解技术架构和核心特点 +3. 查看目录结构 +4. 熟悉核心业务流程 + +### 阶段二:环境搭建(30分钟) + +1. 按照 [references/quick_start.md](./references/quick_start.md) 部署项目 +2. 熟悉后台管理功能 +3. 体验前端商城流程 +4. 验证各项功能是否正常 + +### 阶段三:后端开发(2-3小时) + +1. 阅读 [SKILL.md](./SKILL.md) 的"核心业务模块"章节 +2. 查看 [references/api_flow.md](./references/api_flow.md) 了解API开发 +3. 学习代码分层规范:[references/code_style.md](./references/code_style.md) +4. 尝试使用代码生成器创建CRUD +5. 开发一个简单的功能模块 + +### 阶段四:前端开发(管理端) + +1. 阅读管理端前端文档 +2. 了解Vue 2.x + Element UI开发 +3. 学习API调用方式 +4. 开发一个管理端页面 + +### 阶段五:移动端开发 + +1. 阅读UniApp开发文档 +2. 了解跨端开发特性 +3. 学习移动端API调用 +4. 开发或修改一个页面 + +### 阶段六:高级特性 + +1. 学习队列使用 +2. 了解定时任务 +3. 掌握WebSocket实时通信 +4. 阅读MCP接口文档 +5. 优化系统性能 + +## 🔧 开发工具 + +### 后端开发 +- **IDE**: PhpStorm / VS Code +- **API测试**: Postman / Apifox +- **数据库**: Navicat / phpMyAdmin +- **Redis**: Redis Desktop Manager + +### 前端开发 +- **IDE**: VS Code / WebStorm +- **浏览器**: Chrome(推荐) +- **调试工具**: Vue DevTools + +### 移动端开发 +- **IDE**: HBuilderX(官方推荐) +- **模拟器**: 微信开发者工具 / 真机调试 + +## 📌 开发建议 + +### 1. 使用代码生成器 + +在后台管理中,使用"代码生成器"可以快速生成CRUD代码,大大提高开发效率。 + +### 2. 遵循开发规范 + +务必遵循项目开发规范:[references/code_style.md](./references/code_style.md) + +### 3. 使用事件系统 + +合理使用系统事件,解耦业务逻辑,提高代码可维护性。 + +### 4. 编写注释 + +为复杂业务逻辑编写清晰的注释,方便团队协作。 + +### 5. 使用队列 + +将耗时操作(发送短信、生成海报等)放入队列,提高响应速度。 + +### 6. 注意安全性 + +- 验证所有用户输入 +- 使用参数绑定防止SQL注入 +- 敏感数据加密存储 +- 严格权限控制 + +## 🤝 贡献指南 + +如果你在使用过程中发现文档有误或需要补充,欢迎提交PR或Issue。 + +**贡献方式:** +1. Fork本仓库 +2. 修改或补充文档 +3. 提交Pull Request + +## 📞 获取帮助 + +- **技术社区**: https://www.crmeb.com/ask/thread/list/147 +- **官方文档**: https://doc.crmeb.com +- **在线客服**: https://www.crmeb.com +- **GitHub Issues**: https://gitee.com/ZhongBangKeJi/CRMEB/issues + +## 📝 更新日志 + +### v1.0.0 (2025-03-17) +- 初始版本发布 +- 包含项目概览、快速开始、API流程等核心文档 +- 完整的开发规范和最佳实践 + +## 📄 许可证 + +本项目基于 [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) 协议开源。 + +## 🙏 致谢 + +感谢CRMEB开源社区和所有贡献者。 + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-03-17 +**维护者**: CRMEB开源社区 diff --git a/.codebuddy/skills/crmeb-complete/SKILL.md b/.codebuddy/skills/crmeb-complete/SKILL.md new file mode 100644 index 000000000..4ae94cf28 --- /dev/null +++ b/.codebuddy/skills/crmeb-complete/SKILL.md @@ -0,0 +1,585 @@ +--- +name: CRMEB电商系统完整开发指南 +description: 完整的CRMEB开源电商系统开发指南,包含后端API、管理端、移动端uniapp的全栈开发说明,帮助开发者快速理解和开发CRMEB项目 +version: 1.0.0 +tags: [电商, CRMEB, ThinkPHP, Vue, UniApp, 全栈开发] +--- + +# CRMEB电商系统完整开发指南 + +## 0. 项目概述 + +### 0.1 项目简介 + +CRMEB是一款高品质的开源电商系统,基于Apache-2.0协议,100%开源免费商用。系统采用前后端分离架构,支持多端覆盖(公众号、小程序、H5、APP、PC),内置20+核心营销模块。 + +**核心特点:** +- ✅ 100%开源,Apache-2.0协议,无任何隐藏费用 +- ✅ 前后端分离,ThinkPHP 6 + Vue 2.x + UniApp +- ✅ 多端覆盖,数据实时互通 +- ✅ 20+营销模块(拼团、砍价、秒杀、优惠券、直播等) +- ✅ 代码生成器,快速开发增删改查 +- ✅ 强大的权限管理系统(RBAC) +- ✅ 支持队列、定时任务、WebSocket实时通信 +- ✅ Docker一键部署 + +### 0.2 技术架构 + +**后端架构:** +- **框架**: ThinkPHP 6.x (PHP 7.1-7.4) +- **架构模式**: MVC + Service + DAO 分层架构 +- **数据库**: MySQL 5.7-8.0 (InnoDB引擎) +- **缓存**: Redis (可选) +- **消息队列**: ThinkPHP Queue + Workerman +- **实时通信**: Workerman WebSocket + +**前端架构:** +- **管理端**: Vue 2.x + Element UI + Vuex + Vue Router +- **移动端**: UniApp + uView UI (支持小程序、H5、APP) +- **PC端**: Nuxt.js (Vue SSR) + +**项目地址:** +- **官网**: https://www.crmeb.com +- **Gitee**: https://gitee.com/ZhongBangKeJi/CRMEB +- **在线体验**: http://v5.crmeb.net/admin (账号: demo, 密码: crmeb.com) + +### 0.3 快速开始 + +**Docker一键部署:** +```bash +# 启动服务 +docker-compose up -d + +# 访问地址 +# 网站: http://localhost:8011 +# MySQL: localhost:33061 (root/123456) +# Redis: localhost:63791 (123456) +``` + +**默认账号:** +- 后台管理: http://localhost:8011/admin (admin/crmeb.com) +- 移动端: http://localhost:8011 + +## 1. 目录结构 + +### 1.1 后端核心目录 (`/crmeb`) + +``` +crmeb/ +├── app/ # 应用目录 +│ ├── adminapi/ # 后台管理API +│ │ ├── controller/ # 控制器层 +│ │ ├── middleware/ # 中间件 +│ │ ├── route/ # 路由定义 +│ │ └── validate/ # 验证器 +│ ├── api/ # 移动端API +│ ├── kefuapi/ # 客服端API +│ ├── outapi/ # 外部接口API(MCP) +│ ├── dao/ # 数据访问层(180+文件) +│ ├── model/ # 数据模型层(150+文件) +│ ├── services/ # 业务服务层(230+文件) +│ │ ├── user/ # 用户服务 +│ │ ├── product/ # 商品服务 +│ │ ├── order/ # 订单服务 +│ │ ├── activity/ # 营销服务 +│ │ ├── agent/ # 分销服务 +│ │ └── system/ # 系统服务 +│ ├── jobs/ # 队列任务(30+任务) +│ ├── listener/ # 事件监听器(20+监听器) +│ └── common.php # 公共函数 +├── crmeb/ # 核心框架目录 +│ ├── basic/ # 基础类库 +│ │ ├── BaseController.php +│ │ ├── BaseServices.php +│ │ ├── BaseDao.php +│ │ └── BaseModel.php +│ └── ... +├── config/ # 配置文件 +├── public/ # Web入口 +├── runtime/ # 运行时文件 +└── .env # 环境配置 +``` + +### 1.2 前端目录 + +**管理端 (`/template/admin`):** +``` +template/admin/src/ +├── api/ # API接口定义 +├── assets/ # 静态资源 +├── components/ # 通用组件 +├── pages/ # 页面组件 +├── router/ # 路由配置 +├── store/ # Vuex状态管理 +└── utils/ # 工具函数 +``` + +**移动端 (`/template/uni-app`):** +``` +template/uni-app/ +├── pages/ # 页面目录 +│ ├── index/ # 首页 +│ ├── goods/ # 商品 +│ ├── cart/ # 购物车 +│ ├── order/ # 订单 +│ └── user/ # 用户中心 +├── components/ # 组件目录 +├── static/ # 静态资源 +├── utils/ # 工具函数 +└── api/ # API接口 +``` + +## 2. 核心业务模块 + +### 2.1 用户模块 + +**核心服务:** +- `UserServices` - 用户主服务 +- `LoginServices` - 登录服务 +- `UserBillServices` - 账单流水 +- `UserMoneyServices` - 用户余额 +- `UserLevelServices` - 用户等级 + +**数据表:** +```sql +eb_user # 用户表 +eb_user_bill # 账单表 +eb_user_extract # 提现表 +eb_user_level # 用户等级表 +``` + +**开发要点:** +- 支持多种登录方式(账号密码、手机验证码、微信授权) +- 余额变动必须记录账单 +- 支持多级会员等级 +- 标签分组实现精准营销 + +### 2.2 商品模块 + +**核心服务:** +- `StoreProductServices` - 商品主服务 +- `StoreCategoryServices` - 商品分类 +- `StoreProductAttrServices` - 商品属性 +- `StoreProductReplyServices` - 商品评价 + +**数据表:** +```sql +eb_store_product # 商品表 +eb_store_category # 分类表 +eb_store_product_attr # 属性表 +eb_store_product_reply # 评价表 +``` + +**开发要点:** +- 支持多规格SKU,自动计算价格和库存 +- 商品类型(普通、积分、预售、虚拟) +- 多级分类管理 +- 商品采集(淘宝、京东) + +### 2.3 订单模块 + +**核心服务:** +- `StoreOrderServices` - 订单主服务 +- `StoreOrderCreateServices` - 订单创建 +- `StoreOrderDeliveryServices` - 订单发货 +- `StoreOrderRefundServices` - 订单退款 +- `StoreCartServices` - 购物车 + +**数据表:** +```sql +eb_store_order # 订单表 +eb_store_order_cart # 订单商品表 +eb_store_order_status # 订单状态记录表 +eb_store_cart # 购物车表 +eb_store_refund # 退款表 +``` + +**订单状态流转:** +``` +未支付 (0) → 待发货 (1) → 待收货 (2) → 已完成 (3) + ↓ ↓ +已取消 (-1) 退款中 (-2) → 已退款 (-3) +``` + +**开发要点:** +- 下单时扣减库存,取消订单恢复库存 +- 支持多种支付方式(微信、支付宝、余额) +- 定时任务自动取消未支付订单 +- 定时任务自动确认收货 +- 订单状态变更触发系统事件 + +### 2.4 支付模块 + +**核心服务:** +- `PayServices` - 支付主服务 +- `WechatPayServices` - 微信支付 +- `AlipayServices` - 支付宝支付 + +**支付方式:** +- 微信支付(JSAPI、小程序、H5、扫码) +- 支付宝支付(手机网站、扫码) +- 余额支付 +- 积分支付 + +**支付流程:** +``` +1. 创建支付订单 +2. 调用第三方支付接口 +3. 返回支付参数给客户端 +4. 客户端调起支付 +5. 支付结果异步回调 +6. 更新订单状态 +7. 触发支付成功事件 +``` + +**开发要点:** +- 支付回调必须验证签名 +- 保证幂等性,避免重复支付 +- 事务处理多个业务(订单、账单、通知等) +- 支持原路退款 + +### 2.5 营销模块 + +**2.5.1 优惠券** +- 支持通用券、品类券、商品券、新人券 +- 可设置使用门槛、有效期、适用商品 +- 下单时自动计算优惠金额 +- 定时任务自动清理过期优惠券 + +**2.5.2 拼团** +- 创建拼团活动(拼团价、成团人数、时长) +- 用户发起拼团或参与拼团 +- 拼团成功后创建订单 +- 拼团失败自动退款 + +**2.5.3 砍价** +- 发起砍价活动,分享好友帮砍 +- 每个好友可帮砍一次 +- 达到底价或帮砍人数后可购买 +- 超时未达成则砍价失败 + +**2.5.4 秒杀** +- 设置秒杀时间和库存 +- 使用Redis缓存库存,防止超卖 +- 限制用户购买数量 +- 未支付订单自动恢复库存 + +**2.5.5 积分系统** +- 购物返积分、签到积分、任务积分 +- 积分兑换商品或抵扣现金 +- 设置积分有效期 +- 定时任务清理过期积分 + +### 2.6 分销模块 + +**核心服务:** +- `AgentLevelServices` - 分销等级 +- `AgentManageServices` - 分销员管理 +- `DivisionServices` - 事业部管理 + +**分销流程:** +``` +1. 用户申请成为分销员 +2. 管理员审核通过 +3. 分销员分享推广链接 +4. 新用户注册成为下级 +5. 下级用户下单 +6. 计算分销佣金 +7. 佣金结算到余额 +``` + +**开发要点:** +- 支持多级分销(一级、二级、三级) +- 分销等级自动升级(完成任务) +- 佣金冻结期(防止退款) +- 佣金结算到分销员余额 + +### 2.7 系统管理模块 + +**2.7.1 代码生成器** +- 快速生成CRUD代码 +- 支持自定义字段类型、搜索类型、表单类型 +- 自动生成前后端代码 +- 自动生成菜单和权限 + +**2.7.2 系统配置** +- 后台动态配置系统参数 +- 支持多种配置类型 +- 配置分组管理 +- 配置缓存优化 + +**2.7.3 系统事件** +- 内置30+事件锚点 +- 支持动态添加监听器 +- 事件驱动解耦业务 +- 支持异步事件处理 + +**核心事件:** +- `user.register` - 用户注册 +- `user.login` - 用户登录 +- `order.create` - 订单创建 +- `order.pay_success` - 订单支付成功 +- `pay.success` - 支付成功 + +**2.7.4 定时任务** +- 基于Workerman的定时任务 +- 支持Cron表达式 +- 后台动态配置 + +**系统预置任务:** +1. 自动取消未支付订单(30分钟) +2. 自动确认收货(每天) +3. 自动好评(每天) +4. 自动关闭拼团(10分钟) +5. 自动关闭砍价(10分钟) +6. 积分到期处理(每天) +7. 优惠券过期处理(每天) +8. 分销佣金结算(每天) + +## 3. 开发规范 + +### 3.1 命名规范 + +**类命名:** +- 控制器:模块名 + Controller,如 `UserController` +- 服务:模块名 + Services,如 `UserServices` +- DAO:模块名 + Dao,如 `UserDao` +- 模型:模块名,如 `User` +- 验证器:模块名 + Validate,如 `UserValidate` + +**方法命名:** +- 控制器:小写+下划线,如 `get_list`, `save_data` +- 服务:驼峰法,如 `getUserList`, `saveData` +- DAO:数据库操作相关,如 `selectList`, `insert` + +### 3.2 代码分层规范 + +**控制器层:** +- 接收和验证请求参数 +- 调用服务层处理业务 +- 返回统一的JSON响应 +- 不直接操作数据库 + +**服务层:** +- 实现核心业务逻辑 +- 数据验证和权限验证 +- 调用DAO层操作数据库 +- 事务管理 + +**DAO层:** +- 封装数据库查询逻辑 +- 构建查询条件 +- 防止SQL注入 +- 不提供业务逻辑 + +### 3.3 API响应格式 + +**成功响应:** +```json +{ + "code": 200, + "msg": "操作成功", + "data": {} +} +``` + +**分页响应:** +```json +{ + "code": 200, + "msg": "操作成功", + "data": { + "list": [], + "count": 100, + "page": 1, + "limit": 10 + } +} +``` + +**错误响应:** +```json +{ + "code": 400, + "msg": "错误信息", + "data": null +} +``` + +## 4. 常用命令 + +### 4.1 ThinkPHP命令 +```bash +php think # 查看所有命令 +php think make:controller # 创建控制器 +php think make:model # 创建模型 +php think make:middleware # 创建中间件 +php think make:validate # 创建验证器 +php think clear # 清除缓存 +php think run # 启动内置服务器 +``` + +### 4.2 队列命令 +```bash +php think queue:listen # 监听队列 +php think queue:work # 处理队列任务 +php think queue:restart # 重启队列 +php think queue:fail # 查看失败任务 +``` + +### 4.3 定时任务命令 +```bash +php think timer start # 启动定时任务 +php think timer stop # 停止定时任务 +php think timer restart # 重启定时任务 +php think timer status # 查看状态 +``` + +### 4.4 Workerman命令 +```bash +php think workerman start # 启动WebSocket +php think workerman stop # 停止WebSocket +php think workerman restart # 重启WebSocket +php think workerman status # 查看状态 +``` + +## 5. 开发环境配置 + +### 5.1 环境要求 +- PHP >= 7.1 +- MySQL >= 5.7 +- Redis >= 5.0(可选) +- Node.js >= 14 +- Composer + +### 5.2 数据库配置 +```env +[DATABASE] +TYPE = mysql +HOSTNAME = 127.0.0.1 +HOSTPORT = 3306 +USERNAME = root +PASSWORD = 123456 +DATABASE = crmeb +PREFIX = eb_ +CHARSET = utf8mb4 +``` + +### 5.3 Redis配置 +```env +[CACHE] +DRIVER = redis +CACHE_PREFIX = cache_ + +[REDIS] +REDIS_HOSTNAME = 127.0.0.1 +PORT = 6379 +REDIS_PASSWORD = 123456 +SELECT = 0 +``` + +### 5.4 队列配置 +```env +[QUEUE] +QUEUE_NAME = default +``` + +## 6. 常见问题 + +### 6.1 数据库连接错误 +```bash +# 检查MySQL服务 +systemctl status mysql + +# 检查配置文件.env +# 测试连接 +mysql -u root -p +``` + +### 6.2 队列不执行 +```bash +# 检查队列消费者 +php think queue:work + +# 检查Redis连接 +redis-cli ping + +# 查看队列日志 +tail -f runtime/log/queue.log +``` + +### 6.3 定时任务不执行 +```bash +# 检查定时任务状态 +php think timer status + +# 查看定时任务日志 +tail -f runtime/log/timer.log +``` + +### 6.4 WebSocket连接失败 +```bash +# 检查WebSocket服务 +php think workerman status + +# 检查端口占用 +netstat -tlnp | grep 40001 +``` + +## 7. 参考资源 + +### 7.1 官方文档 +- [ThinkPHP 6 官方文档](https://www.kancloud.cn/manual/thinkphp6_0) +- [Vue 2 官方文档](https://v2.vuejs.org/) +- [Element UI 官方文档](https://element.eleme.io/) +- [UniApp 官方文档](https://uniapp.dcloud.net.cn/) + +### 7.2 项目文档 +- 代码理解指南: `/help/dev-docs/AI代码理解指南.md` +- 错误码说明: `/help/dev-docs/错误码说明文档.md` +- 后端API文档: `/help/dev-docs/phpapi/` +- 移动端文档: `/help/dev-docs/uniapp/` +- 管理端文档: `/help/dev-docs/admin/` + +### 7.3 开发工具 +- **IDE**: PhpStorm / VS Code +- **API测试**: Postman / Apifox +- **数据库**: Navicat / phpMyAdmin +- **Redis**: Redis Desktop Manager + +## 8. 获取帮助 + +### 8.1 技术社区 +- CRMEB技术社区: https://www.crmeb.com/ask/thread/list/147 +- 开源技术交流群: 查看项目README.md + +### 8.2 官方支持 +- 官网: https://www.crmeb.com +- 文档中心: https://doc.crmeb.com +- 在线客服: https://www.crmeb.com + +### 8.3 问题反馈 +- Gitee Issues: https://gitee.com/ZhongBangKeJi/CRMEB/issues +- 技术社区发帖: https://www.crmeb.com/ask/ + +## 9. 扩展阅读 + +### 9.1 专项Skill文档 +本目录下还包含以下专项skill文档,点击对应文件查看详情: + +- **crmeb-agent**: CRMEB电商系统Agent(智能开发助手) +- **php-api**: PHP后端开发专项说明 +- **admin-element**: 管理端前端开发专项说明 +- **uniapp**: 移动端UniApp开发专项说明 + +### 9.2 进阶文档 +- **references/api_flow.md**: 接口请求流程详解 +- **references/code_style.md**: 代码规范详解 +- **references/db_design.md**: 数据库设计规范 +- **references/system_config.md**: 系统配置说明 + +--- + +**最后更新**: 2025年3月17日 +**维护者**: CRMEB开源社区 +**版本**: v1.0.0 diff --git a/.codebuddy/skills/crmeb-complete/SKILL_PACKAGE_SUMMARY.md b/.codebuddy/skills/crmeb-complete/SKILL_PACKAGE_SUMMARY.md new file mode 100644 index 000000000..c052bc7b7 --- /dev/null +++ b/.codebuddy/skills/crmeb-complete/SKILL_PACKAGE_SUMMARY.md @@ -0,0 +1,258 @@ +# CRMEB Skill包创建完成总结 + +## 📦 创建完成的文件清单 + +已成功创建完整的CRMEB电商系统Skill包,文件结构如下: + +``` +.codebuddy/skills/crmeb-complete/ +├── SKILL.md # 主Skill文件(项目概览) +├── README.md # Skill包说明文档 +└── references/ # 参考文档目录 + ├── quick_start.md # 快速开始指南 + ├── api_flow.md # API接口请求流程详解 + ├── code_style.md # 代码开发规范 + ├── db_design.md # 数据库设计规范 + └── system_config.md # 系统配置详解 +``` + +## 📚 Skill包内容概览 + +### 1. 主Skill文件(SKILL.md) +**文件大小:** 约15KB +**内容涵盖:** +- 项目概述(技术架构、核心特点、项目地址) +- 目录结构详解(后端、前端、Docker) +- 核心业务模块详解(用户、商品、订单、支付、营销、分销、系统管理) +- 开发规范(命名、代码分层、API响应格式) +- 常用命令(ThinkPHP、队列、定时任务、Workerman) +- 开发环境配置(环境要求、数据库、Redis、队列) +- 常见问题(数据库、队列、定时任务、WebSocket) +- 参考资源(官方文档、项目文档、开发工具) + +### 2. 快速开始指南(references/quick_start.md) +**文件大小:** 约12KB +**内容涵盖:** +- Docker一键部署(推荐) +- 手动安装步骤 +- 环境配置详解 +- 验证安装 +- 常见问题排查(10+常见问题及解决方案) +- 下一步建议 + +### 3. API接口请求流程详解(references/api_flow.md) +**文件大小:** 约18KB +**内容涵盖:** +- API请求生命周期 +- 请求处理流程详解 +- 统一响应格式(成功、分页、错误) +- 认证与授权流程 +- 参数验证方式 +- 错误处理机制 +- 日志记录规范 +- 性能优化建议 + +### 4. 代码开发规范(references/code_style.md) +**文件大小:** 约20KB +**内容涵盖:** +- 命名规范(类、方法、变量、数据库) +- 代码分层规范(控制器、服务层、DAO层、模型层) +- 注释规范(文件、类、方法、复杂逻辑) +- 数据库规范(表设计、索引设计、SQL编写) +- API接口规范(路由、请求方法、响应格式、状态码) +- 性能优化(数据库、缓存、队列) +- 安全规范(SQL注入、XSS、CSRF、敏感信息保护) + +### 5. 数据库设计规范(references/db_design.md) +**文件大小:** 约22KB +**内容涵盖:** +- 数据库架构和配置 +- 表命名规范 +- 字段命名规范 +- 核心表结构详解(用户表、商品表、订单表) +- 索引设计规范 +- 数据类型优化 +- 关联查询设计 +- 性能优化建议(表分区、分表、读写分离) +- 数据备份与恢复 +- 数据库监控 + +### 6. 系统配置详解(references/system_config.md) +**文件大小:** 约18KB +**内容涵盖:** +- 配置文件结构 +- 应用配置详解 +- 数据库配置详解(含读写分离) +- 缓存配置详解 +- 队列配置详解 +- Workerman配置详解 +- 日志配置详解 +- 文件存储配置(本地、云存储) +- 微信支付配置 +- 支付宝配置 +- 短信服务配置 +- 邮件服务配置 +- 第三方登录配置 +- 安全配置 +- 完整环境变量示例 + +## 🎯 Skill包特点 + +### 1. 完整性 +- 涵盖CRMEB系统的所有核心模块 +- 包含前端、后端、移动端开发指南 +- 覆盖从安装部署到高级优化的全流程 + +### 2. 实用性 +- 提供可直接使用的代码示例 +- 包含常见问题排查指南 +- 提供性能优化和安全加固建议 + +### 3. 规范性 +- 详细的开发规范和最佳实践 +- 统一的命名和代码风格指南 +- 完整的数据库设计规范 + +### 4. 易用性 +- 清晰的目录结构和导航 +- 详细的步骤说明 +- 丰富的示例和截图建议 + +### 5. 可维护性 +- 模块化文档结构 +- 统一的文档格式 +- 版本管理和更新记录 + +## 🚀 使用建议 + +### 对于新手开发者 +1. **第一步**:阅读 `README.md` 了解Skill包结构 +2. **第二步**:按照 `references/quick_start.md` 部署项目 +3. **第三步**:阅读 `SKILL.md` 了解项目架构和核心模块 +4. **第四步**:参考 `references/code_style.md` 开始开发 + +### 对于后端开发者 +1. **必读**:`SKILL.md` 的"核心业务模块"章节 +2. **必读**:`references/api_flow.md` 了解API开发流程 +3. **参考**:`references/code_style.md` 遵循开发规范 +4. **参考**:`references/db_design.md` 数据库设计规范 + +### 对于前端开发者 +1. **必读**:`SKILL.md` 的"目录结构"章节 +2. **必读**:`references/api_flow.md` 了解接口规范 +3. **参考**:管理端或移动端专项Skill文档 + +### 对于全栈开发者 +1. **完整阅读**所有文档 +2. **重点关注**系统架构和设计模式 +3. **深入学习**性能优化和安全加固 + +## 📖 学习路径 + +### 阶段一:环境搭建(30分钟) +- 阅读 `README.md` +- 按照 `references/quick_start.md` 部署项目 +- 验证系统正常运行 + +### 阶段二:项目了解(1小时) +- 阅读 `SKILL.md` 的"项目概述"和"目录结构" +- 浏览后台管理功能 +- 体验前端商城流程 + +### 阶段三:后端开发(3-5小时) +- 深入学习 `SKILL.md` 的"核心业务模块" +- 阅读 `references/api_flow.md` +- 学习 `references/code_style.md` +- 学习 `references/db_design.md` +- 实践代码生成器 + +### 阶段四:功能开发(持续) +- 选择一个小功能模块进行开发 +- 参考现有代码实现 +- 遵循开发规范 +- 编写必要注释 + +### 阶段五:高级特性(2-3小时) +- 学习队列使用 +- 了解定时任务 +- 掌握WebSocket通信 +- 性能优化实践 + +## 🔧 开发工具推荐 + +### 后端开发 +- **IDE**: PhpStorm / VS Code +- **API测试**: Postman / Apifox +- **数据库**: Navicat / phpMyAdmin +- **Redis**: Redis Desktop Manager + +### 前端开发 +- **IDE**: VS Code / WebStorm +- **浏览器**: Chrome + Vue DevTools + +### 移动端开发 +- **IDE**: HBuilderX(官方推荐) +- **调试**: 微信开发者工具 + 真机调试 + +## 💡 最佳实践 + +### 1. 使用代码生成器 +在后台管理中使用"代码生成器"快速生成CRUD代码,节省开发时间。 + +### 2. 遵循开发规范 +严格按照 `references/code_style.md` 中的规范进行开发,保证代码质量。 + +### 3. 合理使用缓存 +对于读多写少的数据,合理使用Redis缓存提高性能。 + +### 4. 异步处理耗时任务 +将发送短信、生成海报等耗时操作放入队列异步处理。 + +### 5. 编写单元测试 +为关键业务逻辑编写单元测试,保证代码稳定性。 + +### 6. 定期备份数据 +使用自动化脚本定期备份数据库和文件。 + +### 7. 监控和日志 +配置完善的监控和日志系统,及时发现和解决问题。 + +## 🎉 Skill包优势 + +1. **节省时间**:无需从零开始研究项目,快速上手 +2. **降低门槛**:详细的文档和示例,降低学习难度 +3. **提高效率**:规范的代码和最佳实践,提高开发效率 +4. **减少错误**:包含常见问题排查,减少踩坑 +5. **促进协作**:统一的开发规范,便于团队协作 + +## 📞 获取帮助 + +- **技术社区**:https://www.crmeb.com/ask/thread/list/147 +- **官方文档**:https://doc.crmeb.com +- **在线客服**:https://www.crmeb.com +- **GitHub Issues**:https://gitee.com/ZhongBangKeJi/CRMEB/issues + +## 📄 许可证 + +本项目基于 [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) 协议开源。 + +## 📝 更新日志 + +### v1.0.0 (2025-03-17) +- ✅ 初始版本发布 +- ✅ 包含项目概览、快速开始、API流程等核心文档 +- ✅ 完整的开发规范和最佳实践 +- ✅ 详细的数据库设计规范 +- ✅ 完整的系统配置详解 +- ✅ 覆盖CRMEB所有核心模块 + +## 🙏 致谢 + +感谢CRMEB开源社区和所有贡献者的支持。 + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-03-17 +**维护者**: CRMEB开源社区 +**贡献者**: AI助手 + CRMEB社区 diff --git a/.codebuddy/skills/crmeb-complete/references/api_flow.md b/.codebuddy/skills/crmeb-complete/references/api_flow.md new file mode 100644 index 000000000..502be54ce --- /dev/null +++ b/.codebuddy/skills/crmeb-complete/references/api_flow.md @@ -0,0 +1,845 @@ +# API接口请求流程详解 + +## 1. API请求生命周期 + +### 1.1 请求流程图 + +``` +客户端请求 + ↓ +Nginx/Apache + ↓ +入口文件 (public/index.php) + ↓ +ThinkPHP应用初始化 + ↓ +路由解析 (route/*.php) + ↓ +中间件处理 (app/http/middleware/) + ↓ +控制器 (app/*/controller/) + ↓ +服务层 (app/services/) + ↓ +DAO层 (app/dao/) + ↓ +模型层 (app/model/) + ↓ +数据库 (MySQL) + ↓ +返回响应 + ↓ +JSON格式化 + ↓ +客户端接收 +``` + +### 1.2 请求处理详解 + +**步骤1:路由解析** +- 配置文件:`route/app.php`, `route/adminapi.php`, `route/api.php` +- 路由规则:支持GET、POST、PUT、DELETE等HTTP方法 +- 路由分组:按模块分组,统一前缀 + +**步骤2:中间件处理** +- 权限验证:验证用户登录状态和权限 +- 请求日志:记录请求日志 +- 参数过滤:过滤非法参数 +- 跨域处理:处理CORS跨域请求 + +**步骤3:控制器层** +- 接收参数:从GET/POST获取参数 +- 参数验证:验证参数合法性 +- 调用服务:调用服务层处理业务 +- 返回响应:返回JSON格式数据 + +**步骤4:服务层** +- 业务逻辑:处理核心业务逻辑 +- 数据验证:验证业务规则 +- 调用DAO:调用DAO层操作数据库 +- 事务管理:处理数据库事务 +- 事件触发:触发系统事件 + +**步骤5:DAO层** +- 构建查询:构建SQL查询条件 +- 执行查询:执行数据库操作 +- 返回结果:返回查询结果 + +**步骤6:模型层** +- 数据映射:ORM对象关系映射 +- 数据转换:自动转换数据类型 +- 关联查询:处理表关联关系 + +## 2. API调用示例 + +### 2.1 用户登录API + +**请求URL:** +``` +POST /api/login +``` + +**请求参数:** +```json +{ + "account": "13800138000", + "password": "123456", + "type": "account" // account:账号密码, mobile:手机验证码 +} +``` + +**处理流程:** +```php +// 1. 路由定义 (route/api.php) +Route::post('login', 'api.Login/login'); + +// 2. 控制器 (app/api/controller/Login.php) +class Login +{ + public function login() + { + // 获取参数 + $data = $this->request->postMore([ + ['account', ''], + ['password', ''], + ['type', 'account'] + ]); + + // 调用登录服务 + $loginServices = app()->make(LoginServices::class); + $token = $loginServices->login($data['account'], $data['password'], $data['type']); + + // 返回token + return app('json')->success(['token' => $token]); + } +} + +// 3. 服务层 (app/services/user/LoginServices.php) +class LoginServices extends BaseServices +{ + public function login($account, $password, $type) + { + // 验证验证码(如果需要) + // 查询用户 + $user = $this->dao->getUserByAccount($account); + + // 验证密码 + if (!password_verify($password, $user['pwd'])) { + throw new ValidateException('密码错误'); + } + + // 生成token + $token = $this->createToken($user['uid']); + + // 更新登录信息 + $this->dao->update($user['uid'], [ + 'last_login_time' => time(), + 'last_login_ip' => request()->ip() + ]); + + return $token; + } +} +``` + +**响应结果:** +```json +{ + "code": 200, + "msg": "登录成功", + "data": { + "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." + } +} +``` + +### 2.2 商品列表API + +**请求URL:** +``` +GET /api/products +``` + +**请求参数:** +``` +page: 1 // 页码 +limit: 10 // 每页数量 +category_id: 1 // 分类ID +keywords: "手机" // 搜索关键词 +sort: "id-desc" // 排序方式 +``` + +**处理流程:** +```php +// 1. 路由定义 +Route::get('products', 'api.Product/get_list'); + +// 2. 控制器 +class Product +{ + public function get_list() + { + // 获取参数 + $where = $this->request->getMore([ + ['page', 1], + ['limit', 10], + ['category_id', 0], + ['keywords', ''], + ['sort', 'id-desc'] + ]); + + // 调用服务层 + $productServices = app()->make(StoreProductServices::class); + $list = $productServices->getProductList($where); + + return app('json')->success($list); + } +} + +// 3. 服务层 +class StoreProductServices extends BaseServices +{ + public function getProductList(array $where) + { + // 构建查询条件 + $query = $this->dao->search($where); + + // 分页查询 + $list = $query->page($where['page'], $where['limit'])->select(); + + // 处理数据 + foreach ($list as &$item) { + $item['price'] = bcadd($item['price'], '0', 2); + $item['image'] = $this->getImageUrl($item['image']); + } + + return [ + 'list' => $list, + 'count' => $query->count(), + 'page' => $where['page'], + 'limit' => $where['limit'] + ]; + } +} + +// 4. DAO层 +class StoreProductDao extends BaseDao +{ + public function search(array $where = []) + { + $query = $this->getModel() + ->where('is_del', 0) + ->where('is_show', 1); + + // 分类筛选 + if ($where['category_id']) { + $query = $query->where('category_id', $where['category_id']); + } + + // 关键词搜索 + if ($where['keywords']) { + $query = $query->whereLike('name|keyword', "%{$where['keywords']}%"); + } + + // 排序 + [$field, $sort] = explode('-', $where['sort']); + $query = $query->order($field, $sort); + + return $query; + } +} +``` + +### 2.3 创建订单API + +**请求URL:** +``` +POST /api/order/create +``` + +**请求头:** +``` +Authorization: Bearer {token} +``` + +**请求参数:** +```json +{ + "cart_id": "1,2,3", // 购物车ID(多个用逗号分隔) + "address_id": 10, // 收货地址ID + "pay_type": "wechat", // 支付方式: wechat, alipay, yue + "coupon_id": 5, // 优惠券ID(可选) + "mark": "尽快发货", // 买家留言(可选) + "use_integral": false // 是否使用积分 +} +``` + +**处理流程:** +```php +// 1. 路由定义 +Route::post('order/create', 'api.Order/create')->middleware(AuthTokenMiddleware::class); + +// 2. 中间件验证 +class AuthTokenMiddleware +{ + public function handle($request, \Closure $next) + { + // 验证token + $token = $request->header('Authorization'); + $user = $this->checkToken($token); + + // 将用户信息存入请求 + $request->user = $user; + + return $next($request); + } +} + +// 3. 控制器 +class Order +{ + public function create() + { + // 获取当前用户 + $uid = $this->request->user['uid']; + + // 获取参数 + $data = $this->request->postMore([ + ['cart_id', ''], + ['address_id', 0], + ['pay_type', ''], + ['coupon_id', 0], + ['mark', ''], + ['use_integral', false] + ]); + + // 调用订单创建服务 + $orderServices = app()->make(StoreOrderCreateServices::class); + $orderId = $orderServices->createOrder($uid, $data); + + return app('json')->success(['order_id' => $orderId]); + } +} + +// 4. 订单创建服务 +class StoreOrderCreateServices extends BaseServices +{ + public function createOrder($uid, $data) + { + // 1. 参数验证 + $this->validateOrderData($data); + + // 2. 查询购物车 + $carts = $this->getCarts($uid, $data['cart_id']); + + // 3. 查询收货地址 + $address = $this->getAddress($uid, $data['address_id']); + + // 4. 验证优惠券 + $coupon = null; + if ($data['coupon_id']) { + $coupon = $this->validateCoupon($uid, $data['coupon_id']); + } + + // 5. 计算订单金额 + $priceInfo = $this->computeOrderPrice($carts, $coupon, $data['use_integral']); + + // 6. 开启事务 + $this->transaction(function () use ($uid, $data, $carts, $address, $priceInfo) { + // 6.1 创建订单 + $orderId = $this->createOrderRecord($uid, $data, $address, $priceInfo); + + // 6.2 创建订单商品 + $this->createOrderCartInfo($orderId, $carts); + + // 6.3 扣减库存 + $this->decrementStock($carts); + + // 6.4 清空购物车 + $this->clearCart($uid, $data['cart_id']); + + // 6.5 使用优惠券 + if ($data['coupon_id']) { + $this->useCoupon($uid, $data['coupon_id'], $orderId); + } + + // 6.6 触发订单创建事件 + event('order.create', ['order_id' => $orderId]); + + return $orderId; + }); + + // 7. 返回订单ID + return $orderId; + } +} +``` + +## 3. 统一响应格式 + +### 3.1 成功响应 + +**格式:** +```json +{ + "code": 200, + "msg": "操作成功", + "data": {} +} +``` + +**示例:** +```php +// 返回成功,无数据 +return app('json')->success(); + +// 返回成功,带数据 +return app('json')->success($data); + +// 返回成功,自定义消息 +return app('json')->success('登录成功'); + +// 返回成功,带数据和消息 +return app('json')->success($data, '获取成功'); +``` + +### 3.2 分页响应 + +**格式:** +```json +{ + "code": 200, + "msg": "操作成功", + "data": { + "list": [], + "count": 100, + "page": 1, + "limit": 10 + } +} +``` + +**示例:** +```php +// 构建分页数据 +$data = [ + 'list' => $list, + 'count' => $total, + 'page' => $page, + 'limit' => $limit +]; + +return app('json')->success($data); +``` + +### 3.3 错误响应 + +**格式:** +```json +{ + "code": 400, + "msg": "错误信息", + "data": null +} +``` + +**示例:** +```php +// 返回错误 +return app('json')->fail('参数错误'); + +// 返回错误,带错误码 +return app('json')->fail('用户不存在', 404); + +// 抛出异常(框架自动捕获并返回错误) +throw new ValidateException('手机号格式错误'); +throw new AuthException('登录已过期'); +``` + +### 3.4 特殊状态码 + +**系统定义的状态码:** + +| 状态码 | 说明 | +|--------|------| +| 200 | 操作成功 | +| 400 | 参数错误 | +| 401 | 未授权(未登录或token过期) | +| 403 | 无权限访问 | +| 404 | 资源不存在 | +| 429 | 请求过于频繁 | +| 500 | 服务器内部错误 | +| 502 | 服务不可用 | + +## 4. 认证与授权 + +### 4.1 Token认证流程 + +``` +1. 用户登录 +2. 服务端验证账号密码 +3. 生成JWT Token +4. 返回Token给客户端 +5. 客户端存储Token(localStorage) +6. 后续请求携带Token(Header: Authorization: Bearer {token}) +7. 服务端验证Token +8. 返回请求数据 +``` + +### 4.2 Token验证中间件 + +```php +header('Authorization'); + + if (!$token) { + throw new AuthException('请先登录', 401); + } + + // 验证Token格式 + if (!preg_match('/Bearer\s+(.+)/', $token, $matches)) { + throw new AuthException('Token格式错误', 401); + } + + $jwt = $matches[1]; + + // 验证JWT + try { + $payload = JWTAuth::decode($jwt); + } catch (\Exception $e) { + throw new AuthException('Token已过期', 401); + } + + // 查询用户 + $user = \app\model\user\User::find($payload['uid']); + if (!$user || $user['status'] == 0) { + throw new AuthException('用户不存在或已被禁用', 401); + } + + // 将用户信息存入请求 + $request->user = $user->toArray(); + + return $next($request); + } +} +``` + +### 4.3 路由中应用中间件 + +```php +middleware([AuthTokenMiddleware::class]); + +// 需要登录和权限验证的接口(后台管理) +Route::group('adminapi', function () { + Route::get('dashboard', 'adminapi.Index/index'); + Route::get('user/list', 'adminapi.User/get_list'); +})->middleware([AuthTokenMiddleware::class, CheckAdminMiddleware::class]); +``` + +## 5. 参数验证 + +### 5.1 控制器参数验证 + +```php +request->postMore([ + ['nickname', '', '昵称长度应在2-20位之间', function($value) { + return mb_strlen($value) >= 2 && mb_strlen($value) <= 20; + }], + ['avatar', '', '头像地址不能为空'], + ['sex', 0, '性别格式错误', function($value) { + return in_array($value, [0, 1, 2]); + }] + ]); + + // 业务处理... + } +} +``` + +### 5.2 验证器类 + +```php + 'require|length:2,20', + 'password' => 'require|length:6,20', + 'phone' => 'require|mobile', + 'email' => 'email', + 'code' => 'require|length:4,6' + ]; + + protected $message = [ + 'account.require' => '账号不能为空', + 'account.length' => '账号长度应在2-20位之间', + 'password.require' => '密码不能为空', + 'password.length' => '密码长度应在6-20位之间', + 'phone.require' => '手机号不能为空', + 'phone.mobile' => '手机号格式错误', + 'email.email' => '邮箱格式错误', + 'code.require' => '验证码不能为空', + 'code.length' => '验证码长度错误' + ]; + + protected $scene = [ + 'login' => ['account', 'password'], + 'register' => ['account', 'password', 'phone', 'code'], + 'update' => ['nickname', 'avatar', 'sex'] + ]; +} +``` + +### 5.3 在控制器中使用验证器 + +```php +scene('register')->check($this->request->post())) { + return app('json')->fail($validate->getError()); + } + + // 业务处理... + } +} +``` + +## 6. 错误处理 + +### 6.1 异常类型 + +**系统定义的异常类:** + +```php +// 验证异常(参数错误) +throw new \crmeb\exceptions\ValidateException('参数验证失败'); + +// 授权异常(登录过期、无权限) +throw new \crmeb\exceptions\AuthException('请先登录', 401); + +// 业务异常(通用业务错误) +throw new \crmeb\exceptions\AdminException('操作失败'); + +// 系统异常(服务器错误) +throw new \crmeb\exceptions\SystemException('系统错误'); +``` + +### 6.2 全局异常处理 + +**异常处理配置:** `app/ExceptionHandle.php` + +```php +fail($e->getError(), 400); + } + + // HTTP异常(404等) + if ($e instanceof HttpException) { + return app('json')->fail($e->getMessage(), $e->getStatusCode()); + } + + // 授权异常 + if ($e instanceof \crmeb\exceptions\AuthException) { + return app('json')->fail($e->getMessage(), $e->getCode() ?: 401); + } + + // 业务异常 + if ($e instanceof \crmeb\exceptions\AdminException) { + return app('json')->fail($e->getMessage(), $e->getCode() ?: 400); + } + + // 系统异常(生产环境不显示详细信息) + if (app()->isDebug()) { + return app('json')->fail($e->getMessage(), 500); + } else { + return app('json')->fail('系统错误,请稍后重试', 500); + } + } +} +``` + +## 7. 日志记录 + +### 7.1 记录业务日志 + +```php + $uid, 'ip' => $ip]); + +// 记录错误日志 +\think\facade\Log::error('订单创建失败', ['uid' => $uid, 'error' => $error]); + +// 记录调试日志 +\think\facade\Log::debug('调试信息', ['data' => $data]); + +// 指定日志通道 +\think\facade\Log::channel('order')->info('订单日志', ['order_id' => $orderId]); +``` + +### 7.2 日志配置 + +**配置文件:** `config/log.php` + +```php + env('log.channel', 'file'), + + // 日志通道 + 'channels' => [ + 'file' => [ + 'type' => 'file', + 'path' => app()->getRuntimePath() . 'log/', + 'level' => ['info', 'error', 'warning'], + 'single' => false, // 是否单文件日志 + 'max_files' => 10, // 最大文件数 + ], + + 'order' => [ + 'type' => 'file', + 'path' => app()->getRuntimePath() . 'log/order/', + 'level' => ['info', 'error'], + ], + + 'pay' => [ + 'type' => 'file', + 'path' => app()->getRuntimePath() . 'log/pay/', + 'level' => ['info', 'error'], + ] + ] +]; +``` + +## 8. 性能优化 + +### 8.1 数据库优化 + +**使用索引:** +```php +// 在DAO层中,为常用查询字段添加索引 +$query = $this->getModel() + ->where('uid', $uid) // uid应添加索引 + ->where('status', 1) // status应添加索引 + ->where('is_del', 0) // is_del应添加索引 + ->order('id', 'desc'); +``` + +**避免N+1查询:** +```php +// 错误示例:循环中查询 +foreach ($orders as $order) { + $user = User::find($order['uid']); // 每次循环都查询数据库 +} + +// 正确示例:预加载 +$orders = Order::with('user')->select(); // 一次查询关联数据 +``` + +### 8.2 缓存使用 + +```php +set('key', $value, 3600); +``` + +### 8.3 队列使用 + +```php + $data['order_sn'] + ]); + + // 发送模板消息(微信) + \app\services\wechat\WechatTemplateServices::sendOrderSuccess($data); + + // 处理完成删除任务 + $job->delete(); + } +} +``` + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-03-17 diff --git a/.codebuddy/skills/crmeb-complete/references/code_style.md b/.codebuddy/skills/crmeb-complete/references/code_style.md new file mode 100644 index 000000000..f35d3f684 --- /dev/null +++ b/.codebuddy/skills/crmeb-complete/references/code_style.md @@ -0,0 +1,1072 @@ +# CRMEB代码开发规范 + +## 1. 命名规范 + +### 1.1 类命名 + +**规则:** +- 使用大驼峰命名法(PascalCase) +- 类名应清晰表达其职责 +- 遵循PSR-2规范 + +**示例:** +```php +services = $services; + } + + /** + * 获取管理员列表 + * @return \think\response\Json + */ + public function get_list() + { + // 1. 获取并验证请求参数 + $where = $this->request->getMore([ + ['keywords', ''], + ['status', ''], + ['role_id', ''] + ]); + + // 2. 调用服务层 + $list = $this->services->getAdminList($where); + + // 3. 返回响应 + return app('json')->success($list); + } + + /** + * 保存管理员 + * @return \think\response\Json + */ + public function save() + { + // 1. 获取并验证POST参数 + $data = $this->request->postMore([ + ['id', 0], + ['account', ''], + ['real_name', ''], + ['pwd', ''], + ['roles', []], + ['status', 1] + ]); + + // 2. 调用服务层保存 + $this->services->saveAdmin($data); + + // 3. 返回成功响应 + return app('json')->success('保存成功'); + } + + /** + * 删除管理员 + * @param int $id + * @return \think\response\Json + */ + public function delete($id) + { + // 1. 参数验证 + if (!$id) { + return app('json')->fail('参数错误'); + } + + // 2. 调用服务层删除 + $this->services->deleteAdmin($id); + + // 3. 返回成功响应 + return app('json')->success('删除成功'); + } +} +``` + +### 2.3 服务层规范 + +**职责:** +1. 实现核心业务逻辑 +2. 数据验证和权限验证 +3. 调用DAO层操作数据库 +4. 事务管理(需要时) +5. 调用其他服务(需要时) +6. 触发系统事件 + +**规范示例:** +```php +dao = $dao; + } + + /** + * 获取管理员列表 + * @param array $where + * @param int $page + * @param int $limit + * @return array + */ + public function getAdminList(array $where, int $page = 1, int $limit = 10): array + { + // 1. 构建查询条件 + $query = $this->dao->search($where); + + // 2. 统计总数 + $count = $query->count(); + + // 3. 获取列表数据 + $list = $query->page($page, $limit)->select()->toArray(); + + // 4. 处理数据 + foreach ($list as &$item) { + $item['role_names'] = $this->getRoleNames($item['roles']); + $item['status_text'] = $item['status'] ? '启用' : '禁用'; + $item['last_login_time_text'] = $item['last_login_time'] + ? date('Y-m-d H:i:s', $item['last_login_time']) + : '-'; + } + + // 5. 返回分页数据 + return [ + 'list' => $list, + 'count' => $count, + 'page' => $page, + 'limit' => $limit + ]; + } + + /** + * 保存管理员 + * @param array $data + * @return int + * @throws AdminException + */ + public function saveAdmin(array $data): int + { + // 1. 数据验证 + if (empty($data['account'])) { + throw new AdminException('账号不能为空'); + } + + // 2. 验证账号唯一性 + $exists = $this->dao->getAdminByAccount($data['account'], $data['id'] ?? 0); + if ($exists) { + throw new AdminException('账号已存在'); + } + + // 3. 密码处理 + if (!empty($data['pwd'])) { + $data['pwd'] = password_hash($data['pwd'], PASSWORD_DEFAULT); + } else { + unset($data['pwd']); + } + + // 4. 开启事务 + return $this->transaction(function () use ($data) { + if (isset($data['id']) && $data['id']) { + // 更新 + $id = $data['id']; + unset($data['id']); + $this->dao->update($id, $data); + return $id; + } else { + // 新增 + $data['create_time'] = time(); + return $this->dao->save($data); + } + }); + } + + /** + * 删除管理员 + * @param int $id + * @return bool + * @throws AdminException + */ + public function deleteAdmin(int $id): bool + { + // 1. 检查是否可删除 + $count = $this->dao->count(); + if ($count <= 1) { + throw new AdminException('至少需要保留一个管理员'); + } + + // 2. 软删除 + return $this->dao->update($id, ['is_del' => 1]); + } + + /** + * 根据角色ID获取角色名称 + * @param array $roleIds + * @return string + */ + private function getRoleNames(array $roleIds): string + { + if (empty($roleIds)) { + return ''; + } + + $roleNames = $this->dao->getRoleNames($roleIds); + return implode(',', $roleNames); + } +} +``` + +### 2.4 DAO层规范 + +**职责:** +1. 封装数据库查询逻辑 +2. 构建查询条件 +3. 防止SQL注入 +4. 不提供业务逻辑 +5. 返回原始数据或模型对象 + +**规范示例:** +```php +getModel() + ->where('is_del', 0); + + // 关键词搜索 + if (!empty($where['keywords'])) { + $query = $query->whereLike('account|real_name', "%{$where['keywords']}%"); + } + + // 状态筛选 + if ($where['status'] !== '') { + $query = $query->where('status', $where['status']); + } + + // 角色筛选 + if (!empty($where['role_id'])) { + $query = $query->whereFindInSet('roles', $where['role_id']); + } + + // 时间范围筛选 + if (!empty($where['start_time'])) { + $query = $query->where('create_time', '>=', strtotime($where['start_time'])); + } + if (!empty($where['end_time'])) { + $query = $query->where('create_time', '<', strtotime($where['end_time'])); + } + + // 排序(默认按创建时间倒序) + $query = $query->order('create_time DESC, id DESC'); + + return $query; + } + + /** + * 根据账号获取管理员 + * @param string $account + * @param int $exceptId + * @return array|null + */ + public function getAdminByAccount(string $account, int $exceptId = 0): ?array + { + $query = $this->getModel() + ->where('account', $account) + ->where('is_del', 0); + + if ($exceptId > 0) { + $query = $query->where('id', '<>', $exceptId); + } + + $admin = $query->find(); + return $admin ? $admin->toArray() : null; + } + + /** + * 统计管理员数量 + * @return int + */ + public function count(): int + { + return $this->getModel() + ->where('is_del', 0) + ->count(); + } +} +``` + +### 2.5 模型层规范 + +**职责:** +1. 定义数据模型 +2. 处理数据关系(关联查询) +3. 自动时间戳 +4. 数据获取器和修改器 + +**规范示例:** +```php +belongsToMany( + SystemRole::class, + 'system_admin_role', + 'role_id', + 'admin_id' + ); + } + + /** + * 密码修改器(自动加密) + * @param string $value + * @return string + */ + public function setPwdAttr(string $value): string + { + return password_hash($value, PASSWORD_DEFAULT); + } + + /** + * 状态获取器 + * @param int $value + * @return string + */ + public function getStatusTextAttr(int $value, array $data): string + { + $status = [ + 0 => '禁用', + 1 => '启用' + ]; + return $status[$data['status']] ?? '未知'; + } + + /** + * 最后登录时间获取器 + * @param int $value + * @return string + */ + public function getLastLoginTimeTextAttr(int $value): string + { + return $value ? date('Y-m-d H:i:s', $value) : '-'; + } +} +``` + +## 3. 注释规范 + +### 3.1 文件注释 + +```php +getAdminList([ + * 'keywords' => 'admin', + * 'status' => 1 + * ], 1, 10); + * ``` + */ +public function getAdminList(array $where, int $page = 1, int $limit = 10): array +{ + // ... +} +``` + +### 3.4 复杂逻辑注释 + +```php += $coupon['use_min_price']) { + $totalPrice -= $coupon['coupon_price']; // 减去优惠券金额 + $totalPrice = max(0, $totalPrice); // 确保不小于0 + } + } + + // 3. 积分抵扣 + if ($useIntegral) { + $integralPrice = $this->convertIntegralToPrice($userIntegral); + $totalPrice -= $integralPrice; + $totalPrice = max(0, $totalPrice); + } + + // 4. 运费计算(满额包邮) + if ($totalPrice < $freeShippingPrice) { + $totalPrice += $shippingPrice; + } + + return $totalPrice; +} +``` + +## 4. 数据库规范 + +### 4.1 表设计规范 + +**字段类型选择:** +```sql +-- 整数类型 +TINYINT(1) -- 状态字段(0/1) +SMALLINT -- 小范围整数(如分类ID) +INT -- 主键、用户ID、订单ID +BIGINT -- 大数值(如雪花算法ID) + +-- 小数类型 +DECIMAL(10,2) -- 金额、价格(精确计算) +FLOAT -- 非精确小数(少用) +DOUBLE -- 非精确大数值(少用) + +-- 字符串类型 +VARCHAR(255) -- 短字符串(账号、名称、标题) +VARCHAR(500) -- 中等长度(描述、简介) +TEXT -- 长文本(商品详情、文章内容) + +-- 时间类型 +INT(11) -- 时间戳(推荐,时区灵活) +DATETIME -- 日期时间(可视性好) +DATE -- 日期(仅日期) +TIME -- 时间(仅时间) +``` + +### 4.2 索引设计 + +**必须添加索引的字段:** +```sql +-- 主键 +PRIMARY KEY (id) + +-- 外键 +INDEX idx_user_id (user_id) +INDEX idx_order_id (order_id) + +-- 查询条件字段 +INDEX idx_status (status) +INDEX idx_is_del (is_del) +INDEX idx_create_time (create_time) + +-- 组合索引(根据查询场景) +INDEX idx_user_status (user_id, status) +INDEX idx_create_type (create_time, type) +``` + +**索引使用原则:** +1. 为WHERE条件中的字段添加索引 +2. 为ORDER BY排序字段添加索引 +3. 为JOIN关联字段添加索引 +4. 避免过多索引(影响写入性能) +5. 组合索引遵循最左前缀原则 + +### 4.3 SQL编写规范 + +**查询规范:** +```php +where('id', $userId) + ->where('status', 1) + ->find(); + +// ✅ 正确 - 参数绑定(防SQL注入) +$users = Db::name('user') + ->where('create_time', '>=', $startTime) + ->where('create_time', '<', $endTime) + ->where('status', $status) + ->select(); + +// ❌ 错误 - 直接拼接SQL(SQL注入风险) +$sql = "SELECT * FROM eb_user WHERE id = $userId"; +Db::query($sql); + +// ❌ 错误 - 不使用参数绑定 +Db::name('user')->where("id = $userId").find(); +``` + +**避免SELECT *:** +```php +select(); + +// ✅ 正确 - 只查询需要的字段 +$users = Db::name('user') + ->field('id, account, real_name, status, create_time') + ->select(); +``` + +## 5. API接口规范 + +### 5.1 路由定义 + +**路由文件:** +- 主路由:`route/app.php` +- 后台API路由:`route/adminapi.php` +- 前端API路由:`route/api.php` + +**路由规范:** +```php +middleware([AuthTokenMiddleware::class]); + +// ❌ 避免 - 不规范的路由 +Route::get('getUserList', 'User/getUserList'); // 无需get前缀 +Route::post('doSaveUser', 'User/doSave'); // 无需do前缀 +``` + +### 5.2 请求方法 + +**HTTP方法使用规范:** + +| 方法 | 用途 | 示例 | +|------|------|------| +| GET | 查询数据 | GET /api/user/list | +| POST | 创建数据 | POST /api/user | +| PUT | 更新数据(完整更新)| PUT /api/user/:id | +| PATCH | 更新数据(部分更新)| PATCH /api/user/:id | +| DELETE | 删除数据 | DELETE /api/user/:id | + +### 5.3 响应格式 + +**统一响应格式:** +```json +{ + "code": 200, + "msg": "操作成功", + "data": {} +} +``` + +**成功响应示例:** +```php +success(); + +// 返回成功,带数据 +return app('json')->success($data); + +// 返回成功,自定义消息 +return app('json')->success('登录成功'); + +// 返回成功,带数据和消息 +return app('json')->success($data, '获取成功'); +``` + +**分页响应格式:** +```json +{ + "code": 200, + "msg": "操作成功", + "data": { + "list": [], + "count": 100, + "page": 1, + "limit": 10 + } +} +``` + +**错误响应格式:** +```json +{ + "code": 400, + "msg": "错误信息", + "data": null +} +``` + +```php +fail('参数错误'); + +// 返回错误,带错误码 +return app('json')->fail('用户不存在', 404); + +// 抛出异常(框架自动处理) +throw new ValidateException('手机号格式错误'); +throw new AuthException('请先登录', 401); +``` + +### 5.4 状态码定义 + +**系统状态码:** + +| 状态码 | 说明 | +|--------|------| +| 200 | 操作成功 | +| 400 | 参数错误 | +| 401 | 未授权(未登录或token过期) | +| 403 | 无权限访问 | +| 404 | 资源不存在 | +| 429 | 请求过于频繁 | +| 500 | 服务器内部错误 | +| 502 | 服务不可用 | + +**业务状态码:** + +| 状态码 | 说明 | +|--------|------| +| 1000 | 用户已存在 | +| 1001 | 账号或密码错误 | +| 1002 | 验证码错误 | +| 1003 | 用户已被禁用 | +| 2000 | 库存不足 | +| 2001 | 商品已下架 | +| 3000 | 订单不存在 | +| 3001 | 订单状态错误 | +| 4000 | 余额不足 | +| 5000 | 优惠券已过期 | + +## 6. 性能优化 + +### 6.1 缓存使用 + +```php +set('key', $value, 3600); +``` + +### 6.2 数据库优化 + +**使用索引:** +```sql +-- 为常用查询字段添加索引 +CREATE INDEX idx_user_id ON eb_order(user_id); +CREATE INDEX idx_create_time ON eb_order(create_time); +CREATE INDEX idx_status ON eb_order(status); + +-- 组合索引 +CREATE INDEX idx_user_status ON eb_order(user_id, status); +``` + +**避免N+1查询:** +```php +select(); // 2次查询 +``` + +### 6.3 队列使用 + +```php +delete(); + } catch (\Exception $e) { + // 失败记录日志 + \think\facade\Log::error('短信发送失败', [ + 'phone' => $data['phone'], + 'error' => $e->getMessage() + ]); + + // 根据失败次数决定重试或删除 + if ($job->attempts() > 3) { + $job->delete(); + } else { + $job->release(60); // 60秒后重试 + } + } + } +} +``` + +## 7. 安全规范 + +### 7.1 SQL注入防护 + +```php +where('account', $account) + ->where('status', 1) + ->find(); + +// ❌ 错误 - SQL注入风险 +$sql = "SELECT * FROM eb_user WHERE account = '$account'"; +Db::query($sql); +``` + +### 7.2 XSS防护 + +```php + + +// 验证token +if (!token_verify($request->post('__token__'))) { + throw new ValidateException('非法请求'); +} +``` + +### 7.4 敏感信息保护 + +```php + env('database.type', 'mysql'), + + // 数据库连接信息 + 'connections' => [ + 'mysql' => [ + 'type' => 'mysql', + 'hostname' => env('database.hostname', '127.0.0.1'), + 'database' => env('database.database', 'crmeb'), + 'username' => env('database.username', 'root'), + 'password' => env('database.password', ''), + 'hostport' => env('database.hostport', '3306'), + 'charset' => env('database.charset', 'utf8mb4'), + 'prefix' => env('database.prefix', 'eb_'), + 'debug' => env('database.debug', false), + 'deploy' => 0, + 'rw_separate' => false, + 'master_num' => 1, + 'slave_no' => '', + 'break_reconnect' => false, + 'trigger_sql' => env('app_debug', true), + 'fields_strict' => true, + 'auto_timestamp' => false, + ], + ], +]; +``` + +### 1.2 数据库设计原则 + +**核心原则:** +1. **统一前缀**:所有表使用 `eb_` 前缀 +2. **清晰命名**:表名和字段名应清晰表达其含义 +3. **适当冗余**:在性能关键处适当冗余,减少JOIN查询 +4. **索引优化**:为高频查询字段添加索引 +5. **数据归档**:定期归档历史数据,保持表体积合理 +6. **字段类型**:选择合适的字段类型,避免浪费空间 + +## 2. 表命名规范 + +### 2.1 通用规则 + +```sql +-- ✅ 正确示例 +eb_user -- 用户表 +eb_store_product -- 商品表 +eb_store_order -- 订单表 +eb_system_config -- 系统配置表 + +-- ❌ 错误示例 +user -- 缺少前缀 +StoreProduct -- 使用大写 +systemconfig -- 无下划线 +``` + +### 2.2 模块命名 + +**用户模块:** +```sql +eb_user -- 用户主表 +eb_user_bill -- 用户账单 +eb_user_extract -- 用户提现 +eb_user_recharge -- 用户充值 +eb_user_level -- 用户等级 +eb_user_group -- 用户分组 +eb_user_label -- 用户标签 +eb_user_sign -- 用户签到 +eb_user_task -- 用户任务 +``` + +**商品模块:** +```sql +eb_store_category -- 商品分类 +eb_store_product -- 商品主表 +eb_store_product_attr -- 商品属性 +eb_store_product_attr_result -- 属性结果 +eb_store_product_description -- 商品详情 +eb_store_product_relation -- 商品关联(收藏、点赞) +eb_store_product_reply -- 商品评价 +``` + +**订单模块:** +```sql +eb_store_cart -- 购物车 +eb_store_order -- 订单主表 +eb_store_order_cart_info -- 订单商品 +eb_store_order_status -- 订单状态记录 +eb_store_refund -- 退款记录 +eb_store_order_invoice -- 发票信息 +``` + +**营销模块:** +```sql +eb_store_coupon -- 优惠券 +eb_store_coupon_user -- 用户优惠券 +eb_store_combination -- 拼团商品 +eb_store_pink -- 拼团记录 +eb_store_bargain -- 砍价商品 +eb_store_seckill -- 秒杀商品 +eb_store_integral -- 积分商品 +``` + +**分销模块:** +```sql +eb_agent_level -- 分销等级 +eb_agent_level_task -- 分销任务 +eb_spread_user -- 分销员 +eb_spread_order -- 分销订单 +eb_spread_commission -- 分销佣金 +eb_division -- 事业部 +``` + +**系统模块:** +```sql +eb_system_admin -- 管理员 +eb_system_role -- 角色 +eb_system_menus -- 菜单 +eb_system_config -- 配置 +eb_system_log -- 操作日志 +``` + +## 3. 字段命名规范 + +### 3.1 通用字段 + +**主键和ID:** +```sql +id INT PRIMARY KEY AUTO_INCREMENT -- 主键,所有表必须有 +``` + +**外键:** +```sql +user_id INT -- 关联用户表 +category_id INT -- 关联分类表 +product_id INT -- 关联商品表 +order_id INT -- 关联订单表 +``` + +**状态字段:** +```sql +status TINYINT(1) -- 状态(0禁用/下架,1启用/上架) +is_del TINYINT(1) -- 是否删除(0未删除,1已删除) +is_show TINYINT(1) -- 是否显示(0不显示,1显示) +``` + +**时间字段:** +```sql +create_time INT -- 创建时间(时间戳) +update_time INT -- 更新时间(时间戳) +delete_time INT -- 删除时间(时间戳,用于软删除) +``` + +### 3.2 字段类型选择 + +**整数类型:** +```sql +-- TINYINT: -128到127(无符号0-255) +status TINYINT(1) -- 状态字段 +type TINYINT(1) -- 类型字段 +is_del TINYINT(1) -- 删除标记 + +-- SMALLINT: -32768到32767(无符号0-65535) +category_id SMALLINT -- 分类ID +sort SMALLINT -- 排序 + +-- INT: -21亿到21亿(无符号0-42亿) +id INT -- 主键 +user_id INT -- 用户ID +order_id INT -- 订单ID +create_time INT -- 时间戳 + +-- BIGINT: 更大范围 +snowflake_id BIGINT -- 雪花算法ID +``` + +**小数类型:** +```sql +-- DECIMAL: 精确小数(推荐用于金额) +price DECIMAL(10,2) -- 价格(最多10位,小数2位) +total_price DECIMAL(10,2) -- 总价 +commission DECIMAL(10,2) -- 佣金 + +-- FLOAT/DOUBLE: 非精确小数(少用) +weight FLOAT -- 重量(可接受精度损失) +``` + +**字符串类型:** +```sql +-- VARCHAR: 变长字符串 +account VARCHAR(30) -- 账号 +phone VARCHAR(11) -- 手机号 +real_name VARCHAR(50) -- 真实姓名 +nickname VARCHAR(50) -- 昵称 +title VARCHAR(255) -- 标题 +image VARCHAR(255) -- 图片路径 + +-- TEXT: 长文本 +description TEXT -- 商品描述 +content TEXT -- 文章内容 +remark TEXT -- 备注 +``` + +**时间类型:** +```sql +-- INT存储时间戳(推荐,灵活) +create_time INT -- 创建时间 + +-- DATETIME(可视性好,但时区不灵活) +create_time DATETIME -- 创建时间 +``` + +## 4. 核心表结构详解 + +### 4.1 用户表(eb_user) + +```sql +CREATE TABLE `eb_user` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `account` varchar(30) NOT NULL DEFAULT '' COMMENT '账号', + `pwd` varchar(255) NOT NULL DEFAULT '' COMMENT '密码', + `real_name` varchar(50) NOT NULL DEFAULT '' COMMENT '真实姓名', + `nickname` varchar(50) NOT NULL DEFAULT '' COMMENT '昵称', + `avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '头像', + `phone` varchar(11) NOT NULL DEFAULT '' COMMENT '手机号', + `sex` tinyint(1) NOT NULL DEFAULT '0' COMMENT '性别(0未知,1男,2女)', + `birthday` int(11) NOT NULL DEFAULT '0' COMMENT '生日', + `level` tinyint(1) NOT NULL DEFAULT '0' COMMENT '会员等级', + `group_id` int(11) NOT NULL DEFAULT '0' COMMENT '用户分组ID', + `label_id` varchar(255) NOT NULL DEFAULT '' COMMENT '用户标签ID(多个用逗号分隔)', + `money` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '余额', + `integral` int(11) NOT NULL DEFAULT '0' COMMENT '积分', + `spread_uid` int(11) NOT NULL DEFAULT '0' COMMENT '推广人UID', + `spread_time` int(11) NOT NULL DEFAULT '0' COMMENT '推广时间', + `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0禁用,1启用)', + `is_del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除', + `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', + `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_account` (`account`), + UNIQUE KEY `idx_phone` (`phone`), + KEY `idx_spread_uid` (`spread_uid`), + KEY `idx_status` (`status`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; +``` + +**索引说明:** +- `PRIMARY KEY (id)`:主键索引 +- `idx_account`:账号唯一索引 +- `idx_phone`:手机号唯一索引 +- `idx_spread_uid`:推广人ID索引(用于分销查询) +- `idx_status`:状态索引(用于筛选启用用户) +- `idx_create_time`:创建时间索引(用于时间范围查询) + +### 4.2 商品表(eb_store_product) + +```sql +CREATE TABLE `eb_store_product` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品ID', + `mer_id` int(11) NOT NULL DEFAULT '0' COMMENT '商户ID', + `cate_id` int(11) NOT NULL DEFAULT '0' COMMENT '分类ID', + `store_name` varchar(255) NOT NULL DEFAULT '' COMMENT '商品名称', + `store_info` varchar(500) NOT NULL DEFAULT '' COMMENT '商品简介', + `keyword` varchar(255) NOT NULL DEFAULT '' COMMENT '关键字', + `bar_code` varchar(50) NOT NULL DEFAULT '' COMMENT '商品条码', + `image` varchar(255) NOT NULL DEFAULT '' COMMENT '商品主图', + `slider_image` text COMMENT '商品轮播图(JSON数组)', + `description` longtext COMMENT '商品详情', + `spec_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '规格类型(0单规格,1多规格)', + `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品价格', + `cost` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品成本价', + `ot_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品原价', + `stock` int(11) NOT NULL DEFAULT '0' COMMENT '商品库存', + `sales` int(11) NOT NULL DEFAULT '0' COMMENT '商品销量', + `unit_name` varchar(50) NOT NULL DEFAULT '件' COMMENT '商品单位', + `is_show` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否上架(0下架,1上架)', + `is_hot` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否热销', + `is_benefit` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否优惠', + `is_best` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否精品', + `is_new` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否新品', + `is_good` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否优品', + `is_postage` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否包邮', + `sort` smallint(6) NOT NULL DEFAULT '0' COMMENT '排序', + `give_integral` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '赠送积分', + `is_del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除', + `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '审核状态(0未审核,1已审核)', + `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', + `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_cate_id` (`cate_id`), + KEY `idx_mer_id` (`mer_id`), + KEY `idx_is_show` (`is_show`), + KEY `idx_is_hot` (`is_hot`), + KEY `idx_is_new` (`is_new`), + KEY `idx_sort` (`sort`), + KEY `idx_create_time` (`create_time`), + FULLTEXT KEY `idx_keyword` (`keyword`,`store_name`,`store_info`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'; +``` + +### 4.3 订单表(eb_store_order) + +```sql +CREATE TABLE `eb_store_order` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单ID', + `order_id` varchar(32) NOT NULL DEFAULT '' COMMENT '订单号(唯一)', + `uid` int(11) NOT NULL DEFAULT '0' COMMENT '用户ID', + `real_name` varchar(50) NOT NULL DEFAULT '' COMMENT '收货人姓名', + `user_phone` varchar(20) NOT NULL DEFAULT '' COMMENT '收货人电话', + `user_address` varchar(255) NOT NULL DEFAULT '' COMMENT '收货地址', + `cart_id` text COMMENT '购物车ID', + `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '商品总数', + `total_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品总价', + `total_postage` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '邮费', + `pay_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '实际支付金额', + `pay_postage` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '实际支付邮费', + `deduction_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '抵扣金额', + `coupon_id` int(11) NOT NULL DEFAULT '0' COMMENT '优惠券ID', + `coupon_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '优惠券金额', + `paid` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否支付(0未支付,1已支付)', + `pay_time` int(11) NOT NULL DEFAULT '0' COMMENT '支付时间', + `pay_type` varchar(20) NOT NULL DEFAULT '' COMMENT '支付方式', + `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态(0未支付,1待发货,2待收货,3已完成,-1已取消,-2退款中,-3已退款)', + `refund_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '退款状态', + `refund_reason` varchar(255) NOT NULL DEFAULT '' COMMENT '退款原因', + `refund_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '退款金额', + `delivery_name` varchar(50) NOT NULL DEFAULT '' COMMENT '快递公司名称', + `delivery_id` varchar(50) NOT NULL DEFAULT '' COMMENT '快递单号', + `delivery_type` varchar(20) NOT NULL DEFAULT 'express' COMMENT '配送方式(express快递,send商家配送,pick自取)', + `delivery_time` int(11) NOT NULL DEFAULT '0' COMMENT '发货时间', + `gain_integral` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '赠送积分', + `mark` varchar(500) NOT NULL DEFAULT '' COMMENT '买家备注', + `remark` varchar(500) NOT NULL DEFAULT '' COMMENT '商家备注', + `cost` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '成本价', + `is_del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除', + `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', + `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `idx_order_id` (`order_id`), + KEY `idx_uid` (`uid`), + KEY `idx_paid` (`paid`), + KEY `idx_status` (`status`), + KEY `idx_pay_time` (`pay_time`), + KEY `idx_create_time` (`create_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表'; +``` + +## 5. 索引设计规范 + +### 5.1 索引使用原则 + +**必须添加索引的场景:** +1. 主键字段 +2. 外键字段 +3. WHERE条件中的字段 +4. ORDER BY排序字段 +5. JOIN关联字段 +6. 唯一性约束字段 + +**索引命名规范:** +- 主键索引:`PRIMARY` +- 唯一索引:`uk_字段名` 或 `idx_字段名` +- 普通索引:`idx_字段名` +- 组合索引:`idx_字段1_字段2` +- 全文索引:`ft_字段名` + +**示例:** +```sql +-- 主键索引(自动创建) +PRIMARY KEY (`id`) + +-- 唯一索引 +UNIQUE KEY `uk_account` (`account`) +UNIQUE KEY `uk_phone` (`phone`) +UNIQUE KEY `uk_order_id` (`order_id`) + +-- 普通索引 +KEY `idx_user_id` (`user_id`) +KEY `idx_status` (`status`) +KEY `idx_create_time` (`create_time`) + +-- 组合索引 +KEY `idx_user_status` (`user_id`, `status`) +KEY `idx_create_type` (`create_time`, `type`) + +-- 全文索引 +FULLTEXT KEY `ft_keyword` (`keyword`, `name`) +``` + +### 5.2 组合索引最左前缀原则 + +**正确示例:** +```sql +-- 创建组合索引 +KEY `idx_user_status_time` (`user_id`, `status`, `create_time`) + +-- 以下查询会使用索引 +WHERE user_id = 1 +WHERE user_id = 1 AND status = 1 +WHERE user_id = 1 AND status = 1 AND create_time > 1234567890 +WHERE user_id = 1 AND create_time > 1234567890 -- 部分使用 + +-- 以下查询不会使用索引 +WHERE status = 1 -- 缺少最左列user_id +WHERE create_time > 1234567890 -- 缺少最左列user_id +WHERE status = 1 AND create_time > 1234567890 -- 缺少最左列user_id +``` + +### 5.3 索引优化建议 + +1. **选择性高的列放前面**:区分度高的字段放在组合索引前面 +2. **避免过多索引**:每个表索引数量不超过6个 +3. **避免冗余索引**:idx_a_b和idx_a是冗余的 +4. **定期维护索引**:使用 `OPTIMIZE TABLE` 优化表 +5. **监控索引使用**:使用 `EXPLAIN` 分析查询 + +**使用EXPLAIN分析:** +```sql +EXPLAIN SELECT * FROM eb_store_order WHERE user_id = 1 AND status = 1; + +-- 输出解读: +-- type: ALL(全表扫描,性能差) +-- type: const(主键查询,性能最好) +-- type: ref(索引查找,性能好) +-- type: range(范围查询,性能较好) +-- key: 使用的索引名 +-- rows: 扫描的行数(越少越好) +``` + +## 6. 数据类型优化 + +### 6.1 整数类型选择 + +| 类型 | 有符号范围 | 无符号范围 | 占用空间 | 适用场景 | +|------|-----------|-----------|----------|----------| +| TINYINT | -128~127 | 0~255 | 1字节 | 状态、布尔值、小范围枚举 | +| SMALLINT | -32768~32767 | 0~65535 | 2字节 | 分类ID、排序 | +| INT | -21亿~21亿 | 0~42亿 | 4字节 | 主键、用户ID、订单ID | +| BIGINT | 很大 | 很大 | 8字节 | 雪花算法ID、大数值 | + +**示例:** +```sql +-- 状态字段使用TINYINT +status TINYINT(1) NOT NULL DEFAULT '1' +is_del TINYINT(1) NOT NULL DEFAULT '0' +type TINYINT(1) NOT NULL DEFAULT '0' + +-- 主键使用INT或BIGINT +id INT(11) NOT NULL AUTO_INCREMENT +id BIGINT(20) NOT NULL AUTO_INCREMENT -- 分布式ID + +-- 分类ID、排序使用SMALLINT +cate_id SMALLINT(6) NOT NULL DEFAULT '0' +sort SMALLINT(6) NOT NULL DEFAULT '0' +``` + +### 6.2 小数类型选择 + +**金额使用DECIMAL(精确计算):** +```sql +-- 正确:金额使用DECIMAL +price DECIMAL(10,2) NOT NULL DEFAULT '0.00' +total_price DECIMAL(10,2) NOT NULL DEFAULT '0.00' +commission DECIMAL(10,2) NOT NULL DEFAULT '0.00' + +-- 参数说明:DECIMAL(M, D) +-- M: 总位数(整数+小数) +-- D: 小数位数 + +-- DECIMAL(10,2) 范围:-99999999.99 到 99999999.99 +``` + +**避免使用FLOAT/DOUBLE存储金额:** +```sql +-- 错误:FLOAT/DOUBLE无法精确表示小数 +price FLOAT -- 可能导致精度丢失 +price DOUBLE -- 可能导致精度丢失 +``` + +### 6.3 字符串类型选择 + +**VARCHAR vs TEXT:** +```sql +-- VARCHAR:变长,占用实际长度+1-2字节 +-- 适合短字符串,有长度限制 +account VARCHAR(30) -- 账号 +phone VARCHAR(11) -- 手机号 +real_name VARCHAR(50) -- 姓名 +title VARCHAR(255) -- 标题 + +-- TEXT:长文本,占用额外空间 +-- 适合长内容,无长度限制 +description TEXT -- 商品描述 +content TEXT -- 文章内容 +remark TEXT -- 备注 + +-- 性能考虑: +-- 1. VARCHAR可以创建索引,TEXT只能创建前缀索引 +-- 2. VARCHAR查询性能更好 +-- 3. TEXT字段会单独存储,查询时需要额外IO +``` + +### 6.4 时间存储方式 + +**时间戳(INT)vs DATETIME:** + +```sql +-- 方案1:使用INT存储时间戳(推荐) +create_time INT(11) NOT NULL DEFAULT '0' + +-- 优点: +-- 1. 时区灵活,可根据用户时区转换 +-- 2. 计算方便(加减秒数) +-- 3. 占用空间小(4字节) +-- 4. 兼容性好 + +-- 缺点: +-- 1. 不直观,需转换才能查看 +-- 2. 范围有限(2038年问题) + +-- 方案2:使用DATETIME +-- create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP + +-- 优点: +-- 1. 直观,可直接查看时间 +-- 2. 支持日期函数(YEAR(), MONTH()等) + +-- 缺点: +-- 1. 时区不灵活 +-- 2. 占用空间大(5-8字节) +-- 3. 性能略差 +``` + +## 7. 关联查询设计 + +### 7.1 一对多关系 + +**示例:用户和订单** +```sql +-- 用户表(一) +CREATE TABLE `eb_user` ( + `id` int(11) PRIMARY KEY, + `account` varchar(30), + ... +); + +-- 订单表(多) +CREATE TABLE `eb_store_order` ( + `id` int(11) PRIMARY KEY, + `user_id` int(11) NOT NULL, -- 关联用户表 + `order_id` varchar(32), + ... + KEY `idx_user_id` (`user_id`) -- 添加索引 +); + +-- 查询用户的所有订单 +SELECT o.* +FROM eb_store_order o +JOIN eb_user u ON o.user_id = u.id +WHERE u.id = 1; +``` + +### 7.2 多对多关系 + +**示例:用户和角色** +```sql +-- 用户表 +CREATE TABLE `eb_system_admin` ( + `id` int(11) PRIMARY KEY, + `account` varchar(30), + ... +); + +-- 角色表 +CREATE TABLE `eb_system_role` ( + `id` int(11) PRIMARY KEY, + `role_name` varchar(50), + ... +); + +-- 中间表(用户-角色关联) +CREATE TABLE `eb_system_admin_role` ( + `admin_id` int(11) NOT NULL, -- 用户ID + `role_id` int(11) NOT NULL, -- 角色ID + PRIMARY KEY (`admin_id`, `role_id`), -- 联合主键 + KEY `idx_admin_id` (`admin_id`), + KEY `idx_role_id` (`role_id`) +); + +-- 查询用户拥有的角色 +SELECT r.* +FROM eb_system_role r +JOIN eb_system_admin_role ar ON r.id = ar.role_id +WHERE ar.admin_id = 1; + +-- 查询拥有某角色的所有用户 +SELECT a.* +FROM eb_system_admin a +JOIN eb_system_admin_role ar ON a.id = ar.admin_id +WHERE ar.role_id = 1; +``` + +### 7.3 一对一关系 + +**示例:用户和用户详情** +```sql +-- 用户主表 +CREATE TABLE `eb_user` ( + `id` int(11) PRIMARY KEY, + `account` varchar(30), + ... +); + +-- 用户详情表 +CREATE TABLE `eb_user_info` ( + `id` int(11) PRIMARY KEY, + `user_id` int(11) NOT NULL, -- 关联用户ID + `birthday` int(11), + `address` varchar(255), + ... + UNIQUE KEY `uk_user_id` (`user_id`) -- 唯一索引,确保一对一 +); + +-- 查询用户详情 +SELECT u.*, ui.birthday, ui.address +FROM eb_user u +LEFT JOIN eb_user_info ui ON u.id = ui.user_id +WHERE u.id = 1; +``` + +## 8. 性能优化建议 + +### 8.1 表分区 + +**按时间分区(适用于大表):** +```sql +-- 订单表按月分区 +CREATE TABLE `eb_store_order` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `order_id` varchar(32), + `create_time` int(11), + ... +) ENGINE=InnoDB +PARTITION BY RANGE (create_time) ( + PARTITION p202501 VALUES LESS THAN (1735689600), -- 2025-01-01 + PARTITION p202502 VALUES LESS THAN (1738368000), -- 2025-02-01 + PARTITION p202503 VALUES LESS THAN (1740950400), -- 2025-03-01 + PARTITION p202504 VALUES LESS THAN (1743628800), -- 2025-04-01 + PARTITION p_max VALUES LESS THAN MAXVALUE +); + +-- 优点: +-- 1. 提高查询性能(只扫描相关分区) +-- 2. 方便数据归档(删除旧分区) +-- 3. 分散IO压力 +``` + +### 8.2 分表策略 + +**水平分表(按ID取模):** +```php +where('user_id', $userId) + ->select(); + +-- 分表规则: +-- eb_store_order_0: user_id取模为0 +-- eb_store_order_1: user_id取模为1 +-- ... +-- eb_store_order_9: user_id取模为9 +``` + +**垂直分表(按字段热度):** +```sql +-- 商品主表(常用字段) +CREATE TABLE `eb_store_product` ( + `id` int(11) PRIMARY KEY, + `store_name` varchar(255), + `price` decimal(10,2), + `stock` int(11), + ... +); + +-- 商品详情表(不常用字段) +CREATE TABLE `eb_store_product_detail` ( + `product_id` int(11) PRIMARY KEY, + `description` longtext, -- 详情(不常查询) + `slider_image` text, -- 轮播图(不常查询) + `parameter` text, -- 参数(不常查询) + ... +); +``` + +### 8.3 读写分离 + +**主从复制架构:** +```php + [ + 'type' => 'mysql', + 'hostname' => '192.168.1.1', + 'username' => 'root', + 'password' => 'password', + 'hostport' => '3306', +], + +// 从库(读操作) +'slaves' => [ + [ + 'type' => 'mysql', + 'hostname' => '192.168.1.2', + 'username' => 'root', + 'password' => 'password', + 'hostport' => '3306', + ], + [ + 'type' => 'mysql', + 'hostname' => '192.168.1.3', + 'username' => 'root', + 'password' => 'password', + 'hostport' => '3306', + ], +] + +// 在DAO层指定读写 +// 写操作(主库) +Db::name('user')->insert($data); + +// 读操作(从库) +Db::name('user')->readMaster(false)->find($id); +``` + +### 8.4 慢查询优化 + +**开启慢查询日志:** +```ini +# MySQL配置文件my.cnf +[mysqld] +slow_query_log = 1 +slow_query_log_file = /var/log/mysql/slow.log +long_query_time = 2 # 超过2秒的查询记录 +log_queries_not_using_indexes = 1 +``` + +**优化慢查询:** +```sql +-- 1. 使用EXPLAIN分析 +EXPLAIN SELECT * FROM eb_store_order +WHERE user_id = 1 AND status = 1 +ORDER BY id DESC; + +-- 2. 添加合适的索引 +CREATE INDEX idx_user_status ON eb_store_order(user_id, status); + +-- 3. 优化查询语句 +-- 错误:SELECT *(查询所有字段) +-- 正确:只查询需要的字段 +SELECT id, order_id, pay_price FROM eb_store_order +WHERE user_id = 1 AND status = 1; + +-- 4. 避免使用函数在WHERE条件中 +-- 错误:WHERE DATE(create_time) = '2025-01-01' +-- 正确:WHERE create_time >= 1735689600 AND create_time < 1735776000 +``` + +## 9. 数据备份与恢复 + +### 9.1 备份策略 + +**定期备份:** +```bash +#!/bin/bash +# 备份脚本 backup.sh +DATE=$(date +%Y%m%d_%H%M%S) +BACKUP_DIR="/backup/mysql" + +# 全量备份 +mysqldump -u root -p'password' crmeb > $BACKUP_DIR/crmeb_full_$DATE.sql + +# 压缩备份 +gzip $BACKUP_DIR/crmeb_full_$DATE.sql + +# 保留最近7天的备份 +find $BACKUP_DIR -name "crmeb_full_*.sql.gz" -mtime +7 -delete +``` + +### 9.2 数据恢复 + +```bash +# 恢复数据 +gunzip /backup/mysql/crmeb_full_20250317_000000.sql.gz +mysql -u root -p'password' crmeb < /backup/mysql/crmeb_full_20250317_000000.sql +``` + +## 10. 数据库监控 + +### 10.1 监控指标 + +**关键指标:** +- QPS(每秒查询数) +- TPS(每秒事务数) +- 慢查询数量 +- 连接数 +- 缓存命中率 +- 磁盘IO +- 表空间使用率 + +**监控工具:** +- MySQL自带:`SHOW STATUS`, `SHOW PROCESSLIST` +- 第三方:Prometheus + Grafana, Percona Monitoring + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-03-17 diff --git a/.codebuddy/skills/crmeb-complete/references/quick_start.md b/.codebuddy/skills/crmeb-complete/references/quick_start.md new file mode 100644 index 000000000..6768cda31 --- /dev/null +++ b/.codebuddy/skills/crmeb-complete/references/quick_start.md @@ -0,0 +1,411 @@ +# CRMEB快速开始指南 + +## 环境准备 + +### 1.1 安装Docker(推荐) + +```bash +# MacOS +brew install docker + +# 启动Docker +open /Applications/Docker.app +``` + +### 1.2 克隆项目 + +```bash +git clone https://gitee.com/ZhongBangKeJi/CRMEB.git +cd CRMEB +``` + +### 1.3 启动服务 + +```bash +# 使用docker-compose启动 +docker-compose up -d + +# 查看日志 +docker-compose logs -f + +# 查看运行状态 +docker-compose ps +``` + +**输出示例:** +``` +NAME COMMAND SERVICE STATUS PORTS +crmeb_mysql "docker-entrypoint.s…" mysql running 0.0.0.0:33061->3306/tcp +crmeb_redis "docker-entrypoint.s…" redis running 0.0.0.0:63791->6379/tcp +crmeb_php "docker-php-entrypoi…" phpfpm running 0.0.0.0:9000->9000/tcp, 0.0.0.0:40001-40002->40001-40002/tcp +crmeb_nginx "/docker-entrypoint.…" nginx running 0.0.0.0:8011->80/tcp +``` + +### 1.4 访问系统 + +**后台管理:** +- URL: http://localhost:8011/admin +- 账号: admin +- 密码: crmeb.com + +**前端商城:** +- URL: http://localhost:8011 +- 移动端: 浏览器模拟手机访问 + +**数据库:** +- Host: localhost:33061 +- 账号: root +- 密码: 123456 +- 数据库: crmeb + +**Redis:** +- Host: localhost:63791 +- 密码: 123456 + +### 1.5 启动后台服务 + +```bash +# 进入PHP容器 +docker exec -it crmeb_php bash + +# 在容器内启动队列(必须) +php think queue:listen --queue + +# 启动定时任务(可选) +php think timer start --d + +# 启动WebSocket(可选,用于实时通知) +php think workerman start --d +``` + +## 手动安装(非Docker) + +### 2.1 环境要求 + +- PHP 7.1 - 7.4 +- MySQL 5.7+ +- Redis 5.0+(可选) +- Composer +- Node.js 14+ + +### 2.2 安装步骤 + +```bash +# 1. 安装PHP依赖 +cd crmeb +composer install + +# 如果安装慢,使用国内镜像 +composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ +composer install + +# 2. 配置环境变量 +cp .env.example .env + +# 3. 修改.env配置文件 +APP_DEBUG = false + +[APP] +DEFAULT_TIMEZONE = Asia/Shanghai + +[DATABASE] +TYPE = mysql +HOSTNAME = 127.0.0.1 +HOSTPORT = 3306 +USERNAME = root +PASSWORD = your_password +DATABASE = crmeb +PREFIX = eb_ +CHARSET = utf8mb4 + +[REDIS] +REDIS_HOSTNAME = 127.0.0.1 +PORT = 6379 +REDIS_PASSWORD = your_password +SELECT = 0 + +# 4. 导入数据库 +mysql -u root -p crmeb < database.sql + +# 5. 设置目录权限 +chmod -R 755 runtime +chmod -R 755 public/uploads + +# 6. 配置Nginx/Apache +# Nginx配置示例: +server { + listen 80; + server_name your-domain.com; + root /path/to/CRMEB/crmeb/public; + index index.php index.html; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass 127.0.0.1:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } +} + +# 7. 启动队列(必须) +php think queue:listen --queue + +# 8. 启动定时任务(可选) +php think timer start --d + +# 9. 启动WebSocket(可选) +php think workerman start --d +``` + +### 2.3 前端构建 + +**管理端:** +```bash +cd template/admin + +# 安装依赖 +npm install + +# 开发环境 +npm run dev + +# 生产构建 +npm run build +``` + +**移动端(UniApp):** +```bash +cd template/uni-app + +# 安装依赖 +npm install + +# 开发环境 - H5 +npm run dev:h5 + +# 开发环境 - 微信小程序 +npm run dev:mp-weixin + +# 生产构建 - H5 +npm run build:h5 + +# 生产构建 - 微信小程序 +npm run build:mp-weixin +``` + +## 验证安装 + +### 3.1 检查后端API + +```bash +# 使用curl测试API +curl http://localhost:8011/api/index + +# 预期响应 +{"code":200,"msg":"ok","data":{...}} +``` + +### 3.2 检查队列 + +```bash +# 进入PHP容器 +docker exec -it crmeb_php bash + +# 查看队列状态 +php think queue:status +``` + +### 3.3 检查定时任务 + +```bash +# 查看定时任务状态 +php think timer status +``` + +### 3.4 检查WebSocket + +```bash +# 查看WebSocket服务状态 +php think workerman status +``` + +## 常见问题 + +### 4.1 Docker容器无法启动 + +**问题:** +``` +Error: Ports are not available: exposing port TCP 0.0.0.0:33061 +``` + +**解决:** +```bash +# 检查端口占用 +lsof -i :33061 +lsof -i :63791 +lsof -i :8011 + +# 杀死占用进程 +kill -9 + +# 修改docker-compose.yml中的端口映射 +# 例如:将 "33061:3306" 改为 "33062:3306" +``` + +### 4.2 MySQL连接失败 + +**问题:** +``` +SQLSTATE[HY000] [2002] Connection refused +``` + +**解决:** +```bash +# 检查MySQL容器状态 +docker ps | grep mysql + +# 查看MySQL日志 +docker logs crmeb_mysql + +# 检查.env配置 +# 使用Docker时HOSTNAME应为crmeb_mysql +# 手动安装时HOSTNAME应为127.0.0.1 + +# 测试MySQL连接 +docker exec -it crmeb_mysql mysql -u root -p +``` + +### 4.3 Redis连接失败 + +**问题:** +``` +RedisException: Connection refused +``` + +**解决:** +```bash +# 检查Redis容器状态 +docker ps | grep redis + +# 测试Redis连接 +docker exec -it crmeb_redis redis-cli -a 123456 ping + +# 检查.env配置 +# REDIS_HOSTNAME应为crmeb_mysql(Docker)或127.0.0.1(手动安装) +``` + +### 4.4 队列不工作 + +**问题:** +``` +队列任务不执行,消息积压在Redis中 +``` + +**解决:** +```bash +# 检查队列进程 +ps aux | grep queue + +# 重新启动队列 +docker exec -it crmeb_php php think queue:restart +docker exec -it crmeb_php php think queue:listen --queue + +# 查看队列日志 +docker exec -it crmeb_php tail -f runtime/log/queue.log +``` + +### 4.5 前端页面空白 + +**问题:** +``` +访问http://localhost:8011/admin,页面空白或404 +``` + +**解决:** +```bash +# 检查Nginx配置 +docker exec -it crmeb_nginx cat /etc/nginx/conf.d/default.conf + +# 检查public目录是否存在 +docker exec -it crmeb_php ls -la /var/www/public/admin/ + +# 如果是手动安装,确保Nginx配置正确 +# root指向/crmeb/public目录 +# 确保伪静态配置正确 + +# 重新构建前端(手动安装) +cd template/admin +npm run build +``` + +### 4.6 图片上传失败 + +**问题:** +``` +上传图片提示失败,或无法显示 +``` + +**解决:** +```bash +# 检查上传目录权限 +docker exec -it crmeb_php ls -la /var/www/public/uploads/ + +# 修改权限 +docker exec -it crmeb_php chmod -R 755 /var/www/public/uploads/ + +# 检查存储配置 +# 后台管理 > 系统设置 > 文件存储 +``` + +### 4.7 微信支付配置 + +**配置步骤:** +1. 登录微信商户平台:https://pay.weixin.qq.com +2. 获取商户号(MCH_ID) +3. 获取API密钥(KEY) +4. 下载API证书(apiclient_key.pem, apiclient_cert.pem) +5. 在微信开放平台获取AppID和AppSecret +6. 后台配置:系统设置 > 支付配置 > 微信支付 + +**注意:** +- 公众号支付需要配置JS接口安全域名 +- 小程序支付需要在小程序后台配置 +- 支付目录需要配置正确 +- 回调地址需要外网可访问 + +### 4.8 支付宝支付配置 + +**配置步骤:** +1. 登录支付宝开放平台:https://open.alipay.com +2. 创建应用并获取APP_ID +3. 生成RSA2密钥(应用私钥、公钥) +4. 配置支付宝公钥 +5. 签约支付产品(手机网站支付、当面付等) +6. 后台配置:系统设置 > 支付配置 > 支付宝支付 + +## 下一步 + +完成安装后,你可以: + +1. **阅读代码结构文档**:了解项目架构和目录结构 +2. **查看专项Skill文档**: + - PHP后端开发:`.codebuddy/skills/php-api/SKILL.md` + - 管理端前端:`.codebuddy/skills/admin-element/SKILL.md` + - 移动端开发:`.codebuddy/skills/uniapp/SKILL.md` + +3. **尝试代码生成器**:在后台管理中快速生成CRUD代码 + +4. **开发新功能**:参考开发规范,创建你的第一个功能模块 + +5. **查看示例代码**:在`crmeb/app/services/`中查看现有功能实现 + +6. **加入社区**:加入CRMEB技术社区,获取更多帮助 + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-03-17 diff --git a/.codebuddy/skills/crmeb-complete/references/system_config.md b/.codebuddy/skills/crmeb-complete/references/system_config.md new file mode 100644 index 000000000..9a8fbf9fa --- /dev/null +++ b/.codebuddy/skills/crmeb-complete/references/system_config.md @@ -0,0 +1,1024 @@ +# CRMEB系统配置详解 + +## 1. 配置文件结构 + +CRMEB使用多文件配置方式,配置文件位于 `crmeb/config/` 目录: + +``` +config/ +├── app.php # 应用配置 +├── cache.php # 缓存配置 +├── cookie.php # Cookie配置 +├── database.php # 数据库配置 +├── log.php # 日志配置 +├── middleware.php # 中间件配置 +├── queue.php # 队列配置 +├── route.php # 路由配置 +├── session.php # Session配置 +├── template.php # 模板配置 +├── trace.php # 调试配置 +├── workerman.php # Workerman配置 +└── ... +``` + +系统还支持环境变量配置(`.env` 文件),可以覆盖配置文件中的设置。 + +## 2. 应用配置(app.php) + +**配置文件:** `crmeb/config/app.php` + +**主要配置项:** + +```php + 'CRMEB', + + // 应用版本 + 'app_version' => '5.6.4', + + // 应用调试模式 + 'app_debug' => false, + + // 应用Trace调试 + 'app_trace' => false, + + // 是否支持多应用 + 'app_multi_app' => true, + + // 入口自动绑定应用 + 'auto_bind_app' => true, + + // 应用映射(自动多应用模式有效) + 'app_map' => [ + 'adminapi' => 'adminapi', + 'api' => 'api', + 'kefuapi' => 'kefuapi', + 'outapi' => 'outapi', + ], + + // 域名绑定(自动多应用模式有效) + 'domain_bind' => [ + // 'adminapi.crmeb.com' => 'adminapi', + // 'api.crmeb.com' => 'api', + ], + + // 默认应用 + 'default_app' => 'home', + + // 默认时区 + 'default_timezone' => 'Asia/Shanghai', + + // 异常处理handle类 + 'exception_handle' => '\app\ExceptionHandle', +]; +``` + +**环境变量配置(.env):** +```env +APP_DEBUG = false +DEFAULT_TIMEZONE = Asia/Shanghai +``` + +## 3. 数据库配置(database.php) + +**配置文件:** `crmeb/config/database.php` + +**主要配置项:** + +```php + env('database.type', 'mysql'), + + // 时间字段取出后的默认时间格式 + 'datetime_format' => 'Y-m-d H:i:s', + + // 数据库连接信息 + 'connections' => [ + 'mysql' => [ + // 数据库类型 + 'type' => 'mysql', + // 服务器地址 + 'hostname' => env('database.hostname', '127.0.0.1'), + // 数据库名 + 'database' => env('database.database', 'crmeb'), + // 用户名 + 'username' => env('database.username', 'root'), + // 密码 + 'password' => env('database.password', ''), + // 端口 + 'hostport' => env('database.hostport', '3306'), + // 数据库连接参数 + 'params' => [ + PDO::ATTR_CASE => PDO::CASE_NATURAL, + ], + // 字符集 + 'charset' => env('database.charset', 'utf8mb4'), + // 数据库表前缀 + 'prefix' => env('database.prefix', 'eb_'), + // 数据库调试模式 + 'debug' => env('database.debug', false), + // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) + 'deploy' => 0, + // 数据库读写是否分离 主从式有效 + 'rw_separate' => false, + // 读写分离后 主服务器数量 + 'master_num' => 1, + // 指定从服务器序号 + 'slave_no' => '', + // 是否严格检查字段是否存在 + 'fields_strict' => true, + // 是否需要断线重连 + 'break_reconnect' => false, + // 监听SQL + 'trigger_sql' => true, + // 开启字段缓存 + 'fields_cache' => false, + ], + ], +]; +``` + +**环境变量配置(.env):** +```env +[DATABASE] +TYPE = mysql +HOSTNAME = 127.0.0.1 +HOSTPORT = 3306 +USERNAME = root +PASSWORD = 123456 +DATABASE = crmeb +PREFIX = eb_ +CHARSET = utf8mb4 +DEBUG = false +``` + +**读写分离配置示例:** +```php + [ + 'mysql' => [ + // 主库(写操作) + 'hostname' => '192.168.1.1,192.168.1.2', + 'username' => 'root', + 'password' => 'password', + 'hostport' => '3306', + 'deploy' => 1, // 1 分布式 + 'rw_separate' => true, // 读写分离 + 'master_num' => 1, // 主库数量 + 'slave_no' => '', // 从库序号 + ], + ], +]; +``` + +## 4. 缓存配置(cache.php) + +**配置文件:** `crmeb/config/cache.php` + +**主要配置项:** + +```php + env('cache.driver', 'redis'), + + // 缓存连接方式配置 + 'stores' => [ + 'file' => [ + // 驱动方式 + 'type' => 'file', + // 缓存保存目录 + 'path' => '../runtime/cache/', + // 缓存前缀 + 'prefix' => 'eb_', + // 缓存有效期 0表示永久缓存 + 'expire' => 0, + ], + + 'redis' => [ + // 驱动方式 + 'type' => 'redis', + // 服务器地址 + 'host' => env('redis.hostname', '127.0.0.1'), + // 端口 + 'port' => env('redis.port', 6379), + // 密码 + 'password' => env('redis.password', ''), + // 缓存前缀 + 'prefix' => env('cache.prefix', 'eb_'), + // 缓存有效期 + 'expire' => 3600, + // 数据库索引 + 'select' => env('redis.select', 0), + // 序列化机制 + 'serialize' => true, + ], + ], +]; +``` + +**环境变量配置(.env):** +```env +[CACHE] +DRIVER = redis +CACHE_PREFIX = cache_ + +[REDIS] +REDIS_HOSTNAME = 127.0.0.1 +PORT = 6379 +REDIS_PASSWORD = 123456 +SELECT = 0 +``` + +## 5. 队列配置(queue.php) + +**配置文件:** `crmeb/config/queue.php` + +**主要配置项:** + +```php + 'redis', + + // 队列驱动配置 + 'connections' => [ + 'sync' => [ + // 同步驱动 + 'type' => 'sync', + ], + + 'redis' => [ + // 驱动方式 + 'type' => 'redis', + // 队列名称 + 'queue' => env('queue.queue_name', 'default'), + // 错误重试次数 + 'retry' => 3, + // redis配置 + 'host' => env('redis.hostname', '127.0.0.1'), + 'port' => env('redis.port', 6379), + 'password' => env('redis.password', ''), + 'select' => env('redis.select', 0), + 'timeout' => 0, + 'persistent' => false, + ], + + 'database' => [ + // 数据库驱动 + 'type' => 'database', + // 队列表名 + 'queue' => 'jobs', + // 错误重试次数 + 'retry' => 3, + ], + ], + + // 队列驱动配置 + 'failed' => [ + // 驱动类型 + 'type' => 'redis', + // 错误日志记录 + 'log' => true, + // redis配置 + 'host' => env('redis.hostname', '127.0.0.1'), + 'port' => env('redis.port', 6379), + 'password' => env('redis.password', ''), + 'select' => env('redis.select', 0), + 'timeout' => 0, + 'persistent' => false, + ], +]; +``` + +**环境变量配置(.env):** +```env +[QUEUE] +QUEUE_NAME = default +``` + +**使用示例:** +```php + [ + // 协议 + 'protocol' => 'websocket', + // 监听地址 + 'ip' => '0.0.0.0', + // 监听端口 + 'port' => 40001, + // 进程数 + 'processes' => 1, + // 心跳间隔(秒) + 'heartbeat' => 30, + // 心跳失败次数 + 'max_fail_count' => 2, + ], + + // 客服消息服务 + 'chat' => [ + 'protocol' => 'websocket', + 'ip' => '0.0.0.0', + 'port' => 40002, + 'processes' => 1, + 'heartbeat' => 30, + 'max_fail_count' => 2, + ], + + // 内部通讯服务 + 'channel' => [ + 'protocol' => 'tcp', + 'ip' => '127.0.0.1', + 'port' => 40003, + 'processes' => 1, + ], + + // 定时任务服务 + 'timer' => [ + // 是否开启定时任务 + 'enable' => true, + // 进程数 + 'processes' => 1, + // 任务列表 + 'jobs' => [ + // 取消未支付订单 + 'cancel_unpaid_order' => [ + 'cron' => '*/30 * * * *', // 每30分钟 + 'class' => '\app\jobs\UnpaidOrderCancelJob', + ], + // 自动确认收货 + 'auto_confirm_receive' => [ + 'cron' => '0 2 * * *', // 每天凌晨2点 + 'class' => '\app\jobs\AutoConfirmJob', + ], + // 自动好评 + 'auto_comment' => [ + 'cron' => '0 3 * * *', // 每天凌晨3点 + 'class' => '\app\jobs\AutoCommentJob', + ], + // 关闭拼团 + 'close_pink' => [ + 'cron' => '*/10 * * * *', // 每10分钟 + 'class' => '\app\jobs\PinkJob', + ], + // 关闭砍价 + 'close_bargain' => [ + 'cron' => '*/10 * * * *', // 每10分钟 + 'class' => '\app\jobs\BargainJob', + ], + // 积分过期处理 + 'integral_expire' => [ + 'cron' => '0 4 * * *', // 每天凌晨4点 + 'class' => '\app\jobs\IntegralExpireJob', + ], + // 优惠券过期处理 + 'coupon_expire' => [ + 'cron' => '0 5 * * *', // 每天凌晨5点 + 'class' => '\app\jobs\CouponExpireJob', + ], + // 佣金结算 + 'commission_settle' => [ + 'cron' => '0 6 * * *', // 每天凌晨6点 + 'class' => '\app\jobs\CommissionJob', + ], + ], + ], +]; +``` + +**启动命令:** +```bash +# 启动Workerman服务 +php think workerman start --d + +# 停止服务 +php think workerman stop + +# 重启服务 +php think workerman restart + +# 查看状态 +php think workerman status + +# 平滑重启 +php think workerman reload +``` + +## 7. 日志配置(log.php) + +**配置文件:** `crmeb/config/log.php` + +**主要配置项:** + +```php + env('log.channel', 'file'), + + // 日志记录级别 + 'level' => ['info', 'error', 'warning', 'debug'], + + // 日志类型记录的通道 + 'type_channel' => [ + 'error' => ['file', 'email'], + ], + + // 日志通道列表 + 'channels' => [ + 'file' => [ + // 驱动方式 + 'type' => 'file', + // 日志保存目录 + 'path' => '../runtime/log/', + // 单个日志文件的大小限制(超过会生成新文件) + 'file_size' => 2097152, + // 日志的时间格式 + 'time_format' => 'c', + // 日志输出格式化 + 'format' => '[%s][%s] %s', + // 是否JSON格式记录 + 'json' => false, + ], + + 'order' => [ + 'type' => 'file', + 'path' => '../runtime/log/order/', + 'file_size' => 2097152, + 'json' => false, + ], + + 'pay' => [ + 'type' => 'file', + 'path' => '../runtime/log/pay/', + 'file_size' => 2097152, + 'json' => false, + ], + ], +]; +``` + +**使用示例:** +```php + $orderId]); +Log::error('支付失败', ['order_id' => $orderId, 'error' => $error]); +Log::warning('库存不足', ['product_id' => $productId]); + +// 指定通道记录 +Log::channel('order')->info('订单日志', ['order_id' => $orderId]); +Log::channel('pay')->info('支付日志', ['pay_id' => $payId]); +``` + +## 8. 文件存储配置 + +### 8.1 本地存储 + +**配置位置:** 后台管理 > 系统设置 > 文件存储 + +**配置参数:** +```php +// config/filesystem.php +return [ + 'default' => 'public', + + 'disks' => [ + 'public' => [ + 'type' => 'local', + 'root' => app()->getRootPath() . 'public/storage', + 'url' => '/storage', + ], + ], +]; +``` + +### 8.2 云存储配置 + +**阿里云OSS:** +```php +'aliyun' => [ + 'type' => 'aliyun', + 'accessId' => env('oss.access_id', ''), + 'accessSecret' => env('oss.access_secret', ''), + 'bucket' => env('oss.bucket', ''), + 'endpoint' => env('oss.endpoint', ''), + 'domain' => env('oss.domain', ''), + 'timeout' => 3600, +], +``` + +**腾讯云COS:** +```php +'tencent' => [ + 'type' => 'tencent', + 'region' => env('cos.region', ''), + 'appId' => env('cos.app_id', ''), + 'secretId' => env('cos.secret_id', ''), + 'secretKey' => env('cos.secret_key', ''), + 'bucket' => env('cos.bucket', ''), + 'timeout' => 3600, +], +``` + +**七牛云:** +```php +'qiniu' => [ + 'type' => 'qiniu', + 'accessKey' => env('qiniu.access_key', ''), + 'secretKey' => env('qiniu.secret_key', ''), + 'bucket' => env('qiniu.bucket', ''), + 'domain' => env('qiniu.domain', ''), + 'timeout' => 3600, +], +``` + +## 9. 微信支付配置 + +### 9.1 配置参数 + +**配置文件:** `crmeb/config/wechat.php` + +```php + [ + 'app_id' => env('wechat.official_account_app_id', ''), + 'secret' => env('wechat.official_account_secret', ''), + 'token' => env('wechat.official_account_token', ''), + 'aes_key' => env('wechat.official_account_aes_key', ''), + 'mch_id' => env('wechat.mch_id', ''), // 商户号 + 'key' => env('wechat.key', ''), // API密钥 + 'cert_path' => env('wechat.cert_path', ''), // 证书路径 + 'key_path' => env('wechat.key_path', ''), // 证书密钥路径 + ], + + // 小程序 + 'mini_program' => [ + 'app_id' => env('wechat.mini_program_app_id', ''), + 'secret' => env('wechat.mini_program_secret', ''), + 'mch_id' => env('wechat.mch_id', ''), + 'key' => env('wechat.key', ''), + 'cert_path' => env('wechat.cert_path', ''), + 'key_path' => env('wechat.key_path', ''), + ], + + // 开放平台 + 'open_platform' => [ + 'app_id' => env('wechat.open_platform_app_id', ''), + 'secret' => env('wechat.open_platform_secret', ''), + 'token' => env('wechat.open_platform_token', ''), + 'aes_key' => env('wechat.open_platform_aes_key', ''), + ], + + // 企业微信 + 'work' => [ + 'corp_id' => env('wechat.work_corp_id', ''), + 'agent_id' => env('wechat.work_agent_id', ''), + 'secret' => env('wechat.work_secret', ''), + ], + + // 支付配置 + 'payment' => [ + 'mch_id' => env('wechat.mch_id', ''), + 'key' => env('wechat.key', ''), + 'cert_path' => env('wechat.cert_path', ''), + 'key_path' => env('wechat.key_path', ''), + 'notify_url' => env('wechat.notify_url', ''), + ], +]; +``` + +**环境变量配置(.env):** +```env +[WECHAT] +MCH_ID = 1234567890 +KEY = your_api_key +CERT_PATH = /path/to/apiclient_cert.pem +KEY_PATH = /path/to/apiclient_key.pem + +[WECHAT_OFFICIAL_ACCOUNT] +APP_ID = wx1234567890abcdef +SECRET = your_secret +TOKEN = your_token +AES_KEY = your_aes_key + +[WECHAT_MINI_PROGRAM] +APP_ID = wx1234567890abcdef +SECRET = your_secret +``` + +## 10. 支付宝配置 + +**配置文件:** `crmeb/config/alipay.php` + +```php + env('alipay.app_id', ''), + + // 商户私钥 + 'merchant_private_key' => env('alipay.merchant_private_key', ''), + + // 支付宝公钥 + 'alipay_public_key' => env('alipay.alipay_public_key', ''), + + // 支付宝网关 + 'gateway_url' => 'https://openapi.alipay.com/gateway.do', + + // 异步通知地址 + 'notify_url' => env('alipay.notify_url', ''), + + // 同步回调地址 + 'return_url' => env('alipay.return_url', ''), + + // 字符编码 + 'charset' => 'UTF-8', + + // 签名方式 + 'sign_type' => 'RSA2', + + // 是否沙箱模式 + 'sandbox' => false, +]; +``` + +**环境变量配置(.env):** +```env +[ALIPAY] +APP_ID = 2021001234567890 +MERCHANT_PRIVATE_KEY = MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC... +ALIPAY_PUBLIC_KEY = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... +NOTIFY_URL = https://yourdomain.com/api/alipay/notify +RETURN_URL = https://yourdomain.com/pages/pay/success +``` + +## 11. 短信服务配置 + +### 11.1 阿里云短信 + +**配置文件:** `crmeb/config/sms.php` + +```php + env('sms.default', 'aliyun'), + + // 短信驱动配置 + 'drivers' => [ + 'aliyun' => [ + 'access_key_id' => env('aliyun.access_key_id', ''), + 'access_key_secret' => env('aliyun.access_key_secret', ''), + 'sign_name' => env('aliyun.sign_name', ''), + 'endpoint' => 'dysmsapi.aliyuncs.com', + 'region_id' => 'cn-hangzhou', + ], + + 'tencent' => [ + 'secret_id' => env('tencent.secret_id', ''), + 'secret_key' => env('tencent.secret_key', ''), + 'app_id' => env('tencent.app_id', ''), + 'sign_name' => env('tencent.sign_name', ''), + 'endpoint' => 'sms.tencentcloudapi.com', + 'region' => 'ap-guangzhou', + ], + ], + + // 短信模板 + 'templates' => [ + 'verify' => [ + 'aliyun' => env('aliyun.template_code.verify', ''), + 'tencent' => env('tencent.template_code.verify', ''), + ], + 'order_pay' => [ + 'aliyun' => env('aliyun.template_code.order_pay', ''), + 'tencent' => env('tencent.template_code.order_pay', ''), + ], + ], +]; +``` + +**环境变量配置(.env):** +```env +[ALIYUN] +ACCESS_KEY_ID = your_access_key_id +ACCESS_KEY_SECRET = your_access_key_secret +SIGN_NAME = CRMEB商城 +TEMPLATE_CODE_VERIFY = SMS_12345678 +TEMPLATE_CODE_ORDER_PAY = SMS_12345679 + +[TENCENT] +SECRET_ID = your_secret_id +SECRET_KEY = your_secret_key +APP_ID = 1400123456 +SIGN_NAME = CRMEB商城 +TEMPLATE_CODE_VERIFY = 123456 +TEMPLATE_CODE_ORDER_PAY = 123457 +``` + +## 12. 邮件服务配置 + +**配置文件:** `crmeb/config/mail.php` + +```php + env('mail.host', 'smtp.qq.com'), + + // SMTP端口 + 'port' => env('mail.port', 465), + + // 加密方式(ssl/tls) + 'encryption' => env('mail.encryption', 'ssl'), + + // 用户名 + 'username' => env('mail.username', ''), + + // 密码/授权码 + 'password' => env('mail.password', ''), + + // 发件人邮箱 + 'from_address' => env('mail.from_address', ''), + + // 发件人名称 + 'from_name' => env('mail.from_name', 'CRMEB'), + + // 超时时间 + 'timeout' => 30, +]; +``` + +**环境变量配置(.env):** +```env +[MAIL] +HOST = smtp.qq.com +PORT = 465 +ENCRYPTION = ssl +USERNAME = your_email@qq.com +PASSWORD = your_authorization_code +FROM_ADDRESS = your_email@qq.com +FROM_NAME = CRMEB商城 +``` + +## 13. 第三方登录配置 + +**配置文件:** `crmeb/config/oauth.php` + +```php + [ + 'app_id' => env('oauth.qq_app_id', ''), + 'app_key' => env('oauth.qq_app_key', ''), + 'callback' => env('oauth.qq_callback', ''), + ], + + // 微信登录 + 'wechat' => [ + 'app_id' => env('oauth.wechat_app_id', ''), + 'app_key' => env('oauth.wechat_app_key', ''), + 'callback' => env('oauth.wechat_callback', ''), + ], + + // 微博登录 + 'weibo' => [ + 'app_id' => env('oauth.weibo_app_id', ''), + 'app_key' => env('oauth.weibo_app_key', ''), + 'callback' => env('oauth.weibo_callback', ''), + ], +]; +``` + +## 14. 安全配置 + +**配置文件:** `crmeb/config/secure.php` + +```php + [ + // 是否开启验证码 + 'captcha' => true, + // 同一IP最大尝试次数 + 'max_attempts' => 5, + // 锁定时间(分钟) + 'lock_time' => 30, + ], + + // API安全 + 'api' => [ + // 是否开启签名验证 + 'sign_check' => false, + // 签名密钥 + 'sign_key' => env('secure.sign_key', 'your_sign_key'), + // 请求有效期(秒) + 'request_expire' => 600, + ], + + // 支付安全 + 'pay' => [ + // 支付超时时间(分钟) + 'timeout' => 30, + // 同一订单最大支付尝试次数 + 'max_attempts' => 3, + ], + + // 密码安全 + 'password' => [ + // 最小长度 + 'min_length' => 6, + // 最大长度 + 'max_length' => 20, + // 是否包含数字 + 'require_number' => false, + // 是否包含字母 + 'require_alpha' => false, + // 是否包含特殊字符 + 'require_symbol' => false, + ], +]; +``` + +## 15. 环境变量配置示例 + +**完整的.env配置示例:** + +```env +APP_DEBUG = false + +[APP] +DEFAULT_TIMEZONE = Asia/Shanghai + +[DATABASE] +TYPE = mysql +HOSTNAME = 127.0.0.1 +HOSTPORT = 3306 +USERNAME = root +PASSWORD = your_password +DATABASE = crmeb +PREFIX = eb_ +CHARSET = utf8mb4 +DEBUG = false + +[LANG] +default_lang = zh-cn + +[CACHE] +DRIVER = redis +CACHE_PREFIX = cache_ +CACHE_TAG_PREFIX = cache_tag_ + +[REDIS] +REDIS_HOSTNAME = 127.0.0.1 +PORT = 6379 +REDIS_PASSWORD = your_redis_password +SELECT = 0 + +[QUEUE] +QUEUE_NAME = default + +[WECHAT] +MCH_ID = 1234567890 +KEY = your_wechat_pay_key +CERT_PATH = /path/to/apiclient_cert.pem +KEY_PATH = /path/to/apiclient_key.pem +NOTIFY_URL = https://yourdomain.com/api/wechat/notify + +[WECHAT_OFFICIAL_ACCOUNT] +APP_ID = wx1234567890abcdef +SECRET = your_official_secret +TOKEN = your_token +AES_KEY = your_aes_key + +[WECHAT_MINI_PROGRAM] +APP_ID = wx1234567890abcdef +SECRET = your_mini_secret + +[ALIPAY] +APP_ID = 2021001234567890 +MERCHANT_PRIVATE_KEY = your_merchant_private_key +ALIPAY_PUBLIC_KEY = your_alipay_public_key +NOTIFY_URL = https://yourdomain.com/api/alipay/notify +RETURN_URL = https://yourdomain.com/pages/pay/success + +[ALIYUN] +ACCESS_KEY_ID = your_access_key_id +ACCESS_KEY_SECRET = your_access_key_secret +SIGN_NAME = CRMEB商城 +TEMPLATE_CODE_VERIFY = SMS_12345678 + +[OSS] +TYPE = aliyun +ACCESS_ID = your_oss_access_id +ACCESS_SECRET = your_oss_access_secret +BUCKET = your_bucket +ENDPOINT = oss-cn-hangzhou.aliyuncs.com +DOMAIN = https://yourdomain.oss-cn-hangzhou.aliyuncs.com + +[COS] +TYPE = tencent +REGION = ap-guangzhou +APP_ID = 1234567890 +SECRET_ID = your_cos_secret_id +SECRET_KEY = your_cos_secret_key +BUCKET = your_bucket-1234567890 +DOMAIN = https://yourbucket-1234567890.cos.ap-guangzhou.myqcloud.com + +[MAIL] +HOST = smtp.qq.com +PORT = 465 +ENCRYPTION = ssl +USERNAME = your_email@qq.com +PASSWORD = your_email_password +FROM_ADDRESS = your_email@qq.com +FROM_NAME = CRMEB商城 + +[SECURE] +SIGN_KEY = your_sign_key +JWT_SECRET = your_jwt_secret +JWT_EXPIRE = 86400 + +[QUEUE] +QUEUE_NAME = default + +[SESSION] +PREFIX = session_ +EXPIRE = 86400 + +[TOKEN] +EXPIRE = 86400 +``` + +## 16. 配置热更新 + +CRMEB支持通过后台管理界面动态修改部分配置,无需重启服务。 + +**支持的配置项:** +- 站点基本信息 +- 支付配置 +- 短信配置 +- 邮件配置 +- 文件存储配置 +- 第三方登录配置 +- 营销功能配置 +- 分销配置 + +**配置存储位置:** +- 数据库:`eb_system_config` 表 +- 缓存:Redis(自动同步) + +**使用方式:** +```php + $value]); +``` + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-03-17 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..684e02229 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,177 @@ +# =========================================== +# Docker 构建镜像过滤配置文件 +# 作用:在 docker build 时排除不需要的文件,减小构建上下文 +# =========================================== + +# =========================================== +# 1. 版本控制与 Git 相关 +# =========================================== +.git +.gitignore +.gitattributes +.gitmodules + +# =========================================== +# 2. Docker 相关文件(构建时使用,不需要进入镜像) +# =========================================== +Dockerfile +.dockerignore +docker-compose*.yml +docker-compose*.yaml +.docker +Dockerfile.* +*.mdc + +# =========================================== +# 3. IDE 和编辑器配置 +# =========================================== +.idea/ +.vscode/ +.vs/ +*.swp +*.swo +*~ +.DS_Store +Thumbs.db +ehthumbs.db +Desktop.ini + +# =========================================== +# 4. 项目辅助目录 +# =========================================== +help/ +template/ +docs/ +doc/ +*.md +LICENSE +README* +CHANGELOG* +CHANGE* +HISTORY* +CONTRIBUTING* + +# =========================================== +# 5. 缓存和临时文件 +# =========================================== +.runtime/ +runtime/ +*.log +*.tmp +*.temp +*.cache +*.bak +*.backup +*_backup +*.old +*.swp +*.swo +*~ +.DS_Store + +# =========================================== +# 6. Node.js 相关(前端依赖,构建后不需要) +# =========================================== +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.npm +.yarn/ +.browserslistrc +.eslintcache +.node_repl_history + +# =========================================== +# 7. PHP Composer 依赖(不使用时的清理) +# =========================================== +# 注意:如果 vendor 目录需要,进入镜像时不要排除 +# 如果使用 composer install 构建,则可以排除 +# vendor/test/ +# vendor/tests/ +# vendor/docs/ +# vendor/*.txt +# vendor/*.md + +# =========================================== +# 8. 大型字体文件(不必要的资源) +# =========================================== +# simsun.ttc +# WenQuanZhengHei.ttf +crmeb/vendor/dh2y/think-qrcode/src/simsun.ttc +crmeb/vendor/fastknife/ajcaptcha/resources/fonts/WenQuanZhengHei.ttf + +# =========================================== +# 9. 数据库和安装文件(运行镜像时重新生成) +# =========================================== +*.sql +*.sql.gz +*.sql.bak + +# =========================================== +# 10. 测试和开发文件 +# =========================================== +phpunit.xml +phpunit.xml.dist +tests/ +test/ +Benchmark/ +coverage/ +.phpunit.result.cache +.php_cs +.php-cs-fixer.cache +.styleci.yml +codesniffer.ruleset.xml + +# =========================================== +# 11. 环境配置文件(敏感信息,运行时挂载) +# =========================================== +.env +.env.* +!.env.example +.secret +.secrets +*.key +*.pem +*.crt +*.csr + +# =========================================== +# 12. 备份和历史文件 +# =========================================== +*backup* +*_backup* +*_bak* +*.backup +*.bak +*~ +*.orig +*.rej +*_COPYING_* +*_TRASH_* + +# =========================================== +# 13. 开发辅助文件 +# =========================================== +.trae/ +.codebuddy/ +.scribe/ +.phpunit.result.cache +php_errors.log +*.log + +# =========================================== +# 14. 其他大型或不必要的文件 +# =========================================== +*.zip +*.tar +*.tar.gz +*.tgz +*.rar +*.7z +*.iso +*.img +*.dmg +*.pdf +*.exe +*.msi diff --git a/.gitignore b/.gitignore index fcc6925aa..7b4c19976 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,78 @@ /.git /.idea +.vscode/ *.log *.DS_Store -/crmeb/runtime/cache -/crmeb/runtime/log -/crmeb/runtime/session -/crmeb/runtime/temp +*.iml + +# CRMEB运行时 +/crmeb/runtime/* +/crmeb/backup/* /crmeb/public/install.lock -/crmeb/public/uploads -/crmeb/runtime/timer.pid -/crmeb/runtime/workerman.pid +crmeb/public/uploads/* + + +# Docker数据 /docker-compose/mysql/data/ /docker-compose/mysql/log/ /docker-compose/nginx/log/ +/docker-compose-universal/*/mysql/ +/docker-compose-universal/*/data/ + +# 构建产物 /template/admin/dist/ -/template/admin/.idea/ /template/admin/node_modules/ /template/uni-app/node_modules/ /template/uni-app/unpackage/ /template/uni-app/.hbuilderx/ /crmeb/.idea/ -/docker-compose/MacArm/mysql/data/ -/docker-compose/MacArm/mysql/log/ -/docker-compose/linux/mysql/data/ -/docker-compose/linux/mysql/log/ + +# 备份文件 +*_backup/ + +# Docker Compose +/docker-compose-dev/ +/help/docker/mysql/data/ + +# 配置文件(敏感信息) +crmeb/.env +crmeb/.constant +crmeb/supervisord.log +crmeb/supervisord.pid + +crmeb/start.sh +crmeb/supervisord.conf +crmeb/my.cnf +crmeb/redis.conf +crmeb/vhost.conf +crmeb/php-ini-overrides.ini +crmeb/php-fpm.conf + +# 代码助手规则文件 +.codebuddy/rules/dockerfile-buid.mdc +.codebuddy/rules/docker-compose-buid.mdc + +.trae/rules/docker.md +.trae/rules/dockerinone.md + + +.trae/skills/dockercompose/ALLINONE_SKILL.md +.gitignore +crmeb/Dockerfile +crmeb/nginx.conf +crmeb/.env.example +crmeb/.dockerignore + +crmeb/backup/readme.md +crmeb/runtime/readme.md +crmeb/runtime/cache/readme.md +crmeb/runtime/log/readme.md +crmeb/runtime/session/readme.md +crmeb/runtime/temp/readme.md + + +.codebuddy/rules/git-commit-standard.mdc +.codebuddy/rules/readme.mdc +Dockerfile +.codebuddy/models.json +.codebuddy/rules/project-intro.mdc diff --git a/crmeb/.constant b/crmeb/.constant old mode 100644 new mode 100755 index e69de29bb..781aa627b --- a/crmeb/.constant +++ b/crmeb/.constant @@ -0,0 +1,3 @@ += 7.4 + +## 快速开始 + +### 1. 创建开放接口账号 + +1. 登录 CRMEB 管理后台 +2. 进入 **设置** -> **系统设置** -> **开放接口** +3. 创建应用获取账号和密码 + +### 2. 配置到 Claude Desktop + +编辑配置文件: + +**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` +**Windows**: `%APPDATA%\Claude\claude_desktop_config.json` + +```json +{ + "mcpServers": { + "crmeb": { + "url": "http://your-domain/outapi/mcp", + "headers": { + "account": "your_account", + "password": "your_password", + "Content-Type": "application/json" + }, + "disabled": false + } + } +} +``` + +**配置示例(演示环境):** +```json +{ + "mcpServers": { + "crmebdemo": { + "url": "https://v5.crmeb.net/outapi/mcp", + "headers": { + "account": "ceshi", + "password": "ceshiceshi", + "Content-Type": "application/json" + }, + "disabled": false + } + } +} +``` + +### 3. 配置到 Cursor + +在 Cursor 设置中添加: + +```json +{ + "mcp.servers": { + "crmeb": { + "url": "http://your-domain/outapi/mcp", + "headers": { + "account": "your_account", + "password": "your_password", + "Content-Type": "application/json" + }, + "disabled": false + } + } +} +``` + +**参数说明:** + +| 参数 | 说明 | 获取方式 | +|------|------|---------| +| `url` | CRMEB MCP 接口地址 | 固定值:`http://域名/outapi/mcp` | +| `account` | 开放接口账号 | CRMEB 后台 -> 设置 -> 开放接口 | +| `password` | 开放接口密码 | CRMEB 后台 -> 设置 -> 开放接口 | +| `disabled` | 是否禁用该服务 | 可选,默认为 false | + +> 注意:直接配置 account 和 password 即可,系统会自动完成认证 + +## 支持的 MCP 客户端应用 + +以下是目前主流的支持 MCP 协议的应用程序,您可以在这些应用中配置和使用 CRMEB MCP 服务。 + +### 1. Claude Desktop + +Anthropic 官方桌面应用,首个原生支持 MCP 的客户端。 + +**配置步骤:** +1. 下载并安装 [Claude Desktop](https://claude.ai/download) +2. 找到配置文件: + - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` + - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` +3. 添加 CRMEB MCP 配置: +```json +{ + "mcpServers": { + "crmeb": { + "url": "http://your-domain/outapi/mcp", + "headers": { + "account": "your_account", + "password": "your_password", + "Content-Type": "application/json" + }, + "disabled": false + } + } +} +``` +4. 重启 Claude Desktop + +**使用方法:** +在对话中直接询问,例如: +``` +帮我查询 CRMEB 中的商品分类列表 +``` + +### 2. Cursor + +AI 驱动的代码编辑器,内置 MCP 支持。 + +**配置步骤:** +1. 下载并安装 [Cursor](https://cursor.sh/) +2. 打开设置(Settings -> Features -> Model Context Protocol) +3. 添加 MCP 服务器配置: +```json +{ + "mcp.servers": { + "crmeb": { + "url": "http://your-domain/outapi/mcp", + "headers": { + "account": "your_account", + "password": "your_password", + "Content-Type": "application/json" + }, + "disabled": false + } + } +} +``` +4. 或者直接编辑配置文件: + - **macOS/Linux**: `~/.cursor/mcp.json` + - **Windows**: `%APPDATA%\Cursor\mcp.json` + +**使用方法:** +在 Cursor 的 AI 聊天窗口中直接使用: +``` +查询 CRMEB 中的订单列表 +``` + +### 3. Cline (VS Code 扩展) + +VS Code 中的自主 AI 编程助手扩展。 + +**配置步骤:** +1. 在 VS Code 中安装 [Cline 扩展](https://marketplace.visualstudio.com/items?itemName=saoudrizwan.claude-dev) +2. 打开 VS Code 设置 +3. 搜索 "Cline MCP" 或在 Cline 面板中找到 MCP 配置 +4. 添加 MCP 服务器: +```json +{ + "mcpServers": { + "crmeb": { + "url": "http://your-domain/outapi/mcp", + "headers": { + "account": "your_account", + "password": "your_password", + "Content-Type": "application/json" + }, + "disabled": false + } + } +} +``` + +**使用方法:** +在 Cline 面板中输入指令: +``` +获取 CRMEB 商品 ID 为 1 的详情 +``` + +### 4. Windsurf + +Codeium 推出的 AI 原生 IDE。 + +**配置步骤:** +1. 下载并安装 [Windsurf](https://codeium.com/windsurf) +2. 打开设置 -> Developer Settings -> MCP Servers +3. 添加配置: +```json +{ + "mcpServers": { + "crmeb": { + "url": "http://your-domain/outapi/mcp", + "headers": { + "account": "your_account", + "password": "your_password", + "Content-Type": "application/json" + } + } + } +} +``` + +### 5. Continue (VS Code/JetBrains 扩展) + +开源的 AI 代码助手扩展。 + +**配置步骤:** +1. 安装 Continue 扩展 + - [VS Code](https://marketplace.visualstudio.com/items?itemName=Continue.continue) + - [JetBrains](https://plugins.jetbrains.com/plugin/22707-continue) +2. 打开 Continue 配置文件(`~/.continue/config.json`) +3. 添加 MCP 配置: +```json +{ + "models": [...], + "mcpServers": { + "crmeb": { + "url": "http://your-domain/outapi/mcp", + "headers": { + "account": "your_account", + "password": "your_password", + "Content-Type": "application/json" + } + } + } +} +``` + +### 6. Zed + +高性能代码编辑器,支持 MCP 协议。 + +**配置步骤:** +1. 下载并安装 [Zed](https://zed.dev/) +2. 打开配置文件(`~/.zed/settings.json`) +3. 添加 MCP 服务器配置: +```json +{ + "mcp_servers": { + "crmeb": { + "url": "http://your-domain/outapi/mcp", + "headers": { + "account": "your_account", + "password": "your_password", + "Content-Type": "application/json" + } + } + } +} +``` + +### 7. 其他支持 MCP 的应用 + +以下应用也在逐步支持 MCP 协议: + +- **Codeium**:AI 代码补全工具 +- **Tabnine**:AI 代码助手 +- **Sourcegraph Cody**:代码智能助手 + +> 💡 **提示**:MCP 是一个开放协议,越来越多的 AI 应用正在支持。如果您的应用支持 MCP,通常可以在设置中找到 MCP 或 Model Context Protocol 相关配置项。 + +## 可用工具 + +### 分类管理 + +| 工具名称 | 描述 | 必需参数 | 可选参数 | +|---------|------|---------|---------| +| `crmeb_category_list` | 获取分类列表 | - | page, limit | +| `crmeb_category_detail` | 获取分类详情 | id | - | +| `crmeb_category_create` | 创建分类 | name | pid, sort | + +### 商品管理 + +| 工具名称 | 描述 | 必需参数 | 可选参数 | +|---------|------|---------|---------| +| `crmeb_product_list` | 获取商品列表 | - | page, limit, cate_id, keyword, stock_min, stock_max | +| `crmeb_product_detail` | 获取商品详情 | id | - | +| `crmeb_product_create` | 创建商品 | name, cate_id, price, stock | image, unit | + +### 订单管理 + +| 工具名称 | 描述 | 必需参数 | 可选参数 | +|---------|------|---------|---------| +| `crmeb_order_list` | 获取订单列表 | - | page, limit, status, keyword | +| `crmeb_order_detail` | 获取订单详情 | order_id | - | +| `crmeb_order_delivery` | 订单发货 | order_id, delivery_type | delivery_name, delivery_id | +| `crmeb_order_express_list` | 获取物流公司列表 | - | - | + +### 售后管理 + +| 工具名称 | 描述 | 必需参数 | 可选参数 | +|---------|------|---------|---------| +| `crmeb_refund_list` | 获取售后列表 | - | page, limit | +| `crmeb_refund_detail` | 获取售后详情 | order_id | - | +| `crmeb_refund_agree` | 同意退款 | order_id | - | +| `crmeb_refund_refuse` | 拒绝退款 | order_id, refuse_reason | - | + +### 优惠券管理 + +| 工具名称 | 描述 | 必需参数 | 可选参数 | +|---------|------|---------|---------| +| `crmeb_coupon_list` | 获取优惠券列表 | - | page, limit | + +### 用户管理 + +| 工具名称 | 描述 | 必需参数 | 可选参数 | +|---------|------|---------|---------| +| `crmeb_user_list` | 获取用户列表 | - | page, limit, keyword | +| `crmeb_user_detail` | 获取用户详情 | uid | - | +| `crmeb_user_give_balance` | 赠送余额 | uid, balance | title | +| `crmeb_user_give_point` | 赠送积分 | uid, point | title | + +## 使用示例 + +在 Claude 或 Cursor 中,您可以这样使用: + +``` +帮我查询 CRMEB 中的商品列表 +``` + +``` +创建一个新商品:名称"测试商品",分类ID 1,价格 99.00,库存 100 +``` + +``` +查询订单号 202403130001 的详情 +``` + +``` +给用户 ID 为 1 的用户赠送 100 积分 +``` + +## 接口测试 + +```bash +# 测试 MCP 初始化 +curl -X POST "http://localhost:8011/outapi/mcp" \ + -H "Content-Type: application/json" \ + -H "account: your_account" \ + -H "password: your_password" \ + -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' + +# 获取工具列表 +curl -X POST "http://localhost:8011/outapi/mcp" \ + -H "Content-Type: application/json" \ + -H "account: your_account" \ + -H "password: your_password" \ + -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' + +# 调用工具 - 获取商品列表 +curl -X POST "http://localhost:8011/outapi/mcp" \ + -H "Content-Type: application/json" \ + -H "account: your_account" \ + -H "password: your_password" \ + -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"crmeb_product_list","arguments":{"page":1,"limit":10}}}' + +# 调用工具 - 创建分类 +curl -X POST "http://localhost:8011/outapi/mcp" \ + -H "Content-Type: application/json" \ + -H "account: your_account" \ + -H "password: your_password" \ + -d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"crmeb_category_create","arguments":{"name":"新分类","sort":100}}}' + +# 调用工具 - 查询库存大于500的商品 +curl -X POST "http://localhost:8011/outapi/mcp" \ + -H "Content-Type: application/json" \ + -H "account: your_account" \ + -H "password: your_password" \ + -d '{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"crmeb_product_list","arguments":{"stock_min":500}}}' + +# 使用演示环境测试 +curl -X POST "https://v5.crmeb.net/outapi/mcp" \ + -H "Content-Type: application/json" \ + -H "account: ceshi" \ + -H "password: ceshiceshi" \ + -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"crmeb_category_list","arguments":{}}}' +``` + +## 项目结构 + +``` +crmeb/app/outapi/ +├── controller/ +│ ├── Mcp.php # MCP 控制器 +│ ├── Login.php # 认证控制器 +│ ├── StoreProduct.php # 商品控制器 +│ ├── StoreCategory.php # 分类控制器 +│ ├── StoreOrder.php # 订单控制器 +│ ├── RefundOrder.php # 售后控制器 +│ ├── StoreCoupon.php # 优惠券控制器 +│ ├── User.php # 用户控制器 +│ └── ... +├── route/ +│ └── route.php # 路由配置 +├── middleware/ +│ └── AuthTokenMiddleware.php +├── mcp.md # 本文档 +└── README.md # outapi 模块说明 +``` + +## 协议说明 + +### MCP 协议版本 + +- 支持版本:`2024-11-05` + +### JSON-RPC 2.0 格式 + +**请求格式:** +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "tools/call", + "params": { + "name": "工具名称", + "arguments": { "参数": "值" } + } +} +``` + +**成功响应:** +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "content": [ + { + "type": "text", + "text": "{...结果数据...}" + } + ] + } +} +``` + +**错误响应:** +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32603, + "message": "错误信息" + } +} +``` + +## 错误码说明 + +| 错误码 | 说明 | +|-------|------| +| -32700 | JSON 解析错误 | +| -32600 | 请求无效(认证失败等) | +| -32601 | 方法不存在 | +| -32603 | 内部错误 | + +## 相关链接 + +- [Model Context Protocol 文档](https://modelcontextprotocol.io/) +- [CRMEB 开放接口](./README.md) diff --git a/crmeb/crmeb/command/Util.php b/crmeb/crmeb/command/Util.php index 226983a17..a6eae6090 100644 --- a/crmeb/crmeb/command/Util.php +++ b/crmeb/crmeb/command/Util.php @@ -145,7 +145,7 @@ class Util extends Command ]; // 执行 SQL 语句 - return $this->transaction(function () use ($sql) { + return Db::transaction(function () use ($sql) { try { foreach ($sql as $item) { Db::execute($item);