409 lines
13 KiB
TypeScript
409 lines
13 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
||
import { useNavigate, useParams } from "react-router-dom";
|
||
import { Button, Input, Switch, message, Spin } from "antd";
|
||
import {
|
||
ArrowLeftOutlined,
|
||
PlusOutlined,
|
||
MinusOutlined,
|
||
CheckOutlined,
|
||
} from "@ant-design/icons";
|
||
import { NavBar } from "antd-mobile";
|
||
import Layout from "@/components/Layout/Layout";
|
||
import {
|
||
createAutoLikeTask,
|
||
updateAutoLikeTask,
|
||
fetchAutoLikeTaskDetail,
|
||
} from "./api";
|
||
import { ContentType } from "@/types/auto-like";
|
||
import style from "./new.module.scss";
|
||
|
||
const contentTypeLabels: Record<ContentType, string> = {
|
||
text: "文字",
|
||
image: "图片",
|
||
video: "视频",
|
||
link: "链接",
|
||
};
|
||
|
||
const steps = ["基础设置", "设备选择", "人群选择"];
|
||
|
||
const defaultForm = {
|
||
name: "",
|
||
interval: 5,
|
||
maxLikes: 200,
|
||
startTime: "08:00",
|
||
endTime: "22:00",
|
||
contentTypes: ["text", "image", "video"] as ContentType[],
|
||
devices: [] as string[],
|
||
friends: [] as string[],
|
||
targetTags: [] as string[],
|
||
friendMaxLikes: 10,
|
||
enableFriendTags: false,
|
||
friendTags: "",
|
||
};
|
||
|
||
const NewAutoLike: React.FC = () => {
|
||
const navigate = useNavigate();
|
||
const { id } = useParams<{ id: string }>();
|
||
const isEditMode = !!id;
|
||
const [currentStep, setCurrentStep] = useState(0);
|
||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||
const [isLoading, setIsLoading] = useState(isEditMode);
|
||
const [autoEnabled, setAutoEnabled] = useState(false);
|
||
const [formData, setFormData] = useState({ ...defaultForm });
|
||
|
||
useEffect(() => {
|
||
if (isEditMode && id) {
|
||
fetchTaskDetail();
|
||
}
|
||
}, [id, isEditMode]);
|
||
|
||
const fetchTaskDetail = async () => {
|
||
setIsLoading(true);
|
||
try {
|
||
const taskDetail = await fetchAutoLikeTaskDetail(id!);
|
||
if (taskDetail) {
|
||
const config = (taskDetail as any).config || taskDetail;
|
||
setFormData({
|
||
name: taskDetail.name || "",
|
||
interval: config.likeInterval || config.interval || 5,
|
||
maxLikes: config.maxLikesPerDay || config.maxLikes || 200,
|
||
startTime: config.timeRange?.start || config.startTime || "08:00",
|
||
endTime: config.timeRange?.end || config.endTime || "22:00",
|
||
contentTypes: config.contentTypes || ["text", "image", "video"],
|
||
devices: config.devices || [],
|
||
friends: config.friends || [],
|
||
targetTags: config.targetTags || [],
|
||
friendMaxLikes: config.friendMaxLikes || 10,
|
||
enableFriendTags: config.enableFriendTags || false,
|
||
friendTags: config.friendTags || "",
|
||
});
|
||
setAutoEnabled(
|
||
(taskDetail as any).status === 1 ||
|
||
(taskDetail as any).status === "running"
|
||
);
|
||
}
|
||
} catch (error) {
|
||
message.error("获取任务详情失败");
|
||
navigate("/workspace/auto-like");
|
||
} finally {
|
||
setIsLoading(false);
|
||
}
|
||
};
|
||
|
||
const handleUpdateFormData = (data: Partial<typeof formData>) => {
|
||
setFormData((prev) => ({ ...prev, ...data }));
|
||
};
|
||
|
||
const handleNext = () => setCurrentStep((prev) => Math.min(prev + 1, 2));
|
||
const handlePrev = () => setCurrentStep((prev) => Math.max(prev - 1, 0));
|
||
|
||
const handleComplete = async () => {
|
||
if (!formData.name.trim()) {
|
||
message.warning("请输入任务名称");
|
||
return;
|
||
}
|
||
if (!formData.devices || formData.devices.length === 0) {
|
||
message.warning("请选择执行设备");
|
||
return;
|
||
}
|
||
setIsSubmitting(true);
|
||
try {
|
||
if (isEditMode && id) {
|
||
await updateAutoLikeTask({ ...formData, id });
|
||
message.success("更新成功");
|
||
} else {
|
||
await createAutoLikeTask(formData);
|
||
message.success("创建成功");
|
||
}
|
||
navigate("/workspace/auto-like");
|
||
} catch (error) {
|
||
message.error(isEditMode ? "更新失败" : "创建失败");
|
||
} finally {
|
||
setIsSubmitting(false);
|
||
}
|
||
};
|
||
|
||
// 步骤1:基础设置
|
||
const renderBasicSettings = () => (
|
||
<div className={style.formStep}>
|
||
<div className={style.formItem}>
|
||
<div className={style.formLabel}>任务名称</div>
|
||
<Input
|
||
placeholder="请输入任务名称"
|
||
value={formData.name}
|
||
onChange={(e) => handleUpdateFormData({ name: e.target.value })}
|
||
className={style.input}
|
||
/>
|
||
</div>
|
||
|
||
<div className={style.formItem}>
|
||
<div className={style.formLabel}>点赞间隔</div>
|
||
<div className={style.counterRow}>
|
||
<button
|
||
type="button"
|
||
className={style.counterBtn}
|
||
onClick={() =>
|
||
handleUpdateFormData({
|
||
interval: Math.max(1, formData.interval - 1),
|
||
})
|
||
}
|
||
>
|
||
<MinusOutlined />
|
||
</button>
|
||
<span className={style.counterValue}>{formData.interval} 秒</span>
|
||
<button
|
||
type="button"
|
||
className={style.counterBtn}
|
||
onClick={() =>
|
||
handleUpdateFormData({ interval: formData.interval + 1 })
|
||
}
|
||
>
|
||
<PlusOutlined />
|
||
</button>
|
||
</div>
|
||
<div className={style.counterTip}>设置两次点赞之间的最小时间间隔</div>
|
||
</div>
|
||
|
||
<div className={style.formItem}>
|
||
<div className={style.formLabel}>每日最大点赞数</div>
|
||
<div className={style.counterRow}>
|
||
<button
|
||
type="button"
|
||
className={style.counterBtn}
|
||
onClick={() =>
|
||
handleUpdateFormData({
|
||
maxLikes: Math.max(1, formData.maxLikes - 10),
|
||
})
|
||
}
|
||
>
|
||
<MinusOutlined />
|
||
</button>
|
||
<span className={style.counterValue}>{formData.maxLikes} 次</span>
|
||
<button
|
||
type="button"
|
||
className={style.counterBtn}
|
||
onClick={() =>
|
||
handleUpdateFormData({ maxLikes: formData.maxLikes + 10 })
|
||
}
|
||
>
|
||
<PlusOutlined />
|
||
</button>
|
||
</div>
|
||
<div className={style.counterTip}>设置每天最多点赞的次数</div>
|
||
</div>
|
||
|
||
<div className={style.formItem}>
|
||
<div className={style.formLabel}>点赞时间范围</div>
|
||
<div className={style.timeRow}>
|
||
<Input
|
||
type="time"
|
||
value={formData.startTime}
|
||
onChange={(e) =>
|
||
handleUpdateFormData({ startTime: e.target.value })
|
||
}
|
||
className={style.inputTime}
|
||
/>
|
||
<span className={style.timeTo}>至</span>
|
||
<Input
|
||
type="time"
|
||
value={formData.endTime}
|
||
onChange={(e) => handleUpdateFormData({ endTime: e.target.value })}
|
||
className={style.inputTime}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className={style.formItem}>
|
||
<div className={style.formLabel}>点赞内容类型</div>
|
||
<div className={style.contentTypes}>
|
||
{(["text", "image", "video"] as ContentType[]).map((type) => (
|
||
<span
|
||
key={type}
|
||
className={
|
||
formData.contentTypes.includes(type)
|
||
? style.contentTypeTagActive
|
||
: style.contentTypeTag
|
||
}
|
||
onClick={() => {
|
||
const newTypes = formData.contentTypes.includes(type)
|
||
? formData.contentTypes.filter((t) => t !== type)
|
||
: [...formData.contentTypes, type];
|
||
handleUpdateFormData({ contentTypes: newTypes });
|
||
}}
|
||
>
|
||
{contentTypeLabels[type]}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div className={style.formItem}>
|
||
<div className={style.switchRow}>
|
||
<span className={style.switchLabel}>启用好友标签</span>
|
||
<Switch
|
||
checked={formData.enableFriendTags}
|
||
onChange={(checked) =>
|
||
handleUpdateFormData({ enableFriendTags: checked })
|
||
}
|
||
className={style.switch}
|
||
/>
|
||
</div>
|
||
{formData.enableFriendTags && (
|
||
<div className={style.formItem}>
|
||
<div className={style.formLabel}>好友标签</div>
|
||
<Input
|
||
placeholder="请输入标签"
|
||
value={formData.friendTags}
|
||
onChange={(e) =>
|
||
handleUpdateFormData({ friendTags: e.target.value })
|
||
}
|
||
className={style.input}
|
||
/>
|
||
<div className={style.counterTip}>只给有此标签的好友点赞</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<div className={style.formItem}>
|
||
<div className={style.switchRow}>
|
||
<span className={style.switchLabel}>自动开启</span>
|
||
<Switch
|
||
checked={autoEnabled}
|
||
onChange={setAutoEnabled}
|
||
className={style.switch}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className={style.formStepBtnRow}>
|
||
<Button type="primary" onClick={handleNext} className={style.nextBtn}>
|
||
下一步
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
);
|
||
|
||
// 步骤2:设备选择
|
||
const renderDeviceSelection = () => (
|
||
<div className={style.formStep}>
|
||
<div className={style.formItem}>
|
||
<div className={style.formLabel}>选择设备</div>
|
||
<Input
|
||
placeholder="请选择设备"
|
||
value={formData.devices.join(", ")}
|
||
readOnly
|
||
onClick={() => message.info("这里应弹出设备选择器")}
|
||
className={style.input}
|
||
/>
|
||
{formData.devices.length > 0 && (
|
||
<div className={style.selectedTip}>
|
||
已选设备: {formData.devices.length}个
|
||
</div>
|
||
)}
|
||
</div>
|
||
<div className={style.formStepBtnRow}>
|
||
<Button onClick={handlePrev} className={style.prevBtn}>
|
||
上一步
|
||
</Button>
|
||
<Button type="primary" onClick={handleNext} className={style.nextBtn}>
|
||
下一步
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
);
|
||
|
||
// 步骤3:人群选择
|
||
const renderFriendSelection = () => (
|
||
<div className={style.formStep}>
|
||
<div className={style.formItem}>
|
||
<div className={style.formLabel}>选择微信好友</div>
|
||
<Input
|
||
placeholder="请选择微信好友"
|
||
value={formData.friends.join(", ")}
|
||
readOnly
|
||
onClick={() => message.info("这里应弹出好友选择器")}
|
||
className={style.input}
|
||
/>
|
||
{formData.friends.length > 0 && (
|
||
<div className={style.selectedTip}>
|
||
已选好友: {formData.friends.length}个
|
||
</div>
|
||
)}
|
||
</div>
|
||
<div className={style.formStepBtnRow}>
|
||
<Button onClick={handlePrev} className={style.prevBtn}>
|
||
上一步
|
||
</Button>
|
||
<Button
|
||
type="primary"
|
||
onClick={handleComplete}
|
||
loading={isSubmitting}
|
||
className={style.completeBtn}
|
||
>
|
||
{isEditMode ? "更新任务" : "创建任务"}
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
);
|
||
|
||
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 className={style.formBg}>
|
||
<div className={style.formSteps}>
|
||
{steps.map((s, i) => (
|
||
<div
|
||
key={s}
|
||
className={
|
||
style.formStepIndicator +
|
||
" " +
|
||
(i === currentStep
|
||
? style.formStepActive
|
||
: i < currentStep
|
||
? style.formStepDone
|
||
: "")
|
||
}
|
||
>
|
||
<span className={style.formStepNum}>
|
||
{i < currentStep ? <CheckOutlined /> : i + 1}
|
||
</span>
|
||
<span>{s}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
{isLoading ? (
|
||
<div className={style.formLoading}>
|
||
<Spin />
|
||
</div>
|
||
) : (
|
||
<>
|
||
{currentStep === 0 && renderBasicSettings()}
|
||
{currentStep === 1 && renderDeviceSelection()}
|
||
{currentStep === 2 && renderFriendSelection()}
|
||
</>
|
||
)}
|
||
</div>
|
||
</Layout>
|
||
);
|
||
};
|
||
|
||
export default NewAutoLike;
|