瀏覽代碼

市场模型接口

zhaoen 5 月之前
父節點
當前提交
ef417d44d4
共有 4 個文件被更改,包括 192 次插入114 次删除
  1. 8 0
      src/api/modelConfig/index.ts
  2. 6 15
      src/views/market/addModel.vue
  3. 63 8
      src/views/market/index.vue
  4. 115 91
      src/views/modeldetailed/index.vue

+ 8 - 0
src/api/modelConfig/index.ts

@@ -75,3 +75,11 @@ export const toggleStatus = (data:boolean,id:Number) => {
     data:data
   })
 }
+
+export const exportModel = (data:ModelList) =>{
+  return request({
+    url:'/ai/model/config/export',
+    method:'post',
+    data:data
+  })
+}

+ 6 - 15
src/views/market/addModel.vue

@@ -1,28 +1,19 @@
 <script setup lang="ts">
 import type { FormInstance, FormRules } from 'element-plus'
 import {addModel,editModel} from '@/api/modelConfig'
+import {modelConfigForm} from '@/api/modelConfig/types'
 import {onMounted} from 'vue';
 
 const props = defineProps<{
   modelValue: boolean,
   addOrEdit:string,
-  model: RuleForm,
+  model: modelConfigForm,
 }>()
 const emit = defineEmits<{ (e: 'update:dialogVisible', value: boolean): void }>()
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const baseInfoFormRef = ref<FormInstance>()
-interface RuleForm{
-  modelName:string,
-  modelType:string,
-  modelVersion:string,
-  baseUrl:string,
-  apiKey:string,
-  status:boolean|number,
-  priority:number|null,
-  id?:number|null,
-  description:string
-}
-const DEFAULT_FORM: RuleForm = {
+
+const DEFAULT_FORM: modelConfigForm = {
   modelName: '',
   modelType: '',
   modelVersion: '',
@@ -32,8 +23,8 @@ const DEFAULT_FORM: RuleForm = {
   apiKey: '',
   baseUrl: ''
 }
-const baseInfoForm = ref<RuleForm>({...DEFAULT_FORM})
-const rules = reactive<FormRules<RuleForm>>(
+const baseInfoForm = ref<modelConfigForm>({...DEFAULT_FORM})
+const rules = reactive<FormRules<modelConfigForm>>(
   {
     modelName:[
       { required:true,message:"请输入模型名称",trigger:"blur" }

+ 63 - 8
src/views/market/index.vue

@@ -66,7 +66,7 @@
         </el-button>
       </el-col>
       <el-col :span="1">
-        <el-button><el-icon><Download /></el-icon>导出</el-button>
+        <el-button @click="handleExport"><el-icon><Download /></el-icon>导出</el-button>
       </el-col>
     </el-row>
     <div class="content">
@@ -159,10 +159,10 @@
     </div>
     <div class="foot">
       <div class="left">
-        <div style="line-height: 2">已选择0项</div>
-        <el-button>批量启用</el-button>
-        <el-button>批量禁用</el-button>
-        <el-button type="danger">批量删除</el-button>
+        <div style="line-height: 2">已选择{{selectedRows.length}}项</div>
+        <el-button @click="handleEnable">批量启用</el-button>
+        <el-button @click="handleDisabled">批量禁用</el-button>
+        <el-button type="danger" @click="handleDelete">批量删除</el-button>
       </div>
       <div class="right">
         <el-pagination
@@ -183,7 +183,7 @@
 import addModel from './addModel.vue'
 import { useRouter } from 'vue-router'
 import {onMounted} from 'vue';
-import {getModelByType,queryModelByNameType,deleteModel,queryModelList,toggleStatus} from '@/api/modelConfig/index'
+import {getModelByType,queryModelByNameType,deleteModel,queryModelList,toggleStatus,exportModel} from '@/api/modelConfig/index'
 import { ModelConfigVo} from '@/api/modelConfig/types'
 
 const router = useRouter()
@@ -193,6 +193,7 @@ const modelNameOption = ref(["模型1","模型2"])
 const modelTypeOption = ref(["类型1","类型2"])
 const modelStateOption = ref(["全部","开启","关闭"])
 const modelData = ref<ModelConfigVo[]>()
+const model = ref<ModelConfigVo>()
 const pageSize = ref(10)
 const selectedRows = ref([])
 
@@ -222,22 +223,76 @@ const toggleModelStatus = async (row) =>{
     await fetchData()
   }
 }
+const handleExport = async () => {
+  const res = await exportModel(modelData)
+  if(res.code === 0){
+    ElMessage({
+      message:'导出成功',
+      type:'success'
+    })
+  }
+}
 const handleSelectionChange = (value)=>{
   selectedRows.value = value;
 }
 const handleAddModel = ()=>{
   addOrEdit.value="新增"
   dialogVisible.value = true;
-  console.log("dialogVisible:",dialogVisible)
 }
 const handleDetail = () =>{
-  router.push('/modeldetailed')
+  router.push({path: '/modeldetailed',query: model})
 }
 const edit = ((index,row)=>{
   modelInfo.value = { ...row }
   addOrEdit.value = "编辑"
   dialogVisible.value=true
 })
+const handleDelete = () =>{
+  console.log('进入了')
+  ElMessageBox.confirm(
+    '此操作将无法撤销,是否继续',
+    '警告',
+    {
+      confirmButtonText:'确定',
+      cancelButtonText: '取消'
+    }
+  ).then(()=>{
+    doDelete()
+  })
+}
+const doDelete = async () => {
+  const promises = selectedRows.value.map(item => deleteModel(item.id));
+  const results = await Promise.all(promises);
+  await fetchData();
+  if(results.every(res => res.code===0)){
+    ElMessage({
+      type:'success',
+      message:'删除成功',
+    })
+  }
+}
+const handleEnable = async () => {
+  const promises = selectedRows.value.map(item => toggleStatus(1,item.id));
+  const results = await Promise.all(promises)
+  await fetchData();
+  if(results.every(res => res.code===0)){
+    ElMessage({
+      type:'success',
+      message:'启用成功',
+    })
+  }
+}
+const handleDisabled = async () => {
+  const promises = selectedRows.value.map(item => toggleStatus(0,item.id));
+  const results = await Promise.all(promises)
+  await fetchData();
+  if(results.every(res => res.code===0)){
+    ElMessage({
+      type:'success',
+      message:'禁用成功',
+    })
+  }
+}
 const handleSearch = async () => {
   if(modelType.value&&modelName.value){
     const data = {

+ 115 - 91
src/views/modeldetailed/index.vue

@@ -28,36 +28,37 @@
                     <div class="model-top-title">基本信息</div>
                     <div class="model-top-row">
                         <span class="model-top-label">模型名称:</span>
-                        <span class="model-top-value">GPT-4</span>
+                        <span class="model-top-value">GPT-4{{model?.modelName}}</span>
                     </div>
                     <div class="model-top-row">
                         <span class="model-top-label">模型类型:</span>
-                        <span class="model-top-value">大语言模型(LLM)</span>
+                        <span class="model-top-value">大语言模型(LLM){{model?.modelType}}</span>
                     </div>
                     <div class="model-top-row">
                         <span class="model-top-label">模型版本:</span>
-                        <span class="model-top-value">gpt-4-1106-preview</span>
+                        <span class="model-top-value">gpt-4-1106-preview{{model?.modelVersion}}</span>
                     </div>
                     <div class="model-top-row">
                         <span class="model-top-label">状态:</span>
-                        <el-tag type="success" size="small">启用</el-tag>
+                        <el-tag type="success" size="small" v-if="model?.status===1">启用</el-tag>
+                        <el-tag type="warning" size="small" v-else-if="model?.status === 0">测试中</el-tag>
                     </div>
                     <div class="model-top-row">
                         <span class="model-top-label">API地址:</span>
-                        <a class="model-top-link" href="https://api.openai.com/v1/chat/completions" target="_blank">https://api.openai.com/v1/chat/completions</a>
+                        <a class="model-top-link" href="https://api.openai.com/v1/chat/completions" target="_blank">https://api.openai.com/v1/chat/completions{{model?.baseUrl}}</a>
                     </div>
                     <div class="model-top-row">
                         <span class="model-top-label">描述:</span>
-                        <span class="model-top-value">GPT-4是OpenAI最先进的大型语言模型,在各种专业和学术基准上表现最佳。相比GPT-3.5,GPT-4在创造性写作、编码和解决复杂问题方面表现出显著提升,能更好地遵循用户意图,理解和生成更长的内容。</span>
+                        <span class="model-top-value">{{model?.description}}GPT-4是OpenAI最先进的大型语言模型,在各种专业和学术基准上表现最佳。相比GPT-3.5,GPT-4在创造性写作、编码和解决复杂问题方面表现出显著提升,能更好地遵循用户意图,理解和生成更长的内容。</span>
                     </div>
                 </div>
                 <!-- 右侧服务信息和按钮 -->
                 <div class="model-top-right">
                     <div class="model-top-right-info">
-                        <div><span class="model-top-label">服务商:</span>&nbsp&nbspOpenAI</div>
-                        <div><span class="model-top-label">优先级:</span>&nbsp&nbsp90</div>
-                        <div><span class="model-top-label">创建时间:</span>&nbsp&nbsp2025-05-15 10:30:15</div>
-                        <div><span class="model-top-label">更新时间:</span>&nbsp&nbsp2025-06-20 14:45:30</div>
+                        <div style="display: flex"><span class="model-top-label">服务商:</span>&nbsp&nbspOpenAI</div>
+                        <div style="display: flex"><span class="model-top-label">优先级:</span>&nbsp&nbsp90{{model?.priority}}</div>
+                        <div style="display: flex"><span class="model-top-label">创建时间:</span>&nbsp&nbsp2025-05-15 10:30:15{{model?.createTime}}</div>
+                        <div style="display: flex"><span class="model-top-label">更新时间:</span>&nbsp&nbsp2025-06-20 14:45:30{{model?.updateTime}}</div>
                     </div>
 
                 </div>
@@ -86,20 +87,23 @@
         </el-card>
         <!-- 抽屉 -->
         <el-drawer
-            title="编辑参数"
+
             v-model="drawerVisible"
             direction="rtl"
-            size="20%"
-    >
-          <el-divider style="margin: 1px 0;" />
+            size="40%"
+            class="drawer-style"
+        >
+          <template #header="{close,titleId,titleClass}">
+            <h2 :id="titleId" style="color:#000000">编辑参数</h2>
+          </template>
           <div >
-            <h3>模型</h3>
+            <h4>模型</h4>
             <el-card class="model-card" style=" background:#F5F5F5;">
               GPT-4 (OpenAI)<br/>
               <span style="color: #777777">版本: gpt-4-1106-preview</span>
             </el-card>
 
-            <h3 style="color: #777777">快速添加参数模板</h3>
+            <h4>快速添加参数模板</h4>
 
             <el-row :gutter="20">
               <el-col :span="12">
@@ -117,7 +121,7 @@
               </el-col>
             </el-row>
 
-            <h3>参数列表</h3>
+            <h4>参数列表</h4>
             <div v-for="(item, index) in tableData" :key="index" class="parameter-card">
               <el-card shadow="never" style="background-color: #FAFAFA" >
                 <div class="card-content">
@@ -171,89 +175,108 @@
     </div>
 </template>
 
-<script>
-import * as echarts from 'echarts';
-import {Refresh} from "@element-plus/icons-vue";
-export default {
-    components: {Refresh},
-    data() {
-        return {
-            tableData: [
-                { name: 'temperature', type: 'NUMBER', defaultValue: '0.7', isRequired: '否', description: '控制生成文本的随机性,值越小结果越随机' },
-                { name: 'max_tokens', type: 'NUMBER', defaultValue: '1024', isRequired: '否', description: '生成文本的最大令牌数' },
-                { name: 'top_p', type: 'NUMBER', defaultValue: '0.95', isRequired: '否', description: '核采样阈值,控制模型选择词的概率分布' },
-                { name: 'frequency_penalty', type: 'NUMBER', defaultValue: '0', isRequired: '否', description: '减少重复词组的出现概率' },
-                { name: 'presence_penalty', type: 'NUMBER', defaultValue: '0', isRequired: '否', description: '增加新话题出现的概率' },
-                { name: 'stream', type: 'BOOLEAN', defaultValue: 'false', isRequired: '否', description: '是否启用流式输出' }
-            ],
-            statList: [
-                { label: '调用次数', value: '156,783', trend: 12.5 },
-                { label: '平均响应时间', value: '1.68s', trend: -0.2 },
-                { label: '成功率', value: '99.87%', trend: 0.05 },
-                { label: 'Token消耗', value: '5.6M', trend: 18.3 }
-            ],
-            statRange: 'month',
-            drawerVisible: false,
-            currentRow: {},       // 当前编辑的行数据
-            currentRowIndex: -1
-        }
+<script setup lang="ts">
+import { ref, onMounted } from 'vue'
+import * as echarts from 'echarts'
+import { Refresh } from "@element-plus/icons-vue"
+import { useRoute } from 'vue-router';
+import { ModelConfigVo} from '@/api/modelConfig/types'
+import {toggleStatus} from '@/api/modelConfig/index.js'
+
+const route = useRoute()
+const model = ref<ModelConfigVo>(route.query.model)
+
+// 表格数据
+const tableData = ref([
+  { name: 'temperature', type: 'NUMBER', defaultValue: '0.7', isRequired: '否', description: '控制生成文本的随机性,值越小结果越随机' },
+  { name: 'max_tokens', type: 'NUMBER', defaultValue: '1024', isRequired: '否', description: '生成文本的最大令牌数' },
+  { name: 'top_p', type: 'NUMBER', defaultValue: '0.95', isRequired: '否', description: '核采样阈值,控制模型选择词的概率分布' },
+  { name: 'frequency_penalty', type: 'NUMBER', defaultValue: '0', isRequired: '否', description: '减少重复词组的出现概率' },
+  { name: 'presence_penalty', type: 'NUMBER', defaultValue: '0', isRequired: '否', description: '增加新话题出现的概率' },
+  { name: 'stream', type: 'BOOLEAN', defaultValue: 'false', isRequired: '否', description: '是否启用流式输出' }
+])
+
+// 统计卡片数据
+const statList = ref([
+  { label: '调用次数', value: '156,783', trend: 12.5 },
+  { label: '平均响应时间', value: '1.68s', trend: -0.2 },
+  { label: '成功率', value: '99.87%', trend: 0.05 },
+  { label: 'Token消耗', value: '5.6M', trend: 18.3 }
+])
+
+// 其他响应式数据
+const statRange = ref('month')
+const drawerVisible = ref(false)
+const currentRow = ref({})
+const currentRowIndex = ref(-1)
+
+// 生命周期钩子
+onMounted(() => {
+  initCallTrendChart()
+
+})
+
+// 方法
+const handleEdit = (index, row) => {
+  currentRowIndex.value = index
+  currentRow.value = { ...row }
+  drawerVisible.value = true
+}
+
+const handleDelete = (index) => {
+  tableData.value.splice(index, 1)
+}
+
+const saveEdit = () => {
+  tableData.value[currentRowIndex.value] = { ...currentRow.value }
+  drawerVisible.value = false
+}
+
+const initCallTrendChart = () => {
+  const callTrendChart = echarts.init(document.getElementById('callTrendChart'))
+  const option = {
+    tooltip: {},
+    xAxis: {
+      type: 'category',
+      data: ['1月', '2月', '3月', '4月', '5月', '6月'],
+      axisLine: { lineStyle: { color: '#e5e6eb' } },
+      axisLabel: { color: '#888' },
     },
- // 当前编辑的行索引
-    mounted() {
-        this.initCallTrendChart();
+    yAxis: {
+      type: 'value',
+      axisLine: { lineStyle: { color: '#e5e6eb' } },
+      splitLine: { lineStyle: { color: '#f0f0f0' } },
+      axisLabel: { color: '#888' },
     },
-    methods: {
-        handleEdit(index, row) {
-            this.currentRowIndex = index
-            this.currentRow = { ...row }  // 拷贝一份数据,避免直接修改原数据
-            this.drawerVisible = true
-        },
-        handleDelete(index, row) {
-            this.tableData.splice(index, 1)
-        },
-        saveEdit() {
-            this.$set(this.tableData, this.currentRowIndex, { ...this.currentRow })  // 替换数组中的对象
-            this.drawerVisible = false
-        },
-        initCallTrendChart() {
-            const callTrendChart = echarts.init(document.getElementById('callTrendChart'));
-            const option = {
-                tooltip: {},
-                xAxis: {
-                    type: 'category',
-                    data: ['1月', '2月', '3月', '4月', '5月', '6月'],
-                    axisLine: { lineStyle: { color: '#e5e6eb' } },
-                    axisLabel: { color: '#888' },
-                },
-                yAxis: {
-                    type: 'value',
-                    axisLine: { lineStyle: { color: '#e5e6eb' } },
-                    splitLine: { lineStyle: { color: '#f0f0f0' } },
-                    axisLabel: { color: '#888' },
-                },
-                series: [
-                    {
-                        data: [120, 200, 150, 80, 70, 110],
-                        type: 'bar',
-                        name: '调用次数',
-                        itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] },
-                        barWidth: 24,
-                    },
-                ],
-                grid: { left: 40, right: 20, top: 30, bottom: 30 },
-            }
-            callTrendChart.setOption(option);
-        }
-    }
+    series: [
+      {
+        data: [120, 200, 150, 80, 70, 110],
+        type: 'bar',
+        name: '调用次数',
+        itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] },
+        barWidth: 24,
+      },
+    ],
+    grid: { left: 40, right: 20, top: 30, bottom: 30 },
+  }
+  callTrendChart.setOption(option)
 }
-</script>
 
+
+</script>
 <style scoped>
 .actions{
   display: flex;
 }
+.drawer-style{
 
-
+  header.el-drawer__header{
+    margin-bottom: 0 !important;
+  }
+}
+:deep(header.el-drawer__header){
+  margin-bottom: 0 !important;
+}
 /* 确保图标靠右对齐 */
 
 .parameter-card {
@@ -323,6 +346,7 @@ export default {
     color: #888;
     min-width: 80px;
     margin-right: 2px;
+
 }
 .model-top-value {
     color: #222;