fix:分类改成书签分组。
This commit is contained in:
@@ -7,16 +7,16 @@
|
||||
<button class="view-toggle-btn" @click="toggleView">
|
||||
{{ viewMode === 'colorful' ? '简洁版' : '炫彩版' }}
|
||||
</button>
|
||||
<button class="manage-btn" @click="goManage">管理数据</button>
|
||||
<button class="manage-btn" @click="goManage">书签管理</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<div class="workbench-container">
|
||||
<div class="tools-container">
|
||||
<!-- 工具分类循环渲染 -->
|
||||
<div
|
||||
v-for="category in categories"
|
||||
<div
|
||||
v-for="category in categories"
|
||||
:key="category.key"
|
||||
v-show="category.tools && category.tools.length > 0"
|
||||
class="tool-category"
|
||||
@@ -24,10 +24,10 @@
|
||||
<h2 class="category-title">{{ category.title }}</h2>
|
||||
<div class="category-items">
|
||||
<!-- 炫彩版 -->
|
||||
<div
|
||||
<div
|
||||
v-if="viewMode === 'colorful'"
|
||||
v-for="tool in category.tools"
|
||||
:key="tool.name"
|
||||
v-for="tool in category.tools"
|
||||
:key="tool.name"
|
||||
class="tool-card"
|
||||
@click="openTool(tool.url)"
|
||||
>
|
||||
@@ -40,12 +40,12 @@
|
||||
<p class="tool-url">{{ tool.displayUrl }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 简洁版 -->
|
||||
<div
|
||||
v-if="viewMode === 'simple'"
|
||||
v-for="tool in category.tools"
|
||||
:key="tool.name"
|
||||
v-for="tool in category.tools"
|
||||
:key="tool.name"
|
||||
class="tool-card-simple"
|
||||
@click="openTool(tool.url)"
|
||||
>
|
||||
@@ -71,7 +71,7 @@ import ToolService from '../services/ToolService'
|
||||
export default {
|
||||
name: 'HomePage',
|
||||
components: { Page },
|
||||
|
||||
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@@ -79,11 +79,11 @@ export default {
|
||||
viewMode: 'colorful' // 'colorful' 或 'simple'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
created() {
|
||||
this.loadData()
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* 加载数据(分类和工具)
|
||||
@@ -91,13 +91,13 @@ export default {
|
||||
async loadData() {
|
||||
try {
|
||||
this.loading = true
|
||||
|
||||
|
||||
// 并发加载分类和工具
|
||||
const [categoriesRes, toolsRes] = await Promise.all([
|
||||
ToolService.getCategories(),
|
||||
ToolService.getTools()
|
||||
])
|
||||
|
||||
|
||||
if (categoriesRes && categoriesRes.code === 200 && toolsRes && toolsRes.code === 200) {
|
||||
// 处理分类数据
|
||||
const categories = (categoriesRes.rows || []).map(cat => ({
|
||||
@@ -107,7 +107,7 @@ export default {
|
||||
sortOrder: cat.sortOrder || 0,
|
||||
tools: []
|
||||
}))
|
||||
|
||||
|
||||
// 处理工具数据
|
||||
const tools = (toolsRes.rows || []).map(tool => ({
|
||||
id: tool.id,
|
||||
@@ -119,7 +119,7 @@ export default {
|
||||
icon: tool.icon,
|
||||
color: tool.color
|
||||
}))
|
||||
|
||||
|
||||
// 将工具分配到对应的分类
|
||||
tools.forEach(tool => {
|
||||
const category = categories.find(cat => cat.id === tool.categoryId)
|
||||
@@ -127,10 +127,10 @@ export default {
|
||||
category.tools.push(tool)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// 按 sortOrder 排序
|
||||
categories.sort((a, b) => a.sortOrder - b.sortOrder)
|
||||
|
||||
|
||||
this.categories = categories
|
||||
} else {
|
||||
console.error('加载数据失败')
|
||||
@@ -149,30 +149,30 @@ export default {
|
||||
*/
|
||||
loadDefaultData() {
|
||||
this.categories = [
|
||||
{
|
||||
key: 'doc',
|
||||
title: '智聪科技',
|
||||
tools: this.getDefaultDocTools()
|
||||
{
|
||||
key: 'doc',
|
||||
title: '智聪科技',
|
||||
tools: this.getDefaultDocTools()
|
||||
},
|
||||
{
|
||||
key: 'code',
|
||||
title: '管理工具',
|
||||
tools: this.getDefaultCodeTools()
|
||||
{
|
||||
key: 'code',
|
||||
title: '管理工具',
|
||||
tools: this.getDefaultCodeTools()
|
||||
},
|
||||
{
|
||||
key: 'database',
|
||||
title: '开发工具',
|
||||
tools: this.getDefaultDatabaseTools()
|
||||
{
|
||||
key: 'database',
|
||||
title: '开发工具',
|
||||
tools: this.getDefaultDatabaseTools()
|
||||
},
|
||||
{
|
||||
key: 'test',
|
||||
title: '第三方服务',
|
||||
tools: this.getDefaultTestTools()
|
||||
{
|
||||
key: 'test',
|
||||
title: '第三方服务',
|
||||
tools: this.getDefaultTestTools()
|
||||
},
|
||||
{
|
||||
key: 'other',
|
||||
title: '其他工具',
|
||||
tools: this.getDefaultOtherTools()
|
||||
{
|
||||
key: 'other',
|
||||
title: '其他工具',
|
||||
tools: this.getDefaultOtherTools()
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -249,7 +249,7 @@ export default {
|
||||
goManage() {
|
||||
this.$router.push('/manage')
|
||||
},
|
||||
|
||||
|
||||
// 切换视图模式
|
||||
toggleView() {
|
||||
this.viewMode = this.viewMode === 'colorful' ? 'simple' : 'colorful'
|
||||
@@ -304,7 +304,7 @@ export default {
|
||||
padding: @spacing-md 40px;
|
||||
background: @primary-gradient;
|
||||
z-index: 99;
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
font-weight: 800;
|
||||
@@ -313,7 +313,7 @@ export default {
|
||||
text-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
|
||||
letter-spacing: 2px;
|
||||
position: relative;
|
||||
|
||||
|
||||
// 发光效果
|
||||
&::before {
|
||||
content: attr(data-text);
|
||||
@@ -332,7 +332,7 @@ export default {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
|
||||
|
||||
.view-toggle-btn {
|
||||
padding: 12px 28px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
@@ -344,19 +344,19 @@ export default {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.5);
|
||||
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
|
||||
}
|
||||
|
||||
|
||||
&:active {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.manage-btn {
|
||||
padding: 12px 28px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
@@ -369,7 +369,7 @@ export default {
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
|
||||
position: relative;
|
||||
|
||||
|
||||
// 齿轮图标
|
||||
&::after {
|
||||
content: '⚙️';
|
||||
@@ -378,17 +378,17 @@ export default {
|
||||
display: inline-block;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.5);
|
||||
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
|
||||
|
||||
|
||||
&::after {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&:active {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||||
@@ -407,7 +407,7 @@ export default {
|
||||
|
||||
.tool-category { flex: 0 1 auto;
|
||||
overflow: visible;
|
||||
|
||||
|
||||
.category-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
@@ -417,7 +417,7 @@ export default {
|
||||
border-left: 4px solid rgba(255, 255, 255, 0.8);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
.category-items {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -436,7 +436,7 @@ export default {
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
width: @card-width;
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||
@@ -459,7 +459,7 @@ export default {
|
||||
backdrop-filter: blur(10px);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
|
||||
.simple-tool-name {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
@@ -467,14 +467,14 @@ export default {
|
||||
white-space: nowrap;
|
||||
letter-spacing: 0.3px;
|
||||
position: relative;
|
||||
|
||||
|
||||
// 文字渐变效果
|
||||
background: linear-gradient(135deg, #333 0%, #555 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
|
||||
// 悬浮提示框
|
||||
.simple-tool-tooltip {
|
||||
position: absolute;
|
||||
@@ -486,7 +486,7 @@ export default {
|
||||
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);
|
||||
@@ -496,7 +496,7 @@ export default {
|
||||
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: '';
|
||||
@@ -508,7 +508,7 @@ export default {
|
||||
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;
|
||||
@@ -516,7 +516,7 @@ export default {
|
||||
line-height: 1.4;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
.tooltip-url {
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
@@ -526,28 +526,28 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px) scale(1.02);
|
||||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.25);
|
||||
background: white;
|
||||
border-color: rgba(102, 126, 234, 0.3);
|
||||
z-index: 999;
|
||||
|
||||
|
||||
.simple-tool-name {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
|
||||
.simple-tool-tooltip {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&:active {
|
||||
transform: translateY(-1px) scale(1.01);
|
||||
box-shadow: 0 3px 12px rgba(102, 126, 234, 0.2);
|
||||
@@ -564,7 +564,7 @@ export default {
|
||||
flex-shrink: 0;
|
||||
margin-right: 16px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||
|
||||
|
||||
.icon-text {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
@@ -606,26 +606,26 @@ export default {
|
||||
.tools-container {
|
||||
gap: 25px @spacing-lg;
|
||||
}
|
||||
|
||||
|
||||
.tool-category {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
|
||||
.category-title {
|
||||
width: auto;
|
||||
text-align: left;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
|
||||
.category-items {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tool-card {
|
||||
width: calc(50% - 8px);
|
||||
}
|
||||
|
||||
|
||||
.workbench-header h1 {
|
||||
font-size: 36px;
|
||||
}
|
||||
@@ -638,19 +638,19 @@ export default {
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
|
||||
|
||||
.manage-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
color: @text-primary;
|
||||
}
|
||||
|
||||
|
||||
.add-btn {
|
||||
padding: 8px 16px;
|
||||
background: #67c23a;
|
||||
@@ -660,18 +660,18 @@ export default {
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #85ce61;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.category-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
|
||||
.category-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -679,17 +679,17 @@ export default {
|
||||
padding: 12px 16px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 8px;
|
||||
|
||||
|
||||
.category-name {
|
||||
font-size: 16px;
|
||||
color: @text-primary;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
||||
.category-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
|
||||
button {
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
@@ -697,22 +697,22 @@ export default {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
|
||||
.edit-btn {
|
||||
background: #409eff;
|
||||
border: none;
|
||||
color: white;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #66b1ff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.delete-btn {
|
||||
background: #f56c6c;
|
||||
border: none;
|
||||
color: white;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #f78989;
|
||||
}
|
||||
@@ -734,7 +734,7 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2000;
|
||||
|
||||
|
||||
.dialog {
|
||||
background: white;
|
||||
border-radius: @border-radius-lg;
|
||||
@@ -742,16 +742,16 @@ export default {
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||
|
||||
|
||||
h3 {
|
||||
margin: 0 0 20px;
|
||||
font-size: 20px;
|
||||
color: @text-primary;
|
||||
}
|
||||
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
@@ -759,7 +759,7 @@ export default {
|
||||
color: @text-secondary;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
||||
input, select {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
@@ -768,30 +768,30 @@ export default {
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.2s ease;
|
||||
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
|
||||
&:disabled {
|
||||
background: #f5f7fa;
|
||||
color: #999;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
select {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.dialog-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
|
||||
|
||||
button {
|
||||
padding: 10px 24px;
|
||||
border-radius: 6px;
|
||||
@@ -799,23 +799,23 @@ export default {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
|
||||
.cancel-btn {
|
||||
background: white;
|
||||
border: 1px solid #dcdfe6;
|
||||
color: @text-primary;
|
||||
|
||||
|
||||
&:hover {
|
||||
color: #409eff;
|
||||
border-color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.confirm-btn {
|
||||
background: #409eff;
|
||||
border: none;
|
||||
color: white;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #66b1ff;
|
||||
}
|
||||
@@ -829,62 +829,62 @@ export default {
|
||||
.workbench-container {
|
||||
padding: @spacing-lg @spacing-sm;
|
||||
}
|
||||
|
||||
|
||||
.workbench-header {
|
||||
justify-content: flex-start;
|
||||
padding: @spacing-md 20px;
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
|
||||
.header-actions {
|
||||
right: 20px;
|
||||
|
||||
|
||||
// 手机端隐藏切换按钮,只保留管理数据按钮
|
||||
.view-toggle-btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tools-container {
|
||||
gap: @spacing-md;
|
||||
}
|
||||
|
||||
|
||||
.tool-category {
|
||||
.category-title {
|
||||
font-size: 16px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tool-card {
|
||||
padding: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.tool-card-simple {
|
||||
// 手机端禁用提示框
|
||||
.simple-tool-tooltip {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tool-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-right: 12px;
|
||||
|
||||
|
||||
.icon-text {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tool-name {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
.tool-desc {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<page class="manage-page">
|
||||
<div class="manage-header">
|
||||
<h1>管理数据</h1>
|
||||
<h1>书签管理</h1>
|
||||
<button class="back-btn" @click="goBack">返回工作台</button>
|
||||
</div>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
<!-- 分类管理 -->
|
||||
<div class="manage-section">
|
||||
<div class="section-header">
|
||||
<h2>分类管理</h2>
|
||||
<button class="add-btn" @click="showAddCategoryDialog">+ 添加分类</button>
|
||||
<h2>书签分组管理</h2>
|
||||
<button class="add-btn" @click="showAddCategoryDialog">+ 添加书签分组</button>
|
||||
</div>
|
||||
<div class="category-list">
|
||||
<div v-for="category in categories" :key="category.id" class="category-item">
|
||||
@@ -68,14 +68,14 @@
|
||||
<!-- 分类编辑对话框 -->
|
||||
<div v-if="showCategoryDialog" class="dialog-overlay" @click="closeCategoryDialog">
|
||||
<div class="dialog" @click.stop>
|
||||
<h3>{{ categoryForm.id ? '编辑分类' : '添加分类' }}</h3>
|
||||
<h3>{{ categoryForm.id ? '编辑书签分组' : '添加书签分组' }}</h3>
|
||||
<div class="form-group">
|
||||
<label><span class="required">*</span>分类标识:</label>
|
||||
<label><span class="required">*</span>书签分组标识:</label>
|
||||
<input v-model="categoryForm.key" placeholder="例如:doc" :disabled="!!categoryForm.id" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><span class="required">*</span>分类名称:</label>
|
||||
<input v-model="categoryForm.title" placeholder="例如:智聪科技" />
|
||||
<label><span class="required">*</span>书签分组名称:</label>
|
||||
<input v-model="categoryForm.title" placeholder="例如:书签1" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>排序序号:</label>
|
||||
@@ -94,21 +94,21 @@
|
||||
<h3>{{ toolForm.id ? '编辑网址' : '添加网址' }}</h3>
|
||||
<div class="form-group">
|
||||
<label><span class="required">*</span>访问地址:</label>
|
||||
<input v-model="toolForm.url" placeholder="例如:https://www.qdintc.com" />
|
||||
<input v-model="toolForm.url" placeholder="例如:https://www.baidu.com" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label><span class="required">*</span>网址名称:</label>
|
||||
<input v-model="toolForm.name" placeholder="例如:智聪官网" />
|
||||
<input v-model="toolForm.name" placeholder="例如:网址1" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label>网址描述:</label>
|
||||
<input v-model="toolForm.desc" placeholder="例如:智聪官网" />
|
||||
<input v-model="toolForm.desc" placeholder="例如:网址描述" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label>显示地址:</label>
|
||||
<input v-model="toolForm.displayUrl" placeholder="例如:www.qdintc.com" />
|
||||
<input v-model="toolForm.displayUrl" placeholder="例如:www.baidu.com" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>图标文字:</label>
|
||||
@@ -117,8 +117,8 @@
|
||||
<div class="form-group">
|
||||
<label>图标颜色:</label>
|
||||
<div class="color-picker">
|
||||
<div
|
||||
v-for="(colorOption, index) in colorOptions"
|
||||
<div
|
||||
v-for="(colorOption, index) in colorOptions"
|
||||
:key="index"
|
||||
class="color-option"
|
||||
:class="{ active: toolForm.color === colorOption.value }"
|
||||
@@ -170,7 +170,7 @@ import ToolService from '../services/ToolService'
|
||||
export default {
|
||||
name: 'ManagePage',
|
||||
components: { Page },
|
||||
|
||||
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@@ -233,7 +233,7 @@ export default {
|
||||
currentCategory: null
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
messageIcon() {
|
||||
const icons = {
|
||||
@@ -244,13 +244,13 @@ export default {
|
||||
return icons[this.message.type] || '✓'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
created() {
|
||||
this.loadData()
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
// 消息提示
|
||||
showMessage(text, type = 'success') {
|
||||
@@ -287,12 +287,12 @@ export default {
|
||||
async loadData() {
|
||||
try {
|
||||
this.loading = true
|
||||
|
||||
|
||||
const [categoriesRes, toolsRes] = await Promise.all([
|
||||
ToolService.getCategories(),
|
||||
ToolService.getTools()
|
||||
])
|
||||
|
||||
|
||||
if (categoriesRes && categoriesRes.code === 200 && toolsRes && toolsRes.code === 200) {
|
||||
const categories = (categoriesRes.rows || []).map(cat => ({
|
||||
id: cat.id,
|
||||
@@ -301,7 +301,7 @@ export default {
|
||||
sortOrder: cat.sortOrder || 0,
|
||||
tools: []
|
||||
}))
|
||||
|
||||
|
||||
const tools = (toolsRes.rows || []).map(tool => ({
|
||||
id: tool.id,
|
||||
categoryId: tool.categoryId,
|
||||
@@ -313,16 +313,16 @@ export default {
|
||||
color: tool.color,
|
||||
sortOrder: tool.sortOrder || 0
|
||||
}))
|
||||
|
||||
|
||||
tools.forEach(tool => {
|
||||
const category = categories.find(cat => cat.id === tool.categoryId)
|
||||
if (category) {
|
||||
category.tools.push(tool)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
categories.sort((a, b) => a.sortOrder - b.sortOrder)
|
||||
|
||||
|
||||
this.categories = categories
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -363,7 +363,7 @@ export default {
|
||||
this.showMessage('请填写分类标识', 'warning')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (!this.categoryForm.title) {
|
||||
this.showMessage('请填写分类名称', 'warning')
|
||||
return
|
||||
@@ -387,9 +387,9 @@ export default {
|
||||
categoryTitle: this.categoryForm.title,
|
||||
sortOrder: this.categoryForm.sortOrder
|
||||
}
|
||||
|
||||
|
||||
const response = await ToolService.createCategory(data)
|
||||
|
||||
|
||||
if (response && response.code === 200) {
|
||||
this.showMessage('添加成功')
|
||||
this.closeCategoryDialog()
|
||||
@@ -411,7 +411,7 @@ export default {
|
||||
categoryTitle: this.categoryForm.title,
|
||||
sortOrder: this.categoryForm.sortOrder
|
||||
})
|
||||
|
||||
|
||||
if (response && response.code === 200) {
|
||||
this.showMessage('修改成功')
|
||||
this.closeCategoryDialog()
|
||||
@@ -426,10 +426,10 @@ export default {
|
||||
},
|
||||
|
||||
deleteCategory(category) {
|
||||
const message = category.tools && category.tools.length > 0
|
||||
const message = category.tools && category.tools.length > 0
|
||||
? `该分类下还有 ${category.tools.length} 个网址,确定要删除"${category.title}"吗?`
|
||||
: `确定要删除分类"${category.title}"吗?`
|
||||
|
||||
|
||||
this.showConfirm(message, () => {
|
||||
this.deleteCategoryFromServer(category.id)
|
||||
})
|
||||
@@ -438,7 +438,7 @@ export default {
|
||||
async deleteCategoryFromServer(id) {
|
||||
try {
|
||||
const response = await ToolService.deleteCategory([id])
|
||||
|
||||
|
||||
if (response && response.code === 200) {
|
||||
this.showMessage('删除成功')
|
||||
this.loadData()
|
||||
@@ -494,12 +494,12 @@ export default {
|
||||
this.showMessage('请填写网址名称', 'warning')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (!this.toolForm.url) {
|
||||
this.showMessage('请填写访问地址', 'warning')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 验证URL格式
|
||||
if (!this.isValidUrl(this.toolForm.url)) {
|
||||
this.showMessage('请输入完整的URL地址,必须以http://或https://开头', 'warning')
|
||||
@@ -516,7 +516,7 @@ export default {
|
||||
this.addToolToServer()
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 验证URL格式
|
||||
isValidUrl(url) {
|
||||
if (!url) return false
|
||||
@@ -535,7 +535,7 @@ export default {
|
||||
color: this.toolForm.color,
|
||||
sortOrder: this.toolForm.sortOrder
|
||||
})
|
||||
|
||||
|
||||
if (response && response.code === 200) {
|
||||
this.showMessage('添加成功')
|
||||
this.closeToolDialog()
|
||||
@@ -562,7 +562,7 @@ export default {
|
||||
color: this.toolForm.color,
|
||||
sortOrder: this.toolForm.sortOrder
|
||||
})
|
||||
|
||||
|
||||
if (response && response.code === 200) {
|
||||
this.showMessage('修改成功')
|
||||
this.closeToolDialog()
|
||||
@@ -585,7 +585,7 @@ export default {
|
||||
async deleteToolFromServer(id) {
|
||||
try {
|
||||
const response = await ToolService.deleteTool([id])
|
||||
|
||||
|
||||
if (response && response.code === 200) {
|
||||
this.showMessage('删除成功')
|
||||
this.loadData()
|
||||
@@ -628,7 +628,7 @@ export default {
|
||||
justify-content: center; // PC端居中
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: 36px; // 与HomePage保持一致
|
||||
@@ -637,7 +637,7 @@ export default {
|
||||
text-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
|
||||
letter-spacing: 2px; // 添加字母间距
|
||||
}
|
||||
|
||||
|
||||
.back-btn {
|
||||
position: absolute; // 绝对定位避免遮挡标题
|
||||
right: 40px;
|
||||
@@ -651,7 +651,7 @@ export default {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
|
||||
|
||||
|
||||
// 返回图标
|
||||
&::before {
|
||||
content: '◄';
|
||||
@@ -660,17 +660,17 @@ export default {
|
||||
display: inline-block;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.5);
|
||||
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
|
||||
|
||||
|
||||
&::before {
|
||||
transform: translateX(-4px);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&:active {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||||
@@ -688,7 +688,7 @@ export default {
|
||||
padding: 20px 12px;
|
||||
margin-bottom: 24px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -696,7 +696,7 @@ export default {
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 2px solid #f0f0f0;
|
||||
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
@@ -717,17 +717,17 @@ export default {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
|
||||
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
|
||||
}
|
||||
|
||||
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
|
||||
&.small {
|
||||
padding: 6px 16px;
|
||||
font-size: 13px;
|
||||
@@ -738,7 +738,7 @@ export default {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 10px;
|
||||
|
||||
|
||||
.category-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -748,17 +748,17 @@ export default {
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e5e7eb;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #f3f4f6;
|
||||
border-color: @primary-color;
|
||||
}
|
||||
|
||||
|
||||
.category-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
|
||||
.category-key {
|
||||
padding: 3px 10px;
|
||||
background: @primary-color;
|
||||
@@ -768,7 +768,7 @@ export default {
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
.category-name {
|
||||
font-size: 14px;
|
||||
color: @text-primary;
|
||||
@@ -778,7 +778,7 @@ export default {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
.category-sort {
|
||||
font-size: 12px;
|
||||
color: @primary-color;
|
||||
@@ -789,18 +789,18 @@ export default {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.category-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
|
||||
.category-count {
|
||||
font-size: 12px;
|
||||
color: @text-tertiary;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
.category-actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
@@ -811,11 +811,11 @@ export default {
|
||||
|
||||
.tool-group {
|
||||
margin-bottom: 24px;
|
||||
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
.tool-group-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -824,19 +824,19 @@ export default {
|
||||
padding: 12px 16px;
|
||||
background: #f9fafb;
|
||||
border-radius: 6px;
|
||||
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
color: @text-primary;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tool-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 10px;
|
||||
|
||||
|
||||
.tool-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -846,17 +846,17 @@ export default {
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e5e7eb;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #f3f4f6;
|
||||
border-color: @primary-color;
|
||||
}
|
||||
|
||||
|
||||
.tool-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
|
||||
.tool-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
@@ -869,11 +869,11 @@ export default {
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
||||
.tool-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
|
||||
.tool-name {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
@@ -883,7 +883,7 @@ export default {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
.tool-desc {
|
||||
font-size: 11px;
|
||||
color: @text-secondary;
|
||||
@@ -892,7 +892,7 @@ export default {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tool-sort {
|
||||
font-size: 11px;
|
||||
color: @primary-color;
|
||||
@@ -904,13 +904,13 @@ export default {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tool-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
|
||||
.tool-url {
|
||||
font-size: 10px;
|
||||
color: @text-tertiary;
|
||||
@@ -920,7 +920,7 @@ export default {
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
.tool-actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
@@ -941,12 +941,12 @@ button {
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #66b1ff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.delete-btn {
|
||||
padding: 5px 10px;
|
||||
background: #f56c6c;
|
||||
@@ -956,7 +956,7 @@ button {
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #f78989;
|
||||
}
|
||||
@@ -975,7 +975,7 @@ button {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2000;
|
||||
|
||||
|
||||
.dialog {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
@@ -983,29 +983,29 @@ button {
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||
|
||||
|
||||
h3 {
|
||||
margin: 0 0 20px;
|
||||
font-size: 20px;
|
||||
color: @text-primary;
|
||||
}
|
||||
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
color: @text-secondary;
|
||||
font-weight: 500;
|
||||
|
||||
|
||||
.required {
|
||||
color: #f56c6c;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
input, select {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
@@ -1014,31 +1014,31 @@ button {
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.2s ease;
|
||||
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: @primary-color;
|
||||
}
|
||||
|
||||
|
||||
&:disabled {
|
||||
background: #f5f7fa;
|
||||
color: #999;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
select {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 颜色选择器样式
|
||||
.color-picker {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, 1fr);
|
||||
gap: 8px;
|
||||
padding: 0 2px;
|
||||
|
||||
|
||||
.color-option {
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
@@ -1050,17 +1050,17 @@ button {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
||||
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
|
||||
&.active {
|
||||
border-color: @primary-color;
|
||||
box-shadow: 0 0 0 2px white, 0 0 0 4px @primary-color;
|
||||
}
|
||||
|
||||
|
||||
.check-icon {
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
@@ -1069,13 +1069,13 @@ button {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.dialog-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
|
||||
|
||||
button {
|
||||
padding: 10px 24px;
|
||||
border-radius: 6px;
|
||||
@@ -1083,23 +1083,23 @@ button {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
|
||||
.cancel-btn {
|
||||
background: white;
|
||||
border: 1px solid @border-color;
|
||||
color: @text-primary;
|
||||
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.confirm-btn {
|
||||
background: @primary-color;
|
||||
border: none;
|
||||
color: white;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #5568d3;
|
||||
}
|
||||
@@ -1117,28 +1117,28 @@ button {
|
||||
max-width: 400px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||
text-align: center;
|
||||
|
||||
|
||||
.confirm-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
|
||||
&.warning {
|
||||
color: #e6a23c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.confirm-message {
|
||||
font-size: 16px;
|
||||
color: @text-primary;
|
||||
margin-bottom: 24px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
|
||||
.confirm-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: center;
|
||||
|
||||
|
||||
button {
|
||||
padding: 10px 32px;
|
||||
border-radius: 6px;
|
||||
@@ -1147,30 +1147,30 @@ button {
|
||||
transition: all 0.2s ease;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
|
||||
.cancel-btn {
|
||||
background: white;
|
||||
border: 1px solid @border-color;
|
||||
color: @text-primary;
|
||||
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.confirm-btn {
|
||||
background: @primary-color;
|
||||
border: none;
|
||||
color: white;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #5568d3;
|
||||
}
|
||||
|
||||
|
||||
&.danger {
|
||||
background: #f56c6c;
|
||||
|
||||
|
||||
&:hover {
|
||||
background: #f78989;
|
||||
}
|
||||
@@ -1195,37 +1195,37 @@ button {
|
||||
z-index: 3000;
|
||||
min-width: 300px;
|
||||
justify-content: center;
|
||||
|
||||
|
||||
.message-icon {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
&.success {
|
||||
background: #f0f9ff;
|
||||
border: 1px solid #67c23a;
|
||||
color: #67c23a;
|
||||
|
||||
|
||||
.message-icon {
|
||||
color: #67c23a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.error {
|
||||
background: #fef0f0;
|
||||
border: 1px solid #f56c6c;
|
||||
color: #f56c6c;
|
||||
|
||||
|
||||
.message-icon {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.warning {
|
||||
background: #fdf6ec;
|
||||
border: 1px solid #e6a23c;
|
||||
color: #e6a23c;
|
||||
|
||||
|
||||
.message-icon {
|
||||
color: #e6a23c;
|
||||
}
|
||||
@@ -1253,32 +1253,32 @@ button {
|
||||
.manage-header {
|
||||
justify-content: flex-start; // 手机端左对齐
|
||||
padding: 20px;
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 24px; // 手机端与HomePage保持一致
|
||||
}
|
||||
|
||||
|
||||
.back-btn {
|
||||
right: 20px;
|
||||
padding: 10px 20px;
|
||||
font-size: 14px;
|
||||
|
||||
|
||||
&::before {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.manage-container {
|
||||
padding: 16px 8px;
|
||||
}
|
||||
|
||||
|
||||
.category-list {
|
||||
grid-template-columns: 1fr !important;
|
||||
}
|
||||
|
||||
|
||||
.tool-list {
|
||||
grid-template-columns: 1fr !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user