From 0baf08b95b01744a000e220dfd6dfed34acc82a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=E9=87=8C=E7=9A=84=E6=B0=B8?= =?UTF-8?q?=E5=B9=B3?= Date: Wed, 23 Jul 2025 17:54:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9C=AC=E6=AC=A1=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E5=A6=82=E4=B8=8B=20?= =?UTF-8?q?=E6=9C=8B=E5=8F=8B=E5=9C=88=E5=90=8C=E6=AD=A5=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ContentLibrarySelection/index.tsx | 2 +- .../pages/workspace/moments-sync/Detail.tsx | 96 +-- .../workspace/moments-sync/MomentsSync.tsx | 20 +- .../pages/workspace/moments-sync/new/api.ts | 27 +- .../workspace/moments-sync/new/index.tsx | 702 +++++++++--------- 5 files changed, 416 insertions(+), 431 deletions(-) diff --git a/nkebao/src/components/ContentLibrarySelection/index.tsx b/nkebao/src/components/ContentLibrarySelection/index.tsx index cd301467..7d5cb5e6 100644 --- a/nkebao/src/components/ContentLibrarySelection/index.tsx +++ b/nkebao/src/components/ContentLibrarySelection/index.tsx @@ -45,7 +45,7 @@ const formatDate = (dateStr?: string) => { // 组件属性接口 interface ContentLibrarySelectionProps { - selectedLibraries: string[]; + selectedLibraries: (string | number)[]; onSelect: (libraries: string[]) => void; onSelectDetail?: (libraries: ContentLibraryItem[]) => void; placeholder?: string; diff --git a/nkebao/src/pages/workspace/moments-sync/Detail.tsx b/nkebao/src/pages/workspace/moments-sync/Detail.tsx index 7b6f2eb8..a8456a52 100644 --- a/nkebao/src/pages/workspace/moments-sync/Detail.tsx +++ b/nkebao/src/pages/workspace/moments-sync/Detail.tsx @@ -1,13 +1,8 @@ import React, { useState, useEffect, useCallback } from "react"; import { useParams, useNavigate } from "react-router-dom"; -import { Button, Switch, message, Spin, Badge } from "antd"; -import { - ArrowLeftOutlined, - EditOutlined, - ClockCircleOutlined, - DatabaseOutlined, - MobileOutlined, -} from "@ant-design/icons"; +import { Button, Switch, message, Spin } from "antd"; +import NavCommon from "@/components/NavCommon"; +import { EditOutlined } from "@ant-design/icons"; import Layout from "@/components/Layout/Layout"; import style from "./index.module.scss"; import request from "@/api/request"; @@ -117,22 +112,19 @@ const MomentsSyncDetail: React.FC = () => { return ( - - + } + onClick={handleEdit} + className={style.editBtn} + type="primary" + > + 编辑任务 + + } + /> } >
@@ -155,29 +147,49 @@ const MomentsSyncDetail: React.FC = () => { size="small" />
-
-
- 推送设备:{task.config?.devices?.length || 0} 个 +
+
+
任务详情
+
+ 推送设备:{task.config?.devices?.length || 0} 个 +
+
+ 内容库:{task.config?.contentLibraryNames?.join(",") || "-"} +
+
+ 已同步:{task.syncCount || 0} 条 +
+
+ 创建人:{task.creatorName} +
-
- 内容库:{task.config?.contentLibraryNames?.join(",") || "-"} +
+
时间信息
+
+ 创建时间:{task.createTime} +
+
+ 上次同步:{task.lastSyncTime || "无"} +
-
-
- 已同步:{task.syncCount || 0} 条 -
-
创建人:{task.creatorName}
-
-
-
- - 上次同步:{task.lastSyncTime || "无"} -
-
创建时间:{task.createTime}
+
+
同步内容预览
+
暂无内容预览
- {/* 可继续补充更多详情卡片,如同步设置、同步记录等 */}
); diff --git a/nkebao/src/pages/workspace/moments-sync/MomentsSync.tsx b/nkebao/src/pages/workspace/moments-sync/MomentsSync.tsx index 48f2d4f7..c6f4f4df 100644 --- a/nkebao/src/pages/workspace/moments-sync/MomentsSync.tsx +++ b/nkebao/src/pages/workspace/moments-sync/MomentsSync.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { Switch, Input, message, Dropdown, Menu } from "antd"; import { NavBar, Button } from "antd-mobile"; +import NavCommon from "@/components/NavCommon"; import { PlusOutlined, SearchOutlined, @@ -149,17 +150,8 @@ const MomentsSync: React.FC = () => { - - navigate("/workspace")} - /> -
- } + { 新建任务 } - > - 朋友圈同步 - + /> +
{
} + loading={loading} >
diff --git a/nkebao/src/pages/workspace/moments-sync/new/api.ts b/nkebao/src/pages/workspace/moments-sync/new/api.ts index d162f747..1ab6006d 100644 --- a/nkebao/src/pages/workspace/moments-sync/new/api.ts +++ b/nkebao/src/pages/workspace/moments-sync/new/api.ts @@ -1,31 +1,12 @@ import request from "@/api/request"; // 创建朋友圈同步任务 -export const createMomentsSync = (params: { - name: string; - devices: string[]; - contentLibraries: string[]; - syncCount: number; - startTime: string; - endTime: string; - accountType: number; - status: number; - type: number; -}) => request("/v1/workbench/create", params, "POST"); +export const createMomentsSync = (params: any) => + request("/v1/workbench/create", params, "POST"); // 更新朋友圈同步任务 -export const updateMomentsSync = (params: { - id: string; - name: string; - devices: string[]; - contentLibraries: string[]; - syncCount: number; - startTime: string; - endTime: string; - accountType: number; - status: number; - type: number; -}) => request("/v1/workbench/update", params, "POST"); +export const updateMomentsSync = (params: any) => + request("/v1/workbench/update", params, "POST"); // 获取朋友圈同步任务详情 export const getMomentsSyncDetail = (id: string) => diff --git a/nkebao/src/pages/workspace/moments-sync/new/index.tsx b/nkebao/src/pages/workspace/moments-sync/new/index.tsx index 872e1dcf..1be6212a 100644 --- a/nkebao/src/pages/workspace/moments-sync/new/index.tsx +++ b/nkebao/src/pages/workspace/moments-sync/new/index.tsx @@ -1,351 +1,351 @@ -import React, { useState, useEffect, useCallback } from "react"; -import { useNavigate, useParams } from "react-router-dom"; -import { Button, Input, Switch, message, Spin } from "antd"; -import { MinusOutlined, PlusOutlined } from "@ant-design/icons"; - -import Layout from "@/components/Layout/Layout"; -import style from "./index.module.scss"; -import request from "@/api/request"; -import StepIndicator from "@/components/StepIndicator"; -import { - createMomentsSync, - updateMomentsSync, - getMomentsSyncDetail, -} from "./api"; -import DeviceSelection from "@/components/DeviceSelection"; -import ContentLibrarySelection from "@/components/ContentLibrarySelection"; -import NavCommon from "@/components/NavCommon"; - -const steps = [ - { id: 1, title: "基础设置", subtitle: "基础设置" }, - { id: 2, title: "设备选择", subtitle: "设备选择" }, - { id: 3, title: "内容库选择", subtitle: "内容库选择" }, -]; - -const defaultForm = { - taskName: "", - startTime: "06:00", - endTime: "23:59", - syncCount: 5, - syncInterval: 30, - syncType: 1, // 1=业务号 2=人设号 - accountType: "business" as "business" | "personal", // 仅UI用 - enabled: true, - selectedDevices: [] as string[], - selectedLibraries: [] as (string | number)[], - contentTypes: ["text", "image", "video"], - targetTags: [] as string[], - filterKeywords: [] as string[], -}; - -const NewMomentsSync: React.FC = () => { - const navigate = useNavigate(); - const { id } = useParams<{ id: string }>(); - const isEditMode = !!id; - const [currentStep, setCurrentStep] = useState(0); - const [loading, setLoading] = useState(false); - const [formData, setFormData] = useState({ ...defaultForm }); - - // 获取详情(编辑) - const fetchDetail = useCallback(async () => { - if (!id) return; - setLoading(true); - try { - const res = await getMomentsSyncDetail(id); - if (res) { - setFormData({ - taskName: res.name, - startTime: res.timeRange?.start || "06:00", - endTime: res.timeRange?.end || "23:59", - syncCount: res.config?.syncCount || res.syncCount || 5, - syncInterval: res.config?.syncInterval || res.syncInterval || 30, - syncType: res.accountType === 1 ? 1 : 2, - accountType: res.accountType === 1 ? "business" : "personal", - enabled: res.status === 1, - selectedDevices: res.config?.devices || [], - selectedLibraries: res.config?.contentLibraryNames || [], - contentTypes: res.config?.contentTypes || ["text", "image", "video"], - targetTags: res.config?.targetTags || [], - filterKeywords: res.config?.filterKeywords || [], - }); - } - } catch { - message.error("获取详情失败"); - } finally { - setLoading(false); - } - }, [id]); - - useEffect(() => { - if (isEditMode) fetchDetail(); - }, [isEditMode, fetchDetail]); - - // 步骤切换 - const next = () => setCurrentStep((s) => Math.min(s + 1, steps.length - 1)); - const prev = () => setCurrentStep((s) => Math.max(s - 1, 0)); - - // 表单数据更新 - const updateForm = (data: Partial) => { - setFormData((prev) => ({ ...prev, ...data })); - }; - - // UI选择账号类型时同步syncType和accountType - const handleAccountTypeChange = (type: "business" | "personal") => { - setFormData((prev) => ({ - ...prev, - accountType: type, - syncType: type === "business" ? 1 : 2, - })); - }; - - // 提交 - const handleSubmit = async () => { - if (!formData.taskName.trim()) { - message.error("请输入任务名称"); - return; - } - if (formData.selectedDevices.length === 0) { - message.error("请选择设备"); - return; - } - if (formData.selectedLibraries.length === 0) { - message.error("请选择内容库"); - return; - } - setLoading(true); - try { - const params = { - name: formData.taskName, - devices: formData.selectedDevices, - contentLibraries: formData.selectedLibraries.map(Number), - syncInterval: formData.syncInterval, - syncCount: formData.syncCount, - syncType: formData.syncType, // 账号类型真实传参 - accountType: formData.accountType === "business" ? 1 : 2, // 也要传 - startTime: formData.startTime, - endTime: formData.endTime, - contentTypes: formData.contentTypes, - targetTags: formData.targetTags, - filterKeywords: formData.filterKeywords, - type: 2, - status: formData.enabled ? 1 : 2, - }; - if (isEditMode && id) { - await updateMomentsSync({ id, ...params }); - message.success("更新成功"); - navigate(`/workspace/moments-sync/${id}`); - } else { - await createMomentsSync(params); - message.success("创建成功"); - navigate("/workspace/moments-sync"); - } - } catch { - message.error(isEditMode ? "更新失败" : "创建失败"); - } finally { - setLoading(false); - } - }; - - // 步骤内容(去除按钮) - const renderStep = () => { - if (currentStep === 0) { - return ( -
-
-
任务名称
- updateForm({ taskName: e.target.value })} - placeholder="请输入任务名称" - maxLength={30} - className={style.input} - /> -
- -
-
允许发布时间段
-
- updateForm({ startTime: e.target.value })} - className={style.inputTime} - /> - - updateForm({ endTime: e.target.value })} - className={style.inputTime} - /> -
-
- -
-
每日同步数量
-
- - {formData.syncCount} - - 条朋友圈 -
-
- -
-
账号类型
-
- - -
-
- -
-
- 是否启用 - updateForm({ enabled: checked })} - className={style.switch} - /> -
-
-
- ); - } - if (currentStep === 1) { - return ( -
-
-
选择设备
- updateForm({ selectedDevices: devices })} - placeholder="请选择设备" - showSelectedList={true} - selectedListMaxHeight={200} - /> -
-
- ); - } - if (currentStep === 2) { - return ( -
-
-
选择内容库
- updateForm({ selectedLibraries: libs })} - placeholder="请选择内容库" - showSelectedList={true} - selectedListMaxHeight={200} - /> - {formData.selectedLibraries.length > 0 && ( -
- 已选内容库: {formData.selectedLibraries.length}个 -
- )} -
-
- ); - } - return null; - }; - - // 统一底部按钮 - const renderFooter = () => { - if (loading) return null; - if (currentStep === 0) { - return ( -
- -
- ); - } - if (currentStep === 1) { - return ( -
- - -
- ); - } - if (currentStep === 2) { - return ( -
- - -
- ); - } - return null; - }; - - return ( - - } - footer={renderFooter()} - > -
- - {loading ? ( -
- -
- ) : ( - renderStep() - )} -
-
- ); -}; - -export default NewMomentsSync; +import React, { useState, useEffect, useCallback } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { Button, Input, Switch, message, Spin } from "antd"; +import { MinusOutlined, PlusOutlined } from "@ant-design/icons"; + +import Layout from "@/components/Layout/Layout"; +import style from "./index.module.scss"; +import request from "@/api/request"; +import StepIndicator from "@/components/StepIndicator"; +import { + createMomentsSync, + updateMomentsSync, + getMomentsSyncDetail, +} from "./api"; +import DeviceSelection from "@/components/DeviceSelection"; +import ContentLibrarySelection from "@/components/ContentLibrarySelection"; +import NavCommon from "@/components/NavCommon"; + +const steps = [ + { id: 1, title: "基础设置", subtitle: "基础设置" }, + { id: 2, title: "设备选择", subtitle: "设备选择" }, + { id: 3, title: "内容库选择", subtitle: "内容库选择" }, +]; + +const defaultForm = { + taskName: "", + startTime: "06:00", + endTime: "23:59", + syncCount: 5, + syncInterval: 30, + syncType: 1, // 1=业务号 2=人设号 + accountType: "business" as "business" | "personal", // 仅UI用 + enabled: true, + selectedDevices: [] as string[], + selectedLibraries: [] as (string | number)[], + contentTypes: ["text", "image", "video"], + targetTags: [] as string[], + filterKeywords: [] as string[], +}; + +const NewMomentsSync: React.FC = () => { + const navigate = useNavigate(); + const { id } = useParams<{ id: string }>(); + const isEditMode = !!id; + const [currentStep, setCurrentStep] = useState(0); + const [loading, setLoading] = useState(false); + const [formData, setFormData] = useState({ ...defaultForm }); + + // 获取详情(编辑) + const fetchDetail = useCallback(async () => { + if (!id) return; + setLoading(true); + try { + const res = await getMomentsSyncDetail(id); + if (res) { + setFormData({ + taskName: res.name, + startTime: res.timeRange?.start || "06:00", + endTime: res.timeRange?.end || "23:59", + syncCount: res.config?.syncCount || res.syncCount || 5, + syncInterval: res.config?.syncInterval || res.syncInterval || 30, + syncType: res.accountType === 1 ? 1 : 2, + accountType: res.accountType === 1 ? "business" : "personal", + enabled: res.status === 1, + selectedDevices: res.config?.devices || [], + selectedLibraries: res.config?.contentLibraryNames || [], + contentTypes: res.config?.contentTypes || ["text", "image", "video"], + targetTags: res.config?.targetTags || [], + filterKeywords: res.config?.filterKeywords || [], + }); + } + } catch { + message.error("获取详情失败"); + } finally { + setLoading(false); + } + }, [id]); + + useEffect(() => { + if (isEditMode) fetchDetail(); + }, [isEditMode, fetchDetail]); + + // 步骤切换 + const next = () => setCurrentStep((s) => Math.min(s + 1, steps.length - 1)); + const prev = () => setCurrentStep((s) => Math.max(s - 1, 0)); + + // 表单数据更新 + const updateForm = (data: Partial) => { + setFormData((prev) => ({ ...prev, ...data })); + }; + + // UI选择账号类型时同步syncType和accountType + const handleAccountTypeChange = (type: "business" | "personal") => { + setFormData((prev) => ({ + ...prev, + accountType: type, + syncType: type === "business" ? 1 : 2, + })); + }; + + // 提交 + const handleSubmit = async () => { + if (!formData.taskName.trim()) { + message.error("请输入任务名称"); + return; + } + if (formData.selectedDevices.length === 0) { + message.error("请选择设备"); + return; + } + if (formData.selectedLibraries.length === 0) { + message.error("请选择内容库"); + return; + } + setLoading(true); + try { + const params = { + name: formData.taskName, + devices: formData.selectedDevices, + contentLibraries: formData.selectedLibraries.map(Number), + syncInterval: formData.syncInterval, + syncCount: formData.syncCount, + syncType: formData.syncType, // 账号类型真实传参 + accountType: formData.accountType === "business" ? 1 : 2, // 也要传 + startTime: formData.startTime, + endTime: formData.endTime, + contentTypes: formData.contentTypes, + targetTags: formData.targetTags, + filterKeywords: formData.filterKeywords, + type: 2, + status: formData.enabled ? 1 : 2, + }; + if (isEditMode && id) { + await updateMomentsSync({ id, ...params }); + message.success("更新成功"); + navigate(`/workspace/moments-sync/${id}`); + } else { + await createMomentsSync(params); + message.success("创建成功"); + navigate("/workspace/moments-sync"); + } + } catch { + message.error(isEditMode ? "更新失败" : "创建失败"); + } finally { + setLoading(false); + } + }; + + // 步骤内容(去除按钮) + const renderStep = () => { + if (currentStep === 0) { + return ( +
+
+
任务名称
+ updateForm({ taskName: e.target.value })} + placeholder="请输入任务名称" + maxLength={30} + className={style.input} + /> +
+ +
+
允许发布时间段
+
+ updateForm({ startTime: e.target.value })} + className={style.inputTime} + /> + + updateForm({ endTime: e.target.value })} + className={style.inputTime} + /> +
+
+ +
+
每日同步数量
+
+ + {formData.syncCount} + + 条朋友圈 +
+
+ +
+
账号类型
+
+ + +
+
+ +
+
+ 是否启用 + updateForm({ enabled: checked })} + className={style.switch} + /> +
+
+
+ ); + } + if (currentStep === 1) { + return ( +
+
+
选择设备
+ updateForm({ selectedDevices: devices })} + placeholder="请选择设备" + showSelectedList={true} + selectedListMaxHeight={200} + /> +
+
+ ); + } + if (currentStep === 2) { + return ( +
+
+
选择内容库
+ updateForm({ selectedLibraries: libs })} + placeholder="请选择内容库" + showSelectedList={true} + selectedListMaxHeight={200} + /> + {formData.selectedLibraries.length > 0 && ( +
+ 已选内容库: {formData.selectedLibraries.length}个 +
+ )} +
+
+ ); + } + return null; + }; + + // 统一底部按钮 + const renderFooter = () => { + if (loading) return null; + if (currentStep === 0) { + return ( +
+ +
+ ); + } + if (currentStep === 1) { + return ( +
+ + +
+ ); + } + if (currentStep === 2) { + return ( +
+ + +
+ ); + } + return null; + }; + + return ( + + } + footer={renderFooter()} + > +
+ + {loading ? ( +
+ +
+ ) : ( + renderStep() + )} +
+
+ ); +}; + +export default NewMomentsSync;