feat: 本次提交更新内容如下
先存一版作为模板,然后开发其他的
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import request from "@/api/request";
|
||||
// 获取场景类型列表
|
||||
export function getScenarioTypes() {
|
||||
return request("/v1/scenarios/types", undefined, "GET");
|
||||
return request("/v1/plan/scenes", undefined, "GET");
|
||||
}
|
||||
|
||||
// 创建计划
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { LeftOutlined } from "@ant-design/icons";
|
||||
import { Button, Steps, message } from "antd";
|
||||
import { message } from "antd";
|
||||
import { NavBar } from "antd-mobile";
|
||||
import { ArrowLeftOutlined } from "@ant-design/icons";
|
||||
import BasicSettings from "./steps/BasicSettings";
|
||||
import FriendRequestSettings from "./steps/FriendRequestSettings";
|
||||
import MessageSettings from "./steps/MessageSettings";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import StepIndicator from "@/components/StepIndicator";
|
||||
import {
|
||||
getPlanScenes,
|
||||
createScenarioPlan,
|
||||
fetchPlanDetail,
|
||||
PlanDetail,
|
||||
updateScenarioPlan,
|
||||
getScenarioTypes,
|
||||
createPlan,
|
||||
getPlanDetail,
|
||||
updatePlan,
|
||||
} from "./index.api";
|
||||
|
||||
// 步骤定义 - 只保留三个步骤
|
||||
@@ -70,7 +71,7 @@ export default function NewPlan() {
|
||||
const loadData = async () => {
|
||||
setSceneLoading(true);
|
||||
//获取场景类型
|
||||
getPlanScenes()
|
||||
getScenarioTypes()
|
||||
.then((data) => {
|
||||
setSceneList(data || []);
|
||||
})
|
||||
@@ -81,28 +82,25 @@ export default function NewPlan() {
|
||||
if (planId) {
|
||||
setIsEdit(true);
|
||||
//获取计划详情
|
||||
try {
|
||||
const detail = await fetchPlanDetail(planId);
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
name: detail.name ?? "",
|
||||
scenario: Number(detail.scenario) || 1,
|
||||
posters: detail.posters ?? [],
|
||||
device: detail.device ?? [],
|
||||
remarkType: detail.remarkType ?? "phone",
|
||||
greeting: detail.greeting ?? "",
|
||||
addInterval: detail.addInterval ?? 1,
|
||||
startTime: detail.startTime ?? "09:00",
|
||||
endTime: detail.endTime ?? "18:00",
|
||||
enabled: detail.enabled ?? true,
|
||||
sceneId: Number(detail.scenario) || 1,
|
||||
remarkFormat: detail.remarkFormat ?? "",
|
||||
addFriendInterval: detail.addFriendInterval ?? 1,
|
||||
tips: detail.tips ?? "",
|
||||
}));
|
||||
} catch (err) {
|
||||
message.error(err.message || "获取计划详情失败");
|
||||
}
|
||||
|
||||
const detail = await getPlanDetail(planId);
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
name: detail.name ?? "",
|
||||
scenario: Number(detail.scenario) || 1,
|
||||
posters: detail.posters ?? [],
|
||||
device: detail.device ?? [],
|
||||
remarkType: detail.remarkType ?? "phone",
|
||||
greeting: detail.greeting ?? "",
|
||||
addInterval: detail.addInterval ?? 1,
|
||||
startTime: detail.startTime ?? "09:00",
|
||||
endTime: detail.endTime ?? "18:00",
|
||||
enabled: detail.enabled ?? true,
|
||||
sceneId: Number(detail.scenario) || 1,
|
||||
remarkFormat: detail.remarkFormat ?? "",
|
||||
addFriendInterval: detail.addFriendInterval ?? 1,
|
||||
tips: detail.tips ?? "",
|
||||
}));
|
||||
} else {
|
||||
if (scenarioId) {
|
||||
setFormData((prev) => ({
|
||||
@@ -131,10 +129,10 @@ export default function NewPlan() {
|
||||
// 兼容后端需要的字段
|
||||
// 你可以根据实际需要补充其它字段
|
||||
};
|
||||
result = await updateScenarioPlan(planId, editData);
|
||||
result = await updatePlan(planId, editData);
|
||||
} else {
|
||||
// 新建
|
||||
result = await createScenarioPlan(formData);
|
||||
result = await createPlan(formData);
|
||||
}
|
||||
message.success(isEdit ? "计划已更新" : "获客计划已创建");
|
||||
const sceneItem = sceneList.find((v) => formData.scenario === v.id);
|
||||
@@ -207,33 +205,29 @@ export default function NewPlan() {
|
||||
<Layout
|
||||
header={
|
||||
<>
|
||||
<header className="sticky top-0 z-10 bg-white border-b">
|
||||
<div className="flex items-center justify-between h-14 px-4">
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
type="text"
|
||||
shape="circle"
|
||||
icon={<LeftOutlined />}
|
||||
<NavBar
|
||||
back={null}
|
||||
style={{ background: "#fff" }}
|
||||
left={
|
||||
<div className="nav-title">
|
||||
<ArrowLeftOutlined
|
||||
twoToneColor="#1677ff"
|
||||
onClick={() => router(-1)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
>
|
||||
<span className="nav-title">
|
||||
{isEdit ? "编辑朋友圈同步" : "新建朋友圈同步"}
|
||||
</span>
|
||||
</NavBar>
|
||||
<div className="px-4 py-6">
|
||||
<Steps current={currentStep - 1}>
|
||||
{steps.map((step, idx) => (
|
||||
<Steps.Step
|
||||
key={step.id}
|
||||
title={step.title}
|
||||
description={step.subtitle}
|
||||
/>
|
||||
))}
|
||||
</Steps>
|
||||
<StepIndicator currentStep={currentStep} steps={steps} />
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<div className="p-4">{renderStepContent()}</div>
|
||||
{renderStepContent()}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,199 +1,199 @@
|
||||
import React, { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button } from "antd-mobile";
|
||||
import { NavBar } from "antd-mobile";
|
||||
import { ArrowLeftOutlined } from "@ant-design/icons";
|
||||
import { createGroupPushTask } from "@/pages/workspace/group-push/detail/groupPush";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import StepIndicator from "./components/StepIndicator";
|
||||
import BasicSettings from "./components/BasicSettings";
|
||||
import GroupSelector from "./components/GroupSelector";
|
||||
import ContentSelector from "./components/ContentSelector";
|
||||
import type { WechatGroup, ContentLibrary, FormData } from "./index.data";
|
||||
|
||||
const steps = [
|
||||
{ id: 1, title: "步骤 1", subtitle: "基础设置" },
|
||||
{ id: 2, title: "步骤 2", subtitle: "选择社群" },
|
||||
{ id: 3, title: "步骤 3", subtitle: "选择内容库" },
|
||||
{ id: 4, title: "步骤 4", subtitle: "京东联盟" },
|
||||
];
|
||||
|
||||
const NewGroupPush: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const [currentStep, setCurrentStep] = useState(1);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [formData, setFormData] = useState<FormData>({
|
||||
name: "",
|
||||
pushTimeStart: "06:00",
|
||||
pushTimeEnd: "23:59",
|
||||
dailyPushCount: 20,
|
||||
pushOrder: "latest",
|
||||
isLoopPush: false,
|
||||
isImmediatePush: false,
|
||||
isEnabled: false,
|
||||
groups: [],
|
||||
contentLibraries: [],
|
||||
});
|
||||
const [isEditMode, setIsEditMode] = useState(false);
|
||||
|
||||
const handleBasicSettingsNext = (values: Partial<FormData>) => {
|
||||
setFormData((prev) => ({ ...prev, ...values }));
|
||||
setCurrentStep(2);
|
||||
};
|
||||
|
||||
const handleGroupsChange = (groups: WechatGroup[]) => {
|
||||
setFormData((prev) => ({ ...prev, groups }));
|
||||
};
|
||||
|
||||
const handleLibrariesChange = (contentLibraries: ContentLibrary[]) => {
|
||||
setFormData((prev) => ({ ...prev, contentLibraries }));
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!formData.name.trim()) {
|
||||
window.alert("请输入任务名称");
|
||||
return;
|
||||
}
|
||||
if (formData.groups.length === 0) {
|
||||
window.alert("请选择至少一个社群");
|
||||
return;
|
||||
}
|
||||
if (formData.contentLibraries.length === 0) {
|
||||
window.alert("请选择至少一个内容库");
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
try {
|
||||
const apiData = {
|
||||
name: formData.name,
|
||||
timeRange: {
|
||||
start: formData.pushTimeStart,
|
||||
end: formData.pushTimeEnd,
|
||||
},
|
||||
maxPushPerDay: formData.dailyPushCount,
|
||||
pushOrder: formData.pushOrder,
|
||||
isLoopPush: formData.isLoopPush,
|
||||
isImmediatePush: formData.isImmediatePush,
|
||||
isEnabled: formData.isEnabled,
|
||||
targetGroups: formData.groups.map((g) => g.name),
|
||||
contentLibraries: formData.contentLibraries.map((c) => c.name),
|
||||
pushMode: formData.isImmediatePush
|
||||
? ("immediate" as const)
|
||||
: ("scheduled" as const),
|
||||
messageType: "text" as const,
|
||||
messageContent: "",
|
||||
targetTags: [],
|
||||
pushInterval: 60,
|
||||
};
|
||||
const response = await createGroupPushTask(apiData);
|
||||
if (response.code === 200) {
|
||||
window.alert("保存成功");
|
||||
navigate("/workspace/group-push");
|
||||
} else {
|
||||
window.alert("保存失败,请稍后重试");
|
||||
}
|
||||
} catch (error) {
|
||||
window.alert("保存失败,请稍后重试");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
navigate("/workspace/group-push");
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout
|
||||
header={
|
||||
<NavBar
|
||||
back={null}
|
||||
style={{ background: "#fff" }}
|
||||
left={
|
||||
<div className="nav-title">
|
||||
<ArrowLeftOutlined
|
||||
twoToneColor="#1677ff"
|
||||
onClick={() => navigate(-1)}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<span className="nav-title">
|
||||
{isEditMode ? "编辑任务" : "新建任务"}
|
||||
</span>
|
||||
</NavBar>
|
||||
}
|
||||
>
|
||||
<div style={{ maxWidth: 600, margin: "0 auto", padding: 16 }}>
|
||||
<StepIndicator currentStep={currentStep} steps={steps} />
|
||||
<div style={{ marginTop: 32 }}>
|
||||
{currentStep === 1 && (
|
||||
<BasicSettings
|
||||
defaultValues={{
|
||||
name: formData.name,
|
||||
pushTimeStart: formData.pushTimeStart,
|
||||
pushTimeEnd: formData.pushTimeEnd,
|
||||
dailyPushCount: formData.dailyPushCount,
|
||||
pushOrder: formData.pushOrder,
|
||||
isLoopPush: formData.isLoopPush,
|
||||
isImmediatePush: formData.isImmediatePush,
|
||||
isEnabled: formData.isEnabled,
|
||||
}}
|
||||
onNext={handleBasicSettingsNext}
|
||||
onSave={handleSave}
|
||||
onCancel={handleCancel}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 2 && (
|
||||
<GroupSelector
|
||||
selectedGroups={formData.groups}
|
||||
onGroupsChange={handleGroupsChange}
|
||||
onPrevious={() => setCurrentStep(1)}
|
||||
onNext={() => setCurrentStep(3)}
|
||||
onSave={handleSave}
|
||||
onCancel={handleCancel}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 3 && (
|
||||
<ContentSelector
|
||||
selectedLibraries={formData.contentLibraries}
|
||||
onLibrariesChange={handleLibrariesChange}
|
||||
onPrevious={() => setCurrentStep(2)}
|
||||
onNext={() => setCurrentStep(4)}
|
||||
onSave={handleSave}
|
||||
onCancel={handleCancel}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 4 && (
|
||||
<div style={{ padding: 32, textAlign: "center", color: "#888" }}>
|
||||
京东联盟设置(此步骤为占位,实际功能待开发)
|
||||
<div
|
||||
style={{
|
||||
marginTop: 24,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
<Button onClick={() => setCurrentStep(3)} disabled={loading}>
|
||||
上一步
|
||||
</Button>
|
||||
<Button color="primary" onClick={handleSave} loading={loading}>
|
||||
完成
|
||||
</Button>
|
||||
<Button onClick={handleCancel} disabled={loading}>
|
||||
取消
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default NewGroupPush;
|
||||
import React, { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button } from "antd-mobile";
|
||||
import { NavBar } from "antd-mobile";
|
||||
import { ArrowLeftOutlined } from "@ant-design/icons";
|
||||
import { createGroupPushTask } from "@/pages/workspace/group-push/detail/groupPush";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import StepIndicator from "@/components/StepIndicator";
|
||||
import BasicSettings from "./components/BasicSettings";
|
||||
import GroupSelector from "./components/GroupSelector";
|
||||
import ContentSelector from "./components/ContentSelector";
|
||||
import type { WechatGroup, ContentLibrary, FormData } from "./index.data";
|
||||
|
||||
const steps = [
|
||||
{ id: 1, title: "步骤 1", subtitle: "基础设置" },
|
||||
{ id: 2, title: "步骤 2", subtitle: "选择社群" },
|
||||
{ id: 3, title: "步骤 3", subtitle: "选择内容库" },
|
||||
{ id: 4, title: "步骤 4", subtitle: "京东联盟" },
|
||||
];
|
||||
|
||||
const NewGroupPush: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const [currentStep, setCurrentStep] = useState(1);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [formData, setFormData] = useState<FormData>({
|
||||
name: "",
|
||||
pushTimeStart: "06:00",
|
||||
pushTimeEnd: "23:59",
|
||||
dailyPushCount: 20,
|
||||
pushOrder: "latest",
|
||||
isLoopPush: false,
|
||||
isImmediatePush: false,
|
||||
isEnabled: false,
|
||||
groups: [],
|
||||
contentLibraries: [],
|
||||
});
|
||||
const [isEditMode, setIsEditMode] = useState(false);
|
||||
|
||||
const handleBasicSettingsNext = (values: Partial<FormData>) => {
|
||||
setFormData((prev) => ({ ...prev, ...values }));
|
||||
setCurrentStep(2);
|
||||
};
|
||||
|
||||
const handleGroupsChange = (groups: WechatGroup[]) => {
|
||||
setFormData((prev) => ({ ...prev, groups }));
|
||||
};
|
||||
|
||||
const handleLibrariesChange = (contentLibraries: ContentLibrary[]) => {
|
||||
setFormData((prev) => ({ ...prev, contentLibraries }));
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!formData.name.trim()) {
|
||||
window.alert("请输入任务名称");
|
||||
return;
|
||||
}
|
||||
if (formData.groups.length === 0) {
|
||||
window.alert("请选择至少一个社群");
|
||||
return;
|
||||
}
|
||||
if (formData.contentLibraries.length === 0) {
|
||||
window.alert("请选择至少一个内容库");
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
try {
|
||||
const apiData = {
|
||||
name: formData.name,
|
||||
timeRange: {
|
||||
start: formData.pushTimeStart,
|
||||
end: formData.pushTimeEnd,
|
||||
},
|
||||
maxPushPerDay: formData.dailyPushCount,
|
||||
pushOrder: formData.pushOrder,
|
||||
isLoopPush: formData.isLoopPush,
|
||||
isImmediatePush: formData.isImmediatePush,
|
||||
isEnabled: formData.isEnabled,
|
||||
targetGroups: formData.groups.map((g) => g.name),
|
||||
contentLibraries: formData.contentLibraries.map((c) => c.name),
|
||||
pushMode: formData.isImmediatePush
|
||||
? ("immediate" as const)
|
||||
: ("scheduled" as const),
|
||||
messageType: "text" as const,
|
||||
messageContent: "",
|
||||
targetTags: [],
|
||||
pushInterval: 60,
|
||||
};
|
||||
const response = await createGroupPushTask(apiData);
|
||||
if (response.code === 200) {
|
||||
window.alert("保存成功");
|
||||
navigate("/workspace/group-push");
|
||||
} else {
|
||||
window.alert("保存失败,请稍后重试");
|
||||
}
|
||||
} catch (error) {
|
||||
window.alert("保存失败,请稍后重试");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
navigate("/workspace/group-push");
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout
|
||||
header={
|
||||
<NavBar
|
||||
back={null}
|
||||
style={{ background: "#fff" }}
|
||||
left={
|
||||
<div className="nav-title">
|
||||
<ArrowLeftOutlined
|
||||
twoToneColor="#1677ff"
|
||||
onClick={() => navigate(-1)}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<span className="nav-title">
|
||||
{isEditMode ? "编辑任务" : "新建任务"}
|
||||
</span>
|
||||
</NavBar>
|
||||
}
|
||||
>
|
||||
<div style={{ maxWidth: 600, margin: "0 auto", padding: 16 }}>
|
||||
<StepIndicator currentStep={currentStep} steps={steps} />
|
||||
<div style={{ marginTop: 32 }}>
|
||||
{currentStep === 1 && (
|
||||
<BasicSettings
|
||||
defaultValues={{
|
||||
name: formData.name,
|
||||
pushTimeStart: formData.pushTimeStart,
|
||||
pushTimeEnd: formData.pushTimeEnd,
|
||||
dailyPushCount: formData.dailyPushCount,
|
||||
pushOrder: formData.pushOrder,
|
||||
isLoopPush: formData.isLoopPush,
|
||||
isImmediatePush: formData.isImmediatePush,
|
||||
isEnabled: formData.isEnabled,
|
||||
}}
|
||||
onNext={handleBasicSettingsNext}
|
||||
onSave={handleSave}
|
||||
onCancel={handleCancel}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 2 && (
|
||||
<GroupSelector
|
||||
selectedGroups={formData.groups}
|
||||
onGroupsChange={handleGroupsChange}
|
||||
onPrevious={() => setCurrentStep(1)}
|
||||
onNext={() => setCurrentStep(3)}
|
||||
onSave={handleSave}
|
||||
onCancel={handleCancel}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 3 && (
|
||||
<ContentSelector
|
||||
selectedLibraries={formData.contentLibraries}
|
||||
onLibrariesChange={handleLibrariesChange}
|
||||
onPrevious={() => setCurrentStep(2)}
|
||||
onNext={() => setCurrentStep(4)}
|
||||
onSave={handleSave}
|
||||
onCancel={handleCancel}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
{currentStep === 4 && (
|
||||
<div style={{ padding: 32, textAlign: "center", color: "#888" }}>
|
||||
京东联盟设置(此步骤为占位,实际功能待开发)
|
||||
<div
|
||||
style={{
|
||||
marginTop: 24,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
<Button onClick={() => setCurrentStep(3)} disabled={loading}>
|
||||
上一步
|
||||
</Button>
|
||||
<Button color="primary" onClick={handleSave} loading={loading}>
|
||||
完成
|
||||
</Button>
|
||||
<Button onClick={handleCancel} disabled={loading}>
|
||||
取消
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default NewGroupPush;
|
||||
|
||||
@@ -31,7 +31,6 @@ import {
|
||||
Menu,
|
||||
} from "antd";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import MeauMobile from "@/components/MeauMobile/MeauMoible";
|
||||
import {
|
||||
fetchGroupPushTasks,
|
||||
deleteGroupPushTask,
|
||||
@@ -41,8 +40,6 @@ import {
|
||||
} from "@/pages/workspace/group-push/detail/groupPush";
|
||||
import styles from "./index.module.scss";
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
const GroupPush: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const [expandedTaskId, setExpandedTaskId] = useState<string | null>(null);
|
||||
|
||||
Reference in New Issue
Block a user