perf: 优化 WebUI About 页面、侧边栏和顶栏
This commit is contained in:
@@ -8,6 +8,7 @@ from quart import request
|
||||
from astrbot.core.core_lifecycle import AstrBotCoreLifecycle
|
||||
from astrbot.core.db import BaseDatabase
|
||||
from astrbot.core.config import VERSION
|
||||
from astrbot.core.utils.io import get_dashboard_version
|
||||
from astrbot.core import DEMO_MODE
|
||||
|
||||
|
||||
@@ -46,7 +47,10 @@ class StatRoute(Route):
|
||||
return f"{h}小时{m}分{s}秒"
|
||||
|
||||
async def get_version(self):
|
||||
return Response().ok({"version": VERSION}).__dict__
|
||||
return Response().ok({
|
||||
"version": VERSION,
|
||||
"dashboard_version": await get_dashboard_version(),
|
||||
}).__dict__
|
||||
|
||||
async def get_start_time(self):
|
||||
return Response().ok({"start_time": self.core_lifecycle.start_time}).__dict__
|
||||
|
||||
@@ -78,6 +78,17 @@ function accountEdit() {
|
||||
});
|
||||
}
|
||||
|
||||
function getVersion() {
|
||||
axios.get('/api/stat/version')
|
||||
.then((res) => {
|
||||
botCurrVersion.value = "v" + res.data.data.version;
|
||||
dashboardCurrentVersion.value = res.data.data?.dashboard_version;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
updateStatus.value = '正在检查更新...';
|
||||
axios.get('/api/update/check')
|
||||
@@ -90,8 +101,6 @@ function checkUpdate() {
|
||||
} else {
|
||||
updateStatus.value = res.data.message;
|
||||
}
|
||||
botCurrVersion.value = res.data.data.version;
|
||||
dashboardCurrentVersion.value = res.data.data.dashboard_version;
|
||||
dashboardHasNewVersion.value = res.data.data.dashboard_has_new_version;
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -181,6 +190,7 @@ function updateDashboard() {
|
||||
});
|
||||
}
|
||||
|
||||
getVersion();
|
||||
checkUpdate();
|
||||
|
||||
const commonStore = useCommonStore();
|
||||
@@ -208,23 +218,29 @@ if (localStorage.getItem('change_pwd_hint') != null && localStorage.getItem('cha
|
||||
<v-icon>mdi-menu</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<span style="margin-left: 16px; font-size: 24px; font-weight: 1000;">Astr<span
|
||||
style="font-weight: normal;">Bot</span></span>
|
||||
<div style="margin-left: 16px; display: flex; align-items: center; gap: 8px;">
|
||||
<span style=" font-size: 24px; font-weight: 1000;">Astr<span style="font-weight: normal;">Bot</span>
|
||||
</span>
|
||||
<span style="font-size: 12px; color: #333333;">{{ botCurrVersion }}</span>
|
||||
</div>
|
||||
|
||||
<v-spacer />
|
||||
|
||||
<div class="mr-4">
|
||||
<small v-if="hasNewVersion">
|
||||
有新版本!
|
||||
AstrBot 有新版本!
|
||||
</small>
|
||||
<small v-else-if="dashboardHasNewVersion">
|
||||
WebUI 有新版本!
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
<v-dialog v-model="updateStatusDialog" width="1000">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn @click="checkUpdate(); getReleases(); getDevCommits();" class="text-primary mr-4" color="lightprimary"
|
||||
<v-btn size="small" @click="checkUpdate(); getReleases(); getDevCommits();" class="text-primary mr-2" color="lightprimary"
|
||||
variant="flat" rounded="sm" v-bind="props">
|
||||
更新 🔄
|
||||
更新
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
@@ -353,8 +369,8 @@ if (localStorage.getItem('change_pwd_hint') != null && localStorage.getItem('cha
|
||||
|
||||
<v-dialog v-model="dialog" persistent width="700">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn class="text-primary mr-4" color="lightprimary" variant="flat" rounded="sm" v-bind="props">
|
||||
账户 📰
|
||||
<v-btn size="small" class="text-primary mr-4" color="lightprimary" variant="flat" rounded="sm" v-bind="props">
|
||||
账户
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
|
||||
@@ -9,9 +9,6 @@ const customizer = useCustomizerStore();
|
||||
const sidebarMenu = shallowRef(sidebarItems);
|
||||
|
||||
const showIframe = ref(false);
|
||||
const version = ref("");
|
||||
const buildVer = ref("");
|
||||
const hasWebUIUpdate = ref(false);
|
||||
|
||||
// 默认桌面端 iframe 样式
|
||||
const iframeStyle = ref({
|
||||
@@ -68,9 +65,10 @@ function toggleIframe() {
|
||||
showIframe.value = !showIframe.value;
|
||||
}
|
||||
|
||||
function openIframeLink() {
|
||||
function openIframeLink(url) {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.open("https://astrbot.app", "_blank");
|
||||
let url_ = url || "https://astrbot.app";
|
||||
window.open(url_, "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,25 +147,6 @@ function endDrag() {
|
||||
document.removeEventListener('touchend', onTouchEnd);
|
||||
}
|
||||
|
||||
// 获取版本和更新信息
|
||||
onMounted(() => {
|
||||
axios.get('/api/stat/version')
|
||||
.then((res) => {
|
||||
version.value = "v" + res.data.data.version;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
axios.get('/api/update/check?type=dashboard')
|
||||
.then((res) => {
|
||||
hasWebUIUpdate.value = res.data.data.has_new_version;
|
||||
buildVer.value = res.data.data.current_version;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -186,27 +165,19 @@ onMounted(() => {
|
||||
<NavItem :item="item" class="leftPadding" />
|
||||
</template>
|
||||
</v-list>
|
||||
<div class="text-center">
|
||||
<v-chip color="inputBorder" size="small"> {{ version }} </v-chip>
|
||||
</div>
|
||||
<div style="position: absolute; bottom: 32px; width: 100%; font-size: 13px;" class="text-center">
|
||||
<v-list-item v-if="!customizer.mini_sidebar" @click="toggleIframe">
|
||||
<v-btn variant="plain" size="small">
|
||||
🤔 点击此处 查看/关闭 悬浮文档!
|
||||
</v-btn>
|
||||
</v-list-item>
|
||||
<small style="display: block;" v-if="buildVer">WebUI 版本: {{ buildVer }}</small>
|
||||
<small style="display: block;" v-else>构建: embedded</small>
|
||||
<v-tooltip text="使用 /dashboard_update 指令更新管理面板">
|
||||
<template v-slot:activator="{ props }">
|
||||
<small v-bind="props" v-if="hasWebUIUpdate" style="display: block; margin-top: 4px;">面板有更新</small>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<small style="display: block; margin-top: 8px;">AGPL-3.0</small>
|
||||
<div style="position: absolute; bottom: 16px; width: 100%; font-size: 13px;" class="text-center">
|
||||
<v-btn style="margin-bottom: 8px;" size="small" variant="plain" v-if="!customizer.mini_sidebar" @click="toggleIframe">
|
||||
官方文档
|
||||
</v-btn>
|
||||
<br/>
|
||||
<v-btn style="margin-bottom: 8px;" size="small" variant="plain" v-if="!customizer.mini_sidebar" @click="openIframeLink('https://github.com/AstrBotDevs/AstrBot')">
|
||||
GitHub
|
||||
</v-btn>
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
</v-navigation-drawer>
|
||||
|
||||
<!-- 优化后的悬浮 iframe -->
|
||||
<div
|
||||
v-if="showIframe"
|
||||
id="draggable-iframe"
|
||||
|
||||
@@ -1,54 +1,84 @@
|
||||
<template>
|
||||
<v-card style="height: 100%;">
|
||||
<v-card-text style="padding: 0; height: 100%; overflow-y: auto;">
|
||||
<div
|
||||
style="display: flex; justify-content: center; align-items: center; height: 100%; flex-direction: column;">
|
||||
<div @click="selectedLogo = selectedLogo == 0 ? 1 : 0" style="height: 300px;">
|
||||
<img v-if="selectedLogo == 0" width="300" src="@/assets/images/logo-waifu.png" alt="AstrBot Logo"
|
||||
class="fade-in">
|
||||
<img v-if="selectedLogo == 1" width="300" src="@/assets/images/logo-normal.svg" alt="AstrBot Logo"
|
||||
class="fade-in">
|
||||
</div>
|
||||
<v-card style="height: 100%;" elevation="0" class="bg-surface">
|
||||
<v-card-text style="padding: 0; height: 100%; overflow-y: hidden;">
|
||||
<div class="about-wrapper">
|
||||
<!-- Hero Section -->
|
||||
<section class="hero-section">
|
||||
<div class="logo-title-container">
|
||||
<div @click="selectedLogo = selectedLogo == 0 ? 1 : 0" class="logo-container">
|
||||
<img v-if="selectedLogo == 0" width="280" src="@/assets/images/logo-waifu.png" alt="AstrBot Logo" class="fade-in">
|
||||
<img v-if="selectedLogo == 1" width="280" src="@/assets/images/logo-normal.svg" alt="AstrBot Logo" class="fade-in">
|
||||
</div>
|
||||
<div class="title-container">
|
||||
<h1 class="text-h2 font-weight-bold">AstrBot</h1>
|
||||
<p class="text-subtitle-1" style="color: #777;">A project out of interests and loves ❤️</p>
|
||||
<div class="action-buttons">
|
||||
<v-btn @click="open('https://github.com/Soulter/AstrBot')"
|
||||
color="primary" variant="elevated" prepend-icon="mdi-star">
|
||||
Star 这个项目! 🌟
|
||||
</v-btn>
|
||||
<v-btn class="ml-4" @click="open('https://github.com/Soulter/AstrBot/issues')"
|
||||
color="secondary" variant="elevated" prepend-icon="mdi-comment-question">
|
||||
提交 Issue
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<h1 class="mt-8">AstrBot</h1>
|
||||
<!-- Contributors Section -->
|
||||
<section class="contributors-section">
|
||||
<v-container>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" md="6" class="pr-md-8 contributors-info">
|
||||
<h2 class="text-h4 font-weight-medium">贡献者</h2>
|
||||
<p class="mb-4 text-body-1" style="color: #777;">
|
||||
本项目由众多开源社区成员共同维护。感谢每一位贡献者的付出!
|
||||
</p>
|
||||
<p class="text-body-1" style="color: #777;">
|
||||
<a href="https://github.com/Soulter/AstrBot/graphs/contributors" class="text-decoration-none custom-link">查看 AstrBot 贡献者</a>
|
||||
</p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-card variant="outlined" class="overflow-hidden" elevation="2">
|
||||
<v-img
|
||||
alt="Active Contributors of Soulter/AstrBot"
|
||||
src="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=575865240&limit=365&image_size=auto&color_scheme=light">
|
||||
</v-img>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</section>
|
||||
|
||||
<span class="mt-2" style="color: #777;">A project out of interests and loves ❤️</span>
|
||||
|
||||
<span style="color: #777; margin-left: 32px; margin-right: 32px" class="mt-4">By <a
|
||||
href="https://soulter.top">Soulter</a>, <a
|
||||
href="https://github.com/Soulter/AstrBot/graphs/contributors">AstrBot Contributors</a>
|
||||
and <a href="https://github.com/Soulter/AstrBot_Plugins_Collection/graphs/contributors">AstrBot
|
||||
Plugin Authors</a>
|
||||
</span>
|
||||
|
||||
<!-- Copy-paste in your Readme.md file -->
|
||||
|
||||
<img style="margin-top: 16px; width: 50%; max-width: 500px; margin-left: 32px; margin-right: 32px"
|
||||
alt="Active Contributors of Soulter/AstrBot - Last 28 days"
|
||||
src="https://next.ossinsight.io/widgets/official/compose-recent-active-contributors/thumbnail.png?repo_id=575865240&limit=365&image_size=auto&color_scheme=light">
|
||||
|
||||
<img style="margin-top: 16px; width: 50%; max-width: 500px; margin-left: 32px; margin-right: 32px"
|
||||
alt="Active Contributors of Soulter/AstrBot - Last 28 days"
|
||||
src="https://next.ossinsight.io/widgets/official/analyze-repo-stars-map/thumbnail.png?activity=stars&repo_id=575865240&image_size=auto&color_scheme=light
|
||||
">
|
||||
|
||||
|
||||
<!-- Made with [OSS Insight](https://ossinsight.io/) -->
|
||||
|
||||
<v-btn class="text-primary mt-8" @click="open('https://github.com/Soulter/AstrBot')"
|
||||
color="lightprimary" variant="flat" rounded="sm">
|
||||
Star 这个项目! 🌟
|
||||
</v-btn>
|
||||
|
||||
<v-btn class="text-primary mt-4" @click="open('https://github.com/Soulter/AstrBot/issues')"
|
||||
color="lightprimary" variant="flat" rounded="sm">
|
||||
有使用问题或者功能建议?提交 Issue!
|
||||
</v-btn>
|
||||
<!-- Stats Section -->
|
||||
<section class="stats-section">
|
||||
<v-container>
|
||||
<v-row justify="center" align="center" class="flex-md-row-reverse">
|
||||
<v-col cols="12" md="6" class="pl-md-8 stats-info">
|
||||
<h2 class="text-h4 font-weight-medium">全球部署</h2>
|
||||
|
||||
<div class="license-container mt-8">
|
||||
<img v-bind="props" src="https://www.gnu.org/graphics/agplv3-with-text-100x42.png" style="cursor: pointer;"/>
|
||||
<p class="text-caption mt-2" style="color: #777;">AstrBot 采用 AGPL v3 协议开源</p>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-card variant="outlined" class="overflow-hidden" elevation="2">
|
||||
<v-img
|
||||
alt="Stars Map of Soulter/AstrBot"
|
||||
src="https://next.ossinsight.io/widgets/official/analyze-repo-stars-map/thumbnail.png?activity=stars&repo_id=575865240&image_size=auto&color_scheme=light">
|
||||
</v-img>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AboutPage',
|
||||
@@ -64,21 +94,135 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
<style scoped>
|
||||
.about-wrapper {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
.hero-section {
|
||||
padding: 40px 20px;
|
||||
background: linear-gradient(to right bottom, rgba(255,255,255,0.7), rgba(240,240,250,0.3));
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo-title-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
max-width: 900px;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.logo-container:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.title-container {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.contributors-section, .stats-section {
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.contributors-section {
|
||||
background-color: #f9f9fb;
|
||||
}
|
||||
|
||||
.contributors-info, .stats-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.custom-link {
|
||||
display: inline-block;
|
||||
padding: 5px 0;
|
||||
position: relative;
|
||||
color: var(--v-primary-base);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.custom-link::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
transform: scaleX(0);
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: var(--v-primary-base);
|
||||
transform-origin: bottom right;
|
||||
transition: transform 0.25s ease-out;
|
||||
}
|
||||
|
||||
.custom-link:hover::after {
|
||||
transform: scaleX(1);
|
||||
transform-origin: bottom left;
|
||||
}
|
||||
|
||||
.license-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
animation: fadeIn 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.logo-title-container {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.license-container {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.contributors-section, .stats-section {
|
||||
padding: 40px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.action-buttons {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.action-buttons .v-btn + .v-btn {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user