feat: 本次提交更新内容如下
朋友圈同步完成
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 (
|
||||
<Layout
|
||||
header={
|
||||
<div className={style.headerBar}>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<ArrowLeftOutlined />}
|
||||
onClick={() => navigate("/workspace/moments-sync")}
|
||||
className={style.backBtn}
|
||||
/>
|
||||
<span className={style.title}>任务详情</span>
|
||||
<Button
|
||||
icon={<EditOutlined />}
|
||||
onClick={handleEdit}
|
||||
className={style.editBtn}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
</div>
|
||||
<NavCommon
|
||||
title="查看朋友圈同步任务"
|
||||
right={
|
||||
<Button
|
||||
icon={<EditOutlined />}
|
||||
onClick={handleEdit}
|
||||
className={style.editBtn}
|
||||
type="primary"
|
||||
>
|
||||
编辑任务
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className={style.detailBg}>
|
||||
@@ -155,29 +147,49 @@ const MomentsSyncDetail: React.FC = () => {
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div className={style.detailInfoRow}>
|
||||
<div className={style.infoCol}>
|
||||
推送设备:{task.config?.devices?.length || 0} 个
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
marginTop: 16,
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div style={{ fontWeight: 500, marginBottom: 8 }}>任务详情</div>
|
||||
<div style={{ fontSize: 14, color: "#222", marginBottom: 4 }}>
|
||||
推送设备:{task.config?.devices?.length || 0} 个
|
||||
</div>
|
||||
<div style={{ fontSize: 14, color: "#222", marginBottom: 4 }}>
|
||||
内容库:{task.config?.contentLibraryNames?.join(",") || "-"}
|
||||
</div>
|
||||
<div style={{ fontSize: 14, color: "#222", marginBottom: 4 }}>
|
||||
已同步:{task.syncCount || 0} 条
|
||||
</div>
|
||||
<div style={{ fontSize: 14, color: "#222" }}>
|
||||
创建人:{task.creatorName}
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.infoCol}>
|
||||
内容库:{task.config?.contentLibraryNames?.join(",") || "-"}
|
||||
<div>
|
||||
<div style={{ fontWeight: 500, marginBottom: 8 }}>时间信息</div>
|
||||
<div style={{ fontSize: 14, color: "#222", marginBottom: 4 }}>
|
||||
创建时间:{task.createTime}
|
||||
</div>
|
||||
<div style={{ fontSize: 14, color: "#222" }}>
|
||||
上次同步:{task.lastSyncTime || "无"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.detailInfoRow}>
|
||||
<div className={style.infoCol}>
|
||||
已同步:{task.syncCount || 0} 条
|
||||
</div>
|
||||
<div className={style.infoCol}>创建人:{task.creatorName}</div>
|
||||
</div>
|
||||
<div className={style.detailBottom}>
|
||||
<div className={style.bottomLeft}>
|
||||
<ClockCircleOutlined className={style.clockIcon} />
|
||||
上次同步:{task.lastSyncTime || "无"}
|
||||
</div>
|
||||
<div className={style.bottomRight}>创建时间:{task.createTime}</div>
|
||||
<div
|
||||
style={{
|
||||
borderTop: "1px solid #f0f0f0",
|
||||
margin: "16px 0 0 0",
|
||||
paddingTop: 12,
|
||||
}}
|
||||
>
|
||||
<div style={{ fontWeight: 500, marginBottom: 8 }}>同步内容预览</div>
|
||||
<div style={{ color: "#888", fontSize: 14 }}>暂无内容预览</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 可继续补充更多详情卡片,如同步设置、同步记录等 */}
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
@@ -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 = () => {
|
||||
<Layout
|
||||
header={
|
||||
<>
|
||||
<NavBar
|
||||
back={null}
|
||||
style={{ background: "#fff" }}
|
||||
left={
|
||||
<div className="nav-title">
|
||||
<ArrowLeftOutlined
|
||||
twoToneColor="#1677ff"
|
||||
onClick={() => navigate("/workspace")}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<NavCommon
|
||||
title="朋友圈同步"
|
||||
right={
|
||||
<Button
|
||||
size="small"
|
||||
@@ -169,9 +161,8 @@ const MomentsSync: React.FC = () => {
|
||||
<PlusOutlined /> 新建任务
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<span className="nav-title">朋友圈同步</span>
|
||||
</NavBar>
|
||||
/>
|
||||
|
||||
<div className="search-bar">
|
||||
<div className="search-input-wrapper">
|
||||
<Input
|
||||
@@ -194,6 +185,7 @@ const MomentsSync: React.FC = () => {
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
loading={loading}
|
||||
>
|
||||
<div className={style.pageBg}>
|
||||
<div className={style.taskList}>
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
@@ -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<typeof formData>) => {
|
||||
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 (
|
||||
<div className={style.formStep}>
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>任务名称</div>
|
||||
<Input
|
||||
value={formData.taskName}
|
||||
onChange={(e) => updateForm({ taskName: e.target.value })}
|
||||
placeholder="请输入任务名称"
|
||||
maxLength={30}
|
||||
className={style.input}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>允许发布时间段</div>
|
||||
<div className={style.timeRow}>
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.startTime}
|
||||
onChange={(e) => updateForm({ startTime: e.target.value })}
|
||||
className={style.inputTime}
|
||||
/>
|
||||
<span className={style.timeTo}>至</span>
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.endTime}
|
||||
onChange={(e) => updateForm({ endTime: e.target.value })}
|
||||
className={style.inputTime}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>每日同步数量</div>
|
||||
<div className={style.counterRow}>
|
||||
<button
|
||||
className={style.counterBtn}
|
||||
onClick={() =>
|
||||
updateForm({ syncCount: Math.max(1, formData.syncCount - 1) })
|
||||
}
|
||||
>
|
||||
<MinusOutlined />
|
||||
</button>
|
||||
<span className={style.counterValue}>{formData.syncCount}</span>
|
||||
<button
|
||||
className={style.counterBtn}
|
||||
onClick={() =>
|
||||
updateForm({ syncCount: formData.syncCount + 1 })
|
||||
}
|
||||
>
|
||||
<PlusOutlined />
|
||||
</button>
|
||||
<span className={style.counterUnit}>条朋友圈</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>账号类型</div>
|
||||
<div className={style.accountTypeRow}>
|
||||
<button
|
||||
className={`${style.accountTypeBtn} ${formData.accountType === "business" ? style.accountTypeActive : ""}`}
|
||||
onClick={() => handleAccountTypeChange("business")}
|
||||
>
|
||||
业务号
|
||||
</button>
|
||||
<button
|
||||
className={`${style.accountTypeBtn} ${formData.accountType === "personal" ? style.accountTypeActive : ""}`}
|
||||
onClick={() => handleAccountTypeChange("personal")}
|
||||
>
|
||||
人设号
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.formItem}>
|
||||
<div className={style.switchRow}>
|
||||
<span className={style.switchLabel}>是否启用</span>
|
||||
<Switch
|
||||
checked={formData.enabled}
|
||||
onChange={(checked) => updateForm({ enabled: checked })}
|
||||
className={style.switch}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (currentStep === 1) {
|
||||
return (
|
||||
<div className={style.formStep}>
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>选择设备</div>
|
||||
<DeviceSelection
|
||||
selectedDevices={formData.selectedDevices}
|
||||
onSelect={(devices) => updateForm({ selectedDevices: devices })}
|
||||
placeholder="请选择设备"
|
||||
showSelectedList={true}
|
||||
selectedListMaxHeight={200}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (currentStep === 2) {
|
||||
return (
|
||||
<div className={style.formStep}>
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>选择内容库</div>
|
||||
<ContentLibrarySelection
|
||||
selectedLibraries={formData.selectedLibraries}
|
||||
onSelect={(libs) => updateForm({ selectedLibraries: libs })}
|
||||
placeholder="请选择内容库"
|
||||
showSelectedList={true}
|
||||
selectedListMaxHeight={200}
|
||||
/>
|
||||
{formData.selectedLibraries.length > 0 && (
|
||||
<div className={style.selectedTip}>
|
||||
已选内容库: {formData.selectedLibraries.length}个
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// 统一底部按钮
|
||||
const renderFooter = () => {
|
||||
if (loading) return null;
|
||||
if (currentStep === 0) {
|
||||
return (
|
||||
<div className={style.formStepBtnRow}>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={!formData.taskName.trim()}
|
||||
onClick={next}
|
||||
className={style.nextBtn}
|
||||
block
|
||||
>
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (currentStep === 1) {
|
||||
return (
|
||||
<div className={style.formStepBtnRow}>
|
||||
<Button onClick={prev} className={style.prevBtn} block>
|
||||
上一步
|
||||
</Button>
|
||||
<Button type="primary" onClick={next} className={style.nextBtn} block>
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (currentStep === 2) {
|
||||
return (
|
||||
<div className={style.formStepBtnRow}>
|
||||
<Button onClick={prev} className={style.prevBtn} block>
|
||||
上一步
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSubmit}
|
||||
loading={loading}
|
||||
className={style.completeBtn}
|
||||
block
|
||||
>
|
||||
完成
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout
|
||||
header={
|
||||
<NavCommon title={isEditMode ? "编辑朋友圈同步" : "新建朋友圈同步"} />
|
||||
}
|
||||
footer={renderFooter()}
|
||||
>
|
||||
<div className={style.formBg}>
|
||||
<StepIndicator currentStep={currentStep + 1} steps={steps} />
|
||||
{loading ? (
|
||||
<div className={style.formLoading}>
|
||||
<Spin />
|
||||
</div>
|
||||
) : (
|
||||
renderStep()
|
||||
)}
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
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<typeof formData>) => {
|
||||
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 (
|
||||
<div className={style.formStep}>
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>任务名称</div>
|
||||
<Input
|
||||
value={formData.taskName}
|
||||
onChange={(e) => updateForm({ taskName: e.target.value })}
|
||||
placeholder="请输入任务名称"
|
||||
maxLength={30}
|
||||
className={style.input}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>允许发布时间段</div>
|
||||
<div className={style.timeRow}>
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.startTime}
|
||||
onChange={(e) => updateForm({ startTime: e.target.value })}
|
||||
className={style.inputTime}
|
||||
/>
|
||||
<span className={style.timeTo}>至</span>
|
||||
<Input
|
||||
type="time"
|
||||
value={formData.endTime}
|
||||
onChange={(e) => updateForm({ endTime: e.target.value })}
|
||||
className={style.inputTime}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>每日同步数量</div>
|
||||
<div className={style.counterRow}>
|
||||
<button
|
||||
className={style.counterBtn}
|
||||
onClick={() =>
|
||||
updateForm({ syncCount: Math.max(1, formData.syncCount - 1) })
|
||||
}
|
||||
>
|
||||
<MinusOutlined />
|
||||
</button>
|
||||
<span className={style.counterValue}>{formData.syncCount}</span>
|
||||
<button
|
||||
className={style.counterBtn}
|
||||
onClick={() =>
|
||||
updateForm({ syncCount: formData.syncCount + 1 })
|
||||
}
|
||||
>
|
||||
<PlusOutlined />
|
||||
</button>
|
||||
<span className={style.counterUnit}>条朋友圈</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>账号类型</div>
|
||||
<div className={style.accountTypeRow}>
|
||||
<button
|
||||
className={`${style.accountTypeBtn} ${formData.accountType === "business" ? style.accountTypeActive : ""}`}
|
||||
onClick={() => handleAccountTypeChange("business")}
|
||||
>
|
||||
业务号
|
||||
</button>
|
||||
<button
|
||||
className={`${style.accountTypeBtn} ${formData.accountType === "personal" ? style.accountTypeActive : ""}`}
|
||||
onClick={() => handleAccountTypeChange("personal")}
|
||||
>
|
||||
人设号
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.formItem}>
|
||||
<div className={style.switchRow}>
|
||||
<span className={style.switchLabel}>是否启用</span>
|
||||
<Switch
|
||||
checked={formData.enabled}
|
||||
onChange={(checked) => updateForm({ enabled: checked })}
|
||||
className={style.switch}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (currentStep === 1) {
|
||||
return (
|
||||
<div className={style.formStep}>
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>选择设备</div>
|
||||
<DeviceSelection
|
||||
selectedDevices={formData.selectedDevices}
|
||||
onSelect={(devices) => updateForm({ selectedDevices: devices })}
|
||||
placeholder="请选择设备"
|
||||
showSelectedList={true}
|
||||
selectedListMaxHeight={200}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (currentStep === 2) {
|
||||
return (
|
||||
<div className={style.formStep}>
|
||||
<div className={style.formItem}>
|
||||
<div className={style.formLabel}>选择内容库</div>
|
||||
<ContentLibrarySelection
|
||||
selectedLibraries={formData.selectedLibraries}
|
||||
onSelect={(libs) => updateForm({ selectedLibraries: libs })}
|
||||
placeholder="请选择内容库"
|
||||
showSelectedList={true}
|
||||
selectedListMaxHeight={200}
|
||||
/>
|
||||
{formData.selectedLibraries.length > 0 && (
|
||||
<div className={style.selectedTip}>
|
||||
已选内容库: {formData.selectedLibraries.length}个
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// 统一底部按钮
|
||||
const renderFooter = () => {
|
||||
if (loading) return null;
|
||||
if (currentStep === 0) {
|
||||
return (
|
||||
<div className={style.formStepBtnRow}>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={!formData.taskName.trim()}
|
||||
onClick={next}
|
||||
className={style.nextBtn}
|
||||
block
|
||||
>
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (currentStep === 1) {
|
||||
return (
|
||||
<div className={style.formStepBtnRow}>
|
||||
<Button onClick={prev} className={style.prevBtn} block>
|
||||
上一步
|
||||
</Button>
|
||||
<Button type="primary" onClick={next} className={style.nextBtn} block>
|
||||
下一步
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (currentStep === 2) {
|
||||
return (
|
||||
<div className={style.formStepBtnRow}>
|
||||
<Button onClick={prev} className={style.prevBtn} block>
|
||||
上一步
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSubmit}
|
||||
loading={loading}
|
||||
className={style.completeBtn}
|
||||
block
|
||||
>
|
||||
完成
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout
|
||||
header={
|
||||
<NavCommon title={isEditMode ? "编辑朋友圈同步" : "新建朋友圈同步"} />
|
||||
}
|
||||
footer={renderFooter()}
|
||||
>
|
||||
<div className={style.formBg}>
|
||||
<StepIndicator currentStep={currentStep + 1} steps={steps} />
|
||||
{loading ? (
|
||||
<div className={style.formLoading}>
|
||||
<Spin />
|
||||
</div>
|
||||
) : (
|
||||
renderStep()
|
||||
)}
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default NewMomentsSync;
|
||||
|
||||
Reference in New Issue
Block a user