Merge branch 'yongpxu-dev' into yongpxu-dev2

# Conflicts:
#	Cunkebao/dist/.vite/manifest.json
#	Cunkebao/dist/index.html
This commit is contained in:
超级老白兔
2025-08-27 17:26:54 +08:00
18 changed files with 327 additions and 356 deletions

View File

@@ -10,7 +10,7 @@ export interface FriendSelectionItem {
export interface FriendSelectionProps {
selectedOptions?: FriendSelectionItem[];
onSelect: (friends: FriendSelectionItem[]) => void;
deviceIds?: string[];
deviceIds?: number[];
enableDeviceFilter?: boolean;
placeholder?: string;
className?: string;

View File

@@ -12,7 +12,7 @@ interface SelectionPopupProps {
onVisibleChange: (visible: boolean) => void;
selectedOptions: FriendSelectionItem[];
onSelect: (friends: FriendSelectionItem[]) => void;
deviceIds?: string[];
deviceIds?: number[];
enableDeviceFilter?: boolean;
readonly?: boolean;
onConfirm?: (

View File

@@ -1,5 +1,5 @@
import React from "react";
import { Modal, Selector } from "antd-mobile";
import { Popup, Selector } from "antd-mobile";
import type { PackageOption } from "./data";
interface BatchAddModalProps {
@@ -15,20 +15,30 @@ interface BatchAddModalProps {
const BatchAddModal: React.FC<BatchAddModalProps> = ({
visible,
onClose,
packageOptions,
packageOptions = [],
batchTarget,
setBatchTarget,
selectedCount,
onConfirm,
}) => (
<Modal
// <Modal visible={visible} title="批量加入分组" onConfirm={onConfirm}>
// <div style={{ marginBottom: 12 }}>
// <div>选择目标分组</div>
// <Selector
// options={packageOptions.map(p => ({ label: p.name, value: p.id }))}
// value={[batchTarget]}
// onChange={v => setBatchTarget(v[0])}
// />
// </div>
// <div style={{ color: "#888", fontSize: 13 }}>
// 将选中的{selectedCount}个用户加入所选分组
// </div>
// </Modal>
<Popup
visible={visible}
title="批量加入分组"
onClose={onClose}
footer={[
{ text: "取消", onClick: onClose },
{ text: "确定", onClick: onConfirm },
]}
onMaskClick={() => onClose()}
position="bottom"
bodyStyle={{ height: "80vh" }}
>
<div style={{ marginBottom: 12 }}>
<div></div>
@@ -41,7 +51,7 @@ const BatchAddModal: React.FC<BatchAddModalProps> = ({
<div style={{ color: "#888", fontSize: 13 }}>
{selectedCount}
</div>
</Modal>
</Popup>
);
export default BatchAddModal;

View File

@@ -9,10 +9,10 @@ export function fetchTrafficPoolList(params: {
return request("/v1/traffic/pool", params, "GET");
}
export async function fetchScenarioOptions(): Promise<any[]> {
export async function fetchScenarioOptions() {
return request("/v1/plan/scenes", {}, "GET");
}
export async function fetchPackageOptions(): Promise<any[]> {
export async function fetchPackageOptions() {
return request("/v1/traffic/pool/getPackage", {}, "GET");
}

View File

@@ -4,14 +4,7 @@ import {
fetchPackageOptions,
fetchScenarioOptions,
} from "./api";
import type {
TrafficPoolUser,
DeviceOption,
PackageOption,
ValueLevel,
UserStatus,
ScenarioOption,
} from "./data";
import type { TrafficPoolUser, PackageOption, ScenarioOption } from "./data";
import { Toast } from "antd-mobile";
export function useTrafficPoolListLogic() {
@@ -78,8 +71,12 @@ export function useTrafficPoolListLogic() {
// 获取筛选项
useEffect(() => {
fetchPackageOptions().then(setPackageOptions);
fetchScenarioOptions().then(setScenarioOptions);
fetchPackageOptions().then(res => {
setPackageOptions(res.list || []);
});
fetchScenarioOptions().then(res => {
setScenarioOptions(res.list || []);
});
}, []);
// 筛选条件变化时刷新列表

View File

@@ -173,8 +173,8 @@ const TrafficPoolList: React.FC = () => {
status: "offline" as const,
})),
);
setPackageId(filters.packageId);
setScenarioId(filters.scenarioId);
setPackageId(filters.packageId ? parseInt(filters.packageId) : 0);
setScenarioId(filters.scenarioId ? parseInt(filters.scenarioId) : 0);
setUserValue(filters.userValue);
setUserStatus(filters.userStatus);
// 重新获取列表

View File

@@ -35,8 +35,8 @@ export function deleteAutoLikeTask(id: string): Promise<any> {
}
// 切换任务状态
export function toggleAutoLikeTask(id: string, status: string): Promise<any> {
return request("/v1/workbench/update-status", { id, status }, "POST");
export function toggleAutoLikeTask(data): Promise<any> {
return request("/v1/workbench/update-status", { ...data, type: 1 }, "POST");
}
// 复制自动点赞任务

View File

@@ -79,9 +79,9 @@ export interface CreateLikeTaskData {
startTime: string;
endTime: string;
contentTypes: ContentType[];
deveiceGroups: string[];
deveiceGroups: number[];
deveiceGroupsOptions: DeviceSelectionItem[];
friendsGroups: string[];
friendsGroups: number[];
friendsGroupsOptions: FriendSelectionItem[];
friendMaxLikes: number;
friendTags?: string;

View File

@@ -330,7 +330,12 @@ const NewAutoLike: React.FC = () => {
<div className={style.formItem}>
<DeviceSelection
selectedOptions={formData.deveiceGroupsOptions}
onSelect={devices => handleUpdateFormData({ devices })}
onSelect={devices =>
handleUpdateFormData({
deveiceGroups: devices.map(v => v.id),
deveiceGroupsOptions: devices,
})
}
showInput={true}
showSelectedList={true}
/>
@@ -363,7 +368,7 @@ const NewAutoLike: React.FC = () => {
selectedOptions={formData.friendsGroupsOptions || []}
onSelect={friends =>
handleUpdateFormData({
friendsGroups: friends.map(f => String(f.id)),
friendsGroups: friends.map(f => f.id),
friendsGroupsOptions: friends,
})
}
@@ -385,7 +390,7 @@ const NewAutoLike: React.FC = () => {
size="large"
loading={isSubmitting}
disabled={
!formData.friendsgroups || formData.friendsgroups.length === 0
!formData.friendsGroups || formData.friendsGroups.length === 0
}
>
{isEditMode ? "更新任务" : "创建任务"}

View File

@@ -12,8 +12,9 @@ export interface GroupPushTask {
createTime: string;
creator: string;
pushInterval: number;
maxPushPerDay: number;
timeRange: { start: string; end: string };
maxPerDay: number;
startTime: string; // 允许推送的开始时间
endTime: string; // 允许推送的结束时间
messageType: "text" | "image" | "video" | "link";
messageContent: string;
targetTags: string[];

View File

@@ -179,7 +179,7 @@ const Detail: React.FC = () => {
<div>
<SettingOutlined /> <b></b>
<div>{task.pushInterval} </div>
<div>{task.maxPushPerDay} </div>
<div>{task.maxPerDay} </div>
<div>
{task.timeRange.start} - {task.timeRange.end}
</div>
@@ -221,12 +221,10 @@ const Detail: React.FC = () => {
<div>
<CalendarOutlined /> <b></b>
<div>
{task.pushCount} / {task.maxPushPerDay}
{task.pushCount} / {task.maxPerDay}
</div>
<Progress
percent={Math.round(
(task.pushCount / task.maxPushPerDay) * 100,
)}
percent={Math.round((task.pushCount / task.maxPerDay) * 100)}
size="small"
/>
{task.targetTags.length > 0 && (

View File

@@ -1,16 +1,33 @@
import React, { useImperativeHandle, forwardRef } from "react";
import { Input, Button, Card, Switch, Form, InputNumber } from "antd";
import React, {
useImperativeHandle,
forwardRef,
useState,
useEffect,
} from "react";
import {
Input,
Button,
Card,
Switch,
Form,
InputNumber,
Select,
Radio,
} from "antd";
import { fetchSocialMediaList, fetchPromotionSiteList } from "../index.api";
interface BasicSettingsProps {
defaultValues?: {
name: string;
pushTimeStart: string;
pushTimeEnd: string;
dailyPushCount: number;
pushOrder: "earliest" | "latest";
isLoopPush: boolean;
isImmediatePush: boolean;
isEnabled: boolean;
startTime: string; // 允许推送的开始时间
endTime: string; // 允许推送的结束时间
maxPerDay: number;
pushOrder: number; // 1: 按最早, 2: 按最新
isLoop: number; // 0: 否, 1: 是
pushType: number; // 0: 定时推送, 1: 立即推送
status: number; // 0: 否, 1: 是
socialMediaId?: string;
promotionSiteId?: string;
};
onNext: (values: any) => void;
onSave: (values: any) => void;
@@ -27,18 +44,61 @@ const BasicSettings = forwardRef<BasicSettingsRef, BasicSettingsProps>(
{
defaultValues = {
name: "",
pushTimeStart: "06:00",
pushTimeEnd: "23:59",
dailyPushCount: 20,
pushOrder: "latest",
isLoopPush: false,
isImmediatePush: false,
isEnabled: false,
startTime: "06:00", // 允许推送的开始时间
endTime: "23:59", // 允许推送的结束时间
maxPerDay: 20,
pushOrder: 1,
isLoop: 0, // 0: 否, 1: 是
pushType: 0, // 0: 定时推送, 1: 立即推送
status: 0, // 0: 否, 1: 是
socialMediaId: undefined,
promotionSiteId: undefined,
},
},
ref,
) => {
const [form] = Form.useForm();
const [, forceUpdate] = useState({});
const [socialMediaList, setSocialMediaList] = useState([]);
const [promotionSiteList, setPromotionSiteList] = useState([]);
const [loadingSocialMedia, setLoadingSocialMedia] = useState(false);
const [loadingPromotionSite, setLoadingPromotionSite] = useState(false);
// 确保组件初始化时能正确显示按钮状态
useEffect(() => {
forceUpdate({});
}, []);
// 组件挂载时获取社交媒体列表
useEffect(() => {
setLoadingSocialMedia(true);
fetchSocialMediaList()
.then(res => {
setSocialMediaList(res);
})
.finally(() => {
setLoadingSocialMedia(false);
});
}, []);
// 监听社交媒体选择变化
const handleSocialMediaChange = value => {
form.setFieldsValue({ socialMediaId: value });
// 清空推广站点选择
form.setFieldsValue({ promotionSiteId: undefined });
setPromotionSiteList([]);
if (value) {
setLoadingPromotionSite(true);
fetchPromotionSiteList(value)
.then(res => {
setPromotionSiteList(res);
})
.finally(() => {
setLoadingPromotionSite(false);
});
}
};
// 暴露方法给父组件
useImperativeHandle(ref, () => ({
@@ -55,7 +115,10 @@ const BasicSettings = forwardRef<BasicSettingsRef, BasicSettingsProps>(
return form.getFieldsValue();
},
}));
const handlePushOrderChange = (value: number) => {
form.setFieldsValue({ pushOrder: value });
forceUpdate({}); // 强制组件重新渲染
};
return (
<div style={{ marginBottom: 24 }}>
<Card>
@@ -64,7 +127,10 @@ const BasicSettings = forwardRef<BasicSettingsRef, BasicSettingsProps>(
layout="vertical"
initialValues={defaultValues}
onValuesChange={(changedValues, allValues) => {
// 可以在这里处理表单值变化
// 当pushOrder值变化时强制更新组件
if ("pushOrder" in changedValues) {
forceUpdate({});
}
}}
>
{/* 任务名称 */}
@@ -78,32 +144,56 @@ const BasicSettings = forwardRef<BasicSettingsRef, BasicSettingsProps>(
>
<Input placeholder="请输入任务名称" />
</Form.Item>
{/* 允许推送的时间段 */}
<Form.Item label="允许推送的时间段">
<div style={{ display: "flex", gap: 8, alignItems: "center" }}>
<Form.Item
name="pushTimeStart"
noStyle
rules={[{ required: true, message: "请选择开始时间" }]}
>
<Input type="time" style={{ width: 120 }} />
</Form.Item>
<span style={{ color: "#888" }}></span>
<Form.Item
name="pushTimeEnd"
noStyle
rules={[{ required: true, message: "请选择结束时间" }]}
>
<Input type="time" style={{ width: 120 }} />
</Form.Item>
</div>
{/* 推送类型 */}
<Form.Item
label="推送类型"
name="pushType"
rules={[{ required: true, message: "请选择推送类型" }]}
>
<Radio.Group>
<Radio value={0}></Radio>
<Radio value={1}></Radio>
</Radio.Group>
</Form.Item>
{/* 允许推送的时间段 - 只在定时推送时显示 */}
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) =>
prevValues.pushType !== currentValues.pushType
}
>
{({ getFieldValue }) => {
// 只在pushType为0定时推送时显示时间段设置
return getFieldValue("pushType") === 0 ? (
<Form.Item label="允许推送的时间段">
<div
style={{ display: "flex", gap: 8, alignItems: "center" }}
>
<Form.Item
name="startTime"
noStyle
rules={[{ required: true, message: "请选择开始时间" }]}
>
<Input type="time" style={{ width: 120 }} />
</Form.Item>
<span style={{ color: "#888" }}></span>
<Form.Item
name="endTime"
noStyle
rules={[{ required: true, message: "请选择结束时间" }]}
>
<Input type="time" style={{ width: 120 }} />
</Form.Item>
</div>
</Form.Item>
) : null;
}}
</Form.Item>
{/* 每日推送 */}
<Form.Item
label="每日推送"
name="dailyPushCount"
name="maxPerDay"
rules={[
{ required: true, message: "请输入每日推送数量" },
{
@@ -130,46 +220,64 @@ const BasicSettings = forwardRef<BasicSettingsRef, BasicSettingsProps>(
>
<div style={{ display: "flex" }}>
<Button
type="default"
style={{ borderRadius: "6px 0 0 6px" }}
onClick={() => form.setFieldValue("pushOrder", "earliest")}
className={
form.getFieldValue("pushOrder") === "earliest"
? "ant-btn-primary"
: ""
type={
form.getFieldValue("pushOrder") == 1 ? "primary" : "default"
}
style={{ borderRadius: "6px 0 0 6px" }}
onClick={() => handlePushOrderChange(1)}
>
</Button>
<Button
type="default"
style={{ borderRadius: "0 6px 6px 0", marginLeft: -1 }}
onClick={() => form.setFieldValue("pushOrder", "latest")}
className={
form.getFieldValue("pushOrder") === "latest"
? "ant-btn-primary"
: ""
type={
form.getFieldValue("pushOrder") == 2 ? "primary" : "default"
}
style={{ borderRadius: "0 6px 6px 0", marginLeft: -1 }}
onClick={() => handlePushOrderChange(2)}
>
</Button>
</div>
</Form.Item>
{/* 京东联盟 */}
<Form.Item label="京东联盟" style={{ marginBottom: 16 }}>
<div style={{ display: "flex", gap: 12, alignItems: "flex-end" }}>
<Form.Item name="socialMediaId" noStyle>
<Select
placeholder="请选择社交媒体"
style={{ width: 200 }}
loading={loadingSocialMedia}
onChange={handleSocialMediaChange}
options={socialMediaList.map(item => ({
label: item.name,
value: item.id,
}))}
/>
</Form.Item>
<Form.Item name="promotionSiteId" noStyle>
<Select
placeholder="请选择推广站点"
style={{ width: 200 }}
loading={loadingPromotionSite}
disabled={!form.getFieldValue("socialMediaId")}
options={promotionSiteList.map(item => ({
label: item.name,
value: item.id,
}))}
/>
</Form.Item>
</div>
</Form.Item>
{/* 是否循环推送 */}
<Form.Item
label="是否循环推送"
name="isLoopPush"
valuePropName="checked"
>
<Switch />
</Form.Item>
{/* 是否立即推送 */}
<Form.Item
label="是否立即推送"
name="isImmediatePush"
name="isLoop"
valuePropName="checked"
getValueFromEvent={checked => (checked ? 1 : 0)}
getValueProps={value => ({ checked: value === 1 })}
>
<Switch />
</Form.Item>
@@ -177,30 +285,40 @@ const BasicSettings = forwardRef<BasicSettingsRef, BasicSettingsProps>(
{/* 是否启用 */}
<Form.Item
label="是否启用"
name="isEnabled"
name="status"
valuePropName="checked"
getValueFromEvent={checked => (checked ? 1 : 0)}
getValueProps={value => ({ checked: value === 1 })}
>
<Switch />
</Form.Item>
{/* 立即推送提示 */}
<Form.Item noStyle shouldUpdate>
{() => {
const isImmediatePush = form.getFieldValue("isImmediatePush");
return isImmediatePush ? (
<div
style={{
background: "#fffbe6",
border: "1px solid #ffe58f",
borderRadius: 4,
padding: 8,
color: "#ad8b00",
marginBottom: 16,
}}
>
</div>
) : null;
{/* 推送类型提示 */}
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) =>
prevValues.pushType !== currentValues.pushType
}
>
{({ getFieldValue }) => {
const pushType = getFieldValue("pushType");
if (pushType === 1) {
return (
<div
style={{
background: "#fffbe6",
border: "1px solid #ffe58f",
borderRadius: 4,
padding: 8,
color: "#ad8b00",
marginBottom: 16,
}}
>
</div>
);
}
return null;
}}
</Form.Item>
</Form>

View File

@@ -1,148 +0,0 @@
import React, {
useState,
useEffect,
useImperativeHandle,
forwardRef,
} from "react";
import { Form, Select, Card } from "antd";
import { fetchSocialMediaList, fetchPromotionSiteList } from "../index.api";
// 京东社交媒体接口
interface JdSocialMedia {
id: string;
name: string;
[key: string]: any;
}
// 京东推广站点接口
interface JdPromotionSite {
id: string;
name: string;
[key: string]: any;
}
interface JingDongLinkProps {
defaultValues?: {
socialMediaId?: string;
promotionSiteId?: string;
};
onNext?: (values: any) => void;
onSave?: (values: any) => void;
loading?: boolean;
}
export interface JingDongLinkRef {
validate: () => Promise<boolean>;
getValues: () => any;
}
const JingDongLink = forwardRef<JingDongLinkRef, JingDongLinkProps>(
(
{
defaultValues = {
socialMediaId: undefined,
promotionSiteId: undefined,
},
onNext,
onSave,
loading = false,
},
ref,
) => {
const [form] = Form.useForm();
const [socialMediaList, setSocialMediaList] = useState<JdSocialMedia[]>([]);
const [promotionSiteList, setPromotionSiteList] = useState<
JdPromotionSite[]
>([]);
const [loadingSocialMedia, setLoadingSocialMedia] = useState(false);
const [loadingPromotionSite, setLoadingPromotionSite] = useState(false);
// 暴露方法给父组件
useImperativeHandle(ref, () => ({
validate: async () => {
try {
await form.validateFields();
return true;
} catch (error) {
console.log("JingDongLink 表单验证失败:", error);
return false;
}
},
getValues: () => {
return form.getFieldsValue();
},
}));
// 组件挂载时获取社交媒体列表
useEffect(() => {
fetchSocialMediaList().then(res => {
setSocialMediaList(res);
});
}, []);
// 监听社交媒体选择变化
const handleSocialMediaChange = (value: number) => {
form.setFieldsValue({ socialMediaId: value });
// 清空推广站点选择
form.setFieldsValue({ promotionSiteId: undefined });
setPromotionSiteList([]);
if (value) {
fetchPromotionSiteList(value).then(res => {
setPromotionSiteList(res);
});
}
};
return (
<div style={{ marginBottom: 24 }}>
<Card title="京东联盟">
<Form form={form} layout="vertical" initialValues={defaultValues}>
{/* 京东社交媒体选择 */}
<Form.Item label="京东联盟" style={{ marginBottom: 16 }}>
<div style={{ display: "flex", gap: 12, alignItems: "flex-end" }}>
<Form.Item
name="socialMediaId"
noStyle
rules={[{ required: true, message: "请选择社交媒体" }]}
>
<Select
placeholder="请选择社交媒体"
style={{ width: 200 }}
loading={loadingSocialMedia}
onChange={handleSocialMediaChange}
options={socialMediaList.map(item => ({
label: item.name,
value: item.id,
}))}
/>
</Form.Item>
<Form.Item
name="promotionSiteId"
noStyle
rules={[{ required: true, message: "请选择推广站点" }]}
>
<Select
placeholder="请选择推广站点"
style={{ width: 200 }}
loading={loadingPromotionSite}
disabled={!form.getFieldValue("socialMediaId")}
options={promotionSiteList.map(item => ({
label: item.name,
value: item.id,
}))}
/>
</Form.Item>
</div>
</Form.Item>
</Form>
</Card>
</div>
);
},
);
JingDongLink.displayName = "JingDongLink";
export default JingDongLink;

View File

@@ -1,8 +1,12 @@
import request from "@/api/request";
export function createGroupPushTask(taskData) {
return request("/v1/workspace/group-push/tasks", taskData, "POST");
export function createGroupPushTask(data) {
return request("/v1/workbench/create", { ...data, type: 3 }, "POST");
}
export function updateGroupPushTask(data) {
return request("/v1/workbench/update", { ...data, type: 3 }, "POST");
}
// 获取京东社交媒体列表
export const fetchSocialMediaList = async () => {
return request("/v1/workbench/getJdSocialMedia", {}, "GET");

View File

@@ -21,13 +21,13 @@ export interface ContentLibrary {
export interface FormData {
name: string;
pushTimeStart: string;
pushTimeEnd: string;
dailyPushCount: number;
pushOrder: "earliest" | "latest";
isLoopPush: boolean;
isImmediatePush: boolean;
isEnabled: boolean;
startTime: string; // 允许推送的开始时间
endTime: string; // 允许推送的结束时间
maxPerDay: number;
pushOrder: number; // 1: 按最早, 2: 按最新
isLoop: number; // 0: 否, 1: 是
pushType: number; // 0: 定时推送, 1: 立即推送
status: number; // 0: 否, 1: 是
contentGroups: string[];
wechatGroups: string[];
// 京东联盟相关字段

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect, useRef } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { Button } from "antd";
import { Toast } from "antd-mobile";
import { createGroupPushTask } from "./index.api";
import Layout from "@/components/Layout/Layout";
import StepIndicator from "@/components/StepIndicator";
@@ -9,7 +10,6 @@ import GroupSelector, { GroupSelectorRef } from "./components/GroupSelector";
import ContentSelector, {
ContentSelectorRef,
} from "./components/ContentSelector";
import JingDongLink, { JingDongLinkRef } from "./components/JingDongLink";
import type { FormData } from "./index.data";
import NavCommon from "@/components/NavCommon";
import { GroupSelectionItem } from "@/components/GroupSelection/data";
@@ -18,7 +18,6 @@ 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 = () => {
@@ -35,13 +34,13 @@ const NewGroupPush: React.FC = () => {
const [formData, setFormData] = useState<FormData>({
name: "",
pushTimeStart: "06:00",
pushTimeEnd: "23:59",
dailyPushCount: 20,
pushOrder: "latest",
isLoopPush: false,
isImmediatePush: false,
isEnabled: false,
startTime: "06:00", // 允许推送的开始时间
endTime: "23:59", // 允许推送的结束时间
maxPerDay: 20,
pushOrder: 2, // 2: 按最新
isLoop: 0, // 0: 否, 1: 是
pushType: 0, // 0: 定时推送, 1: 立即推送
status: 0, // 0: 否, 1: 是
wechatGroups: [],
contentGroups: [],
});
@@ -51,7 +50,6 @@ const NewGroupPush: React.FC = () => {
const basicSettingsRef = useRef<BasicSettingsRef>(null);
const groupSelectorRef = useRef<GroupSelectorRef>(null);
const contentSelectorRef = useRef<ContentSelectorRef>(null);
const jingDongLinkRef = useRef<JingDongLinkRef>(null);
useEffect(() => {
if (!id) return;
@@ -83,57 +81,61 @@ const NewGroupPush: React.FC = () => {
};
const handleSave = async () => {
if (!formData.name.trim()) {
window.alert("请输入任务名称");
return;
}
if (formData.wechatGroups.length === 0) {
window.alert("请选择至少一个社群");
return;
}
if (formData.contentGroups.length === 0) {
window.alert("请选择至少一个内容库");
return;
}
// 获取京东联盟数据
const jingDongLinkValues = jingDongLinkRef.current?.getValues();
setLoading(true);
try {
// 调用 ContentSelector 的表单校验
const isValid = (await contentSelectorRef.current?.validate()) || false;
if (!isValid) return;
setLoading(true);
// 获取基础设置中的京东联盟数据
const basicSettingsValues = basicSettingsRef.current?.getValues() || {};
// 构建 API 请求数据
const apiData = {
name: formData.name,
timeRange: {
start: formData.pushTimeStart,
end: formData.pushTimeEnd,
},
maxPushPerDay: formData.dailyPushCount,
startTime: formData.startTime, // 允许推送的开始时间
endTime: formData.endTime, // 允许推送的结束时间
maxPerDay: formData.maxPerDay,
pushOrder: formData.pushOrder,
isLoopPush: formData.isLoopPush,
isImmediatePush: formData.isImmediatePush,
isEnabled: formData.isEnabled,
isLoop: formData.isLoop, // 0: 否, 1: 是
pushType: formData.pushType, // 0: 定时推送, 1: 立即推送
status: formData.status, // 0: 否, 1: 是
wechatGroups: formData.wechatGroups,
contentGroups: formData.contentGroups,
// 京东联盟数据
socialMediaId: jingDongLinkValues?.socialMediaId,
promotionSiteId: jingDongLinkValues?.promotionSiteId,
pushMode: formData.isImmediatePush
? ("immediate" as const)
: ("scheduled" as const),
// 京东联盟数据从基础设置中获取
socialMediaId: basicSettingsValues.socialMediaId,
promotionSiteId: basicSettingsValues.promotionSiteId,
pushMode:
formData.pushType === 1
? ("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("保存成功");
// 打印API请求数据用于调试
console.log("发送到API的数据:", apiData);
// 调用创建或更新 API
if (id) {
// 更新逻辑将在这里实现
Toast.show({ content: "更新成功", position: "top" });
navigate("/workspace/group-push");
} else {
window.alert("保存失败,请稍后重试");
createGroupPushTask(apiData)
.then(() => {
Toast.show({ content: "创建成功", position: "top" });
navigate("/workspace/group-push");
})
.catch(() => {
Toast.show({ content: "创建失败,请稍后重试", position: "top" });
});
}
} catch (error) {
window.alert("保存失败,请稍后重试");
Toast.show({ content: "保存失败,请稍后重试", position: "top" });
} finally {
setLoading(false);
}
@@ -146,7 +148,7 @@ const NewGroupPush: React.FC = () => {
};
const handleNext = async () => {
if (currentStep < 4) {
if (currentStep < 3) {
try {
let isValid = false;
@@ -171,14 +173,6 @@ const NewGroupPush: React.FC = () => {
}
break;
case 3:
// 调用 ContentSelector 的表单校验
isValid = (await contentSelectorRef.current?.validate()) || false;
if (isValid) {
setCurrentStep(4);
}
break;
default:
setCurrentStep(currentStep + 1);
}
@@ -196,7 +190,7 @@ const NewGroupPush: React.FC = () => {
</Button>
)}
{currentStep === 4 ? (
{currentStep === 3 ? (
<Button size="large" type="primary" onClick={handleSave}>
</Button>
@@ -224,13 +218,13 @@ const NewGroupPush: React.FC = () => {
ref={basicSettingsRef}
defaultValues={{
name: formData.name,
pushTimeStart: formData.pushTimeStart,
pushTimeEnd: formData.pushTimeEnd,
dailyPushCount: formData.dailyPushCount,
startTime: formData.startTime,
endTime: formData.endTime,
maxPerDay: formData.maxPerDay,
pushOrder: formData.pushOrder,
isLoopPush: formData.isLoopPush,
isImmediatePush: formData.isImmediatePush,
isEnabled: formData.isEnabled,
isLoop: formData.isLoop,
status: formData.status,
pushType: formData.pushType,
}}
onNext={handleBasicSettingsChange}
onSave={handleSave}
@@ -253,9 +247,6 @@ const NewGroupPush: React.FC = () => {
onNext={handleLibrariesChange}
/>
)}
{currentStep === 4 && (
<JingDongLink ref={jingDongLinkRef} loading={loading} />
)}
</div>
</div>
</Layout>

View File

@@ -1,4 +1,5 @@
import request from "@/api/request";
import { GroupPushTask } from "../detail/groupPush";
interface ApiResponse<T = any> {
code: number;
@@ -11,22 +12,16 @@ export async function fetchGroupPushTasks() {
}
export async function deleteGroupPushTask(id: string): Promise<ApiResponse> {
return request(`/v1/workspace/group-push/tasks/${id}`, {}, "DELETE");
return request("/v1/workbench/delete", { id }, "DELETE");
}
export async function toggleGroupPushTask(
id: string,
status: string,
): Promise<ApiResponse> {
return request(
`/v1/workspace/group-push/tasks/${id}/toggle`,
{ status },
"POST",
);
// 切换任务状态
export function toggleGroupPushTask(data): Promise<any> {
return request("/v1/workbench/update-status", { ...data, type: 3 }, "POST");
}
export async function copyGroupPushTask(id: string): Promise<ApiResponse> {
return request(`/v1/workspace/group-push/tasks/${id}/copy`, {}, "POST");
return request("/v1/workbench/copy", { id }, "POST");
}
export async function createGroupPushTask(

View File

@@ -133,7 +133,7 @@ const GroupPush: React.FC = () => {
const task = tasks.find(t => t.id === taskId);
if (!task) return;
const newStatus = task.status === 1 ? 2 : 1;
await toggleGroupPushTask(taskId, String(newStatus));
await toggleGroupPushTask({ id: taskId, status: newStatus });
fetchTasks();
};