Explorar el Código

新增服务商

zhaoen hace 5 meses
padre
commit
37f31732ce

+ 156 - 0
src/views/modleServiceProvide/components/AdditionInfo.vue

@@ -0,0 +1,156 @@
+<template>
+    <el-form
+            :model="form"
+            label-position="top"
+            label-width="120px"
+            :rules="rules"
+            ref="formRef"
+    >
+
+        <!-- 联系方式 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="contact" label="联系方式">
+                    <template #label>
+                        <span class="el-form-item__label">联系方式</span>
+                    </template>
+                    <el-input v-model="form.contact" placeholder="请输入联系方式,如邮箱或电话" />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 官网 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="website" label="官网">
+                    <template #label>
+                        <span class="el-form-item__label">官网</span>
+                    </template>
+                    <el-input v-model="form.website" placeholder="请输入官网地址,如:https://openai.com" />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- API文档地址 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="apiDocUrl" label="API文档地址">
+                    <template #label>
+                        <span class="el-form-item__label">API文档地址</span>
+                    </template>
+                    <el-input v-model="form.apiDocUrl" placeholder="请输入API文档地址" />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 定价页面地址 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="pricingUrl" label="定价页面地址">
+                    <template #label>
+                        <span class="el-form-item__label">定价页面地址</span>
+                    </template>
+                    <el-input v-model="form.pricingUrl" placeholder="请输入定价页面URL" />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 描述 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="description" label="描述">
+                    <el-input
+                            v-model="form.description"
+                            type="textarea"
+                            :rows="4"
+                            placeholder="请输入服务商描述"
+                    />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 备注 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item label="备注" prop="remark">
+                    <el-input
+                            v-model="form.remark"
+                            type="textarea"
+                            :rows="4"
+                            placeholder="请输入备注信息"
+                    />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+    </el-form>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import { ElMessage } from 'element-plus'
+
+// ================== 表单数据类型定义 ==================
+interface Form {
+    contact: string
+    website: string
+    apiDocUrl: string
+    pricingUrl: string
+    description: string
+    remark: string
+}
+const dialogVisible = ref(true)
+// ================== 表单数据初始化 ==================
+const form = ref<Form>({
+    contact: '',
+    website: '',
+    apiDocUrl: '',
+    pricingUrl: '',
+    description: '',
+    remark: ''
+})
+
+// ================== 表单验证规则 ==================
+const rules = {
+    contact: [
+        { required: true, message: '请输入联系方式,如邮箱或电话', trigger: 'blur' }
+    ],
+    website: [
+        { required: true, message: '请输入官网地址', trigger: 'blur' },
+        { type: 'url', message: '请输入合法的网址', trigger: 'blur' }
+    ],
+    apiDocUrl: [
+        { required: true, message: '请输入API文档地址', trigger: 'blur' },
+        { type: 'url', message: '请输入合法的网址', trigger: 'blur' }
+    ],
+    pricingUrl: [
+        { required: true, message: '请输入定价页面地址', trigger: 'blur' },
+        { type: 'url', message: '请输入合法的网址', trigger: 'blur' }
+    ]
+}
+
+// ================== 表单引用 ==================
+const formRef = ref()
+
+// ================== 提交方法 ==================
+const submitForm = () => {
+    formRef.value.validate((valid: boolean) => {
+        if (valid) {
+            ElMessage.success('验证通过,准备提交')
+            console.log('提交数据:', form.value)
+            // 这里可以调用 API 提交数据
+        } else {
+            ElMessage.error('请检查表单输入')
+            return false
+        }
+    })
+}
+</script>
+
+<style scoped lang="scss">
+.input-tips {
+  font-size: 12px;
+  color: #999;
+  margin-top: 4px;
+}
+</style>

+ 197 - 0
src/views/modleServiceProvide/components/ApiInfo.vue

