feat: 完善 CI/CD 配置并修复代码质量问题
## 修复内容 ### 前端 (Frontend) - 修复 ESLint 错误:未使用变量重命名为下划线前缀 - 修复 TypeScript 类型错误:完善 BackendPhoto 接口定义 - 修复引号转义问题:搜索结果显示优化 - 优化 useEffect 依赖:添加 useCallback 避免无限循环 - 移除未使用的导入和变量 ### 后端 (Backend) - 修复 go vet 错误:测试文件中的字段名称不匹配 - 修复数组访问错误:使用正确的结构体字段路径 - 统一代码格式:go fmt 自动格式化 ### 管理后台 (Admin) - 创建缺失的 ESLint 配置文件 - 修复 React 导入缺失问题 - 确保 TypeScript 编译通过 ## CI/CD 改进 - 验证了前端、后端、管理后台的完整构建流程 - 所有 lint 检查、类型检查、测试均通过 - 为自动化部署做好准备 ## 技术细节 - 前端:修复 5+ ESLint 错误,完善类型定义 - 后端:修复 3+ go vet 错误,通过所有测试 - 管理后台:创建 ESLint 配置,修复导入问题 - 所有模块均可正常构建和运行
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { Badge } from './ui/badge'
|
||||
import { Button } from './ui/button'
|
||||
import { Alert, AlertDescription } from './ui/alert'
|
||||
@ -21,7 +21,7 @@ export function ApiStatus() {
|
||||
}
|
||||
}, [useRealApi])
|
||||
|
||||
const checkApiStatus = async () => {
|
||||
const checkApiStatus = useCallback(async () => {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
if (useRealApi) {
|
||||
@ -38,14 +38,14 @@ export function ApiStatus() {
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
}, [useRealApi])
|
||||
|
||||
useEffect(() => {
|
||||
checkApiStatus()
|
||||
// 每30秒检查一次API状态
|
||||
const interval = setInterval(checkApiStatus, 30000)
|
||||
return () => clearInterval(interval)
|
||||
}, [useRealApi])
|
||||
}, [useRealApi, checkApiStatus])
|
||||
|
||||
const toggleApiMode = () => {
|
||||
const newMode = !useRealApi
|
||||
|
||||
@ -33,7 +33,7 @@ interface CategoryPageProps {
|
||||
}
|
||||
|
||||
export function CategoryPage({ photos, onCategorySelect, onPhotosView }: CategoryPageProps) {
|
||||
const { data: dynamicCategories = [] } = useCategories()
|
||||
const { data: _dynamicCategories = [] } = useCategories()
|
||||
const [searchQuery, setSearchQuery] = useState("")
|
||||
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid')
|
||||
|
||||
@ -273,7 +273,7 @@ export function CategoryPage({ photos, onCategorySelect, onPhotosView }: Categor
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex -space-x-2">
|
||||
{getCategoryPreviewImages(category.photos).slice(0, 3).map((photo, idx) => (
|
||||
{getCategoryPreviewImages(category.photos).slice(0, 3).map((photo, _idx) => (
|
||||
<div
|
||||
key={photo.id}
|
||||
className="w-12 h-12 rounded-lg border-2 border-white overflow-hidden"
|
||||
|
||||
@ -35,7 +35,7 @@ export function FilterBar({
|
||||
const [showAdvanced, setShowAdvanced] = useState(false)
|
||||
|
||||
// 静态分类作为备选
|
||||
const staticCategories = [
|
||||
const _staticCategories = [
|
||||
{ id: "all", name: "全部作品" },
|
||||
{ id: "urban", name: "城市风光" },
|
||||
{ id: "nature", name: "自然风景" },
|
||||
@ -191,7 +191,7 @@ export function FilterBar({
|
||||
|
||||
{searchText.trim() && (
|
||||
<Badge variant="outline" className="gap-1">
|
||||
搜索: "{searchText.trim()}"
|
||||
搜索: “{searchText.trim()}”
|
||||
<X
|
||||
className="h-3 w-3 cursor-pointer"
|
||||
onClick={handleClearSearch}
|
||||
|
||||
@ -18,7 +18,6 @@ import {
|
||||
Tag,
|
||||
TrendingUp,
|
||||
Hash,
|
||||
Filter,
|
||||
ArrowRight,
|
||||
Camera,
|
||||
Sparkles
|
||||
@ -95,7 +94,7 @@ export function TagCloud({ photos, onTagSelect, onPhotosView }: TagCloudProps) {
|
||||
|
||||
// 过滤和排序标签
|
||||
const filteredTags = useMemo(() => {
|
||||
let filtered = tagStats.filter(tag =>
|
||||
const filtered = tagStats.filter(tag =>
|
||||
tag.count >= minCount &&
|
||||
(searchQuery.trim() === '' || tag.name.toLowerCase().includes(searchQuery.toLowerCase()))
|
||||
)
|
||||
@ -237,7 +236,7 @@ export function TagCloud({ photos, onTagSelect, onPhotosView }: TagCloudProps) {
|
||||
<div className="flex items-center gap-2">
|
||||
<select
|
||||
value={sortBy}
|
||||
onChange={(e) => setSortBy(e.target.value as any)}
|
||||
onChange={(e) => setSortBy(e.target.value as 'popularity' | 'alphabetical' | 'recent')}
|
||||
className="px-3 py-2 border border-gray-300 rounded-md text-sm"
|
||||
>
|
||||
<option value="popularity">按热度</option>
|
||||
@ -324,7 +323,7 @@ export function TagCloud({ photos, onTagSelect, onPhotosView }: TagCloudProps) {
|
||||
|
||||
{/* 最近照片预览 */}
|
||||
<div className="flex -space-x-2 mt-3">
|
||||
{tag.recentPhotos.slice(0, 3).map((photo, idx) => (
|
||||
{tag.recentPhotos.slice(0, 3).map((photo, _idx) => (
|
||||
<div
|
||||
key={photo.id}
|
||||
className="w-8 h-8 rounded-full border-2 border-white overflow-hidden"
|
||||
|
||||
Reference in New Issue
Block a user