perf: 更好的 list 可视化

This commit is contained in:
Soulter
2025-02-06 15:59:45 +08:00
parent aebc7850f4
commit ad95572d5f
2 changed files with 150 additions and 48 deletions
@@ -1,22 +1,26 @@
<template>
<h3 style="margin-bottom: 8px;" v-if="iterable && metadata[metadataKey]?.type === 'object'">
{{metadata[metadataKey]?.description }}
{{ metadata[metadataKey]?.description }}
</h3>
<v-card-text>
<div v-for="(index, key) in iterable" :key="key" style="margin-bottom: 0.5px;" v-if="metadata[metadataKey]?.type === 'object' || metadata[metadataKey]?.config_template">
<v-alert v-if="metadata[metadataKey].items[key]?.obvious_hint && metadata[metadataKey].items[key]?.hint" style="margin-bottom: 16px"
:text="metadata[metadataKey].items[key]?.hint" :title="'💡 关于' + metadata[metadataKey].items[key]?.description"
type="info" variant="tonal">
<div v-for="(index, key) in iterable" :key="key" style="margin-bottom: 0.5px;"
v-if="metadata[metadataKey]?.type === 'object' || metadata[metadataKey]?.config_template">
<v-alert v-if="metadata[metadataKey].items[key]?.obvious_hint && metadata[metadataKey].items[key]?.hint"
style="margin-bottom: 16px" :text="metadata[metadataKey].items[key]?.hint"
:title="'💡 关于' + metadata[metadataKey].items[key]?.description" type="info" variant="tonal">
</v-alert>
<div style="display: flex; align-items: center; justify-content: center; gap: 16px">
<div style="width: 100%;" v-if="metadata[metadataKey].items[key]">
<v-select v-if="metadata[metadataKey].items[key]?.options && !metadata[metadataKey].items[key]?.invisible" v-model="iterable[key]"
variant="outlined" :items="metadata[metadataKey].items[key]?.options"
:label="metadata[metadataKey].items[key]?.description + '(' + key + ')'" dense :disabled="metadata[metadataKey].items[key]?.readonly"></v-select>
<v-text-field v-else-if="metadata[metadataKey].items[key]?.type === 'string' && !metadata[metadataKey].items[key]?.invisible"
<v-select
v-if="metadata[metadataKey].items[key]?.options && !metadata[metadataKey].items[key]?.invisible"
v-model="iterable[key]" variant="outlined" :items="metadata[metadataKey].items[key]?.options"
:label="metadata[metadataKey].items[key]?.description + '(' + key + ')'" dense
:disabled="metadata[metadataKey].items[key]?.readonly"></v-select>
<v-text-field
v-else-if="metadata[metadataKey].items[key]?.type === 'string' && !metadata[metadataKey].items[key]?.invisible"
v-model="iterable[key]" :label="metadata[metadataKey].items[key]?.description + '(' + key + ')'"
variant="outlined" dense ></v-text-field>
variant="outlined" dense></v-text-field>
<v-text-field
v-else-if="(metadata[metadataKey].items[key]?.type === 'int' || metadata[metadataKey].items[key]?.type === 'float') && !metadata[metadataKey].items[key]?.invisible"
v-model="iterable[key]" :label="metadata[metadataKey].items[key]?.description + '(' + key + ')'"
@@ -27,17 +31,11 @@
<v-switch v-else-if="metadata[metadataKey].items[key]?.type === 'bool' && !metadata[metadataKey].items[key]?.invisible" v-model="iterable[key]"
:label="metadata[metadataKey].items[key]?.description + '(' + key + ')'" color="primary"
inset></v-switch>
<v-combobox variant="outlined" v-else-if="metadata[metadataKey].items[key]?.type === 'list' && !metadata[metadataKey].items[key]?.invisible"
v-model="iterable[key]" chips clearable
:label="metadata[metadataKey].items[key]?.description + '(' + key + ')'" multiple
prepend-icon="mdi-tag-multiple-outline">
<template v-slot:selection="{ attrs, item, select, selected }">
<v-chip v-bind="attrs" :model-value="selected" closable @click="select"
@click:close="remove(item)">
<strong>{{ item }}</strong>
</v-chip>
</template>
</v-combobox>
<ListConfigItem
v-else-if="metadata[metadataKey].items[key]?.type === 'list' && !metadata[metadataKey].items[key]?.invisible"
:value="iterable[key]"
:label="metadata[metadataKey].items[key]?.description + '(' + key + ')'"/>
<div v-else-if="metadata[metadataKey].items[key]?.type === 'object' && !metadata[metadataKey].items[key]?.invisible"
style="border: 1px solid #e0e0e0; padding: 8px; margin-bottom: 16px; border-radius: 10px;">
<AstrBotConfig :metadata="metadata[metadataKey].items" :iterable="iterable[key]"
@@ -59,44 +57,47 @@
}}</v-tooltip>
</v-btn>
</div>
<div>
<v-chip v-if="!metadata[metadataKey].items[key]?.invisible" color="primary">{{ metadata[metadataKey].items[key]?.type }}</v-chip>
</div>
</div>
</div>
<div v-else>
<v-alert v-if="metadata[metadataKey]?.obvious_hint && metadata[metadataKey]?.hint" style="margin-bottom: 16px"
:text="metadata[metadataKey]?.hint" :title="'💡 关于' + metadata[metadataKey]?.description"
type="info" variant="tonal">
<v-alert v-if="metadata[metadataKey]?.obvious_hint && metadata[metadataKey]?.hint"
style="margin-bottom: 16px" :text="metadata[metadataKey]?.hint"
:title="'💡 关于' + metadata[metadataKey]?.description" type="info" variant="tonal">
</v-alert>
<div style="display: flex; align-items: center; justify-content: center; gap: 16px">
<div style="width: 100%;">
<v-select v-if="metadata[metadataKey]?.options && !metadata[metadataKey]?.invisible" v-model="iterable[metadataKey]"
variant="outlined" :items="metadata[metadataKey]?.options"
:label="metadata[metadataKey]?.description + '(' + metadataKey+ ')'" dense :disabled="metadata[metadataKey]?.readonly"></v-select>
<v-text-field v-else-if="metadata[metadataKey]?.type === 'string' && !metadata[metadataKey]?.invisible"
v-model="iterable[metadataKey]" :label="metadata[metadataKey]?.description + '(' + metadataKey+ ')'"
variant="outlined" dense ></v-text-field>
<v-select v-if="metadata[metadataKey]?.options && !metadata[metadataKey]?.invisible"
v-model="iterable[metadataKey]" variant="outlined" :items="metadata[metadataKey]?.options"
:label="metadata[metadataKey]?.description + '(' + metadataKey + ')'" dense
:disabled="metadata[metadataKey]?.readonly"></v-select>
<v-text-field
v-else-if="metadata[metadataKey]?.type === 'string' && !metadata[metadataKey]?.invisible"
v-model="iterable[metadataKey]"
:label="metadata[metadataKey]?.description + '(' + metadataKey + ')'" variant="outlined"
dense></v-text-field>
<v-text-field
v-else-if="(metadata[metadataKey]?.type === 'int' || metadata[metadataKey]?.type === 'float') && !metadata[metadataKey]?.invisible"
v-model="iterable[metadataKey]" :label="metadata[metadataKey]?.description + '(' + metadataKey+ ')'"
variant="outlined" dense></v-text-field>
<v-textarea v-else-if="metadata[metadataKey]?.type === 'text' && !metadata[metadataKey]?.invisible" v-model="iterable[metadataKey]"
:label="metadata[metadataKey]?.description + '(' + metadataKey+ ')'" variant="outlined"
v-model="iterable[metadataKey]"
:label="metadata[metadataKey]?.description + '(' + metadataKey + ')'" variant="outlined"
dense></v-text-field>
<v-textarea v-else-if="metadata[metadataKey]?.type === 'text' && !metadata[metadataKey]?.invisible"
v-model="iterable[metadataKey]"
:label="metadata[metadataKey]?.description + '(' + metadataKey + ')'" variant="outlined"
dense></v-textarea>
<v-switch v-else-if="metadata[metadataKey]?.type === 'bool' && !metadata[metadataKey]?.invisible" v-model="iterable[metadataKey]"
:label="metadata[metadataKey]?.description + '(' + metadataKey+ ')'" color="primary"
<v-switch v-else-if="metadata[metadataKey]?.type === 'bool' && !metadata[metadataKey]?.invisible"
v-model="iterable[metadataKey]"
:label="metadata[metadataKey]?.description + '(' + metadataKey + ')'" color="primary"
inset></v-switch>
<v-combobox variant="outlined" v-else-if="metadata[metadataKey]?.type === 'list' && !metadata[metadataKey]?.invisible"
v-model="iterable[metadataKey]" chips clearable
:label="metadata[metadataKey]?.description + '(' + metadataKey+ ')'" multiple
prepend-icon="mdi-tag-multiple-outline">
<template v-slot:selection="{ attrs, item, select, selected }">
<v-chip v-bind="attrs" :model-value="selected" closable @click="select"
@click:close="remove(item)">
<strong>{{ item }}</strong>
</v-chip>
</template>
</v-combobox>
<ListConfigItem
v-else-if="metadata[metadataKey]?.type === 'list' && !metadata[metadataKey]?.invisible"
:value="iterable[metadataKey]"
:label="metadata[metadataKey]?.description + '(' + metadataKey+ ')'"/>
<div v-else-if="metadata[metadataKey]?.type === 'object' && !metadata[metadataKey]?.invisible"
style="border: 1px solid #e0e0e0; padding: 8px; margin-bottom: 16px; border-radius: 10px;">
<AstrBotConfig :metadata="metadata[metadataKey].items" :iterable="iterable[metadataKey]"
@@ -113,6 +114,10 @@
}}</v-tooltip>
</v-btn>
</div>
<div>
<v-chip v-if="!metadata[metadataKey]?.invisible" color="primary">{{ metadata[metadataKey]?.type }}</v-chip>
</div>
</div>
</div>
</v-card-text>
@@ -120,8 +125,12 @@
<script>
import { readonly } from 'vue';
import ListConfigItem from './ListConfigItem.vue';
export default {
components: {
ListConfigItem
},
props: {
metadata: Object,
iterable: Object,
@@ -0,0 +1,93 @@
<template>
<div class="list-config-item">
<h3>{{ label }}</h3>
<v-list dense style="background-color: transparent;max-height: 300px; overflow-y: scroll;" >
<v-list-item v-for="(item, index) in items" :key="index">
<v-list-item-content style="display: flex; justify-content: space-between;">
<v-list-item-title>
<v-chip>{{ item }}</v-chip>
</v-list-item-title>
<v-btn @click="removeItem(index)" variant="plain">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-list-item-content>
</v-list-item>
</v-list>
<v-text-field
v-model="newItem"
label="添加新项"
@keyup.enter="addItem"
clearable
dense
hide-details
variant="outlined"
></v-text-field>
</div>
</template>
<script>
export default {
name: 'ListConfigItem',
props: {
value: {
type: Array,
default: () => [],
},
label: {
type: String,
default: '',
},
},
data() {
return {
newItem: '',
items: this.value,
};
},
watch: {
items(newVal) {
this.$emit('input', newVal);
},
},
methods: {
addItem() {
if (this.newItem.trim() !== '') {
this.items.push(this.newItem.trim());
this.newItem = '';
}
},
removeItem(index) {
this.items.splice(index, 1);
},
},
};
</script>
<style scoped>
.list-config-item {
border: 1px solid #e0e0e0;
padding: 16px;
margin-bottom: 16px;
border-radius: 10px;
background-color: #ffffff;
}
.list-config-item h3 {
margin-top: 0;
margin-bottom: 16px;
font-size: 18px;
font-weight: 500;
}
.v-list-item {
padding: 0;
}
.v-list-item-title {
font-size: 14px;
}
.v-btn {
margin-left: 8px;
}
</style>