@@ -0,0 +1,197 @@
+<template>
+    <el-form
+            :model="form"
+            label-position="top"
+            label-width="120px"
+            :rules="rules"
+            ref="formRef"
+    >
+
+        <!-- 默认 API 地址 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="defaultApiUrl" label="默认API地址">
+                    <template #label>
+                        <span class="el-form-item__label">默认API地址</span>
+                    </template>
+                    <el-input
+                            v-model="form.defaultApiUrl"
+                            placeholder="请输入默认API地址,如:https://api.openai.com/v1"
+                    />
+                    <div class="input-tips">用于连接服务器的API基础地址</div>
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 认证方式 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="authType" label="认证方式">
+                    <template #label>
+                        <span class="el-form-item__label">认证方式</span>
+                    </template>
+                    <el-select v-model="form.authType" placeholder="请选择认证方式" style="width: 100%">
+                        <el-option
+                                v-for="item in authTypeOption"
+                                :key="item.value"
+                                :label="item.label"
+                                :value="item.value"
+                        />
+                    </el-select>
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 请求头Key -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="requestHeaderKey" label="请求头Key">
+                    <template #label>
+                        <span class="el-form-item__label">请求头Key</span>
+                    </template>
+                    <el-input v-model="form.requestHeaderKey" placeholder="请输入请求头Key,如:Authorization,X-API" />
+                    <div class="input-tips">例如:Authorization, X-API 等</div>
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 请求头Value前缀 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item prop="requestHeaderValuePrefix" label="请求头Value前缀">
+                    <template #label>
+                        <span class="el-form-item__label">请求头Value前缀</span>
+                    </template>
+                    <el-input v-model="form.requestHeaderValuePrefix" placeholder="请输入请求头Value前缀,如:Bearer,basic" />
+                    <div class="input-tips">例如:Bearer, basic 等与API key拼接</div>
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 请求超时时间 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item label="请求超时时间(毫秒)" prop="requestTimeout">
+                    <el-input
+                            v-model.number="form.requestTimeout"
+                            placeholder="请输入请求超时时间(秒)"
+                            style="width: 100%"
+                    />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 重试次数 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item label="重试次数" prop="retryCount">
+                    <template #label>
+                        <span class="el-form-item__label">重试次数</span>
+                    </template>
+                    <el-input
+                            v-model.number="form.retryCount"
+                            placeholder="请输入重试次数"
+                            style="width: 100%"
+                    />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+        <!-- 拓展配置 -->
+        <el-row :gutter="20">
+            <el-col :span="24">
+                <el-form-item label="拓展配置" prop="extraConfig">
+                    <el-input
+                            v-model="form.extraConfig"
+                            type="textarea"
+                            :rows="4"
+                            placeholder="请输入拓展配置,例如:{ timeout: 5000, proxy: 'xxx' }"
+                    />
+                </el-form-item>
+            </el-col>
+        </el-row>
+
+
+
+    </el-form>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import { ElMessage } from 'element-plus'
+const dialogVisible = ref(true)
+// ================== 表单数据类型定义 ==================
+interface Form {
+    defaultApiUrl: string
+    authType: string
+    requestHeaderKey: string
+    requestHeaderValuePrefix: string
+    requestTimeout: number | null
+    retryCount: number | null
+    extraConfig: string
+}
+
+// ================== 表单数据初始化 ==================
+const form = ref<Form>({
+    defaultApiUrl: '',
+    authType: 'API_KEY',
+    requestHeaderKey: 'Authorization',
+    requestHeaderValuePrefix: 'Bearer',
+    requestTimeout: 6,
+    retryCount: 3,
+    extraConfig: ''
+})
+
+// ================== 认证方式选项 ==================
+const authTypeOption = [
+    { label: 'API Key', value: 'API_KEY' },
+    { label: 'OAuth2', value: 'OAUTH2' },
+    { label: 'None', value: 'NONE' }
+]
+
+// ================== 表单验证规则 ==================
+const rules = {
+    defaultApiUrl: [
+        { required: true, message: '请输入默认 API 地址', trigger: 'blur' },
+        { type: 'url', message: '请输入合法的 URL 地址', trigger: 'blur' }
+    ],
+    authType: [
+        { required: true, message: '请选择认证方式', trigger: 'change' }
+    ],
+    requestHeaderKey: [
+        { required: true, message: '请输入请求头 Key', trigger: 'blur' }
+    ],
+    requestHeaderValuePrefix: [
+        { required: true, message: '请输入请求头 Value 前缀', trigger: 'blur' }
+    ],
+    retryCount: [
+        { required: true, message: '请输入重试次数', trigger: 'blur' },
+        { type: 'number', min: 0, max: 10, message: '重试次数应在 0~10 之间', trigger: 'blur' }
+    ]
+}
+
+// ================== 表单引用 ==================
+const formRef = ref()
+
+// ================== 提交方法 ==================
+const submitForm = () => {
+    formRef.value.validate((valid: boolean) => {
+        if (valid) {
+            ElMessage.success('验证通过,准备提交')
+            console.log('提交数据:', form.value)
+            // 这里可以调用 API 提交数据
+        } else {
+            ElMessage.error('请检查表单输入')
+            return false
+        }
+    })
+}
+</script>
+
+<style scoped lang="scss">
+.input-tips {
+  font-size: 12px;
+  color: #999;
+  margin-top: 4px;
+}
+</style>

