feat: 移除侧边栏中的上游网址快捷入口,并在上游管理列表各条记录操作列增加官网跳转按钮
This commit is contained in:
@@ -56,42 +56,6 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sidebar-divider" />
|
|
||||||
|
|
||||||
<div class="sidebar-section sidebar-section-pages">
|
|
||||||
<div class="sidebar-section-head">
|
|
||||||
<div>
|
|
||||||
<div class="sidebar-section-title">上游网址</div>
|
|
||||||
<p class="sidebar-section-note">外部控制台快捷入口</p>
|
|
||||||
</div>
|
|
||||||
<router-link to="/custom-pages" class="nav-manage-link" title="管理上游网址" @click="closeMobileNav">
|
|
||||||
<el-icon><Setting /></el-icon>
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="custom-page-stack">
|
|
||||||
<template v-if="customPages.length > 0">
|
|
||||||
<a
|
|
||||||
v-for="page in customPages"
|
|
||||||
:key="page.id"
|
|
||||||
class="nav-item nav-item-custom"
|
|
||||||
href="#"
|
|
||||||
@click.prevent="openCustomPage(page)"
|
|
||||||
>
|
|
||||||
<span class="nav-icon"><el-icon><component :is="iconMap[page.icon] || LinkIcon" /></el-icon></span>
|
|
||||||
<span class="nav-copy">
|
|
||||||
<strong class="nav-custom-label">{{ page.name }}</strong>
|
|
||||||
<small>{{ page.description || '外部控制台入口' }}</small>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
<router-link v-else to="/custom-pages" class="add-page-link" @click="closeMobileNav">
|
|
||||||
<el-icon><Plus /></el-icon>
|
|
||||||
<span>添加网址</span>
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<div class="main-wrap">
|
<div class="main-wrap">
|
||||||
@@ -124,26 +88,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onUnmounted, markRaw } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import {
|
import {
|
||||||
Link as LinkIcon,
|
|
||||||
Plus,
|
|
||||||
Setting,
|
|
||||||
Close,
|
Close,
|
||||||
Monitor,
|
Monitor,
|
||||||
SetUp,
|
|
||||||
Reading,
|
|
||||||
Cpu,
|
|
||||||
DataLine,
|
|
||||||
Grid,
|
|
||||||
Ticket,
|
|
||||||
Wallet,
|
|
||||||
Key,
|
|
||||||
Tools,
|
|
||||||
Star,
|
|
||||||
House,
|
|
||||||
OfficeBuilding,
|
OfficeBuilding,
|
||||||
Connection,
|
Connection,
|
||||||
Bell,
|
Bell,
|
||||||
@@ -152,66 +102,19 @@ import {
|
|||||||
SwitchButton,
|
SwitchButton,
|
||||||
Operation,
|
Operation,
|
||||||
} from '@element-plus/icons-vue'
|
} from '@element-plus/icons-vue'
|
||||||
import { customPagesApi, type CustomPageData } from '@/api'
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
const mobileNavOpen = ref(false)
|
const mobileNavOpen = ref(false)
|
||||||
|
|
||||||
const iconMap: Record<string, any> = {
|
|
||||||
Link: markRaw(LinkIcon),
|
|
||||||
Monitor: markRaw(Monitor),
|
|
||||||
SetUp: markRaw(SetUp),
|
|
||||||
Reading: markRaw(Reading),
|
|
||||||
Cpu: markRaw(Cpu),
|
|
||||||
DataLine: markRaw(DataLine),
|
|
||||||
Grid: markRaw(Grid),
|
|
||||||
Ticket: markRaw(Ticket),
|
|
||||||
Wallet: markRaw(Wallet),
|
|
||||||
Key: markRaw(Key),
|
|
||||||
Tools: markRaw(Tools),
|
|
||||||
Star: markRaw(Star),
|
|
||||||
House: markRaw(House),
|
|
||||||
}
|
|
||||||
|
|
||||||
const customPages = ref<CustomPageData[]>([])
|
|
||||||
|
|
||||||
async function loadCustomPages() {
|
|
||||||
try {
|
|
||||||
const res = await customPagesApi.list()
|
|
||||||
customPages.value = res.data.filter((page) => page.enabled)
|
|
||||||
} catch {
|
|
||||||
// sidebar data is non-blocking
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPagesUpdated() {
|
|
||||||
loadCustomPages()
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeMobileNav() {
|
function closeMobileNav() {
|
||||||
mobileNavOpen.value = false
|
mobileNavOpen.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function openCustomPage(page: CustomPageData) {
|
|
||||||
closeMobileNav()
|
|
||||||
window.open(page.url, '_blank', 'noopener,noreferrer')
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleLogout() {
|
function handleLogout() {
|
||||||
auth.clear()
|
auth.clear()
|
||||||
router.push('/login')
|
router.push('/login')
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
loadCustomPages()
|
|
||||||
window.addEventListener('custom-pages-updated', onPagesUpdated)
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
window.removeEventListener('custom-pages-updated', onPagesUpdated)
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -353,32 +256,11 @@ onUnmounted(() => {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-section-head {
|
.sidebar-nav {
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-section-note {
|
|
||||||
margin-top: 0.35rem;
|
|
||||||
color: var(--text-soft);
|
|
||||||
font-size: 0.82rem;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-nav,
|
|
||||||
.custom-page-stack {
|
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.55rem;
|
gap: 0.55rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-divider {
|
|
||||||
height: 1px;
|
|
||||||
margin: 0 0.4rem;
|
|
||||||
background: linear-gradient(90deg, transparent, var(--border-color), transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
@@ -443,20 +325,6 @@ onUnmounted(() => {
|
|||||||
line-height: 1.45;
|
line-height: 1.45;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-manage-link,
|
|
||||||
.add-page-link {
|
|
||||||
min-height: 2.75rem;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 0.45rem;
|
|
||||||
padding: 0.7rem 0.95rem;
|
|
||||||
border-radius: 0.95rem;
|
|
||||||
border: 1px solid var(--border-color);
|
|
||||||
color: var(--text-secondary);
|
|
||||||
text-decoration: none;
|
|
||||||
background: rgba(255, 244, 232, 0.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-wrap {
|
.main-wrap {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@@ -91,9 +91,10 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="操作" width="280">
|
<el-table-column label="操作" width="320">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div class="action-row">
|
<div class="action-row">
|
||||||
|
<el-button size="small" text :disabled="!row.base_url" @click="openOfficialSite(row)" title="在新标签页中打开上游官网">官网</el-button>
|
||||||
<el-button size="small" text @click="openEdit(row)" title="编辑上游配置(认证、接口、余额等)">编辑</el-button>
|
<el-button size="small" text @click="openEdit(row)" title="编辑上游配置(认证、接口、余额等)">编辑</el-button>
|
||||||
<el-button size="small" text @click="testUpstream(row)" :loading="row._testing" title="仅验证连通性:登录 + 拉取分组列表,不写快照、不触发通知">测试连接</el-button>
|
<el-button size="small" text @click="testUpstream(row)" :loading="row._testing" title="仅验证连通性:登录 + 拉取分组列表,不写快照、不触发通知">测试连接</el-button>
|
||||||
<el-button size="small" text @click="checkNow(row)" :loading="row._checking" title="完整同步:拉取倍率 → 生成快照 → 对比变化 → 触发 Webhook → 同步 Key">立即同步</el-button>
|
<el-button size="small" text @click="checkNow(row)" :loading="row._checking" title="完整同步:拉取倍率 → 生成快照 → 对比变化 → 触发 Webhook → 同步 Key">立即同步</el-button>
|
||||||
@@ -977,6 +978,11 @@ function openCreate() {
|
|||||||
drawerVisible.value = true
|
drawerVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openOfficialSite(row: UpstreamData) {
|
||||||
|
if (!row.base_url) return
|
||||||
|
window.open(row.base_url, '_blank', 'noopener,noreferrer')
|
||||||
|
}
|
||||||
|
|
||||||
function openEdit(row: UpstreamData) {
|
function openEdit(row: UpstreamData) {
|
||||||
editingId.value = row.id
|
editingId.value = row.id
|
||||||
quickPlatform.value = inferPlatform(row)
|
quickPlatform.value = inferPlatform(row)
|
||||||
|
|||||||
Reference in New Issue
Block a user