feat(P1): 素材库改名为视频库 + 配音素材库改配音库 #556

Merged
auto-approve-bot merged 1 commits from feat/rename-asset-to-video-library into develop 2026-07-19 07:14:30 +08:00
12 changed files with 57 additions and 57 deletions
+1 -1
View File
@@ -130,7 +130,7 @@ export interface SaveTtsToLibraryRequest {
tag_ids?: string[]
}
/** 将 TTS 合成结果保存到配音素材库 */
/** 将 TTS 合成结果保存到配音库 */
export const saveTtsToLibrary = async (
jobId: string,
data?: SaveTtsToLibraryRequest,
+2 -2
View File
@@ -44,7 +44,7 @@ export interface PageHeadProps {
const ROUTE_TITLE_MAP: Record<string, string> = {
"/app/dashboard": "首页",
"/app/generate": "一键生成",
"/app/assets": "素材库",
"/app/assets": "视频库",
"/app/voices": "配音库",
"/app/titles": "标题库",
"/app/products": "成片库",
@@ -62,7 +62,7 @@ const ROUTE_TITLE_MAP: Record<string, string> = {
"/app/editing-planner": "剪辑规划",
"/app/my-templates": "我的模板",
"/app/voice-clone": "我的音色",
"/app/voice-materials": "配音素材库",
"/app/voice-materials": "配音库",
"/app/accounts": "账号管理",
"/app/duplication": "查重",
"/app/duplication/results": "查重结果",
+2 -2
View File
@@ -47,7 +47,7 @@ export const NAV_ITEMS: NavItem[] = [
},
{
key: "assets",
label: "素材库",
label: "视频库",
path: "/app/assets",
icon: React.createElement(FileOutlined),
},
@@ -155,7 +155,7 @@ export const NAV_GROUPS: NavGroup[] = [
items: [
{
key: "assets",
label: "素材库",
label: "视频库",
path: "/app/assets",
icon: React.createElement(FileOutlined),
},
+23 -23
View File
@@ -1,6 +1,6 @@
/**
* 素材库页面 — V21 设计系统
* 两栏布局:左侧素材库列表(260px+ 右侧素材网格
* 视频库页面 — V21 设计系统
* 两栏布局:左侧视频库列表(260px+ 右侧素材网格
* 使用 useQuery 对接后端真实 APIapi/assets.ts
*/
import React, { useMemo, useState } from "react"
@@ -350,7 +350,7 @@ const AssetCard: React.FC<{
const AssetLibrary: React.FC = () => {
const queryClient = useQueryClient()
/* ── 获取素材库列表 ── */
/* ── 获取视频库列表 ── */
const { data: apiLibraries = [], isLoading: libLoading } = useQuery<AssetLibraryItem[], Error>({
queryKey: ["asset-libraries"],
queryFn: getAssetLibraries,
@@ -362,7 +362,7 @@ const AssetLibrary: React.FC = () => {
[apiLibraries],
)
/* ── 当前选中的素材库 ── */
/* ── 当前选中的视频库 ── */
const [activeLibId, setActiveLibId] = useState<string>("")
// 当库列表加载完成后,自动选中第一个
@@ -396,10 +396,10 @@ const AssetLibrary: React.FC = () => {
mutationFn: createAssetLibrary,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["asset-libraries"] })
message.success("素材库创建成功")
message.success("视频库创建成功")
},
onError: () => {
message.error("创建素材库失败")
message.error("创建视频库失败")
},
})
@@ -407,10 +407,10 @@ const AssetLibrary: React.FC = () => {
mutationFn: deleteAssetLibrary,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["asset-libraries"] })
message.success("素材库已删除")
message.success("视频库已删除")
},
onError: () => {
message.error("删除素材库失败")
message.error("删除视频库失败")
},
})
@@ -428,7 +428,7 @@ const AssetLibrary: React.FC = () => {
const [uploading, setUploading] = useState(false)
const [uploadProgress, setUploadProgress] = useState(0)
/* 新建素材库 */
/* 新建视频库 */
const [createModalOpen, setCreateModalOpen] = useState(false)
const [newLibName, setNewLibName] = useState("")
const [newLibKind, setNewLibKind] = useState<AssetKind>("video")
@@ -469,7 +469,7 @@ const AssetLibrary: React.FC = () => {
const filteredAssets = useMemo(() => {
let list = assets
/* 按素材库类型过滤(如果筛选类型不是 all) */
/* 按视频库类型过滤(如果筛选类型不是 all) */
if (filterType !== "all") {
list = list.filter((a) => a.kind === filterType)
}
@@ -521,7 +521,7 @@ const AssetLibrary: React.FC = () => {
return
}
if (!effectiveLibId) {
message.warning("请先选择或创建一个素材库")
message.warning("请先选择或创建一个视频库")
return
}
@@ -551,10 +551,10 @@ const AssetLibrary: React.FC = () => {
}
}
/* 新建素材库 */
/* 新建视频库 */
const handleCreateLibrary = async () => {
if (!newLibName.trim()) {
message.warning("请输入素材库名称")
message.warning("请输入视频库名称")
return
}
try {
@@ -571,7 +571,7 @@ const AssetLibrary: React.FC = () => {
}
}
/* 删除素材库 */
/* 删除视频库 */
const handleDeleteLibrary = async (id: string) => {
try {
await deleteLibMutation.mutateAsync(id)
@@ -827,7 +827,7 @@ const AssetLibrary: React.FC = () => {
{/* 两栏布局 */}
<div className="xx-assets-layout">
{/* ─── 左侧:素材库列表 ─── */}
{/* ─── 左侧:视频库列表 ─── */}
<div className="xx-asset-library-list">
{libraries.map((lib) => (
<div
@@ -840,7 +840,7 @@ const AssetLibrary: React.FC = () => {
{kindIcon(lib.kind)} {lib.name}
</h4>
<Popconfirm
title={`确定删除素材库 "${lib.name}"`}
title={`确定删除视频库 "${lib.name}"`}
onConfirm={(e) => {
e?.stopPropagation()
handleDeleteLibrary(lib.id)
@@ -852,7 +852,7 @@ const AssetLibrary: React.FC = () => {
<button
className="xx-asset-library-delete"
onClick={(e) => e.stopPropagation()}
title="删除素材库"
title="删除视频库"
>
<DeleteOutlined />
</button>
@@ -864,10 +864,10 @@ const AssetLibrary: React.FC = () => {
</div>
))}
{/* 新建素材库 */}
{/* 新建视频库 */}
<div className="xx-asset-library-add" onClick={() => setCreateModalOpen(true)}>
<PlusOutlined />
</div>
</div>
@@ -1018,15 +1018,15 @@ const AssetLibrary: React.FC = () => {
<div className="xx-assets-empty-icon">
<PictureOutlined />
</div>
<p className="xx-assets-empty-title"></p>
<p className="xx-assets-empty-title"></p>
</div>
)}
</div>
</div>
{/* ─── 新建素材库弹窗 ─── */}
{/* ─── 新建视频库弹窗 ─── */}
<AntModal
title="新建素材库"
title="新建视频库"
open={createModalOpen}
onCancel={() => setCreateModalOpen(false)}
onOk={handleCreateLibrary}
@@ -1039,7 +1039,7 @@ const AssetLibrary: React.FC = () => {
<div>
<div className="xx-asset-form-label"></div>
<Input
placeholder="请输入素材库名称"
placeholder="请输入视频库名称"
value={newLibName}
onChange={(e) => setNewLibName(e.target.value)}
maxLength={50}
+3 -3
View File
@@ -1,6 +1,6 @@
/**
* 素材库页面 - V21 设计系统样式
* 两栏布局:左侧素材库列表(260px+ 右侧素材网格
* 视频库页面 - V21 设计系统样式
* 两栏布局:左侧视频库列表(260px+ 右侧素材网格
* 统一使用 CSS 变量,支持深色/浅色主题
*/
@import "../../styles/global.css";
@@ -24,7 +24,7 @@
}
/* ============================================================
左侧素材库列表
左侧视频库列表
============================================================ */
.xx-asset-library-list {
display: flex;
+1 -1
View File
@@ -203,7 +203,7 @@ const DuplicationUpload: React.FC = () => {
<div className="dup-info-card">
<h3>📋 </h3>
<ul className="dup-info-list">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
+2 -2
View File
@@ -560,7 +560,7 @@ const PlanClipsManager: React.FC = () => {
{/* 素材导入抽屉 */}
<Drawer
title="从素材库导入"
title="从视频库导入"
open={importDrawerOpen}
onClose={() => setImportDrawerOpen(false)}
width={480}
@@ -611,7 +611,7 @@ const PlanClipsManager: React.FC = () => {
))}
</div>
) : (
<Empty description="素材库为空" />
<Empty description="视频库为空" />
)}
</Drawer>
</div>
@@ -47,7 +47,7 @@ interface ClipPropertiesPanelProps {
onOpenBgmDrawer?: () => void
/** 打开字幕样式配置 Drawer */
onOpenSubtitleDrawer?: () => void
/** 配音素材列表(从配音素材库 API 获取) */
/** 配音素材列表(从配音库 API 获取) */
voiceMaterials?: AssetItem[]
/** 配音素材加载中 */
voiceMaterialsLoading?: boolean
@@ -313,7 +313,7 @@ const TtsPanel: React.FC<TtsPanelProps> = ({ open, onClose, config, onChange })
{config.mode === "upload" && (
<div className="tts-upload-hint">
<p></p>
<p></p>
<p></p>
</div>
)}
+13 -13
View File
@@ -245,7 +245,7 @@ const GeneratePage: React.FC = () => {
})
const [selectedLibraryId, setSelectedLibraryId] = useState<string>("")
// 自动选中第一个素材
// 自动选中第一个视频
useEffect(() => {
if (libraries.length > 0 && !selectedLibraryId) {
setSelectedLibraryId(libraries[0].id)
@@ -373,7 +373,7 @@ const GeneratePage: React.FC = () => {
message.success({
content: (
<span>
{" "}
{" "}
<a
onClick={handleGoToLibrary}
style={{
@@ -381,7 +381,7 @@ const GeneratePage: React.FC = () => {
cursor: "pointer",
}}
>
</a>
</span>
),
@@ -440,7 +440,7 @@ const GeneratePage: React.FC = () => {
[allTags, saveTagIds],
)
/** 保存成功后跳转到素材库 */
/** 保存成功后跳转到视频库 */
const handleGoToLibrary = useCallback(() => {
navigate("/app/voice-materials")
}, [navigate])
@@ -654,7 +654,7 @@ const GeneratePage: React.FC = () => {
return "所选模板或素材不可用,请重新选择"
}
if (msg.includes("asset") && (msg.includes("not found") || msg.includes("missing"))) {
return "素材数据异常,请返回素材库重新检查"
return "素材数据异常,请返回视频库重新检查"
}
// 网络/超时
if (msg.includes("timeout") || msg.includes("network") || msg.includes("ECONN")) {
@@ -861,13 +861,13 @@ const GeneratePage: React.FC = () => {
onClick={() => setMaterialMode("auto")}
type="button"
>
</button>
</div>
{/* ── 素材库选择(两种模式共用) ── */}
{/* ── 视频库选择(两种模式共用) ── */}
<div className="xx-form-field" style={{ marginTop: 12 }}>
<label></label>
<label></label>
<select value={selectedLibraryId} onChange={(e) => setSelectedLibraryId(e.target.value)}>
{libraries.map((lib) => (
<option key={lib.id} value={lib.id}>
@@ -897,7 +897,7 @@ const GeneratePage: React.FC = () => {
<Text style={{ color: "var(--text-secondary)", padding: "16px 0" }}></Text>
) : materials.items.length === 0 ? (
<Text style={{ color: "var(--text-secondary)", padding: "16px 0" }}>
</Text>
) : (
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
@@ -965,7 +965,7 @@ const GeneratePage: React.FC = () => {
<div className="xx-auto-match-body">
<h4 className="xx-auto-match-title"></h4>
<p className="xx-auto-match-desc">
AI
</p>
<div className="xx-auto-match-features">
@@ -982,7 +982,7 @@ const GeneratePage: React.FC = () => {
marginTop: 8,
}}
>
</Text>
) : (
<Text
@@ -992,7 +992,7 @@ const GeneratePage: React.FC = () => {
marginTop: 8,
}}
>
{materials.items.length}
{materials.items.length}
</Text>
)}
</div>
@@ -1231,7 +1231,7 @@ const GeneratePage: React.FC = () => {
<div className="xx-save-modal-overlay" onClick={() => setSaveModalOpen(false)}>
<div className="xx-save-modal" onClick={(e) => e.stopPropagation()}>
<div className="xx-save-modal-header">
<span></span>
<span></span>
<button className="xx-save-modal-close" onClick={() => setSaveModalOpen(false)}>
<CloseOutlined />
</button>
@@ -927,7 +927,7 @@ const VoiceMaterialLibrary: React.FC = () => {
// 自动创建 voice 素材库(如果不存在)
const createLibMutation = useMutation({
mutationFn: () => createAssetLibrary({ name: "配音素材库", kind: "voice" }),
mutationFn: () => createAssetLibrary({ name: "配音库", kind: "voice" }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["asset-libraries"] })
},
@@ -1032,7 +1032,7 @@ const VoiceMaterialLibrary: React.FC = () => {
queryFn: getAssetLibraries,
})
lib = libs.find((l) => l.kind === "voice")
if (!lib) throw new Error("无法创建配音素材库")
if (!lib) throw new Error("无法创建配音库")
}
// 2. 上传文件(带进度)
@@ -1474,7 +1474,7 @@ const VoiceMaterialLibrary: React.FC = () => {
await saveTtsToLibrary(ttsJobId, {
name: ttsText.slice(0, 20) || "AI配音",
})
message.success("已保存到配音素材库")
message.success("已保存到配音库")
queryClient.invalidateQueries({ queryKey: ["assets", "voice"] })
setTtsOpen(false)
} catch {
@@ -1513,7 +1513,7 @@ const VoiceMaterialLibrary: React.FC = () => {
return (
<div className="vmat-page">
<PageHead
title="配音素材库"
title="配音库"
description="管理配音音频素材,支持上传、试听、编辑元信息"
actions={pageActions}
/>
+4 -4
View File
@@ -670,13 +670,13 @@ const VoiceLibrary: React.FC = () => {
}) => {
setUploadProgress(0)
try {
/* 获取或创建默认配音素材库 */
/* 获取或创建默认配音库 */
const libs = await queryClient.fetchQuery({
queryKey: ["asset-libraries"],
queryFn: getAssetLibraries,
})
const lib = libs.find((l) => l.kind === "voice")
if (!lib) throw new Error("配音素材库不存在,请先在配音素材库页面创建")
if (!lib) throw new Error("配音库不存在,请先在配音库页面创建")
/* 直传文件 */
const { storage_key } = await uploadAssetDirect({
@@ -769,7 +769,7 @@ const VoiceLibrary: React.FC = () => {
try {
await saveTtsToLibrary(ttsJobId, { name: ttsText.slice(0, 50) })
queryClient.invalidateQueries({ queryKey: ["assets", "voice"] })
showToast("已保存到配音素材库", "success")
showToast("已保存到配音库", "success")
setTtsOpen(false)
} catch (err: unknown) {
const msg = err instanceof Error ? err.message : "保存失败"
@@ -1669,7 +1669,7 @@ const VoiceLibrary: React.FC = () => {
cursor: "pointer",
}}
>
</button>
</div>
)}