From 37588d0f0502c49c70487e0fb5286aa5b869c7c9 Mon Sep 17 00:00:00 2001 From: wwwwwwwww <526125649@qq.com> Date: Sat, 11 Jul 2026 11:31:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E5=8F=B0=E7=B4=A0=E6=9D=90=E4=BA=91?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=A0=B7=E5=BC=8F=E7=BB=9F=E4=B8=80=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/UnifiedFilterBar.tsx | 186 +++++++ video-gen-app/src/pages/ConsumePage.tsx | 35 +- video-gen-app/src/pages/GeneratedRecord.tsx | 455 ++++++------------ video-gen-app/src/pages/MaterialListPage.tsx | 47 +- 4 files changed, 374 insertions(+), 349 deletions(-) create mode 100644 video-gen-app/src/components/UnifiedFilterBar.tsx diff --git a/video-gen-app/src/components/UnifiedFilterBar.tsx b/video-gen-app/src/components/UnifiedFilterBar.tsx new file mode 100644 index 00000000..ed84c8cd --- /dev/null +++ b/video-gen-app/src/components/UnifiedFilterBar.tsx @@ -0,0 +1,186 @@ +import React from 'react'; +import { Button, DatePicker, Input, Space } from 'antd'; +import { + CheckOutlined, + ClearOutlined, + DeleteOutlined, + DownloadOutlined, + SearchOutlined, + UploadOutlined, +} from '@ant-design/icons'; +import type { Dayjs } from 'dayjs'; + +interface UnifiedFilterBarProps { + // 搜索 + searchValue: string; + searchPlaceholder?: string; + onSearchChange: (value: string) => void; + onSearch: () => void; + // 日期 + showDate?: boolean; + dateValue?: Dayjs | null; + onDateChange?: (date: Dayjs | null) => void; + datePlaceholder?: string; + // 批量操作 + batchCount: number; + totalCount: number; + onSelectAll: () => void; + onClearSelection: () => void; + onDelete: () => void; + onDownload?: () => void; + onPush?: () => void; + pushLoading?: boolean; + pushText?: string; + // 右侧额外操作 + extraActions?: React.ReactNode; +} + +const btnBase: React.CSSProperties = { + borderRadius: 8, + fontWeight: 600, + height: 36, +}; + +const btnSecondary: React.CSSProperties = { + ...btnBase, + background: '#f8f9fc', + border: '1px solid #e2e8f0', + color: '#334155', +}; + +const btnDanger: React.CSSProperties = { + ...btnBase, + background: 'linear-gradient(135deg, #ef4444, #dc2626)', + border: 'none', + color: '#fff', +}; + +const btnPrimary: React.CSSProperties = { + ...btnBase, + background: 'linear-gradient(135deg, #6366f1, #8b5cf6)', + border: 'none', + color: '#fff', +}; + +const UnifiedFilterBar: React.FC = ({ + searchValue, + searchPlaceholder = '搜索...', + onSearchChange, + onSearch, + showDate = false, + dateValue, + onDateChange, + datePlaceholder = '选择日期', + batchCount, + totalCount, + onSelectAll, + onClearSelection, + onDelete, + onDownload, + onPush, + pushLoading = false, + pushText = '推送至账户', + extraActions, +}) => { + const allSelected = batchCount === totalCount && totalCount > 0; + + return ( +
+ {/* 左侧:搜索 + 日期 */} + + { + const val = e.target.value; + onSearchChange(val); + if (!val) onSearch(); + }} + onSearch={onSearch} + style={{ width: 240, borderRadius: 8 }} + enterButton + /> + {showDate && ( + <> + onDateChange?.(date)} + format="YYYY-MM-DD" + placeholder={datePlaceholder} + style={{ width: 160, borderRadius: 8 }} + allowClear + /> + + )} + + + {/* 右侧:批量操作 + 额外操作 */} + + {/* 全选 / 取消选择 */} + + + {/* 删除 */} + + + {/* 下载 */} + {onDownload && ( + + )} + + {/* 推送 */} + {onPush && ( + + )} + + {/* 额外操作按钮 */} + {extraActions} + +
+ ); +}; + +export default UnifiedFilterBar; diff --git a/video-gen-app/src/pages/ConsumePage.tsx b/video-gen-app/src/pages/ConsumePage.tsx index c030cfc1..c79a8051 100644 --- a/video-gen-app/src/pages/ConsumePage.tsx +++ b/video-gen-app/src/pages/ConsumePage.tsx @@ -7,6 +7,9 @@ import dayjs from 'dayjs'; const { RangePicker } = DatePicker; +// 统一按钮样式 +const btnBase: React.CSSProperties = { borderRadius: 8, fontWeight: 600 }; + const toCamelCase = (str: string) => str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()); interface ConsumptionRecord { @@ -164,13 +167,24 @@ const ConsumePage: React.FC = () => { 消耗记录 -
-
+
+
setAdvertiserId(e.target.value)} - style={{ width: 180 }} + style={{ width: 180, borderRadius: 8 }} allowClear onPressEnter={() => { setCurrentPage(1); loadData(1, pageSize); }} /> @@ -183,25 +197,32 @@ const ConsumePage: React.FC = () => { setConsumeDateRange(undefined); } }} + style={{ borderRadius: 8 }} />
-
+
- +
diff --git a/video-gen-app/src/pages/GeneratedRecord.tsx b/video-gen-app/src/pages/GeneratedRecord.tsx index e6f663dc..ffa39602 100644 --- a/video-gen-app/src/pages/GeneratedRecord.tsx +++ b/video-gen-app/src/pages/GeneratedRecord.tsx @@ -17,6 +17,8 @@ import { DeleteOutlined, LoadingOutlined, UserOutlined, + CheckOutlined, + ClearOutlined, } from '@ant-design/icons'; import { useSearchParams } from 'react-router-dom'; import { PrivatePortraitLibraryPanel } from '../components/privatePortrait'; @@ -909,225 +911,86 @@ const GeneratedRecord: React.FC = () => { }, [filterType, filterMedia]); return (
- {/* 操作栏:筛选 + 推送按钮 */} + {/* 顶部:标签切换 + 批量操作按钮 */}
-
- - - - - - - - - -
+ { + setFilterType(key as typeof filterType); + setIsSelectionMode(false); + setSelectedItems(new Set()); + }} + items={[ + { key: 'project', label: 项目记录 }, + { key: 'creation', label: 创作记录 }, + { key: 'hot_opening_replicate', label: 爆款复刻 }, + { key: 'shot_replicate', label: 拆镜复刻 }, + { key: 'private_portrait', label: 私域素材库 }, + { key: 'upload_resource', label: 历史素材 }, + ]} + size="middle" + /> {filterType !== 'private_portrait' && filterType !== 'upload_resource' && ( -
- {/* 多选模式按钮 */} - {isSelectionMode ? ( - - - - - +
+ {isSelectionMode ? ( + + + + + + + + ) : ( - - ) : ( - - - )} -
+ )} +
)}
{filterType === 'private_portrait' ? ( @@ -1136,122 +999,75 @@ const GeneratedRecord: React.FC = () => { ) : ( <> - {/* Second row filter: 视频 / 图片 */} + {/* 统一筛选栏:搜索 + 日期 */}
-
- 媒体类型: - - - - handleDateChange(dateString || '')} - format="YYYY-MM-DD" - style={{ width: 160, borderRadius: 8, border: '1px solid #e2e8f0' }} - placeholder="选择日期" - /> - {selectedDate && ( - - )} - { - const val = e.target.value; - setSearchKeyword(val); - if (!val) { - setPagebreak(prev => ({ ...prev, page: 1 })); - loadRecordList(); - } - }} - onSearch={() => { +
+ 媒体类型: + + +
+ + handleDateChange(dateString || '')} + format="YYYY-MM-DD" + style={{ width: 160, borderRadius: 8, border: '1px solid #e2e8f0' }} + placeholder="选择日期" + allowClear + /> + { + const val = e.target.value; + setSearchKeyword(val); + if (!val) { setPagebreak(prev => ({ ...prev, page: 1 })); loadRecordList(); - }} - style={{ width: 240, borderRadius: 8 }} - /> - -
- + } + }} + onSearch={() => { + setPagebreak(prev => ({ ...prev, page: 1 })); + loadRecordList(); + }} + style={{ width: 240, borderRadius: 8 }} + enterButton + /> + +
{/* Content area */} {loading ? ( @@ -1408,18 +1224,20 @@ const GeneratedRecord: React.FC = () => {
{ e.stopPropagation(); @@ -1517,10 +1335,11 @@ const GeneratedRecord: React.FC = () => { left: 0, right: 0, bottom: 0, - border: '3px solid #10b981', + border: '3px solid #6366f1', borderRadius: 4, pointerEvents: 'none', zIndex: 5, + boxShadow: 'inset 0 0 0 1px rgba(99,102,241,0.2)', }} /> )}
diff --git a/video-gen-app/src/pages/MaterialListPage.tsx b/video-gen-app/src/pages/MaterialListPage.tsx index a7098272..8d81a160 100644 --- a/video-gen-app/src/pages/MaterialListPage.tsx +++ b/video-gen-app/src/pages/MaterialListPage.tsx @@ -383,13 +383,24 @@ const MaterialListPage: React.FC = () => { 素材列表
-
-
+
+
setSearchParams(prev => ({ ...prev, advertiser_id: e.target.value }))} - style={{ width: 160 }} + style={{ width: 150, borderRadius: 8 }} allowClear onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }} /> @@ -397,7 +408,7 @@ const MaterialListPage: React.FC = () => { placeholder="素材ID" value={searchParams.material_id} onChange={(e) => setSearchParams(prev => ({ ...prev, material_id: e.target.value }))} - style={{ width: 160 }} + style={{ width: 150, borderRadius: 8 }} allowClear onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }} /> @@ -405,7 +416,7 @@ const MaterialListPage: React.FC = () => { placeholder="上传ID" value={searchParams.upload_id} onChange={(e) => setSearchParams(prev => ({ ...prev, upload_id: e.target.value }))} - style={{ width: 160 }} + style={{ width: 150, borderRadius: 8 }} allowClear onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }} /> @@ -413,7 +424,7 @@ const MaterialListPage: React.FC = () => { placeholder="文件名" value={searchParams.file_name} onChange={(e) => setSearchParams(prev => ({ ...prev, file_name: e.target.value }))} - style={{ width: 140 }} + style={{ width: 140, borderRadius: 8 }} allowClear onPressEnter={() => { setCurrentPage(1); loadMaterialList(1, pageSize); }} /> @@ -421,7 +432,7 @@ const MaterialListPage: React.FC = () => { placeholder="资源类型" value={searchParams.resource_type} onChange={(value) => setSearchParams(prev => ({ ...prev, resource_type: value }))} - style={{ width: 120 }} + style={{ width: 110, borderRadius: 8 }} allowClear options={[ { value: 'image', label: '图片' }, @@ -431,21 +442,16 @@ const MaterialListPage: React.FC = () => {
-
+
@@ -454,16 +460,9 @@ const MaterialListPage: React.FC = () => { loading={pushTemplatesLoading} onClick={handleOpenPushModal} disabled={selectedRows.size === 0} - style={{ - borderRadius: 12, - fontSize: 14, - background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', - border: 'none', - color: '#fff', - boxShadow: '0 4px 14px rgba(99,102,241,0.3)', - }} + style={{ borderRadius: 8, fontWeight: 600, background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', border: 'none', color: '#fff' }} > - 推送前测 ({selectedRows.size}) + 推送前测 {selectedRows.size > 0 && `(${selectedRows.size})`}