1. 调整异常处理类

2. 统一职责分工
3. 清除多余代码
This commit is contained in:
技术老胡
2026-02-24 13:37:35 +08:00
parent d29751cce8
commit d5a134d3a8
59 changed files with 3370 additions and 646 deletions

View File

@@ -4,6 +4,7 @@ namespace app\services;
use app\common\base\BaseService;
use app\common\utils\JwtUtil;
use app\exceptions\{BadRequestException, ForbiddenException, UnauthorizedException};
use app\repositories\UserRepository;
use support\Cache;
@@ -30,29 +31,28 @@ class AuthService extends BaseService
* @param string $verifyCode 验证码
* @param string $captchaId 验证码ID
* @return array ['token' => string]
* @throws \RuntimeException
*/
public function login(string $username, string $password, string $verifyCode, string $captchaId): array
{
// 1. 校验验证码
if (!$this->captchaService->validate($captchaId, $verifyCode)) {
throw new \RuntimeException('验证码错误或已失效', 400);
throw new BadRequestException('验证码错误或已失效');
}
// 2. 查询用户
$user = $this->userRepository->findByUserName($username);
if (!$user) {
throw new \RuntimeException('账号或密码错误', 401);
throw new UnauthorizedException('账号或密码错误');
}
// 3. 校验密码
if (!$this->validatePassword($password, $user->password)) {
throw new \RuntimeException('账号或密码错误', 401);
throw new UnauthorizedException('账号或密码错误');
}
// 4. 检查用户状态
if ($user->status !== 1) {
throw new \RuntimeException('账号已被禁用', 403);
throw new ForbiddenException('账号已被禁用');
}
// 5. 生成 JWT token包含用户ID、用户名、昵称等信息

View File

@@ -0,0 +1,89 @@
<?php
namespace app\services;
use app\common\base\BaseService;
use app\exceptions\InternalServerException;
use support\Cache;
/**
* 菜单相关业务服务
*
* 负责:
* - 从 JSON / 配置文件读取系统菜单
* - 使用 webman/cache 缓存菜单数据
* - 构建路由树结构
*/
class MenuService extends BaseService
{
/**
* 缓存键:系统菜单
* 注意webman/cache (symfony/cache) 不允许 key 中包含 : 等特殊字符
*/
private const CACHE_KEY_MENU = 'system_menu_all';
/**
* 获取前端路由(树形结构)
*
* @return array
*/
public function getRouters(): array
{
$menus = $this->getSystemMenu();
return $this->buildMenuTree($menus);
}
/**
* 获取系统菜单数据
* 仅从 JSON 文件 + 缓存中读取
*/
protected function getSystemMenu(): array
{
$menus = Cache::get(self::CACHE_KEY_MENU);
if (!is_array($menus)) {
// 优先读取 JSON 文件
$jsonPath = config_path('system-file/menu.json');
if (!file_exists($jsonPath)) {
throw new InternalServerException('菜单配置文件不存在');
}
$jsonContent = file_get_contents($jsonPath);
$data = json_decode($jsonContent, true);
if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) {
throw new InternalServerException('菜单配置文件格式错误:' . json_last_error_msg());
}
$menus = $data;
Cache::set(self::CACHE_KEY_MENU, $menus);
}
return $menus;
}
/**
* 构建菜单树形结构
*/
protected function buildMenuTree(array $menus, string $parentId = '0'): array
{
$tree = [];
foreach ($menus as $menu) {
if (($menu['parentId'] ?? '0') === $parentId) {
$children = $this->buildMenuTree($menus, $menu['id']);
$menu['children'] = !empty($children) ? $children : null;
$tree[] = $menu;
}
}
// 按 sort 排序
usort($tree, function ($a, $b) {
return ($a['meta']['sort'] ?? 0) <=> ($b['meta']['sort'] ?? 0);
});
return $tree;
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace app\services;
use app\common\base\BaseService;
use app\repositories\SystemConfigRepository;
/**
* 系统配置服务
*/
class SystemConfigService extends BaseService
{
public function __construct(
protected SystemConfigRepository $configRepository
) {
}
/**
* 根据配置键名获取配置值
*
* @param string $configKey
* @param mixed $default 默认值
* @return mixed
*/
public function getValue(string $configKey, $default = null)
{
$value = $this->configRepository->getValueByKey($configKey);
return $value !== null ? $value : $default;
}
/**
* 根据配置键名数组批量获取配置值
*
* @param array $configKeys
* @return array 返回 ['config_key' => 'config_value'] 格式的数组
*/
public function getValues(array $configKeys): array
{
return $this->configRepository->getValuesByKeys($configKeys);
}
/**
* 保存配置值
*
* @param string $configKey
* @param mixed $configValue
* @return bool
*/
public function setValue(string $configKey, $configValue): bool
{
// 如果是数组或对象转换为JSON字符串
if (is_array($configValue) || is_object($configValue)) {
$configValue = json_encode($configValue, JSON_UNESCAPED_UNICODE);
} else {
$configValue = (string) $configValue;
}
return $this->configRepository->updateOrCreate($configKey, $configValue);
}
/**
* 批量保存配置值
*
* @param array $configs 格式:['config_key' => 'config_value']
* @return bool
*/
public function setValues(array $configs): bool
{
// 处理数组和对象类型的值
$processedConfigs = [];
foreach ($configs as $key => $value) {
if (is_array($value) || is_object($value)) {
$processedConfigs[$key] = json_encode($value, JSON_UNESCAPED_UNICODE);
} else {
$processedConfigs[$key] = (string) $value;
}
}
return $this->configRepository->batchUpdateOrCreate($processedConfigs);
}
}

View File

@@ -0,0 +1,211 @@
<?php
namespace app\services;
use app\common\base\BaseService;
use app\exceptions\{InternalServerException, NotFoundException};
use support\Cache;
/**
* 系统设置相关业务服务
*
* 负责:
* - 字典配置dict.json + 缓存)
* - 系统设置 Tab 配置tabs.json + 缓存)
* - 表单配置({tabKey}.json + 数据库配置值 + 缓存)
*/
class SystemSettingService extends BaseService
{
/**
* 缓存键系统设置Tab
*/
private const CACHE_KEY_TABS = 'system_base_config_tabs';
/**
* 缓存键前缀:系统设置表单配置
*/
private const CACHE_KEY_FORM_PREFIX = 'system_base_config_form_';
/**
* 缓存键:所有字典
*/
private const CACHE_KEY_DICT = 'system_dict_all';
public function __construct(
protected SystemConfigService $configService
) {
}
/**
* 获取字典数据
*
* @param string $code 字典编码,不传返回全部
* @return array
*/
public function getDict(string $code = ''): array
{
$allDicts = Cache::get(self::CACHE_KEY_DICT);
if (!is_array($allDicts)) {
$jsonPath = config_path('system-file/dict.json');
if (!file_exists($jsonPath)) {
throw new InternalServerException('字典配置文件不存在');
}
$jsonContent = file_get_contents($jsonPath);
$data = json_decode($jsonContent, true);
if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) {
throw new InternalServerException('字典配置文件格式错误:' . json_last_error_msg());
}
$allDicts = $data;
Cache::set(self::CACHE_KEY_DICT, $allDicts);
}
if ($code === '') {
return $allDicts;
}
$dictsByCode = array_column($allDicts, null, 'code');
$dict = $dictsByCode[$code] ?? null;
if ($dict === null) {
throw new NotFoundException('未找到指定的字典:' . $code);
}
return $dict;
}
/**
* 获取所有系统设置 Tab 配置
*
* @return array
*/
public function getTabs(): array
{
$cached = Cache::get(self::CACHE_KEY_TABS);
if (is_array($cached)) {
return $cached;
}
$configPath = config_path('base-config/tabs.json');
if (!file_exists($configPath)) {
throw new NotFoundException('Tab配置文件不存在');
}
$jsonContent = file_get_contents($configPath);
$tabs = json_decode($jsonContent, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new InternalServerException('Tab配置文件格式错误' . json_last_error_msg());
}
usort($tabs, function ($a, $b) {
$sortA = $a['sort'] ?? 0;
$sortB = $b['sort'] ?? 0;
return $sortA <=> $sortB;
});
Cache::set(self::CACHE_KEY_TABS, $tabs);
return $tabs;
}
/**
* 获取指定 Tab 的表单配置(合并数据库值)
*
* @param string $tabKey
* @return array
*/
public function getFormConfig(string $tabKey): array
{
$cacheKey = self::CACHE_KEY_FORM_PREFIX . $tabKey;
$formConfig = Cache::get($cacheKey);
if (!is_array($formConfig)) {
$configPath = config_path("base-config/{$tabKey}.json");
if (!file_exists($configPath)) {
throw new NotFoundException("表单配置文件不存在:{$tabKey}");
}
$jsonContent = file_get_contents($configPath);
$formConfig = json_decode($jsonContent, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new InternalServerException('表单配置文件格式错误:' . json_last_error_msg());
}
Cache::set($cacheKey, $formConfig);
}
// 合并数据库配置值
if (isset($formConfig['rules']) && is_array($formConfig['rules'])) {
$fieldNames = [];
foreach ($formConfig['rules'] as $rule) {
if (isset($rule['field'])) {
$fieldNames[] = $rule['field'];
}
}
if (!empty($fieldNames)) {
$dbValues = $this->configService->getValues($fieldNames);
foreach ($formConfig['rules'] as &$rule) {
if (isset($rule['field']) && isset($dbValues[$rule['field']])) {
$value = $dbValues[$rule['field']];
$decoded = json_decode($value, true);
if (json_last_error() === JSON_ERROR_NONE) {
$rule['value'] = $decoded;
} else {
if (isset($rule['type'])) {
switch ($rule['type']) {
case 'inputNumber':
$rule['value'] = is_numeric($value) ? (float) $value : ($rule['value'] ?? 0);
break;
case 'switch':
$rule['value'] = in_array(strtolower($value), ['1', 'true', 'yes', 'on'], true);
break;
default:
$rule['value'] = $value;
}
} else {
$rule['value'] = $value;
}
}
}
}
unset($rule);
}
}
Cache::set($cacheKey, $formConfig);
return $formConfig;
}
/**
* 保存表单配置
*
* @param string $tabKey
* @param array $formData
* @return void
*/
public function saveFormConfig(string $tabKey, array $formData): void
{
$result = $this->configService->setValues($formData);
if (!$result) {
throw new InternalServerException('保存失败');
}
// 清理对应表单缓存
$cacheKey = self::CACHE_KEY_FORM_PREFIX . $tabKey;
Cache::delete($cacheKey);
}
}

View File

@@ -4,6 +4,7 @@ namespace app\services;
use app\common\base\BaseService;
use app\common\constants\RoleCode;
use app\exceptions\NotFoundException;
use app\repositories\UserRepository;
/**
@@ -29,7 +30,7 @@ class UserService extends BaseService
{
$user = $this->users->find($id);
if (!$user) {
throw new \RuntimeException('用户不存在', 404);
throw new NotFoundException('用户不存在');
}
$userArray = $user->toArray();