+ 185 - 0
src/views/modleServiceProvide/components/BasicInfo.vue

@@ -0,0 +1,185 @@
+<script setup lang="ts">
+import { ref } from 'vue'
+import { UploadFilled } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+
+// ================== 表单数据类型定义 ==================
+interface Form {
+    providerCode: string
+    providerName: string
+    modelType: string[]
+    officialCertified: boolean
+    status: boolean
+    sort: number | null
+}
+
+// ================== 表单数据初始化 ==================
+const form = ref<Form>({
+    providerCode: '',
+    providerName: '',
+    modelType: [],
+    officialCertified: false,
+    status: true,
+    sort: null
+})
+
+// ================== 模型种类选项 ==================
+const modelTypeOption = ['大语言模型', '多模态', 'OCR', '视觉', '向量化', '重排序', '语音']
+
+// ================== 表单验证规则 ==================
+const rules = {
+  providerCode: [
+    { required: true, message: '请输入服务商编码', trigger: 'blur' },
+    { pattern: /^[a-z0-9\-_]+$/, message: '只能使用小写字母、数字、下划线或横线', trigger: 'blur' }
+  ],
+  providerName: [
+    { required: true, message: '请输入服务商名称', trigger: 'blur' }
+  ],
+  modelType: [
+    { required: true, message: '请选择至少一个模型种类', trigger: 'change' }
+  ],
+  sort: [
+    { required: true, message: '请输入排序值', trigger: 'blur' },
+    { type: 'number', message: '必须为数字', trigger: 'blur' }
+  ]
+}
+
+// ================== 表单引用 ==================
+const formRef = ref()
+
+// ================== 提交方法 ==================
+const submitForm = () => {
+    formRef.value.validate((valid: boolean) => {
+        if (valid) {
+            ElMessage.success('验证通过,准备提交')
+            console.log('提交数据:', form.value)
+            // 这里可以调用 API 提交数据
+        } else {
+            ElMessage.error('请检查表单输入')
+            return false
+        }
+    })
+}
+
+// ================== 控制对话框显示 ==================
+const dialogVisible = ref(true)
+
+interface ProviderModel {
+
+}
+
+</script>
+
+<template>
+  <el-form :model="form" label-position="top" label-width="100px" :rules="rules" ref="formRef">
+    <!-- 服务商编码 -->
+    <el-row>
+      <el-col :span="24">
+        <el-form-item prop="providerCode" label="服务商编码">
+          <template #label>
+            <span class="el-form-item__label">服务商编码</span>
+          </template>
+          <el-input v-model="form.providerCode" placeholder="输入服务商编码,如:openai" />
+          <div class="input-tips">英文小写,不含特殊字符,作为系统标识</div>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <!-- 服务商名称 -->
+    <el-row :gutter="20">
+      <el-col :span="24">
+        <el-form-item prop="providerName" label="服务商名称">
+          <template #label>
+            <span class="el-form-item__label">服务商名称</span>
+          </template>
+          <el-input v-model="form.providerName" placeholder="输入服务商名称,如:OpenAi" />
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <!-- 模型种类 -->
+    <el-row :gutter="20">
+      <el-col :span="24">
+        <el-form-item prop="modelType" label="模型种类">
+          <template #label>
+            <span class="el-form-item__label">模型种类</span>
+          </template>
+          <el-checkbox-group v-model="form.modelType" style="width: 100%">
+            <el-checkbox
+                v-for="option in modelTypeOption"
+                :key="option"
+                :label="option"
+                :value="option"
+            />
+          </el-checkbox-group>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <!-- Logo -->
+    <el-row :gutter="20">
+      <el-col :span="24">
+        <el-form-item label="Logo">
+          <el-upload
+              style="width: 100%"
+              class="upload-demo"
+              drag
+              action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
+              multiple
+          >
+            <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+            <div class="el-upload__text">
+              点击或拖拽上传Logo
+            </div>
+          </el-upload>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <!-- 官方认证 -->
+    <el-row :gutter="20">
+      <el-col :span="24">
+        <el-form-item label="官方认证">
+          <el-switch v-model="form.officialCertified" />
+          <span class="switch-label">{{ form.officialCertified ? '是' : '否' }}</span>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <!-- 状态 -->
+    <el-row :gutter="20">
+      <el-col :span="12">
+        <el-form-item label="状态">
+          <el-switch v-model="form.status" />
+          <span class="switch-label">{{ form.status ? '启用' : '未启用' }}</span>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <!-- 排序值 -->
+    <el-row :gutter="20">
+      <el-col :span="12">
+        <el-form-item label="排序值" >
+          <el-input v-model.number="form.sort" placeholder="0" />
+          <div class="input-tips">数值越小越靠前</div>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+
+  </el-form>
+</template>
+
+<style scoped lang="scss">
+.input-tips{
+  font-size: 10px;
+  color: #989a9a;
+
+}
+.switch-label {
+  margin-left: 10px;
+  font-size: 14px;
+  color: #666;
+  line-height: 32px;
+}
+</style>

