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