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:
xujiang
2025-07-14 10:01:48 +08:00
parent 8a0792500e
commit 48b6a5f4aa
11 changed files with 297 additions and 239 deletions

View File

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

View File

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

View File

@ -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()}"
: &ldquo;{searchText.trim()}&rdquo;
<X
className="h-3 w-3 cursor-pointer"
onClick={handleClearSearch}

View File

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