CzRger 2 周之前
父节点
当前提交
43bc95263f

+ 46 - 47
src/api/interceptors.ts

@@ -46,6 +46,18 @@ export class Interceptors {
     this.instance.interceptors.response.use(
     this.instance.interceptors.response.use(
       // 请求成功
       // 请求成功
       (res: any) => {
       (res: any) => {
+        if (
+          res.config.url.includes(
+            (import.meta as any).env.VITE_WORKFLOW_API_PROXY,
+          )
+        ) {
+          if (res.data.success) {
+            return Promise.resolve(res.data)
+          } else {
+            this.errorHandle(res)
+            return Promise.reject(res.data)
+          }
+        }
         return Promise.resolve(res.data)
         return Promise.resolve(res.data)
       },
       },
       // 请求失败
       // 请求失败
@@ -66,8 +78,16 @@ export class Interceptors {
 
 
   private errorHandle(res: any) {
   private errorHandle(res: any) {
     console.error('错误接口:' + res.request.responseURL)
     console.error('错误接口:' + res.request.responseURL)
-    const exportLog = (arr, date) => {
+    const exportLog = () => {
       let str = ''
       let str = ''
+      const arr = [
+        `错误日期:${YMDHms(res.headers.date)}`,
+        `接口地址:${res.config.method.toUpperCase()} ${res.request.responseURL}`,
+        `接口状态:${res.status} ${res.statusText}`,
+        `请求Token:${res.config.headers.Authorization}`,
+        `请求参数:${res.config.data}`,
+        `返回结果:${res.request.response}`,
+      ]
       arr.forEach((v) => {
       arr.forEach((v) => {
         str += v
         str += v
         str += '\n\n'
         str += '\n\n'
@@ -76,7 +96,7 @@ export class Interceptors {
       const url = URL.createObjectURL(blob)
       const url = URL.createObjectURL(blob)
       const a = document.createElement('a')
       const a = document.createElement('a')
       a.href = url
       a.href = url
-      a.download = `错误日志_${date}.txt`
+      a.download = `错误日志_${YMDHms(res.headers.date)}.txt`
       document.body.appendChild(a)
       document.body.appendChild(a)
       a.click()
       a.click()
       setTimeout(() => {
       setTimeout(() => {
@@ -84,50 +104,29 @@ export class Interceptors {
         URL.revokeObjectURL(url)
         URL.revokeObjectURL(url)
       }, 0)
       }, 0)
     }
     }
-    // 状态码判断
-    switch (res.status) {
-      case 400:
-        ElNotification({
-          title: res.data.message,
-          message: h('div', null, [
-            h(
-              ElButton,
-              {
-                type: 'warning',
-                size: 'small',
-                plain: true,
-                onClick: () =>
-                  exportLog(
-                    [
-                      `错误日期:${YMDHms(res.headers.date)}`,
-                      `接口地址:${res.config.method.toUpperCase()} ${res.request.responseURL}`,
-                      `接口状态:${res.status} ${res.statusText}`,
-                      `请求Token:${res.config.headers.Authorization}`,
-                      `请求参数:${res.config.data}`,
-                      `返回结果:${res.request.response}`,
-                    ],
-                    YMDHms(res.headers.date),
-                  ),
-              },
-              { default: () => '错误日志' },
-            ),
-            h(
-              'div',
-              { class: 'mt-2' },
-              typeof res.data.data === 'string'
-                ? res.data.data
-                : JSON.stringify(res.data.data),
-            ),
-          ]),
-          type: 'error',
-          duration: 0,
-        })
-        break
-      default:
-        ElNotification({
-          title: '连接错误',
-          type: 'error',
-        })
-    }
+    ElNotification({
+      title: res.data.message,
+      message: h('div', null, [
+        h(
+          ElButton,
+          {
+            type: 'warning',
+            size: 'small',
+            plain: true,
+            onClick: () => exportLog(),
+          },
+          { default: () => '错误日志' },
+        ),
+        h(
+          'div',
+          { class: 'mt-2 overflow-y-auto', style: 'max-height: 50vh;' },
+          typeof res.data.data === 'string'
+            ? res.data.data
+            : JSON.stringify(res.data.data),
+        ),
+      ]),
+      type: 'error',
+      duration: 0,
+    })
   }
   }
 }
 }

+ 8 - 0
src/api/modules/model/index.ts

@@ -12,3 +12,11 @@ export const pluginConfigs = () => get('/plugin/configs', {}, {}, proxy)
 // 根据类型获取对应模型
 // 根据类型获取对应模型
 export const pluginGetListByType = (params) =>
 export const pluginGetListByType = (params) =>
   get('/plugin/get-list-by-type', params, {}, proxy)
   get('/plugin/get-list-by-type', params, {}, proxy)
+// 新增模型纳管
+export const pluginAddInstance = (params) =>
+  post('/plugin/add-instance', params, {}, proxy)
+// 修改模型纳管
+export const pluginUpdateInstance = (params) =>
+  put('/plugin/update-instance', params, {}, proxy)
+// 模型纳管详情
+export const pluginDetail = (id) => get(`/plugin/${id}`, {}, {}, proxy)

+ 9 - 4
src/stores/modules/dictionary.ts

@@ -42,11 +42,16 @@ export const useDictionaryStore = defineStore('dictionary', {
       map: new Map(),
       map: new Map(),
       objMap: new Map(),
       objMap: new Map(),
     },
     },
+    shareConditions: [
+      { label: '不开放', value: 'NO_SHARE' },
+      { label: '全部开放', value: 'OPEN_SHARE' },
+      { label: '申请开放', value: 'SHARE_ON_CONDITION' },
+    ],
   }),
   }),
   getters: {
   getters: {
-    // dictStateMap() {
-    // 	return listToMap(this.dictStateList)
-    // },
+    shareConditionsMap() {
+      return listToMap((this as any).shareConditions)
+    },
   },
   },
   actions: {
   actions: {
     initKnowledgeTags(tenantId) {
     initKnowledgeTags(tenantId) {
@@ -126,7 +131,7 @@ export const useDictionaryStore = defineStore('dictionary', {
               arr.push(
               arr.push(
                 ...v.map((v) => {
                 ...v.map((v) => {
                   v.label = v.providerName
                   v.label = v.providerName
-                  v.value = v.providerName
+                  v.value = v.id
                   return v
                   return v
                 }),
                 }),
               )
               )

+ 1 - 1
src/views/global/login/index.vue

@@ -85,7 +85,7 @@ const state: any = reactive({
     username: 'super-admin',
     username: 'super-admin',
     password: 'Ai@2025',
     password: 'Ai@2025',
     captcha: '',
     captcha: '',
-    tenantId: AppStore.tenantInfo?.id,
+    tenantId: 0,
   },
   },
   loading: false,
   loading: false,
   codeImg: '',
   codeImg: '',

+ 130 - 94
src/views/manage/model/detail.vue

@@ -10,103 +10,75 @@
     :loading="state.loading"
     :loading="state.loading"
   >
   >
     <div class="bm-form">
     <div class="bm-form">
-      <CzrForm ref="ref_form" :form-view="isViewCpt">
+      <CzrForm ref="ref_form" label-width="100px" :form-view="isViewCpt">
         <div class="__czr-title_1">基本信息</div>
         <div class="__czr-title_1">基本信息</div>
         <CzrFormColumn
         <CzrFormColumn
           required
           required
           :span="12"
           :span="12"
-          label="模型供应商"
-          v-model:param="state.form.name"
-          link="select"
-          :options="[]"
-        />
-        <CzrFormColumn
-          required
-          :span="12"
           label="模型类型"
           label="模型类型"
-          v-model:param="state.form.name"
+          v-model:param="state.form.type"
           link="select"
           link="select"
-          :options="[]"
-        />
-        <CzrFormColumn
-          required
-          :span="24"
-          label="模型名称"
-          v-model:param="state.form.name"
-        />
-        <CzrFormColumn
-          :span="24"
-          label="模型简介"
-          v-model:param="state.form.remark"
-          type="textarea"
-          :rows="4"
+          :options="DictionaryStore.modelTypes.list"
+          @change="state.form.pluginClass = ''"
         />
         />
+        <template v-if="state.form.type">
+          <CzrFormColumn
+            required
+            :span="12"
+            label="模型供应商"
+            v-model:param="state.form.pluginClass"
+            link="select"
+            :options="
+              DictionaryStore.modelProvides.list.filter(
+                (v) => v.type === state.form.type,
+              )
+            "
+            @getObject="getModelProvide"
+          />
+        </template>
+        <template v-if="state.form.pluginClass">
+          <CzrFormColumn
+            required
+            :span="24"
+            label="模型名称"
+            v-model:param="state.form.name"
+          />
+          <CzrFormColumn
+            :span="24"
+            label="模型简介"
+            v-model:param="state.form.description"
+            type="textarea"
+            :rows="4"
+          />
+        </template>
         <CzrFormColumn
         <CzrFormColumn
           required
           required
           :span="24"
           :span="24"
           label="共享条件"
           label="共享条件"
-          v-model:param="state.form.name"
-          link="radio"
-          :options="[
-            { label: '不开放', value: 0 },
-            { label: '全部开放', value: 1 },
-            { label: '申请开放', value: 2 },
-          ]"
-        />
-        <div class="__czr-title_1">模型参数配置</div>
-        <CzrFormColumn
-          required
-          :span="12"
-          label="基础URL"
-          v-model:param="state.form.name"
-        />
-        <CzrFormColumn
-          required
-          :span="12"
-          label="上下文长度"
-          v-model:param="state.form.name"
-          link="number"
-        />
-        <CzrFormColumn
-          required
-          :span="12"
-          label="最大Token上限"
-          v-model:param="state.form.name"
-          link="number"
-        />
-        <CzrFormColumn
-          :span="12"
-          label="Vision"
-          v-model:param="state.form.name"
-          link="radio"
-          :options="[
-            { label: '支持', value: 0 },
-            { label: '不支持', value: 1 },
-          ]"
-        />
-        <CzrFormColumn
-          :span="12"
-          label="函数调用"
-          v-model:param="state.form.name"
+          v-model:param="state.form.openStrategy"
           link="radio"
           link="radio"
-          :options="[
-            { label: '支持', value: 0 },
-            { label: '不支持', value: 1 },
-          ]"
-        />
-        <div class="__czr-title_1">业务参数配置</div>
-        <CzrFormColumn
-          required
-          :span="12"
-          label="待定"
-          v-model:param="state.form.name"
-        />
-        <CzrFormColumn
-          required
-          :span="12"
-          label="待定"
-          v-model:param="state.form.name"
+          :options="DictionaryStore.shareConditions"
         />
         />
+        <template v-if="state.form.pluginClass">
+          <template v-if="state.baseForms?.length > 0">
+            <div class="__czr-title_1">基本参数配置</div>
+            <template v-for="item in state.baseForms">
+              <modelFormInit :config="item" :form="state.form.basicConfigs" />
+            </template>
+          </template>
+          <template v-if="state.paramForms?.length > 0">
+            <div class="__czr-title_1">模型参数配置</div>
+            <template v-for="item in state.paramForms">
+              <modelFormInit :config="item" :form="state.form.paramConfigs" />
+            </template>
+          </template>
+          <template v-if="state.bizForms?.length > 0">
+            <div class="__czr-title_1">业务参数配置</div>
+            <template v-for="item in state.bizForms">
+              <modelFormInit :config="item" :form="state.form.bizConfigs" />
+            </template>
+          </template>
+        </template>
       </CzrForm>
       </CzrForm>
     </div>
     </div>
   </CzrDialog>
   </CzrDialog>
@@ -122,10 +94,17 @@ import {
   watch,
   watch,
 } from 'vue'
 } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { ElMessage, ElMessageBox } from 'element-plus'
-import { useDialogStore, useDictionaryStore } from '@/stores'
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
 import { useRouter } from 'vue-router'
 import { useRouter } from 'vue-router'
+import modelFormInit from './model-form-init.vue'
+import {
+  pluginAddInstance,
+  pluginDetail,
+  pluginUpdateInstance,
+} from '@/api/modules/model'
 
 
 const router = useRouter()
 const router = useRouter()
+const AppStore = useAppStore()
 const DictionaryStore = useDictionaryStore()
 const DictionaryStore = useDictionaryStore()
 const DialogStore = useDialogStore()
 const DialogStore = useDialogStore()
 const emit = defineEmits(['update:show', 'refresh'])
 const emit = defineEmits(['update:show', 'refresh'])
@@ -136,7 +115,14 @@ const props = defineProps({
 })
 })
 const state: any = reactive({
 const state: any = reactive({
   loading: false,
   loading: false,
-  form: {},
+  form: {
+    basicConfigs: {},
+    paramConfigs: {},
+    bizConfigs: {},
+  },
+  baseForms: [],
+  paramForms: [],
+  bizForms: [],
 })
 })
 const ref_form = ref()
 const ref_form = ref()
 const titleCpt = computed(() => {
 const titleCpt = computed(() => {
@@ -160,7 +146,15 @@ watch(
   (n) => {
   (n) => {
     if (n) {
     if (n) {
       initDictionary()
       initDictionary()
-      state.form = {}
+      state.form = {
+        tenantId: AppStore.tenantInfo?.id,
+        basicConfigs: {},
+        paramConfigs: {},
+        bizConfigs: {},
+      }
+      state.baseForms = []
+      state.paramForms = []
+      state.bizForms = []
       if (props.transfer.mode !== 'add') {
       if (props.transfer.mode !== 'add') {
         initData()
         initData()
       }
       }
@@ -170,9 +164,16 @@ watch(
     }
     }
   },
   },
 )
 )
-const initDictionary = () => {}
-const initData = () => {}
-const onSubmit = (isImport) => {
+const initDictionary = () => {
+  DictionaryStore.initModelProvides()
+}
+const initData = () => {
+  state.loading = true
+  pluginDetail(props.transfer.id).then(({ data }: any) => {
+    state.form = data
+  })
+}
+const onSubmit = () => {
   ref_form.value
   ref_form.value
     .submit()
     .submit()
     .then(() => {
     .then(() => {
@@ -180,10 +181,33 @@ const onSubmit = (isImport) => {
         content: `请确认是否提交?`,
         content: `请确认是否提交?`,
         onSubmit: () => {
         onSubmit: () => {
           state.loading = true
           state.loading = true
-          ElMessage.success(`${titleCpt.value}成功!`)
-          emit('update:show', false)
-          emit('refresh')
-          state.loading = false
+          if (props.transfer.mode === 'add') {
+            pluginAddInstance(state.form)
+              .then(() => {
+                ElMessage.success(`${titleCpt.value}成功!`)
+                emit('update:show', false)
+                emit('refresh')
+              })
+              .catch(({ message }: any) => {
+                ElMessage.error(message)
+              })
+              .finally(() => {
+                state.loading = false
+              })
+          } else {
+            pluginUpdateInstance(state.form)
+              .then(() => {
+                ElMessage.success(`${titleCpt.value}成功!`)
+                emit('update:show', false)
+                emit('refresh')
+              })
+              .catch(({ message }: any) => {
+                ElMessage.error(message)
+              })
+              .finally(() => {
+                state.loading = false
+              })
+          }
         },
         },
       })
       })
     })
     })
@@ -195,6 +219,18 @@ const onSubmit = (isImport) => {
       })
       })
     })
     })
 }
 }
