feat:新增标签分类。
This commit is contained in:
@@ -4,6 +4,71 @@ import request from './request'
|
|||||||
* 工具管理服务
|
* 工具管理服务
|
||||||
*/
|
*/
|
||||||
class ToolService {
|
class ToolService {
|
||||||
|
/**
|
||||||
|
* 获取所有大分类列表(不分页)
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
static getSuperCategories() {
|
||||||
|
return request({
|
||||||
|
url: '/invest/workToolSuperCategory/list',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 1000
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取大分类详情
|
||||||
|
* @param {number} id - 大分类ID
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
static getSuperCategoryById(id) {
|
||||||
|
return request({
|
||||||
|
url: `/invest/workToolSuperCategory/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建大分类
|
||||||
|
* @param {Object} data - 大分类数据
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
static createSuperCategory(data) {
|
||||||
|
return request({
|
||||||
|
url: '/invest/workToolSuperCategory',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新大分类
|
||||||
|
* @param {Object} data - 大分类数据(包含id)
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
static updateSuperCategory(data) {
|
||||||
|
return request({
|
||||||
|
url: '/invest/workToolSuperCategory',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除大分类(逻辑删除)
|
||||||
|
* @param {Array} ids - 大分类ID数组
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
static deleteSuperCategory(ids) {
|
||||||
|
return request({
|
||||||
|
url: `/invest/workToolSuperCategory/${ids.join(',')}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有分类列表(不分页)
|
* 获取所有分类列表(不分页)
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import axios from 'axios'
|
|||||||
|
|
||||||
// 创建 axios 实例
|
// 创建 axios 实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: 'https://qdintc.com/prod-api',
|
// baseURL: 'https://qdintc.com/prod-api',
|
||||||
timeout: 20000
|
baseURL: 'http://localhost:8080',
|
||||||
|
timeout: 10000
|
||||||
})
|
})
|
||||||
|
|
||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
|
|||||||
@@ -13,10 +13,24 @@
|
|||||||
|
|
||||||
<!-- 主内容区 -->
|
<!-- 主内容区 -->
|
||||||
<div class="workbench-container">
|
<div class="workbench-container">
|
||||||
|
<!-- 大分类 Tab 标签 -->
|
||||||
|
<div class="super-category-tabs" v-if="superCategories.length > 0">
|
||||||
|
<div
|
||||||
|
v-for="superCategory in superCategories"
|
||||||
|
:key="superCategory.id"
|
||||||
|
:class="['tab-item', { active: activeSuperCategoryId === superCategory.id }]"
|
||||||
|
@click="switchTab(superCategory.id)"
|
||||||
|
>
|
||||||
|
<span class="tab-title">{{ superCategory.title }}</span>
|
||||||
|
<span class="tab-count">{{ getCategoryCountInSuper(superCategory.id) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab 内容区 -->
|
||||||
<div class="tools-container">
|
<div class="tools-container">
|
||||||
<!-- 工具分类循环渲染 -->
|
<!-- 工具分类循环渲染 -->
|
||||||
<div
|
<div
|
||||||
v-for="category in categories"
|
v-for="category in currentCategories"
|
||||||
:key="category.key"
|
:key="category.key"
|
||||||
v-show="category.tools && category.tools.length > 0"
|
v-show="category.tools && category.tools.length > 0"
|
||||||
class="tool-category"
|
class="tool-category"
|
||||||
@@ -50,12 +64,7 @@
|
|||||||
@click="openTool(tool.url)"
|
@click="openTool(tool.url)"
|
||||||
>
|
>
|
||||||
<span class="simple-tool-name">{{ tool.name }}</span>
|
<span class="simple-tool-name">{{ tool.name }}</span>
|
||||||
<div class="simple-tool-tooltip">
|
</div>
|
||||||
<div class="tooltip-content">
|
|
||||||
<p class="tooltip-desc">{{ tool.desc }}</p>
|
|
||||||
<p class="tooltip-url">{{ tool.url }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -75,7 +84,9 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
superCategories: [],
|
||||||
categories: [],
|
categories: [],
|
||||||
|
activeSuperCategoryId: null, // 当前Tab的大分类ID
|
||||||
viewMode: 'colorful' // 'colorful' 或 'simple'
|
viewMode: 'colorful' // 'colorful' 或 'simple'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -84,26 +95,59 @@ export default {
|
|||||||
this.loadData()
|
this.loadData()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
// 当前激活的大分类下的分类列表
|
||||||
|
currentCategories() {
|
||||||
|
if (!this.activeSuperCategoryId) return []
|
||||||
|
return this.categories.filter(c => c.superCategoryId === this.activeSuperCategoryId)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
// 辅助方法
|
||||||
|
getCategoriesInSuper(superCategoryId) {
|
||||||
|
return this.categories.filter(c => c.superCategoryId === superCategoryId)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取大分类下的分组数量
|
||||||
|
getCategoryCountInSuper(superCategoryId) {
|
||||||
|
return this.categories.filter(c => c.superCategoryId === superCategoryId).length
|
||||||
|
},
|
||||||
|
|
||||||
|
// 切换Tab
|
||||||
|
switchTab(superCategoryId) {
|
||||||
|
this.activeSuperCategoryId = superCategoryId
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载数据(分类和工具)
|
* 加载数据(大分类、分类和工具)
|
||||||
*/
|
*/
|
||||||
async loadData() {
|
async loadData() {
|
||||||
try {
|
try {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
// 并发加载分类和工具
|
// 并发加载大分类、分类和工具
|
||||||
const [categoriesRes, toolsRes] = await Promise.all([
|
const [superCategoriesRes, categoriesRes, toolsRes] = await Promise.all([
|
||||||
|
ToolService.getSuperCategories(),
|
||||||
ToolService.getCategories(),
|
ToolService.getCategories(),
|
||||||
ToolService.getTools()
|
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 => ({
|
const categories = (categoriesRes.rows || []).map(cat => ({
|
||||||
id: cat.id,
|
id: cat.id,
|
||||||
key: cat.categoryKey,
|
key: cat.categoryKey,
|
||||||
title: cat.categoryTitle,
|
title: cat.categoryTitle,
|
||||||
|
superCategoryId: cat.superCategoryId,
|
||||||
sortOrder: cat.sortOrder || 0,
|
sortOrder: cat.sortOrder || 0,
|
||||||
tools: []
|
tools: []
|
||||||
}))
|
}))
|
||||||
@@ -117,7 +161,8 @@ export default {
|
|||||||
url: tool.url,
|
url: tool.url,
|
||||||
displayUrl: tool.displayUrl,
|
displayUrl: tool.displayUrl,
|
||||||
icon: tool.icon,
|
icon: tool.icon,
|
||||||
color: tool.color
|
color: tool.color,
|
||||||
|
sortOrder: tool.sortOrder || 0
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// 将工具分配到对应的分类
|
// 将工具分配到对应的分类
|
||||||
@@ -128,10 +173,24 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 对每个分类下的工具按 sortOrder 排序
|
||||||
|
categories.forEach(category => {
|
||||||
|
if (category.tools && category.tools.length > 0) {
|
||||||
|
category.tools.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 按 sortOrder 排序
|
// 按 sortOrder 排序
|
||||||
categories.sort((a, b) => a.sortOrder - b.sortOrder)
|
categories.sort((a, b) => a.sortOrder - b.sortOrder)
|
||||||
|
superCategories.sort((a, b) => a.sortOrder - b.sortOrder)
|
||||||
|
|
||||||
|
this.superCategories = superCategories
|
||||||
this.categories = categories
|
this.categories = categories
|
||||||
|
|
||||||
|
// 默认激活第一个大分类
|
||||||
|
if (superCategories.length > 0 && !this.activeSuperCategoryId) {
|
||||||
|
this.activeSuperCategoryId = superCategories[0].id
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('加载数据失败')
|
console.error('加载数据失败')
|
||||||
this.loadDefaultData()
|
this.loadDefaultData()
|
||||||
@@ -274,7 +333,7 @@ export default {
|
|||||||
|
|
||||||
// 间距变量
|
// 间距变量
|
||||||
@spacing-sm: 10px;
|
@spacing-sm: 10px;
|
||||||
@spacing-md: 20px;
|
@spacing-md: 15px;
|
||||||
@spacing-lg: 30px;
|
@spacing-lg: 30px;
|
||||||
|
|
||||||
// 页面主体
|
// 页面主体
|
||||||
@@ -288,10 +347,87 @@ export default {
|
|||||||
.workbench-container {
|
.workbench-container {
|
||||||
max-width: 1920px;
|
max-width: 1920px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px @spacing-md;
|
padding: @spacing-md;
|
||||||
|
padding-top: 89px; // 为固定的 Tab 区域预留空间 (76px标题栏 + 20px上边距 + 40px Tab高度)
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 大分类 Tab 标签样式
|
||||||
|
.super-category-tabs {
|
||||||
|
position: fixed;
|
||||||
|
top: @header-height;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 98;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
padding: @spacing-md @spacing-md;
|
||||||
|
background: rgba(102, 126, 234, 0.95);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 5px 15px;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.tab-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-count {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 0 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.25);
|
||||||
|
color: white;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: background 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.25);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: white;
|
||||||
|
border-color: white;
|
||||||
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
|
.tab-title {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-count {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.workbench-header {
|
.workbench-header {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -399,23 +535,30 @@ export default {
|
|||||||
|
|
||||||
.tools-container {
|
.tools-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-direction: column;
|
||||||
gap: 15px @spacing-md;
|
gap: 30px;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tool-category { flex: 0 1 auto;
|
.tool-category {
|
||||||
|
flex: 0 1 auto;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
.category-title {
|
.category-title {
|
||||||
font-size: 20px;
|
font-size: 22px;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
color: @white-color;
|
color: @white-color;
|
||||||
margin-bottom: @spacing-sm;
|
margin-bottom: 10px;
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
border-left: 4px solid rgba(255, 255, 255, 0.8);
|
border-left: 4px solid rgba(255, 255, 255, 0.9);
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-items {
|
.category-items {
|
||||||
@@ -458,7 +601,6 @@ export default {
|
|||||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
.simple-tool-name {
|
.simple-tool-name {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
@@ -466,7 +608,6 @@ export default {
|
|||||||
color: @text-primary;
|
color: @text-primary;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
letter-spacing: 0.3px;
|
letter-spacing: 0.3px;
|
||||||
position: relative;
|
|
||||||
|
|
||||||
// 文字渐变效果
|
// 文字渐变效果
|
||||||
background: linear-gradient(135deg, #333 0%, #555 100%);
|
background: linear-gradient(135deg, #333 0%, #555 100%);
|
||||||
@@ -475,64 +616,11 @@ export default {
|
|||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 悬浮提示框
|
|
||||||
.simple-tool-tooltip {
|
|
||||||
position: absolute;
|
|
||||||
bottom: calc(100% + 10px);
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%) translateY(5px);
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
transition: all 0.15s ease-out;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 1001;
|
|
||||||
|
|
||||||
.tooltip-content {
|
|
||||||
background: rgba(255, 255, 255, 0.98);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
color: @text-primary;
|
|
||||||
padding: 14px 18px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(102, 126, 234, 0.2);
|
|
||||||
white-space: nowrap;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
// 小三角
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
border: 6px solid transparent;
|
|
||||||
border-top-color: rgba(255, 255, 255, 0.98);
|
|
||||||
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-desc {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
margin: 0 0 4px;
|
|
||||||
line-height: 1.4;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-url {
|
|
||||||
font-size: 12px;
|
|
||||||
margin: 0;
|
|
||||||
font-family: 'Consolas', 'Monaco', monospace;
|
|
||||||
color: #667eea;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: translateY(-3px) scale(1.02);
|
transform: translateY(-3px) scale(1.02);
|
||||||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.25);
|
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.25);
|
||||||
background: white;
|
background: white;
|
||||||
border-color: rgba(102, 126, 234, 0.3);
|
border-color: rgba(102, 126, 234, 0.3);
|
||||||
z-index: 999;
|
|
||||||
|
|
||||||
.simple-tool-name {
|
.simple-tool-name {
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
@@ -540,12 +628,6 @@ export default {
|
|||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.simple-tool-tooltip {
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
transform: translateX(-50%) translateY(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
@@ -830,6 +912,27 @@ export default {
|
|||||||
padding: @spacing-lg @spacing-sm;
|
padding: @spacing-lg @spacing-sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.super-category-tabs {
|
||||||
|
padding: 12px;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 10px 16px;
|
||||||
|
|
||||||
|
.tab-title {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-count {
|
||||||
|
min-width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 0 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.workbench-header {
|
.workbench-header {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
padding: @spacing-md 20px;
|
padding: @spacing-md 20px;
|
||||||
@@ -865,10 +968,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tool-card-simple {
|
.tool-card-simple {
|
||||||
// 手机端禁用提示框
|
// 手机端已移除提示框
|
||||||
.simple-tool-tooltip {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tool-icon {
|
.tool-icon {
|
||||||
|
|||||||
@@ -6,14 +6,44 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="manage-container">
|
<div class="manage-container">
|
||||||
<!-- 分类管理 -->
|
<!-- 大分类 Tab 标签页(固定在顶部) -->
|
||||||
<div class="manage-section">
|
<div class="manage-section fixed-section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<h2>书签分组管理</h2>
|
<h2>书签分类</h2>
|
||||||
|
<div class="header-actions">
|
||||||
|
<button class="add-btn" @click="showAddSuperCategoryDialog">+ 添加分类</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab 标签 -->
|
||||||
|
<div class="tab-container">
|
||||||
|
<div class="tab-list">
|
||||||
|
<div
|
||||||
|
v-for="superCategory in superCategories"
|
||||||
|
:key="superCategory.id"
|
||||||
|
:class="['tab-item', { active: activeSuperCategoryId === superCategory.id }]"
|
||||||
|
@click="switchTab(superCategory.id)"
|
||||||
|
>
|
||||||
|
<span class="tab-sort">{{ superCategory.sortOrder }}</span>
|
||||||
|
<span class="tab-title">{{ superCategory.title }}</span>
|
||||||
|
<span class="tab-count">{{ getCategoryCountInSuper(superCategory.id) }} 个分组</span>
|
||||||
|
<div class="tab-actions" @click.stop>
|
||||||
|
<button class="tab-edit-btn" @click="editSuperCategory(superCategory)" title="编辑分类">✎</button>
|
||||||
|
<button class="tab-delete-btn" @click="deleteSuperCategory(superCategory)" title="删除分类">×</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 当前分类下的书签分组管理 -->
|
||||||
|
<div v-if="activeSuperCategoryId" class="manage-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>书签分组</h2>
|
||||||
<button class="add-btn" @click="showAddCategoryDialog">+ 添加书签分组</button>
|
<button class="add-btn" @click="showAddCategoryDialog">+ 添加书签分组</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="category-list">
|
<div class="category-list">
|
||||||
<div v-for="category in categories" :key="category.id" class="category-item">
|
<div v-for="category in currentCategories" :key="category.id" class="category-item">
|
||||||
<div class="category-info">
|
<div class="category-info">
|
||||||
<span class="category-key">{{ category.key }}</span>
|
<span class="category-key">{{ category.key }}</span>
|
||||||
<span class="category-name">{{ category.title }}</span>
|
<span class="category-name">{{ category.title }}</span>
|
||||||
@@ -31,11 +61,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 网址管理 -->
|
<!-- 网址管理 -->
|
||||||
<div class="manage-section">
|
<div v-if="activeSuperCategoryId" class="manage-section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<h2>网址管理</h2>
|
<h2>网址管理</h2>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="category in categories" :key="category.id" class="tool-group">
|
<div v-for="category in currentCategories" :key="category.id" class="tool-group">
|
||||||
<div class="tool-group-header">
|
<div class="tool-group-header">
|
||||||
<h3>{{ category.title }}</h3>
|
<h3>{{ category.title }}</h3>
|
||||||
<button class="add-btn small" @click="showAddToolDialog(category)">+ 添加网址</button>
|
<button class="add-btn small" @click="showAddToolDialog(category)">+ 添加网址</button>
|
||||||
@@ -65,6 +95,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 分类编辑对话框 -->
|
||||||
|
<div v-if="showSuperCategoryDialog" class="dialog-overlay" @click="closeSuperCategoryDialog">
|
||||||
|
<div class="dialog" @click.stop>
|
||||||
|
<h3>{{ superCategoryForm.id ? '编辑分类' : '添加分类' }}</h3>
|
||||||
|
<div class="form-group">
|
||||||
|
<label><span class="required">*</span>分类标识:</label>
|
||||||
|
<input v-model="superCategoryForm.key" placeholder="例如:work" :disabled="!!superCategoryForm.id" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label><span class="required">*</span>分类名称:</label>
|
||||||
|
<input v-model="superCategoryForm.title" placeholder="例如:工作" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>排序序号:</label>
|
||||||
|
<input v-model.number="superCategoryForm.sortOrder" type="number" placeholder="数字越小越靠前,例如:0" />
|
||||||
|
</div>
|
||||||
|
<div class="dialog-actions">
|
||||||
|
<button class="cancel-btn" @click="closeSuperCategoryDialog">取消</button>
|
||||||
|
<button class="confirm-btn" @click="saveSuperCategory">保存</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 分类编辑对话框 -->
|
<!-- 分类编辑对话框 -->
|
||||||
<div v-if="showCategoryDialog" class="dialog-overlay" @click="closeCategoryDialog">
|
<div v-if="showCategoryDialog" class="dialog-overlay" @click="closeCategoryDialog">
|
||||||
<div class="dialog" @click.stop>
|
<div class="dialog" @click.stop>
|
||||||
@@ -174,7 +227,10 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
superCategories: [],
|
||||||
categories: [],
|
categories: [],
|
||||||
|
activeSuperCategoryId: null, // 当前Tab的分类ID
|
||||||
|
showSuperCategoryDialog: false,
|
||||||
showCategoryDialog: false,
|
showCategoryDialog: false,
|
||||||
showToolDialog: false,
|
showToolDialog: false,
|
||||||
showConfirmDialog: false,
|
showConfirmDialog: false,
|
||||||
@@ -213,10 +269,17 @@ export default {
|
|||||||
{ name: '淡黄', value: 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)' },
|
{ name: '淡黄', value: 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)' },
|
||||||
{ name: '淡蓝', value: 'linear-gradient(135deg, #accbee 0%, #e7f0fd 100%)' }
|
{ name: '淡蓝', value: 'linear-gradient(135deg, #accbee 0%, #e7f0fd 100%)' }
|
||||||
],
|
],
|
||||||
|
superCategoryForm: {
|
||||||
|
id: null,
|
||||||
|
key: '',
|
||||||
|
title: '',
|
||||||
|
sortOrder: 0
|
||||||
|
},
|
||||||
categoryForm: {
|
categoryForm: {
|
||||||
id: null,
|
id: null,
|
||||||
key: '',
|
key: '',
|
||||||
title: '',
|
title: '',
|
||||||
|
superCategoryId: null,
|
||||||
sortOrder: 0
|
sortOrder: 0
|
||||||
},
|
},
|
||||||
toolForm: {
|
toolForm: {
|
||||||
@@ -242,6 +305,12 @@ export default {
|
|||||||
warning: '⚠'
|
warning: '⚠'
|
||||||
}
|
}
|
||||||
return icons[this.message.type] || '✓'
|
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('/')
|
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() {
|
async loadData() {
|
||||||
try {
|
try {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
const [categoriesRes, toolsRes] = await Promise.all([
|
const [superCategoriesRes, categoriesRes, toolsRes] = await Promise.all([
|
||||||
|
ToolService.getSuperCategories(),
|
||||||
ToolService.getCategories(),
|
ToolService.getCategories(),
|
||||||
ToolService.getTools()
|
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 => ({
|
const categories = (categoriesRes.rows || []).map(cat => ({
|
||||||
id: cat.id,
|
id: cat.id,
|
||||||
key: cat.categoryKey,
|
key: cat.categoryKey,
|
||||||
title: cat.categoryTitle,
|
title: cat.categoryTitle,
|
||||||
|
superCategoryId: cat.superCategoryId,
|
||||||
sortOrder: cat.sortOrder || 0,
|
sortOrder: cat.sortOrder || 0,
|
||||||
tools: []
|
tools: []
|
||||||
}))
|
}))
|
||||||
@@ -322,8 +416,15 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
categories.sort((a, b) => a.sortOrder - b.sortOrder)
|
categories.sort((a, b) => a.sortOrder - b.sortOrder)
|
||||||
|
superCategories.sort((a, b) => a.sortOrder - b.sortOrder)
|
||||||
|
|
||||||
|
this.superCategories = superCategories
|
||||||
this.categories = categories
|
this.categories = categories
|
||||||
|
|
||||||
|
// 默认激活第一个分类
|
||||||
|
if (superCategories.length > 0 && !this.activeSuperCategoryId) {
|
||||||
|
this.activeSuperCategoryId = superCategories[0].id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载数据异常:', 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() {
|
showAddCategoryDialog() {
|
||||||
|
if (!this.activeSuperCategoryId) {
|
||||||
|
this.showMessage('请先选择一个分类', 'warning')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.categoryForm = {
|
this.categoryForm = {
|
||||||
id: null,
|
id: null,
|
||||||
key: '',
|
key: '',
|
||||||
title: '',
|
title: '',
|
||||||
sortOrder: this.categories.length
|
superCategoryId: this.activeSuperCategoryId,
|
||||||
|
sortOrder: this.currentCategories.length
|
||||||
}
|
}
|
||||||
this.showCategoryDialog = true
|
this.showCategoryDialog = true
|
||||||
},
|
},
|
||||||
@@ -349,6 +575,7 @@ export default {
|
|||||||
id: category.id,
|
id: category.id,
|
||||||
key: category.key,
|
key: category.key,
|
||||||
title: category.title,
|
title: category.title,
|
||||||
|
superCategoryId: category.superCategoryId,
|
||||||
sortOrder: category.sortOrder
|
sortOrder: category.sortOrder
|
||||||
}
|
}
|
||||||
this.showCategoryDialog = true
|
this.showCategoryDialog = true
|
||||||
@@ -385,6 +612,7 @@ export default {
|
|||||||
const data = {
|
const data = {
|
||||||
categoryKey: this.categoryForm.key,
|
categoryKey: this.categoryForm.key,
|
||||||
categoryTitle: this.categoryForm.title,
|
categoryTitle: this.categoryForm.title,
|
||||||
|
superCategoryId: this.categoryForm.superCategoryId,
|
||||||
sortOrder: this.categoryForm.sortOrder
|
sortOrder: this.categoryForm.sortOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,6 +637,7 @@ export default {
|
|||||||
id: this.categoryForm.id,
|
id: this.categoryForm.id,
|
||||||
categoryKey: this.categoryForm.key,
|
categoryKey: this.categoryForm.key,
|
||||||
categoryTitle: this.categoryForm.title,
|
categoryTitle: this.categoryForm.title,
|
||||||
|
superCategoryId: this.categoryForm.superCategoryId,
|
||||||
sortOrder: this.categoryForm.sortOrder
|
sortOrder: this.categoryForm.sortOrder
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -679,35 +908,195 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.manage-container {
|
.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 {
|
.manage-section {
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 20px 12px;
|
padding: 10px 12px;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 10px;
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
.section-header {
|
.section-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 10px;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 10px;
|
||||||
border-bottom: 2px solid #f0f0f0;
|
border-bottom: 2px solid #f0f0f0;
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: @text-primary;
|
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 {
|
.add-btn {
|
||||||
padding: 8px 20px;
|
padding: 10px 24px;
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@@ -779,6 +1168,16 @@ export default {
|
|||||||
white-space: nowrap;
|
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 {
|
.category-sort {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: @primary-color;
|
color: @primary-color;
|
||||||
@@ -1271,6 +1670,11 @@ button {
|
|||||||
|
|
||||||
.manage-container {
|
.manage-container {
|
||||||
padding: 16px 8px;
|
padding: 16px 8px;
|
||||||
|
padding-top: 200px; // 手机端为固定区域预留更多空间
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-section {
|
||||||
|
padding: 12px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-list {
|
.category-list {
|
||||||
|
|||||||
Reference in New Issue
Block a user