From 2d28a912539838427265461d573916afda5d6262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=B8=85=E7=88=BD?= Date: Mon, 31 Mar 2025 17:33:05 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=9F=BA=E6=9C=AC=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/api/devices.ts | 16 ++ Cunkebao/app/devices/[id]/page.tsx | 163 +++++++++++++++++- Server/application/devices/config/route.php | 1 + .../application/devices/controller/Device.php | 69 ++++++++ 4 files changed, 240 insertions(+), 9 deletions(-) diff --git a/Cunkebao/api/devices.ts b/Cunkebao/api/devices.ts index eece0035..e07f0cfc 100644 --- a/Cunkebao/api/devices.ts +++ b/Cunkebao/api/devices.ts @@ -33,6 +33,22 @@ export const fetchDeviceDetail = async (id: string | number): Promise>(`/v1/devices/${id}`); }; +// 更新设备任务配置 +export const updateDeviceTaskConfig = async ( + id: string | number, + config: { + autoAddFriend?: boolean; + autoReply?: boolean; + momentsSync?: boolean; + aiChat?: boolean; + } +): Promise> => { + return api.post>(`/v1/devices/task-config`, { + id, + ...config + }); +}; + // 删除设备 export const deleteDevice = async (id: number): Promise> => { return api.delete>(`/v1/devices/${id}`); diff --git a/Cunkebao/app/devices/[id]/page.tsx b/Cunkebao/app/devices/[id]/page.tsx index cd258090..b0107eff 100644 --- a/Cunkebao/app/devices/[id]/page.tsx +++ b/Cunkebao/app/devices/[id]/page.tsx @@ -10,7 +10,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Switch } from "@/components/ui/switch" import { Label } from "@/components/ui/label" import { ScrollArea } from "@/components/ui/scroll-area" -import { fetchDeviceDetail } from "@/api/devices" +import { fetchDeviceDetail, updateDeviceTaskConfig } from "@/api/devices" import { toast } from "sonner" interface WechatAccount { @@ -37,7 +37,7 @@ interface Device { features: { autoAddFriend: boolean autoReply: boolean - contentSync: boolean + momentsSync: boolean aiChat: boolean } history: { @@ -68,6 +68,12 @@ export default function DeviceDetailPage() { const [device, setDevice] = useState(null) const [activeTab, setActiveTab] = useState("info") const [loading, setLoading] = useState(true) + const [savingFeatures, setSavingFeatures] = useState({ + autoAddFriend: false, + autoReply: false, + momentsSync: false, + aiChat: false + }) useEffect(() => { if (!params.id) return @@ -91,16 +97,47 @@ export default function DeviceDetailPage() { historicalIds: [], // 服务端暂无此数据 wechatAccounts: [], // 默认空数组 history: [], // 服务端暂无此数据 - features: serverData.features || { + features: { autoAddFriend: false, autoReply: false, - contentSync: false, + momentsSync: false, aiChat: false }, totalFriend: serverData.totalFriend || 0, thirtyDayMsgCount: serverData.thirtyDayMsgCount || 0 } + // 解析features + if (serverData.features) { + // 如果后端直接返回了features对象,使用它 + formattedDevice.features = { + autoAddFriend: Boolean(serverData.features.autoAddFriend), + autoReply: Boolean(serverData.features.autoReply), + momentsSync: Boolean(serverData.features.momentsSync || serverData.features.contentSync), + aiChat: Boolean(serverData.features.aiChat) + } + } else if (serverData.taskConfig) { + try { + // 解析taskConfig字段 + let taskConfig = serverData.taskConfig + if (typeof taskConfig === 'string') { + taskConfig = JSON.parse(taskConfig) + } + + if (taskConfig) { + console.log('解析的taskConfig:', taskConfig); + formattedDevice.features = { + autoAddFriend: Boolean(taskConfig.autoAddFriend), + autoReply: Boolean(taskConfig.autoReply), + momentsSync: Boolean(taskConfig.momentsSync), + aiChat: Boolean(taskConfig.aiChat) + } + } + } catch (err) { + console.error('解析taskConfig失败:', err) + } + } + // 如果有微信账号信息,构建微信账号对象 if (serverData.wechatId) { formattedDevice.wechatAccounts = [ @@ -169,7 +206,7 @@ export default function DeviceDetailPage() { features: { autoAddFriend: true, autoReply: true, - contentSync: false, + momentsSync: false, aiChat: true, }, history: [ @@ -193,6 +230,74 @@ export default function DeviceDetailPage() { fetchDevice() }, [params.id]) + // 处理功能开关状态变化 + const handleFeatureChange = async (feature: keyof Device['features'], checked: boolean) => { + if (!device) return + + // 避免已经在处理中的功能被重复触发 + if (savingFeatures[feature]) { + return + } + + setSavingFeatures(prev => ({ ...prev, [feature]: true })) + + try { + // 准备更新后的功能状态 + const updatedFeatures = { ...device.features, [feature]: checked } + + // 创建API请求参数 + const configUpdate = { [feature]: checked } + + // 立即更新UI状态,提供即时反馈 + setDevice(prev => prev ? { + ...prev, + features: updatedFeatures + } : null) + + // 调用API更新服务器配置 + const response = await updateDeviceTaskConfig(device.id, configUpdate) + + if (response && response.code === 200) { + toast.success(`${getFeatureName(feature)}${checked ? '已启用' : '已禁用'}`) + } else { + // 如果请求失败,回滚UI变更 + setDevice(prev => prev ? { + ...prev, + features: { ...prev.features, [feature]: !checked } + } : null) + + // 处理错误信息,使用类型断言解决字段不一致问题 + const anyResponse = response as any; + const errorMsg = anyResponse ? (anyResponse.message || anyResponse.msg || '未知错误') : '未知错误'; + toast.error(`更新失败: ${errorMsg}`) + } + } catch (error) { + console.error(`更新${getFeatureName(feature)}失败:`, error) + + // 异常情况下也回滚UI变更 + setDevice(prev => prev ? { + ...prev, + features: { ...prev.features, [feature]: !checked } + } : null) + + toast.error('更新失败,请稍后重试') + } finally { + setSavingFeatures(prev => ({ ...prev, [feature]: false })) + } + } + + // 获取功能中文名称 + const getFeatureName = (feature: string): string => { + const nameMap: Record = { + autoAddFriend: '自动加好友', + autoReply: '自动回复', + momentsSync: '朋友圈同步', + aiChat: 'AI会话' + } + + return nameMap[feature] || feature + } + if (loading || !device) { return
加载中...
} @@ -261,28 +366,68 @@ export default function DeviceDetailPage() {
自动通过好友验证
- +
+ {savingFeatures.autoAddFriend && ( +
+ )} + handleFeatureChange('autoAddFriend', checked)} + disabled={savingFeatures.autoAddFriend} + className="data-[state=checked]:bg-blue-500 transition-all duration-200" + /> +
自动回复好友消息
- +
+ {savingFeatures.autoReply && ( +
+ )} + handleFeatureChange('autoReply', checked)} + disabled={savingFeatures.autoReply} + className="data-[state=checked]:bg-blue-500 transition-all duration-200" + /> +
自动同步朋友圈内容
- +
+ {savingFeatures.momentsSync && ( +
+ )} + handleFeatureChange('momentsSync', checked)} + disabled={savingFeatures.momentsSync} + className="data-[state=checked]:bg-blue-500 transition-all duration-200" + /> +
启用AI智能对话
- +
+ {savingFeatures.aiChat && ( +
+ )} + handleFeatureChange('aiChat', checked)} + disabled={savingFeatures.aiChat} + className="data-[state=checked]:bg-blue-500 transition-all duration-200" + /> +
diff --git a/Server/application/devices/config/route.php b/Server/application/devices/config/route.php index c7efd83f..5c92d024 100644 --- a/Server/application/devices/config/route.php +++ b/Server/application/devices/config/route.php @@ -16,6 +16,7 @@ Route::group('v1/', function () { Route::post('', 'app\\devices\\controller\\Device@save'); // 添加设备 Route::put('refresh', 'app\\devices\\controller\\Device@refresh'); // 刷新设备状态 Route::delete(':id', 'app\\devices\\controller\\Device@delete'); // 删除设备 + Route::post('task-config', 'app\\devices\\controller\\Device@updateTaskConfig'); // 更新设备任务配置 }); // 设备微信相关 diff --git a/Server/application/devices/controller/Device.php b/Server/application/devices/controller/Device.php index db574c48..24595a65 100644 --- a/Server/application/devices/controller/Device.php +++ b/Server/application/devices/controller/Device.php @@ -396,4 +396,73 @@ class Device extends Controller ]); } } + + /** + * 更新设备任务配置 + * @return \think\response\Json + */ + public function updateTaskConfig() + { + // 获取请求参数 + $data = $this->request->post(); + + // 验证参数 + if (empty($data['id'])) { + return json(['code' => 400, 'msg' => '设备ID不能为空']); + } + + // 转换为整型,确保ID格式正确 + $deviceId = intval($data['id']); + + // 先获取设备信息,确认设备存在且未删除 + $device = \app\devices\model\Device::where('id', $deviceId) + ->where('isDeleted', 0) + ->find(); + + if (!$device) { + return json(['code' => 404, 'msg' => '设备不存在或已删除']); + } + + // 读取原taskConfig,如果存在则解析 + $taskConfig = []; + if (!empty($device['taskConfig'])) { + $taskConfig = json_decode($device['taskConfig'], true) ?: []; + } + + // 更新需要修改的配置项 + $updateFields = ['autoAddFriend', 'autoReply', 'momentsSync', 'aiChat']; + $hasUpdate = false; + + foreach ($updateFields as $field) { + if (isset($data[$field])) { + // 将值转换为布尔类型存储 + $taskConfig[$field] = (bool)$data[$field]; + $hasUpdate = true; + } + } + + // 如果没有需要更新的字段,直接返回成功 + if (!$hasUpdate) { + return json(['code' => 200, 'msg' => '更新成功', 'data' => ['taskConfig' => $taskConfig]]); + } + + // 更新设备taskConfig字段 + $result = \app\devices\model\Device::where('id', $deviceId) + ->update([ + 'taskConfig' => json_encode($taskConfig), + 'updateTime' => time() + ]); + + if ($result) { + return json([ + 'code' => 200, + 'msg' => '更新任务配置成功', + 'data' => [ + 'taskConfig' => $taskConfig + ] + ]); + } else { + return json(['code' => 500, 'msg' => '更新任务配置失败']); + } + } } \ No newline at end of file