mirror of
https://gitee.com/technical-laohu/mpay_v2_webman.git
synced 2026-04-22 10:04:27 +08:00
1. 调整异常处理类
2. 统一职责分工 3. 清除多余代码
This commit is contained in:
22
app/command/Test.php
Normal file
22
app/command/Test.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand('test', 'test')]
|
||||
class Test extends Command
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$output->writeln('<info>Hello</info> <comment>' . $this->getName() . '</comment>');
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ class BaseController
|
||||
{
|
||||
return json([
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'msg' => $message,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class BaseController
|
||||
{
|
||||
return json([
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'msg' => $message,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
@@ -59,5 +59,3 @@ class BaseController
|
||||
return (int) ($request->userId ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\constants;
|
||||
|
||||
/**
|
||||
* 通用启用/禁用状态
|
||||
* 多个表 status 字段复用:users.status, departments.status, roles.status, cron_jobs.status 等
|
||||
*/
|
||||
class CommonStatus
|
||||
{
|
||||
/**
|
||||
* 禁用 / 停用
|
||||
*/
|
||||
public const DISABLED = 0;
|
||||
|
||||
/**
|
||||
* 启用
|
||||
*/
|
||||
public const ENABLED = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\constants;
|
||||
|
||||
/**
|
||||
* 数据字典编码常量
|
||||
* 对应表:dict_groups.code
|
||||
*/
|
||||
class DictCode
|
||||
{
|
||||
/**
|
||||
* 性别字典
|
||||
*/
|
||||
public const GENDER = 'gender';
|
||||
|
||||
/**
|
||||
* 通用启用/禁用状态字典
|
||||
*/
|
||||
public const STATUS = 'status';
|
||||
|
||||
/**
|
||||
* 岗位字典
|
||||
*/
|
||||
public const POST = 'post';
|
||||
|
||||
/**
|
||||
* 任务状态字典
|
||||
*/
|
||||
public const TASK_STATUS = 'taskStatus';
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\constants;
|
||||
|
||||
/**
|
||||
* 权限标识常量
|
||||
* 对应表:menus.permission 以及前端 permissionData.meta.permission
|
||||
*/
|
||||
class Permission
|
||||
{
|
||||
// 系统按钮权限(示例)
|
||||
public const SYS_BTN_ADD = 'sys:btn:add';
|
||||
public const SYS_BTN_EDIT = 'sys:btn:edit';
|
||||
public const SYS_BTN_DELETE = 'sys:btn:delete';
|
||||
|
||||
// 通用按钮权限(示例)
|
||||
public const COMMON_BTN_ADD = 'common:btn:add';
|
||||
public const COMMON_BTN_EDIT = 'common:btn:edit';
|
||||
public const COMMON_BTN_DELETE = 'common:btn:delete';
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\constants;
|
||||
|
||||
/**
|
||||
* 角色编码常量
|
||||
* 对应表:roles.code
|
||||
*/
|
||||
class RoleCode
|
||||
{
|
||||
/**
|
||||
* 超级管理员
|
||||
*/
|
||||
public const ADMIN = 'admin';
|
||||
|
||||
/**
|
||||
* 普通员工
|
||||
*/
|
||||
public const COMMON = 'common';
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\enums;
|
||||
|
||||
/**
|
||||
* 定时任务日志状态
|
||||
* 对应表:cron_logs.status
|
||||
* 1 成功 0 失败
|
||||
*/
|
||||
class CronLogStatus
|
||||
{
|
||||
public const FAIL = 0;
|
||||
public const SUCCESS = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\enums;
|
||||
|
||||
/**
|
||||
* 定时任务执行策略(misfire_policy)
|
||||
* 对应表:cron_jobs.misfire_policy
|
||||
* 1 循环执行 2 执行一次
|
||||
*/
|
||||
class CronMisfirePolicy
|
||||
{
|
||||
/**
|
||||
* 循环执行
|
||||
*/
|
||||
public const LOOP = 1;
|
||||
|
||||
/**
|
||||
* 只执行一次
|
||||
*/
|
||||
public const RUN_ONCE = 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\enums;
|
||||
|
||||
/**
|
||||
* 定时任务类型
|
||||
* 对应表:cron_jobs.task_type
|
||||
* 0 cron 表达式 1 时间间隔(秒)
|
||||
*/
|
||||
class CronTaskType
|
||||
{
|
||||
public const CRON_EXPRESSION = 0;
|
||||
public const INTERVAL_SECOND = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\enums;
|
||||
|
||||
/**
|
||||
* 用户性别枚举
|
||||
* 对应表:users.sex 以及 gender 字典
|
||||
*/
|
||||
class UserSex
|
||||
{
|
||||
/**
|
||||
* 女
|
||||
*/
|
||||
public const FEMALE = 0;
|
||||
|
||||
/**
|
||||
* 男
|
||||
*/
|
||||
public const MALE = 1;
|
||||
|
||||
/**
|
||||
* 未知/其它
|
||||
*/
|
||||
public const UNKNOWN = 2;
|
||||
}
|
||||
|
||||
|
||||
28
app/events/SystemConfig.php
Normal file
28
app/events/SystemConfig.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace app\events;
|
||||
|
||||
use app\repositories\SystemConfigRepository;
|
||||
|
||||
/**
|
||||
* 系统配置相关事件处理
|
||||
*
|
||||
* 负责在配置更新后重新从数据库加载缓存
|
||||
*/
|
||||
class SystemConfig
|
||||
{
|
||||
/**
|
||||
* 重新加载系统配置缓存
|
||||
*
|
||||
* @param mixed $data 事件数据(此处用不到)
|
||||
* @return void
|
||||
*/
|
||||
public function reload($data = null): void
|
||||
{
|
||||
// 通过仓储重新加载缓存
|
||||
$repository = new SystemConfigRepository();
|
||||
$repository->reloadCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
app/exceptions/BadRequestException.php
Normal file
25
app/exceptions/BadRequestException.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace app\exceptions;
|
||||
|
||||
use Webman\Exception\BusinessException;
|
||||
|
||||
/**
|
||||
* 请求参数错误异常
|
||||
* 用于请求参数格式错误、验证码错误等情况
|
||||
*
|
||||
* 示例:
|
||||
* throw new BadRequestException('验证码错误或已失效');
|
||||
* throw new BadRequestException('请求参数格式错误');
|
||||
*/
|
||||
class BadRequestException extends BusinessException
|
||||
{
|
||||
public function __construct(string $message = '请求参数错误', int $bizCode = 400, array $data = [])
|
||||
{
|
||||
parent::__construct($message, $bizCode);
|
||||
if (!empty($data)) {
|
||||
$this->data($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
app/exceptions/ForbiddenException.php
Normal file
25
app/exceptions/ForbiddenException.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace app\exceptions;
|
||||
|
||||
use Webman\Exception\BusinessException;
|
||||
|
||||
/**
|
||||
* 禁止访问异常
|
||||
* 用于无权限、账号被禁用等情况
|
||||
*
|
||||
* 示例:
|
||||
* throw new ForbiddenException('账号已被禁用');
|
||||
* throw new ForbiddenException('无权限访问该资源');
|
||||
*/
|
||||
class ForbiddenException extends BusinessException
|
||||
{
|
||||
public function __construct(string $message = '禁止访问', int $bizCode = 403, array $data = [])
|
||||
{
|
||||
parent::__construct($message, $bizCode);
|
||||
if (!empty($data)) {
|
||||
$this->data($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
app/exceptions/InternalServerException.php
Normal file
26
app/exceptions/InternalServerException.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\exceptions;
|
||||
|
||||
use Webman\Exception\BusinessException;
|
||||
|
||||
/**
|
||||
* 系统内部错误异常
|
||||
* 用于配置文件错误、系统错误等不可预期的错误
|
||||
*
|
||||
* 示例:
|
||||
* throw new InternalServerException('字典配置文件不存在');
|
||||
* throw new InternalServerException('配置文件格式错误:' . json_last_error_msg());
|
||||
* throw new InternalServerException('保存失败');
|
||||
*/
|
||||
class InternalServerException extends BusinessException
|
||||
{
|
||||
public function __construct(string $message = '系统内部错误', int $bizCode = 500, array $data = [])
|
||||
{
|
||||
parent::__construct($message, $bizCode);
|
||||
if (!empty($data)) {
|
||||
$this->data($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
app/exceptions/NotFoundException.php
Normal file
25
app/exceptions/NotFoundException.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace app\exceptions;
|
||||
|
||||
use Webman\Exception\BusinessException;
|
||||
|
||||
/**
|
||||
* 资源不存在异常
|
||||
* 用于资源未找到的情况
|
||||
*
|
||||
* 示例:
|
||||
* throw new NotFoundException('用户不存在');
|
||||
* throw new NotFoundException('未找到指定的字典:' . $code);
|
||||
*/
|
||||
class NotFoundException extends BusinessException
|
||||
{
|
||||
public function __construct(string $message = '资源不存在', int $bizCode = 404, array $data = [])
|
||||
{
|
||||
parent::__construct($message, $bizCode);
|
||||
if (!empty($data)) {
|
||||
$this->data($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
app/exceptions/UnauthorizedException.php
Normal file
26
app/exceptions/UnauthorizedException.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\exceptions;
|
||||
|
||||
use Webman\Exception\BusinessException;
|
||||
|
||||
/**
|
||||
* 未授权异常
|
||||
* 用于认证失败、token无效等情况
|
||||
*
|
||||
* 示例:
|
||||
* throw new UnauthorizedException('账号或密码错误');
|
||||
* throw new UnauthorizedException('认证令牌已过期');
|
||||
* throw new UnauthorizedException('认证令牌无效');
|
||||
*/
|
||||
class UnauthorizedException extends BusinessException
|
||||
{
|
||||
public function __construct(string $message = '未授权', int $bizCode = 401, array $data = [])
|
||||
{
|
||||
parent::__construct($message, $bizCode);
|
||||
if (!empty($data)) {
|
||||
$this->data($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
namespace app\exceptions;
|
||||
|
||||
use Webman\Exception\BusinessException;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
|
||||
/**
|
||||
* 参数校验异常
|
||||
@@ -19,6 +17,9 @@ class ValidationException extends BusinessException
|
||||
{
|
||||
public function __construct(string $message = '参数校验失败', int $bizCode = 422, array $data = [])
|
||||
{
|
||||
parent::__construct($message, $bizCode, $data);
|
||||
parent::__construct($message, $bizCode);
|
||||
if (!empty($data)) {
|
||||
$this->data($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,12 +27,8 @@ class AuthController extends BaseController
|
||||
*/
|
||||
public function captcha(Request $request)
|
||||
{
|
||||
try {
|
||||
$data = $this->captchaService->generate();
|
||||
return $this->success($data);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->fail('验证码生成失败:' . $e->getMessage(), 500);
|
||||
}
|
||||
$data = $this->captchaService->generate();
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,14 +48,8 @@ class AuthController extends BaseController
|
||||
return $this->fail('请填写完整登录信息', 400);
|
||||
}
|
||||
|
||||
try {
|
||||
$data = $this->authService->login($username, $password, $verifyCode, $captchaId);
|
||||
return $this->success($data);
|
||||
} catch (\RuntimeException $e) {
|
||||
return $this->fail($e->getMessage(), $e->getCode() ?: 500);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->fail('登录失败:' . $e->getMessage(), 500);
|
||||
}
|
||||
$data = $this->authService->login($username, $password, $verifyCode, $captchaId);
|
||||
return $this->success($data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace app\http\admin\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\services\MenuService;
|
||||
use support\Request;
|
||||
|
||||
/**
|
||||
@@ -10,44 +11,15 @@ use support\Request;
|
||||
*/
|
||||
class MenuController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected MenuService $menuService
|
||||
) {
|
||||
}
|
||||
|
||||
public function getRouters()
|
||||
{
|
||||
// 获取菜单数据并转换为树形结构
|
||||
$routers = $this->buildMenuTree($this->getSystemMenu());
|
||||
|
||||
$routers = $this->menuService->getRouters();
|
||||
return $this->success($routers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统菜单数据
|
||||
* 从配置文件读取
|
||||
*/
|
||||
private function getSystemMenu(): array
|
||||
{
|
||||
return config('menu', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建菜单树形结构
|
||||
*/
|
||||
private 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace app\http\admin\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\services\SystemSettingService;
|
||||
use support\Request;
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,10 @@ use support\Request;
|
||||
*/
|
||||
class SystemController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected SystemSettingService $settingService
|
||||
) {
|
||||
}
|
||||
/**
|
||||
* GET /system/getDict
|
||||
* GET /system/getDict/{code}
|
||||
@@ -24,23 +29,50 @@ class SystemController extends BaseController
|
||||
*/
|
||||
public function getDict(Request $request, string $code = '')
|
||||
{
|
||||
// 获取所有字典数据
|
||||
$allDicts = config('dict', []);
|
||||
|
||||
// 如果指定了 code,则只返回对应的字典
|
||||
if (!empty($code)) {
|
||||
// 将数组转换为以 code 为键的关联数组,便于快速查找
|
||||
$dictsByCode = array_column($allDicts, null, 'code');
|
||||
$dict = $dictsByCode[$code] ?? null;
|
||||
|
||||
if ($dict === null) {
|
||||
return $this->fail('未找到指定的字典:' . $code, 404);
|
||||
}
|
||||
return $this->success($dict);
|
||||
$data = $this->settingService->getDict($code);
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /system/base-config/tabs
|
||||
*
|
||||
* 获取所有Tab配置
|
||||
* 由 SystemSettingService 负责读取配置和缓存
|
||||
*/
|
||||
public function getTabsConfig()
|
||||
{
|
||||
$tabs = $this->settingService->getTabs();
|
||||
return $this->success($tabs);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /system/base-config/form/{tabKey}
|
||||
*
|
||||
* 获取指定Tab的表单配置
|
||||
* 从 SystemSettingService 获取合并后的配置
|
||||
*/
|
||||
public function getFormConfig(Request $request, string $tabKey)
|
||||
{
|
||||
$formConfig = $this->settingService->getFormConfig($tabKey);
|
||||
return $this->success($formConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /system/base-config/submit/{tabKey}
|
||||
*
|
||||
* 提交表单数据
|
||||
* 接收表单数据,直接使用字段名(fieldName)作为 config_key 保存到数据库
|
||||
*/
|
||||
public function submitConfig(Request $request, string $tabKey)
|
||||
{
|
||||
$formData = $request->post();
|
||||
|
||||
if (empty($formData)) {
|
||||
return $this->fail('提交数据不能为空', 400);
|
||||
}
|
||||
|
||||
// 返回所有字典
|
||||
return $this->success($allDicts);
|
||||
|
||||
$this->settingService->saveFormConfig($tabKey, $formData);
|
||||
return $this->success(null, '保存成功');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,12 +33,8 @@ class UserController extends BaseController
|
||||
return $this->fail('未获取到用户信息,请先登录', 401);
|
||||
}
|
||||
|
||||
try {
|
||||
$data = $this->userService->getUserInfoById($userId);
|
||||
return $this->success($data);
|
||||
} catch (\RuntimeException $e) {
|
||||
return $this->fail($e->getMessage(), $e->getCode() ?: 500);
|
||||
}
|
||||
$data = $this->userService->getUserInfoById($userId);
|
||||
return $this->success($data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
namespace app\http\admin\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use app\common\utils\JwtUtil;
|
||||
use app\exceptions\UnauthorizedException;
|
||||
|
||||
/**
|
||||
* JWT 认证中间件
|
||||
@@ -25,7 +26,7 @@ class AuthMiddleware implements MiddlewareInterface
|
||||
// 从请求头中获取 token
|
||||
$auth = $request->header('Authorization', '');
|
||||
if (!$auth) {
|
||||
return $this->unauthorized('缺少认证令牌');
|
||||
throw new UnauthorizedException('缺少认证令牌');
|
||||
}
|
||||
|
||||
// 兼容 "Bearer xxx" 或直接 "xxx"
|
||||
@@ -36,7 +37,7 @@ class AuthMiddleware implements MiddlewareInterface
|
||||
}
|
||||
|
||||
if (!$token) {
|
||||
return $this->unauthorized('认证令牌格式错误');
|
||||
throw new UnauthorizedException('认证令牌格式错误');
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -44,7 +45,7 @@ class AuthMiddleware implements MiddlewareInterface
|
||||
$payload = JwtUtil::parseToken($token);
|
||||
|
||||
if (empty($payload) || !isset($payload['user_id'])) {
|
||||
return $this->unauthorized('认证令牌无效');
|
||||
throw new UnauthorizedException('认证令牌无效');
|
||||
}
|
||||
|
||||
// 将用户信息存储到请求对象中,供控制器使用
|
||||
@@ -53,29 +54,20 @@ class AuthMiddleware implements MiddlewareInterface
|
||||
|
||||
// 继续处理请求
|
||||
return $handler($request);
|
||||
} catch (UnauthorizedException $e) {
|
||||
// 重新抛出业务异常,让框架处理
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
// 根据异常类型返回不同的错误信息
|
||||
$message = $e->getMessage();
|
||||
if (str_contains($message, 'expired') || str_contains($message, 'Expired')) {
|
||||
return $this->unauthorized('认证令牌已过期', 401);
|
||||
throw new UnauthorizedException('认证令牌已过期');
|
||||
} elseif (str_contains($message, 'signature') || str_contains($message, 'Signature')) {
|
||||
return $this->unauthorized('认证令牌签名无效', 401);
|
||||
throw new UnauthorizedException('认证令牌签名无效');
|
||||
} else {
|
||||
return $this->unauthorized('认证令牌验证失败:' . $message, 401);
|
||||
throw new UnauthorizedException('认证令牌验证失败:' . $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回未授权响应
|
||||
*/
|
||||
private function unauthorized(string $message, int $code = 401): Response
|
||||
{
|
||||
return json([
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'data' => null,
|
||||
], $code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
38
app/models/SystemConfig.php
Normal file
38
app/models/SystemConfig.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use app\common\base\BaseModel;
|
||||
|
||||
/**
|
||||
* 系统配置模型
|
||||
*
|
||||
* 对应表:ma_system_config
|
||||
*/
|
||||
class SystemConfig extends BaseModel
|
||||
{
|
||||
/**
|
||||
* 启用自动维护 created_at / updated_at
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'ma_system_config';
|
||||
|
||||
/**
|
||||
* 允许批量赋值的字段
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'config_key',
|
||||
'config_value',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\repositories;
|
||||
|
||||
use app\common\base\BaseRepository;
|
||||
use app\models\CronJob;
|
||||
|
||||
/**
|
||||
* 定时任务仓储
|
||||
*/
|
||||
class CronJobRepository extends BaseRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new CronJob());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\repositories;
|
||||
|
||||
use app\common\base\BaseRepository;
|
||||
use app\models\CronLog;
|
||||
|
||||
/**
|
||||
* 定时任务日志仓储
|
||||
*/
|
||||
class CronLogRepository extends BaseRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new CronLog());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\repositories;
|
||||
|
||||
use app\common\base\BaseRepository;
|
||||
use app\models\Department;
|
||||
|
||||
/**
|
||||
* 部门仓储
|
||||
*/
|
||||
class DepartmentRepository extends BaseRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new Department());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\repositories;
|
||||
|
||||
use app\common\base\BaseRepository;
|
||||
use app\models\DictGroup;
|
||||
|
||||
/**
|
||||
* 字典分组仓储
|
||||
*/
|
||||
class DictGroupRepository extends BaseRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new DictGroup());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\repositories;
|
||||
|
||||
use app\common\base\BaseRepository;
|
||||
use app\models\DictItem;
|
||||
|
||||
/**
|
||||
* 字典项仓储
|
||||
*/
|
||||
class DictItemRepository extends BaseRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new DictItem());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\repositories;
|
||||
|
||||
use app\common\base\BaseRepository;
|
||||
use app\models\Menu;
|
||||
|
||||
/**
|
||||
* 菜单 / 权限仓储
|
||||
*/
|
||||
class MenuRepository extends BaseRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new Menu());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有启用的菜单(仅目录和菜单类型,排除按钮)
|
||||
*/
|
||||
public function getAllEnabledMenus(): array
|
||||
{
|
||||
return $this->model
|
||||
->newQuery()
|
||||
->whereIn('type', [1, 2]) // 1目录 2菜单,排除3按钮
|
||||
->where('status', 1) // 只获取启用的菜单
|
||||
->orderBy('sort', 'asc')
|
||||
->orderBy('id', 'asc')
|
||||
->get()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据菜单ID列表获取启用的菜单(仅目录和菜单类型,排除按钮)
|
||||
*/
|
||||
public function getMenusByIds(array $menuIds): array
|
||||
{
|
||||
if (empty($menuIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->model
|
||||
->newQuery()
|
||||
->whereIn('id', $menuIds)
|
||||
->whereIn('type', [1, 2]) // 1目录 2菜单,排除3按钮
|
||||
->where('status', 1) // 只获取启用的菜单
|
||||
->orderBy('sort', 'asc')
|
||||
->orderBy('id', 'asc')
|
||||
->get()
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\repositories;
|
||||
|
||||
use app\common\base\BaseRepository;
|
||||
use app\models\Role;
|
||||
|
||||
/**
|
||||
* 角色仓储
|
||||
*/
|
||||
class RoleRepository extends BaseRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new Role());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
157
app/repositories/SystemConfigRepository.php
Normal file
157
app/repositories/SystemConfigRepository.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace app\repositories;
|
||||
|
||||
use app\common\base\BaseRepository;
|
||||
use app\models\SystemConfig;
|
||||
use support\Cache;
|
||||
use Webman\Event\Event;
|
||||
|
||||
/**
|
||||
* 系统配置仓储
|
||||
*/
|
||||
class SystemConfigRepository extends BaseRepository
|
||||
{
|
||||
/**
|
||||
* 缓存键:全部系统配置
|
||||
*/
|
||||
private const CACHE_KEY_ALL_CONFIG = 'system_config_all';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(new SystemConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据库加载所有配置到缓存
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function loadAllToCache(): array
|
||||
{
|
||||
// 优先从 webman/cache 获取
|
||||
$cached = Cache::get(self::CACHE_KEY_ALL_CONFIG);
|
||||
if (is_array($cached)) {
|
||||
return $cached;
|
||||
}
|
||||
|
||||
// 缓存不存在时从数据库加载
|
||||
$configs = $this->model
|
||||
->newQuery()
|
||||
->get(['config_key', 'config_value']);
|
||||
|
||||
$result = [];
|
||||
foreach ($configs as $config) {
|
||||
$result[$config->config_key] = $config->config_value;
|
||||
}
|
||||
|
||||
// 写入缓存(不过期,除非显式清理)
|
||||
Cache::set(self::CACHE_KEY_ALL_CONFIG, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存(供事件调用)
|
||||
*/
|
||||
public static function clearCache(): void
|
||||
{
|
||||
Cache::delete(self::CACHE_KEY_ALL_CONFIG);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新从数据库加载缓存(供事件调用)
|
||||
*/
|
||||
public function reloadCache(): void
|
||||
{
|
||||
Cache::delete(self::CACHE_KEY_ALL_CONFIG);
|
||||
$this->loadAllToCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置键名查询配置值
|
||||
*
|
||||
* @param string $configKey
|
||||
* @return string|null
|
||||
*/
|
||||
public function getValueByKey(string $configKey): ?string
|
||||
{
|
||||
$all = $this->loadAllToCache();
|
||||
|
||||
return $all[$configKey] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置键名数组批量查询配置
|
||||
*
|
||||
* @param array $configKeys
|
||||
* @return array 返回 ['config_key' => 'config_value'] 格式的数组
|
||||
*/
|
||||
public function getValuesByKeys(array $configKeys): array
|
||||
{
|
||||
if (empty($configKeys)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$all = $this->loadAllToCache();
|
||||
|
||||
$result = [];
|
||||
foreach ($configKeys as $key) {
|
||||
if (array_key_exists($key, $all)) {
|
||||
$result[$key] = $all[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置键名更新或创建配置
|
||||
*
|
||||
* @param string $configKey
|
||||
* @param string $configValue
|
||||
* @return bool
|
||||
*/
|
||||
public function updateOrCreate(string $configKey, string $configValue): bool
|
||||
{
|
||||
$this->model
|
||||
->newQuery()
|
||||
->updateOrCreate(
|
||||
['config_key' => $configKey],
|
||||
['config_value' => $configValue]
|
||||
);
|
||||
|
||||
// 通过事件通知重新加载缓存
|
||||
Event::emit('system.config.updated', null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新或创建配置
|
||||
*
|
||||
* @param array $configs 格式:['config_key' => 'config_value']
|
||||
* @return bool
|
||||
*/
|
||||
public function batchUpdateOrCreate(array $configs): bool
|
||||
{
|
||||
if (empty($configs)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($configs as $configKey => $configValue) {
|
||||
$this->model
|
||||
->newQuery()
|
||||
->updateOrCreate(
|
||||
['config_key' => $configKey],
|
||||
['config_value' => $configValue]
|
||||
);
|
||||
}
|
||||
|
||||
// 批量更新后只触发一次事件,通知重新加载缓存
|
||||
Event::emit('system.config.updated', null);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,5 +30,10 @@ Route::group('/adminapi', function () {
|
||||
|
||||
// 系统相关(需要JWT验证)
|
||||
Route::get('/system/getDict[/{code}]', [SystemController::class, 'getDict']);
|
||||
|
||||
// 系统配置相关(需要JWT验证)
|
||||
Route::get('/system/base-config/tabs', [SystemController::class, 'getTabsConfig']);
|
||||
Route::get('/system/base-config/form/{tabKey}', [SystemController::class, 'getFormConfig']);
|
||||
Route::post('/system/base-config/submit/{tabKey}', [SystemController::class, 'submitConfig']);
|
||||
})->middleware([AuthMiddleware::class]);
|
||||
})->middleware([Cors::class]);
|
||||
8
app/routes/mer.php
Normal file
8
app/routes/mer.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* API 路由定义
|
||||
*/
|
||||
|
||||
use Webman\Route;
|
||||
|
||||
@@ -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、用户名、昵称等信息)
|
||||
|
||||
89
app/services/MenuService.php
Normal file
89
app/services/MenuService.php
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
82
app/services/SystemConfigService.php
Normal file
82
app/services/SystemConfigService.php
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
211
app/services/SystemSettingService.php
Normal file
211
app/services/SystemSettingService.php
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
23
app/validation/SystemConfigValidator.php
Normal file
23
app/validation/SystemConfigValidator.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
class SystemConfigValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'config_key' => 'string|max:100',
|
||||
'config_value' => 'nullable|string',
|
||||
];
|
||||
|
||||
protected array $messages = [];
|
||||
|
||||
protected array $attributes = [
|
||||
'config_key' => '配置项键名',
|
||||
'config_value' => '配置项值',
|
||||
];
|
||||
|
||||
protected array $scenes = [];
|
||||
}
|
||||
Reference in New Issue
Block a user