+ 144 - 7
src/views/modleServiceProvide/index.vue

@@ -8,6 +8,7 @@
         <el-form-item label="服务商名称">
             <el-input v-model="input" style="width: 240px" placeholder="请输入服务商名称" />
         </el-form-item>
+
       </el-col>
       <el-col :span="5">
         <el-form-item label="服务商编码">
@@ -47,9 +48,32 @@
     </el-row>
     <el-row :gutter="20">
       <el-col :span="2">
-        <el-button type="primary">
-          +新增服务商
-        </el-button>
+        <el-button type="primary" @click="dialogVisible = true">+新增服务商</el-button>
+        <el-dialog v-model="dialogVisible" title="新增服务商" width="40%">
+
+            <el-form>
+                <!-- Tab 栏 -->
+                <el-tabs  tab-position="top" v-model="activeTab" type="card">
+                    <el-tab-pane label="基本信息" name="info1">
+                        <BasicInfo v-model="formData.info1" />
+                    </el-tab-pane>
+                    <el-tab-pane label="API配置" name="info2">
+                        <ApiInfo v-model="formData.info2" />
+                    </el-tab-pane>
+                    <el-tab-pane label="附加信息" name="info3">
+                        <AdditionInfo v-model="formData.info3" />
+                    </el-tab-pane>
+                </el-tabs>
+                <!-- 提交按钮 -->
+                <div style="display: flex; justify-content: flex-end;">
+                    <el-form-item>
+                        <el-button @click="dialogVisible = false">取消</el-button>
+                        <el-button type="primary" @click="submitForm">提交</el-button>
+                    </el-form-item>
+                </div>
+            </el-form>
+
+        </el-dialog>
       </el-col>
         <el-col :span="1.5">
             <el-button><el-icon><Upload /></el-icon>批量导入</el-button>
@@ -162,13 +186,19 @@
 </template>
 
 <script setup lang="ts">
-
-import {Download, More} from "@element-plus/icons-vue";
 import { ref } from 'vue'
+import type { TabsInstance, FormInstance } from 'element-plus'
+import {Download, More, UploadFilled} from "@element-plus/icons-vue";
 import { View, Edit, List, Check, Close } from '@element-plus/icons-vue'
