request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } try { // 获取系统配置(全局 enterprise_id=0) $systemConfig = SystemConfigModel::where('key', 'system')->where('enterprise_id', 0)->find(); $notificationConfig = SystemConfigModel::where('key', 'notification')->where('enterprise_id', 0)->find(); $promptsConfig = SystemConfigModel::where('key', 'prompts')->where('enterprise_id', 0)->find(); $reportRequiresPaymentConfig = SystemConfigModel::where('key', 'report_requires_payment')->where('enterprise_id', 0)->find(); $textConfigModel = SystemConfigModel::where('key', 'text_config')->where('enterprise_id', 0)->find(); $reviewModeConfig = SystemConfigModel::where('key', 'review_mode')->where('enterprise_id', 0)->find(); // 获取当前超管用户名(直接使用JWT中的username) $jwtUsername = $user['username'] ?? null; $username = 'admin'; if ($jwtUsername) { $currentUser = UserModel::where('username', $jwtUsername) ->where('role', 'superadmin') ->find(); if ($currentUser) { $username = $currentUser->username; } else { // 如果找不到用户,使用JWT中的username $username = $jwtUsername; } } $systemDefault = [ 'siteName' => '神仙团队AI性格测试', 'siteDescription' => '专业的AI性格测试平台', 'miniprogramName' => '神仙团队AI性格测试', 'maintenanceMode' => false, /** 小程序提审:隐藏神仙 AI 对话/深度报告等深度合成入口,与 maintenanceMode(面相审核)可分开 */ 'miniprogramAuditMode' => false, 'maxTestsPerDay' => 100, 'trialTestCount' => 10, 'defaultEnterpriseId' => null, /** 为 true(默认)时:打开超管设置会按间隔拉微信审核状态并自动切换 miniprogramAuditMode */ 'wechatAuditAutoMiniprogramMode' => true, 'wechatLastAuditErrcode' => null, 'wechatLastAuditStatus' => null, 'wechatLastAuditReason' => '', 'wechatLastAuditSyncedAt' => null, ]; $systemOut = $systemDefault; // 仅当 system 行「未包含」maintenanceMode 键时,才用旧表 review_mode 回退(否则关闭审核后会被 review_mode.enabled 再次顶成「已开启」) $hasMaintenanceKeyInSystem = false; if ($systemConfig && $systemConfig->value !== null && $systemConfig->value !== '') { $raw = $systemConfig->value; $decoded = is_array($raw) ? $raw : (is_string($raw) ? json_decode($raw, true) : null); if (is_array($decoded)) { $hasMaintenanceKeyInSystem = array_key_exists('maintenanceMode', $decoded); $systemOut = array_merge($systemDefault, $decoded); } } // 审核模式:system.maintenanceMode 为唯一口径;兼容旧数据仅在没有该键时读 review_mode.enabled $maint = (bool) ($systemOut['maintenanceMode'] ?? false); if (!$hasMaintenanceKeyInSystem && !$maint && $reviewModeConfig && !empty($reviewModeConfig->value)) { $rv = $reviewModeConfig->value; if (is_string($rv)) { $rv = json_decode($rv, true); } if (is_array($rv) && !empty($rv['enabled'])) { $maint = true; } } $systemOut['maintenanceMode'] = $maint; if (!array_key_exists('miniprogramAuditMode', $systemOut)) { $systemOut['miniprogramAuditMode'] = false; } $systemOut['miniprogramAuditMode'] = (bool) ($systemOut['miniprogramAuditMode'] ?? false); if (!array_key_exists('wechatAuditAutoMiniprogramMode', $systemOut)) { $systemOut['wechatAuditAutoMiniprogramMode'] = true; } else { $systemOut['wechatAuditAutoMiniprogramMode'] = $systemOut['wechatAuditAutoMiniprogramMode'] !== false; } // 跟随微信审核:非手动请求时按节流调用,避免每次打开页面都打微信接口 try { if (WechatAuditSyncService::shouldAutoSync($systemOut)) { $sync = WechatAuditSyncService::run(false); if (!empty($sync['systemBroadcast']) && is_array($sync['systemBroadcast'])) { $systemOut = array_merge($systemOut, $sync['systemBroadcast']); } } } catch (\Throwable $e) { \think\facade\Log::error('wechat audit sync on settings index: ' . $e->getMessage()); } // 与前端 el-option 的 number value 对齐,避免类型不一致导致下拉不反显 if (array_key_exists('defaultEnterpriseId', $systemOut)) { $de = $systemOut['defaultEnterpriseId']; if ($de === '' || $de === null || (int) $de <= 0) { $systemOut['defaultEnterpriseId'] = null; } else { $systemOut['defaultEnterpriseId'] = (int) $de; } } return success([ 'system' => $systemOut, 'reviewMode' => ['enabled' => $maint], 'notification' => $notificationConfig ? $notificationConfig->value : [ 'emailNotification' => true, 'lowBalanceAlert' => true, 'lowBalanceThreshold' => 1000, 'newEnterpriseNotify' => true ], 'prompts' => $promptsConfig && !empty($promptsConfig->value) ? $promptsConfig->value : [ 'faceAnalyze' => '{"mbti":"四字母如INTJ","pdp":"老虎/孔雀/无尾熊/猫头鹰/变色龙其一","disc":"D/I/S/C其一","overview":"一段50字以内的综合描述","faceAnalysis":"面相特点简短描述"}', 'reportSummary' => '' ], 'reportRequiresPayment' => $reportRequiresPaymentConfig && !empty($reportRequiresPaymentConfig->value) ? $reportRequiresPaymentConfig->value : ['face' => 1, 'mbti' => 0, 'disc' => 0, 'pdp' => 0], 'textConfig' => $textConfigModel && !empty($textConfigModel->value) ? $textConfigModel->value : [ 'analyzingTitle' => '正在分析中', 'startButtonText' => '30秒测出你的性格', 'startButtonEnterprise' => '开始面部测试', 'reportTitle' => '分析报告', 'aiAnalysisText' => '智能分析' ], 'username' => $username ]); } catch (\Exception $e) { return error('获取配置失败:' . $e->getMessage(), 500); } } /** * 更新系统配置 * @return \think\response\Json */ public function updateSystem() { // 验证是否为超级管理员 $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } // 前端 axios 发 JSON body,用 getContent 解析更可靠 $input = json_decode($this->request->getContent(), true); if (!is_array($input)) { $input = []; } $allowedKeys = ['siteName', 'siteDescription', 'miniprogramName', 'maintenanceMode', 'miniprogramAuditMode', 'wechatAuditAutoMiniprogramMode', 'maxTestsPerDay', 'trialTestCount', 'defaultEnterpriseId']; $data = array_intersect_key($input, array_flip($allowedKeys)); // 兼容 fallback:JSON 解析失败时尝试 Request::only if (empty($data)) { $data = Request::only($allowedKeys); } if (array_key_exists('maintenanceMode', $data)) { $data['maintenanceMode'] = filter_var($data['maintenanceMode'], FILTER_VALIDATE_BOOLEAN); } if (array_key_exists('miniprogramAuditMode', $data)) { $data['miniprogramAuditMode'] = filter_var($data['miniprogramAuditMode'], FILTER_VALIDATE_BOOLEAN); } if (array_key_exists('wechatAuditAutoMiniprogramMode', $data)) { $data['wechatAuditAutoMiniprogramMode'] = filter_var($data['wechatAuditAutoMiniprogramMode'], FILTER_VALIDATE_BOOLEAN); } // 默认企业:0 或空视为不启用 if (array_key_exists('defaultEnterpriseId', $data)) { $de = $data['defaultEnterpriseId']; if ($de === '' || $de === null) { $data['defaultEnterpriseId'] = null; } else { $deInt = (int) $de; if ($deInt <= 0) { $data['defaultEnterpriseId'] = null; } else { $exists = EnterpriseModel::where('id', $deInt)->find(); if (!$exists) { return error('所选默认企业不存在', 400); } $data['defaultEnterpriseId'] = $deInt; } } } $textConfig = $input['textConfig'] ?? (Request::param('textConfig') ?: []); try { // 查找或创建全局配置(enterprise_id=0) $config = SystemConfigModel::where('key', 'system')->where('enterprise_id', 0)->find(); if (!$config) { $config = new SystemConfigModel(); $config->key = 'system'; $config->enterprise_id = 0; $config->description = '系统基础配置'; } // 合并保存,避免仅提交部分字段时丢失其它键(如 defaultEnterpriseId) $oldVal = $config->value; $oldArr = is_array($oldVal) ? $oldVal : (is_string($oldVal) ? (json_decode($oldVal, true) ?: []) : []); if (!is_array($oldArr)) { $oldArr = []; } $config->value = array_merge($oldArr, $data); $config->save(); // 与旧版 review_mode 行同步,避免库内 enabled=true 与 system.maintenanceMode=false 并存 if (array_key_exists('maintenanceMode', $data)) { $rmRow = SystemConfigModel::where('key', 'review_mode')->where('enterprise_id', 0)->find(); if ($rmRow) { $rv = $rmRow->value; $rv = is_array($rv) ? $rv : (is_string($rv) ? (json_decode($rv, true) ?: []) : []); if (!is_array($rv)) { $rv = []; } $rv['enabled'] = !empty($data['maintenanceMode']); $rmRow->value = $rv; $rmRow->save(); } } // 更新站点信息 $this->updateSiteInfo($data); // 保存全局小程序文案配置(enterprise_id=0) if (is_array($textConfig)) { $tcKeys = ['analyzingTitle', 'startButtonText', 'startButtonEnterprise', 'reportTitle', 'aiAnalysisText']; $tcData = array_intersect_key($textConfig, array_flip($tcKeys)); $tcDefaults = ['analyzingTitle' => '正在分析中', 'startButtonText' => '30秒测出你的性格', 'startButtonEnterprise' => '开始面部测试', 'reportTitle' => '分析报告', 'aiAnalysisText' => '智能分析']; $tcConfig = SystemConfigModel::where('key', 'text_config')->where('enterprise_id', 0)->find(); if (!$tcConfig) { $tcConfig = new SystemConfigModel(); $tcConfig->key = 'text_config'; $tcConfig->enterprise_id = 0; $tcConfig->description = '小程序文案配置(全局)'; } $tcConfig->value = array_merge($tcDefaults, $tcData); $tcConfig->save(); } return success($config->value, '系统配置已保存'); } catch (\Exception $e) { return error('保存失败:' . $e->getMessage(), 500); } } /** * POST /api/v1/superadmin/settings/wechat-audit-sync * 立即请求微信 get_latest_auditstatus 并写入 miniprogramAuditMode(不受节流限制) */ public function syncWechatAuditStatus() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } try { $sync = WechatAuditSyncService::run(true); return success([ 'applied' => !empty($sync['applied']), 'miniprogramAuditMode' => (bool) ($sync['miniprogramAuditMode'] ?? false), 'wechat' => $sync['wechat'] ?? [], 'systemBroadcast' => $sync['systemBroadcast'] ?? [], ], '已同步微信审核状态'); } catch (\Throwable $e) { return error('同步失败:' . $e->getMessage(), 500); } } /** * 更新「报告需付费」配置:哪些测试类型需付费后才显示完整报告 * PUT body: { "face": 1, "mbti": 0, "disc": 0, "pdp": 0 }(1=需付费解锁完整,0=免费完整) * @return \think\response\Json */ public function updateReportRequiresPayment() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $data = Request::param('reportRequiresPayment', Request::param('data', [])); if (!is_array($data)) { return error('配置格式错误', 400); } $defaults = ['face' => 1, 'mbti' => 0, 'disc' => 0, 'pdp' => 0]; $value = array_merge($defaults, array_intersect_key($data, array_flip(['face', 'mbti', 'disc', 'pdp']))); $value = array_map(function ($v) { return (int) $v ? 1 : 0; }, $value); try { $config = SystemConfigModel::where('key', 'report_requires_payment')->where('enterprise_id', 0)->find(); if (!$config) { $config = new SystemConfigModel(); $config->key = 'report_requires_payment'; $config->enterprise_id = 0; $config->description = '哪些测试类型需付费后才显示完整报告:1需付费0免费'; } $config->value = $value; $config->save(); return success($config->value, '报告付费开关已保存'); } catch (\Exception $e) { return error('保存失败:' . $e->getMessage(), 500); } } /** * 更新提示词配置 * @return \think\response\Json */ public function updatePrompts() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $data = Request::param('prompts', []); if (!is_array($data)) { return error('提示词配置格式错误', 400); } try { $config = SystemConfigModel::where('key', 'prompts')->where('enterprise_id', 0)->find(); if (!$config) { $config = new SystemConfigModel(); $config->key = 'prompts'; $config->enterprise_id = 0; $config->description = '系统提示词配置(如面相分析、企业简历等)'; } $config->value = $data; $config->save(); return success($config->value, '提示词配置已保存'); } catch (\Exception $e) { return error('保存失败:' . $e->getMessage(), 500); } } /** * 更新通知配置 * @return \think\response\Json */ public function updateNotification() { // 验证是否为超级管理员 $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $data = Request::only([ 'emailNotification', 'lowBalanceAlert', 'lowBalanceThreshold', 'newEnterpriseNotify' ]); try { $config = SystemConfigModel::where('key', 'notification')->where('enterprise_id', 0)->find(); if (!$config) { $config = new SystemConfigModel(); $config->key = 'notification'; $config->enterprise_id = 0; $config->description = '通知与告警配置'; } $config->value = $data; $config->save(); return success($config->value, '通知配置已保存'); } catch (\Exception $e) { return error('保存失败:' . $e->getMessage(), 500); } } /** * 飞书获客 Webhook(与 admin 共用配置) */ public function getFeishuLeadConfig() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $cfg = FeishuLeadWebhookService::getConfig(); return success([ 'enabled' => !empty($cfg['enabled']), 'webhookUrl' => (string) ($cfg['webhookUrl'] ?? ''), 'contactPerson' => (string) ($cfg['contactPerson'] ?? '运营'), ]); } public function updateFeishuLeadConfig() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $raw = $this->request->getContent(); $input = $raw ? json_decode($raw, true) : []; if (!is_array($input)) { $input = []; } $enabled = !empty($input['enabled']); $webhookUrl = trim((string) ($input['webhookUrl'] ?? '')); $contactPerson = trim((string) ($input['contactPerson'] ?? '运营')); if ($contactPerson === '') { $contactPerson = '运营'; } if ($enabled && $webhookUrl !== '' && stripos($webhookUrl, 'http') !== 0) { return error('Webhook 须以 http(s) 开头', 400); } $json = json_encode([ 'enabled' => $enabled, 'webhookUrl' => $webhookUrl, 'contactPerson' => $contactPerson, ], JSON_UNESCAPED_UNICODE); $now = time(); $key = FeishuLeadWebhookService::CONFIG_KEY; $exists = Db::name('system_config')->where('key', $key)->where('enterprise_id', 0)->find(); if ($exists) { Db::name('system_config') ->where('key', $key) ->where('enterprise_id', 0) ->update(['value' => $json, 'updatedAt' => $now]); } else { Db::name('system_config')->insert([ 'key' => $key, 'enterprise_id' => 0, 'value' => $json, 'description' => '飞书获客 Webhook', 'createdAt' => $now, 'updatedAt' => $now, ]); } return success(null, '已保存'); } /** * 通用 HTTP 出站推送 Hook(仅维护全平台默认 enterprise_id=0;企业专属由企业管理端维护) * GET /api/v1/superadmin/settings/push-hook */ public function getPushHookConfig() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $cfg = OutboundPushHookService::getConfig(0); $events = $cfg['events'] ?? []; if (!is_array($events)) { $events = []; } return success([ 'scope' => 'platform', 'configEnterpriseId' => 0, 'enterpriseName' => null, 'enabled' => !empty($cfg['enabled']), 'url' => (string) ($cfg['url'] ?? ''), 'secret' => (string) ($cfg['secret'] ?? ''), 'events' => $events, ]); } /** * PUT /api/v1/superadmin/settings/push-hook */ public function updatePushHookConfig() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $raw = $this->request->getContent(); $input = $raw ? json_decode($raw, true) : []; if (!is_array($input)) { $input = []; } $enabled = !empty($input['enabled']); $url = trim((string) ($input['url'] ?? '')); $secret = (string) ($input['secret'] ?? ''); $eventsRaw = $input['events'] ?? null; $events = []; if (is_array($eventsRaw)) { foreach ($eventsRaw as $ev) { $ev = trim((string) $ev); if ($ev !== '') { $events[] = $ev; } } } if ($enabled && $url !== '' && stripos($url, 'http') !== 0) { return error('URL 须以 http(s) 开头', 400); } $json = json_encode([ 'enabled' => $enabled, 'url' => $url, 'secret' => $secret, 'events' => $events, ], JSON_UNESCAPED_UNICODE); $now = time(); $key = OutboundPushHookService::CONFIG_KEY; $exists = Db::name('system_config')->where('key', $key)->where('enterprise_id', 0)->find(); if ($exists) { Db::name('system_config') ->where('key', $key) ->where('enterprise_id', 0) ->update(['value' => $json, 'updatedAt' => $now]); } else { Db::name('system_config')->insert([ 'key' => $key, 'enterprise_id' => 0, 'value' => $json, 'description' => '通用 HTTP 出站推送 Hook(全平台默认)', 'createdAt' => $now, 'updatedAt' => $now, ]); } return success(null, '已保存'); } /** * POST /api/v1/superadmin/settings/push-hook/test * 按全平台默认配置发送 hook.ping(contextEnterpriseId=0) */ public function testPushHookConfig() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $r = OutboundPushHookService::sendTestPing(0); return success($r, $r['ok'] ? '测试推送已发出' : ($r['message'] ?? '测试失败')); } /** * POST /api/v1/superadmin/settings/push-hook/test-result * 按真实业务数据重放一条 test.result_completed,支持 force=1 强制清去重。 */ public function testPushHookTestResult() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $testResultId = (int) Request::param('testResultId', 0); $force = (int) Request::param('force', 0) === 1; $r = OutboundPushHookService::replayTestResultForDebug($testResultId, $force); return success($r, $r['message'] ?? ($r['ok'] ? '已重放推送' : '重放失败')); } /** * 更新超管账户信息 * @return \think\response\Json */ public function updateCredentials() { // 验证是否为超级管理员 $user = $this->request->user ?? null; if (!$user || ($user['role'] ?? '') !== 'superadmin') { return error('无权限访问', 403); } // 兼容 axios JSON PUT 与表单提交 $rawBody = $this->request->getContent(); if (empty($rawBody)) { $rawBody = file_get_contents('php://input'); } $input = $rawBody ? json_decode($rawBody, true) : null; if (!is_array($input)) { $input = []; } $username = trim((string)($input['username'] ?? Request::param('username', ''))); $currentPassword = (string)($input['currentPassword'] ?? Request::param('currentPassword', '')); $newPassword = (string)($input['newPassword'] ?? Request::param('newPassword', '')); $confirmPassword = (string)($input['confirmPassword'] ?? Request::param('confirmPassword', '')); if (empty($username)) { return error('用户名不能为空', 400); } try { // 优先使用JWT中的username来查找用户(最可靠的方式) $jwtUsername = $user['username'] ?? null; if (empty($jwtUsername)) { \think\facade\Log::error('JWT中缺少username', [ 'user' => $user, 'requestUserId' => $this->request->userId ?? null ]); return error('无法获取用户信息,请重新登录', 400); } // 直接通过username查找用户 $userModel = UserModel::where('username', $jwtUsername) ->where('role', 'superadmin') ->find(); if (!$userModel) { // 添加调试信息 \think\facade\Log::error('用户不存在', [ 'jwtUsername' => $jwtUsername, 'user' => $user, 'requestUserId' => $this->request->userId ?? null, 'requestUsername' => $username ]); return error('用户不存在,请检查登录状态', 404); } // 验证当前用户是否为超级管理员(双重验证) if ($userModel->role !== 'superadmin') { \think\facade\Log::error('用户角色不正确', [ 'userId' => $userModel->id, 'role' => $userModel->role ]); return error('无权限修改此账户', 403); } // 如果要修改密码,需要验证当前密码 if (!empty($newPassword)) { if (empty($currentPassword)) { return error('请输入当前密码', 400); } if ($newPassword !== $confirmPassword) { return error('两次输入的密码不一致', 400); } // 验证当前密码(User 模型中 password 字段已是加密值) if (!password_verify($currentPassword, $userModel->password)) { return error('当前密码错误', 400); } // 更新密码:传入明文,交由 User 模型的 setPasswordAttr 自动加密 $userModel->password = $newPassword; } // 更新用户名 if ($username !== $userModel->username) { // 检查用户名是否已存在(排除当前用户) $exists = UserModel::where('username', $username) ->where('id', '<>', $userModel->id) ->find(); if ($exists) { return error('用户名已存在', 400); } $userModel->username = $username; } $userModel->save(); return success([ 'username' => $userModel->username ], '账户信息已更新'); } catch (\Exception $e) { return error('更新失败:' . $e->getMessage(), 500); } } /** * 更新审核模式:仅写入 system 顶层 maintenanceMode(true/false),与 runtime 一致。 * PUT body: { "enabled": true } 或 { "maintenanceMode": true }(二者等价,任一即可) */ public function updateReviewMode() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $input = json_decode($this->request->getContent(), true); if (!is_array($input)) { $input = Request::param(); } $on = false; if (array_key_exists('maintenanceMode', $input)) { $on = !empty($input['maintenanceMode']); } elseif (array_key_exists('enabled', $input)) { $on = !empty($input['enabled']); } try { $config = SystemConfigModel::where('key', 'system')->where('enterprise_id', 0)->find(); if (!$config) { $config = new SystemConfigModel(); $config->key = 'system'; $config->enterprise_id = 0; $config->description = '系统基础配置'; } $oldVal = $config->value; $oldArr = is_array($oldVal) ? $oldVal : (is_string($oldVal) ? (json_decode($oldVal, true) ?: []) : []); if (!is_array($oldArr)) { $oldArr = []; } $oldArr['maintenanceMode'] = (bool) $on; $config->value = $oldArr; $config->save(); $rmRow = SystemConfigModel::where('key', 'review_mode')->where('enterprise_id', 0)->find(); if ($rmRow) { $rv = $rmRow->value; $rv = is_array($rv) ? $rv : (is_string($rv) ? (json_decode($rv, true) ?: []) : []); if (!is_array($rv)) { $rv = []; } $rv['enabled'] = (bool) $on; $rmRow->value = $rv; $rmRow->save(); } return success([ 'maintenanceMode' => (bool) $on, 'enabled' => (bool) $on, ], '审核模式已' . ($on ? '开启' : '关闭')); } catch (\Exception $e) { return error('保存失败:' . $e->getMessage(), 500); } } /** * 获取可用字体列表 * GET /api/v1/superadmin/settings/fonts */ public function getFonts() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $fonts = \app\common\service\PosterService::getAvailableFonts(); return success([ 'fonts' => $fonts, 'fontDir' => root_path() . 'public/fonts/', 'dirExist' => is_dir(root_path() . 'public/fonts/'), ]); } /** * 获取海报配置 * GET /api/v1/superadmin/settings/poster */ public function getPosterConfig() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $row = Db::name('system_config')->where('key', 'poster_config')->where('enterprise_id', 0)->find(); $raw = $row['value'] ?? null; $poster = self::decodeJsonSafe($raw) ?: [ 'bgColor' => '#ffffff', 'bgImage' => '', 'elements' => [] ]; return success(['poster' => $poster]); } /** * 保存海报配置 * PUT /api/v1/superadmin/settings/poster */ public function updatePosterConfig() { $user = $this->request->user ?? null; if (!$user || $user['role'] !== 'superadmin') { return error('无权限访问', 403); } $input = json_decode($this->request->getContent(), true); if (!is_array($input)) { $input = []; } $data = [ 'bgColor' => $input['bgColor'] ?? '#ffffff', 'bgImage' => $input['bgImage'] ?? '', 'elements' => $input['elements'] ?? [] ]; $jsonValue = json_encode($data, JSON_UNESCAPED_UNICODE); try { $now = time(); $exists = Db::name('system_config')->where('key', 'poster_config')->where('enterprise_id', 0)->find(); if ($exists) { Db::name('system_config') ->where('key', 'poster_config') ->where('enterprise_id', 0) ->update(['value' => $jsonValue, 'updatedAt' => $now]); } else { Db::name('system_config')->insert([ 'key' => 'poster_config', 'enterprise_id' => 0, 'value' => $jsonValue, 'description' => '分销海报可视化配置(全局)', 'createdAt' => $now, 'updatedAt' => $now, ]); } return success(null, '海报配置已保存'); } catch (\Exception $e) { return error('保存失败:' . $e->getMessage(), 500); } } /** * 安全解码 JSON(处理可能的多重编码) */ private static function decodeJsonSafe($raw): ?array { if (!$raw) return null; $val = $raw; for ($i = 0; $i < 5 && is_string($val); $i++) { $decoded = json_decode($val, true); if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) break; $val = $decoded; } return is_array($val) ? $val : null; } /** * 更新站点信息 * 当系统配置中的siteName或siteDescription修改时,同步更新站点信息 */ private function updateSiteInfo($systemData) { try { $siteConfig = SystemConfigModel::where('key', 'site_info')->where('enterprise_id', 0)->find(); $siteInfo = [ 'siteName' => $systemData['siteName'] ?? '', 'siteDescription' => $systemData['siteDescription'] ?? '', 'miniprogramName' => $systemData['miniprogramName'] ?? '', 'updatedAt' => time() ]; if (!$siteConfig) { $siteConfig = new SystemConfigModel(); $siteConfig->key = 'site_info'; $siteConfig->enterprise_id = 0; $siteConfig->description = '站点信息配置'; } $siteConfig->value = $siteInfo; $siteConfig->save(); // 也可以更新其他相关的配置或缓存 // 例如:清除缓存、更新.env文件等 } catch (\Exception $e) { // 站点信息更新失败不影响系统配置保存 \think\facade\Log::error('更新站点信息失败:' . $e->getMessage()); } } }