fix(settings): use local state in LLMTableRow to avoid props mutation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import { Eye, EyeOff, Play, ChevronDown, ChevronRight, Trash2 } from 'lucide-vue-next'
|
import { Eye, EyeOff, Play, ChevronDown, ChevronRight, Trash2 } from 'lucide-vue-next'
|
||||||
import type { LLMModelConfig } from '@/api/settings'
|
import type { LLMModelConfig } from '@/api/settings'
|
||||||
|
|
||||||
@@ -17,6 +17,14 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
const showApiKey = ref(false)
|
const showApiKey = ref(false)
|
||||||
|
const editingModel = ref<LLMModelConfig>({ ...props.model })
|
||||||
|
|
||||||
|
// Reinitialize editing model when expanding (handles editing different rows)
|
||||||
|
watch(() => props.isExpanded, (expanded, wasExpanded) => {
|
||||||
|
if (expanded && !wasExpanded) {
|
||||||
|
editingModel.value = { ...props.model }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const status = computed(() => {
|
const status = computed(() => {
|
||||||
if (!props.model.api_key || !props.model.model) return 'empty'
|
if (!props.model.api_key || !props.model.model) return 'empty'
|
||||||
@@ -37,8 +45,8 @@ function onProviderChange() {
|
|||||||
claude: 'https://api.anthropic.com',
|
claude: 'https://api.anthropic.com',
|
||||||
deepseek: 'https://api.deepseek.com/v1'
|
deepseek: 'https://api.deepseek.com/v1'
|
||||||
}
|
}
|
||||||
if (!props.model.base_url || Object.values(defaults).includes(props.model.base_url)) {
|
if (!editingModel.value.base_url || Object.values(defaults).includes(editingModel.value.base_url)) {
|
||||||
emit('update', { ...props.model, base_url: defaults[props.model.provider] || '' })
|
editingModel.value.base_url = defaults[editingModel.value.provider] || ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -69,7 +77,7 @@ function onProviderChange() {
|
|||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>// PROVIDER</label>
|
<label>// PROVIDER</label>
|
||||||
<select v-model="model.provider" @change="onProviderChange">
|
<select v-model="editingModel.provider" @change="onProviderChange">
|
||||||
<option value="openai">OpenAI</option>
|
<option value="openai">OpenAI</option>
|
||||||
<option value="claude">Claude</option>
|
<option value="claude">Claude</option>
|
||||||
<option value="ollama">Ollama</option>
|
<option value="ollama">Ollama</option>
|
||||||
@@ -79,18 +87,18 @@ function onProviderChange() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>// MODEL</label>
|
<label>// MODEL</label>
|
||||||
<input v-model="model.model" type="text" placeholder="gpt-4o" />
|
<input v-model="editingModel.model" type="text" placeholder="gpt-4o" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>// BASE URL</label>
|
<label>// BASE URL</label>
|
||||||
<input v-model="model.base_url" type="text" />
|
<input v-model="editingModel.base_url" type="text" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>// API KEY</label>
|
<label>// API KEY</label>
|
||||||
<div class="input-with-toggle">
|
<div class="input-with-toggle">
|
||||||
<input
|
<input
|
||||||
v-model="model.api_key"
|
v-model="editingModel.api_key"
|
||||||
:type="showApiKey ? 'text' : 'password'"
|
:type="showApiKey ? 'text' : 'password'"
|
||||||
placeholder="sk-..."
|
placeholder="sk-..."
|
||||||
/>
|
/>
|
||||||
@@ -101,13 +109,13 @@ function onProviderChange() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-actions">
|
<div class="panel-actions">
|
||||||
<button class="test-btn" @click="emit('test', model)">
|
<button class="test-btn" @click="emit('test', editingModel)">
|
||||||
<Play :size="12" /> 测试连接
|
<Play :size="12" /> 测试连接
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="save-btn"
|
class="save-btn"
|
||||||
:disabled="status !== 'available'"
|
:disabled="status !== 'available'"
|
||||||
@click="emit('update', model)"
|
@click="emit('update', editingModel)"
|
||||||
>
|
>
|
||||||
保存
|
保存
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user