mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-08 01:06:41 +08:00
refactor: optimize ai assistant settings actions
This commit is contained in:
@@ -1341,6 +1341,8 @@ export default {
|
|||||||
llmTestDisabledUnsaved: 'Testing only uses saved configuration. Please save before testing',
|
llmTestDisabledUnsaved: 'Testing only uses saved configuration. Please save before testing',
|
||||||
llmTestSaving: 'Basic settings are being saved, please test again in a moment',
|
llmTestSaving: 'Basic settings are being saved, please test again in a moment',
|
||||||
llmTestLoading: 'Testing LLM call, please wait',
|
llmTestLoading: 'Testing LLM call, please wait',
|
||||||
|
llmTestPanelTitle: 'Connectivity Test',
|
||||||
|
llmTestPanelDesc: 'This test only uses saved AI assistant settings to verify the current LLM service can be called successfully.',
|
||||||
llmTestSuccess: 'Test Succeeded',
|
llmTestSuccess: 'Test Succeeded',
|
||||||
llmTestFailed: 'Test Failed',
|
llmTestFailed: 'Test Failed',
|
||||||
llmTestProvider: 'Provider',
|
llmTestProvider: 'Provider',
|
||||||
@@ -1353,6 +1355,8 @@ export default {
|
|||||||
llmTestReplyPreviewValue: 'Reply Preview: {value}',
|
llmTestReplyPreviewValue: 'Reply Preview: {value}',
|
||||||
llmTestErrorMessage: 'Error Message',
|
llmTestErrorMessage: 'Error Message',
|
||||||
llmTestErrorMessageValue: 'Error Message: {value}',
|
llmTestErrorMessageValue: 'Error Message: {value}',
|
||||||
|
llmTestSuccessDialogTitle: 'AI Assistant Test Succeeded',
|
||||||
|
llmTestSuccessDialogDesc: 'The saved LLM configuration is reachable and returned a valid response.',
|
||||||
llmTestSuccessToast: 'LLM test call succeeded',
|
llmTestSuccessToast: 'LLM test call succeeded',
|
||||||
llmTestFailedToast: 'LLM test call failed',
|
llmTestFailedToast: 'LLM test call failed',
|
||||||
aiAgentGlobal: 'Global AI Assistant',
|
aiAgentGlobal: 'Global AI Assistant',
|
||||||
|
|||||||
@@ -1339,6 +1339,8 @@ export default {
|
|||||||
llmTestDisabledUnsaved: '测试仅针对已保存配置,请先保存后再测试',
|
llmTestDisabledUnsaved: '测试仅针对已保存配置,请先保存后再测试',
|
||||||
llmTestSaving: '基础设置保存中,请稍后再测试',
|
llmTestSaving: '基础设置保存中,请稍后再测试',
|
||||||
llmTestLoading: '正在测试 LLM 调用,请稍候',
|
llmTestLoading: '正在测试 LLM 调用,请稍候',
|
||||||
|
llmTestPanelTitle: '连通性测试',
|
||||||
|
llmTestPanelDesc: '测试按钮仅针对已保存的智能助手配置,用于验证当前 LLM 服务是否可正常调用。',
|
||||||
llmTestSuccess: '测试成功',
|
llmTestSuccess: '测试成功',
|
||||||
llmTestFailed: '测试失败',
|
llmTestFailed: '测试失败',
|
||||||
llmTestProvider: '供应商',
|
llmTestProvider: '供应商',
|
||||||
@@ -1351,6 +1353,8 @@ export default {
|
|||||||
llmTestReplyPreviewValue: '结果摘要:{value}',
|
llmTestReplyPreviewValue: '结果摘要:{value}',
|
||||||
llmTestErrorMessage: '错误信息',
|
llmTestErrorMessage: '错误信息',
|
||||||
llmTestErrorMessageValue: '错误信息:{value}',
|
llmTestErrorMessageValue: '错误信息:{value}',
|
||||||
|
llmTestSuccessDialogTitle: '智能助手测试成功',
|
||||||
|
llmTestSuccessDialogDesc: '当前已保存的 LLM 配置可以正常连通并返回结果。',
|
||||||
llmTestSuccessToast: 'LLM 调用测试成功',
|
llmTestSuccessToast: 'LLM 调用测试成功',
|
||||||
llmTestFailedToast: 'LLM 调用测试失败',
|
llmTestFailedToast: 'LLM 调用测试失败',
|
||||||
aiAgentGlobal: '全局智能助手',
|
aiAgentGlobal: '全局智能助手',
|
||||||
|
|||||||
@@ -1341,6 +1341,8 @@ export default {
|
|||||||
llmTestDisabledUnsaved: '測試僅針對已保存配置,請先保存後再測試',
|
llmTestDisabledUnsaved: '測試僅針對已保存配置,請先保存後再測試',
|
||||||
llmTestSaving: '基礎設置保存中,請稍後再測試',
|
llmTestSaving: '基礎設置保存中,請稍後再測試',
|
||||||
llmTestLoading: '正在測試 LLM 調用,請稍候',
|
llmTestLoading: '正在測試 LLM 調用,請稍候',
|
||||||
|
llmTestPanelTitle: '連通性測試',
|
||||||
|
llmTestPanelDesc: '測試按鈕僅針對已保存的智能助手配置,用於驗證當前 LLM 服務是否可正常調用。',
|
||||||
llmTestSuccess: '測試成功',
|
llmTestSuccess: '測試成功',
|
||||||
llmTestFailed: '測試失敗',
|
llmTestFailed: '測試失敗',
|
||||||
llmTestProvider: '供應商',
|
llmTestProvider: '供應商',
|
||||||
@@ -1353,6 +1355,8 @@ export default {
|
|||||||
llmTestReplyPreviewValue: '結果摘要:{value}',
|
llmTestReplyPreviewValue: '結果摘要:{value}',
|
||||||
llmTestErrorMessage: '錯誤信息',
|
llmTestErrorMessage: '錯誤信息',
|
||||||
llmTestErrorMessageValue: '錯誤信息:{value}',
|
llmTestErrorMessageValue: '錯誤信息:{value}',
|
||||||
|
llmTestSuccessDialogTitle: '智能助手測試成功',
|
||||||
|
llmTestSuccessDialogDesc: '當前已保存的 LLM 配置可以正常連通並返回結果。',
|
||||||
llmTestSuccessToast: 'LLM 調用測試成功',
|
llmTestSuccessToast: 'LLM 調用測試成功',
|
||||||
llmTestFailedToast: 'LLM 調用測試失敗',
|
llmTestFailedToast: 'LLM 調用測試失敗',
|
||||||
aiAgentGlobal: '全局智能助手',
|
aiAgentGlobal: '全局智能助手',
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ const llmModels = ref<string[]>([])
|
|||||||
const loadingModels = ref(false)
|
const loadingModels = ref(false)
|
||||||
const savingBasic = ref(false)
|
const savingBasic = ref(false)
|
||||||
const testingLlm = ref(false)
|
const testingLlm = ref(false)
|
||||||
|
const llmTestSuccessDialog = ref(false)
|
||||||
|
|
||||||
type LlmSettingsSnapshot = {
|
type LlmSettingsSnapshot = {
|
||||||
AI_AGENT_ENABLE: boolean
|
AI_AGENT_ENABLE: boolean
|
||||||
@@ -204,6 +205,7 @@ function invalidateLlmTestState() {
|
|||||||
llmTestAbortController = null
|
llmTestAbortController = null
|
||||||
}
|
}
|
||||||
testingLlm.value = false
|
testingLlm.value = false
|
||||||
|
llmTestSuccessDialog.value = false
|
||||||
llmTestResult.value = null
|
llmTestResult.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,6 +441,7 @@ async function testLlmConnection() {
|
|||||||
llmTestAbortController = abortController
|
llmTestAbortController = abortController
|
||||||
|
|
||||||
testingLlm.value = true
|
testingLlm.value = true
|
||||||
|
llmTestSuccessDialog.value = false
|
||||||
llmTestResult.value = null
|
llmTestResult.value = null
|
||||||
try {
|
try {
|
||||||
const result: { [key: string]: any } = await api.post('system/llm-test', null, {
|
const result: { [key: string]: any } = await api.post('system/llm-test', null, {
|
||||||
@@ -457,7 +460,7 @@ async function testLlmConnection() {
|
|||||||
reply_preview: data.reply_preview,
|
reply_preview: data.reply_preview,
|
||||||
message: result?.message,
|
message: result?.message,
|
||||||
}
|
}
|
||||||
if (result?.success) $toast.success(t('setting.system.llmTestSuccessToast'))
|
if (result?.success) llmTestSuccessDialog.value = true
|
||||||
else $toast.error(t('setting.system.llmTestFailedToast'))
|
else $toast.error(t('setting.system.llmTestFailedToast'))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (requestId !== llmTestRequestId || abortController.signal.aborted || currentLlmSnapshotKey.value !== snapshotKey) {
|
if (requestId !== llmTestRequestId || abortController.signal.aborted || currentLlmSnapshotKey.value !== snapshotKey) {
|
||||||
@@ -1006,74 +1009,101 @@ watch(
|
|||||||
</VCardText>
|
</VCardText>
|
||||||
<VCardText>
|
<VCardText>
|
||||||
<VForm @submit.prevent="() => {}">
|
<VForm @submit.prevent="() => {}">
|
||||||
<VAlert
|
<VRow v-if="SystemSettings.Basic.AI_AGENT_ENABLE" class="mt-1">
|
||||||
v-if="SystemSettings.Basic.AI_AGENT_ENABLE && llmTestResult"
|
<VCol cols="12">
|
||||||
:type="llmTestResult.success ? 'success' : 'error'"
|
<VSheet
|
||||||
variant="tonal"
|
border
|
||||||
density="comfortable"
|
rounded="lg"
|
||||||
class="mb-4"
|
class="pa-4"
|
||||||
>
|
>
|
||||||
<div class="text-subtitle-2 mb-2">
|
<div class="d-flex flex-column flex-md-row align-start align-md-center justify-space-between gap-4">
|
||||||
{{ llmTestResult.success ? t('setting.system.llmTestSuccess') : t('setting.system.llmTestFailed') }}
|
<div class="flex-1-1-auto">
|
||||||
</div>
|
<div class="text-subtitle-1 font-weight-medium">
|
||||||
<div class="text-body-2">
|
{{ t('setting.system.llmTestPanelTitle') }}
|
||||||
{{ t('setting.system.llmTestProviderValue', { value: llmTestResult.provider }) }}
|
</div>
|
||||||
</div>
|
<div class="text-body-2 text-medium-emphasis mt-1">
|
||||||
<div class="text-body-2">
|
{{ t('setting.system.llmTestPanelDesc') }}
|
||||||
{{ t('setting.system.llmTestModelValue', { value: llmTestResult.model }) }}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="llmTestResult.duration_ms !== undefined" class="text-body-2">
|
<div class="w-100 w-md-auto">
|
||||||
{{ t('setting.system.llmTestDurationValue', { duration: llmTestResult.duration_ms }) }}
|
<VTooltip v-if="llmTestDisabledReason" location="top">
|
||||||
</div>
|
<template #activator="{ props }">
|
||||||
<div v-if="llmTestResult.success && llmTestResult.reply_preview" class="text-body-2">
|
<span v-bind="props" class="d-flex">
|
||||||
{{ t('setting.system.llmTestReplyPreviewValue', { value: llmTestResult.reply_preview }) }}
|
<VBtn
|
||||||
</div>
|
color="secondary"
|
||||||
<div v-else-if="llmTestResult.message" class="text-body-2">
|
variant="tonal"
|
||||||
{{ t('setting.system.llmTestErrorMessageValue', { value: llmTestResult.message }) }}
|
prepend-icon="mdi-connection"
|
||||||
</div>
|
:disabled="true"
|
||||||
</VAlert>
|
:loading="testingLlm"
|
||||||
<div class="d-flex flex-wrap gap-4 mt-4">
|
:block="!display.smAndUp.value"
|
||||||
|
class="text-no-wrap"
|
||||||
|
>
|
||||||
|
{{ t('setting.system.llmTestAction') }}
|
||||||
|
</VBtn>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<span>{{ llmTestDisabledReason }}</span>
|
||||||
|
</VTooltip>
|
||||||
|
<VBtn
|
||||||
|
v-else
|
||||||
|
color="secondary"
|
||||||
|
variant="tonal"
|
||||||
|
prepend-icon="mdi-connection"
|
||||||
|
:loading="testingLlm"
|
||||||
|
:block="!display.smAndUp.value"
|
||||||
|
class="text-no-wrap"
|
||||||
|
@click="testLlmConnection"
|
||||||
|
>
|
||||||
|
{{ t('setting.system.llmTestAction') }}
|
||||||
|
</VBtn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<VAlert
|
||||||
|
v-if="llmTestResult && !llmTestResult.success"
|
||||||
|
type="error"
|
||||||
|
variant="tonal"
|
||||||
|
density="comfortable"
|
||||||
|
class="mt-4"
|
||||||
|
>
|
||||||
|
<div class="text-subtitle-2 mb-2">
|
||||||
|
{{ t('setting.system.llmTestFailed') }}
|
||||||
|
</div>
|
||||||
|
<div class="text-body-2">
|
||||||
|
{{ t('setting.system.llmTestProviderValue', { value: llmTestResult.provider }) }}
|
||||||
|
</div>
|
||||||
|
<div class="text-body-2">
|
||||||
|
{{ t('setting.system.llmTestModelValue', { value: llmTestResult.model }) }}
|
||||||
|
</div>
|
||||||
|
<div v-if="llmTestResult.duration_ms !== undefined" class="text-body-2">
|
||||||
|
{{ t('setting.system.llmTestDurationValue', { duration: llmTestResult.duration_ms }) }}
|
||||||
|
</div>
|
||||||
|
<div v-if="llmTestResult.message" class="text-body-2">
|
||||||
|
{{ t('setting.system.llmTestErrorMessageValue', { value: llmTestResult.message }) }}
|
||||||
|
</div>
|
||||||
|
</VAlert>
|
||||||
|
</VSheet>
|
||||||
|
</VCol>
|
||||||
|
</VRow>
|
||||||
|
<div class="setting-actions mt-4">
|
||||||
<VBtn
|
<VBtn
|
||||||
type="submit"
|
type="submit"
|
||||||
@click="saveBasicSettings"
|
@click="saveBasicSettings"
|
||||||
prepend-icon="mdi-content-save"
|
prepend-icon="mdi-content-save"
|
||||||
:loading="savingBasic"
|
:loading="savingBasic"
|
||||||
:disabled="testingLlm"
|
:disabled="testingLlm"
|
||||||
|
:block="!display.smAndUp.value"
|
||||||
|
class="text-no-wrap"
|
||||||
>
|
>
|
||||||
{{ t('common.save') }}
|
{{ t('common.save') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
<VTooltip v-if="SystemSettings.Basic.AI_AGENT_ENABLE && llmTestDisabledReason" location="top">
|
|
||||||
<template #activator="{ props }">
|
|
||||||
<span v-bind="props" class="d-inline-flex">
|
|
||||||
<VBtn
|
|
||||||
color="secondary"
|
|
||||||
variant="tonal"
|
|
||||||
prepend-icon="mdi-connection"
|
|
||||||
:disabled="true"
|
|
||||||
:loading="testingLlm"
|
|
||||||
>
|
|
||||||
{{ t('setting.system.llmTestAction') }}
|
|
||||||
</VBtn>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<span>{{ llmTestDisabledReason }}</span>
|
|
||||||
</VTooltip>
|
|
||||||
<VBtn
|
|
||||||
v-else-if="SystemSettings.Basic.AI_AGENT_ENABLE"
|
|
||||||
color="secondary"
|
|
||||||
variant="tonal"
|
|
||||||
prepend-icon="mdi-connection"
|
|
||||||
:loading="testingLlm"
|
|
||||||
@click="testLlmConnection"
|
|
||||||
>
|
|
||||||
{{ t('setting.system.llmTestAction') }}
|
|
||||||
</VBtn>
|
|
||||||
<VSpacer />
|
|
||||||
<VBtn
|
<VBtn
|
||||||
color="error"
|
color="error"
|
||||||
@click="advancedDialog = true"
|
@click="advancedDialog = true"
|
||||||
prepend-icon="mdi-cog"
|
prepend-icon="mdi-cog"
|
||||||
append-icon="mdi-dots-horizontal"
|
append-icon="mdi-dots-horizontal"
|
||||||
|
:block="!display.smAndUp.value"
|
||||||
|
class="text-no-wrap setting-actions__secondary"
|
||||||
>
|
>
|
||||||
{{ t('setting.system.advancedSettings') }}
|
{{ t('setting.system.advancedSettings') }}
|
||||||
</VBtn>
|
</VBtn>
|
||||||
@@ -1185,6 +1215,53 @@ watch(
|
|||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
|
|
||||||
|
<VDialog
|
||||||
|
v-if="llmTestSuccessDialog && llmTestResult?.success"
|
||||||
|
v-model="llmTestSuccessDialog"
|
||||||
|
max-width="34rem"
|
||||||
|
:fullscreen="display.xs.value"
|
||||||
|
>
|
||||||
|
<VCard>
|
||||||
|
<VCardItem class="py-3">
|
||||||
|
<template #prepend>
|
||||||
|
<VIcon icon="mdi-check-circle" color="success" class="me-2" />
|
||||||
|
</template>
|
||||||
|
<VCardTitle>{{ t('setting.system.llmTestSuccessDialogTitle') }}</VCardTitle>
|
||||||
|
<VCardSubtitle>{{ t('setting.system.llmTestSuccessDialogDesc') }}</VCardSubtitle>
|
||||||
|
</VCardItem>
|
||||||
|
<VDialogCloseBtn @click="llmTestSuccessDialog = false" />
|
||||||
|
<VCardText>
|
||||||
|
<VAlert
|
||||||
|
type="success"
|
||||||
|
variant="tonal"
|
||||||
|
density="comfortable"
|
||||||
|
>
|
||||||
|
{{ t('setting.system.llmTestSuccessToast') }}
|
||||||
|
</VAlert>
|
||||||
|
<div class="d-flex flex-column gap-2 mt-4">
|
||||||
|
<div class="text-body-1">
|
||||||
|
{{ t('setting.system.llmTestProviderValue', { value: llmTestResult.provider }) }}
|
||||||
|
</div>
|
||||||
|
<div class="text-body-1">
|
||||||
|
{{ t('setting.system.llmTestModelValue', { value: llmTestResult.model }) }}
|
||||||
|
</div>
|
||||||
|
<div v-if="llmTestResult.duration_ms !== undefined" class="text-body-1">
|
||||||
|
{{ t('setting.system.llmTestDurationValue', { duration: llmTestResult.duration_ms }) }}
|
||||||
|
</div>
|
||||||
|
<div v-if="llmTestResult.reply_preview" class="text-body-2 text-medium-emphasis">
|
||||||
|
{{ t('setting.system.llmTestReplyPreviewValue', { value: llmTestResult.reply_preview }) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VCardText>
|
||||||
|
<VCardActions class="px-6 pb-6">
|
||||||
|
<VSpacer />
|
||||||
|
<VBtn color="primary" @click="llmTestSuccessDialog = false">
|
||||||
|
{{ t('common.close') }}
|
||||||
|
</VBtn>
|
||||||
|
</VCardActions>
|
||||||
|
</VCard>
|
||||||
|
</VDialog>
|
||||||
|
|
||||||
<!-- 高级系统设置 -->
|
<!-- 高级系统设置 -->
|
||||||
<VDialog
|
<VDialog
|
||||||
v-if="advancedDialog"
|
v-if="advancedDialog"
|
||||||
@@ -1714,3 +1791,23 @@ watch(
|
|||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.setting-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-actions__secondary {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 599px) {
|
||||||
|
.setting-actions {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user