diff --git a/Cunkebao/app/components/device-selection-dialog.tsx b/Cunkebao/app/components/device-selection-dialog.tsx index 05625768..db65cd37 100644 --- a/Cunkebao/app/components/device-selection-dialog.tsx +++ b/Cunkebao/app/components/device-selection-dialog.tsx @@ -123,9 +123,9 @@ export function DeviceSelectionDialog({ open, onOpenChange, selectedDevices, onS
{/* 搜索和筛选 */}
- setSearchQuery(e.target.value)} className="flex-1 rounded-lg border-gray-200 focus:border-blue-500 focus:ring-2 focus:ring-blue-100" /> diff --git a/Cunkebao/app/scenarios/[channel]/edit/[id]/page.tsx b/Cunkebao/app/scenarios/[channel]/edit/[id]/page.tsx index 531ad57f..014d1641 100644 --- a/Cunkebao/app/scenarios/[channel]/edit/[id]/page.tsx +++ b/Cunkebao/app/scenarios/[channel]/edit/[id]/page.tsx @@ -1,13 +1,12 @@ "use client" -import { useState, useEffect } from "react" +import { useState, useEffect, use } from "react" import { ChevronLeft } from "lucide-react" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" import { BasicSettings } from "../../../new/steps/BasicSettings" import { FriendRequestSettings } from "../../../new/steps/FriendRequestSettings" import { MessageSettings } from "../../../new/steps/MessageSettings" -import { TagSettings } from "@/scenarios/new/steps/TagSettings" import { useRouter } from "next/navigation" import { toast } from "@/components/ui/use-toast" import { api, ApiResponse } from "@/lib/api" @@ -16,40 +15,47 @@ const steps = [ { id: 1, title: "步骤一", subtitle: "基础设置" }, { id: 2, title: "步骤二", subtitle: "好友申请设置" }, { id: 3, title: "步骤三", subtitle: "消息设置" }, - { id: 4, title: "步骤四", subtitle: "流量标签设置" }, ] -export default function EditAcquisitionPlan({ params }: { params: { channel: string; id: string } }) { +export default function EditAcquisitionPlan({ params }: { params: Promise<{ channel: string; id: string }> }) { const router = useRouter() const [currentStep, setCurrentStep] = useState(1) const [loading, setLoading] = useState(true) const [scenes, setScenes] = useState([]) const [formData, setFormData] = useState({ planName: "", - accounts: [], - dailyLimit: 10, - enabled: true, - remarkType: "phone", - remarkKeyword: "", + posters: [], + device: [], + remarkType: "default", greeting: "", - addFriendTimeStart: "09:00", - addFriendTimeEnd: "18:00", - addFriendInterval: 1, - maxDailyFriends: 20, - messageInterval: 1, - messageContent: "", + addInterval: 60, + startTime: "09:00", + endTime: "18:00", + enabled: true, + sceneId: "", + scenario: "", + planNameEdited: false }) + const [planNameEdited, setPlanNameEdited] = useState(false); + + const resolvedParams = use(params); + const { id, channel } = resolvedParams; useEffect(() => { const fetchPlanData = async () => { try { const [planRes, scenesRes] = await Promise.all([ - api.get(`/v1/plan/detail?id=${params.id}`), + api.get(`/v1/plan/detail?planId=${id}`), api.get("/v1/plan/scenes") ]) if (planRes.code === 200 && planRes.data) { - setFormData(planRes.data) + setFormData({ + ...planRes.data, + device: planRes.data.device || [], + selectedDevices: planRes.data.device || [], + planNameEdited: false + }) } if (scenesRes.code === 200 && Array.isArray(scenesRes.data)) { @@ -68,18 +74,23 @@ export default function EditAcquisitionPlan({ params }: { params: { channel: str } fetchPlanData() - }, [params.id]) + }, [id]) const handleSave = async () => { try { - const res = await api.put(`/v1/plan/update?id=${params.id}`, formData) - + const submitData = { + ...formData, + device: formData.selectedDevices || formData.device, + posters: formData.materials || formData.posters, + }; + const { selectedDevices, materials, ...finalData } = submitData; + const res = await api.put(`/v1/plan/update?planId=${id}`, finalData); if (res.code === 200) { - toast({ - title: "保存成功", - description: "获客计划已更新", - }) - router.push(`/scenarios/${params.channel}`) + toast({ + title: "保存成功", + description: "获客计划已更新", + }) + router.push(`/scenarios/${channel}`) } else { toast({ title: "保存失败", @@ -113,7 +124,7 @@ export default function EditAcquisitionPlan({ params }: { params: { channel: str const isStepValid = () => { switch (currentStep) { case 1: - if (!formData.planName.trim() || formData.accounts.length === 0) { + if (!formData.planName.trim() || formData.posters.length === 0) { toast({ title: "请完善信息", description: "请填写计划名称并选择至少一个账号", @@ -133,7 +144,7 @@ export default function EditAcquisitionPlan({ params }: { params: { channel: str } return true case 3: - if (!formData.messageContent.trim()) { + if (!formData.messageContent || !formData.messageContent.trim()) { toast({ title: "请完善信息", description: "请填写消息内容", @@ -142,13 +153,16 @@ export default function EditAcquisitionPlan({ params }: { params: { channel: str return false } return true - case 4: - return true default: return true } } + const onChange = (data: any) => { + if ('planName' in data) setPlanNameEdited(true); + setFormData(prev => ({ ...prev, ...data })) + } + if (loading) { return (
@@ -163,15 +177,11 @@ export default function EditAcquisitionPlan({ params }: { params: { channel: str const renderStepContent = () => { switch (currentStep) { case 1: - return + return case 2: - return ( - - ) + return case 3: - return - case 4: - return + return default: return null } @@ -182,7 +192,7 @@ export default function EditAcquisitionPlan({ params }: { params: { channel: str
-

编辑获客计划

@@ -225,18 +235,7 @@ export default function EditAcquisitionPlan({ params }: { params: { channel: str
{renderStepContent()}
-
-
- {currentStep > 1 && ( - - )} - -
-
+
diff --git a/Cunkebao/app/scenarios/new/page.tsx b/Cunkebao/app/scenarios/new/page.tsx index 3d33bbf9..cce8ec8b 100644 --- a/Cunkebao/app/scenarios/new/page.tsx +++ b/Cunkebao/app/scenarios/new/page.tsx @@ -1,7 +1,7 @@ "use client" import { useState, useEffect } from "react" -import { useRouter } from "next/navigation" +import { useRouter, useSearchParams } from "next/navigation" import { ChevronLeft, Settings } from "lucide-react" import { Button } from "@/components/ui/button" import { toast } from "@/components/ui/use-toast" @@ -20,17 +20,21 @@ const steps = [ export default function NewPlan() { const router = useRouter() + const searchParams = useSearchParams() const [currentStep, setCurrentStep] = useState(1) const [formData, setFormData] = useState({ planName: "", posters: [], device: [], - remarkType: "phone", - greeting: "你好,请通过", - addInterval: 1, + remarkType: "default", + greeting: "", + addInterval: 60, startTime: "09:00", endTime: "18:00", enabled: true, + sceneId: searchParams.get("type") || "", + scenario: searchParams.get("type") || "", + planNameEdited: false }) // 场景数据 @@ -49,7 +53,8 @@ export default function NewPlan() { // 更新表单数据 const onChange = (data: any) => { - setFormData((prev) => ({ ...prev, ...data })) + if ('planName' in data) setFormData(prev => ({ ...prev, planNameEdited: true })) + setFormData(prev => ({ ...prev, ...data })) } // 处理保存 @@ -103,7 +108,7 @@ export default function NewPlan() { const renderStepContent = () => { switch (currentStep) { case 1: - return + return case 2: return case 3: diff --git a/Cunkebao/app/scenarios/new/steps/BasicSettings.tsx b/Cunkebao/app/scenarios/new/steps/BasicSettings.tsx index ef2220ab..23092918 100644 --- a/Cunkebao/app/scenarios/new/steps/BasicSettings.tsx +++ b/Cunkebao/app/scenarios/new/steps/BasicSettings.tsx @@ -2,7 +2,7 @@ import type React from "react" -import { useState, useEffect, useRef } from "react" +import { useState, useEffect, useRef, useMemo } from "react" import { Card } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" @@ -262,7 +262,7 @@ const PlaceholderSection = ({ title }) => (
{title}功能区待开发
) -export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSettingsProps) { +export function BasicSettings({ formData, onChange, onNext, scenarios, loadingScenes, planNameEdited }: BasicSettingsProps & { loadingScenes?: boolean, planNameEdited?: boolean }) { const [isAccountDialogOpen, setIsAccountDialogOpen] = useState(false) const [isMaterialDialogOpen, setIsMaterialDialogOpen] = useState(false) const [isQRCodeOpen, setIsQRCodeOpen] = useState(false) @@ -325,29 +325,21 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe const searchParams = useSearchParams() const type = searchParams.get("type") - // 类型映射表 - const typeMap: Record = { - haibao: "poster", - douyin: "douyin", - kuaishou: "kuaishou", - xiaohongshu: "xiaohongshu", - weibo: "weibo", - phone: "phone", - gongzhonghao: "gongzhonghao", - weixinqun: "weixinqun", - payment: "payment", - api: "api", - order: "order" - } - const realType = typeMap[type] || type - const filteredScenarios = scenarios.filter(scene => scene.type === realType) - - // 只在有唯一匹配时自动选中,否则不自动选中 + // 初始化时,如果有type参数且scenarios已加载,立即设置选中状态 useEffect(() => { - if (filteredScenarios.length === 1 && formData.sceneId !== filteredScenarios[0].id) { - onChange({ sceneId: filteredScenarios[0].id }) + if (!loadingScenes && scenarios.length > 0 && type && !planNameEdited) { + const targetScenario = scenarios.find(scene => String(scene.id) === String(type)); + if (targetScenario) { + onChange({ + sceneId: String(type), + scenario: String(type), + planName: targetScenario.name.includes('电话') + ? `电话获客${new Date().toLocaleDateString("zh-CN").replace(/\//g, "")}` + : targetScenario.name + new Date().toLocaleDateString("zh-CN").replace(/\//g, "") + }); + } } - }, [filteredScenarios, formData.sceneId, onChange]) + }, [loadingScenes, scenarios, type, planNameEdited]); // 展示所有场景 const displayedScenarios = scenarios @@ -382,11 +374,22 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe }, [formData, onChange]) const handleScenarioSelect = (scenarioId: string) => { + const targetScenario = scenarios.find(s => String(s.id) === String(scenarioId)); + if (targetScenario) { if (scenarioId === "phone") { - const today = new Date().toLocaleDateString("zh-CN").replace(/\//g, "") - onChange({ ...formData, scenario: scenarioId, planName: `电话获客${today}` }) + const today = new Date().toLocaleDateString("zh-CN").replace(/\//g, ""); + onChange({ + sceneId: String(scenarioId), + scenario: String(scenarioId), + planName: `电话获客${today}` + }); } else { - onChange({ ...formData, scenario: scenarioId }) + onChange({ + sceneId: String(scenarioId), + scenario: String(scenarioId), + planName: targetScenario.name + new Date().toLocaleDateString("zh-CN").replace(/\//g, "") + }); + } } } @@ -498,7 +501,15 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe setIsPhoneSettingsOpen(false) } - const currentScenario = scenarios.find((s: any) => s.id === formData.scenario); + const currentScenario = useMemo( + () => scenarios.find((s: any) => String(s.id) === String(formData.scenario)), + [scenarios, formData.scenario] + ) + + // 调试日志 + useEffect(() => { + console.log('formData:', formData, 'currentScenario:', currentScenario); + }, [formData, currentScenario]); const handleUploadPoster = () => { fileInputRef.current?.click() @@ -778,12 +789,12 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe type="button" className={ "h-10 rounded-lg text-base transition-all w-full " + - (formData.sceneId === scenario.id + (String(formData.sceneId) === String(scenario.id) ? "bg-blue-100 font-bold" : "bg-gray-50 text-gray-800 font-medium hover:bg-blue-50") } - style={formData.sceneId === scenario.id ? { color: "#1677ff" } : {}} - onClick={() => handleScenarioSelect(scenario.id)} + style={String(formData.sceneId) === String(scenario.id) ? { color: "#1677ff" } : {}} + onClick={() => handleScenarioSelect(String(scenario.id))} > {scenario.name.replace("获客", "")} @@ -809,20 +820,20 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe />
- {formData.scenario && ( + {currentScenario && (
- {(scenarios.find((s) => s.id === formData.scenario)?.scenarioTags || []).map((tag: string) => { + {(currentScenario.scenarioTags || []).map((tag: string) => { const idx = getTagColorIdx(tag); const selected = selectedScenarioTags.includes(tag); return ( -
handleScenarioTagToggle(tag)} > {tag} -
+
); })}
@@ -897,10 +908,10 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe
)} - {formData.scenario && ( + {currentScenario && ( <> - {scenarios.find((s) => s.id === formData.scenario)?.type === "social" && - formData.scenario !== "phone" && ( + {currentScenario.type === "social" && + currentScenario.id !== "phone" && (
@@ -940,7 +951,7 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe
)} - {formData.scenario === "phone" && ( + {String(formData.scenario) === "phone" && (
@@ -1001,7 +1012,7 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe )} - {formData.scenario === "phone" && ( + {String(formData.scenario) === "phone" && ( <>
@@ -1034,13 +1045,13 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe
- {(scenarios.find((s: any) => s.id === formData.scenario)?.scenarioTags || []).map((tag: string) => { + {(currentScenario.scenarioTags || []).map((tag: string) => { const idx = getTagColorIdx(tag); const selected = selectedPhoneTags.includes(tag); return ( -
handleTagToggle(tag)} > {tag} -
+
); })}
@@ -1056,13 +1067,13 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe )} - {((currentScenario?.type === "material" || currentScenario?.name === "海报获客" || currentScenario?.id === 1) && ( + {((currentScenario?.type === "material" || currentScenario?.name === "海报获客" || String(currentScenario?.id) === "1") && (
{renderSceneExtra()} -
- ))} +
+ ))} - {scenarios.find((s: any) => s.id === formData.scenario)?.id === "order" && ( + {String(currentScenario?.id) === "order" && (
@@ -1114,7 +1125,7 @@ export function BasicSettings({ formData, onChange, onNext, scenarios }: BasicSe )}
)} - {formData.scenario === "weixinqun" && ( + {String(formData.scenario) === "weixinqun" && ( <>
diff --git a/Cunkebao/app/scenarios/new/steps/FriendRequestSettings.tsx b/Cunkebao/app/scenarios/new/steps/FriendRequestSettings.tsx index 10fb75f3..63751727 100644 --- a/Cunkebao/app/scenarios/new/steps/FriendRequestSettings.tsx +++ b/Cunkebao/app/scenarios/new/steps/FriendRequestSettings.tsx @@ -102,8 +102,8 @@ export function FriendRequestSettings({ formData, onChange, onNext, onPrev }: Fr // 设备选择回填 const handleDeviceSelect = (deviceIds: string[]) => { setSelectedDeviceIds(deviceIds) - // 只存id,或如需完整对象可自行扩展 - onChange({ ...formData, selectedDevices: deviceIds }) + // 同步 device 和 selectedDevices 字段 + onChange({ ...formData, selectedDevices: deviceIds, device: deviceIds }) } return ( diff --git a/Cunkebao/app/scenarios/new/steps/MessageSettings.tsx b/Cunkebao/app/scenarios/new/steps/MessageSettings.tsx index 800d5fb7..d8bd8451 100644 --- a/Cunkebao/app/scenarios/new/steps/MessageSettings.tsx +++ b/Cunkebao/app/scenarios/new/steps/MessageSettings.tsx @@ -583,7 +583,7 @@ export function MessageSettings({ formData, onChange, onNext, onPrev }: MessageS - +
diff --git a/Cunkebao/app/workspace/traffic-distribution/[id]/edit/page.tsx b/Cunkebao/app/workspace/traffic-distribution/[id]/edit/page.tsx index d0a4e056..a7ec2ecb 100644 --- a/Cunkebao/app/workspace/traffic-distribution/[id]/edit/page.tsx +++ b/Cunkebao/app/workspace/traffic-distribution/[id]/edit/page.tsx @@ -49,7 +49,7 @@ export default function EditTrafficDistributionPage({ params }: { params: Promis const [loading, setLoading] = useState(true) const [formData, setFormData] = useState({ basicInfo: { - name: "", + name: "", distributeType: 1, maxPerDay: 100, timeType: 2, @@ -57,7 +57,7 @@ export default function EditTrafficDistributionPage({ params }: { params: Promis endTime: "22:00", source: "", sourceIcon: "", - description: "", + description: "", }, targetSettings: { targetGroups: [], @@ -217,4 +217,4 @@ export default function EditTrafficDistributionPage({ params }: { params: Promis
) -} + } diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index e7094ff0..ff4709e6 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -43,6 +43,8 @@ Route::group('v1/', function () { Route::get('copy', 'app\cunkebao\controller\plan\PlanSceneV1Controller@copy'); Route::delete('delete', 'app\cunkebao\controller\plan\PlanSceneV1Controller@delete'); Route::post('updateStatus', 'app\cunkebao\controller\plan\PlanSceneV1Controller@updateStatus'); + Route::get('detail', 'app\cunkebao\controller\plan\GetAddFriendPlanDetailV1Controller@index'); + Route::PUT('update', 'app\cunkebao\controller\plan\PostUpdateAddFriendPlanV1Controller@index'); }); // 流量池相关 diff --git a/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php b/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php index 59e8a799..33410d13 100644 --- a/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php +++ b/Server/application/cunkebao/controller/device/GetDeviceListV1Controller.php @@ -79,7 +79,6 @@ class GetDeviceListV1Controller extends BaseController ]) ->leftJoin('device_wechat_login l', 'd.id = l.deviceId and l.alive =' . DeviceWechatLoginModel::ALIVE_WECHAT_ACTIVE . ' and l.companyId = d.companyId') ->leftJoin('wechat_account a', 'l.wechatId = a.wechatId') - ->group('l.wechatId') ->order('d.id desc'); foreach ($where as $key => $value) { diff --git a/Server/application/cunkebao/controller/plan/GetAddFriendPlanDetailV1Controller.php b/Server/application/cunkebao/controller/plan/GetAddFriendPlanDetailV1Controller.php new file mode 100644 index 00000000..0dbe4f45 --- /dev/null +++ b/Server/application/cunkebao/controller/plan/GetAddFriendPlanDetailV1Controller.php @@ -0,0 +1,65 @@ +request->param('planId'); + + if (empty($planId)) { + return ResponseHelper::error('计划ID不能为空', 400); + } + + // 查询计划详情 + $plan = Db::name('customer_acquisition_task') + ->where('id', $planId) + ->find(); + + if (!$plan) { + return ResponseHelper::error('计划不存在', 404); + } + + // 解析JSON字段 + $sceneConf = json_decode($plan['sceneConf'], true) ?: []; + $reqConf = json_decode($plan['reqConf'], true) ?: []; + $msgConf= json_decode($plan['msgConf'], true) ?: []; + $tagConf = json_decode($plan['tagConf'], true) ?: []; + + $newData['messagePlans'] = $msgConf; + $newData = array_merge($newData,$sceneConf,$reqConf,$tagConf,$plan); + unset( + $newData['sceneConf'], + $newData['reqConf'], + $newData['msgConf'], + $newData['tagConf'], + $newData['userInfo'], + $newData['createTime'], + $newData['updateTime'], + $newData['deleteTime'], + $newData['apiKey'] + ); + + + + return ResponseHelper::success($newData, '获取计划详情成功'); + + } catch (\Exception $e) { + return ResponseHelper::error('系统错误: ' . $e->getMessage(), 500); + } + } +} \ No newline at end of file diff --git a/Server/application/cunkebao/controller/plan/PostCreateAddFriendPlanV1Controller.php b/Server/application/cunkebao/controller/plan/PostCreateAddFriendPlanV1Controller.php index c716ed26..a2303056 100644 --- a/Server/application/cunkebao/controller/plan/PostCreateAddFriendPlanV1Controller.php +++ b/Server/application/cunkebao/controller/plan/PostCreateAddFriendPlanV1Controller.php @@ -61,7 +61,7 @@ class PostCreateAddFriendPlanV1Controller extends Controller $params = $this->request->param(); // 验证必填字段 - if (empty($params['planName'])) { + if (empty($params['name'])) { return ResponseHelper::error('计划名称不能为空', 400); } @@ -91,8 +91,8 @@ class PostCreateAddFriendPlanV1Controller extends Controller // 其余参数归为sceneConf $sceneConf = $params; unset( - $sceneConf['planName'], - $sceneConf['scenario'], + $sceneConf['name'], + $sceneConf['sceneId'], $sceneConf['messagePlans'], $sceneConf['scenarioTags'], $sceneConf['customTags'], @@ -106,8 +106,8 @@ class PostCreateAddFriendPlanV1Controller extends Controller // 构建数据 $data = [ - 'name' => $params['planName'], - 'sceneId' => $params['scenario'], + 'name' => $params['name'], + 'sceneId' => $params['sceneId'], 'sceneConf' => json_encode($sceneConf, JSON_UNESCAPED_UNICODE), 'reqConf' => json_encode($reqConf, JSON_UNESCAPED_UNICODE), 'msgConf' => json_encode($msgConf, JSON_UNESCAPED_UNICODE), diff --git a/Server/application/cunkebao/controller/plan/PostUpdateAddFriendPlanV1Controller.php b/Server/application/cunkebao/controller/plan/PostUpdateAddFriendPlanV1Controller.php new file mode 100644 index 00000000..4b7499bb --- /dev/null +++ b/Server/application/cunkebao/controller/plan/PostUpdateAddFriendPlanV1Controller.php @@ -0,0 +1,120 @@ +request->param(); + + // 验证必填字段 + if (empty($params['planId'])) { + return ResponseHelper::error('计划ID不能为空', 400); + } + + if (empty($params['name'])) { + return ResponseHelper::error('计划名称不能为空', 400); + } + + if (empty($params['sceneId'])) { + return ResponseHelper::error('场景ID不能为空', 400); + } + + if (empty($params['device'])) { + return ResponseHelper::error('请选择设备', 400); + } + + // 检查计划是否存在 + $plan = Db::name('customer_acquisition_task') + ->where('id', $params['planId']) + ->find(); + + if (!$plan) { + return ResponseHelper::error('计划不存在', 404); + } + + // 归类参数 + $msgConf = isset($params['messagePlans']) ? $params['messagePlans'] : []; + $tagConf = [ + 'scenarioTags' => $params['scenarioTags'] ?? [], + 'customTags' => $params['customTags'] ?? [], + ]; + $reqConf = [ + 'device' => $params['device'] ?? [], + 'remarkType' => $params['remarkType'] ?? '', + 'greeting' => $params['greeting'] ?? '', + 'addFriendInterval' => $params['addFriendInterval'] ?? '', + 'startTime' => $params['startTime'] ?? '', + 'endTime' => $params['endTime'] ?? '', + ]; + + // 其余参数归为sceneConf + $sceneConf = $params; + unset( + $sceneConf['planId'], + $sceneConf['name'], + $sceneConf['sceneId'], + $sceneConf['messagePlans'], + $sceneConf['scenarioTags'], + $sceneConf['customTags'], + $sceneConf['device'], + $sceneConf['remarkType'], + $sceneConf['greeting'], + $sceneConf['addFriendInterval'], + $sceneConf['startTime'], + $sceneConf['endTime'] + ); + + // 构建更新数据 + $data = [ + 'name' => $params['name'], + 'sceneId' => $params['sceneId'], + 'sceneConf' => json_encode($sceneConf, JSON_UNESCAPED_UNICODE), + 'reqConf' => json_encode($reqConf, JSON_UNESCAPED_UNICODE), + 'msgConf' => json_encode($msgConf, JSON_UNESCAPED_UNICODE), + 'tagConf' => json_encode($tagConf, JSON_UNESCAPED_UNICODE), + 'updateTime'=> time(), + ]; + + // 开启事务 + Db::startTrans(); + try { + // 更新数据 + $result = Db::name('customer_acquisition_task') + ->where('id', $params['planId']) + ->update($data); + + if ($result === false) { + throw new \Exception('更新计划失败'); + } + + // 提交事务 + Db::commit(); + + return ResponseHelper::success(['planId' => $params['planId']], '更新计划任务成功'); + + } catch (\Exception $e) { + // 回滚事务 + Db::rollback(); + throw $e; + } + + } catch (\Exception $e) { + return ResponseHelper::error('系统错误: ' . $e->getMessage(), 500); + } + } +} \ No newline at end of file