selectInput($request); $methods = [ 'select' => 'formatSelect', 'tree' => 'formatTree', 'table_tree' => 'formatTableTree', 'normal' => 'formatNormal', ]; $format_function = $methods[$format] ?? 'formatNormal'; $total = $this->service->getCount($where); $list = $this->service->selectList($where, $field, $page, $limit, $order, [], false); return call_user_func([$this, $format_function], $list, $total); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * @param \support\Request $request * * @return \support\Response */ public function select(Request $request): \support\Response { try { [$where, $format, $limit, $field, $order, $page] = $this->selectInput($request); $data = $this->service->selectList($where, $field, 0, 99999, $order, [], true); return Json::success('ok', $data); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * @param \support\Request $request * * @return \support\Response */ public function create(Request $request): \support\Response { try { $id = $request->get('id'); throw new AdminException('表单不存在'); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * 插入数据 * * @param \support\Request $request * * @return \support\Response */ public function store(Request $request): \support\Response { try { $data = $this->insertInput($request); if (isset($this->validate) && $this->validate) { if (!$this->validate->scene('store')->check($data)) { throw new \Exception($this->validate->getError()); } } $model = $this->service->save($data); if (empty($model)) { throw new AdminException('插入失败'); } $pk = $model->getPk(); return Json::success('ok', [$pk => $model->getAttribute($pk)]); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * 查询详情 * * @param \support\Request $request * * @return \support\Response */ public function show(Request $request): \support\Response { try { $id = $request->route->param('id'); $data = $this->service->get($id); if (empty($data)) { throw new AdminException('数据未找到', ['errorCode' => 400]); } return Json::success('ok', $data->toArray()); } catch (\Throwable $e) { return Json::fail($e->getMessage(), [], $e->getCode()); } } public function edit(Request $request): \support\Response { try { $id = $request->route->param('id'); throw new AdminException('表单不存在'); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * 更新 * * @param \support\Request $request * * @return \support\Response */ public function update(Request $request): \support\Response { try { $id = $request->route->param('id'); $data = $this->insertInput($request); if (isset($this->validate) && $this->validate) { if (!$this->validate->scene('update')->check($data)) { throw new \Exception($this->validate->getError()); } } //路由模式兼容 if (empty($id)) { $model = $this->service->getModel(); $primaryKey = $model->getKeyName(); if (!array_key_exists($primaryKey, $data)) { throw new \Exception('参数异常缺少参数:' . $primaryKey); } $id = $data[$primaryKey]; } $this->service->update($id, $data); return Json::success('ok', []); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * 更新状态 * * @param \support\Request $request * * @return \support\Response */ public function changeStatus(Request $request): \support\Response { try { $data = $this->insertInput($request); $model = $this->service->getModel(); $primaryKey = $model->getKeyName(); if (!array_key_exists($primaryKey, $data)) { throw new \Exception('参数异常缺少主键'); } $targetModel = $model->findOrFail($data[$primaryKey]); if (empty($targetModel)) { throw new \Exception('资源不存在' . $primaryKey . '=', $data[$primaryKey]); } $targetModel->fill($data); if (!$targetModel->save()) { throw new \RuntimeException('数据保存失败'); } return Json::success('ok', []); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * Excel导出 * * @param \support\Request $request * * @return \support\Response */ public function export(Request $request): \support\Response { try { $params = $request->all(); $args = (array)$params['query'] ?? []; $scope = $params['scope'] ?? 'all'; $exportPage = max(1, (int)($args['__export_page'] ?? 1)); $exportLimit = min(1000, max(1, (int)($args['__export_limit'] ?? 20))); $exportIds = array_values(array_filter((array)($args['__export_ids'] ?? []), static fn ($id) => $id !== null && $id !== '')); unset($args['__export_page'], $args['__export_limit'], $args['__export_ids']); if ($scope === 'selected' && empty($exportIds)) { return Json::fail('请先选择需要导出的数据'); } $result = ExcelExportService::export($params, function ($chunkHandler) use ($args, $scope, $exportPage, $exportLimit, $exportIds) { $model = $this->service->getModel(); $allow_column = $model->getFields(); $query = $model->query(); $where = $this->convertToStandardFormat($args, $allow_column); if (!empty($where)) { $whereInConditions = []; foreach ($where as $key => $condition) { if (is_array($condition) && count($condition) === 3 && ($condition[1] === 'in' || $condition[1] === 'IN')) { $whereInConditions[] = $condition; unset($where[$key]);//移除分离后的条件 } } //普通条件格式直接传入构建 if (!empty($where)) { $query->where($where); } //特殊条件格式额外处理 foreach ($whereInConditions as $condition) { if (empty($condition[2])) { continue; } $value = Arr::normalize($condition[2]); $query->whereIn($condition[0], $value); } } if ($scope === 'selected') { $query->whereIn($model->getKeyName(), $exportIds); } $query->orderBy($model->getKeyName(), 'desc'); $handleChunk = function ($items) use ($chunkHandler) { $chunkHandler($this->expandExportRows($items)); }; if ($scope === 'current') { $query->forPage($exportPage, $exportLimit)->get()->chunk(1000)->each($handleChunk); return; } //切片查询数据 $query->chunk(1000, $handleChunk); }); return Json::success('导出成功', $result); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * 展开导出行;子控制器可覆盖此方法将一条记录转换为多条导出明细。 */ protected function expandExportRows(iterable $items): iterable { return $items; } /** * 删除资源 * * @param \support\Request $request * * @return \support\Response */ public function destroy(Request $request): \support\Response { try { // 获取要删除的ID集合 $data = $this->getDeleteIds($request); if (empty($data)) { throw new AdminException('删除参数不能为空'); } $result = $this->service->transaction(function () use ($data) { $data = is_array($data) ? $data : explode(',', $data); $deletedIds = []; foreach ($data as $id) { $item = $this->service->get($id); if (!$item) { continue; // 如果找不到项,跳过 } $item->delete(); $primaryKey = $item->getPk(); $deletedIds[] = $item->{$primaryKey}; } return $deletedIds; }); return Json::success('ok', $result); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * 获取要删除的ID集合 * 支持多种参数来源: * 1. 路由参数中的 'id' * 2. 请求体中的 'ids' 数组 * 3. 请求体中的 'data' 数组(兼容旧版) * * @param Request $request * * @return array */ protected function getDeleteIds(Request $request): array { // 优先从路由参数获取单个ID $routeId = $request->route->param('id'); if (!empty($routeId) && $routeId !== '0') { return [$routeId]; } // 尝试从请求体中获取 'ids' 参数 $ids = $request->input('ids', []); // 如果 'ids' 不存在,尝试兼容旧版的 'data' 参数 if (empty($ids)) { $ids = $request->input('data', []); } // 确保返回数组格式 if (is_array($ids)) { return $ids; } // 处理逗号分隔的字符串 if (is_string($ids) && !empty($ids)) { return explode(',', $ids); } return []; } /** * 数据恢复 * * @param \support\Request $request * * @return \support\Response */ public function recovery(Request $request): \support\Response { try { $id = $request->route->param('id'); $data = $request->input('data', []); $data = !empty($id) && $id !== '0' ? $id : $data; if (empty($data)) { throw new AdminException('参数错误'); } $this->service->transaction(function () use ($data) { $data = is_array($data) ? $data : explode(',', $data); foreach ($data as $id) { $this->service->update($id, ['delete' => null]); } }); return Json::success('操作成功', []); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } /** * 将各种格式的查询条件转换为统一格式 * 支持大写前缀、三元素数组、普通字段等格式 * 自动过滤空值参数(null、空字符串、空数组) * * @param array $params * @param array $allowColumns * @return array */ private function convertToStandardFormat(array $params, array $allowColumns): array { $result = []; $hasTripleArray = false; // 检查是否包含三元素数组格式 foreach ($params as $key => $value) { if (is_numeric($key) && is_array($value) && count($value) === 3) { $hasTripleArray = true; break; } } // 如果有三元素数组格式,直接保留原格式 if ($hasTripleArray) { foreach ($params as $key => $value) { // 跳过非查询参数 if (in_array($key, ['field', 'order', 'orderBy', 'orderDirection', 'sort', 'format', 'limit', 'page'])) { continue; } // 三元素数组直接添加(跳过空值条件) if (is_numeric($key) && is_array($value) && count($value) === 3) { if ($this->isValidCondition($value)) { $result[] = $value; } continue; } // 处理大写前缀格式: OPERATOR_field if (preg_match('/^([A-Z_]+)_(.+)$/', $key, $matches)) { $operatorUpper = $matches[1]; $field = $matches[2]; // 字段白名单验证 if (in_array($field, $allowColumns, true)) { // 检查值是否为空 if (!$this->isValidValue($value, $operatorUpper)) { continue; } // 转换操作符 $operatorMap = [ 'IN' => 'IN', 'LIKE' => 'LIKE', 'GT' => '>', 'LT' => '<', 'GTE' => '>=', 'LTE' => '<=', 'NE' => '!=', 'BETWEEN' => 'BETWEEN', 'EQ' => '=', ]; $operator = $operatorMap[$operatorUpper] ?? '='; // 特殊处理 LIKE 操作符自动加 % if ($operatorUpper === 'LIKE') { $result[] = [$field, $operator, "%{$value}%"]; } elseif ($operatorUpper === 'IN' && is_array($value)) { $result[] = [$field, 'IN', $value]; } elseif ($operatorUpper === 'BETWEEN' && is_array($value) && count($value) === 2) { $start = DateTime::dateTimeStringToTimestamp($value[0]); $end = DateTime::dateTimeStringToTimestamp($value[1]); $result[] = [$field, '>', $start]; $result[] = [$field, '<', $end]; } else { $result[] = [$field, $operator, $value]; } } continue; } // 处理普通字段 (默认使用 =) if (in_array($key, $allowColumns, true)) { // 检查值是否为空 if (!$this->isValidValue($value)) { continue; } $result[] = [$key, '=', $value]; } } } else { // 没有三元素数组,转换为标准三元组格式 foreach ($params as $key => $value) { // 跳过非查询参数 if (in_array($key, ['field', 'order', 'orderBy', 'orderDirection', 'sort', 'format', 'limit', 'page', 'filters'], true)) { continue; } // 处理大写前缀格式: OPERATOR_field if (preg_match('/^([A-Z_]+)_(.+)$/', $key, $matches)) { $operatorUpper = $matches[1]; $field = $matches[2]; // 字段白名单验证 if (in_array($field, $allowColumns, true)) { // 检查值是否为空 if (!$this->isValidValue($value, $operatorUpper)) { continue; } // 转换为标准操作符 $operatorMap = [ 'IN' => 'IN', 'LIKE' => 'LIKE', 'GT' => '>', 'LT' => '<', 'GTE' => '>=', 'LTE' => '<=', 'NE' => '!=', 'BETWEEN' => 'BETWEEN', 'EQ' => '=', ]; $operator = $operatorMap[$operatorUpper] ?? '='; // 特殊处理 LIKE 操作符自动加 % if ($operatorUpper === 'LIKE') { $result[] = [$field, $operator, "%{$value}%"]; } elseif ($operatorUpper === 'IN' && is_array($value)) { $result[] = [$field, 'IN', $value]; } elseif ($operatorUpper === 'BETWEEN' && is_array($value) && count($value) === 2) { $start = DateTime::dateTimeStringToTimestamp($value[0]); $end = DateTime::dateTimeStringToTimestamp($value[1]); $result[] = [$field, '>', $start]; $result[] = [$field, '<', $end]; } else { $result[] = [$field, $operator, $value]; } } continue; } // 处理普通字段 (默认使用 eq) if (in_array($key, $allowColumns, true)) { // 检查值是否为空 if (!$this->isValidValue($value)) { continue; } $result[] = [$key, '=', $value]; } } } return $result; } /** * 检查值是否有效(非空) * * @param mixed $value * @param string $operator 操作符(可选) * @return bool */ private function isValidValue(mixed $value, string $operator = ''): bool { // null 值无效 if ($value === null) { return false; } // 空字符串无效 if ($value === '') { return false; } // 空数组无效 if (is_array($value) && empty($value)) { return false; } // 对于 BETWEEN 操作,需要检查数组元素 if ($operator === 'BETWEEN' && is_array($value) && count($value) === 2) { return $value[0] !== '' && $value[0] !== null && $value[1] !== '' && $value[1] !== null; } return true; } /** * 检查三元素数组条件是否有效 * * @param array $condition [字段, 操作符, 值] * @return bool */ private function isValidCondition(array $condition): bool { if (count($condition) !== 3) { return false; } // 检查值是否有效 return $this->isValidValue($condition[2]); } /** * 解析排序参数为 SQL order 字符串 - 支持多种场景 * * 场景1: order=id 或 order=id desc (单字段排序) * 场景2: sort=id:asc,create_time:desc 或 sort[]=id:asc&sort[]=create_time:desc (多字段排序) * 场景3: orderBy=id&orderDirection=desc (兼容旧版大写前缀) * * @param array $params * @param array $allowColumns * @return string SQL order 字符串,如 "id desc, create_time asc" */ private function parseSortToOrder(array $params, array $allowColumns): string { $orders = []; // 场景1: order=id 或 order=id desc if (isset($params['order']) && !isset($params['sort']) && !isset($params['orderBy'])) { $orderValue = $params['order']; $parts = explode(' ', $orderValue, 2); $field = $parts[0]; $direction = strtolower($parts[1] ?? 'desc'); if (in_array($field, $allowColumns)) { $orders[] = "$field $direction"; } } // 场景2: sort=id:asc,create_time:desc 或 sort[]=id:asc&sort[]=create_time:desc if (isset($params['sort'])) { $sortValues = is_array($params['sort']) ? $params['sort'] : explode(',', $params['sort']); foreach ($sortValues as $sortValue) { $parts = explode(':', trim($sortValue), 2); $field = $parts[0]; $direction = strtolower($parts[1] ?? 'desc'); if (in_array($field, $allowColumns)) { $orders[] = "$field $direction"; } } } // 场景3: orderBy=id&orderDirection=desc (兼容旧版) if (isset($params['orderBy']) && !isset($params['sort']) && empty($orders)) { $field = $params['orderBy']; $direction = strtolower($params['orderDirection'] ?? 'desc'); if (in_array($field, $allowColumns)) { $orders[] = "$field $direction"; } } return implode(', ', $orders); } /** * 处理查询输入参数 * * @param Request $request * @param array|null $config 临时配置(可选),会覆盖类属性配置 * @return array [where, format, limit, field, order, page] */ protected function selectInput(Request $request, ?array $config = null): array { $model = $this->service->getModel(); $baseConfig = $this->getSelectInputConfig($request); // 扩展 allowed_fields 并处理配置 $helperConfig = $this->prepareHelperConfig($config, $baseConfig, $model); // 处理查询参数 $result = $this->processQueryParams($request, $model, $helperConfig); // 处理 custom_fields $where = $this->processCustomFields( $result['where'], $result, $request, $config, $baseConfig ); // 兼容旧格式返回值 return [ $where, $result['format'] ?? $request->input('format', 'normal'), $result['limit'], $result['field'] ?? $this->validateField($request->input('field', '*'), $model->getFields()), $result['order'], $result['page'], ]; } /** * 准备 QuerySelectHelper 配置 */ private function prepareHelperConfig(?array $config, array $baseConfig, Model $model): QuerySelectConfig { $allowColumn = $model->getFields(); // 扩展 allowed_fields:自动包含所有数据库字段 if (isset($baseConfig['allowed_fields']) && is_array($baseConfig['allowed_fields'])) { $baseConfig['allowed_fields'] = array_unique(array_merge($allowColumn, $baseConfig['allowed_fields'])); } if ($config !== null) { if (isset($config['allowed_fields']) && is_array($config['allowed_fields'])) { $config['allowed_fields'] = array_unique(array_merge($allowColumn, $config['allowed_fields'])); } return QuerySelectConfig::make(array_merge($baseConfig, $config)); } return QuerySelectConfig::make($baseConfig); } /** * 处理查询参数 */ private function processQueryParams(Request $request, Model $model, QuerySelectConfig $helperConfig): array { $helper = new QuerySelectHelper($helperConfig, $model->getFields()); $result = $helper->process($request->all(), $model); $keywordParam = $helperConfig->getKeywordParam(); $keyword = trim((string)$request->input($keywordParam, '')); if ($helperConfig->isEnableKeywordSearch() && $keyword !== '') { foreach ($helperConfig->getKeywordFields() as $field) { unset($result['where']['filters'][$field]); } $result['where']['keyword'] = $keyword; } // 提取 custom_fields(它们会被合并到 where 中) $customFields = array_filter($result, function ($key) { return !in_array($key, ['where', 'format', 'limit', 'field', 'order', 'page']); }, ARRAY_FILTER_USE_KEY); return array_merge($result, ['custom_fields' => $customFields]); } /** * 处理 custom_fields */ private function processCustomFields(array $where, array $result, Request $request, ?array $config, array $baseConfig): array { $customFields = $result['custom_fields'] ?? []; $filterFormat = $this->getFilterFormat($config, $baseConfig); $defaultOperator = $this->getDefaultOperator($config, $baseConfig); $excludeFilters = $this->getExcludeFilters($config, $baseConfig); $hasTripleArray = $this->hasTripleArray($where); $hasFiltersKey = isset($where['filters']) && is_array($where['filters']); if ($excludeFilters) { return $this->processCustomFieldsWithoutFilters($where, $customFields, $request, $filterFormat, $defaultOperator, $hasFiltersKey); } return $this->processCustomFieldsWithFilters($where, $customFields, $request, $filterFormat, $defaultOperator, $hasFiltersKey, $hasTripleArray); } /** * 获取过滤器格式 */ private function getFilterFormat(?array $config, array $baseConfig): string { if ($config !== null && isset($config['filter_format'])) { return $config['filter_format']; } return $baseConfig['filter_format'] ?? 'array'; } /** * 获取默认操作符 */ private function getDefaultOperator(?array $config, array $baseConfig): string { if ($config !== null && isset($config['default_operator'])) { return $config['default_operator']; } return $baseConfig['default_operator'] ?? 'eq'; } /** * 获取 exclude_filters 配置 */ private function getExcludeFilters(?array $config, array $baseConfig): bool { if ($config !== null && isset($config['exclude_filters'])) { return $config['exclude_filters']; } return $baseConfig['exclude_filters'] ?? false; } /** * 检查是否有三元素数组格式 */ private function hasTripleArray(array $where): bool { foreach ($where as $key => $value) { if (is_numeric($key) && is_array($value) && count($value) === 3) { return true; } } return false; } /** * 处理 custom_fields(exclude_filters = true) */ private function processCustomFieldsWithoutFilters(array $where, array $customFields, Request $request, string $filterFormat, string $defaultOperator, bool $hasFiltersKey): array { if ($hasFiltersKey) { unset($where['filters']); } foreach ($customFields as $key => $value) { if (is_numeric($key)) { $fieldName = $value; $fieldValue = $request->input($fieldName); if ($fieldValue !== null && $fieldValue !== '') { $this->addCustomFieldToWhere($where, $fieldName, $fieldValue, $filterFormat, $defaultOperator); } } else { if ($value !== null && $value !== '') { $this->addCustomFieldToWhere($where, $key, $value, $filterFormat, $defaultOperator); } } } return $where; } /** * 处理 custom_fields(exclude_filters = false) */ private function processCustomFieldsWithFilters(array $where, array $customFields, Request $request, string $filterFormat, string $defaultOperator, bool $hasFiltersKey, bool $hasTripleArray): array { if (empty($customFields) && !$hasFiltersKey) { if (!isset($where['filters']) && !$hasTripleArray) { $where['filters'] = []; } return $where; } if (!isset($where['filters']) || !is_array($where['filters'])) { $where['filters'] = []; } $normalizedFilters = $this->normalizeFilters($where['filters']); foreach ($customFields as $key => $value) { if (is_numeric($key)) { $fieldName = $value; $fieldValue = $request->input($fieldName); if ($fieldValue !== null && $fieldValue !== '') { $parsed = $this->parseFieldPrefix($fieldName, $defaultOperator); $normalizedFilters[] = [$parsed['field'], $parsed['operator'], $fieldValue]; } } else { if ($value !== null && $value !== '') { $parsed = $this->parseFieldPrefix($key, $defaultOperator); $normalizedFilters[] = [$parsed['field'], $parsed['operator'], $value]; } } } if ($filterFormat === 'keyvalue') { $finalFilters = []; foreach ($normalizedFilters as $filter) { $finalFilters[$filter[0]] = $filter[1] . ':' . $filter[2]; } $where['filters'] = $finalFilters; } else { $where['filters'] = $normalizedFilters; } return $where; } /** * 添加 custom_field 到 where */ private function addCustomFieldToWhere(array &$where, string $field, $value, string $filterFormat, string $defaultOperator): void { // 解析字段前缀(如 LIKE_user_name) $parsed = $this->parseFieldPrefix($field, $defaultOperator); $actualField = $parsed['field']; $operator = $parsed['operator']; switch ($filterFormat) { case 'simple': $where[$actualField] = $value; break; case 'keyvalue': $where[$actualField] = $operator . ':' . $value; break; default: $where[] = [$actualField, $operator, $value]; break; } } /** * 解析字段前缀,支持 LIKE_, EQ_, GT_, LT_, GTE_, LTE_, NEQ_ 等前缀 */ private function parseFieldPrefix(string $field, string $defaultOperator): array { $prefixes = [ 'LIKE_' => 'like', 'EQ_' => 'eq', 'GT_' => 'gt', 'LT_' => 'lt', 'GTE_' => 'gte', 'LTE_' => 'lte', 'NEQ_' => 'neq', 'IN_' => 'in', 'NOTIN_' => 'notin', 'BETWEEN_' => 'between', 'NOTBETWEEN_' => 'notbetween', 'NULL_' => 'null', 'NOTNULL_' => 'notnull', ]; foreach ($prefixes as $prefix => $operator) { if (strpos($field, $prefix) === 0) { return [ 'field' => substr($field, strlen($prefix)), 'operator' => $operator, ]; } } return [ 'field' => $field, 'operator' => $defaultOperator, ]; } /** * 标准化 filters */ private function normalizeFilters(array $filters): array { $normalized = []; foreach ($filters as $key => $filter) { if (is_array($filter) && count($filter) === 3) { $normalized[] = $filter; } elseif (is_string($key) && is_string($filter)) { if (strpos($filter, ':') !== false) { [$op, $val] = explode(':', $filter, 2); $normalized[] = [$key, $op, $val]; } else { $normalized[] = [$key, 'eq', $filter]; } } } return $normalized; } /** * 将 where 条件应用到查询构建器 * * @param \Illuminate\Database\Eloquent\Builder $query * @param array $where * * @return \Illuminate\Database\Eloquent\Builder */ protected function applyWhereToQuery(\Illuminate\Database\Eloquent\Builder $query, array $where): \Illuminate\Database\Eloquent\Builder { // 处理 filters 格式 if (isset($where['filters']) && is_array($where['filters'])) { QueryBuilderHelper::applyFiltersToQuery($query, $where['filters']); } // 处理三元素数组格式(直接应用到查询) foreach ($where as $key => $value) { if (is_numeric($key) && is_array($value) && count($value) === 3) { $field = $value[0]; $operator = $value[1]; $val = $value[2]; $query->where($field, $operator, $val); } } // 处理普通字段键值对格式(exclude_filters = true 时的 custom_fields) foreach ($where as $key => $value) { // 跳过系统保留键 if (in_array($key, ['filters', 'format', 'limit', 'field', 'order', 'page'])) { continue; } // 处理普通字段(字符串键且非数组) if (is_string($key) && !is_array($value)) { // 检查是否是 'op:value' 格式 if (strpos($value, ':') !== false) { [$op, $val] = explode(':', $value, 2); $query->where($key, $op, $val); } else { $query->where($key, '=', $value); } } } return $query; } /** * 获取 SelectInput 配置 * 保持原有行为,默认不启用新特性 * * @param Request $request * @return array */ protected function getSelectInputConfig(Request $request): array { $format = $request->input('format', 'normal'); $defaultConfig = $this->selectInputConfig ?? []; // 如果子类没有配置自定义选项,使用完全兼容的默认配置 if (empty($defaultConfig)) { return [ 'return_format' => 'array', 'param_format' => 'auto', // 自动检测参数格式,兼容现有所有格式 'skip_fields' => [], // 默认不跳过任何字段 'allowed_fields' => null, // 默认不限制字段 'sort_fields' => null, // 默认不限制排序字段 'default_sort' => [], // 默认不设置默认排序 'default_page_size' => $format === 'tree' ? 10000 : 10, 'max_page_size' => 10000, 'default_page' => 1, 'keyword_fields' => [], // 默认不启用关键词搜索 'enable_keyword_search' => false, 'enable_range_query' => true, // 启用范围查询 'enable_like_query' => true, // 启用模糊匹配 'auto_convert_datetime' => true, 'skip_empty_values' => true, 'custom_fields' => [], // 默认无自定义字段 'filter_format' => 'keyvalue', // 过滤器格式:array、keyvalue、simple 'default_operator' => 'eq', // 默认操作符 'exclude_filters' => false, // 是否排除 filters 键,默认为 false(包含 filters) ]; } // 子类配置了自定义选项,合并默认值 return array_merge([ 'return_format' => 'array', 'param_format' => 'auto', 'skip_fields' => ['password', 'token', 'deleted_at'], 'allowed_fields' => null, 'sort_fields' => null, 'default_sort' => [], 'default_page_size' => $format === 'tree' ? 10000 : 10, 'max_page_size' => 10000, 'default_page' => 1, 'keyword_fields' => [], 'enable_keyword_search' => false, 'enable_range_query' => true, 'enable_like_query' => true, 'auto_convert_datetime' => true, 'skip_empty_values' => true, 'custom_fields' => [], // 默认无自定义字段 'filter_format' => 'keyvalue', // 过滤器格式:array([[字段, 操作符, 值]])、keyvalue([字段 => 'op:value'])、simple([字段 => 值]) 'default_operator' => 'eq', // 默认操作符 'exclude_filters' => false, // 是否排除 filters 键,默认为 false(包含 filters) ], $defaultConfig); } /** * 验证字段是否有效 * * @param string $field * @param array $allow_column * @return string */ protected function validateField(string $field, array $allow_column): string { if ($field === '*') { return '*'; } // 处理多个字段(逗号分隔) $fields = array_map('trim', explode(',', $field)); $validFields = []; foreach ($fields as $f) { if (in_array($f, $allow_column)) { $validFields[] = $f; } } return empty($validFields) ? '*' : implode(', ', $validFields); } /** * 插入前置方法 * * @param Request $request * * @return array */ protected function insertInput(Request $request): array { $data = $this->inputFilter($request->all()); $password_filed = 'password'; if (isset($data[$password_filed])) { $data[$password_filed] = password_hash($data[$password_filed], PASSWORD_DEFAULT); } return $data; } /** * 对用户输入表单过滤 * * @param array $data * @param array $skipKeys * * @return array */ protected function inputFilter(array $data, array $skipKeys = []): array { $model = $this->service->getModel(); $columns = $model->getFields(); foreach ($data as $col => $item) { // 检查是否在跳过的键中,或者不在列中 if (!in_array($col, $columns) && !in_array($col, $skipKeys)) { unset($data[$col]); continue; } } // 处理时间字段 if (empty($data['created_at']) && !in_array('created_at', $skipKeys)) { unset($data['created_at']); } if (empty($data['updated_at']) && !in_array('updated_at', $skipKeys)) { unset($data['updated_at']); } return $data; } /** * 格式化树 * * @param $items * * @return \support\Response */ protected function formatTree($items): \support\Response { $format_items = []; foreach ($items as $item) { $format_items[] = [ 'name' => $item->title ?? $item->name ?? $item->id, 'value' => (string)$item->id, 'id' => $item->id, 'pid' => $item->pid, ]; } $tree = new Tree($format_items); return Json::success('ok', $tree->getTree()); } /** * 格式化表格树 * * @param $data * @param $total * * @return \support\Response */ protected function formatTableTree($data, $total): \support\Response { $tree = new Tree($data->toArray()); $items = $tree->getTree(); return Json::success('ok', $items); } /** * 格式化下拉列表 * * @param $items * * @return \support\Response */ protected function formatSelect($items): \support\Response { $formatted_items = []; foreach ($items as $item) { $formatted_items[] = [ 'label' => $item->title ?? $item->name ?? $item->real_name ?? $item->id, 'value' => $item->id, ]; } return Json::success('ok', $formatted_items); } /** * 通用格式化 * * @param $items * @param $total * * @return \support\Response */ protected function formatNormal($items, $total): \support\Response { return Json::success('ok', compact('items', 'total')); } public function dev(Request $request): \support\Response { return Json::fail('接口开发中'); } }