feat: 本次提交更新内容如下

旧项目抢救
This commit is contained in:
笔记本里的永平
2025-07-18 22:16:04 +08:00
parent 56a2f41aef
commit 77148dff3a
2 changed files with 130 additions and 81 deletions

View File

@@ -123,7 +123,7 @@ export default function MomentsSyncDetail() {
>
<ChevronLeft className="h-5 w-5" />
</Button>
<h1 className="text-lg font-medium"></h1>
<h1 className="text-lg font-medium"></h1>
</div>
<div className="flex items-center space-x-2">
<Button variant="outline" size="sm" onClick={handleEdit}>
@@ -138,7 +138,6 @@ export default function MomentsSyncDetail() {
</div>
</div>
}
footer={<BottomNav />}
>
<div className="bg-gray-50">
<div className="p-4 space-y-6">
@@ -172,12 +171,16 @@ export default function MomentsSyncDetail() {
<div className="flex items-center justify-between">
<span className="text-gray-600"></span>
<span className="font-medium">
{task.contentLib || "未设置"}
{task.config?.contentLibraries
.map((item: any) => item.name)
.join(",")}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-gray-600"></span>
<span className="font-medium">{task.syncCount} </span>
<span className="font-medium">
{task.config?.syncCount}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-gray-600"></span>

View File

@@ -1,14 +1,18 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Switch } from '@/components/ui/switch';
import { useToast } from '@/components/ui/toast';
import { createMomentsSyncTask, updateMomentsSyncTask, fetchMomentsSyncTaskDetail } from '@/api/momentsSync';
import { ChevronLeft } from 'lucide-react';
import { DeviceSelectionDialog } from '@/components/DeviceSelectionDialog';
import { ContentLibrarySelectionDialog } from '@/components/ContentLibrarySelectionDialog';
import { ContentType } from '@/types/moments-sync';
import React, { useState, useEffect, useCallback } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { useToast } from "@/components/ui/toast";
import {
createMomentsSyncTask,
updateMomentsSyncTask,
fetchMomentsSyncTaskDetail,
} from "@/api/momentsSync";
import { ChevronLeft } from "lucide-react";
import { DeviceSelectionDialog } from "@/components/DeviceSelectionDialog";
import { ContentLibrarySelectionDialog } from "@/components/ContentLibrarySelectionDialog";
import { ContentType } from "@/types/moments-sync";
// 步骤指示器组件
interface StepIndicatorProps {
@@ -25,36 +29,41 @@ function StepIndicator({ currentStep }: StepIndicatorProps) {
return (
<div className="relative flex justify-between px-6 mb-8">
{/* 连线 - 背景线 */}
<div className="absolute top-5 left-0 right-0 h-[1px] bg-gray-200" style={{ width: '100%', zIndex: 0 }} />
{/* 连线 - 已完成线 */}
<div
className="absolute top-5 left-0 h-[1px] bg-blue-600 transition-all duration-300"
style={{
width: `${((currentStep - 1) / (steps.length - 1)) * 100}%`,
zIndex: 1
}}
<div
className="absolute top-5 left-0 right-0 h-[1px] bg-gray-200"
style={{ width: "100%", zIndex: 0 }}
/>
{/* 连线 - 已完成线 */}
<div
className="absolute top-5 left-0 h-[1px] bg-blue-600 transition-all duration-300"
style={{
width: `${((currentStep - 1) / (steps.length - 1)) * 100}%`,
zIndex: 1,
}}
/>
{/* 步骤圆圈 */}
{steps.map((step, index) => (
<div key={step.id} className="flex flex-col items-center relative z-10">
<div
<div
className={`w-10 h-10 rounded-full flex items-center justify-center mb-2 ${
currentStep === index + 1
? "bg-blue-600 text-white"
currentStep === index + 1
? "bg-blue-600 text-white"
: index + 1 < currentStep
? "bg-blue-600 text-white"
: "bg-white text-gray-400 border border-gray-200"
? "bg-blue-600 text-white"
: "bg-white text-gray-400 border border-gray-200"
}`}
>
{index + 1}
</div>
<div className={`text-sm ${
currentStep === index + 1 || index + 1 < currentStep
? "text-blue-600"
: "text-gray-400"
}`}>
<div
className={`text-sm ${
currentStep === index + 1 || index + 1 < currentStep
? "text-blue-600"
: "text-gray-400"
}`}
>
{step.title}
</div>
</div>
@@ -70,18 +79,19 @@ export default function NewMomentsSyncTask() {
const [currentStep, setCurrentStep] = useState(1);
const [loading, setLoading] = useState(false);
const [deviceDialogOpen, setDeviceDialogOpen] = useState(false);
const [contentLibraryDialogOpen, setContentLibraryDialogOpen] = useState(false);
const [contentLibraryDialogOpen, setContentLibraryDialogOpen] =
useState(false);
const [formData, setFormData] = useState({
taskName: '',
startTime: '06:00',
endTime: '23:59',
taskName: "",
startTime: "06:00",
endTime: "23:59",
syncCount: 5,
interval: 30, // 同步间隔,单位:分钟
accountType: 'business' as 'business' | 'personal',
accountType: "business" as "business" | "personal",
enabled: true,
selectedDevices: [] as string[],
selectedLibraries: [] as string[],
contentTypes: ['text', 'image', 'video'] as ContentType[],
contentTypes: ["text", "image", "video"] as ContentType[],
targetTags: [] as string[],
filterKeywords: [] as string[],
});
@@ -109,21 +119,21 @@ export default function NewMomentsSyncTask() {
if (taskData) {
setFormData({
taskName: taskData.name,
startTime: taskData.timeRange?.start || '06:00',
endTime: taskData.timeRange?.end || '23:59',
syncCount: taskData.maxSyncPerDay || 5,
startTime: taskData.timeRange?.start || "06:00",
endTime: taskData.timeRange?.end || "23:59",
syncCount: taskData?.config?.syncCount || 0,
interval: taskData.syncInterval || 30,
accountType: taskData.syncMode === 'auto' ? 'business' : 'personal',
accountType: taskData.syncMode === "auto" ? "business" : "personal",
enabled: taskData.status === 1,
selectedDevices: taskData.devices || [],
selectedLibraries: taskData.contentLib ? [taskData.contentLib] : [],
contentTypes: taskData.contentTypes || ['text', 'image', 'video'],
contentTypes: taskData.contentTypes || ["text", "image", "video"],
targetTags: taskData.targetTags || [],
filterKeywords: taskData.filterKeywords || [],
});
}
} catch (error) {
toast({ title: '获取任务详情失败', variant: 'destructive' });
toast({ title: "获取任务详情失败", variant: "destructive" });
} finally {
setLoading(false);
}
@@ -137,15 +147,15 @@ export default function NewMomentsSyncTask() {
const handleComplete = async () => {
if (!formData.taskName.trim()) {
toast({ title: '请输入任务名称', variant: 'destructive' });
toast({ title: "请输入任务名称", variant: "destructive" });
return;
}
if (formData.selectedDevices.length === 0) {
toast({ title: '请选择设备', variant: 'destructive' });
toast({ title: "请选择设备", variant: "destructive" });
return;
}
if (formData.selectedLibraries.length === 0) {
toast({ title: '请选择内容库', variant: 'destructive' });
toast({ title: "请选择内容库", variant: "destructive" });
return;
}
@@ -157,10 +167,10 @@ export default function NewMomentsSyncTask() {
contentLibraries: formData.selectedLibraries,
syncInterval: formData.interval,
syncCount: formData.syncCount,
syncType: formData.accountType === 'business' ? 1 : 2,
syncType: formData.accountType === "business" ? 1 : 2,
startTime: formData.startTime,
endTime: formData.endTime,
accountType: formData.accountType === 'business' ? 1 : 2,
accountType: formData.accountType === "business" ? 1 : 2,
contentTypes: formData.contentTypes,
targetTags: formData.targetTags,
filterKeywords: formData.filterKeywords,
@@ -171,15 +181,18 @@ export default function NewMomentsSyncTask() {
id,
...taskData,
});
toast({ title: '更新成功' });
toast({ title: "更新成功" });
navigate(`/workspace/moments-sync/${id}`);
} else {
await createMomentsSyncTask(taskData);
toast({ title: '创建成功' });
navigate('/workspace/moments-sync');
toast({ title: "创建成功" });
navigate("/workspace/moments-sync");
}
} catch (error) {
toast({ title: isEditMode ? '更新失败' : '创建失败', variant: 'destructive' });
toast({
title: isEditMode ? "更新失败" : "创建失败",
variant: "destructive",
});
} finally {
setLoading(false);
}
@@ -202,8 +215,12 @@ export default function NewMomentsSyncTask() {
<div className="mb-6">
<div className="text-base font-medium mb-2"></div>
<div className="flex items-center">
<button
onClick={() => handleUpdateFormData({ syncCount: Math.max(1, formData.syncCount - 1) })}
<button
onClick={() =>
handleUpdateFormData({
syncCount: Math.max(1, formData.syncCount - 1),
})
}
className="w-12 h-12 rounded-lg bg-white border border-gray-200 flex items-center justify-center text-xl"
>
-
@@ -211,8 +228,10 @@ export default function NewMomentsSyncTask() {
<div className="flex-1 text-center text-lg font-medium">
{formData.syncCount}
</div>
<button
onClick={() => handleUpdateFormData({ syncCount: formData.syncCount + 1 })}
<button
onClick={() =>
handleUpdateFormData({ syncCount: formData.syncCount + 1 })
}
className="w-12 h-12 rounded-lg bg-white border border-gray-200 flex items-center justify-center text-xl"
>
+
@@ -224,8 +243,12 @@ export default function NewMomentsSyncTask() {
<div className="mb-6">
<div className="text-base font-medium mb-2"></div>
<div className="flex items-center">
<button
onClick={() => handleUpdateFormData({ interval: Math.max(1, formData.interval - 1) })}
<button
onClick={() =>
handleUpdateFormData({
interval: Math.max(1, formData.interval - 1),
})
}
className="w-12 h-12 rounded-lg bg-white border border-gray-200 flex items-center justify-center text-xl"
>
-
@@ -233,15 +256,19 @@ export default function NewMomentsSyncTask() {
<div className="flex-1 text-center text-lg font-medium">
{formData.interval}
</div>
<button
onClick={() => handleUpdateFormData({ interval: formData.interval + 1 })}
<button
onClick={() =>
handleUpdateFormData({ interval: formData.interval + 1 })
}
className="w-12 h-12 rounded-lg bg-white border border-gray-200 flex items-center justify-center text-xl"
>
+
</button>
<span className="ml-2 text-gray-500"></span>
</div>
<div className="text-xs text-gray-500 mt-1"></div>
<div className="text-xs text-gray-500 mt-1">
</div>
</div>
<div className="mb-6">
@@ -251,7 +278,9 @@ export default function NewMomentsSyncTask() {
<Input
type="time"
value={formData.startTime}
onChange={(e) => handleUpdateFormData({ startTime: e.target.value })}
onChange={(e) =>
handleUpdateFormData({ startTime: e.target.value })
}
className="h-12 rounded-lg border-gray-200 text-base"
/>
</div>
@@ -260,7 +289,9 @@ export default function NewMomentsSyncTask() {
<Input
type="time"
value={formData.endTime}
onChange={(e) => handleUpdateFormData({ endTime: e.target.value })}
onChange={(e) =>
handleUpdateFormData({ endTime: e.target.value })
}
className="h-12 rounded-lg border-gray-200 text-base"
/>
</div>
@@ -297,7 +328,9 @@ export default function NewMomentsSyncTask() {
<span className="text-base font-medium"></span>
<Switch
checked={formData.enabled}
onCheckedChange={(checked) => handleUpdateFormData({ enabled: checked })}
onCheckedChange={(checked) =>
handleUpdateFormData({ enabled: checked })
}
className="data-[state=checked]:bg-blue-600 h-7 w-12"
/>
</div>
@@ -316,7 +349,12 @@ export default function NewMomentsSyncTask() {
<div className="min-h-screen bg-gray-50">
<header className="sticky top-0 z-10 bg-white border-b">
<div className="flex items-center h-14 px-4">
<Button variant="ghost" size="icon" onClick={() => navigate(-1)} className="hover:bg-gray-50">
<Button
variant="ghost"
size="icon"
onClick={() => navigate(-1)}
className="hover:bg-gray-50"
>
<ChevronLeft className="h-6 w-6" />
</Button>
<h1 className="ml-2 text-lg font-medium"></h1>
@@ -327,7 +365,7 @@ export default function NewMomentsSyncTask() {
<StepIndicator currentStep={currentStep} />
{currentStep === 1 && renderBasicSettings()}
{currentStep === 2 && (
<div className="px-4 space-y-6">
<Input
@@ -336,15 +374,19 @@ export default function NewMomentsSyncTask() {
onClick={() => setDeviceDialogOpen(true)}
readOnly
/>
{formData.selectedDevices.length > 0 && (
<div className="text-base text-gray-500">
{formData.selectedDevices.length}
</div>
)}
<div className="flex space-x-4 pt-4">
<Button variant="outline" onClick={handlePrev} className="flex-1 h-12 rounded-lg">
<Button
variant="outline"
onClick={handlePrev}
className="flex-1 h-12 rounded-lg"
>
</Button>
<Button
@@ -354,7 +396,7 @@ export default function NewMomentsSyncTask() {
</Button>
</div>
<DeviceSelectionDialog
open={deviceDialogOpen}
onOpenChange={setDeviceDialogOpen}
@@ -365,7 +407,7 @@ export default function NewMomentsSyncTask() {
/>
</div>
)}
{currentStep === 3 && (
<div className="px-4 space-y-6">
<Input
@@ -374,15 +416,19 @@ export default function NewMomentsSyncTask() {
onClick={() => setContentLibraryDialogOpen(true)}
readOnly
/>
{formData.selectedLibraries.length > 0 && (
<div className="text-base text-gray-500">
{formData.selectedLibraries.length}
</div>
)}
<div className="flex space-x-4 pt-4">
<Button variant="outline" onClick={handlePrev} className="flex-1 h-12 rounded-lg">
<Button
variant="outline"
onClick={handlePrev}
className="flex-1 h-12 rounded-lg"
>
</Button>
<Button
@@ -390,10 +436,10 @@ export default function NewMomentsSyncTask() {
loading={loading}
className="flex-1 h-12 bg-blue-500 hover:bg-blue-600 rounded-lg text-white"
>
{loading ? '创建中...' : '完成'}
{loading ? "创建中..." : "完成"}
</Button>
</div>
<ContentLibrarySelectionDialog
open={contentLibraryDialogOpen}
onOpenChange={setContentLibraryDialogOpen}
@@ -407,4 +453,4 @@ export default function NewMomentsSyncTask() {
</div>
</div>
);
}
}