[], 'cc' => [], 'ob' => [], ]; protected $oModel; protected string $sPageName = ''; protected string $sModelName = ''; protected array $aFilterFields = []; // 允许where的字段 // protected array $aArticleFields = []; // 文章字段 protected array $aFieldTypes = []; protected array $aValueFields = []; protected array $aLenthFields = []; // 限制长度的字段 protected array $aSelectFields = []; // 默认作为select的字段 protected array $aListFields = []; // list展示的字段和名字映射 protected array $aDateFields = []; // date字段 protected array $aJsonFields = []; // json字段 protected array $aValueStyle = []; // 特定文字渲染样式 protected int $iLimitMax = 300; // 默认limit限制 protected int $iLimit = 30; // 默认显示行数 protected array $aCcExtFields = []; // 自定义条件字段追加在listFields后 protected array $aCcFields = []; protected int $iOrderByMax = 3; protected array $aOrderBy = [ [ "sField" => "id", "sSort" => "desc" ] ]; public function __construct() { if ($this->sModelName) { $sFullNamespace = "App\Models\\{$this->sModelName}"; if (! class_exists($sFullNamespace)) { throw new InvalidArgumentException("【系统架构错误】: 找不到领域模型 {$sFullNamespace}"); } $this->oModel = new $sFullNamespace(); $this->aCcFields = array_merge($this->aListFields, $this->aCcExtFields); } } public function getMapAll() { $a = []; if (method_exists($this->oModel, 'getMapAll')) { $a = $this->oModel->getMapAll(); } $b = array_merge($a, $this->aValueFields); return $b; } public function index(Request $oRequest, Response $oResponse, $args) { if (! $this->oModel) { return $oResponse->withJson(['code' => 500, 'msg' => '未绑定核心领域模型'], 500); } $oQuery = $this->oModel->newQuery(); $aParams = $oRequest->getParams(); $iLimit = $aParams['limit'] ?? $this->iLimit; $iPage = $aParams['page'] ?? 1; foreach ($aParams as $k => $v) { if (!empty($this->aFilterFields)) { if (!in_array($k, $this->aFilterFields)) { continue; } } // w__name__eq=1 $aK = explode("__", $k); $sType = $aK[0] ?? ''; $sField = $aK[1] ?? ''; $sOperator = $aK[2] ?? $this->sOperatorDefault; $sSqlOperator = $this->mapOperator($sOperator); if (!isset($this->aFilterParams[$sType])) { continue; } if (!$sType || !$sField) { continue; } $this->aFilterParams[$k] = $v; if ($sType === 'ob') { $this->aFilterParams[$sType][] = [ 'sField' => $sField, 'sSort' => $v ?? $this->sSortDefault ]; continue; } if ($sType === 'c') { // 预制条件,字典式 $this->aFilterParams[$sType][$sField] = [ 'sOperator' => $sOperator, 'sValue' => $v ]; } if ($sType === 'cc') { // 自定义条件,集合式 $this->aFilterParams[$sType][] = [ 'sField' => $sField, 'sOperator' => $sOperator, 'sValue' => $v ]; } if (blank($v)) continue; // 空v可以back但不加入sql查询 $sSqlValue = $v; if ($sSqlOperator === 'like') { $sSqlValue = "%{$v}%"; } if (in_array($sField, $this->aDateFields)) { $oQuery->whereDate($sField, $sSqlOperator, $sSqlValue); } else { $oQuery->where($sField, $sSqlOperator, $sSqlValue); } } $iLimit = max(1, $iLimit); $iLimit = min($this->iLimitMax, $iLimit); if (!empty($this->aFilterParams['ob'])) { $this->aOrderBy = $this->aFilterParams['ob']; } foreach ($this->aOrderBy as $aOrderBy) { $oQuery->orderBy($aOrderBy['sField'], $aOrderBy['sSort']); } // $oPaginatedData = $oQuery->paginate($iLimit, array_keys($this->aListFields)); $oPaginatedData = $oQuery->paginate( $iLimit, array_keys($this->aListFields), 'page', $iPage ); return $oResponse->withJson([ 'iCode' => 200, 'aData' => [ 'cList' => $oPaginatedData->items(), 'aListField' => $this->getListFields(), 'aFieldTypes' => $this->aFieldTypes, 'aMap' => $this->getMapAll(), 'aValueStyle' => $this->aValueStyle, 'aSelectField' => $this->aSelectFields, 'aFilterParam' => $this->aFilterParams, 'aCcField' => $this->aCcFields, 'sCcLast' => $this->getCcLast(), 'sPageName' => $this->sPageName, 'aPager' => [ 'aOrderBySchema'=> $this->getOrderBySchema(), 'aOrderBy' => $this->getOrderBy(), 'iTotal' => $oPaginatedData->total(), 'iLimit' => min($this->iLimitMax, $iLimit), 'iCurrentPage' => $oPaginatedData->currentPage(), 'iLastPage' => $oPaginatedData->lastPage(), 'iPerPage' => $oPaginatedData->perPage(), 'iPrevPage' => max(1, $oPaginatedData->currentPage() - 1), 'iNextPage' => min($oPaginatedData->lastPage(), $oPaginatedData->currentPage() + 1) ] ] ], 200); } private function mapOperator($sOperator) { $sSqlOperator = match ($sOperator) { 'like' => 'like', 'eq' => '=', 'ne' => '!=', 'gt' => '>', 'gte' => '>=', 'lt' => '<', 'lte' => '<=', default => '', }; return $sSqlOperator; } private function getOrderBySchema() { $iOrderByCount = count($this->aOrderBy); $iDiff = $this->iOrderByMax - $iOrderByCount; $a = $this->aOrderBy; for ($i=0; $i<$iDiff; $i++) { $a[] = []; } return $a; } private function getOrderBy() { return $this->aOrderBy; } public function getListFields() { $a = []; foreach ($this->aListFields as $k => $v) { if ($v) { $a[$k] = $v; } else { $a[$k] = $k; } } return $a; } private function getCcLast() { $aCcFieldsTmp = $this->aCcFields; foreach ($this->aFilterParams['cc'] as $ACC) { unset($aCcFieldsTmp[$ACC['sField']]); } $s = head(array_keys($aCcFieldsTmp)); return $s; } public function add(Request $oRequest, Response $oResponse, $args) { // 1. 获取表名 $sTableName = $this->oModel->getTable(); // 2. 修复 500 报错:改用连接对象的 Schema 构建器,彻底解耦门面 // 变量命名:oSchemaBuilder (Schema构建器对象) -> 【欧 斯基玛 标德儿】 $oSchemaBuilder = $this->oModel->getConnection()->getSchemaBuilder(); $aRawFields = $oSchemaBuilder->getColumnListing($sTableName); // 3. 大厂正统手法:利用模型原生方法安全获取时间戳字段名(自动处理关闭时间戳的情况) // 变量命名:aKickFields (要剔除的字段数组) -> 【诶 踢客 费尔茨】 $aKickFields = ['id']; if ($this->oModel->timestamps) { $aKickFields[] = $this->oModel->getCreatedAtColumn(); $aKickFields[] = $this->oModel->getUpdatedAtColumn(); } // 4. 高效数组过滤:干掉 foreach,改用内置函数完成差集计算 // 变量命名:aCleanFields (干净的字段数组) -> 【诶 克林 费尔茨】 $aCleanFields = array_values(array_diff($aRawFields, $aKickFields)); // 5. 标准响应返回 return $oResponse->withJson([ 'iCode' => 200, 'aData' => [ 'cList' => $aCleanFields, // 保持你原有的前端 Key 兼容 'sPageName' => $this->sPageName ] ], 200); } public function clone(Request $oRequest, Response $oResponse, $args) { // 1. 安全获取参数并查询 $iId = $args['id'] ?? 0; // 确保使用 findOrFail,找不到直接抛出 404 异常(由框架底层捕获) $oModelResult = $this->oModel->findOrFail($iId); // 2. 匈牙利命名法修正:获取原始属性数组 // 变量命名:aRowAttributes (行属性数组) -> 【诶 柔 艾特里比茨】 $aRowAttributes = $oModelResult->getRawOriginal(); // 3. 修复 500 报错:抛弃 DB 门面,改用解耦的实例调用 // 变量命名:oConnection (连接对象) -> 【欧 康内克闪】 $oConnection = $this->oModel->getConnection(); $sTableName = $this->oModel->getTable(); // 防御性编程:将原生 SQL 占位绑定,防止潜在注入风险 // 直接把表名变量拼进单引号里 $aStatus = $oConnection->select("SHOW TABLE STATUS LIKE '{$sTableName}'"); $iNextId = $aStatus[0]->Auto_increment ?? 1; // 4. 移除旧主键,赋予预测的自增 ID(注:若无特殊业务强需求,大厂更倾向于 unset($aRowAttributes['id'])) $aRowAttributes['id'] = (int)$iNextId; // 强制强类型转换 // 5. 健壮的方法存在性检查(呼应你上一条的需求) // 变量命名:aMapData (映射数据数组) -> 【诶 迈普 数据】 $aMapData = $this->getMapAll(); // 6. 统一标准的 JSON 响应输出 return $oResponse->withJson([ 'iCode' => 200, 'aData' => [ 'cList' => $aRowAttributes, // 保持你前端需要的 Key 命名不变 'aMap' => $aMapData, 'aListField' => $this->getListFields(), 'sPageName' => $this->sPageName ] ], 200); } // public function clone(Request $oRequest, Response $oResponse, $args) // { // $iId = $args['id']; // $oModelResult = $this->oModel->findOrFail($iId); // $cList = $oModelResult->getRawOriginal(); // // $sTableName = $this->oModel->getTable(); // $aStatus = DB::select("SHOW TABLE STATUS LIKE '{$sTableName}'"); // $iNextId = $aStatus[0]->Auto_increment ?? 1; // // $cList['id'] = $iNextId; // // return $oResponse->withJson([ // 'iCode' => 200, // 'aData' => [ // 'cList' => $cList, // 'aMap' => $this->oModel->getMapAll(), // 'aListField' => $this->getListFields(), // 'sPageName' => $this->sPageName // ] // ], 200); // } // 原代码是这样 // public function cloneSave(Request $oRequest, Response $oResponse, $args) // { //// tt(123); // $iId = $args['id']; ////dd(123); // $aParams = $oRequest->getParams(); // // foreach ($aParams as $k => $v) { // $this->oModel->{$k} = $v; // } // $this->oModel->create(); // // return $oResponse->withJson([ // 'iCode' => 200, // 'aData' => [], // 'sMsg' => "保存成功:id ".$this->oModel->id // ], 200); // } // 也不行? public function detail(Request $oRequest, Response $oResponse, $args) { $iId = $args['id']; $oModelResult = $this->oModel->findOrFail($iId); $cList = $oModelResult->getRawOriginal(); return $oResponse->withJson([ 'iCode' => 200, 'aData' => [ 'cList' => $cList, 'aMap' => $this->getMapAll(), 'aListField' => $this->getListFields(), 'sPageName' => $this->sPageName ] ], 200); } public function hit(Request $oRequest, Response $oResponse, $args) { $iId = $args['id']; $sField = $args['field']; $sHitType = $this->aFieldTypes[$sField] ?? ''; $sHit = $this->oModel->find($iId)?->{$sField}; if ($sHitType) { if ($sHitType == 'json') { $aHit = json_decode($sHit); $sHit = json_encode($aHit, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } } return $oResponse->withJson([ 'iCode' => 200, 'aData' => [ 'sHit' => $sHit ] ], 200); } public function delete(Request $oRequest, Response $oResponse, $args) { $iId = $args['id']; $this->oModel->findOrFail($iId)->delete(); return $oResponse->withJson([ 'iCode' => 200, 'aData' => [], 'sMsg' => '删除成功' ], 200); } public function addSave(Request $oRequest, Response $oResponse, $args) { $aParams = $oRequest->getParams(); foreach ($aParams as $k => $v) { $this->oModel->{$k} = $v; } if (!$this->oModel->save()) { return $oResponse->withJson(['code' => 500, 'msg' => '保存失败?'], 500); } return $oResponse->withJson([ 'iCode' => 200, 'aData' => [], 'sMsg' => '保存成功' ], 200); } public function detailSave(Request $oRequest, Response $oResponse, $args) { $iId = $args['id']; $oThisModel = $this->oModel->find($iId); $aParams = $oRequest->getParams(); unset($aParams['id'], $aParams['_method']); foreach ($aParams as $k => &$v) { if (empty($v) && empty($oThisModel->{$k})) { continue; } if (empty($v) && $v !== 0 && $v !== '0') { $v = ''; } if ($oThisModel->{$k} != $v) { $oThisModel->{$k} = $v; } } $oThisModel->save(); $aChangeField = $oThisModel->getChanges(); /// 排除update_at $sClassName = get_class($this->oModel); if ( defined($sClassName . '::UPDATED_AT') && ($sUpdateColumn = constant($sClassName . '::UPDATED_AT')) && !isset($aParams[$sUpdateColumn]) && isset($aChangeField[$sUpdateColumn]) ) { unset($aChangeField[$sUpdateColumn]); } /// 构造msg $sMsg = ""; $sJiantou = " -> "; foreach ($aChangeField as $k => $v) { if (mb_strlen($v, 'UTF-8') > 60 ) { $sJiantou = ''; // $v = mb_substr($v, 0, 60, 'UTF-8'); $v = ''; } if (!isset($aParams[$k])) { $sMsg .= "⚠️ ".$k . $sJiantou . $v . "

"; } else { $sMsg .= "✅ ".$k . $sJiantou . $v . "

"; unset($aParams[$k]); } } foreach ($aParams as $k => $v) { if (mb_strlen($v, 'UTF-8') > 60 ) { $sJiantou = ''; // $v = mb_substr($v, 0, 60, 'UTF-8'); $v = ''; } $sMsg .= "❌ ".$k . $sJiantou . $v . "

"; } $sMsg = rtrim($sMsg, "

"); return $oResponse->withJson([ 'iCode' => 200, 'aData' => $aChangeField, 'sMsg' => $sMsg ], 200); } }