fix: Resolve TypeScript build errors and clean up unused imports
Fixed Build Issues: - Removed unused imports in ProjectList, ModelList, ProjectForm, DataTable, CardGrid - Fixed variant type mismatches in TableAction and GridAction interfaces - Replaced InteractiveTextarea with standard textarea in ProjectForm - Updated EmptyState usage to use correct component props - Removed unused ModelCardSkeleton component definition Code Cleanup: - Cleaned up unused Search, Filter, MoreHorizontal, Eye, Edit, Trash2 imports - Removed unused filters state in DataTable - Removed unused actions parameter in CardGrid - Simplified ProjectForm description field implementation - Fixed EmptyProjectList usage in ProjectList Build Status: - All TypeScript errors resolved - Hot reload working correctly - Development server running smoothly on port 5174 - No more compilation warnings or errors The application now builds successfully with all UI/UX enhancements intact.
This commit is contained in:
parent
496b26cdeb
commit
a6f9e82c65
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useMemo } from 'react';
|
||||
import { Grid, List, Search, Filter, SortAsc, SortDesc } from 'lucide-react';
|
||||
import { Grid, List, SortAsc, SortDesc } from 'lucide-react';
|
||||
import { SearchInput } from './InteractiveInput';
|
||||
import { InteractiveButton } from './InteractiveButton';
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ export interface GridAction<T> {
|
|||
label: string;
|
||||
icon?: React.ReactNode;
|
||||
onClick: (item: T) => void;
|
||||
variant?: 'default' | 'primary' | 'danger';
|
||||
variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'ghost' | 'outline';
|
||||
disabled?: (item: T) => boolean;
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +87,6 @@ export function CardGrid<T extends CardGridItem>({
|
|||
emptyText = '暂无数据',
|
||||
emptyComponent,
|
||||
className = '',
|
||||
actions = [],
|
||||
selectedItems = [],
|
||||
onSelectionChange,
|
||||
bulkActions = [],
|
||||
|
|
@ -147,15 +146,6 @@ export function CardGrid<T extends CardGridItem>({
|
|||
|
||||
// 网格列数类名
|
||||
const getGridColsClass = () => {
|
||||
const colsMap = {
|
||||
1: 'grid-cols-1',
|
||||
2: 'grid-cols-2',
|
||||
3: 'grid-cols-3',
|
||||
4: 'grid-cols-4',
|
||||
5: 'grid-cols-5',
|
||||
6: 'grid-cols-6',
|
||||
};
|
||||
|
||||
const classes = [];
|
||||
if (gridCols.sm) classes.push(`grid-cols-${gridCols.sm}`);
|
||||
if (gridCols.md) classes.push(`md:grid-cols-${gridCols.md}`);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useMemo } from 'react';
|
||||
import { ChevronUp, ChevronDown, Search, Filter, MoreHorizontal, Eye, Edit, Trash2 } from 'lucide-react';
|
||||
import { ChevronUp, ChevronDown, Filter } from 'lucide-react';
|
||||
import { SearchInput } from './InteractiveInput';
|
||||
import { InteractiveButton } from './InteractiveButton';
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ export interface TableAction<T> {
|
|||
label: string;
|
||||
icon?: React.ReactNode;
|
||||
onClick: (record: T) => void;
|
||||
variant?: 'default' | 'primary' | 'danger';
|
||||
variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'ghost' | 'outline';
|
||||
disabled?: (record: T) => boolean;
|
||||
}
|
||||
|
||||
|
|
@ -71,8 +71,6 @@ export function DataTable<T extends Record<string, any>>({
|
|||
direction: 'asc' | 'desc';
|
||||
} | null>(null);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [filters, setFilters] = useState<Record<string, any>>({});
|
||||
|
||||
// 获取行的唯一键
|
||||
const getRowKey = (record: T, index: number): string => {
|
||||
if (typeof rowKey === 'function') {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import { modelService } from '../services/modelService';
|
|||
import ModelCard from './ModelCard';
|
||||
import ModelForm from './ModelForm';
|
||||
import ModelSearch from './ModelSearch';
|
||||
import { ModelCardSkeleton } from './SkeletonLoader';
|
||||
import {
|
||||
PlusIcon,
|
||||
Squares2X2Icon,
|
||||
|
|
@ -185,21 +184,7 @@ const ModelList: React.FC<ModelListProps> = ({ onModelSelect }) => {
|
|||
|
||||
|
||||
|
||||
// 骨架屏组件
|
||||
const ModelCardSkeleton = () => (
|
||||
<div className="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden animate-pulse">
|
||||
<div className="aspect-[3/4] bg-gray-200 loading-shimmer" />
|
||||
<div className="p-5 space-y-3">
|
||||
<div className="h-6 bg-gray-200 rounded loading-shimmer" />
|
||||
<div className="h-4 bg-gray-200 rounded w-3/4 loading-shimmer" />
|
||||
<div className="h-4 bg-gray-200 rounded w-1/2 loading-shimmer" />
|
||||
<div className="flex gap-2 pt-2">
|
||||
<div className="flex-1 h-10 bg-gray-200 rounded-xl loading-shimmer" />
|
||||
<div className="w-10 h-10 bg-gray-200 rounded-xl loading-shimmer" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
|
|
@ -222,7 +207,27 @@ const ModelList: React.FC<ModelListProps> = ({ onModelSelect }) => {
|
|||
{/* 模特卡片骨架 */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
||||
{[...Array(8)].map((_, i) => (
|
||||
<ModelCardSkeleton key={i} />
|
||||
<div key={i} className="bg-white rounded-xl border border-gray-200 p-4 space-y-4 animate-pulse">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="h-12 w-12 bg-gray-300 rounded-full"></div>
|
||||
<div className="space-y-2 flex-1">
|
||||
<div className="h-4 bg-gray-300 rounded w-2/3"></div>
|
||||
<div className="h-3 bg-gray-300 rounded w-1/2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="h-3 bg-gray-300 rounded"></div>
|
||||
<div className="h-3 bg-gray-300 rounded w-4/5"></div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="h-6 w-16 bg-gray-300 rounded-full"></div>
|
||||
<div className="h-6 w-20 bg-gray-300 rounded-full"></div>
|
||||
</div>
|
||||
<div className="flex gap-2 pt-2">
|
||||
<div className="h-8 bg-gray-300 rounded flex-1"></div>
|
||||
<div className="h-8 w-8 bg-gray-300 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import React, { useState, useEffect } from 'react';
|
|||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { useProjectStore } from '../store/projectStore';
|
||||
import { ProjectFormData, ProjectFormErrors } from '../types/project';
|
||||
import { InteractiveInput, InteractiveTextarea } from './InteractiveInput';
|
||||
import { InteractiveInput } from './InteractiveInput';
|
||||
import { InteractiveButton } from './InteractiveButton';
|
||||
import { Folder, X, AlertCircle } from 'lucide-react';
|
||||
import { Folder, X } from 'lucide-react';
|
||||
|
||||
interface ProjectFormProps {
|
||||
initialData?: Partial<ProjectFormData>;
|
||||
|
|
@ -206,16 +206,35 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
|
|||
</div>
|
||||
|
||||
{/* 项目描述 */}
|
||||
<InteractiveTextarea
|
||||
label="项目描述"
|
||||
value={formData.description}
|
||||
onChange={(value) => setFormData(prev => ({ ...prev, description: value }))}
|
||||
placeholder="描述一下这个项目的用途和内容(可选)"
|
||||
error={errors.description}
|
||||
hint="添加描述有助于您更好地管理项目"
|
||||
rows={4}
|
||||
maxLength={500}
|
||||
/>
|
||||
<div className="form-group">
|
||||
<label htmlFor="description" className="form-label">
|
||||
项目描述
|
||||
</label>
|
||||
<textarea
|
||||
id="description"
|
||||
className={`form-textarea ${errors.description ? 'error' : ''}`}
|
||||
value={formData.description}
|
||||
onChange={(e) => setFormData(prev => ({ ...prev, description: e.target.value }))}
|
||||
placeholder="描述一下这个项目的用途和内容(可选)"
|
||||
rows={4}
|
||||
maxLength={500}
|
||||
/>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="form-hint">
|
||||
添加描述有助于您更好地管理项目
|
||||
</div>
|
||||
<div className="text-xs text-gray-500">
|
||||
{formData.description.length}/500
|
||||
</div>
|
||||
</div>
|
||||
{errors.description && (
|
||||
<div className="form-error">
|
||||
<span className="text-red-600">
|
||||
{errors.description}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{/* 模态框底部 */}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ import { invoke } from '@tauri-apps/api/core';
|
|||
import { useProjectStore } from '../store/projectStore';
|
||||
import { useUIStore } from '../store/uiStore';
|
||||
import { ProjectCard } from './ProjectCard';
|
||||
import { EmptyProjectList } from './EmptyState';
|
||||
import { EmptyState } from './EmptyState';
|
||||
import { LoadingSpinner } from './LoadingSpinner';
|
||||
import { ErrorMessage } from './ErrorMessage';
|
||||
import { DeleteConfirmDialog } from './DeleteConfirmDialog';
|
||||
import { ProjectCardSkeleton, PageLoadingSkeleton } from './SkeletonLoader';
|
||||
import { PageLoadingSkeleton } from './SkeletonLoader';
|
||||
import { InteractiveButton } from './InteractiveButton';
|
||||
import { Plus, Trash2 } from 'lucide-react';
|
||||
|
||||
|
|
@ -222,7 +222,18 @@ export const ProjectList: React.FC = () => {
|
|||
{/* 项目内容区域 */}
|
||||
{projects.length === 0 ? (
|
||||
<div className="animate-fade-in-up">
|
||||
<EmptyProjectList onCreateProject={openCreateProjectModal} />
|
||||
<EmptyState
|
||||
illustration="folder"
|
||||
title="还没有项目"
|
||||
description="创建您的第一个项目开始使用 MixVideo"
|
||||
actionText="新建项目"
|
||||
onAction={openCreateProjectModal}
|
||||
showTips
|
||||
tips={[
|
||||
"提示:您可以通过拖拽文件夹到此处快速创建项目",
|
||||
"支持导入现有的视频项目文件夹"
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
|
|
|
|||
Loading…
Reference in New Issue