fix: enhance PersonaForm layout and improve tool selection display

This commit is contained in:
Soulter
2026-02-20 15:54:02 +08:00
parent ed4cacfffb
commit 46152d3faf
2 changed files with 70 additions and 36 deletions
+51 -35
View File
@@ -1,36 +1,30 @@
<template>
<v-dialog
v-model="showDialog"
:max-width="$vuetify.display.smAndDown ? undefined : '760px'"
scrollable
>
<v-dialog v-model="showDialog" :max-width="$vuetify.display.smAndDown ? undefined : '1200px'" scrollable>
<v-card class="persona-form-card" :class="{ 'persona-form-card-mobile': $vuetify.display.smAndDown }">
<v-card-title class="persona-form-title text-h2">
<v-card-title class="persona-form-title text-h2 px-6 pt-6 pl-6">
{{ editingPersona ? tm('dialog.edit.title') : tm('dialog.create.title') }}
</v-card-title>
<v-card-text class="persona-form-content">
<!-- 创建位置提示 -->
<v-alert
v-if="!editingPersona"
type="info"
variant="tonal"
density="compact"
class="mb-4"
icon="mdi-folder-outline"
>
<v-alert v-if="!editingPersona" type="info" variant="tonal" density="compact" class="mb-4"
icon="mdi-folder-outline">
{{ tm('form.createInFolder', { folder: folderDisplayName }) }}
</v-alert>
<v-form ref="personaForm" v-model="formValid">
<v-text-field v-model="personaForm.persona_id" :label="tm('form.personaId')"
:rules="personaIdRules" :disabled="editingPersona" variant="outlined" density="comfortable"
class="mb-4" />
<v-row class="persona-form-layout">
<v-col cols="12" md="6" class="persona-basic-col">
<v-text-field v-model="personaForm.persona_id" :label="tm('form.personaId')"
:rules="personaIdRules" :disabled="editingPersona" variant="outlined"
density="comfortable" class="mb-4" />
<v-textarea v-model="personaForm.system_prompt" :label="tm('form.systemPrompt')"
:rules="systemPromptRules" variant="outlined" rows="6" class="mb-4" />
<v-textarea v-model="personaForm.system_prompt" :label="tm('form.systemPrompt')"
:rules="systemPromptRules" variant="outlined" rows="16" class="mb-4" />
</v-col>
<v-expansion-panels v-model="expandedPanels" multiple>
<v-col cols="12" md="6" class="persona-panels-col">
<v-expansion-panels v-model="expandedPanels" multiple>
<!-- 工具选择面板 -->
<v-expansion-panel value="tools">
<v-expansion-panel-title>
@@ -69,8 +63,8 @@
<div class="d-flex flex-wrap ga-2">
<v-chip v-for="server in mcpServers" :key="server.name"
:color="isServerSelected(server) ? 'primary' : 'default'"
:variant="isServerSelected(server) ? 'flat' : 'outlined'"
size="small" clickable @click="toggleMcpServer(server)"
:variant="isServerSelected(server) ? 'flat' : 'outlined'" size="small"
clickable @click="toggleMcpServer(server)"
:disabled="!server.tools || server.tools.length === 0">
<v-icon start size="small">mdi-server</v-icon>
{{ server.name }}
@@ -83,7 +77,7 @@
<!-- 工具选择列表 -->
<div v-if="filteredTools.length > 0" class="tools-selection">
<v-virtual-scroll :items="filteredTools" height="300" item-height="48">
<v-virtual-scroll :items="filteredTools" height="300" item-height="72">
<template v-slot:default="{ item }">
<v-list-item :key="item.name" density="comfortable"
@click="toggleTool(item.name)">
@@ -94,10 +88,16 @@
<v-list-item-title>
{{ item.name }}
<v-chip v-if="item.mcp_server_name" size="x-small"
color="secondary" variant="tonal" class="ml-2">
{{ item.mcp_server_name }}
<v-chip v-if="item.origin" size="x-small" color="info" class="mr-2"
variant="tonal">
{{ item.origin }}
</v-chip>
<v-chip v-if="item.origin_name" size="x-small" color="info"
variant="outlined">
{{ item.origin_name }}
</v-chip>
</v-list-item-title>
<v-list-item-subtitle v-if="item.description">
@@ -112,7 +112,7 @@
class="text-center pa-4">
<v-icon size="48" color="grey-lighten-2" class="mb-2">mdi-tools</v-icon>
<p class="text-body-2 text-medium-emphasis">{{ tm('form.noToolsAvailable')
}}
}}
</p>
</div>
@@ -127,7 +127,7 @@
<div v-if="loadingTools" class="text-center pa-4">
<v-progress-circular indeterminate color="primary" />
<p class="text-body-2 text-medium-emphasis mt-2">{{ tm('form.loadingTools')
}}
}}
</p>
</div>
@@ -143,9 +143,9 @@
</span>
</h4>
<div v-if="Array.isArray(personaForm.tools) && personaForm.tools.length > 0"
class="d-flex flex-wrap ga-1" style="max-height: 100px; overflow-y: auto;">
<v-chip v-for="toolName in personaForm.tools" :key="toolName"
size="small" color="primary" variant="tonal" closable
class="d-flex flex-wrap ga-1" style="max-height: 100px; overflow-y: auto;">
<v-chip v-for="toolName in personaForm.tools" :key="toolName" size="small"
color="primary" variant="tonal" closable
@click:close="removeTool(toolName)">
{{ toolName }}
</v-chip>
@@ -209,7 +209,8 @@
<div v-else-if="!loadingSkills && availableSkills.length === 0"
class="text-center pa-4">
<v-icon size="48" color="grey-lighten-2" class="mb-2">mdi-lightning-bolt</v-icon>
<v-icon size="48" color="grey-lighten-2"
class="mb-2">mdi-lightning-bolt</v-icon>
<p class="text-body-2 text-medium-emphasis">{{ tm('form.noSkillsAvailable') }}
</p>
</div>
@@ -288,7 +289,9 @@
</v-btn>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
</v-expansion-panels>
</v-col>
</v-row>
</v-form>
</v-card-text>
@@ -484,7 +487,7 @@ export default {
};
this.toolSelectValue = '0';
this.skillSelectValue = '0';
this.expandedPanels = [];
this.expandedPanels = this.getDefaultExpandedPanels();
},
initFormWithPersona(persona) {
@@ -499,7 +502,11 @@ export default {
// 根据 tools 的值设置 toolSelectValue
this.toolSelectValue = persona.tools === null ? '0' : '1';
this.skillSelectValue = persona.skills === null ? '0' : '1';
this.expandedPanels = [];
this.expandedPanels = this.getDefaultExpandedPanels();
},
getDefaultExpandedPanels() {
return this.$vuetify.display.smAndDown ? [] : ['tools', 'skills', 'dialogs'];
},
closeDialog() {
@@ -829,6 +836,10 @@ export default {
margin-left: 32px;
}
.persona-form-layout {
align-items: flex-start;
}
.tools-selection {
max-height: 300px;
overflow-y: auto;
@@ -853,6 +864,11 @@ export default {
padding: 16px !important;
}
.persona-basic-col,
.persona-panels-col {
padding-top: 0 !important;
}
.persona-form-title {
font-size: 1.15rem !important;
padding: 12px 16px !important;
+19 -1
View File
@@ -117,7 +117,18 @@
<v-card v-if="viewingPersona">
<v-card-title class="d-flex justify-space-between align-center">
<span class="text-h5">{{ viewingPersona.persona_id }}</span>
<v-btn icon="mdi-close" variant="text" @click="showViewDialog = false" />
<div class="d-flex align-center ga-1">
<v-btn
color="primary"
variant="tonal"
size="small"
prepend-icon="mdi-pencil"
@click="openEditFromViewDialog"
>
{{ tm('buttons.edit') }}
</v-btn>
<v-btn icon="mdi-close" variant="text" @click="showViewDialog = false" />
</div>
</v-card-title>
<v-card-text>
@@ -414,6 +425,13 @@ export default defineComponent({
this.showViewDialog = true;
},
openEditFromViewDialog() {
if (!this.viewingPersona) return;
this.editingPersona = this.viewingPersona;
this.showViewDialog = false;
this.showPersonaDialog = true;
},
handlePersonaSaved(message: string) {
this.showSuccess(message);
this.refreshCurrentFolder();