mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-17 01:49:15 +08:00
feat: add backend URL preset sharing via URL parameters
- Add URL param support (?api_url=, ?username=) for shareable config - Add share link button to server config dialog - Fix ToolSet API bug: tools.func_list -> tools.list_tools() - Fix Vue template bugs in CommandTable.vue (orphaned v-else, wrong prop) - Use master version of InstalledPluginsTab.vue (dev had pre-existing bugs) BREAKING CHANGE: Uses master version for InstalledPluginsTab.vue
This commit is contained in:
@@ -549,7 +549,7 @@ class ProviderOpenAIOfficial(Provider):
|
|||||||
# 工具集未提供
|
# 工具集未提供
|
||||||
# Should be unreachable
|
# Should be unreachable
|
||||||
raise Exception("工具集未提供")
|
raise Exception("工具集未提供")
|
||||||
for tool in tools.func_list:
|
for tool in tools.list_tools():
|
||||||
if (
|
if (
|
||||||
tool_call.type == "function"
|
tool_call.type == "function"
|
||||||
and tool.name == tool_call.function.name
|
and tool.name == tool_call.function.name
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ const canEditPermission = (cmd: CommandItem): boolean => cmd.supports_permission
|
|||||||
<v-data-table
|
<v-data-table
|
||||||
:headers="commandHeaders"
|
:headers="commandHeaders"
|
||||||
:items="items"
|
:items="items"
|
||||||
item-value="command_key"
|
item-key="handler_full_name"
|
||||||
hover
|
hover
|
||||||
:row-props="getRowProps"
|
:row-props="getRowProps"
|
||||||
:loading="props.loading"
|
:loading="props.loading"
|
||||||
@@ -201,14 +201,6 @@ const canEditPermission = (cmd: CommandItem): boolean => cmd.supports_permission
|
|||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
<v-chip
|
|
||||||
v-else
|
|
||||||
:color="getPermissionColor(item.permission)"
|
|
||||||
size="small"
|
|
||||||
class="font-weight-medium"
|
|
||||||
>
|
|
||||||
{{ getPermissionLabel(item.permission) }}
|
|
||||||
</v-chip>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #item.enabled="{ item }">
|
<template #item.enabled="{ item }">
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
"username": "Username",
|
"username": "Username",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"defaultHint": "Default username: astrbot. Run `astrbot conf admin` before the first login.",
|
"defaultHint": "Default username: astrbot. Run `astrbot conf admin` before the first login.",
|
||||||
|
"shareLink": "Share Link",
|
||||||
|
"linkCopied": "Link copied to clipboard",
|
||||||
|
"linkCopyFailed": "Failed to copy link",
|
||||||
"logo": {
|
"logo": {
|
||||||
"title": "AstrBot Dashboard",
|
"title": "AstrBot Dashboard",
|
||||||
"subtitle": "Welcome"
|
"subtitle": "Welcome"
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
"username": "用户名",
|
"username": "用户名",
|
||||||
"password": "密码",
|
"password": "密码",
|
||||||
"defaultHint": "默认账户为:astrbot,请先执行 `astrbot conf admin` 设置密码",
|
"defaultHint": "默认账户为:astrbot,请先执行 `astrbot conf admin` 设置密码",
|
||||||
|
"shareLink": "分享链接",
|
||||||
|
"linkCopied": "链接已复制到剪贴板",
|
||||||
|
"linkCopyFailed": "复制链接失败",
|
||||||
"logo": {
|
"logo": {
|
||||||
"title": "AstrBot WebUI",
|
"title": "AstrBot WebUI",
|
||||||
"subtitle": "欢迎使用"
|
"subtitle": "欢迎使用"
|
||||||
|
|||||||
@@ -21,6 +21,42 @@ const toast = useToast();
|
|||||||
const serverConfigDialog = ref(false);
|
const serverConfigDialog = ref(false);
|
||||||
const apiUrl = ref(apiStore.apiBaseUrl);
|
const apiUrl = ref(apiStore.apiBaseUrl);
|
||||||
|
|
||||||
|
// URL parameter handling for shareable config
|
||||||
|
function applyUrlParams() {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const apiUrlParam = params.get("api_url");
|
||||||
|
const usernameParam = params.get("username");
|
||||||
|
if (apiUrlParam) {
|
||||||
|
apiUrl.value = apiUrlParam;
|
||||||
|
const validationError = getApiBaseUrlValidationError(apiUrlParam);
|
||||||
|
if (!validationError) {
|
||||||
|
apiStore.setApiBaseUrl(apiUrlParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (usernameParam) {
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent("astrbot-url-param-username", {
|
||||||
|
detail: { username: usernameParam },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getShareableUrl() {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
url.searchParams.set("api_url", apiUrl.value);
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyShareableUrl() {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(getShareableUrl());
|
||||||
|
toast.success(t("linkCopied"));
|
||||||
|
} catch {
|
||||||
|
toast.error(t("linkCopyFailed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const showAddPreset = ref(false);
|
const showAddPreset = ref(false);
|
||||||
const newPresetName = ref("");
|
const newPresetName = ref("");
|
||||||
const newPresetUrl = ref("");
|
const newPresetUrl = ref("");
|
||||||
@@ -58,6 +94,9 @@ function toggleTheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// 应用URL参数(用于分享预设配置)
|
||||||
|
applyUrlParams();
|
||||||
|
|
||||||
// 检查用户是否已登录,如果已登录则重定向
|
// 检查用户是否已登录,如果已登录则重定向
|
||||||
if (authStore.has_token()) {
|
if (authStore.has_token()) {
|
||||||
router.push(authStore.returnUrl || "/");
|
router.push(authStore.returnUrl || "/");
|
||||||
@@ -257,6 +296,17 @@ onMounted(() => {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
density="compact"
|
density="compact"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
variant="tonal"
|
||||||
|
size="small"
|
||||||
|
block
|
||||||
|
class="mt-2"
|
||||||
|
prepend-icon="mdi-share-variant"
|
||||||
|
@click="copyShareableUrl"
|
||||||
|
>
|
||||||
|
{{ t("shareLink") }}
|
||||||
|
</v-btn>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref, onMounted, onUnmounted } from "vue";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
import { Form } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
import { useModuleI18n } from "@/i18n/composables";
|
import { useModuleI18n } from "@/i18n/composables";
|
||||||
@@ -11,6 +11,27 @@ const password = ref("");
|
|||||||
const username = ref("");
|
const username = ref("");
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// 从URL参数读取用户名
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const usernameParam = params.get("username");
|
||||||
|
if (usernameParam) {
|
||||||
|
username.value = usernameParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听从LoginPage传来的用户名参数
|
||||||
|
function handleUsernameParam(event: Event) {
|
||||||
|
const customEvent = event as CustomEvent<{ username: string }>;
|
||||||
|
username.value = customEvent.detail.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener("astrbot-url-param-username", handleUsernameParam);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener("astrbot-url-param-username", handleUsernameParam);
|
||||||
|
});
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
async function validate(_values: any, { setErrors }: any) {
|
async function validate(_values: any, { setErrors }: any) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user