+import BasicInfo from "@/views/modleServiceProvide/components/BasicInfo.vue";
+import ApiInfo from "@/views/modleServiceProvide/components/ApiInfo.vue";
+import AdditionInfo from "@/views/modleServiceProvide/components/AdditionInfo.vue";
+import components from "../../../vite/plugins/components";
+
+
 const serviceOption = ref(["OpenAI"])
 const modelNameOption = ref(["服务商1","服务商2"])
-const modelTypeOption = ref(["类型1","类型2"])
+const modelTypeOption = ref(["大语言模型","多模态","OCR","视觉","向量化","重排序","语音"])
 const modelStateOption = ref(["全部","开启","关闭"])
 // const models = ref([])
 const total = ref(50) // 总条目数
@@ -177,6 +207,7 @@ const pageSize = ref(10) // 每页显示条目个数
 const selected = ref<number[]>([]) // 存储选中的行ID
 const modelName = ref(null)
 const modelType = ref(null)
+const activeTab = 'info1'
 const service = ref(null)
 const modelState = ref(null)
 // 定义表格数据的类型
@@ -254,9 +285,111 @@ const selectedIds = ref<number[]>([])
 const handleSelectionChange = (selection: ProviderModel[]) => {
   selectedIds.value = selection.map(item => item.id)
 }
+
+const dialogVisible = ref(false)
+const formRef = ref<FormInstance>()
+
+interface Info1 {
+    name: string
+    desc: string
+}
+
+interface Info2 {
+    phone: string
+    email: string
+}
+const formData = ref({
+    info1: { name: '', desc: '' },
+    info2: { phone: '', email: '' },
+    info3: { address: '', remark: '' }
+})
+interface Info3 {
+    address: string
+    remark: string
+}
+
+interface formData {
+    info1: Info1
+    info2: Info2
+    info3: Info3
+}
+
+const form = ref({
+  providerName: '',
+  providerCode: '',
+  modelType: '',
+  logo: '',
+  officialCertified: false,
+  apiAccess: false,
+  status: 'active'
+})
+
+const rules = {
+  providerName: [
+    { required: true, message: '服务商名称不能为空', trigger: 'blur' }
+  ],
+  providerCode: [
+    { required: true, message: '服务商编码不能为空', trigger: 'blur' }
+  ],
+  modelType: [
+    { required: true, message: '请选择模型种类', trigger: 'change' }
+  ]
+}
+
+// const modelTypeOption = ref(['大语言模型', '图像识别', '语音识别'])
+
+// Logo 上传成功回调
+const handleLogoSuccess = (response, file) => {
+  form.value.logo = URL.createObjectURL(file.raw)
+}
+
+// Logo 上传前校验
+const beforeLogoUpload = (file) => {
+  const isValid = ['image/jpeg', 'image/png'].includes(file.type)
+  if (!isValid) {
+    alert('只能上传 JPG/PNG 文件')
+  }
+  return isValid
+}
+
+// 提交表单
+const submitForm = () => {
+  formRef.value.validate(valid => {
+    if (valid) {
+      // 添加 ID 和 创建时间
+      const newProvider = {
+        ...form.value,
+        id: Math.floor(Math.random() * 10000),
+        createTime: new Date().toLocaleString()
+      }
+
+      // 添加到表格数据
+      models.value.unshift(newProvider)
+
+      // 关闭弹窗并重置表单
+      dialogVisible.value = false
+      form.value = {
+        providerName: '',
+        providerCode: '',
+        modelType: '',
+        logo: '',
+        officialCertified: false,
+        apiAccess: false,
+        status: 'active'
+      }
+    } else {
+      return false
+    }
+  })
+}
 </script>
 
 <style scoped lang="scss">
+.input-tips{
+  font-size: 10px;
+  color: #989a9a;
+
+}
 .wrapper{
   margin:10px auto;
   width:90%;
@@ -295,5 +428,9 @@ const handleSelectionChange = (selection: ProviderModel[]) => {
 .table{
   margin-top: 10px;
 }
-
+.el-dialog {
+  .el-form {
+    padding: 10px;
+  }
+}
 </style>