feat: 小程序 AI 底栏与聊天页、出站推送调试与 tabbar 迁移

- 自定义 tabBar:AI 入口图标与样式,相关页面与审核门控调整

- API:MpTabbar、出站推送 Hook、后台设置与迁移 SQL(含 FAB 居中排序)

- 管理端:推送 Hook 面板、出站推送调试工具与生产环境注释说明

Made-with: Cursor
This commit is contained in:
Ghost
2026-04-20 15:29:10 +08:00
parent ce55c48c64
commit d07235b64c
26 changed files with 486 additions and 317 deletions

View File

@@ -554,17 +554,11 @@ class Settings extends BaseController
/**
* POST /api/v1/admin/settings/push-hook/test
* 向当前解析到的 URL 发送 hook.ping不写去重表
* 企业后台不提供:请在超管后台调试,避免误触对外 URL / 重放业务数据。
*/
public function testPushHookConfig()
{
$user = $this->request->user ?? null;
if (!$user || !in_array($user['role'], ['admin', 'enterprise_admin'])) {
return error('无权限访问', 403);
}
$ctx = $this->resolveAdminPushHookEnterpriseId();
$r = OutboundPushHookService::sendTestPing($ctx);
return success($r, $r['ok'] ? '测试推送已发出' : ($r['message'] ?? '测试失败'));
return error('连接测试与重放调试仅在超管后台开放', 403);
}
/**
@@ -573,16 +567,7 @@ class Settings extends BaseController
*/
public function testPushHookTestResult()
{
$user = $this->request->user ?? null;
if (!$user || !in_array($user['role'], ['admin', 'enterprise_admin'])) {
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 error('连接测试与重放调试仅在超管后台开放', 403);
}
/**

View File

@@ -55,7 +55,14 @@ class InternalPushHook extends BaseController
if ($uid <= 0 || $cid <= 0 || $jid === '' || strlen($jid) > 64 || !preg_match('/^[a-f0-9]+$/', $jid)) {
return error('invalid ai chat job', 400);
}
\app\controller\api\AiChat::runDeferredChatJob($uid, $cid, $jid);
// 大模型耗时长:须先结束本 HTTP 响应,再在 shutdown 中跑任务;否则主请求里 postJsonAsyncNoWait 无法读到 2xx且易误判投递失败
register_shutdown_function(static function () use ($uid, $cid, $jid) {
try {
\app\controller\api\AiChat::runDeferredChatJob($uid, $cid, $jid);
} catch (\Throwable $e) {
Log::error('InternalPushHook ai.chat_turn deferred: ' . $e->getMessage());
}
});
break;
default:
return error('unsupported job', 400);