@@ -46,7 +40,30 @@ import { EventSourcePolyfill } from "event-source-polyfill";
-
diff --git a/dashboard/src/components/shared/PluginSetSelector.vue b/dashboard/src/components/shared/PluginSetSelector.vue
index 279256ba0..c3435a6ee 100644
--- a/dashboard/src/components/shared/PluginSetSelector.vue
+++ b/dashboard/src/components/shared/PluginSetSelector.vue
@@ -145,11 +145,18 @@ const props = defineProps({
const emit = defineEmits(["update:modelValue"]);
const { tm } = useModuleI18n("core.shared");
+interface PluginEntry {
+ name: string;
+ desc?: string;
+ activated: boolean;
+ reserved: boolean;
+}
+
const dialog = ref(false);
-const pluginList = ref([]);
+const pluginList = ref
([]);
const loading = ref(false);
const selectionMode = ref("custom"); // 'all', 'none', 'custom'
-const selectedPlugins = ref([]);
+const selectedPlugins = ref([]);
// 判断是否为"所有插件"模式
const isAllPlugins = computed(() => {
@@ -160,18 +167,11 @@ const isAllPlugins = computed(() => {
);
});
-// 移除插件
-function removePlugin(pluginName) {
- if (props.modelValue && props.modelValue.length > 0) {
- const newValue = props.modelValue.filter((name) => name !== pluginName);
- emit("update:modelValue", newValue);
- }
-}
// 监听 modelValue 变化,同步内部状态
watch(
() => props.modelValue,
- (newValue) => {
+ (newValue: unknown[]) => {
if (!newValue || newValue.length === 0) {
selectionMode.value = "none";
selectedPlugins.value = [];
@@ -180,7 +180,7 @@ watch(
selectedPlugins.value = [];
} else {
selectionMode.value = "custom";
- selectedPlugins.value = [...newValue];
+ selectedPlugins.value = [...newValue] as string[];
}
},
{ immediate: true },
@@ -243,7 +243,7 @@ function cancelSelection() {
selectedPlugins.value = [];
} else {
selectionMode.value = "custom";
- selectedPlugins.value = [...currentValue];
+ selectedPlugins.value = [...currentValue] as string[];
}
dialog.value = false;
diff --git a/dashboard/src/components/shared/ProviderSelector.vue b/dashboard/src/components/shared/ProviderSelector.vue
index b82c43c3d..c5c8c08f3 100644
--- a/dashboard/src/components/shared/ProviderSelector.vue
+++ b/dashboard/src/components/shared/ProviderSelector.vue
@@ -210,6 +210,14 @@ import axios from "@/utils/request";
import { useModuleI18n } from "@/i18n/composables";
import ProviderPage from "@/views/ProviderPage.vue";
+interface Provider {
+ id: string;
+ type?: string;
+ provider_type?: string;
+ model?: string;
+ provider?: string;
+}
+
const props = defineProps({
modelValue: {
type: [String, Array],
@@ -237,10 +245,10 @@ const emit = defineEmits(["update:modelValue"]);
const { tm } = useModuleI18n("core.shared");
const dialog = ref(false);
-const providerList = ref([]);
+const providerList = ref([]);
const loading = ref(false);
const selectedProvider = ref("");
-const selectedProviders = ref([]);
+const selectedProviders = ref([]);
const providerDrawer = ref(false);
const hasSelection = computed(() => {
@@ -315,7 +323,7 @@ async function loadProviders() {
}
}
-function matchesProviderSubtype(provider, subtype) {
+function matchesProviderSubtype(provider: Provider, subtype: string): boolean {
if (!subtype) {
return true;
}
@@ -326,7 +334,7 @@ function matchesProviderSubtype(provider, subtype) {
return candidates.includes(normalized);
}
-function selectProvider(provider) {
+function selectProvider(provider: { id: string }): void {
if (props.multiple) {
if (!provider.id) {
selectedProviders.value = [];
@@ -364,21 +372,21 @@ function cancelSelection() {
dialog.value = false;
}
-function isProviderSelected(providerId) {
+function isProviderSelected(providerId: string): boolean {
if (props.multiple) {
return selectedProviders.value.includes(providerId);
}
return selectedProvider.value === providerId;
}
-function removeSelected(providerId) {
+function removeSelected(providerId: string): void {
const idx = selectedProviders.value.indexOf(providerId);
if (idx >= 0) {
selectedProviders.value.splice(idx, 1);
}
}
-function moveSelected(index, delta) {
+function moveSelected(index: number, delta: number): void {
const targetIndex = index + delta;
if (
targetIndex < 0 ||
diff --git a/dashboard/src/components/shared/ProxySelector.vue b/dashboard/src/components/shared/ProxySelector.vue
index b973976fe..1961f4e93 100644
--- a/dashboard/src/components/shared/ProxySelector.vue
+++ b/dashboard/src/components/shared/ProxySelector.vue
@@ -99,8 +99,8 @@ export default {
selectedGitHubProxy: "",
radioValue: "0", // 0: 不使用, 1: 使用
loadingTestingConnection: false,
- testingProxies: {},
- proxyStatus: {},
+ testingProxies: {} as Record,
+ proxyStatus: {} as Record,
initializing: true,
};
},
@@ -167,7 +167,7 @@ export default {
this.initializing = false;
},
methods: {
- getProxyByControl(control) {
+ getProxyByControl(control: string) {
const normalizedControl = String(control);
if (normalizedControl === "-1") {
return "";
@@ -178,7 +178,7 @@ export default {
}
return this.githubProxies[index] || "";
},
- async testSingleProxy(idx) {
+ async testSingleProxy(idx: number) {
this.testingProxies[idx] = true;
const proxy = this.githubProxies[idx];
diff --git a/dashboard/src/components/shared/ReadmeDialog.vue b/dashboard/src/components/shared/ReadmeDialog.vue
index 5cb9f5ccc..3587c61a7 100644
--- a/dashboard/src/components/shared/ReadmeDialog.vue
+++ b/dashboard/src/components/shared/ReadmeDialog.vue
@@ -43,15 +43,15 @@ const props = defineProps({
const emit = defineEmits(["update:show"]);
const { t, locale } = useI18n();
-const content = ref(null);
-const error = ref(null);
+const content = ref(null);
+const error = ref(null);
const loading = ref(false);
const isEmpty = ref(false);
-const copyFeedbackTimer = ref(null);
+const copyFeedbackTimer = ref | null>(null);
const lastRequestId = ref(0);
-const scrollContainer = ref(null);
+const scrollContainer = ref(null);
-function slugifyHeading(text, slugCounts) {
+function slugifyHeading(text: string | null, slugCounts: Map) {
const base = (text || "")
.trim()
.toLowerCase()
@@ -262,8 +262,8 @@ async function fetchContent() {
} else {
error.value = res.data.message;
}
- } catch (err) {
- if (requestId === lastRequestId.value) error.value = err.message;
+ } catch (err: unknown) {
+ if (requestId === lastRequestId.value) error.value = err instanceof Error ? err.message : String(err);
} finally {
if (requestId === lastRequestId.value) loading.value = false;
}
@@ -279,24 +279,26 @@ watch(
{ immediate: true },
);
-function handleContainerClick(event) {
- const btn = event.target.closest(".copy-code-btn");
+function handleContainerClick(event: MouseEvent) {
+ const clickTarget = event.target;
+ if (!(clickTarget instanceof Element)) return;
+ const btn = clickTarget.closest(".copy-code-btn");
if (btn) {
const code = btn.closest(".code-block-wrapper")?.querySelector("code");
if (code) {
if (navigator.clipboard?.writeText) {
navigator.clipboard
- .writeText(code.textContent)
+ .writeText(code.textContent ?? "")
.then(() => showCopyFeedback(btn, true))
- .catch(() => tryFallbackCopy(code.textContent, btn));
+ .catch(() => tryFallbackCopy(code.textContent ?? "", btn));
} else {
- tryFallbackCopy(code.textContent, btn);
+ tryFallbackCopy(code.textContent ?? "", btn);
}
}
return;
}
- const anchor = event.target.closest('a[href^="#"]');
+ const anchor = clickTarget.closest('a[href^="#"]');
if (!anchor) return;
const rawHref = anchor.getAttribute("href");
@@ -312,7 +314,7 @@ function handleContainerClick(event) {
target.scrollIntoView({ behavior: "smooth", block: "start" });
}
-function tryFallbackCopy(text, btn) {
+function tryFallbackCopy(text: string, btn: Element) {
try {
const textArea = document.createElement("textarea");
textArea.value = text;
@@ -331,12 +333,12 @@ function tryFallbackCopy(text, btn) {
} else {
showCopyFeedback(btn, false);
}
- } catch (err) {
+ } catch (_err: unknown) {
showCopyFeedback(btn, false);
}
}
-function showCopyFeedback(btn, success) {
+function showCopyFeedback(btn: Element, success: boolean) {
if (copyFeedbackTimer.value) clearTimeout(copyFeedbackTimer.value);
btn.setAttribute("title", t(`core.common.${success ? "copied" : "error"}`));
btn.innerHTML = success ? ICONS.SUCCESS : ICONS.ERROR;
@@ -358,7 +360,7 @@ const _show = computed({
});
// 安全打开外部链接
-function openExternalLink(url) {
+function openExternalLink(url: string | null) {
if (!url) return;
window.open(url, "_blank", "noopener,noreferrer");
}
@@ -414,6 +416,7 @@ const showActionArea = computed(() => {
+
(null);
// --- 编辑器配置 ---
const editorTheme = computed(() => "vs-light");
@@ -351,7 +351,8 @@ const previewContent = computed(() => {
);
return content;
} catch (error) {
- return `
模板渲染错误: ${error.message}
`;
+ const message = error instanceof Error ? error.message : String(error);
+ return `
模板渲染错误: ${message}
`;
}
});
@@ -533,7 +534,7 @@ const refreshPreview = () => {
syncPreviewVersion();
nextTick(() => {
if (previewFrame.value) {
- previewFrame.value.contentWindow.location.reload();
+ previewFrame.value.contentWindow?.location.reload();
}
setTimeout(() => (previewLoading.value = false), 500);
});
diff --git a/dashboard/src/components/shared/TemplateListEditor.vue b/dashboard/src/components/shared/TemplateListEditor.vue
index 70e3de45a..81fbffa69 100644
--- a/dashboard/src/components/shared/TemplateListEditor.vue
+++ b/dashboard/src/components/shared/TemplateListEditor.vue
@@ -107,7 +107,7 @@
@@ -131,7 +131,7 @@
[],
- },
- templates: {
- type: Object,
- default: () => ({}),
- },
-});
+interface TemplateMetaItem {
+ type?: string;
+ invisible?: boolean;
+ description?: string;
+ hint?: string;
+ default?: unknown;
+ condition?: Record;
+ items?: Record;
+ [key: string]: unknown;
+}
-const emit = defineEmits(["update:modelValue"]);
+interface TemplateMeta {
+ name?: string;
+ hint?: string;
+ description?: string;
+ items?: Record;
+ [key: string]: unknown;
+}
+
+type EntryValue =
+ | string
+ | number
+ | boolean
+ | Record
+ | unknown[]
+ | null
+ | undefined;
+
+type ConfigEntry = Record;
+
+const props = withDefaults(
+ defineProps<{
+ modelValue?: ConfigEntry[];
+ templates?: Record;
+ }>(),
+ {
+ modelValue: () => [],
+ templates: () => ({}),
+ },
+);
+
+const emit = defineEmits<{
+ (e: "update:modelValue", value: ConfigEntry[]): void;
+}>();
const { t } = useI18n();
const { tm, getRaw } = useModuleI18n("features/config-metadata");
-const expandedEntries = ref({});
+const expandedEntries = ref>({});
-const safeText = (val, fallback) =>
+const safeText = (val: unknown, fallback: string): string =>
val && typeof val === "string" ? val : fallback;
const addButtonText = computed(() =>
safeText(t("core.common.templateList.addEntry"), "添加条目"),
@@ -274,24 +306,24 @@ const templateOptions = computed(() => {
}));
});
-function templateLabel(key) {
+function templateLabel(key: string | null | undefined): string {
if (!key)
return t("core.common.templateList.unknownTemplate") || "未指定模板";
- return translateIfKey(props.templates?.[key]?.name || key);
+ return translateIfKey(props.templates?.[key]?.name || key) as string;
}
-function translateIfKey(value) {
+function translateIfKey(value: unknown): unknown {
if (!value || typeof value !== "string") return value;
return getRaw(value) ? tm(value) : value;
}
-function buildDefaults(itemsMeta = {}) {
- const result = {};
+function buildDefaults(itemsMeta: Record = {}): Record {
+ const result: Record = {};
for (const [k, meta] of Object.entries(itemsMeta)) {
if (!meta || !meta.type) continue;
const fallback = Object.prototype.hasOwnProperty.call(meta, "default")
? meta.default
- : defaultValueMap[meta.type];
+ : defaultValueMap[meta.type as keyof typeof defaultValueMap];
if (meta.type === "object") {
result[k] = buildDefaults(meta.items || {});
@@ -302,19 +334,22 @@ function buildDefaults(itemsMeta = {}) {
return result;
}
-function applyDefaults(target, itemsMeta = {}) {
+function applyDefaults(
+ target: Record,
+ itemsMeta: Record = {},
+): boolean {
let changed = false;
for (const [k, meta] of Object.entries(itemsMeta)) {
if (!meta || !meta.type) continue;
const hasDefault = Object.prototype.hasOwnProperty.call(meta, "default");
- const fallback = hasDefault ? meta.default : defaultValueMap[meta.type];
+ const fallback = hasDefault ? meta.default : defaultValueMap[meta.type as keyof typeof defaultValueMap];
if (meta.type === "object") {
if (!target[k] || typeof target[k] !== "object") {
target[k] = buildDefaults(meta.items || {});
changed = true;
} else {
- if (applyDefaults(target[k], meta.items || {})) {
+ if (applyDefaults(target[k] as Record, meta.items || {})) {
changed = true;
}
}
@@ -335,7 +370,7 @@ function ensureEntryDefaults() {
if (!template || !template.items) return entry;
// 我们必须克隆以避免就地修改
- const newEntry = JSON.parse(JSON.stringify(entry));
+ const newEntry = JSON.parse(JSON.stringify(entry)) as ConfigEntry;
let entryChanged = applyDefaults(newEntry, template.items);
if (!Object.prototype.hasOwnProperty.call(newEntry, "__template_key")) {
@@ -364,22 +399,22 @@ watch(
{ immediate: true, deep: true },
);
-function addEntry(templateKey) {
+function addEntry(templateKey: string) {
if (!templateKey) return;
const template = props.templates?.[templateKey];
if (!template) return;
const newEntry = {
__template_key: templateKey,
...buildDefaults(template.items || {}),
- };
+ } as ConfigEntry;
emit("update:modelValue", [...(props.modelValue || []), newEntry]);
expandedEntries.value[props.modelValue.length] = true;
}
-function removeEntry(index) {
+function removeEntry(index: number) {
const next = [...(props.modelValue || [])];
next.splice(index, 1);
- const rebuilt = {};
+ const rebuilt: Record = {};
next.forEach((_, idx) => {
const sourceIdx = idx >= index ? idx + 1 : idx;
rebuilt[idx] = expandedEntries.value[sourceIdx] ?? false;
@@ -388,23 +423,31 @@ function removeEntry(index) {
emit("update:modelValue", next);
}
-function toggleEntry(index) {
+function toggleEntry(index: number) {
expandedEntries.value[index] = !expandedEntries.value[index];
}
-function getTemplate(entry) {
+function getTemplate(entry: Record | null | undefined): TemplateMeta | null {
if (!entry) return null;
const key = entry.__template_key;
- if (!key) return null;
- return props.templates?.[key] || null;
+ if (!key || typeof key !== "string") return null;
+ return (props.templates?.[key] as TemplateMeta | undefined) || null;
}
-function getValueBySelector(obj, selector) {
+function getValueBySelector(
+ obj: Record,
+ selector: string,
+): unknown {
const keys = selector.split(".");
- let current = obj;
+ let current: unknown = obj;
for (const key of keys) {
- if (current && typeof current === "object" && key in current) {
- current = current[key];
+ if (
+ current &&
+ typeof current === "object" &&
+ key in current &&
+ current !== null
+ ) {
+ current = (current as Record)[key];
} else {
return undefined;
}
@@ -412,7 +455,10 @@ function getValueBySelector(obj, selector) {
return current;
}
-function shouldShowItem(itemMeta, entry) {
+function shouldShowItem(
+ itemMeta: TemplateMetaItem | null | undefined,
+ entry: Record,
+): boolean {
if (!itemMeta?.condition) {
return true;
}
@@ -427,9 +473,13 @@ function shouldShowItem(itemMeta, entry) {
return true;
}
-function hasVisibleItemsAfter(entries, currentIndex, entry) {
+function hasVisibleItemsAfter(
+ entries: [string, TemplateMetaItem][],
+ currentIndex: number,
+ entry: Record,
+): boolean {
for (let i = currentIndex + 1; i < entries.length; i++) {
- const [k, meta] = entries[i];
+ const [_k, meta] = entries[i];
if (!meta?.invisible && shouldShowItem(meta, entry)) {
return true;
}
diff --git a/dashboard/src/stores/toast.js b/dashboard/src/stores/toast.js
index 3d04b10b7..bd30bc645 100644
--- a/dashboard/src/stores/toast.js
+++ b/dashboard/src/stores/toast.js
@@ -1,7 +1,18 @@
import { defineStore } from "pinia";
import { ref, computed } from "vue";
+/**
+ * @typedef {Object} ToastItem
+ * @property {string} message
+ * @property {string} color
+ * @property {number} timeout
+ * @property {boolean} closable
+ * @property {boolean} multiLine
+ * @property {string} location
+ */
+
export const useToastStore = defineStore("toast", () => {
+ /** @type {import('vue').Ref} */
const queue = ref([]);
const current = computed(() => queue.value[0]);
diff --git a/dashboard/src/views/AboutPage.vue b/dashboard/src/views/AboutPage.vue
index 85a870801..facfebaf2 100644
--- a/dashboard/src/views/AboutPage.vue
+++ b/dashboard/src/views/AboutPage.vue
@@ -54,7 +54,7 @@ export default {
},
methods: {
useCustomizerStore,
- open(url) {
+ open(url: string) {
window.open(url, "_blank");
},
},
diff --git a/dashboard/src/views/ConfigPage.vue b/dashboard/src/views/ConfigPage.vue
index 602622307..7ae09b213 100644
--- a/dashboard/src/views/ConfigPage.vue
+++ b/dashboard/src/views/ConfigPage.vue
@@ -340,6 +340,25 @@ import {
import UnsavedChangesConfirmDialog from "@/components/config/UnsavedChangesConfirmDialog.vue";
import { normalizeTextInput } from "@/utils/inputValue";
import { defineReactorMonacoTheme } from "@/utils/monacoTheme";
+import type { RouteLocationNormalized } from "vue-router";
+
+interface ConfigInfoItem {
+ id: string;
+ name: string;
+}
+
+type WfrRef = {
+ check: (initialStartTime?: number | null) => void | Promise;
+ stop?: () => void;
+};
+
+interface UnsavedChangesOptions {
+ title?: string;
+ message?: string;
+ confirmHint?: string;
+ cancelHint?: string;
+ closeHint?: string;
+}
export default {
name: "ConfigPage",
@@ -352,9 +371,12 @@ export default {
},
// 检查未保存的更改
- async beforeRouteLeave(to, from) {
+ async beforeRouteLeave(
+ _to: RouteLocationNormalized,
+ _from: RouteLocationNormalized,
+ ) {
if (this.hasUnsavedChanges) {
- const confirmed = await this.$refs.unsavedChangesDialog?.open({
+ const confirmed = await (this.$refs.unsavedChangesDialog as undefined | { open: (opts: UnsavedChangesOptions) => Promise })?.open({
title: this.tm("unsavedChangesWarning.dialogTitle"),
message: this.tm("unsavedChangesWarning.leavePage"),
confirmHint: `${this.tm("unsavedChangesWarning.options.saveAndSwitch")}:${this.tm("unsavedChangesWarning.options.confirm")}`,
@@ -429,17 +451,17 @@ export default {
isSystemConfig: false,
// 多配置文件管理
- selectedConfigID: null, // 用于存储当前选中的配置项信息
- currentConfigId: null, // 跟踪当前正在编辑的配置id
- configInfoList: [],
+ selectedConfigID: null as string | null, // 用于存储当前选中的配置项信息
+ currentConfigId: null as string | null, // 跟踪当前正在编辑的配置id
+ configInfoList: [] as ConfigInfoItem[],
configFormData: {
name: "",
- },
- editingConfigId: null,
+ } as { name: string },
+ editingConfigId: null as string | null,
// 测试聊天
testChatDrawer: false,
- testConfigId: null,
+ testConfigId: null as string | null,
// 未保存的更改状态
// 存储原始配置
@@ -469,7 +491,7 @@ export default {
configInfoNameList() {
return this.configInfoList.map((info) => info.name);
},
- selectedConfigInfo() {
+ selectedConfigInfo(): Partial {
return (
this.configInfoList.find((info) => info.id === this.selectedConfigID) ||
{}
@@ -480,7 +502,6 @@ export default {
items.push({
id: "_%manage%_",
name: this.tm("configManagement.manageConfigs"),
- umop: [],
});
return items;
},
@@ -549,10 +570,10 @@ export default {
}
},
- onConfigSearchInput(value) {
+ onConfigSearchInput(value: string) {
this.configSearchKeyword = normalizeTextInput(value);
},
- extractConfigTypeFromHash(hash) {
+ extractConfigTypeFromHash(hash: string): string | null {
const rawHash = String(hash || "");
const lastHashIndex = rawHash.lastIndexOf("#");
if (lastHashIndex === -1) {
@@ -563,7 +584,7 @@ export default {
? cleanHash
: null;
},
- async syncConfigTypeFromHash(hash) {
+ async syncConfigTypeFromHash(hash: string): Promise {
const configType = this.extractConfigTypeFromHash(hash);
if (!configType || configType === this.configType) {
return false;
@@ -573,7 +594,7 @@ export default {
await this.onConfigTypeToggle();
return true;
},
- getConfigInfoList(abconf_id) {
+ getConfigInfoList(abconf_id?: string) {
// 获取配置列表
axios
.get("/api/config/abconfs")
@@ -606,14 +627,14 @@ export default {
this.save_message_success = "error";
});
},
- getConfig(abconf_id, reloadFromFile = false) {
+ getConfig(abconf_id?: string, reloadFromFile = false) {
this.fetched = false;
- const params = {};
+ const params: Record = {};
if (this.isSystemConfig) {
params.system_config = "1";
} else {
- params.id = abconf_id || this.selectedConfigID;
+ params.id = abconf_id || this.selectedConfigID || "";
}
if (reloadFromFile) {
params.reload_from_file = "1";
@@ -655,7 +676,7 @@ export default {
if (this.refreshingConfig) return;
if (this.hasUnsavedChanges) {
- const shouldDiscard = await this.$refs.unsavedChangesDialog?.open({
+ const shouldDiscard = await (this.$refs.unsavedChangesDialog as undefined | { open: (opts: UnsavedChangesOptions) => Promise })?.open({
title: this.tm("unsavedChangesWarning.dialogTitle"),
message: this.tm("unsavedChangesWarning.reloadConfig"),
confirmHint: `${this.tm("actions.refresh")}:${this.tm("unsavedChangesWarning.options.confirm")}`,
@@ -670,7 +691,7 @@ export default {
this.refreshingConfig = true;
try {
await this.getConfig(
- this.isSystemConfig ? undefined : this.selectedConfigID,
+ this.isSystemConfig ? undefined : (this.selectedConfigID ?? undefined),
true,
);
this.save_message = this.tm("messages.refreshSuccess");
@@ -687,7 +708,7 @@ export default {
updateConfig() {
if (!this.fetched) return;
- const postData = {
+ const postData: Record = {
config: JSON.parse(JSON.stringify(this.config_data)),
};
@@ -710,7 +731,7 @@ export default {
this.onConfigSaved();
if (this.isSystemConfig) {
- restartAstrBotRuntime(this.$refs.wfr).catch(() => undefined);
+ restartAstrBotRuntime(this.$refs.wfr as WfrRef | null | undefined).catch(() => undefined);
}
return { success: true };
} else {
@@ -774,7 +795,7 @@ export default {
this.save_message_success = "error";
});
},
- async onConfigSelect(value) {
+ async onConfigSelect(value: string) {
if (value === "_%manage%_") {
this.configManageDialog = true;
// 重置选择到之前的值
@@ -790,7 +811,7 @@ export default {
? "default"
: this.currentConfigId || this.selectedConfigID || "default";
const message = this.tm("unsavedChangesWarning.switchConfig");
- const saveAndSwitch = await this.$refs.unsavedChangesDialog?.open({
+ const saveAndSwitch = await (this.$refs.unsavedChangesDialog as undefined | { open: (opts: UnsavedChangesOptions) => Promise })?.open({
title: this.tm("unsavedChangesWarning.dialogTitle"),
message: message,
confirmHint: `${this.tm("unsavedChangesWarning.options.saveAndSwitch")}:${this.tm("unsavedChangesWarning.options.confirm")}`,
@@ -833,7 +854,7 @@ export default {
};
this.editingConfigId = null;
},
- startEditConfig(config) {
+ startEditConfig(config: ConfigInfoItem) {
this.showConfigForm = true;
this.isEditingConfig = true;
this.editingConfigId = config.id;
@@ -864,7 +885,7 @@ export default {
this.createNewConfig();
}
},
- async confirmDeleteConfig(config) {
+ async confirmDeleteConfig(config: ConfigInfoItem) {
const message = this.tm("configManagement.confirmDelete").replace(
"{name}",
config.name,
@@ -873,7 +894,7 @@ export default {
this.deleteConfig(config.id);
}
},
- deleteConfig(configId) {
+ deleteConfig(configId: string) {
axios
.post("/api/config/abconf/delete", {
id: configId,
@@ -910,7 +931,7 @@ export default {
this.save_message = res.data.message;
this.save_message_snack = true;
this.save_message_success = "success";
- this.getConfigInfoList(this.editingConfigId);
+ this.getConfigInfoList(this.editingConfigId ?? undefined);
this.cancelConfigForm();
} else {
this.save_message = res.data.message;
@@ -929,7 +950,7 @@ export default {
// 检查是否有未保存的更改
if (this.hasUnsavedChanges) {
const message = this.tm("unsavedChangesWarning.leavePage");
- const saveAndSwitch = await this.$refs.unsavedChangesDialog?.open({
+ const saveAndSwitch = await (this.$refs.unsavedChangesDialog as undefined | { open: (opts: UnsavedChangesOptions) => Promise })?.open({
title: this.tm("unsavedChangesWarning.dialogTitle"),
message: message,
confirmHint: `${this.tm("unsavedChangesWarning.options.saveAndSwitch")}:${this.tm("unsavedChangesWarning.options.confirm")}`,
@@ -988,7 +1009,7 @@ export default {
this.testChatDrawer = false;
this.testConfigId = null;
},
- getConfigSnapshot(config) {
+ getConfigSnapshot(config: Record) {
return JSON.stringify(config ?? {});
},
},
diff --git a/dashboard/src/views/ConversationPage.vue b/dashboard/src/views/ConversationPage.vue
index 789cd3b12..7e716ed4a 100644
--- a/dashboard/src/views/ConversationPage.vue
+++ b/dashboard/src/views/ConversationPage.vue
@@ -552,9 +552,10 @@
-