feat(wechat): 微信机器人全链路集成与稳定性修复

- 新增:管理员后台的微信机器人双向收发参数设置页面及扫码绑定能力。
- 新增:WechatBotApiService 与 KafkaConsumerService 模块打通过往僵尸进程导致的拒绝连接问题。
- 新增:下发所有群发/私聊通知时统一带上「[和平聊吧]」标注前缀。
- 优化:前端个人中心绑定逻辑支持一键生成及复制动态口令。
- 修复:闭环联调修补各个模型中产生的变量警告如 stdClass 对象获取等异常预警。
This commit is contained in:
2026-04-02 14:56:51 +08:00
parent 8a809e3cc0
commit fc57f97c9e
19 changed files with 1552 additions and 6 deletions

View File

@@ -0,0 +1,128 @@
<?php
/**
* 文件功能:微信机器人配置控制器
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\SysParam;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class WechatBotController extends Controller
{
/**
* 显示微信机器人配置表单
*/
public function edit(): View
{
// 从 SysParam 获取配置,若不存在赋予默认空 JSON
$param = SysParam::firstOrCreate(
['alias' => 'wechat_bot_config'],
[
'body' => json_encode([
'kafka' => [
'brokers' => '',
'topic' => '',
'group_id' => 'chatroom_wechat_bot',
'bot_wxid' => '',
],
'api' => [
'base_url' => '',
'bot_key' => '',
],
'group_notify' => [
'target_wxid' => '',
'toggle_admin_online' => false,
'toggle_baccarat_result' => false,
'toggle_lottery_result' => false,
],
'personal_notify' => [
'toggle_friend_online' => false,
'toggle_spouse_online' => false,
'toggle_level_change' => false,
],
]),
'guidetxt' => '微信机器人全站配置包含群聊推送和私聊推送开关及Kafka连接',
]
);
$config = json_decode($param->body, true);
return view('admin.wechat_bot.edit', compact('config'));
}
/**
* 更新微信机器人配置
*/
public function update(Request $request): RedirectResponse
{
$validated = $request->validate([
'kafka_brokers' => 'nullable|string',
'kafka_topic' => 'nullable|string',
'kafka_group_id' => 'nullable|string',
'kafka_bot_wxid' => 'nullable|string',
'api_base_url' => 'nullable|string',
'api_bot_key' => 'nullable|string',
'qrcode_image' => 'nullable|image|max:2048',
'group_target_wxid' => 'nullable|string',
'toggle_admin_online' => 'nullable|boolean',
'toggle_baccarat_result' => 'nullable|boolean',
'toggle_lottery_result' => 'nullable|boolean',
'toggle_friend_online' => 'nullable|boolean',
'toggle_spouse_online' => 'nullable|boolean',
'toggle_level_change' => 'nullable|boolean',
]);
$param = SysParam::where('alias', 'wechat_bot_config')->first();
$oldConfig = $param ? (json_decode($param->body, true) ?? []) : [];
$qrcodePath = $oldConfig['api']['qrcode_image'] ?? '';
if ($request->hasFile('qrcode_image')) {
// 删除旧图
if ($qrcodePath && \Illuminate\Support\Facades\Storage::disk('public')->exists($qrcodePath)) {
\Illuminate\Support\Facades\Storage::disk('public')->delete($qrcodePath);
}
$qrcodePath = $request->file('qrcode_image')->store('wechat', 'public');
}
$config = [
'kafka' => [
'brokers' => $validated['kafka_brokers'] ?? '',
'topic' => $validated['kafka_topic'] ?? '',
'group_id' => $validated['kafka_group_id'] ?? 'chatroom_wechat_bot',
'bot_wxid' => $validated['kafka_bot_wxid'] ?? '',
],
'api' => [
'base_url' => $validated['api_base_url'] ?? '',
'bot_key' => $validated['api_bot_key'] ?? '',
'qrcode_image' => $qrcodePath,
],
'group_notify' => [
'target_wxid' => $validated['group_target_wxid'] ?? '',
'toggle_admin_online' => $validated['toggle_admin_online'] ?? false,
'toggle_baccarat_result' => $validated['toggle_baccarat_result'] ?? false,
'toggle_lottery_result' => $validated['toggle_lottery_result'] ?? false,
],
'personal_notify' => [
'toggle_friend_online' => $validated['toggle_friend_online'] ?? false,
'toggle_spouse_online' => $validated['toggle_spouse_online'] ?? false,
'toggle_level_change' => $validated['toggle_level_change'] ?? false,
],
];
if ($param) {
$param->update(['body' => json_encode($config)]);
SysParam::clearCache('wechat_bot_config');
}
return redirect()->route('admin.wechat_bot.edit')->with('success', '机器相关配置已更新完成。如修改了Kafka请重启后端监听队列守护进程。');
}
}

View File

@@ -160,6 +160,16 @@ class AuthController extends Controller
'sdate' => now(),
'uuname' => $user->username,
]);
// 触发微信机器人消息推送 (登录上线类)
try {
$wechatService = new \App\Services\WechatBot\WechatNotificationService;
$wechatService->notifyAdminOnline($user);
$wechatService->notifyFriendsOnline($user);
$wechatService->notifySpouseOnline($user);
} catch (\Exception $e) {
\Illuminate\Support\Facades\Log::error('WechatBot presence notification failed', ['error' => $e->getMessage()]);
}
}
/**

View File

@@ -220,6 +220,45 @@ class UserController extends Controller
return response()->json(['status' => 'success', 'message' => '密码已成功修改。下次请使用新密码登录。']);
}
/**
* 生成微信绑定代码
*/
public function generateWechatCode(\Illuminate\Http\Request $request): JsonResponse
{
$user = \Illuminate\Support\Facades\Auth::user();
if (! $user) {
return response()->json(['status' => 'error', 'message' => '未登录']);
}
$code = 'BD-'.mt_rand(100000, 999999);
\Illuminate\Support\Facades\Cache::put('wechat_bind_code:'.$code, $user->username, 300); // 5分钟有效
return response()->json([
'status' => 'success',
'code' => $code,
'message' => '生成成功',
]);
}
/**
* 取消绑定微信
*/
public function unbindWechat(\Illuminate\Http\Request $request): JsonResponse
{
$user = \Illuminate\Support\Facades\Auth::user();
if (! $user) {
return response()->json(['status' => 'error', 'message' => '未登录']);
}
$user->wxid = null;
$user->save();
return response()->json([
'status' => 'success',
'message' => '解绑成功',
]);
}
/**
* 通用权限校验:检查操作者是否有权操作目标用户
*