@@ -174,7 +227,10 @@ export default {
data() {
return {
loading: false,
+ superCategories: [],
categories: [],
+ activeSuperCategoryId: null, // 当前Tab的分类ID
+ showSuperCategoryDialog: false,
showCategoryDialog: false,
showToolDialog: false,
showConfirmDialog: false,
@@ -213,10 +269,17 @@ export default {
{ name: '淡黄', value: 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)' },
{ name: '淡蓝', value: 'linear-gradient(135deg, #accbee 0%, #e7f0fd 100%)' }
],
+ superCategoryForm: {
+ id: null,
+ key: '',
+ title: '',
+ sortOrder: 0
+ },
categoryForm: {
id: null,
key: '',
title: '',
+ superCategoryId: null,
sortOrder: 0
},
toolForm: {
@@ -242,6 +305,12 @@ export default {
warning: '⚠'
}
return icons[this.message.type] || '✓'
+ },
+
+ // 当前激活的分类下的分类列表
+ currentCategories() {
+ if (!this.activeSuperCategoryId) return []
+ return this.categories.filter(c => c.superCategoryId === this.activeSuperCategoryId)
}
},
@@ -284,20 +353,45 @@ export default {
this.$router.push('/')
},
+ // 辅助方法
+ getSuperCategoryName(superCategoryId) {
+ const superCat = this.superCategories.find(s => s.id === superCategoryId)
+ return superCat ? superCat.title : '未分类'
+ },
+
+ getCategoryCountInSuper(superCategoryId) {
+ return this.categories.filter(c => c.superCategoryId === superCategoryId).length
+ },
+
+ // 切换Tab
+ switchTab(superCategoryId) {
+ this.activeSuperCategoryId = superCategoryId
+ },
+
async loadData() {
try {
this.loading = true
- const [categoriesRes, toolsRes] = await Promise.all([
+ const [superCategoriesRes, categoriesRes, toolsRes] = await Promise.all([
+ ToolService.getSuperCategories(),
ToolService.getCategories(),
ToolService.getTools()
])
- if (categoriesRes && categoriesRes.code === 200 && toolsRes && toolsRes.code === 200) {
+ if (superCategoriesRes && superCategoriesRes.code === 200 && categoriesRes && categoriesRes.code === 200 && toolsRes && toolsRes.code === 200) {
+ // 处理分类数据
+ const superCategories = (superCategoriesRes.rows || []).map(superCat => ({
+ id: superCat.id,
+ key: superCat.superCategoryKey,
+ title: superCat.superCategoryTitle,
+ sortOrder: superCat.sortOrder || 0
+ }))
+
const categories = (categoriesRes.rows || []).map(cat => ({
id: cat.id,
key: cat.categoryKey,
title: cat.categoryTitle,
+ superCategoryId: cat.superCategoryId,
sortOrder: cat.sortOrder || 0,
tools: []
}))
@@ -322,8 +416,15 @@ export default {
})
categories.sort((a, b) => a.sortOrder - b.sortOrder)
+ superCategories.sort((a, b) => a.sortOrder - b.sortOrder)
+ this.superCategories = superCategories
this.categories = categories
+
+ // 默认激活第一个分类
+ if (superCategories.length > 0 && !this.activeSuperCategoryId) {
+ this.activeSuperCategoryId = superCategories[0].id
+ }
}
} catch (error) {
console.error('加载数据异常:', error)
@@ -333,13 +434,138 @@ export default {
}
},
+ // 分类管理
+ showAddSuperCategoryDialog() {
+ this.superCategoryForm = {
+ id: null,
+ key: '',
+ title: '',
+ sortOrder: this.superCategories.length
+ }
+ this.showSuperCategoryDialog = true
+ },
+
+ editSuperCategory(superCategory) {
+ this.superCategoryForm = {
+ id: superCategory.id,
+ key: superCategory.key,
+ title: superCategory.title,
+ sortOrder: superCategory.sortOrder
+ }
+ this.showSuperCategoryDialog = true
+ },
+
+ closeSuperCategoryDialog() {
+ this.showSuperCategoryDialog = false
+ },
+
+ saveSuperCategory() {
+ if (!this.superCategoryForm.key) {
+ this.showMessage('请填写分类标识', 'warning')
+ return
+ }
+
+ if (!this.superCategoryForm.title) {
+ this.showMessage('请填写分类名称', 'warning')
+ return
+ }
+
+ if (this.superCategoryForm.id) {
+ this.updateSuperCategoryToServer()
+ } else {
+ if (this.superCategories.find(c => c.key === this.superCategoryForm.key)) {
+ this.showMessage('分类标识已存在,请使用其他标识', 'warning')
+ return
+ }
+ this.addSuperCategoryToServer()
+ }
+ },
+
+ async addSuperCategoryToServer() {
+ try {
+ const data = {
+ superCategoryKey: this.superCategoryForm.key,
+ superCategoryTitle: this.superCategoryForm.title,
+ sortOrder: this.superCategoryForm.sortOrder
+ }
+
+ const response = await ToolService.createSuperCategory(data)
+
+ if (response && response.code === 200) {
+ this.showMessage('添加成功')
+ this.closeSuperCategoryDialog()
+ this.loadData()
+ } else {
+ this.showMessage('添加失败:' + (response.msg || '未知错误'), 'error')
+ }
+ } catch (error) {
+ console.error('添加分类失败:', error)
+ this.showMessage('添加失败,请检查网络连接', 'error')
+ }
+ },
+
+ async updateSuperCategoryToServer() {
+ try {
+ const response = await ToolService.updateSuperCategory({
+ id: this.superCategoryForm.id,
+ superCategoryKey: this.superCategoryForm.key,
+ superCategoryTitle: this.superCategoryForm.title,
+ sortOrder: this.superCategoryForm.sortOrder
+ })
+
+ if (response && response.code === 200) {
+ this.showMessage('修改成功')
+ this.closeSuperCategoryDialog()
+ this.loadData()
+ } else {
+ this.showMessage('修改失败:' + (response.msg || '未知错误'), 'error')
+ }
+ } catch (error) {
+ console.error('修改分类失败:', error)
+ this.showMessage('修改失败,请检查网络连接', 'error')
+ }
+ },
+
+ deleteSuperCategory(superCategory) {
+ const categoryCount = this.getCategoryCountInSuper(superCategory.id)
+ const message = categoryCount > 0
+ ? `该分类下还有 ${categoryCount} 个分组,确定要删除“${superCategory.title}”吗?`
+ : `确定要删除分类“${superCategory.title}”吗?`
+
+ this.showConfirm(message, () => {
+ this.deleteSuperCategoryFromServer(superCategory.id)
+ })
+ },
+
+ async deleteSuperCategoryFromServer(id) {
+ try {
+ const response = await ToolService.deleteSuperCategory([id])
+
+ if (response && response.code === 200) {
+ this.showMessage('删除成功')
+ this.loadData()
+ } else {
+ this.showMessage('删除失败:' + (response.msg || '未知错误'), 'error')
+ }
+ } catch (error) {
+ console.error('删除分类失败:', error)
+ this.showMessage('删除失败,请检查网络连接', 'error')
+ }
+ },
+
// 分类管理
showAddCategoryDialog() {
+ if (!this.activeSuperCategoryId) {
+ this.showMessage('请先选择一个分类', 'warning')
+ return
+ }
+
this.categoryForm = {
id: null,
key: '',
title: '',
- sortOrder: this.categories.length
+ superCategoryId: this.activeSuperCategoryId,
+ sortOrder: this.currentCategories.length
}
this.showCategoryDialog = true
},
@@ -349,6 +575,7 @@ export default {
id: category.id,
key: category.key,
title: category.title,
+ superCategoryId: category.superCategoryId,
sortOrder: category.sortOrder
}
this.showCategoryDialog = true
@@ -385,6 +612,7 @@ export default {
const data = {
categoryKey: this.categoryForm.key,
categoryTitle: this.categoryForm.title,
+ superCategoryId: this.categoryForm.superCategoryId,
sortOrder: this.categoryForm.sortOrder
}
@@ -409,6 +637,7 @@ export default {
id: this.categoryForm.id,
categoryKey: this.categoryForm.key,
categoryTitle: this.categoryForm.title,
+ superCategoryId: this.categoryForm.superCategoryId,
sortOrder: this.categoryForm.sortOrder
})
@@ -679,35 +908,195 @@ export default {
}
.manage-container {
- padding: 20px 8px;
+ padding: 10px 8px;
+ padding-top: 180px; // 减小与固定区域的间距
+}
+
+// 固定的书签分类区域
+.fixed-section {
+ position: fixed;
+ top:70px;
+ left: 0;
+ right: 0;
+ z-index: 999;
+ margin: 0;
+ border-radius: 0;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ padding: 28px 20px 20px 20px !important; // 顶部增加更多内边距
}
.manage-section {
background: white;
border-radius: 12px;
- padding: 20px 12px;
- margin-bottom: 24px;
+ padding: 10px 12px;
+ margin-bottom: 10px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 20px;
- padding-bottom: 16px;
+ margin-bottom: 10px;
+ padding-bottom: 10px;
border-bottom: 2px solid #f0f0f0;
h2 {
margin: 0;
font-size: 20px;
color: @text-primary;
+ flex: 1; // 让标题占据剩余空间
+ min-width: 0; // 允许文本截断
+ }
+
+ .header-actions {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ flex-shrink: 0; // 防止按钮被压缩
+ }
+ }
+}
+
+// Tab 标签样式
+.tab-container {
+ margin-top: 10px;
+
+ .tab-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+ padding: 0;
+
+ .tab-item {
+ position: relative;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 10px 10px;
+ background: #f5f7fa;
+ border: 2px solid transparent;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ user-select: none;
+
+ .tab-title {
+ font-size: 15px;
+ font-weight: 600;
+ color: @text-secondary;
+ transition: color 0.3s ease;
+ }
+
+ .tab-sort {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 28px;
+ height: 28px;
+ padding: 0 8px;
+ background: rgba(102, 126, 234, 0.1);
+ color: @primary-color;
+ font-size: 13px;
+ font-weight: 700;
+ border-radius: 6px;
+ transition: all 0.3s ease;
+ }
+
+ .tab-count {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding: 4px 10px;
+ background: #e5e7eb;
+ color: @text-secondary;
+ font-size: 12px;
+ font-weight: 600;
+ border-radius: 12px;
+ transition: background 0.3s ease;
+ }
+
+ .tab-actions {
+ display: none;
+ gap: 4px;
+ margin-left: 8px;
+
+ button {
+ width: 24px;
+ height: 24px;
+ padding: 0;
+ background: transparent;
+ border: none;
+ border-radius: 4px;
+ color: @text-tertiary;
+ font-size: 16px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ &.tab-edit-btn:hover {
+ background: #409eff;
+ color: white;
+ }
+
+ &.tab-delete-btn:hover {
+ background: #f56c6c;
+ color: white;
+ }
+ }
+ }
+
+ &:hover {
+ background: #e5e7eb;
+
+ .tab-actions {
+ display: flex;
+ }
+ }
+
+ &.active {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-color: #667eea;
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+
+ .tab-title {
+ color: white;
+ }
+
+ .tab-sort {
+ background: rgba(255, 255, 255, 0.3);
+ color: white;
+ }
+
+ .tab-count {
+ background: rgba(255, 255, 255, 0.25);
+ color: white;
+ }
+
+ .tab-actions {
+ display: flex;
+
+ button {
+ color: white;
+
+ &.tab-edit-btn:hover {
+ background: rgba(255, 255, 255, 0.2);
+ }
+
+ &.tab-delete-btn:hover {
+ background: rgba(255, 255, 255, 0.2);
+ }
+ }
+ }
+ }
}
}
}
// 统一的添加按钮样式
.add-btn {
- padding: 8px 20px;
+ padding: 10px 24px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 8px;
@@ -779,6 +1168,16 @@ export default {
white-space: nowrap;
}
+ .category-super {
+ font-size: 12px;
+ color: #67c23a;
+ background: rgba(103, 194, 58, 0.1);
+ padding: 2px 8px;
+ border-radius: 4px;
+ white-space: nowrap;
+ font-weight: 500;
+ }
+
.category-sort {
font-size: 12px;
color: @primary-color;
@@ -1271,6 +1670,11 @@ button {
.manage-container {
padding: 16px 8px;
+ padding-top: 200px; // 手机端为固定区域预留更多空间
+ }
+
+ .fixed-section {
+ padding: 12px 8px;
}
.category-list {