Ver Fonte

Merge branch 'wxd/faVersion'

sheldon há 1 mês atrás
pai
commit
f0d4f26771

+ 1 - 1
src/api/index.ts

@@ -37,7 +37,7 @@ api.interceptors.request.use(
     // 设置请求头
     if (request.headers) {
       if (userStore.isLogin) {
-        request.headers.Token = userStore.token
+        request.headers.accessToken = userStore.token
         // request.headers.adminToken = userStore.token
       }
     }

+ 12 - 1
src/api/modules/anycallService.ts

@@ -51,7 +51,10 @@ export type TRole = {
   voiceFileName: string;
   voiceId: string;
 };
-export function createRole(params: TRole){
+export function saveRole(params: TRole){
+  if(params.id){
+    return request(`/anycall/update`, params)
+  }
   return request(`/anycall/create`, params)
 }
 export function importZip(params: any){
@@ -64,3 +67,11 @@ export function importZip(params: any){
         };
   return request(`/anycall/import`, params, config)
 }
+
+
+export function updateAgentLLm(params: {
+  agentId: string,
+  llmId: string
+}){
+  return request(`/anycall/updateAgentLLm`, params)
+}

+ 16 - 2
src/api/modules/model.ts

@@ -2,10 +2,24 @@ import { request } from '@/api'
 import type { TModel } from '@/types/model'
 
 // 获取大模型列表
-export function fetchModel(){
-  return request<{
+export async function fetchModel(){
+  // return request<{
+  //   total: number,
+  //   content: TModel[]
+  // }>(`/anycall/selectLLMModel`)
+  const res = await request<{
     total: number,
     content: TModel[]
   }>(`/anycall/selectLLMModel`)
+  console.log(res.data, 4444444)
+  //@ts-ignore
+  return res.data
+}
+
+export async function fetchModelDetail(){
+  return request<{
+    total: number,
+    content: TModel[]
+  }>(`/anycall/selectAgentDetail`)
 }
 

+ 82 - 0
src/components/LLMSelector.vue

@@ -0,0 +1,82 @@
+<script setup lang="ts">
+import { fetchModel } from '@/api/modules/model'
+
+// 定义组件属性
+interface Props {
+  modelValue?: string
+  disabled?: boolean
+  placeholder?: string
+  style?: string | object
+  className?: string
+}
+
+// 定义组件事件
+interface Emits {
+  (e: 'update:modelValue', value: string | undefined): void
+}
+
+// 设置默认属性
+const props = withDefaults(defineProps<Props>(), {
+  disabled: false,
+  placeholder: '请选择大模型',
+  style: 'width: 220px;'
+})
+
+// 定义事件触发器
+const emit = defineEmits<Emits>()
+
+// 创建本地响应式变量用于v-model绑定
+const localValue = ref(props.modelValue)
+
+// 监听props中的modelValue变化,同步到本地变量
+watch(
+  () => props.modelValue,
+  (newValue) => {
+    localValue.value = newValue
+  },
+  { immediate: true }
+)
+
+// 音色选项数据
+const options = ref<Array<{value: string, name: string}>>([])
+
+// 获取音色数据
+const fetchData = async () => {
+  try {
+    const params = {
+      page: 1,
+      size: 100,
+    }
+    const res = await fetchModel()
+    if (res.code === 0) {
+      // 将API返回的数据转换为select需要的格式
+      options.value = res.data.content.map((item: any) => ({
+        value: item.id,
+        name: item.name
+      }))
+    } else {
+      console.error('获取模型失败:', res.msg)
+    }
+  } catch (error) {
+    console.error('获取模型失败:', error)
+  }
+}
+
+// 组件挂载时获取数据
+onMounted(() => {
+  fetchData()
+})
+</script>
+
+<template>
+  <el-select
+    v-model="localValue"
+    :placeholder="placeholder"
+    :style="style"
+    :disabled="disabled"
+    :class="className"
+    @update:model-value="(value) => emit('update:modelValue', value)"
+  >
+    <el-option v-for="item in options" :key="item.value" :label="item.name" :value="item.value" />
+  </el-select>
+</template>

+ 3 - 3
src/store/modules/user.ts

@@ -28,7 +28,7 @@ export const useUserStore = defineStore(
     }) {
       const {code, data} = await apiUser.login(params)
       if(code === 0 ){
-        localStorage.setItem('token', data)
+        localStorage.setItem('accessToken', data)
         token.value = data
       }
     }
@@ -36,7 +36,7 @@ export const useUserStore = defineStore(
     // 手动登出
     function logout(redirect = router.currentRoute.value.fullPath) {
       // 此处仅清除计算属性 isLogin 中判断登录状态过期的变量,以保证在弹出登录窗口模式下页面展示依旧正常
-      localStorage.removeItem('token')
+      localStorage.removeItem('accessToken')
       token.value = ''
       router.push({
         name: 'login',
@@ -48,7 +48,7 @@ export const useUserStore = defineStore(
     // 请求登出
     function requestLogout() {
       // 此处仅清除计算属性 isLogin 中判断登录状态过期的变量,以保证在弹出登录窗口模式下页面展示依旧正常
-      localStorage.removeItem('token')
+      localStorage.removeItem('accessToken')
       token.value = ''
       router.push({
         name: 'login',

+ 1 - 0
src/types/model.ts

@@ -9,3 +9,4 @@ export type TModel = {
   ctime: number;
   customEdit: boolean;
 };
+

+ 1 - 1
src/ui/components/FaImageUpload/index.vue

@@ -106,7 +106,7 @@ function onSelectFile(e: Event) {
       headersObj = { ...props.headers }
     }
     return axios({
-      url: props.action ?? `${import.meta.env.VITE_APP_API_BASEURL}/cmn/upload`,
+      url: props.action ?? `${import.meta.env.VITE_APP_CDN_BASEURL}/cmn/upload`,
       method: props.method,
       headers: headersObj,
       data: formData,

+ 18 - 26
src/views/model/model-list/index.vue

@@ -4,13 +4,12 @@ defineOptions({
   name: 'modelList',
 })
 import { Plus } from '@element-plus/icons-vue'
-import { ElButton, ElDialog, ElEmpty, ElInput, ElOption, ElPagination, ElSelect, ElTable, ElTableColumn, ElTag } from 'element-plus'
+import { ElButton, ElDialog, ElEmpty, ElInput, ElMessage, ElOption, ElPagination, ElSelect, ElTable, ElTableColumn, ElTag } from 'element-plus'
 // import SearchForm from './components/SearchForm.vue'
 
 import type { TModel } from '@/types/model'
 import { fetchModel } from '@/api/modules/model'
 import { formatDateGeneral } from '@/utils'
-import { size } from 'zod'
 
 const tableRef = ref()
 const loading = ref(false)
@@ -38,10 +37,11 @@ const  handleRecommend = (id: string) => {
 
 async function fetchData() {
   loading.value = true
-  console.log(11133)
   const res = await fetchModel()
+  console.log(res, 'res')
   if(res.code === 0){
     dataList.value = res.data.content
+    console.log(dataList.value, 'dataList')
     pagination.value.total = res.data.total
   }
   loading.value = false
@@ -59,18 +59,11 @@ function handleSizeChange(size: number) {
   fetchData()
 }
 
-function handleSearch () {
-  pagination.value.page = 1 // 搜索时重置到第一页
-  fetchData()
+function handleView (row: TModel) {
+  console.log(row, 'view')
+  ElMessage.info('查看功能待开发')
 }
 
-function handleReset () {
-  searchParams.value = {
-    name: '',
-  }
-  pagination.value.page = 1 // 重置时重置到第一页
-  fetchData()
-}
 
 
 onMounted(async () => {
@@ -85,26 +78,25 @@ onMounted(async () => {
     <FaPageHeader title="大模型列表" />
     <FaPageMain class="flex-1 overflow-auto" main-class="flex-1 flex flex-col overflow-auto">
       <ElTable
+        v-loading="loading"
         ref="tableRef" :data="dataList" stripe highlight-current-row border height="100%"
       >
-        <ElTableColumn label="ID" prop="id" min-width="240" />
-        <ElTableColumn label="Agent ID" prop="agentId" min-width="220" />
-        <ElTableColumn label="Role Name" prop="name" min-width="220" />
-        <ElTableColumn label="Avatar" prop="photo">
-          <template #default="{row}">
-            <ElImage :src="row.photo" fit="cover" class="w-12 h-12 rounded" />
+        <ElTableColumn label="id" prop="id" min-width="240" />
+        <ElTableColumn label="Name" prop="name" min-width="220" />
+        <ElTableColumn label="service" prop="service" />
+        <ElTableColumn label="spaceId" prop="spaceId" />
+        <ElTableColumn label="userId" prop="userId" width="180" />
+        <ElTableColumn label="userId" prop="customEdit" width="180" />
+        <ElTableColumn label="createTime" prop="ctime" width="180">
+          <template #default="scope">
+            {{ formatDateGeneral(scope.row.ctime) }}
           </template>
         </ElTableColumn>
-        <ElTableColumn label="callings" prop="callings" />
-        <ElTableColumn label="Voice Name" prop="voiceName" min-width="240" />
-        <ElTableColumn label="prompt" prop="prompt" min-width="340">
+        <ElTableColumn fixed="right" label="操作" min-width="200">
           <template #default="{row}">
-            <ElTag type="info" v-for="(tag, index) in row.prompt.split(/\,|\,/)" :key="index" class="mb-1 mr-1">
-              <div :title="tag">{{ tag }}</div>
-            </ElTag>
+            <ElButton link type="primary" size="small" @click="handleView(row)">查看</ElButton>
           </template>
         </ElTableColumn>
-        <ElTableColumn label="Language" prop="language" width="180" />
       </ElTable>
       <div class="p-4">
         <ElPagination

+ 15 - 10
src/views/role-management/components/EditForm.vue

@@ -3,7 +3,8 @@ import { ElDialog, ElForm, ElFormItem, ElInput, ElDatePicker, ElButton, ElMessag
 import type { FormInstance, FormRules } from 'element-plus'
 import FaImageUpload from '@/ui/components/FaImageUpload/index.vue'
 import VoiceSelector from '@/components/VoiceSelector.vue'
-import { createRole } from '@/api/modules/anycallService'
+import LLMSelector from '@/components/LLMSelector.vue'
+import { saveRole } from '@/api/modules/anycallService'
 import type { TRole } from '@/api/modules/anycallService'
 // 定义表单数据类型
 type IFormData  = {
@@ -92,12 +93,12 @@ const formRules = ref<FormRules>({
   prompt: [
     { required: true, message: '请输入 prompt', trigger: 'blur' },
   ],
-  description: [
-    { required: true, message: '请输入描述', trigger: 'blur' },
-  ],
-  language: [
-    { required: true, message: '请输入语言', trigger: 'blur' },
-  ],
+  // description: [
+  //   { required: true, message: '请输入描述', trigger: 'blur' },
+  // ],
+  // language: [
+  //   { required: true, message: '请输入语言', trigger: 'blur' },
+  // ],
 })
 
 // 监听可见性变化
@@ -146,7 +147,7 @@ async function handleConfirm() {
     const avatar =  formData.value.avatar?.[0] ?? ''
     const d: TRole = { ...defaultData, ...formData.value, avatar , photo: avatar }
     console.log(d)
-    const { code } = await createRole(d)
+    const { code } = await saveRole(d)
     if (code === 0) {
       ElMessage.success('创建成功')
       emit('refresh')
@@ -207,6 +208,10 @@ const handleRemoveAgent = ()=> {
            <ElInput type="textarea" v-model="formData.description" placeholder="Enter description"  />
         </ElFormItem>
 
+        <!-- <ElFormItem label="use voice" prop="voiceName" label-width="120">
+           <LLMSelector v-model="formData.voiceId" />
+        </ElFormItem> -->
+
         <ElFormItem label="use voice" prop="voiceName" label-width="120">
            <VoiceSelector v-model="formData.voiceId" />
         </ElFormItem>
@@ -219,11 +224,11 @@ const handleRemoveAgent = ()=> {
           />
         </ElFormItem>
 
-        <ElFormItem label="大模型" prop="agentId" label-width="120">
+        <!-- <ElFormItem label="大模型" prop="agentId" label-width="120">
           <ElSpace wrap>
             <ElButton v-if="mode === 'create'" type="primary" @click="dialogCardSelectorVisible = true">选择大模型</ElButton>
           </ElSpace>
-        </ElFormItem>
+        </ElFormItem> -->
         <ElFormItem label="语言" prop="language">
           <ElSelect v-model="formData.language" placeholder="请选择语言">
             <ElOption label="英语" value="en" />

+ 151 - 0
src/views/role-management/components/EditLLMForm.vue

@@ -0,0 +1,151 @@
+<script setup lang="ts">
+import { ElDialog, ElForm, ElFormItem, ElInput, ElDatePicker, ElButton, ElMessage, ElRadio } from 'element-plus'
+import type { FormInstance, FormRules } from 'element-plus'
+import FaImageUpload from '@/ui/components/FaImageUpload/index.vue'
+import LLMSelector from '@/components/LLMSelector.vue'
+import { updateAgentLLm } from '@/api/modules/anycallService'
+import type { TRole } from '@/api/modules/anycallService'
+// 定义表单数据类型
+type IFormData  = {
+  llmId: string
+}
+
+// 定义组件的属性
+interface Props {
+  agentId: string
+  visible: boolean
+  modelValue?: IFormData | null
+  mode?: 'create' | 'edit'
+}
+
+// 定义组件的事件
+interface Emits {
+  (e: 'update:visible', value: boolean): void
+  (e: 'cancel'): void
+  (e: 'refresh'): void
+}
+
+// 接收属性和事件
+const props = withDefaults(defineProps<Props>(), {
+  visible: false,
+  modelValue: null,
+  mode: 'create'
+})
+
+const emit = defineEmits<Emits>()
+
+// 创建本地响应式变量用于 v-model 绑定
+const dialogVisible = ref(props.visible)
+const dialogCardSelectorVisible = ref(false)
+
+// 监听 props.visible 变化,更新本地变量
+watch(() => props.visible, (newVisible) => {
+  dialogVisible.value = newVisible
+})
+
+// 监听本地变量变化,发出 update 事件
+watch(dialogVisible, (newVisible) => {
+  emit('update:visible', newVisible)
+})
+
+// 表单引用
+const editFormRef = ref<FormInstance>();
+
+// 响应式数据 - 直接定义所有必需字段
+const formData = ref<Partial<IFormData>>({
+  llmId: '',
+});
+
+
+
+// 监听 props.modelValue 变化
+watch(() => props.modelValue, (newModelValue) => {
+  if (newModelValue) {
+    formData.value = {
+      ...formData.value,
+      ...newModelValue
+    };
+  }
+});
+
+// 表单验证规则
+const formRules = ref<FormRules>({
+  llmId: [
+    { required: true, message: '请选择模型', trigger: 'blur' },
+  ],
+})
+
+// 监听可见性变化
+watch(() => props.visible, (newVisible) => {
+  resetForm()
+})
+
+
+// 重置表单
+function resetForm() {
+  console.log('reset')
+  if (editFormRef.value) {
+    editFormRef.value.resetFields()
+  }
+  formData.value = {
+    llmId: '',
+  }
+}
+
+// 处理确认
+async function handleConfirm() {
+  if (!editFormRef.value) return
+
+  try {
+    await editFormRef.value.validate()
+
+    const { code } = await updateAgentLLm({
+      agentId: props.agentId,
+      llmId: formData.value.llmId || ''
+    })
+    if (code === 0) {
+      ElMessage.success('操作成功')
+      emit('refresh')
+    }
+    // 关闭对话框
+    emit('update:visible', false)
+  } catch (error) {
+    // 验证失败,不做处理
+  }
+}
+
+
+function handleCancel() {
+  emit('cancel')
+  emit('update:visible', false)
+}
+
+
+function handleClose() {
+  emit('update:visible', false)
+}
+
+</script>
+<template>
+  <div>
+
+    <ElDialog title="编辑大模型" v-model="dialogVisible" align-center @close="handleClose"
+      width="400" :z-index="2000">
+      <ElForm ref="editFormRef" :model="formData" :rules="formRules" label-width="120px" class="mt-4 space-y-4 w-full">
+
+
+
+        <ElFormItem label="大模型" prop="voiceName" label-width="120">
+           <LLMSelector v-model="formData.llmId" />
+        </ElFormItem>
+
+      </ElForm>
+      <template #footer>
+        <div class="flex justify-end space-x-2">
+          <ElButton @click="handleCancel">取消</ElButton>
+          <ElButton type="primary" @click="handleConfirm">确定</ElButton>
+        </div>
+      </template>
+    </ElDialog>
+  </div>
+</template>

+ 13 - 0
src/views/role-management/index.vue

@@ -9,6 +9,7 @@ import { ElButton, ElDialog, ElEmpty, ElInput, ElMessage, ElOption, ElPagination
 import type { UploadFile, UploadFiles } from 'element-plus'
 import FileUploader from '@/components/Uploader/FileUploader.vue'
 import EditForm from './components/EditForm.vue'
+import EditLLMForm from './components/EditLLMForm.vue'
 import SearchForm from './components/SearchForm.vue'
 
 import type { TAgent } from '@/types/role'
@@ -24,6 +25,9 @@ const editFormVisible = ref(false)
 const editMode = ref<'create' | 'edit'>('create')
 const currentData = ref<any>(null)
 
+const editLLMFormVisible = ref(false)
+const currentAgentId = ref<string>()
+
 const importedResultDialogVisible = ref(false)
 const importedFile = ref<UploadFile | null>(null)
 const importedResult = ref('')
@@ -104,6 +108,11 @@ const handleEdit = (data: TAgent) => {
   currentData.value = {...data, avatar: [data.photo]}
   editFormVisible.value = true
 }
+const handleEditLLM = (data: TAgent) => {
+  console.log(data)
+  currentAgentId.value = data.agentId
+  editLLMFormVisible.value = true
+}
 
 const handleSearch = () => {
   pagination.value.page = 1
@@ -140,6 +149,7 @@ onMounted(async () => {
         </ElSpace>
       </div>
       <ElTable
+        v-loading="loading"
         ref="tableRef" :data="dataList" stripe highlight-current-row border height="100%"
       >
         <ElTableColumn label="id" prop="id" min-width="240" />
@@ -167,6 +177,7 @@ onMounted(async () => {
         <ElTableColumn fixed="right" label="操作" min-width="200">
           <template #default="{row}">
             <ElButton link type="primary" size="small" @click="handleEdit(row)">编辑</ElButton>
+            <ElButton link type="primary" size="small" @click="handleEditLLM(row)">绑定大模型</ElButton>
             <!-- <ElPopconfirm title="确定推荐吗?" @confirm="handleRecommend(row.id, row.topFlag)">
               <template #reference>
                 <ElButton link type="primary" size="small">
@@ -192,6 +203,8 @@ onMounted(async () => {
     <EditForm v-model:visible="editFormVisible" :model-value="currentData" :mode="editMode" @refresh="handleRefresh"
       @cancel="handleFormCancel" />
 
+    <EditLLMForm v-model:visible="editLLMFormVisible" :agentId="currentAgentId" @refresh="handleRefresh"></EditLLMForm>
+
     <ElDialog title="导入结果" v-model="importedResultDialogVisible" align-center
       width="800" :z-index="2000" :close-on-click-modal="false">
         <div class="max-h-200 overflow-y-auto leading-6">