321 lines
8.5 KiB
Vue
321 lines
8.5 KiB
Vue
<template>
|
|
<div class="ai-model-test">
|
|
<n-card title="AI模型字典API测试">
|
|
<n-space vertical size="large">
|
|
<!-- 操作按钮 -->
|
|
<n-card title="操作" size="small">
|
|
<n-space>
|
|
<n-button
|
|
@click="handleLoadModels"
|
|
:loading="loading"
|
|
type="primary"
|
|
>
|
|
加载AI模型列表
|
|
</n-button>
|
|
<n-button
|
|
@click="handleDirectRequest"
|
|
:loading="loading"
|
|
type="info"
|
|
>
|
|
直接请求测试
|
|
</n-button>
|
|
<n-button @click="handleClearModels">
|
|
清空数据
|
|
</n-button>
|
|
</n-space>
|
|
</n-card>
|
|
|
|
<!-- 状态信息 -->
|
|
<n-card title="状态信息" size="small">
|
|
<n-descriptions :column="2" bordered>
|
|
<n-descriptions-item label="加载状态">
|
|
<n-tag :type="loading ? 'warning' : 'success'">
|
|
{{ loading ? '加载中' : '已完成' }}
|
|
</n-tag>
|
|
</n-descriptions-item>
|
|
<n-descriptions-item label="错误信息">
|
|
<n-tag v-if="error" type="error">
|
|
{{ error }}
|
|
</n-tag>
|
|
<n-tag v-else type="success">无错误</n-tag>
|
|
</n-descriptions-item>
|
|
<n-descriptions-item label="模型数量">
|
|
{{ modelList.length }}
|
|
</n-descriptions-item>
|
|
<n-descriptions-item label="API地址">
|
|
<n-code>/sys/dict/getDictItems/airag_model where model_type = 'LLM',name,id</n-code>
|
|
</n-descriptions-item>
|
|
<n-descriptions-item label="用户Token">
|
|
<n-tag v-if="userStore.token" type="success">已登录</n-tag>
|
|
<n-tag v-else type="warning">未登录</n-tag>
|
|
</n-descriptions-item>
|
|
<n-descriptions-item label="Base URL">
|
|
<n-code>{{ baseURL }}</n-code>
|
|
</n-descriptions-item>
|
|
</n-descriptions>
|
|
</n-card>
|
|
|
|
<!-- 模型列表 -->
|
|
<n-card title="AI模型列表" size="small">
|
|
<n-data-table
|
|
:columns="modelColumns"
|
|
:data="modelList"
|
|
:pagination="false"
|
|
size="small"
|
|
/>
|
|
</n-card>
|
|
|
|
<!-- 选择器测试 -->
|
|
<n-card title="选择器测试" size="small">
|
|
<n-form-item label="选择AI模型">
|
|
<n-select
|
|
v-model:value="selectedModel"
|
|
placeholder="请选择AI模型"
|
|
:options="modelOptions"
|
|
:loading="loading"
|
|
@update:value="handleModelSelect"
|
|
/>
|
|
</n-form-item>
|
|
<n-form-item label="当前选择">
|
|
<n-tag v-if="selectedModel" type="info">
|
|
{{ getSelectedModelText() }}
|
|
</n-tag>
|
|
<span v-else>未选择</span>
|
|
</n-form-item>
|
|
</n-card>
|
|
|
|
<!-- 原始数据 -->
|
|
<n-card title="原始API响应数据" size="small">
|
|
<n-code
|
|
:code="JSON.stringify(rawData, null, 2)"
|
|
language="json"
|
|
show-line-numbers
|
|
/>
|
|
</n-card>
|
|
</n-space>
|
|
</n-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, h } from 'vue'
|
|
import {
|
|
NCard,
|
|
NSpace,
|
|
NDescriptions,
|
|
NDescriptionsItem,
|
|
NTag,
|
|
NButton,
|
|
NDataTable,
|
|
NCode,
|
|
NFormItem,
|
|
NSelect,
|
|
useMessage
|
|
} from 'naive-ui'
|
|
import type { DataTableColumns } from 'naive-ui'
|
|
import { SystemApi, type DictItem } from '@/api'
|
|
import axios from 'axios'
|
|
import { useUserStore } from '@/stores/user'
|
|
|
|
const message = useMessage()
|
|
const userStore = useUserStore()
|
|
|
|
// 状态
|
|
const loading = ref(false)
|
|
const error = ref<string | null>(null)
|
|
const modelList = ref<DictItem[]>([])
|
|
const rawData = ref<any>(null)
|
|
const selectedModel = ref<string>('')
|
|
|
|
// 计算属性
|
|
const baseURL = computed(() => import.meta.env.VITE_API_BASE_URL || '/jeecgboot')
|
|
|
|
// 计算属性
|
|
const modelOptions = computed(() =>
|
|
modelList.value.map(item => ({
|
|
label: item.text,
|
|
value: item.value
|
|
}))
|
|
)
|
|
|
|
// 表格列定义
|
|
const modelColumns: DataTableColumns<DictItem> = [
|
|
{
|
|
title: 'Value',
|
|
key: 'value',
|
|
width: 200,
|
|
render: (row) => {
|
|
return h('code', {
|
|
style: 'background: #f5f5f5; padding: 2px 4px; border-radius: 3px;'
|
|
}, row.value)
|
|
}
|
|
},
|
|
{
|
|
title: 'Text',
|
|
key: 'text',
|
|
width: 120,
|
|
},
|
|
{
|
|
title: 'Label',
|
|
key: 'label',
|
|
width: 120,
|
|
},
|
|
{
|
|
title: 'Title',
|
|
key: 'title',
|
|
width: 120,
|
|
},
|
|
{
|
|
title: 'Color',
|
|
key: 'color',
|
|
width: 100,
|
|
render: (row) => {
|
|
return row.color ? h(NTag, { type: 'info' }, () => row.color) : '无'
|
|
}
|
|
}
|
|
]
|
|
|
|
// 加载AI模型列表
|
|
const handleLoadModels = async () => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
console.log('🚀 开始加载AI模型列表...')
|
|
console.log('🔍 当前时间戳:', Date.now())
|
|
console.log('🔍 请求URL:', '/sys/dict/getDictItems/airag_model%20where%20model_type%20=%20\'LLM\',name,id')
|
|
|
|
const response = await SystemApi.getAiModelDict()
|
|
|
|
console.log('📦 完整API响应:', response)
|
|
console.log('📦 响应数据:', response.data)
|
|
|
|
rawData.value = response
|
|
|
|
if (response.code === 200 || response.code === 0) {
|
|
modelList.value = response.data || []
|
|
message.success(`加载成功,共${modelList.value.length}个模型`)
|
|
console.log('✅ AI模型列表加载成功:', modelList.value)
|
|
} else {
|
|
throw new Error(response.message || '获取模型列表失败')
|
|
}
|
|
} catch (err: any) {
|
|
error.value = err.message || '加载失败'
|
|
message.error(error.value || '未知错误')
|
|
console.error('❌ 加载AI模型列表失败:', err)
|
|
console.error('❌ 错误详情:', {
|
|
message: err.message,
|
|
response: err.response,
|
|
config: err.config,
|
|
stack: err.stack
|
|
})
|
|
|
|
// 保存错误信息到rawData以便查看
|
|
rawData.value = {
|
|
error: err.message,
|
|
response: err.response?.data,
|
|
config: err.config
|
|
}
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 直接请求测试
|
|
const handleDirectRequest = async () => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
console.log('🚀 开始直接请求测试...')
|
|
|
|
const baseURL = import.meta.env.VITE_API_BASE_URL || '/jeecgboot'
|
|
const timestamp = Date.now()
|
|
const token = userStore.token || localStorage.getItem('X-Access-Token') || ''
|
|
|
|
const url = `${baseURL}/sys/dict/getDictItems/airag_model%20where%20model_type%20=%20'LLM',name,id?_t=${timestamp}`
|
|
|
|
console.log('🔍 请求信息:', {
|
|
url,
|
|
timestamp,
|
|
token: token ? '***' : '无',
|
|
baseURL
|
|
})
|
|
|
|
const headers: any = {
|
|
'Content-Type': 'application/json',
|
|
'X-Request-Time': timestamp.toString(),
|
|
'timestamp': timestamp.toString(),
|
|
'X-Timestamp': timestamp.toString(),
|
|
}
|
|
|
|
if (token) {
|
|
headers['X-Access-Token'] = token
|
|
}
|
|
|
|
console.log('🔍 请求头:', headers)
|
|
|
|
const response = await axios.get(url, { headers })
|
|
|
|
console.log('📦 直接请求响应:', response)
|
|
rawData.value = response.data
|
|
|
|
if (response.data.code === 200 || response.data.code === 0) {
|
|
modelList.value = response.data.result || response.data.data || []
|
|
message.success(`直接请求成功,共${modelList.value.length}个模型`)
|
|
} else {
|
|
throw new Error(response.data.message || '直接请求失败')
|
|
}
|
|
} catch (err: any) {
|
|
error.value = err.message || '直接请求失败'
|
|
message.error(error.value || '未知错误')
|
|
console.error('❌ 直接请求失败:', err)
|
|
|
|
rawData.value = {
|
|
error: err.message,
|
|
response: err.response?.data,
|
|
status: err.response?.status,
|
|
headers: err.response?.headers
|
|
}
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 清空数据
|
|
const handleClearModels = () => {
|
|
modelList.value = []
|
|
rawData.value = null
|
|
selectedModel.value = ''
|
|
error.value = null
|
|
message.info('数据已清空')
|
|
}
|
|
|
|
// 模型选择
|
|
const handleModelSelect = (value: string) => {
|
|
const model = modelList.value.find(item => item.value === value)
|
|
if (model) {
|
|
message.info(`已选择: ${model.text}`)
|
|
}
|
|
}
|
|
|
|
// 获取选择的模型文本
|
|
const getSelectedModelText = () => {
|
|
const model = modelList.value.find(item => item.value === selectedModel.value)
|
|
return model ? model.text : selectedModel.value
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.ai-model-test {
|
|
padding: 20px;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
:deep(.n-code) {
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
}
|
|
</style>
|