+const getModelProvide = (obj) => {
+  console.log(obj)
+  state.form.name = obj.name
+  state.form.description = obj.description
+  state.baseForms = obj.basicConfigAttr
+    ? Object.values(obj.basicConfigAttr)
+    : []
+  state.paramForms = obj.paramConfigAttr
+    ? Object.values(obj.paramConfigAttr)
+    : []
+  state.bizForms = obj.bizConfigAttr ? Object.values(obj.bizConfigAttr) : []
+}
 </script>
 </script>
 
 
 <style lang="scss" scoped></style>
 <style lang="scss" scoped></style>

文件差异内容过多而无法显示
+ 27 - 38
src/views/manage/model/index.vue


+ 110 - 0
src/views/manage/model/model-form-init.vue

@@ -0,0 +1,110 @@
+<template>
+  <template v-if="config?.type === 'INPUT'">
+    <CzrFormColumn
+      @click.ctrl="$czrUtil._console(config)"
+      :required="config.required"
+      :span="12"
+      :label="config.screenName"
+      v-model:param="form[config.key]"
+      :rules="
+        config.regEx
+          ? [
+              {
+                handle: (val: any) => !isValue(val) || config.regEx.test(val),
+                message: config.regExNote,
+              },
+            ]
+          : []
+      "
+    />
+  </template>
+  <template v-else-if="config?.type === 'INPUT_NUMBER'">
+    <CzrFormColumn
+      @click.ctrl="$czrUtil._console(config)"
+      :required="config.required"
+      :span="12"
+      :label="config.screenName"
+      v-model:param="form[config.key]"
+      link="number"
+      :max="config.maxNumber"
+      :min="config.minNumber"
+      :decimal="config.decimalSize || 0"
+    />
+  </template>
+  <template v-else-if="config?.type === 'SELECT'">
+    <CzrFormColumn
+      @click.ctrl="$czrUtil._console(config)"
+      :required="config.required"
+      :span="12"
+      :label="config.screenName"
+      v-model:param="form[config.key]"
+      link="select"
+      :options="JSON.parse(config.values)"
+    />
+  </template>
+  <template v-else-if="config?.type === 'CHECKBOX'">
+    <CzrFormColumn
+      @click.ctrl="$czrUtil._console(config)"
+      :required="config.required"
+      :span="12"
+      :label="config.screenName"
+      v-model:param="form[config.key]"
+      link="checkbox"
+      :options="JSON.parse(config.values)"
+    />
+  </template>
+  <template v-else-if="config?.type === 'RADIO'">
+    <CzrFormColumn
+      @click.ctrl="$czrUtil._console(config)"
+      :required="config.required"
+      :span="12"
+      :label="config.screenName"
+      v-model:param="form[config.key]"
+      link="radio"
+      :options="JSON.parse(config.values)"
+    />
+  </template>
+  <template v-else-if="config?.type === 'TEXTAREA'">
+    <CzrFormColumn
+      @click.ctrl="$czrUtil._console(config)"
+      :required="config.required"
+      :span="12"
+      :label="config.screenName"
+      v-model:param="form[config.key]"
+      type="textarea"
+      :rows="4"
+      :rules="
+        config.regEx
+          ? [
+              {
+                handle: (val: any) =>
+                  !isValue(val) || new RegExp(config.regEx).test(val),
+                message: config.regExNote,
+              },
+            ]
+          : []
+      "
+    />
+  </template>
+  <template v-else>
+    <el-col :span="12">
+      <el-button @click="$czrUtil._console(config)">{{
+        config.type
+      }}</el-button>
+    </el-col>
+  </template>
+</template>
+
+<script setup lang="ts">
+import { reactive } from 'vue'
+import CzrFormColumn from '@/components/czr-ui/CzrFormColumn.vue'
+import { isValue } from '@/utils/czr-util'
+
+const props = defineProps({
+  config: { required: true },
+  form: <any>{},
+})
+const state: any = reactive({})
+</script>
+
+<style lang="scss" scoped></style>