diff --git a/db/connection.go b/db/connection.go
index c9c774c..351183c 100644
--- a/db/connection.go
+++ b/db/connection.go
@@ -170,8 +170,8 @@ func insertDefaultDataIfEmpty() error {
{Name: "weiyun", Key: 6, Icon: "", Remark: "微云"},
{Name: "lanzou", Key: 7, Icon: "", Remark: "蓝奏云"},
{Name: "123", Key: 8, Icon: "", Remark: "123云盘"},
- {Name: "onedrive", Key: 9, Icon: "", Remark: "OneDrive"},
- {Name: "google", Key: 10, Icon: "", Remark: "Google云盘"},
+ {Name: "onedrive", Key: 9, Icon: "", Remark: "OneDrive"},
+ {Name: "google", Key: 10, Icon: "", Remark: "Google云盘"},
{Name: "ctfile", Key: 11, Icon: "", Remark: "城通网盘"},
{Name: "115", Key: 12, Icon: "", Remark: "115网盘"},
{Name: "magnet", Key: 13, Icon: "", Remark: "磁力链接"},
diff --git a/db/repo/resource_repository.go b/db/repo/resource_repository.go
index 1aab4d7..3883924 100644
--- a/db/repo/resource_repository.go
+++ b/db/repo/resource_repository.go
@@ -55,11 +55,29 @@ func (r *ResourceRepositoryImpl) FindWithRelationsPaginated(page, limit int) ([]
var total int64
offset := (page - 1) * limit
- db := r.db.Model(&entity.Resource{}).Preload("Category").Preload("Pan").Preload("Tags")
- // 获取总数
- if err := db.Count(&total).Error; err != nil {
- return nil, 0, err
+ // 优化查询:只预加载必要的关联,并添加排序
+ db := r.db.Model(&entity.Resource{}).
+ Preload("Category").
+ Preload("Pan").
+ Order("updated_at DESC") // 按更新时间倒序,显示最新内容
+
+ // 获取总数(使用缓存键)
+ cacheKey := fmt.Sprintf("resources_total_%d_%d", page, limit)
+ if cached, exists := r.cache[cacheKey]; exists {
+ if totalCached, ok := cached.(int64); ok {
+ total = totalCached
+ }
+ } else {
+ if err := db.Count(&total).Error; err != nil {
+ return nil, 0, err
+ }
+ // 缓存总数(5分钟)
+ r.cache[cacheKey] = total
+ go func() {
+ time.Sleep(5 * time.Minute)
+ delete(r.cache, cacheKey)
+ }()
}
// 获取分页数据
diff --git a/handlers/resource_handler.go b/handlers/resource_handler.go
index 2085070..0ae8d6f 100644
--- a/handlers/resource_handler.go
+++ b/handlers/resource_handler.go
@@ -22,6 +22,9 @@ func GetResources(c *gin.Context) {
var total int64
var err error
+ // 设置响应头,启用缓存
+ c.Header("Cache-Control", "public, max-age=300") // 5分钟缓存
+
if search != "" {
resources, total, err = repoManager.ResourceRepository.Search(search, nil, page, pageSize)
} else if categoryID != "" {
diff --git a/handlers/stats_handler.go b/handlers/stats_handler.go
index 136b605..13f3a52 100644
--- a/handlers/stats_handler.go
+++ b/handlers/stats_handler.go
@@ -11,6 +11,9 @@ import (
// GetStats 获取基础统计信息
func GetStats(c *gin.Context) {
+ // 设置响应头,启用缓存
+ c.Header("Cache-Control", "public, max-age=60") // 1分钟缓存
+
// 获取数据库统计
var totalResources, totalCategories, totalTags, totalViews int64
db.DB.Model(&entity.Resource{}).Count(&totalResources)
diff --git a/web/components/Icon.vue b/web/components/Icon.vue
new file mode 100644
index 0000000..2b070e2
--- /dev/null
+++ b/web/components/Icon.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/nuxt.config.ts b/web/nuxt.config.ts
index d8e0649..dcb3144 100644
--- a/web/nuxt.config.ts
+++ b/web/nuxt.config.ts
@@ -9,6 +9,7 @@ export default defineNuxtConfig({
'~/assets/css/main.css',
'vfonts/Lato.css',
'vfonts/FiraCode.css',
+ '@fortawesome/fontawesome-free/css/all.min.css', // 本地Font Awesome
],
app: {
head: {
@@ -19,11 +20,7 @@ export default defineNuxtConfig({
{ name: 'description', content: '网盘资源管理系统 - 一个现代化的资源管理系统' }
],
link: [
- { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
- {
- rel: 'stylesheet',
- href: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css'
- }
+ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
}
},
diff --git a/web/package.json b/web/package.json
index 56520bf..03e7dca 100644
--- a/web/package.json
+++ b/web/package.json
@@ -21,6 +21,7 @@
},
"dependencies": {
"@css-render/vue3-ssr": "^0.15.12",
+ "@fortawesome/fontawesome-free": "^6.7.2",
"@juggle/resize-observer": "^3.3.1",
"@nuxtjs/tailwindcss": "^6.8.0",
"@pinia/nuxt": "^0.5.0",
diff --git a/web/pages/index.vue b/web/pages/index.vue
index e6f04de..ae21ecd 100644
--- a/web/pages/index.vue
+++ b/web/pages/index.vue
@@ -525,45 +525,65 @@ onMounted(async () => {
console.log('首页 - isAuthenticated:', userStore.isAuthenticated)
console.log('首页 - user:', userStore.userInfo)
- // 使用Promise.allSettled来确保即使某个请求失败也不会影响其他请求
- const results = await Promise.allSettled([
- store.fetchResources().then((data: any) => {
+ // 设置超时时间(5秒)
+ const timeout = 5000
+ const timeoutPromise = new Promise((_, reject) => {
+ setTimeout(() => reject(new Error('请求超时')), timeout)
+ })
+
+ // 使用Promise.race来添加超时机制,并优化请求顺序
+ try {
+ // 首先加载最重要的数据(资源列表)
+ const resourcesPromise = store.fetchResources().then((data: any) => {
localResources.value = data.resources || []
return data
}).catch((e: any) => {
console.error('获取资源失败:', e)
return { resources: [] }
- }),
- store.fetchCategories().then((data: any) => {
- localCategories.value = data.categories || []
- return data
- }).catch((e: any) => {
- console.error('获取分类失败:', e)
- return { categories: [] }
- }),
- store.fetchStats().then((data: any) => {
- localStats.value = data || { total_resources: 0, total_categories: 0, total_tags: 0, total_views: 0 }
- return data
- }).catch((e: any) => {
- console.error('获取统计失败:', e)
- return { total_resources: 0, total_categories: 0, total_tags: 0, total_views: 0 }
- }),
- fetchPlatforms().catch((e: any) => console.error('获取平台失败:', e)),
- fetchSystemConfig().catch((e: any) => console.error('获取系统配置失败:', e)),
- ])
-
- // 检查哪些请求成功了
- results.forEach((result, index) => {
- if (result.status === 'rejected') {
- console.error(`请求 ${index} 失败:`, result.reason)
- }
- })
+ })
+
+ // 等待资源数据加载完成或超时
+ await Promise.race([resourcesPromise, timeoutPromise])
+
+ // 然后并行加载其他数据
+ const otherDataPromise = Promise.allSettled([
+ store.fetchCategories().then((data: any) => {
+ localCategories.value = data.categories || []
+ return data
+ }).catch((e: any) => {
+ console.error('获取分类失败:', e)
+ return { categories: [] }
+ }),
+ store.fetchStats().then((data: any) => {
+ localStats.value = data || { total_resources: 0, total_categories: 0, total_tags: 0, total_views: 0 }
+ return data
+ }).catch((e: any) => {
+ console.error('获取统计失败:', e)
+ return { total_resources: 0, total_categories: 0, total_tags: 0, total_views: 0 }
+ }),
+ fetchPlatforms().catch((e: any) => console.error('获取平台失败:', e)),
+ fetchSystemConfig().catch((e: any) => console.error('获取系统配置失败:', e)),
+ ])
+
+ // 检查哪些请求成功了
+ otherDataPromise.then(results => {
+ results.forEach((result, index) => {
+ if (result.status === 'rejected') {
+ console.error(`请求 ${index} 失败:`, result.reason)
+ }
+ })
+ })
+
+ } catch (timeoutError) {
+ console.warn('部分数据加载超时,使用默认数据:', timeoutError)
+ // 超时后使用默认数据,不阻塞页面显示
+ }
animateCounters()
} catch (error) {
console.error('页面数据加载失败:', error)
} finally {
- // 所有数据加载完成后,关闭加载状态
+ // 无论成功还是失败,都要关闭加载状态
pageLoading.value = false
console.log('首页 - onMounted 完成')
}
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
index 1a084a0..11589f5 100644
--- a/web/pnpm-lock.yaml
+++ b/web/pnpm-lock.yaml
@@ -11,6 +11,9 @@ importers:
'@css-render/vue3-ssr':
specifier: ^0.15.12
version: 0.15.14(vue@3.5.17(typescript@5.8.3))
+ '@fortawesome/fontawesome-free':
+ specifier: ^6.7.2
+ version: 6.7.2
'@juggle/resize-observer':
specifier: ^3.3.1
version: 3.4.0
@@ -549,6 +552,10 @@ packages:
'@fastify/busboy@3.1.1':
resolution: {integrity: sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==}
+ '@fortawesome/fontawesome-free@6.7.2':
+ resolution: {integrity: sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==}
+ engines: {node: '>=6'}
+
'@ioredis/commands@1.2.0':
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
@@ -4970,6 +4977,8 @@ snapshots:
'@fastify/busboy@3.1.1': {}
+ '@fortawesome/fontawesome-free@6.7.2': {}
+
'@ioredis/commands@1.2.0': {}
'@isaacs/cliui@8.0.2':