FEAT => 本次更新项目为:

内容库处理完成
This commit is contained in:
超级老白兔
2025-08-07 18:21:35 +08:00
parent 504e8ff9b6
commit bb06d3e4f8
9 changed files with 84 additions and 120 deletions

View File

@@ -0,0 +1,21 @@
// 内容库接口类型
export interface ContentItem {
id: number;
name: string;
[key: string]: any;
}
// 组件属性接口
export interface ContentSelectionProps {
selectedContent: ContentItem[];
onSelect: (selectedItems: ContentItem[]) => void;
placeholder?: string;
className?: string;
visible?: boolean;
onVisibleChange?: (visible: boolean) => void;
selectedListMaxHeight?: number;
showInput?: boolean;
showSelectedList?: boolean;
readonly?: boolean;
onConfirm?: (selectedItems: ContentItem[]) => void;
}

View File

@@ -7,17 +7,7 @@ import Layout from "@/components/Layout/Layout";
import PopupHeader from "@/components/PopuLayout/header";
import PopupFooter from "@/components/PopuLayout/footer";
import { getContentLibraryList } from "./api";
// 内容库接口类型
interface ContentLibraryItem {
id: string;
name: string;
description?: string;
sourceType?: number; // 1=文本 2=图片 3=视频
creatorName?: string;
updateTime?: string;
[key: string]: any;
}
import { ContentItem, ContentSelectionProps } from "./data";
// 类型标签文本
const getTypeText = (type?: number) => {
@@ -43,29 +33,9 @@ const formatDate = (dateStr?: string) => {
.padStart(2, "0")}`;
};
// 组件属性接口
interface ContentLibrarySelectionProps {
selectedLibraries: (string | number)[];
onSelect: (libraries: string[]) => void;
onSelectDetail?: (libraries: ContentLibraryItem[]) => void;
placeholder?: string;
className?: string;
visible?: boolean;
onVisibleChange?: (visible: boolean) => void;
selectedListMaxHeight?: number;
showInput?: boolean;
showSelectedList?: boolean;
readonly?: boolean;
onConfirm?: (
selectedIds: string[],
selectedItems: ContentLibraryItem[],
) => void;
}
export default function ContentLibrarySelection({
selectedLibraries,
export default function ContentSelection({
selectedContent,
onSelect,
onSelectDetail,
placeholder = "选择内容库",
className = "",
visible,
@@ -75,24 +45,19 @@ export default function ContentLibrarySelection({
showSelectedList = true,
readonly = false,
onConfirm,
}: ContentLibrarySelectionProps) {
}: ContentSelectionProps) {
const [popupVisible, setPopupVisible] = useState(false);
const [libraries, setLibraries] = useState<ContentLibraryItem[]>([]);
const [libraries, setLibraries] = useState<ContentItem[]>([]);
const [searchQuery, setSearchQuery] = useState("");
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [totalLibraries, setTotalLibraries] = useState(0);
const [loading, setLoading] = useState(false);
// 获取已选内容库详细信息
const selectedLibraryObjs = libraries.filter(item =>
selectedLibraries.includes(item.id),
);
// 删除已选内容库
const handleRemoveLibrary = (id: string) => {
const handleRemoveLibrary = (id: number) => {
if (readonly) return;
onSelect(selectedLibraries.filter(g => g !== id));
onSelect(selectedContent.filter(c => c.id !== id));
};
// 受控弹窗逻辑
@@ -153,30 +118,24 @@ export default function ContentLibrarySelection({
};
// 处理内容库选择
const handleLibraryToggle = (libraryId: string) => {
const handleLibraryToggle = (library: ContentItem) => {
if (readonly) return;
const newSelected = selectedLibraries.includes(libraryId)
? selectedLibraries.filter(id => id !== libraryId)
: [...selectedLibraries, libraryId];
const newSelected = selectedContent.some(c => c.id === library.id)
? selectedContent.filter(c => c.id !== library.id)
: [...selectedContent, library];
onSelect(newSelected);
if (onSelectDetail) {
const selectedObjs = libraries.filter(item =>
newSelected.includes(item.id),
);
onSelectDetail(selectedObjs);
}
};
// 获取显示文本
const getDisplayText = () => {
if (selectedLibraries.length === 0) return "";
return `已选择 ${selectedLibraries.length} 个内容库`;
if (selectedContent.length === 0) return "";
return `已选择 ${selectedContent.length} 个内容库`;
};
// 确认选择
const handleConfirm = () => {
if (onConfirm) {
onConfirm(selectedLibraries, selectedLibraryObjs);
onConfirm(selectedContent);
}
setRealVisible(false);
};
@@ -202,7 +161,7 @@ export default function ContentLibrarySelection({
</div>
)}
{/* 已选内容库列表窗口 */}
{showSelectedList && selectedLibraryObjs.length > 0 && (
{showSelectedList && selectedContent.length > 0 && (
<div
className={style.selectedListWindow}
style={{
@@ -214,7 +173,7 @@ export default function ContentLibrarySelection({
background: "#fff",
}}
>
{selectedLibraryObjs.map(item => (
{selectedContent.map(item => (
<div
key={item.id}
className={style.selectedListRow}
@@ -284,7 +243,7 @@ export default function ContentLibrarySelection({
currentPage={currentPage}
totalPages={totalPages}
loading={loading}
selectedCount={selectedLibraries.length}
selectedCount={selectedContent.length}
onPageChange={setCurrentPage}
onCancel={() => setRealVisible(false)}
onConfirm={handleConfirm}
@@ -301,8 +260,8 @@ export default function ContentLibrarySelection({
{libraries.map(item => (
<label key={item.id} className={style.libraryItem}>
<Checkbox
checked={selectedLibraries.includes(item.id)}
onChange={() => !readonly && handleLibraryToggle(item.id)}
checked={selectedContent.map(c => c.id).includes(item.id)}
onChange={() => !readonly && handleLibraryToggle(item)}
disabled={readonly}
className={style.checkboxWrapper}
/>

View File

@@ -5,11 +5,11 @@ import NavCommon from "@/components/NavCommon";
import DeviceSelection from "@/components/DeviceSelection";
import FriendSelection from "@/components/FriendSelection";
import GroupSelection from "@/components/GroupSelection";
import ContentLibrarySelection from "@/components/ContentLibrarySelection";
import ContentSelection from "@/components/ContentSelection";
import AccountSelection from "@/components/AccountSelection";
import { isDevelopment } from "@/utils/env";
import { GroupSelectionItem } from "@/components/GroupSelection/data";
import { ContentItem } from "@/components/ContentSelection/data";
const ComponentTest: React.FC = () => {
const [activeTab, setActiveTab] = useState("libraries");
@@ -25,7 +25,7 @@ const ComponentTest: React.FC = () => {
);
// 内容库选择状态
const [selectedLibraries, setSelectedLibraries] = useState<string[]>([]);
const [selectedContent, setSelectedContent] = useState<ContentItem[]>([]);
const [selectedAccounts, setSelectedAccounts] = useState<number[]>([]);
@@ -43,12 +43,10 @@ const ComponentTest: React.FC = () => {
<Tabs activeKey={activeTab} onChange={setActiveTab}>
<Tabs.Tab title="内容库选择" key="libraries">
<div style={{ padding: "16px 0" }}>
<h3 style={{ marginBottom: 16 }}>
ContentLibrarySelection
</h3>
<ContentLibrarySelection
selectedLibraries={selectedLibraries}
onSelect={setSelectedLibraries}
<h3 style={{ marginBottom: 16 }}>ContentSelection </h3>
<ContentSelection
selectedContent={selectedContent}
onSelect={setSelectedContent}
placeholder="请选择内容库"
showSelectedList={true}
selectedListMaxHeight={300}
@@ -61,10 +59,10 @@ const ComponentTest: React.FC = () => {
borderRadius: 8,
}}
>
<strong>:</strong> {selectedLibraries.length}
<strong>:</strong> {selectedContent.length}
<br />
<strong>ID:</strong>{" "}
{selectedLibraries.join(", ") || "无"}
{selectedContent.map(c => c.id).join(", ") || "无"}
</div>
</div>
</Tabs.Tab>

View File

@@ -1,23 +1,15 @@
import React, { useImperativeHandle, forwardRef } from "react";
import { Form, Card } from "antd";
import ContentLibrarySelection from "@/components/ContentLibrarySelection";
interface ContentLibrary {
id: string;
name: string;
targets: Array<{
id: string;
avatar: string;
}>;
}
import ContentSelection from "@/components/ContentSelection";
import { ContentItem } from "@/components/ContentSelection/data";
interface ContentSelectorProps {
selectedLibraries: ContentLibrary[];
onLibrariesChange: (libraries: ContentLibrary[]) => void;
selectedContent: ContentItem[];
onPrevious: () => void;
onNext: () => void;
onSave: () => void;
loading?: boolean;
onNext: (data: {
contentGroups: string[];
contentGroupsOptions: ContentItem[];
}) => void;
}
export interface ContentSelectorRef {
@@ -26,17 +18,7 @@ export interface ContentSelectorRef {
}
const ContentSelector = forwardRef<ContentSelectorRef, ContentSelectorProps>(
(
{
selectedLibraries,
onLibrariesChange,
onPrevious,
onNext,
onSave,
loading = false,
},
ref,
) => {
({ selectedContent, onNext }, ref) => {
const [form] = Form.useForm();
// 暴露方法给父组件
@@ -55,20 +37,17 @@ const ContentSelector = forwardRef<ContentSelectorRef, ContentSelectorProps>(
},
}));
// 将 ContentLibrary[] 转换为 string[] 用于 ContentLibrarySelection
const selectedLibraryIds = selectedLibraries.map(lib => lib.id);
// 处理选择变化
const handleLibrariesChange = (libraryIds: string[]) => {
// 这里需要根据选中的ID重新构建ContentLibrary对象
// 由于ContentLibrarySelection只返回ID我们需要从原始数据中获取完整信息
// 暂时使用简化的处理方式
const newSelectedLibraries = libraryIds.map(id => ({
const handleLibrariesChange = (contentGroups: string[]) => {
const newSelectedLibraries = contentGroups.map(id => ({
id,
name: `内容库 ${id}`, // 这里应该从API获取完整信息
targets: [], // 这里应该从API获取完整信息
}));
onLibrariesChange(newSelectedLibraries);
onNext({
contentGroups: libraryIds,
contentGroupsOptions: newSelectedLibraries,
});
form.setFieldValue("contentLibraries", libraryIds);
};
@@ -80,7 +59,7 @@ const ContentSelector = forwardRef<ContentSelectorRef, ContentSelectorProps>(
name: lib.name,
targets: [], // 这里需要根据实际情况获取targets数据
}));
onLibrariesChange(convertedLibraries);
onNext(convertedLibraries);
form.setFieldValue(
"contentLibraries",
libraries.map(lib => lib.id),
@@ -112,8 +91,8 @@ const ContentSelector = forwardRef<ContentSelectorRef, ContentSelectorProps>(
{ type: "array", max: 20, message: "最多只能选择20个内容库" },
]}
>
<ContentLibrarySelection
selectedLibraries={selectedLibraryIds}
<ContentSelection
selectedLibraries={selectedContent}
onSelect={handleLibrariesChange}
onSelectDetail={handleSelectDetail}
placeholder="选择内容库"

View File

@@ -1,3 +1,4 @@
import { ContentItem } from "@/components/ContentSelection/data";
export interface WechatGroup {
id: string;
name: string;
@@ -27,7 +28,7 @@ export interface FormData {
isLoopPush: boolean;
isImmediatePush: boolean;
isEnabled: boolean;
contentLibraries: ContentLibrary[];
contentGroups: string[];
wechatGroups: string[];
[key: string]: any;
}

View File

@@ -12,6 +12,7 @@ import ContentSelector, {
import type { ContentLibrary, FormData } from "./index.data";
import NavCommon from "@/components/NavCommon";
import { GroupSelectionItem } from "@/components/GroupSelection/data";
import { ContentItem } from "@/components/ContentSelection/data";
const steps = [
{ id: 1, title: "步骤 1", subtitle: "基础设置" },
{ id: 2, title: "步骤 2", subtitle: "选择社群" },
@@ -27,6 +28,10 @@ const NewGroupPush: React.FC = () => {
const [wechatGroupsOptions, setWechatGroupsOptions] = useState<
GroupSelectionItem[]
>([]);
const [contentGroupsOptions, setContentGroupsOptions] = useState<
ContentItem[]
>([]);
const [formData, setFormData] = useState<FormData>({
name: "",
pushTimeStart: "06:00",
@@ -37,7 +42,7 @@ const NewGroupPush: React.FC = () => {
isImmediatePush: false,
isEnabled: false,
wechatGroups: [],
contentLibraries: [],
contentGroups: [],
});
const [isEditMode, setIsEditMode] = useState(false);
@@ -66,9 +71,13 @@ const NewGroupPush: React.FC = () => {
}));
setWechatGroupsOptions(data.wechatGroupsOptions);
};
const handleLibrariesChange = (contentLibraries: ContentLibrary[]) => {
setFormData(prev => ({ ...prev, contentLibraries }));
//内容库选择
const handleLibrariesChange = (data: {
contentGroups: string[];
contentGroupsOptions: ContentItem[];
}) => {
setFormData(prev => ({ ...prev, contentGroups: data.contentGroups }));
setContentGroupsOptions(data.contentGroupsOptions);
};
const handleSave = async () => {
@@ -230,12 +239,9 @@ const NewGroupPush: React.FC = () => {
{currentStep === 3 && (
<ContentSelector
ref={contentSelectorRef}
selectedLibraries={formData.contentLibraries}
onLibrariesChange={handleLibrariesChange}
selectedContent={contentGroupsOptions}
onPrevious={() => setCurrentStep(2)}
onNext={() => setCurrentStep(4)}
onSave={handleSave}
loading={loading}
onNext={handleLibrariesChange}
/>
)}
{currentStep === 4 && (

View File

@@ -13,7 +13,7 @@ import {
getMomentsSyncDetail,
} from "./api";
import DeviceSelection from "@/components/DeviceSelection";
import ContentLibrarySelection from "@/components/ContentLibrarySelection";
import ContentLibrarySelection from "@/components/ContentSelection";
import NavCommon from "@/components/NavCommon";
const steps = [