✨ feat: add draggable iframe for tutorial links and enhance platform configuration UI
This commit is contained in:
@@ -1,16 +1,69 @@
|
||||
<script setup lang="ts">
|
||||
import { shallowRef } from 'vue';
|
||||
import { ref, shallowRef } from 'vue';
|
||||
import { useCustomizerStore } from '../../../stores/customizer';
|
||||
import sidebarItems from './sidebarItem';
|
||||
import NavItem from './NavItem.vue';
|
||||
|
||||
const customizer = useCustomizerStore();
|
||||
const sidebarMenu = shallowRef(sidebarItems);
|
||||
|
||||
const showIframe = ref(false);
|
||||
|
||||
const iframeStyle = ref({
|
||||
position: 'fixed',
|
||||
bottom: '16px',
|
||||
right: '16px',
|
||||
width: '500px',
|
||||
height: '400px',
|
||||
border: '1px solid #ccc',
|
||||
background: 'white',
|
||||
resize: 'both',
|
||||
overflow: 'auto',
|
||||
zIndex: 10000000,
|
||||
borderRadius: '8px'
|
||||
});
|
||||
|
||||
const dragButtonStyle = {
|
||||
width: '100%',
|
||||
padding: '4px',
|
||||
cursor: 'move',
|
||||
background: '#f0f0f0',
|
||||
borderBottom: '1px solid #ccc',
|
||||
borderTopLeftRadius: '8px',
|
||||
borderTopRightRadius: '8px'
|
||||
};
|
||||
|
||||
function toggleIframe() {
|
||||
showIframe.value = !showIframe.value;
|
||||
}
|
||||
|
||||
let offsetX = 0;
|
||||
let offsetY = 0;
|
||||
let isDragging = false;
|
||||
|
||||
function onMouseDown(event) {
|
||||
isDragging = true;
|
||||
offsetX = event.clientX - event.target.parentElement.getBoundingClientRect().left;
|
||||
offsetY = event.clientY - event.target.parentElement.getBoundingClientRect().top;
|
||||
}
|
||||
|
||||
function onMouseMove(event) {
|
||||
if (isDragging) {
|
||||
const dm = document.getElementById('draggable-iframe');
|
||||
dm.style.left = (event.clientX - offsetX) + 'px';
|
||||
dm.style.top = (event.clientY - offsetY) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseUp() {
|
||||
isDragging = false;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-navigation-drawer left v-model="customizer.Sidebar_drawer" elevation="0" rail-width="80"
|
||||
app class="leftSidebar" :rail="customizer.mini_sidebar">
|
||||
<v-navigation-drawer left v-model="customizer.Sidebar_drawer" elevation="0" rail-width="80" app class="leftSidebar"
|
||||
:rail="customizer.mini_sidebar">
|
||||
<v-list class="pa-4 listitem" style="height: auto">
|
||||
<template v-for="(item, i) in sidebarMenu" :key="i">
|
||||
<NavItem :item="item" class="leftPadding" />
|
||||
@@ -21,9 +74,9 @@ const sidebarMenu = shallowRef(sidebarItems);
|
||||
</div>
|
||||
|
||||
<div style="position: absolute; bottom: 32px; width: 100%" class="text-center">
|
||||
<v-list-item v-if="!customizer.mini_sidebar" href="https://astrbot.app/">
|
||||
<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">构建: {{ buildVer }}</small>
|
||||
@@ -34,11 +87,23 @@ const sidebarMenu = shallowRef(sidebarItems);
|
||||
</template>
|
||||
</v-tooltip>
|
||||
|
||||
|
||||
|
||||
<small style="display: block; margin-top: 8px;">© 2025 AstrBot</small>
|
||||
</div>
|
||||
|
||||
</v-navigation-drawer>
|
||||
|
||||
<div v-if="showIframe"
|
||||
id="draggable-iframe"
|
||||
:style="iframeStyle"
|
||||
@mousemove="onMouseMove"
|
||||
@mouseup="onMouseUp"
|
||||
@mouseleave="onMouseUp">
|
||||
<div :style="dragButtonStyle" @mousedown="onMouseDown">
|
||||
<v-icon icon="mdi-cursor-move" />
|
||||
</div>
|
||||
<iframe src="https://astrbot.app" style="width: 100%; height: calc(100% - 24px); border: none; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -9,6 +9,17 @@ export const useCommonStore = defineStore({
|
||||
log_cache: [],
|
||||
log_cache_max_len: 1000,
|
||||
startTime: -1,
|
||||
|
||||
tutorial_map: {
|
||||
"qq_official_webhook": "https://astrbot.app/deploy/platform/qqofficial/webhook.html",
|
||||
"qq_official": "https://astrbot.app/deploy/platform/qqofficial/websockets.html",
|
||||
"aiocqhttp": "https://astrbot.app/deploy/platform/aiocqhttp/napcat.html",
|
||||
"wecom": "https://astrbot.app/deploy/platform/wecom.html",
|
||||
"gewechat": "https://astrbot.app/deploy/platform/gewechat.html",
|
||||
"lark": "https://astrbot.app/deploy/platform/lark.html",
|
||||
"telegram": "https://astrbot.app/deploy/platform/telegram.html",
|
||||
}
|
||||
|
||||
}),
|
||||
actions: {
|
||||
createWebSocket() {
|
||||
@@ -39,5 +50,8 @@ export const useCommonStore = defineStore({
|
||||
this.startTime = res.data.data.start_time
|
||||
})
|
||||
},
|
||||
getTutorialLink(platform) {
|
||||
return this.tutorial_map[platform]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -47,14 +47,29 @@
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-dialog v-model="showPlatformCfg" width="700">
|
||||
<v-dialog v-model="showPlatformCfg">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="text-h4">{{ newSelectedPlatformName }} 配置</span>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<AstrBotConfig :iterable="newSelectedPlatformConfig"
|
||||
:metadata="metadata['platform_group']['metadata']" metadataKey="platform" />
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<AstrBotConfig :iterable="newSelectedPlatformConfig"
|
||||
:metadata="metadata['platform_group']['metadata']" metadataKey="platform" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-btn :loading="iframeLoading" @click="refreshIframe" variant="tonal" color="primary" style="float: right;">
|
||||
<v-icon>mdi-refresh</v-icon>
|
||||
刷新
|
||||
</v-btn>
|
||||
<iframe v-show="!iframeLoading"
|
||||
:src="store.getTutorialLink(newSelectedPlatformConfig.type)"
|
||||
@load="iframeLoading = false" style="width: 100%; border: none; height: 100%;">
|
||||
</iframe>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
@@ -66,7 +81,8 @@
|
||||
</v-dialog>
|
||||
|
||||
|
||||
<v-btn style="margin-top: 16px" class="flex-grow-1" variant="tonal" size="large" rounded="lg" color="gray" @click="showConsole = !showConsole">
|
||||
<v-btn style="margin-top: 16px" class="flex-grow-1" variant="tonal" size="large" rounded="lg" color="gray"
|
||||
@click="showConsole = !showConsole">
|
||||
<template v-slot:default>
|
||||
<v-icon>mdi-console-line</v-icon>
|
||||
{{ showConsole ? '隐藏' : '显示' }}日志
|
||||
@@ -91,6 +107,7 @@ import axios from 'axios';
|
||||
import AstrBotConfig from '@/components/shared/AstrBotConfig.vue';
|
||||
import WaitingForRestart from '@/components/shared/WaitingForRestart.vue';
|
||||
import ConsoleDisplayer from '@/components/shared/ConsoleDisplayer.vue';
|
||||
import { useCommonStore } from '@/stores/common';
|
||||
|
||||
export default {
|
||||
name: 'PlatformPage',
|
||||
@@ -117,6 +134,9 @@ export default {
|
||||
save_message_success: "",
|
||||
|
||||
showConsole: false,
|
||||
iframeLoading: true,
|
||||
|
||||
store: useCommonStore()
|
||||
}
|
||||
},
|
||||
|
||||
@@ -125,6 +145,12 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
refreshIframe() {
|
||||
this.iframeLoading = true;
|
||||
const iframe = document.querySelector('iframe');
|
||||
console.log(iframe.src);
|
||||
iframe.src = iframe.src + '?t=' + new Date().getTime();
|
||||
},
|
||||
getConfig() {
|
||||
// 获取配置
|
||||
axios.get('/api/config/get').then((res) => {
|
||||
|
||||
Reference in New Issue
Block a user