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:
imeepos 2025-07-15 20:50:54 +08:00
parent 496b26cdeb
commit a6f9e82c65
5 changed files with 71 additions and 48 deletions

View File

@ -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}`);

View File

@ -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') {

View File

@ -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>

View File

@ -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>
{/* 模态框底部 */}

View File

@ -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">