feat: 暂时可以了

This commit is contained in:
许永平
2025-07-09 19:13:23 +08:00
parent d78698aa6b
commit c75b8d596d
10 changed files with 518 additions and 521 deletions

View File

@@ -12,20 +12,16 @@ import { ScrollArea } from '@/components/ui/scroll-area';
import { Checkbox } from '@/components/ui/checkbox';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { createAutoLikeTask, updateAutoLikeTask, fetchAutoLikeTaskDetail } from '@/api/autoLike';
import { ContentType } from '@/types/auto-like';
import { useToast } from '@/components/ui/toast';
import Layout from '@/components/Layout';
import { fetchDeviceList } from '@/api/devices';
import type { Device } from '@/types/device';
import { get } from '@/api/request';
interface TagGroup {
id: string;
name: string;
tags: string[];
}
// 用于设备选择弹窗的简化设备类型
interface DeviceSelectionItem {
@@ -177,7 +173,7 @@ export default function NewAutoLike() {
// 处理状态字段,使用双等号允许类型自动转换
const status = taskAny.status;
setAutoEnabled(status == 1 || status == 'running');
setAutoEnabled(status === 1 || status === 'running');
} else {
toast({
title: '获取任务详情失败',
@@ -199,44 +195,7 @@ export default function NewAutoLike() {
}
};
// 标签组数据
const [tagGroups] = useState<TagGroup[]>([
{
id: 'intention',
name: '意向度',
tags: ['高意向', '中意向', '低意向'],
},
{
id: 'customer',
name: '客户类型',
tags: ['新客户', '老客户', 'VIP客户'],
},
{
id: 'gender',
name: '性别',
tags: ['男性', '女性'],
},
{
id: 'age',
name: '年龄段',
tags: ['年轻人', '中年人', '老年人'],
},
{
id: 'location',
name: '地区',
tags: ['城市', '农村'],
},
{
id: 'income',
name: '收入',
tags: ['高收入', '中等收入', '低收入'],
},
{
id: 'interaction',
name: '互动频率',
tags: ['高频互动', '中频互动', '低频互动'],
},
]);
const handleUpdateFormData = (data: Partial<CreateLikeTaskDataLocal>) => {
setFormData((prev) => ({ ...prev, ...data }));
@@ -827,203 +786,7 @@ function DeviceSelectionDialog({ open, onOpenChange, selectedDevices, onSelect,
);
}
// 标签选择器组件
interface TagSelectorProps {
selectedTags: string[];
tagOperator: 'and' | 'or';
onTagsChange: (tags: string[]) => void;
onOperatorChange: (operator: 'and' | 'or') => void;
onBack: () => void;
onComplete: () => void;
tagGroups: TagGroup[];
}
function TagSelector({
selectedTags,
tagOperator,
onTagsChange,
onOperatorChange,
onBack,
onComplete,
tagGroups,
}: TagSelectorProps) {
const [searchQuery, setSearchQuery] = useState('');
const [customTag, setCustomTag] = useState('');
const toggleTag = (tag: string) => {
if (selectedTags.includes(tag)) {
onTagsChange(selectedTags.filter((t) => t !== tag));
} else {
onTagsChange([...selectedTags, tag]);
}
};
const addCustomTag = () => {
if (customTag.trim() && !selectedTags.includes(customTag.trim())) {
onTagsChange([...selectedTags, customTag.trim()]);
setCustomTag('');
}
};
const removeTag = (tag: string) => {
onTagsChange(selectedTags.filter((t) => t !== tag));
};
const filteredTagGroups = tagGroups
.map((group) => ({
...group,
tags: group.tags.filter((tag) => tag.toLowerCase().includes(searchQuery.toLowerCase())),
}))
.filter((group) => group.tags.length > 0);
return (
<Card className="mb-6">
<CardContent className="pt-6">
<div className="space-y-6">
<div>
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-medium"></h3>
</div>
<div className="relative mb-4">
<Search className="absolute left-3 top-2.5 h-4 w-4 text-gray-400" />
<Input
placeholder="搜索标签"
className="pl-9"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<Tabs defaultValue="intention" className="mb-6">
<TabsList className="grid grid-cols-4 mb-4">
{tagGroups.slice(0, 4).map((group) => (
<TabsTrigger key={group.id} value={group.id}>
{group.name}
</TabsTrigger>
))}
</TabsList>
{tagGroups.map((group) => (
<TabsContent key={group.id} value={group.id} className="mt-0">
<div className="flex flex-wrap gap-2">
{group.tags.map((tag) => (
<Badge
key={tag}
variant={selectedTags.includes(tag) ? 'default' : 'outline'}
className="cursor-pointer py-1 px-3"
onClick={() => toggleTag(tag)}
>
{selectedTags.includes(tag) && <Check className="h-3 w-3 mr-1" />}
{tag}
</Badge>
))}
</div>
</TabsContent>
))}
</Tabs>
<ScrollArea className="h-48 border rounded-md p-4 mb-4">
<div className="space-y-4">
{filteredTagGroups.length > 0 ? (
filteredTagGroups.map((group) => (
<div key={group.id} className="space-y-2">
<h4 className="text-sm font-medium text-gray-500">{group.name}</h4>
<div className="flex flex-wrap gap-2">
{group.tags.map((tag) => (
<div key={tag} className="flex items-center space-x-2">
<Checkbox
id={`tag-${tag}`}
checked={selectedTags.includes(tag)}
onCheckedChange={() => toggleTag(tag)}
/>
<Label htmlFor={`tag-${tag}`} className="text-sm font-normal">
{tag}
</Label>
</div>
))}
</div>
</div>
))
) : (
<div className="text-center text-gray-500"></div>
)}
</div>
</ScrollArea>
<div className="flex space-x-2 mt-2">
<div className="relative flex-1">
<TagIcon className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
value={customTag}
onChange={(e) => setCustomTag(e.target.value)}
className="pl-9"
placeholder="添加自定义标签"
onKeyDown={(e) => e.key === 'Enter' && addCustomTag()}
/>
</div>
<Button onClick={addCustomTag} disabled={!customTag.trim()}>
</Button>
</div>
</div>
<div className="space-y-2">
<h3 className="text-base font-medium"></h3>
<p className="text-sm text-muted-foreground mb-2"></p>
<RadioGroup
value={tagOperator}
onValueChange={(value: string) => onOperatorChange(value as 'and' | 'or')}
className="flex flex-col space-y-2"
>
<div className="flex items-center space-x-2">
<RadioGroupItem value="and" id="and-operator" />
<Label htmlFor="and-operator" className="font-normal">
AND
</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="or" id="or-operator" />
<Label htmlFor="or-operator" className="font-normal">
OR
</Label>
</div>
</RadioGroup>
</div>
<div>
<h3 className="text-base font-medium mb-2"></h3>
<div className="min-h-[60px] border rounded-md p-3">
{selectedTags.length === 0 ? (
<p className="text-sm text-muted-foreground"></p>
) : (
<div className="flex flex-wrap gap-2">
{selectedTags.map((tag) => (
<Badge key={tag} className="flex items-center gap-1 py-1 px-2">
{tag}
<Button variant="ghost" size="icon" className="h-4 w-4 p-0 ml-1" onClick={() => removeTag(tag)}>
<X className="h-3 w-3" />
</Button>
</Badge>
))}
</div>
)}
</div>
</div>
<div className="flex justify-between space-x-4">
<Button variant="outline" className="flex-1" onClick={onBack}>
</Button>
<Button className="flex-1" onClick={onComplete} disabled={selectedTags.length === 0}>
</Button>
</div>
</div>
</CardContent>
</Card>
);
}
// 微信好友选择弹窗组件
interface FriendSelectionDialogProps {
@@ -1096,27 +859,7 @@ function FriendSelectionDialog({ open, onOpenChange, selectedFriends = [], onSel
}
};
const handleSelectAll = () => {
// 选择当前页面上所有好友
const currentPageIds = filteredFriends.map(friend => friend.id);
const newSelectedFriends = [...selectedFriends];
// 添加未选中的好友
currentPageIds.forEach(id => {
if (!selectedFriends.includes(id)) {
newSelectedFriends.push(id);
}
});
onSelect(newSelectedFriends);
};
const handleUnselectAll = () => {
// 取消当前页面上所有好友的选择
const currentPageIds = filteredFriends.map(friend => friend.id);
const newSelectedFriends = selectedFriends.filter(id => !currentPageIds.includes(id));
onSelect(newSelectedFriends);
};
const handleConfirm = () => {
onOpenChange(false);