diff --git a/db/repo/category_repository.go b/db/repo/category_repository.go
index fcd4f04..5b4ac61 100644
--- a/db/repo/category_repository.go
+++ b/db/repo/category_repository.go
@@ -10,6 +10,7 @@ import (
type CategoryRepository interface {
BaseRepository[entity.Category]
FindByName(name string) (*entity.Category, error)
+ FindByNameIncludingDeleted(name string) (*entity.Category, error)
FindWithResources() ([]entity.Category, error)
FindWithTags() ([]entity.Category, error)
GetResourceCount(categoryID uint) (int64, error)
@@ -17,6 +18,7 @@ type CategoryRepository interface {
GetTagNames(categoryID uint) ([]string, error)
FindWithPagination(page, pageSize int) ([]entity.Category, int64, error)
Search(query string, page, pageSize int) ([]entity.Category, int64, error)
+ RestoreDeletedCategory(id uint) error
}
// CategoryRepositoryImpl Category的Repository实现
@@ -41,6 +43,21 @@ func (r *CategoryRepositoryImpl) FindByName(name string) (*entity.Category, erro
return &category, nil
}
+// FindByNameIncludingDeleted 根据名称查找(包括已删除的记录)
+func (r *CategoryRepositoryImpl) FindByNameIncludingDeleted(name string) (*entity.Category, error) {
+ var category entity.Category
+ err := r.db.Unscoped().Where("name = ?", name).First(&category).Error
+ if err != nil {
+ return nil, err
+ }
+ return &category, nil
+}
+
+// RestoreDeletedCategory 恢复已删除的分类
+func (r *CategoryRepositoryImpl) RestoreDeletedCategory(id uint) error {
+ return r.db.Unscoped().Model(&entity.Category{}).Where("id = ?", id).Update("deleted_at", nil).Error
+}
+
// FindWithResources 查找包含资源的分类
func (r *CategoryRepositoryImpl) FindWithResources() ([]entity.Category, error) {
var categories []entity.Category
diff --git a/db/repo/tag_repository.go b/db/repo/tag_repository.go
index 3d31356..a2e876d 100644
--- a/db/repo/tag_repository.go
+++ b/db/repo/tag_repository.go
@@ -10,6 +10,7 @@ import (
type TagRepository interface {
BaseRepository[entity.Tag]
FindByName(name string) (*entity.Tag, error)
+ FindByNameIncludingDeleted(name string) (*entity.Tag, error)
FindWithResources() ([]entity.Tag, error)
FindByCategoryID(categoryID uint) ([]entity.Tag, error)
FindByCategoryIDPaginated(categoryID uint, page, pageSize int) ([]entity.Tag, int64, error)
@@ -19,6 +20,7 @@ type TagRepository interface {
Search(query string, page, pageSize int) ([]entity.Tag, int64, error)
UpdateWithNulls(tag *entity.Tag) error
GetByID(id uint) (*entity.Tag, error)
+ RestoreDeletedTag(id uint) error
}
// TagRepositoryImpl Tag的Repository实现
@@ -43,6 +45,16 @@ func (r *TagRepositoryImpl) FindByName(name string) (*entity.Tag, error) {
return &tag, nil
}
+// FindByNameIncludingDeleted 根据名称查找(包括已删除的记录)
+func (r *TagRepositoryImpl) FindByNameIncludingDeleted(name string) (*entity.Tag, error) {
+ var tag entity.Tag
+ err := r.db.Unscoped().Where("name = ?", name).First(&tag).Error
+ if err != nil {
+ return nil, err
+ }
+ return &tag, nil
+}
+
// FindWithResources 查找包含资源的标签
func (r *TagRepositoryImpl) FindWithResources() ([]entity.Tag, error) {
var tags []entity.Tag
@@ -155,3 +167,8 @@ func (r *TagRepositoryImpl) GetByID(id uint) (*entity.Tag, error) {
}
return &tag, nil
}
+
+// RestoreDeletedTag 恢复已删除的标签
+func (r *TagRepositoryImpl) RestoreDeletedTag(id uint) error {
+ return r.db.Unscoped().Model(&entity.Tag{}).Where("id = ?", id).Update("deleted_at", nil).Error
+}
diff --git a/handlers/category_handler.go b/handlers/category_handler.go
index 2a79829..b6c2efc 100644
--- a/handlers/category_handler.go
+++ b/handlers/category_handler.go
@@ -7,6 +7,7 @@ import (
"github.com/ctwj/urldb/db/converter"
"github.com/ctwj/urldb/db/dto"
"github.com/ctwj/urldb/db/entity"
+ "github.com/ctwj/urldb/utils"
"github.com/gin-gonic/gin"
)
@@ -18,6 +19,8 @@ func GetCategories(c *gin.Context) {
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
search := c.Query("search")
+ utils.Debug("获取分类列表 - 分页参数: page=%d, pageSize=%d, search=%s", page, pageSize, search)
+
var categories []entity.Category
var total int64
var err error
@@ -35,6 +38,8 @@ func GetCategories(c *gin.Context) {
return
}
+ utils.Debug("查询到分类数量: %d, 总数: %d", len(categories), total)
+
// 获取每个分类的资源数量和标签名称
resourceCounts := make(map[uint]int64)
tagNamesMap := make(map[uint][]string)
@@ -73,12 +78,50 @@ func CreateCategory(c *gin.Context) {
return
}
+ // 首先检查是否存在已删除的同名分类
+ deletedCategory, err := repoManager.CategoryRepository.FindByNameIncludingDeleted(req.Name)
+ if err == nil && deletedCategory.DeletedAt.Valid {
+ utils.Debug("找到已删除的分类: ID=%d, Name=%s", deletedCategory.ID, deletedCategory.Name)
+
+ // 如果存在已删除的同名分类,则恢复它
+ err = repoManager.CategoryRepository.RestoreDeletedCategory(deletedCategory.ID)
+ if err != nil {
+ ErrorResponse(c, "恢复已删除分类失败: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ utils.Debug("分类恢复成功: ID=%d", deletedCategory.ID)
+
+ // 重新获取恢复后的分类
+ restoredCategory, err := repoManager.CategoryRepository.FindByID(deletedCategory.ID)
+ if err != nil {
+ ErrorResponse(c, "获取恢复的分类失败: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ utils.Debug("重新获取到恢复的分类: ID=%d, Name=%s", restoredCategory.ID, restoredCategory.Name)
+
+ // 更新分类信息
+ restoredCategory.Description = req.Description
+ err = repoManager.CategoryRepository.Update(restoredCategory)
+ if err != nil {
+ ErrorResponse(c, "更新恢复的分类失败: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+ utils.Debug("分类信息更新成功: ID=%d, Description=%s", restoredCategory.ID, restoredCategory.Description)
+
+ SuccessResponse(c, gin.H{
+ "message": "分类恢复成功",
+ "category": converter.ToCategoryResponse(restoredCategory, 0, []string{}),
+ })
+ return
+ }
+
+ // 如果不存在已删除的同名分类,则创建新分类
category := &entity.Category{
Name: req.Name,
Description: req.Description,
}
- err := repoManager.CategoryRepository.Create(category)
+ err = repoManager.CategoryRepository.Create(category)
if err != nil {
ErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
diff --git a/handlers/tag_handler.go b/handlers/tag_handler.go
index 3c437a2..1d10fde 100644
--- a/handlers/tag_handler.go
+++ b/handlers/tag_handler.go
@@ -65,13 +65,47 @@ func CreateTag(c *gin.Context) {
return
}
+ // 首先检查是否存在已删除的同名标签
+ deletedTag, err := repoManager.TagRepository.FindByNameIncludingDeleted(req.Name)
+ if err == nil && deletedTag.DeletedAt.Valid {
+ // 如果存在已删除的同名标签,则恢复它
+ err = repoManager.TagRepository.RestoreDeletedTag(deletedTag.ID)
+ if err != nil {
+ ErrorResponse(c, "恢复已删除标签失败: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // 重新获取恢复后的标签
+ restoredTag, err := repoManager.TagRepository.FindByID(deletedTag.ID)
+ if err != nil {
+ ErrorResponse(c, "获取恢复的标签失败: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // 更新标签信息
+ restoredTag.Description = req.Description
+ restoredTag.CategoryID = req.CategoryID
+ err = repoManager.TagRepository.UpdateWithNulls(restoredTag)
+ if err != nil {
+ ErrorResponse(c, "更新恢复的标签失败: "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ SuccessResponse(c, gin.H{
+ "message": "标签恢复成功",
+ "tag": converter.ToTagResponse(restoredTag, 0),
+ })
+ return
+ }
+
+ // 如果不存在已删除的同名标签,则创建新标签
tag := &entity.Tag{
Name: req.Name,
Description: req.Description,
CategoryID: req.CategoryID,
}
- err := repoManager.TagRepository.Create(tag)
+ err = repoManager.TagRepository.Create(tag)
if err != nil {
ErrorResponse(c, err.Error(), http.StatusInternalServerError)
return
diff --git a/utils/scheduler.go b/utils/scheduler.go
index 2edc1f3..ba5bbc2 100644
--- a/utils/scheduler.go
+++ b/utils/scheduler.go
@@ -1038,15 +1038,30 @@ func (s *Scheduler) handleTags(tagStr string) ([]uint, error) {
Debug("查找标签: %s", name)
tag, err := s.tagRepo.FindByName(name)
if err != nil {
- Debug("标签 %s 不存在,创建新标签", name)
- // 不存在则新建
- tag = &entity.Tag{Name: name}
- err = s.tagRepo.Create(tag)
- if err != nil {
- Error("创建标签 %s 失败: %v", name, err)
- return nil, fmt.Errorf("创建标签 %s 失败: %v", name, err)
+ // 检查是否存在已删除的同名标签
+ Debug("标签 %s 不存在,检查是否有已删除的同名标签", name)
+ deletedTag, err2 := s.tagRepo.FindByNameIncludingDeleted(name)
+ if err2 == nil && deletedTag.DeletedAt.Valid {
+ // 如果存在已删除的同名标签,则恢复它
+ Debug("找到已删除的同名标签 %s,正在恢复", name)
+ err2 = s.tagRepo.RestoreDeletedTag(deletedTag.ID)
+ if err2 != nil {
+ Error("恢复已删除标签 %s 失败: %v", name, err2)
+ return nil, fmt.Errorf("恢复已删除标签 %s 失败: %v", name, err2)
+ }
+ tag = deletedTag
+ Debug("成功恢复标签: %s (ID: %d)", name, tag.ID)
+ } else {
+ // 如果不存在已删除的同名标签,则创建新标签
+ Debug("标签 %s 不存在,创建新标签", name)
+ tag = &entity.Tag{Name: name}
+ err2 = s.tagRepo.Create(tag)
+ if err2 != nil {
+ Error("创建标签 %s 失败: %v", name, err2)
+ return nil, fmt.Errorf("创建标签 %s 失败: %v", name, err2)
+ }
+ Debug("成功创建标签: %s (ID: %d)", name, tag.ID)
}
- Debug("成功创建标签: %s (ID: %d)", name, tag.ID)
} else {
Debug("找到已存在的标签: %s (ID: %d)", name, tag.ID)
}
@@ -1065,8 +1080,24 @@ func (s *Scheduler) resolveCategory(categoryName string, tagIDs []uint) (*uint,
Debug("查找分类: %s", categoryName)
cat, err := s.categoryRepo.FindByName(categoryName)
if err != nil {
- Debug("分类 %s 不存在: %v", categoryName, err)
- } else if cat != nil {
+ // 检查是否存在已删除的同名分类
+ Debug("分类 %s 不存在,检查是否有已删除的同名分类", categoryName)
+ deletedCat, err2 := s.categoryRepo.FindByNameIncludingDeleted(categoryName)
+ if err2 == nil && deletedCat.DeletedAt.Valid {
+ // 如果存在已删除的同名分类,则恢复它
+ Debug("找到已删除的同名分类 %s,正在恢复", categoryName)
+ err2 = s.categoryRepo.RestoreDeletedCategory(deletedCat.ID)
+ if err2 != nil {
+ Error("恢复已删除分类 %s 失败: %v", categoryName, err2)
+ return nil, fmt.Errorf("恢复已删除分类 %s 失败: %v", categoryName, err2)
+ }
+ cat = deletedCat
+ Debug("成功恢复分类: %s (ID: %d)", categoryName, cat.ID)
+ } else {
+ Debug("分类 %s 不存在: %v", categoryName, err)
+ }
+ }
+ if cat != nil {
Debug("找到分类: %s (ID: %d)", categoryName, cat.ID)
return &cat.ID, nil
}
diff --git a/web/components.d.ts b/web/components.d.ts
index d4f3195..afa3022 100644
--- a/web/components.d.ts
+++ b/web/components.d.ts
@@ -11,6 +11,8 @@ declare module 'vue' {
NA: typeof import('naive-ui')['NA']
NAlert: typeof import('naive-ui')['NAlert']
NButton: typeof import('naive-ui')['NButton']
+ NCheckbox: typeof import('naive-ui')['NCheckbox']
+ NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NInput: typeof import('naive-ui')['NInput']
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
NSelect: typeof import('naive-ui')['NSelect']
diff --git a/web/components/BatchAddResource.vue b/web/components/BatchAddResource.vue
index ba59b71..68cb63e 100644
--- a/web/components/BatchAddResource.vue
+++ b/web/components/BatchAddResource.vue
@@ -7,8 +7,8 @@
格式要求:标题和URL为一组,标题必填, 同一标题URL支持多行
电影1
-https://pan.baidu.com/s/123456 # 百度网盘 电影1
-https://pan.quark.com/s/123456 # 夸克网盘 电影1
+https://pan.baidu.com/s/123456
+https://pan.quark.com/s/123456
电影标题2
https://pan.baidu.com/s/789012
电视剧标题3
@@ -21,9 +21,9 @@ https://pan.quark.cn/s/345678
-
+
diff --git a/web/components/ResourceModal.vue b/web/components/ResourceModal.vue
deleted file mode 100644
index 077519e..0000000
--- a/web/components/ResourceModal.vue
+++ /dev/null
@@ -1,272 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
格式1:标题和URL两行一组
-
-电影标题1
-https://pan.baidu.com/s/123456
-电影标题2
-https://pan.baidu.com/s/789012
-
格式2:只有URL,系统自动判断
-
-https://pan.baidu.com/s/123456
-https://pan.baidu.com/s/789012
-https://pan.baidu.com/s/345678
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ tag }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
你可以通过API批量添加资源:
-
-POST /api/resources/batch
-Content-Type: application/json
-Body:
-[
- { "title": "资源A", "url": "https://a.com", "file_type": "pan", ... },
- { "title": "资源B", "url": "https://b.com", ... }
-]
-
-
参数说明:
- title: 标题
- url: 资源链接
- file_type: 类型(pan/link/other)
- tags: 标签数组(可选)
- description: 描述(可选)
- ... 其他字段参考文档
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/web/components/SingleAddResource.vue b/web/components/SingleAddResource.vue
index 4dec13f..584edb8 100644
--- a/web/components/SingleAddResource.vue
+++ b/web/components/SingleAddResource.vue
@@ -5,9 +5,8 @@
-
@@ -18,12 +17,11 @@
-
+ />
@@ -31,13 +29,12 @@
-
+ />
支持百度网盘、阿里云盘、夸克网盘等链接,每行一个链接
@@ -48,9 +45,8 @@
-
@@ -76,10 +72,9 @@
-
@@ -89,9 +84,8 @@
-
@@ -101,9 +95,8 @@
-
@@ -113,12 +106,11 @@
-
+ />
diff --git a/web/layouts/admin.vue b/web/layouts/admin.vue
index 9b24cb0..8a7985c 100644
--- a/web/layouts/admin.vue
+++ b/web/layouts/admin.vue
@@ -23,8 +23,10 @@
-
-
+
+
+
+
diff --git a/web/pages/admin/categories.vue b/web/pages/admin/categories.vue
index 0ab2757..4535591 100644
--- a/web/pages/admin/categories.vue
+++ b/web/pages/admin/categories.vue
@@ -3,24 +3,21 @@
@@ -54,10 +51,9 @@
暂无分类
你可以点击上方"添加分类"按钮创建新分类
-
+
@@ -85,16 +81,12 @@
-
-
+
|
@@ -152,36 +144,31 @@
{{ editingCategory ? '编辑分类' : '添加分类' }}
-
+
@@ -221,6 +208,7 @@ let searchTimeout: NodeJS.Timeout | null = null
const showAddModal = ref(false)
const submitting = ref(false)
const editingCategory = ref(null)
+const dialog = useDialog()
// 表单数据
const formData = ref({
@@ -263,6 +251,8 @@ const fetchCategories = async () => {
console.log('获取分类列表参数:', params)
const response = await categoryApi.getCategories(params)
console.log('分类接口响应:', response)
+ console.log('响应类型:', typeof response)
+ console.log('响应是否为数组:', Array.isArray(response))
// 适配后端API响应格式
if (response && response.items) {
@@ -283,6 +273,7 @@ const fetchCategories = async () => {
totalPages.value = 1
}
console.log('最终分类数据:', categories.value)
+ console.log('分类数据长度:', categories.value.length)
} catch (error) {
console.error('获取分类列表失败:', error)
categories.value = []
@@ -317,36 +308,61 @@ const goToPage = (page: number) => {
// 编辑分类
const editCategory = (category: any) => {
+ console.log('编辑分类:', category)
editingCategory.value = category
formData.value = {
name: category.name,
description: category.description || ''
}
+ console.log('设置表单数据:', formData.value)
showAddModal.value = true
}
// 删除分类
const deleteCategory = async (categoryId: number) => {
- if (!confirm(`确定要删除分类吗?`)) {
- return
- }
- try {
- await categoryApi.deleteCategory(categoryId)
- await fetchCategories()
- } catch (error) {
- console.error('删除分类失败:', error)
- }
+ dialog.warning({
+ title: '警告',
+ content: '确定要删除分类吗?',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ await categoryApi.deleteCategory(categoryId)
+ await fetchCategories()
+ } catch (error) {
+ console.error('删除分类失败:', error)
+ }
+ }
+ })
}
// 提交表单
const handleSubmit = async () => {
try {
submitting.value = true
+ let response: any
if (editingCategory.value) {
- await categoryApi.updateCategory(editingCategory.value.id, formData.value)
+ response = await categoryApi.updateCategory(editingCategory.value.id, formData.value)
} else {
- await categoryApi.createCategory(formData.value)
+ response = await categoryApi.createCategory(formData.value)
}
+ console.log('分类操作响应:', response)
+
+ // 检查是否是恢复操作
+ if (response && response.message && response.message.includes('恢复成功')) {
+ console.log('检测到分类恢复操作,延迟刷新数据')
+ console.log('恢复的分类信息:', response.category)
+ closeModal()
+ // 延迟一点时间再刷新,确保数据库状态已更新
+ setTimeout(async () => {
+ console.log('开始刷新分类数据...')
+ await fetchCategories()
+ console.log('分类数据刷新完成')
+ }, 500)
+ return
+ }
+
closeModal()
await fetchCategories()
} catch (error) {
diff --git a/web/pages/admin/cks.vue b/web/pages/admin/cks.vue
index a98b97b..989a428 100644
--- a/web/pages/admin/cks.vue
+++ b/web/pages/admin/cks.vue
@@ -19,23 +19,23 @@
@@ -71,12 +71,12 @@
暂无账号
你可以点击上方"添加账号"按钮创建新账号
-
+
@@ -228,8 +228,8 @@
class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-gray-100"
>
-
编辑时不允许修改平台类型
@@ -242,49 +242,44 @@
-
+ />
-
-
-
+
@@ -323,6 +318,7 @@ const loading = ref(true)
const pageLoading = ref(true)
const submitting = ref(false)
const platform = ref(null)
+const dialog = useDialog()
import { useCksApi, usePanApi } from '~/composables/useApi'
const cksApi = useCksApi()
@@ -334,10 +330,18 @@ const pans = computed(() => {
return Array.isArray(pansData.value) ? pansData.value : (pansData.value?.list || [])
})
const platformOptions = computed(() => {
- return pans.value.map(pan => ({
- label: pan.remark,
- value: pan.id
- }))
+ const options = [
+ { label: '全部平台', value: null }
+ ]
+
+ pans.value.forEach(pan => {
+ options.push({
+ label: pan.remark || pan.name || `平台${pan.id}`,
+ value: pan.id
+ })
+ })
+
+ return options
})
// 检查认证
@@ -383,8 +387,11 @@ const createCks = async () => {
await fetchCks()
closeModal()
} catch (error) {
- console.error('创建账号失败:', error)
- alert('创建账号失败: ' + (error.message || '未知错误'))
+ dialog.error({
+ title: '错误',
+ content: '创建账号失败: ' + (error.message || '未知错误'),
+ positiveText: '确定'
+ })
} finally {
submitting.value = false
}
@@ -407,47 +414,68 @@ const updateCks = async () => {
// 删除账号
const deleteCks = async (id) => {
- if (!confirm('确定要删除这个账号吗?')) return
-
- try {
- await cksApi.deleteCks(id)
- await fetchCks()
- } catch (error) {
- console.error('删除账号失败:', error)
- alert('删除账号失败: ' + (error.message || '未知错误'))
- }
+ dialog.warning({
+ title: '警告',
+ content: '确定要删除这个账号吗?',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ await cksApi.deleteCks(id)
+ await fetchCks()
+ } catch (error) {
+ console.error('删除账号失败:', error)
+ alert('删除账号失败: ' + (error.message || '未知错误'))
+ }
+ }
+ })
}
// 刷新容量
const refreshCapacity = async (id) => {
- if (!confirm('确定要刷新此账号的容量信息吗?')) return
-
- try {
- await cksApi.refreshCapacity(id)
- await fetchCks()
- alert('容量信息已刷新!')
- } catch (error) {
- console.error('刷新容量失败:', error)
- alert('刷新容量失败: ' + (error.message || '未知错误'))
- }
+ dialog.warning({
+ title: '警告',
+ content: '确定要刷新此账号的容量信息吗?',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ await cksApi.refreshCapacity(id)
+ await fetchCks()
+ alert('容量信息已刷新!')
+ } catch (error) {
+ console.error('刷新容量失败:', error)
+ alert('刷新容量失败: ' + (error.message || '未知错误'))
+ }
+ }
+ })
}
// 切换账号状态
const toggleStatus = async (cks) => {
const newStatus = !cks.is_valid
- if (!confirm(`确定要${cks.is_valid ? '禁用' : '启用'}此账号吗?`)) return
-
- try {
- console.log('切换状态 - 账号ID:', cks.id, '当前状态:', cks.is_valid, '新状态:', newStatus)
- await cksApi.updateCks(cks.id, { is_valid: newStatus })
- console.log('状态更新成功,正在刷新数据...')
- await fetchCks()
- console.log('数据刷新完成')
- alert(`账号已${newStatus ? '启用' : '禁用'}!`)
- } catch (error) {
- console.error('切换账号状态失败:', error)
- alert(`切换账号状态失败: ${error.message || '未知错误'}`)
- }
+ dialog.warning({
+ title: '警告',
+ content: `确定要${cks.is_valid ? '禁用' : '启用'}此账号吗?`,
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ console.log('切换状态 - 账号ID:', cks.id, '当前状态:', cks.is_valid, '新状态:', newStatus)
+ await cksApi.updateCks(cks.id, { is_valid: newStatus })
+ console.log('状态更新成功,正在刷新数据...')
+ await fetchCks()
+ console.log('数据刷新完成')
+ alert(`账号已${newStatus ? '启用' : '禁用'}!`)
+ } catch (error) {
+ console.error('切换账号状态失败:', error)
+ alert(`切换账号状态失败: ${error.message || '未知错误'}`)
+ }
+ }
+ })
}
// 编辑账号
@@ -532,13 +560,24 @@ const formatFileSize = (bytes) => {
// 过滤和分页计算
const filteredCksList = computed(() => {
let filtered = cksList.value
+ console.log('原始账号数量:', filtered.length)
+
+ // 平台过滤
+ if (platform.value !== null && platform.value !== undefined) {
+ filtered = filtered.filter(cks => cks.pan_id === platform.value)
+ console.log('平台过滤后数量:', filtered.length, '平台ID:', platform.value)
+ }
+
+ // 搜索过滤
if (searchQuery.value) {
const query = searchQuery.value.toLowerCase()
filtered = filtered.filter(cks =>
cks.pan?.name?.toLowerCase().includes(query) ||
cks.remark?.toLowerCase().includes(query)
)
+ console.log('搜索过滤后数量:', filtered.length, '搜索词:', searchQuery.value)
}
+
totalPages.value = Math.ceil(filtered.length / itemsPerPage.value)
const start = (currentPage.value - 1) * itemsPerPage.value
const end = start + itemsPerPage.value
@@ -556,9 +595,17 @@ const debounceSearch = () => {
}, 500)
}
+// 平台变化处理
+const onPlatformChange = () => {
+ currentPage.value = 1
+ console.log('平台过滤条件变化:', platform.value)
+ console.log('当前过滤后的账号数量:', filteredCksList.value.length)
+}
+
// 刷新数据
const refreshData = () => {
currentPage.value = 1
+ // 保持当前的过滤条件,只刷新数据
fetchCks()
fetchPlatforms()
}
diff --git a/web/pages/admin/failed-resources.vue b/web/pages/admin/failed-resources.vue
index ff5bb9c..bb0c3f7 100644
--- a/web/pages/admin/failed-resources.vue
+++ b/web/pages/admin/failed-resources.vue
@@ -251,6 +251,7 @@ const totalPages = ref(0)
// 错误统计
const errorStats = ref>({})
+const dialog = useDialog()
// 获取失败资源API
import { useReadyResourceApi } from '~/composables/useApi'
@@ -338,83 +339,108 @@ const refreshData = () => {
// 重试单个资源
const retryResource = async (id: number) => {
- if (!confirm('确定要重试这个资源吗?')) {
- return
- }
-
- try {
- await readyResourceApi.clearErrorMsg(id)
- alert('错误信息已清除,资源将在下次调度时重新处理')
- fetchData()
- } catch (error) {
- console.error('重试失败:', error)
- alert('重试失败')
- }
+ dialog.warning({
+ title: '警告',
+ content: '确定要重试这个资源吗?',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ await readyResourceApi.clearErrorMsg(id)
+ alert('错误信息已清除,资源将在下次调度时重新处理')
+ fetchData()
+ } catch (error) {
+ console.error('重试失败:', error)
+ alert('重试失败')
+ }
+ }
+ })
}
// 清除单个资源错误
const clearError = async (id: number) => {
- if (!confirm('确定要清除这个资源的错误信息吗?')) {
- return
- }
-
- try {
- await readyResourceApi.clearErrorMsg(id)
- alert('错误信息已清除')
- fetchData()
- } catch (error) {
- console.error('清除错误失败:', error)
- alert('清除错误失败')
- }
+ dialog.warning({
+ title: '警告',
+ content: '确定要清除这个资源的错误信息吗?',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ await readyResourceApi.clearErrorMsg(id)
+ alert('错误信息已清除')
+ fetchData()
+ } catch (error) {
+ console.error('清除错误失败:', error)
+ alert('清除错误失败')
+ }
+ }
+ })
}
// 删除资源
const deleteResource = async (id: number) => {
- if (!confirm('确定要删除这个失败资源吗?')) {
- return
- }
-
- try {
- await readyResourceApi.deleteReadyResource(id)
- if (failedResources.value.length === 1 && currentPage.value > 1) {
- currentPage.value--
+ dialog.warning({
+ title: '警告',
+ content: '确定要删除这个失败资源吗?',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ await readyResourceApi.deleteReadyResource(id)
+ if (failedResources.value.length === 1 && currentPage.value > 1) {
+ currentPage.value--
+ }
+ fetchData()
+ } catch (error) {
+ console.error('删除失败:', error)
+ alert('删除失败')
+ }
}
- fetchData()
- } catch (error) {
- console.error('删除失败:', error)
- alert('删除失败')
- }
+ })
}
// 重试所有失败资源
const retryAllFailed = async () => {
- if (!confirm('确定要重试所有可重试的失败资源吗?')) {
- return
- }
-
- try {
- const response = await readyResourceApi.retryFailedResources() as any
- alert(`重试操作完成:\n总数量:${response.total_count}\n已清除:${response.cleared_count}\n跳过:${response.skipped_count}`)
- fetchData()
- } catch (error) {
- console.error('重试所有失败资源失败:', error)
- alert('重试失败')
- }
+ dialog.warning({
+ title: '警告',
+ content: '确定要重试所有可重试的失败资源吗?',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ const response = await readyResourceApi.retryFailedResources() as any
+ alert(`重试操作完成:\n总数量:${response.total_count}\n已清除:${response.cleared_count}\n跳过:${response.skipped_count}`)
+ fetchData()
+ } catch (error) {
+ console.error('重试所有失败资源失败:', error)
+ alert('重试失败')
+ }
+ }
+ })
}
// 清除所有错误
const clearAllErrors = async () => {
- if (!confirm('确定要清除所有失败资源的错误信息吗?此操作不可恢复!')) {
- return
- }
-
- try {
- // 这里需要实现批量清除错误的API
- alert('批量清除错误功能待实现')
- } catch (error) {
- console.error('清除所有错误失败:', error)
- alert('清除失败')
- }
+ dialog.warning({
+ title: '警告',
+ content: '确定要清除所有失败资源的错误信息吗?此操作不可恢复!',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ // 这里需要实现批量清除错误的API
+ alert('批量清除错误功能待实现')
+ } catch (error) {
+ console.error('清除所有错误失败:', error)
+ alert('清除失败')
+ }
+ }
+ })
}
// 格式化时间
diff --git a/web/pages/admin/ready-resources.vue b/web/pages/admin/ready-resources.vue
index 954bfc4..9a6b555 100644
--- a/web/pages/admin/ready-resources.vue
+++ b/web/pages/admin/ready-resources.vue
@@ -78,83 +78,31 @@
-
-
-
-
-
批量添加待处理资源
-
-
-
-
-
-
-
格式1:标题和URL两行一组
-
-电影标题1
-https://pan.baidu.com/s/123456
-电影标题2
-https://pan.baidu.com/s/789012
-
格式2:只有URL,系统自动判断
-
-https://pan.baidu.com/s/123456
-https://pan.baidu.com/s/789012
-https://pan.baidu.com/s/345678
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
添加资源
-
-
-
+
@@ -189,17 +137,11 @@ https://pan.baidu.com/s/345678
你可以点击上方"添加资源"按钮快速导入资源
添加资源
-
@@ -324,8 +266,6 @@ interface ReadyResource {
const readyResources = ref([])
const loading = ref(false)
-const showAddModal = ref(false)
-const resourceText = ref('')
const pageLoading = ref(true) // 添加页面加载状态
// 分页相关状态
@@ -344,6 +284,7 @@ const systemConfigStore = useSystemConfigStore()
// 获取系统配置
const systemConfig = ref(null)
const updatingConfig = ref(false) // 添加配置更新状态
+const dialog = useDialog()
const fetchSystemConfig = async () => {
try {
const response = await systemConfigApi.getSystemConfig()
@@ -449,66 +390,55 @@ const refreshConfig = () => {
fetchSystemConfig()
}
-// 关闭模态框
-const closeModal = () => {
- showAddModal.value = false
- resourceText.value = ''
-}
-// 批量添加
-const handleBatchAdd = async () => {
- if (!resourceText.value.trim()) {
- alert('请输入资源内容')
- return
- }
- try {
- const response = await readyResourceApi.createReadyResourcesFromText(resourceText.value) as any
- console.log('批量添加成功:', response)
- closeModal()
- fetchData()
- alert(`成功添加 ${response.data.count} 个资源`)
- } catch (error) {
- console.error('批量添加失败:', error)
- alert('批量添加失败,请检查输入格式')
- }
-}
+
// 删除资源
const deleteResource = async (id: number) => {
- if (!confirm('确定要删除这个待处理资源吗?')) {
- return
- }
-
- try {
- await readyResourceApi.deleteReadyResource(id)
- // 如果当前页没有数据了,回到上一页
- if (readyResources.value.length === 1 && currentPage.value > 1) {
- currentPage.value--
+ dialog.warning({
+ title: '警告',
+ content: '确定要删除这个待处理资源吗?',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ await readyResourceApi.deleteReadyResource(id)
+ // 如果当前页没有数据了,回到上一页
+ if (readyResources.value.length === 1 && currentPage.value > 1) {
+ currentPage.value--
+ }
+ fetchData()
+ } catch (error) {
+ console.error('删除失败:', error)
+ alert('删除失败')
+ }
}
- fetchData()
- } catch (error) {
- console.error('删除失败:', error)
- alert('删除失败')
- }
+ })
}
// 清空全部
const clearAll = async () => {
- if (!confirm('确定要清空所有待处理资源吗?此操作不可恢复!')) {
- return
- }
-
- try {
- const response = await readyResourceApi.clearReadyResources() as any
- console.log('清空成功:', response)
- currentPage.value = 1 // 清空后回到第一页
- fetchData()
- alert(`成功清空 ${response.data.deleted_count} 个资源`)
- } catch (error) {
- console.error('清空失败:', error)
- alert('清空失败')
- }
+ dialog.warning({
+ title: '警告',
+ content: '确定要清空所有待处理资源吗?此操作不可恢复!',
+ positiveText: '确定',
+ negativeText: '取消',
+ draggable: true,
+ onPositiveClick: async () => {
+ try {
+ const response = await readyResourceApi.clearReadyResources() as any
+ console.log('清空成功:', response)
+ currentPage.value = 1 // 清空后回到第一页
+ fetchData()
+ alert(`成功清空 ${response.data.deleted_count} 个资源`)
+ } catch (error) {
+ console.error('清空失败:', error)
+ alert('清空失败')
+ }
+ }
+ })
}
// 格式化时间
diff --git a/web/pages/admin/resources.vue b/web/pages/admin/resources.vue
index d301076..508521f 100644
--- a/web/pages/admin/resources.vue
+++ b/web/pages/admin/resources.vue
@@ -22,11 +22,10 @@