# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## 项目概述 勾股 OA 5.0,企业办公自动化系统。技术栈:**ThinkPHP 8.1 多应用模式 + think-orm 4.0 + Layui 前端 + MySQL**。PHP 要求 `>=8.2`。数据库表前缀 `oa_`(`Db::name('Admin')` → 表 `oa_admin`)。 ## 常用命令 ```bash composer install # 安装依赖(已配腾讯云镜像) php think migrate:run # 执行数据库迁移(建表 / 改表) php think migrate:create CreateXxx # 新建迁移文件 php think seed:run --seeder=XxxData # 执行单个 seeder php think seed:create XxxData # 新建 seeder rm -rf runtime/cache/* # 清缓存(改了菜单/权限/系统配置后必须清才生效) ``` - **无单元测试框架**。验证靠跑迁移 + 浏览器手测(见 `新增审批类型指南.md` 的验证清单)。 - 迁移与种子数据均以 Phinx 迁移文件形式放在 `database/migrations/`,文件名前缀 `xxx_create_*`(建表)/ `xxx_seed_*`(填数据)。 - 重装系统:删除 `config/install.lock` 后访问 `/install/index`。 - 环境配置走 `.env`(数据库、Redis 缓存),勿提交真实凭据。 ## 架构 ### 多应用结构 每个业务域是 `app/` 下的一个独立应用(`home` `finance` `adm` `customer` `contract` `project` `oa` `api` `mobile` `qiye` `disk` `user` `install`)。`default_app` 是 `home`。另有 `crud` 代码生成器应用(脚手架工具,非业务域,含 `command/` `tpl/`,用于生成 CRUD 骨架)。每个应用目录内自带: ``` app/{module}/ controller/ 控制器(继承 app\base\BaseController) model/ 模型(继承 think\Model) validate/ 验证器(可选) view/ 模板(目录名 = Str::snake(类名)) common.php ★ 该模块专属 helper 函数 middleware.php ``` - `app/base/BaseController.php` —— 所有控制器的基类。构造时跑 `checkLogin()`:校验 `Session(gougu_admin)`、超 10 小时强制重登、调 `checkAuth()` 用 `systematic\Systematic` 做权限节点校验(节点格式 `module/controller/action`,缓存在 `RulesSrc{uid}`)。控制器内可直接用 `$this->uid` / `$this->did` / `$this->pid`。 - `extend/` 是 PSR-0 自动加载目录(`systematic\`、`backup\`、`smsservice\` 等公共库)。 - 自定义异常处理:`app/exception/Http.php`(在 `app/provider.php` 绑定)。 ### CRUD 约定(强约束,新增功能照抄现有样本) Model 标准方法:`datalist($where, $param)`(`paginate` + `each` 翻译关联字段)、`add()`、`edit()`、`getById($id)`、`delById($id, $type=0)`。 - 写库用 `self::strict(false)->field(true)`;增删改成功/失败统一 `return to_assign(...)`,并调 `add_log()` 记操作日志。 - **软删除**:`delById` 默认 `update(['delete_time' => time()])`,查询一律带 `['delete_time', '=', 0]`。物理删除传 `$type=1`。 Controller `add()` 必须用 **if/else 结构**:AJAX 分支处理提交(不 `return` 模型结果),else 分支渲染视图。非 AJAX 分支**必须给 `$detail` 所有字段初始化默认值**(PHP 8 对 `Undefined array key` 是 fatal error)。 ### 全局 helper(`app/common.php`) `get_params()` 取请求参数、`to_assign($code,$msg,$data)` 统一 JSON 响应、`table_assign()` Layui 表格响应、`add_log($type,$id,$param,$subject)` 操作日志、`get_admin($uid)` 取用户信息、`check_status_name()` 审批状态文案、`to_date()` 时间戳格式化、`get_system_config()` 读系统配置(带缓存)。 ### 审批系统(核心业务) 审批类型注册在数据库,不是配置文件。关键表关系: ``` oa_flow_module → oa_flow_cate(name 唯一标识 = 前端 oaCheck.init 的 check_name) ├→ oa_flow(流程) ├→ oa_template(消息模板) └→ oa_{业务表}(含 check_* / admin_id / did / *_time 必填字段) oa_admin_rule(菜单权限节点池) oa_admin_group.rules(角色节点,逗号分隔) ``` 业务表必含审批字段:`check_status` `check_flow_id` `check_step_sort` `check_uids` `check_last_uid` `check_history_uids` `check_copy_uids` `check_time`,外加 `admin_id` `did` `create_time` `update_time` `delete_time`。 **新增审批类型必须照着 `新增审批类型指南.md` 走完整 10 步流程**(迁移 → Model → Controller → 3 个 View → seeder 注册类型/菜单/权限 → 清缓存)。 `finance` 应用是审批类型最全的样本库,新增同类审批照抄其结构即可:报销 `Expense`、借款 `Loan`、付款 `Payment`、开票 `Invoice`、收入 `Income`、提现 `Withdraw`、费用返还 `Feerefund`、VCC 返点/提成付款 `Vccpayment`、调价 `Priceadjust`、授信&核销 `Creditwriteoff`。其中带枚举的类型均配套 `Xxxcate` 字典表控制器(如 `Withdrawcate` `Feerefundcate`)。 ## 项目约定(踩坑点) - **helper 函数必须放对应模块的 `common.php`**(财务类放 `app/finance/common.php`)。放错模块 → 视图渲染时函数未定义 → 页面中途截断。 - **多词控制器命名用「首字母大写+其余全小写」**(`Vccpayment.php` / `class Vccpayment`,不是 `VccPayment`)。原因:TP 从全小写 URL 解析控制器得到 `Vccpayment`,Linux 大小写敏感文件系统下找不到 `VccPayment.php` 会报「控制器不存在」。单词控制器(`Expense` `Loan`)不受影响。 - **枚举字段建 `xxx_cate` 字典表**(含 `type` 字段区分同一审批类型下的多组枚举),业务表只存字典的 `value`(int,跨环境稳定),**不存中文、不存自增 id**。固定且极少的枚举(如是/否)才在 `common.php` 写 helper。 - MySQL `TEXT`/`BLOB` 字段不能有默认值,迁移里用 `'null' => true` 并去掉 `default`。 - Seeder 的 `run()` 必须声明 `run(): void`;`$db->query(...)` 返回 `PDOStatement`,取数组要 `->fetchAll(\PDO::FETCH_ASSOC)`。 - Seeder 里所有父节点 ID(菜单、模块、超管组)**动态查询**,不能写死(不同环境 ID 会漂移)。 - **财务五个新审批类型暂未开放删除**(`Withdraw` `Feerefund` `Vccpayment` `Priceadjust` `Creditwriteoff`),已前后端双重关闭:列表页 `datalist.html` 的删除按钮与 `del` 事件监听用注释关掉(`