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

View File

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

View File

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

View File

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

View File

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

View File

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