Files
WebAI2API/webui/src/components/settings/adapters.vue
T

138 lines
5.5 KiB
Vue

<script setup>
import { ref, onMounted, reactive, computed } from 'vue';
import { useSettingsStore } from '@/stores/settings';
import { message } from 'ant-design-vue';
import { SettingOutlined, AppstoreOutlined } from '@ant-design/icons-vue';
const settingsStore = useSettingsStore();
const drawerVisible = ref(false);
const currentAdapter = ref(null);
const currentConfig = reactive({});
// 挂载时获取数据
onMounted(async () => {
await Promise.all([
settingsStore.fetchAdaptersMeta(),
settingsStore.fetchAdapterConfig()
]);
});
// 适配器列表
const adapters = computed(() => settingsStore.adaptersMeta);
// 打开抽屉进行编辑
const handleEdit = (adapter) => {
currentAdapter.value = adapter;
// 加载现有配置或默认值
const existing = settingsStore.adapterConfig[adapter.id] || {};
// 重置当前配置表单
Object.keys(currentConfig).forEach(key => delete currentConfig[key]);
// 使用现有值或schema中的默认值初始化表单
if (adapter.configSchema) {
adapter.configSchema.forEach(field => {
if (existing[field.key] !== undefined) {
currentConfig[field.key] = existing[field.key];
} else {
currentConfig[field.key] = field.default;
}
});
}
drawerVisible.value = true;
};
// 保存配置
const handleSave = async () => {
if (!currentAdapter.value) return;
const configToSave = {
[currentAdapter.value.id]: { ...currentConfig }
};
const success = await settingsStore.saveAdapterConfig(configToSave);
if (success) {
drawerVisible.value = false;
}
};
</script>
<template>
<a-layout style="background: transparent;">
<a-card title="适配器管理" :bordered="false">
<template #extra>
<a-button type="link" @click="settingsStore.fetchAdaptersMeta">刷新列表</a-button>
</template>
<a-list :grid="{ gutter: 16, xs: 1, sm: 2, md: 3, lg: 3, xl: 4, xxl: 4 }" :data-source="adapters">
<template #renderItem="{ item }">
<a-list-item>
<a-card hoverable @click="handleEdit(item)" :bodyStyle="{ padding: '12px 16px' }">
<div style="display: flex; align-items: center; justify-content: space-between; gap: 8px;">
<div style="display: flex; align-items: center; min-width: 0; flex: 1;">
<AppstoreOutlined
style="font-size: 18px; color: #1890ff; margin-right: 8px; flex-shrink: 0;" />
<span
style="font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{
item.id }}</span>
</div>
<SettingOutlined style="font-size: 16px; color: #8c8c8c; flex-shrink: 0;" />
</div>
</a-card>
</a-list-item>
</template>
</a-list>
</a-card>
<!-- 配置抽屉 -->
<a-drawer v-if="currentAdapter" v-model:open="drawerVisible" :title="`配置适配器 - ${currentAdapter.id}`" width="500"
placement="right">
<!-- 适配器描述 -->
<div v-if="currentAdapter.description"
style="margin-bottom: 16px; padding: 12px; background: #f5f5f5; border-radius: 6px; color: #666; font-size: 13px; line-height: 1.6;">
{{ currentAdapter.description }}
</div>
<div v-if="!currentAdapter.configSchema || currentAdapter.configSchema.length === 0">
<a-empty description="该适配器没有可配置项" />
</div>
<a-form layout="vertical" v-else>
<template v-for="field in currentAdapter.configSchema" :key="field.key">
<a-form-item :label="field.label" :required="field.required">
<!-- 字符串输入 -->
<a-input v-if="field.type === 'string'" v-model:value="currentConfig[field.key]"
:placeholder="field.placeholder" />
<!-- 数字输入 -->
<a-input-number v-if="field.type === 'number'" v-model:value="currentConfig[field.key]"
:min="field.min" :max="field.max" style="width: 100%;" />
<!-- 布尔开关 -->
<div v-if="field.type === 'boolean'">
<a-switch v-model:checked="currentConfig[field.key]" />
</div>
<!-- 下拉选择 -->
<a-select v-if="field.type === 'select'" v-model:value="currentConfig[field.key]"
:options="field.options" />
<div v-if="field.note" style="font-size: 12px; color: #8c8c8c; margin-top: 4px;">
{{ field.note }}
</div>
</a-form-item>
</template>
</a-form>
<template #footer>
<div style="text-align: right;">
<a-button style="margin-right: 8px" @click="drawerVisible = false">取消</a-button>
<a-button type="primary" @click="handleSave">保存配置</a-button>
</div>
</template>
</a-drawer>
</a-layout>
</template>