feat: 本次提交更新内容如下
消息推送列表优化
This commit is contained in:
@@ -1,250 +0,0 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import { useParams, useNavigate } from "react-router-dom";
|
|
||||||
import { Button, Spin, message } from "antd";
|
|
||||||
import { ArrowLeftOutlined } from "@ant-design/icons";
|
|
||||||
import Layout from "@/components/Layout/Layout";
|
|
||||||
import MeauMobile from "@/components/MeauMobile/MeauMoible";
|
|
||||||
import StepIndicator from "./form/components/StepIndicator";
|
|
||||||
import BasicSettings from "./form/components/BasicSettings";
|
|
||||||
import GroupSelector from "./form/components/GroupSelector";
|
|
||||||
import ContentSelector from "./form/components/ContentSelector";
|
|
||||||
import {
|
|
||||||
getGroupPushTaskDetail,
|
|
||||||
updateGroupPushTask,
|
|
||||||
GroupPushTask,
|
|
||||||
} from "@/api/groupPush";
|
|
||||||
|
|
||||||
const steps = [
|
|
||||||
{ id: 1, title: "步骤 1", subtitle: "基础设置" },
|
|
||||||
{ id: 2, title: "步骤 2", subtitle: "选择社群" },
|
|
||||||
{ id: 3, title: "步骤 3", subtitle: "选择内容库" },
|
|
||||||
{ id: 4, title: "步骤 4", subtitle: "京东联盟" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const EditGroupPush: React.FC = () => {
|
|
||||||
const { id } = useParams<{ id: string }>();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const [currentStep, setCurrentStep] = useState(1);
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [saving, setSaving] = useState(false);
|
|
||||||
const [formData, setFormData] = useState<any>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!id) return;
|
|
||||||
setLoading(true);
|
|
||||||
getGroupPushTaskDetail(id)
|
|
||||||
.then((res) => {
|
|
||||||
const task = res.data || res;
|
|
||||||
setFormData({
|
|
||||||
name: task.name,
|
|
||||||
pushTimeStart: task.timeRange?.start || "06:00",
|
|
||||||
pushTimeEnd: task.timeRange?.end || "23:59",
|
|
||||||
dailyPushCount: task.maxPushPerDay,
|
|
||||||
pushOrder: task.pushOrder || "latest",
|
|
||||||
isLoopPush: task.isLoopPush || false,
|
|
||||||
isImmediatePush: task.pushMode === "immediate",
|
|
||||||
isEnabled: task.isEnabled || false,
|
|
||||||
groups: (task.targetGroups || []).map(
|
|
||||||
(name: string, idx: number) => ({
|
|
||||||
id: String(idx + 1),
|
|
||||||
name,
|
|
||||||
avatar: "",
|
|
||||||
serviceAccount: { id: "", name: "", avatar: "" },
|
|
||||||
})
|
|
||||||
),
|
|
||||||
contentLibraries: (task.contentLibraries || []).map(
|
|
||||||
(name: string, idx: number) => ({
|
|
||||||
id: String(idx + 1),
|
|
||||||
name,
|
|
||||||
targets: [],
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.finally(() => setLoading(false));
|
|
||||||
}, [id]);
|
|
||||||
|
|
||||||
const handleBasicSettingsNext = (values: any) => {
|
|
||||||
setFormData((prev: any) => ({ ...prev, ...values }));
|
|
||||||
setCurrentStep(2);
|
|
||||||
};
|
|
||||||
const handleGroupsChange = (groups: any[]) => {
|
|
||||||
setFormData((prev: any) => ({ ...prev, groups }));
|
|
||||||
};
|
|
||||||
const handleLibrariesChange = (contentLibraries: any[]) => {
|
|
||||||
setFormData((prev: any) => ({ ...prev, contentLibraries }));
|
|
||||||
};
|
|
||||||
const handleSave = async () => {
|
|
||||||
if (!formData.name.trim()) {
|
|
||||||
message.error("请输入任务名称");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!formData.groups || formData.groups.length === 0) {
|
|
||||||
message.error("请选择至少一个社群");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!formData.contentLibraries || formData.contentLibraries.length === 0) {
|
|
||||||
message.error("请选择至少一个内容库");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setSaving(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: any) => g.name),
|
|
||||||
contentLibraries: formData.contentLibraries.map((c: any) => c.name),
|
|
||||||
pushMode: formData.isImmediatePush
|
|
||||||
? ("immediate" as const)
|
|
||||||
: ("scheduled" as const),
|
|
||||||
messageType: "text" as const,
|
|
||||||
messageContent: "",
|
|
||||||
targetTags: [],
|
|
||||||
pushInterval: 60,
|
|
||||||
};
|
|
||||||
const response = await updateGroupPushTask(id!, apiData);
|
|
||||||
if (response.code === 200) {
|
|
||||||
message.success("保存成功");
|
|
||||||
navigate("/workspace/group-push");
|
|
||||||
} else {
|
|
||||||
message.error("保存失败,请稍后重试");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
message.error("保存失败,请稍后重试");
|
|
||||||
} finally {
|
|
||||||
setSaving(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
|
||||||
navigate("/workspace/group-push");
|
|
||||||
};
|
|
||||||
|
|
||||||
if (loading || !formData) {
|
|
||||||
return (
|
|
||||||
<Layout
|
|
||||||
header={
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
background: "#fff",
|
|
||||||
padding: "0 16px",
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: 18,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ArrowLeftOutlined
|
|
||||||
onClick={() => navigate(-1)}
|
|
||||||
style={{ marginRight: 12, cursor: "pointer" }}
|
|
||||||
/>
|
|
||||||
编辑群发推送
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
footer={<MeauMobile />}
|
|
||||||
>
|
|
||||||
<div style={{ padding: 48, textAlign: "center" }}>
|
|
||||||
<Spin />
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Layout
|
|
||||||
header={
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
background: "#fff",
|
|
||||||
padding: "0 16px",
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: 18,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ArrowLeftOutlined
|
|
||||||
onClick={() => navigate(-1)}
|
|
||||||
style={{ marginRight: 12, cursor: "pointer" }}
|
|
||||||
/>
|
|
||||||
编辑群发推送
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
footer={<MeauMobile />}
|
|
||||||
>
|
|
||||||
<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={saving}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{currentStep === 2 && (
|
|
||||||
<GroupSelector
|
|
||||||
selectedGroups={formData.groups}
|
|
||||||
onGroupsChange={handleGroupsChange}
|
|
||||||
onPrevious={() => setCurrentStep(1)}
|
|
||||||
onNext={() => setCurrentStep(3)}
|
|
||||||
onSave={handleSave}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
loading={saving}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{currentStep === 3 && (
|
|
||||||
<ContentSelector
|
|
||||||
selectedLibraries={formData.contentLibraries}
|
|
||||||
onLibrariesChange={handleLibrariesChange}
|
|
||||||
onPrevious={() => setCurrentStep(2)}
|
|
||||||
onNext={() => setCurrentStep(4)}
|
|
||||||
onSave={handleSave}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
loading={saving}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{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={saving}>
|
|
||||||
上一步
|
|
||||||
</Button>
|
|
||||||
<Button type="primary" onClick={handleSave} loading={saving}>
|
|
||||||
完成
|
|
||||||
</Button>
|
|
||||||
<Button onClick={handleCancel} disabled={saving}>
|
|
||||||
取消
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EditGroupPush;
|
|
||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
import Layout from "@/components/Layout/Layout";
|
import Layout from "@/components/Layout/Layout";
|
||||||
import MeauMobile from "@/components/MeauMobile/MeauMoible";
|
import MeauMobile from "@/components/MeauMobile/MeauMoible";
|
||||||
import { getGroupPushTaskDetail, GroupPushTask } from "@/api/groupPush";
|
import { getGroupPushTaskDetail, GroupPushTask } from "@/api/groupPush";
|
||||||
import styles from "./GroupPush.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
const Detail: React.FC = () => {
|
const Detail: React.FC = () => {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
|
|||||||
107
nkebao/src/pages/workspace/group-push/list/index.module.scss
Normal file
107
nkebao/src/pages/workspace/group-push/list/index.module.scss
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.searchBar {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refresh-btn {
|
||||||
|
height: 38px;
|
||||||
|
width: 40px;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.taskList {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emptyCard {
|
||||||
|
text-align: center;
|
||||||
|
padding: 48px 0;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.taskCard {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
|
||||||
|
padding: 20px 16px 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.taskHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.taskTitle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.taskActions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.taskInfoGrid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 8px 16px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressBlock {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressLabel {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #888;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.taskFooter {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
border-top: 1px dashed #eee;
|
||||||
|
padding-top: 8px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandedPanel {
|
||||||
|
margin-top: 16px;
|
||||||
|
padding-top: 16px;
|
||||||
|
border-top: 1px dashed #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandedGrid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.taskCard {
|
||||||
|
padding: 12px 6px 8px 6px;
|
||||||
|
}
|
||||||
|
.expandedGrid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { NavBar } from "antd-mobile";
|
||||||
import {
|
import {
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
SearchOutlined,
|
SearchOutlined,
|
||||||
@@ -37,7 +38,7 @@ import {
|
|||||||
copyGroupPushTask,
|
copyGroupPushTask,
|
||||||
GroupPushTask,
|
GroupPushTask,
|
||||||
} from "@/api/groupPush";
|
} from "@/api/groupPush";
|
||||||
import styles from "./GroupPush.module.scss";
|
import styles from "./index.module.scss";
|
||||||
|
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
|
|
||||||
@@ -146,37 +147,31 @@ const GroupPush: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Layout
|
<Layout
|
||||||
header={
|
header={
|
||||||
<div style={{ background: "#fff", padding: "0 16px" }}>
|
<NavBar back={null} style={{ background: "#fff" }}>
|
||||||
<div style={{ display: "flex", alignItems: "center", height: 48 }}>
|
<span style={{ fontWeight: 600, fontSize: 18 }}>群消息推送</span>
|
||||||
<span style={{ fontWeight: 600, fontSize: 18 }}>群消息推送</span>
|
</NavBar>
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
icon={<PlusOutlined />}
|
|
||||||
style={{ marginLeft: "auto" }}
|
|
||||||
onClick={handleCreateNew}
|
|
||||||
>
|
|
||||||
新建任务
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
footer={<MeauMobile />}
|
footer={<MeauMobile />}
|
||||||
>
|
>
|
||||||
<div className={styles.bg}>
|
<div className={styles.bg}>
|
||||||
<div className={styles.searchBar}>
|
<div className={styles.searchBar}>
|
||||||
<Search
|
<Input
|
||||||
placeholder="搜索任务名称"
|
placeholder="搜索计划名称"
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
enterButton={<SearchOutlined />}
|
prefix={<SearchOutlined />}
|
||||||
style={{ maxWidth: 320 }}
|
allowClear
|
||||||
|
size="large"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
icon={<ReloadOutlined />}
|
className={styles["refresh-btn"]}
|
||||||
|
size="small"
|
||||||
onClick={fetchTasks}
|
onClick={fetchTasks}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
style={{ marginLeft: 8 }}
|
>
|
||||||
/>
|
<ReloadOutlined />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.taskList}>
|
<div className={styles.taskList}>
|
||||||
{filteredTasks.length === 0 ? (
|
{filteredTasks.length === 0 ? (
|
||||||
@@ -4,7 +4,7 @@ import NewAutoLike from "@/pages/workspace/auto-like/NewAutoLike";
|
|||||||
import AutoLikeDetail from "@/pages/workspace/auto-like/AutoLikeDetail";
|
import AutoLikeDetail from "@/pages/workspace/auto-like/AutoLikeDetail";
|
||||||
import AutoGroup from "@/pages/workspace/auto-group/AutoGroup";
|
import AutoGroup from "@/pages/workspace/auto-group/AutoGroup";
|
||||||
import AutoGroupDetail from "@/pages/workspace/auto-group/Detail";
|
import AutoGroupDetail from "@/pages/workspace/auto-group/Detail";
|
||||||
import GroupPush from "@/pages/workspace/group-push/GroupPush";
|
import GroupPush from "@/pages/workspace/group-push/list";
|
||||||
import FormGroupPush from "@/pages/workspace/group-push/form";
|
import FormGroupPush from "@/pages/workspace/group-push/form";
|
||||||
import DetailGroupPush from "@/pages/workspace/group-push/detail";
|
import DetailGroupPush from "@/pages/workspace/group-push/detail";
|
||||||
import MomentsSync from "@/pages/workspace/moments-sync/MomentsSync";
|
import MomentsSync from "@/pages/workspace/moments-sync/MomentsSync";
|
||||||
|
|||||||
Reference in New Issue
Block a user