mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-28 05:42:51 +00:00
This commit is contained in:
parent
aa901c7fc7
commit
47368a5f99
|
|
@ -1,7 +1,11 @@
|
|||
import { Result } from '@/request/Result'
|
||||
import type { Ref } from 'vue'
|
||||
import { get, post, del } from '@/request/index'
|
||||
import type { WorkspaceItem, CreateWorkspaceMemberParamsItem, WorkspaceMemberItem } from '@/api/type/workspace'
|
||||
import type {
|
||||
WorkspaceItem,
|
||||
CreateWorkspaceMemberParamsItem,
|
||||
WorkspaceMemberItem,
|
||||
} from '@/api/type/workspace'
|
||||
import type { pageRequest, PageList } from '@/api/type/common'
|
||||
|
||||
const prefix = '/workspace'
|
||||
|
|
@ -9,25 +13,30 @@ const prefix = '/workspace'
|
|||
/**
|
||||
* 获取首页的工作空间下拉列表
|
||||
*/
|
||||
const getWorkspaceListByUser: (loading?: Ref<boolean>) => Promise<Result<WorkspaceItem[]>> = (loading) => {
|
||||
const getWorkspaceListByUser: (loading?: Ref<boolean>) => Promise<Result<WorkspaceItem[]>> = (
|
||||
loading,
|
||||
) => {
|
||||
return get('/workspace/by_user', undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取添加成员时的工作空间下拉列表
|
||||
*/
|
||||
const getWorkspaceList: (loading?: Ref<boolean>) => Promise<Result<Record<string, any>[]>> = (loading) => {
|
||||
const getWorkspaceList: (loading?: Ref<boolean>) => Promise<Result<Record<string, any>[]>> = (
|
||||
loading,
|
||||
) => {
|
||||
return get('/workspace/current_user', undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取工作空间列表
|
||||
*/
|
||||
const getSystemWorkspaceList: (loading?: Ref<boolean>) => Promise<Result<WorkspaceItem[]>> = (loading) => {
|
||||
const getSystemWorkspaceList: (loading?: Ref<boolean>) => Promise<Result<WorkspaceItem[]>> = (
|
||||
loading,
|
||||
) => {
|
||||
return get(`${prefix}`, undefined, loading)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取工作空间成员列表
|
||||
*/
|
||||
|
|
@ -47,14 +56,11 @@ const getWorkspaceMemberList: (
|
|||
/**
|
||||
* 获取工作空间全部成员列表
|
||||
*/
|
||||
const getAllMemberList: (
|
||||
workspace_id: string,
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any[]>> = (workspace_id, loading) => {
|
||||
return get(
|
||||
`${prefix}/${workspace_id}/user_list`,
|
||||
loading,
|
||||
)
|
||||
const getAllMemberList: (workspace_id: string, loading?: Ref<boolean>) => Promise<Result<any[]>> = (
|
||||
workspace_id,
|
||||
loading,
|
||||
) => {
|
||||
return get(`${prefix}/${workspace_id}/user_list`, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,18 +77,20 @@ const CreateWorkspaceMember: (
|
|||
/**
|
||||
* 删除工作空间成员
|
||||
*/
|
||||
const deleteWorkspaceMember: (workspace_id: string, user_relation_id: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
workspace_id,
|
||||
user_relation_id,
|
||||
loading,
|
||||
) => {
|
||||
const deleteWorkspaceMember: (
|
||||
workspace_id: string,
|
||||
user_relation_id: string,
|
||||
loading?: Ref<boolean>,
|
||||
) => Promise<Result<any>> = (workspace_id, user_relation_id, loading) => {
|
||||
return post(`${prefix}/${workspace_id}/remove_member/${user_relation_id}`, undefined, {}, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取添加成员时的角色下拉列表
|
||||
*/
|
||||
const getWorkspaceRoleList: (loading?: Ref<boolean>) => Promise<Result<Record<string, any>[]>> = (loading) => {
|
||||
const getWorkspaceRoleList: (loading?: Ref<boolean>) => Promise<Result<Record<string, any>[]>> = (
|
||||
loading,
|
||||
) => {
|
||||
return get('/role_list/current_user', undefined, loading)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ import { computed, ref } from 'vue'
|
|||
import ParagraphSourceDialog from './ParagraphSourceDialog.vue'
|
||||
import ExecutionDetailDialog from './ExecutionDetailDialog.vue'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
import { getImgUrl, getNormalizedUrl } from '@/utils/utils'
|
||||
import { getImgUrl, getNormalizedUrl } from '@/utils/common'
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, watch, onBeforeUnmount } from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { arraySort } from '@/utils/utils'
|
||||
import { arraySort } from '@/utils/array'
|
||||
import ParagraphSourceContent from './component/ParagraphSourceContent.vue'
|
||||
const emit = defineEmits(['refresh'])
|
||||
|
||||
|
|
|
|||
|
|
@ -700,10 +700,10 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import ParagraphCard from '@/components/ai-chat/component/ParagraphCard.vue'
|
||||
import { arraySort } from '@/utils/utils'
|
||||
import { arraySort } from '@/utils/array'
|
||||
import { iconComponent } from '@/workflow/icons/utils'
|
||||
import { WorkflowType } from '@/enums/application'
|
||||
import { getImgUrl } from '@/utils/utils'
|
||||
import { getImgUrl } from '@/utils/common'
|
||||
import DynamicsForm from '@/components/dynamics-form/index.vue'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
</CardBox>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getImgUrl, getNormalizedUrl } from '@/utils/utils'
|
||||
import { getImgUrl, getNormalizedUrl } from '@/utils/common'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ import UserForm from '@/components/ai-chat/component/user-form/index.vue'
|
|||
import { MsgAlert } from '@/utils/message'
|
||||
import { type chatType } from '@/api/type/application'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { getImgUrl } from '@/utils/utils'
|
||||
import { getImgUrl } from '@/utils/common'
|
||||
import bus from '@/bus'
|
||||
import 'recorder-core/src/engine/mp3'
|
||||
import 'recorder-core/src/engine/mp3-engine'
|
||||
|
|
|
|||
|
|
@ -96,7 +96,8 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { type chatType } from '@/api/type/application'
|
||||
import { getImgUrl, getAttrsArray, downloadByURL } from '@/utils/utils'
|
||||
import { getImgUrl, downloadByURL } from '@/utils/common'
|
||||
import { getAttrsArray } from '@/utils/array'
|
||||
import { onMounted, computed } from 'vue'
|
||||
import useStore from '@/stores'
|
||||
const props = defineProps<{
|
||||
|
|
@ -116,7 +117,7 @@ const document_list = computed(() => {
|
|||
return props.chatRecord.upload_meta?.document_list || []
|
||||
}
|
||||
const startNode = props.chatRecord.execution_details?.find(
|
||||
(detail) => detail.type === 'start-node'
|
||||
(detail) => detail.type === 'start-node',
|
||||
)
|
||||
return startNode?.document_list || []
|
||||
})
|
||||
|
|
@ -125,7 +126,7 @@ const image_list = computed(() => {
|
|||
return props.chatRecord.upload_meta?.image_list || []
|
||||
}
|
||||
const startNode = props.chatRecord.execution_details?.find(
|
||||
(detail) => detail.type === 'start-node'
|
||||
(detail) => detail.type === 'start-node',
|
||||
)
|
||||
return startNode?.image_list || []
|
||||
})
|
||||
|
|
@ -134,7 +135,7 @@ const audio_list = computed(() => {
|
|||
return props.chatRecord.upload_meta?.audio_list || []
|
||||
}
|
||||
const startNode = props.chatRecord.execution_details?.find(
|
||||
(detail) => detail.type === 'start-node'
|
||||
(detail) => detail.type === 'start-node',
|
||||
)
|
||||
return startNode?.audio_list || []
|
||||
})
|
||||
|
|
@ -143,7 +144,7 @@ const other_list = computed(() => {
|
|||
return props.chatRecord.upload_meta?.other_list || []
|
||||
}
|
||||
const startNode = props.chatRecord.execution_details?.find(
|
||||
(detail) => detail.type === 'start-node'
|
||||
(detail) => detail.type === 'start-node',
|
||||
)
|
||||
return startNode?.other_list || []
|
||||
})
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ import applicationApi from '@/api/application/application'
|
|||
import chatAPI from '@/api/chat/chat'
|
||||
import chatLogApi from '@/api/application/chat-log'
|
||||
import { ChatManagement, type chatType } from '@/api/type/application'
|
||||
import { randomId } from '@/utils/utils'
|
||||
import { randomId } from '@/utils/common'
|
||||
import useStore from '@/stores'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
import { debounce } from 'lodash'
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, nextTick, watch, onBeforeUnmount } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { numberFormat } from '@/utils/utils'
|
||||
import { numberFormat } from '@/utils/common'
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref, onMounted } from 'vue'
|
||||
import type { Provider } from '@/api/type/model'
|
||||
import { relatedObject } from '@/utils/common'
|
||||
import { relatedObject } from '@/utils/array'
|
||||
import CreateModelDialog from '@/views/model/component/CreateModelDialog.vue'
|
||||
import SelectProviderDialog from '@/views/model/component/SelectProviderDialog.vue'
|
||||
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ import { useRoute } from 'vue-router'
|
|||
const route = useRoute()
|
||||
const {
|
||||
params: { folderId }, // id为knowledgeID
|
||||
query: { type },
|
||||
} = route as any
|
||||
|
||||
const isShared = computed(() => {
|
||||
return folderId === 'shared'
|
||||
return folderId === 'shared' || type === 'systemShare'
|
||||
})
|
||||
const { theme } = useStore()
|
||||
const isDefaultTheme = computed(() => {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,29 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import UserHeader from '@/layout/layout-header/UserHeader.vue'
|
||||
import SystemHeader from '@/layout/layout-header/SystemHeader.vue'
|
||||
import AppMain from '@/layout/app-main/index.vue'
|
||||
import useStore from '@/stores'
|
||||
import { useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const { theme } = useStore()
|
||||
const isDefaultTheme = computed(() => {
|
||||
return theme.isDefaultTheme()
|
||||
})
|
||||
const {
|
||||
params: { folderId }, // id为knowledgeID
|
||||
query: { type },
|
||||
} = route as any
|
||||
const isShared = computed(() => {
|
||||
return folderId === 'shared' || type === 'systemShare'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-layout">
|
||||
<div class="app-header" :class="!isDefaultTheme ? 'custom-header' : ''">
|
||||
<UserHeader />
|
||||
<SystemHeader v-if="isShared"></SystemHeader>
|
||||
<UserHeader v-else />
|
||||
</div>
|
||||
<div class="app-main">
|
||||
<AppMain />
|
||||
|
|
|
|||
|
|
@ -36,22 +36,6 @@ const useKnowledgeStore = defineStore('knowledge', {
|
|||
setKnowledgeList(list: any[]) {
|
||||
this.knowledgeList = list
|
||||
},
|
||||
|
||||
async asyncGetFolderKnowledge(folder_id?: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const params = {
|
||||
folder_id: folder_id || localStorage.getItem('workspace_id'),
|
||||
}
|
||||
knowledgeApi
|
||||
.getKnowledgeList(params, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,76 @@
|
|||
// 树形结构转平
|
||||
/**
|
||||
* 拆分数组 每n个拆分为一个数组
|
||||
* @param sourceDataList 资源数据
|
||||
* @param splitNum 每多少个拆分为一个数组
|
||||
* @returns 拆分后数组
|
||||
*/
|
||||
export function splitArray<T>(sourceDataList: Array<T>, splitNum: number) {
|
||||
const count =
|
||||
sourceDataList.length % splitNum == 0
|
||||
? sourceDataList.length / splitNum
|
||||
: sourceDataList.length / splitNum + 1
|
||||
const arrayList: Array<Array<T>> = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
let index = i * splitNum
|
||||
const list: Array<T> = []
|
||||
let j = 0
|
||||
while (j < splitNum && index < sourceDataList.length) {
|
||||
list.push(sourceDataList[index++])
|
||||
j++
|
||||
}
|
||||
arrayList.push(list)
|
||||
}
|
||||
return arrayList
|
||||
}
|
||||
/*
|
||||
树形结构转平
|
||||
*/
|
||||
export function TreeToFlatten(treeData: any[]) {
|
||||
return treeData.reduce((acc, node) => {
|
||||
const { children, ...rest } = node
|
||||
return [...acc, rest, ...(children ? TreeToFlatten(children) : [])]
|
||||
}, [])
|
||||
}
|
||||
|
||||
/*
|
||||
从指定数组中过滤出对应的对象
|
||||
*/
|
||||
export function relatedObject(list: any, val: any, attr: string) {
|
||||
const filterData: any = list.find((item: any) => item[attr] === val)
|
||||
return filterData || null
|
||||
}
|
||||
|
||||
// 排序
|
||||
export function arraySort(list: Array<any>, property: any, desc?: boolean) {
|
||||
return list.sort((a: any, b: any) => {
|
||||
return desc ? b[property] - a[property] : a[property] - b[property]
|
||||
})
|
||||
}
|
||||
|
||||
// 判断对象里所有属性全部为空
|
||||
export function isAllPropertiesEmpty(obj: object) {
|
||||
return Object.values(obj).every(
|
||||
(value) =>
|
||||
value === null || typeof value === 'undefined' || (typeof value === 'string' && !value),
|
||||
)
|
||||
}
|
||||
|
||||
// 数组对象中某一属性值的集合
|
||||
export function getAttrsArray(array: Array<any>, attr: string) {
|
||||
return array.map((item) => {
|
||||
return item[attr]
|
||||
})
|
||||
}
|
||||
|
||||
// 求和
|
||||
export function getSum(array: Array<any>) {
|
||||
return array.reduce((total, item) => total + item, 0)
|
||||
}
|
||||
|
||||
// 对象数组去重
|
||||
export function uniqueArray(array: Array<any>, key: string) {
|
||||
const map = new Map()
|
||||
return array.filter((item) => {
|
||||
return !map.has(item[key]) && map.set(item[key], 1)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,42 +1,3 @@
|
|||
/*
|
||||
从指定数组中过滤出对应的对象
|
||||
*/
|
||||
export function relatedObject(list: any, val: any, attr: string) {
|
||||
const filterData: any = list.filter((item: any) => item[attr] === val)?.[0]
|
||||
return filterData || null
|
||||
}
|
||||
|
||||
// 排序
|
||||
export function arraySort(list: Array<any>, property: any, desc?: boolean) {
|
||||
return list.sort((a: any, b: any) => {
|
||||
return desc ? b[property] - a[property] : a[property] - b[property]
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 拆分数组 每n个拆分为一个数组
|
||||
* @param sourceDataList 资源数据
|
||||
* @param splitNum 每多少个拆分为一个数组
|
||||
* @returns 拆分后数组
|
||||
*/
|
||||
export function splitArray<T>(sourceDataList: Array<T>, splitNum: number) {
|
||||
const count =
|
||||
sourceDataList.length % splitNum == 0
|
||||
? sourceDataList.length / splitNum
|
||||
: sourceDataList.length / splitNum + 1
|
||||
const arrayList: Array<Array<T>> = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
let index = i * splitNum
|
||||
const list: Array<T> = []
|
||||
let j = 0
|
||||
while (j < splitNum && index < sourceDataList.length) {
|
||||
list.push(sourceDataList[index++])
|
||||
j++
|
||||
}
|
||||
arrayList.push(list)
|
||||
}
|
||||
return arrayList
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字处理
|
||||
*/
|
||||
|
|
@ -71,6 +32,117 @@ export function isFunction(fn: any) {
|
|||
return typeof fn === 'function'
|
||||
}
|
||||
|
||||
/*
|
||||
随机id
|
||||
*/
|
||||
export const randomId = function () {
|
||||
return Math.floor(Math.random() * 10000) + ''
|
||||
}
|
||||
|
||||
/*
|
||||
获取文件后缀
|
||||
*/
|
||||
export function fileType(name: string) {
|
||||
const suffix = name.split('.')
|
||||
return suffix[suffix.length - 1]
|
||||
}
|
||||
|
||||
/*
|
||||
获得文件对应图片
|
||||
*/
|
||||
const typeList: any = {
|
||||
txt: ['txt', 'pdf', 'docx', 'md', 'html', 'zip', 'xlsx', 'xls', 'csv'],
|
||||
table: ['xlsx', 'xls', 'csv'],
|
||||
QA: ['xlsx', 'csv', 'xls', 'zip'],
|
||||
}
|
||||
|
||||
export function getImgUrl(name: string) {
|
||||
const list = Object.values(typeList).flat()
|
||||
|
||||
const type = list.includes(fileType(name).toLowerCase())
|
||||
? fileType(name).toLowerCase()
|
||||
: 'unknown'
|
||||
return new URL(`../assets/fileType/${type}-icon.svg`, import.meta.url).href
|
||||
}
|
||||
// 是否是白名单后缀
|
||||
export function isRightType(name: string, type: string) {
|
||||
return typeList[type].includes(fileType(name).toLowerCase())
|
||||
}
|
||||
|
||||
// 下载
|
||||
export function downloadByURL(url: string, name: string) {
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href', url)
|
||||
a.setAttribute('target', '_blank')
|
||||
a.setAttribute('download', name)
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
}
|
||||
|
||||
// 截取文件名
|
||||
export function cutFilename(filename: string, num: number) {
|
||||
const lastIndex = filename.lastIndexOf('.')
|
||||
const suffix = lastIndex === -1 ? '' : filename.substring(lastIndex + 1)
|
||||
return filename.substring(0, num - suffix.length - 1) + '.' + suffix
|
||||
}
|
||||
|
||||
interface LoadScriptOptions {
|
||||
jsId?: string // 自定义脚本 ID
|
||||
forceReload?: boolean // 是否强制重新加载(默认 false)
|
||||
}
|
||||
|
||||
export const loadScript = (url: string, options: LoadScriptOptions = {}): Promise<void> => {
|
||||
const { jsId, forceReload = false } = options
|
||||
const scriptId = jsId || `script-${btoa(url).slice(0, 12)}` // 生成唯一 ID
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// 检查是否已存在且无需强制加载
|
||||
const existingScript = document.getElementById(scriptId) as HTMLScriptElement | null
|
||||
if (existingScript && !forceReload) {
|
||||
if (existingScript.src === url) {
|
||||
existingScript.onload = () => resolve() // 复用现有脚本
|
||||
return
|
||||
}
|
||||
// URL 不同则移除旧脚本
|
||||
existingScript.parentElement?.removeChild(existingScript)
|
||||
}
|
||||
|
||||
// 创建新脚本
|
||||
const script = document.createElement('script')
|
||||
script.id = scriptId
|
||||
script.src = url
|
||||
script.async = true // 明确启用异步加载
|
||||
|
||||
// 成功回调
|
||||
script.onload = () => {
|
||||
resolve()
|
||||
}
|
||||
|
||||
// 错误处理(兼容性增强)
|
||||
script.onerror = () => {
|
||||
reject(new Error(`Failed to load script: ${url}`))
|
||||
cleanupScript(script)
|
||||
}
|
||||
|
||||
// 插入到 <head> 确保加载顺序
|
||||
document.head.appendChild(script)
|
||||
})
|
||||
}
|
||||
|
||||
// 清理脚本(可选)
|
||||
const cleanupScript = (script: HTMLScriptElement) => {
|
||||
script.onload = null
|
||||
script.onerror = null
|
||||
script.parentElement?.removeChild(script)
|
||||
}
|
||||
|
||||
export function getNormalizedUrl(url: string) {
|
||||
if (url && !url.endsWith('/') && !/\.[^/]+$/.test(url)) {
|
||||
return url + '/'
|
||||
}
|
||||
return url
|
||||
}
|
||||
export const resetUrl = (url: string, defaultUrl?: string) => {
|
||||
if (url && url.startsWith('./')) {
|
||||
return `${window.MaxKB.prefix}/${url.substring(2)}`
|
||||
|
|
|
|||
|
|
@ -1,167 +0,0 @@
|
|||
import { MsgError } from '@/utils/message'
|
||||
|
||||
export function toThousands(num: any) {
|
||||
return num?.toString().replace(/\d+/, function (n: any) {
|
||||
return n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
|
||||
})
|
||||
}
|
||||
export function numberFormat(num: number) {
|
||||
return num < 1000 ? toThousands(num) : toThousands((num / 1000).toFixed(1)) + 'k'
|
||||
}
|
||||
|
||||
export function filesize(size: number) {
|
||||
if (!size) return ''
|
||||
/* byte */
|
||||
const num = 1024.0
|
||||
|
||||
if (size < num) return size + 'B'
|
||||
if (size < Math.pow(num, 2)) return (size / num).toFixed(2) + 'K' //kb
|
||||
if (size < Math.pow(num, 3)) return (size / Math.pow(num, 2)).toFixed(2) + 'M' //M
|
||||
if (size < Math.pow(num, 4)) return (size / Math.pow(num, 3)).toFixed(2) + 'G' //G
|
||||
return (size / Math.pow(num, 4)).toFixed(2) + 'T' //T
|
||||
}
|
||||
|
||||
/*
|
||||
随机id
|
||||
*/
|
||||
export const randomId = function () {
|
||||
return Math.floor(Math.random() * 10000) + ''
|
||||
}
|
||||
|
||||
/*
|
||||
获取文件后缀
|
||||
*/
|
||||
export function fileType(name: string) {
|
||||
const suffix = name.split('.')
|
||||
return suffix[suffix.length - 1]
|
||||
}
|
||||
|
||||
/*
|
||||
获得文件对应图片
|
||||
*/
|
||||
const typeList: any = {
|
||||
txt: ['txt', 'pdf', 'docx', 'md', 'html', 'zip', 'xlsx', 'xls', 'csv'],
|
||||
table: ['xlsx', 'xls', 'csv'],
|
||||
QA: ['xlsx', 'csv', 'xls', 'zip']
|
||||
}
|
||||
|
||||
export function getImgUrl(name: string) {
|
||||
const list = Object.values(typeList).flat()
|
||||
|
||||
const type = list.includes(fileType(name).toLowerCase()) ? fileType(name).toLowerCase() : 'unknown'
|
||||
return new URL(`../assets/fileType/${type}-icon.svg`, import.meta.url).href
|
||||
}
|
||||
// 是否是白名单后缀
|
||||
export function isRightType(name: string, type: string) {
|
||||
return typeList[type].includes(fileType(name).toLowerCase())
|
||||
}
|
||||
|
||||
/*
|
||||
从指定数组中过滤出对应的对象
|
||||
*/
|
||||
export function relatedObject(list: any, val: any, attr: string) {
|
||||
const filterData: any = list.filter((item: any) => item[attr] === val)?.[0]
|
||||
return filterData || null
|
||||
}
|
||||
|
||||
// 排序
|
||||
export function arraySort(list: Array<any>, property: any, desc?: boolean) {
|
||||
return list.sort((a: any, b: any) => {
|
||||
return desc ? b[property] - a[property] : a[property] - b[property]
|
||||
})
|
||||
}
|
||||
|
||||
// 判断对象里所有属性全部为空
|
||||
export function isAllPropertiesEmpty(obj: object) {
|
||||
return Object.values(obj).every(
|
||||
(value) =>
|
||||
value === null || typeof value === 'undefined' || (typeof value === 'string' && !value)
|
||||
)
|
||||
}
|
||||
|
||||
// 数组对象中某一属性值的集合
|
||||
export function getAttrsArray(array: Array<any>, attr: string) {
|
||||
return array.map((item) => {
|
||||
return item[attr]
|
||||
})
|
||||
}
|
||||
|
||||
// 求和
|
||||
export function getSum(array: Array<any>) {
|
||||
return array.reduce((total, item) => total + item, 0)
|
||||
}
|
||||
|
||||
// 下载
|
||||
export function downloadByURL(url: string, name: string) {
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href', url)
|
||||
a.setAttribute('target', '_blank')
|
||||
a.setAttribute('download', name)
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
}
|
||||
|
||||
// 截取文件名
|
||||
export function cutFilename(filename: string, num: number) {
|
||||
const lastIndex = filename.lastIndexOf('.')
|
||||
const suffix = lastIndex === -1 ? '' : filename.substring(lastIndex + 1)
|
||||
return filename.substring(0, num - suffix.length - 1) + '.' + suffix
|
||||
}
|
||||
|
||||
export function getNormalizedUrl(url: string) {
|
||||
if (url && !url.endsWith('/') && !/\.[^/]+$/.test(url)) {
|
||||
return url + '/'
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
interface LoadScriptOptions {
|
||||
jsId?: string // 自定义脚本 ID
|
||||
forceReload?: boolean // 是否强制重新加载(默认 false)
|
||||
}
|
||||
|
||||
export const loadScript = (url: string, options: LoadScriptOptions = {}): Promise<void> => {
|
||||
const { jsId, forceReload = false } = options
|
||||
const scriptId = jsId || `script-${btoa(url).slice(0, 12)}` // 生成唯一 ID
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// 检查是否已存在且无需强制加载
|
||||
const existingScript = document.getElementById(scriptId) as HTMLScriptElement | null
|
||||
if (existingScript && !forceReload) {
|
||||
if (existingScript.src === url) {
|
||||
existingScript.onload = () => resolve() // 复用现有脚本
|
||||
return
|
||||
}
|
||||
// URL 不同则移除旧脚本
|
||||
existingScript.parentElement?.removeChild(existingScript)
|
||||
}
|
||||
|
||||
// 创建新脚本
|
||||
const script = document.createElement('script')
|
||||
script.id = scriptId
|
||||
script.src = url
|
||||
script.async = true // 明确启用异步加载
|
||||
|
||||
// 成功回调
|
||||
script.onload = () => {
|
||||
resolve()
|
||||
}
|
||||
|
||||
// 错误处理(兼容性增强)
|
||||
script.onerror = () => {
|
||||
reject(new Error(`Failed to load script: ${url}`))
|
||||
cleanupScript(script)
|
||||
}
|
||||
|
||||
// 插入到 <head> 确保加载顺序
|
||||
document.head.appendChild(script)
|
||||
})
|
||||
}
|
||||
|
||||
// 清理脚本(可选)
|
||||
const cleanupScript = (script: HTMLScriptElement) => {
|
||||
script.onload = null
|
||||
script.onerror = null
|
||||
script.parentElement?.removeChild(script)
|
||||
}
|
||||
|
|
@ -56,13 +56,14 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import AppCharts from '@/components/app-charts/index.vue'
|
||||
import { getAttrsArray, getSum, numberFormat } from '@/utils/utils'
|
||||
import { getAttrsArray, getSum } from '@/utils/array'
|
||||
import { numberFormat } from '@/utils/common'
|
||||
import { t } from '@/locales'
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
const statisticsType = computed(() => [
|
||||
{
|
||||
|
|
@ -74,7 +75,7 @@ const statisticsType = computed(() => [
|
|||
color: '#3370FF',
|
||||
sum: [
|
||||
getSum(getAttrsArray(props.data, 'customer_num') || 0),
|
||||
getSum(getAttrsArray(props.data, 'customer_added_count') || 0)
|
||||
getSum(getAttrsArray(props.data, 'customer_added_count') || 0),
|
||||
],
|
||||
option: {
|
||||
title: t('views.applicationOverview.monitor.charts.customerTotal'),
|
||||
|
|
@ -84,20 +85,20 @@ const statisticsType = computed(() => [
|
|||
name: t('views.applicationOverview.monitor.charts.customerTotal'),
|
||||
type: 'line',
|
||||
area: true,
|
||||
data: getAttrsArray(props.data, 'customer_num')
|
||||
data: getAttrsArray(props.data, 'customer_num'),
|
||||
},
|
||||
{
|
||||
name: t('views.applicationOverview.monitor.charts.customerNew'),
|
||||
name: t('views.applicationOverview.monitor.charts.customerNew'),
|
||||
type: 'line',
|
||||
area: true,
|
||||
data: getAttrsArray(props.data, 'customer_added_count')
|
||||
}
|
||||
]
|
||||
}
|
||||
data: getAttrsArray(props.data, 'customer_added_count'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'chatRecordCharts',
|
||||
name: t('views.applicationOverview.monitor.charts.queryCount'),
|
||||
name: t('views.applicationOverview.monitor.charts.queryCount'),
|
||||
icon: 'app-question',
|
||||
background: '#FFF3E5',
|
||||
color: '#FF8800',
|
||||
|
|
@ -108,10 +109,10 @@ const statisticsType = computed(() => [
|
|||
yData: [
|
||||
{
|
||||
type: 'line',
|
||||
data: getAttrsArray(props.data, 'chat_record_count')
|
||||
}
|
||||
]
|
||||
}
|
||||
data: getAttrsArray(props.data, 'chat_record_count'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'tokensCharts',
|
||||
|
|
@ -126,10 +127,10 @@ const statisticsType = computed(() => [
|
|||
yData: [
|
||||
{
|
||||
type: 'line',
|
||||
data: getAttrsArray(props.data, 'tokens_num')
|
||||
}
|
||||
]
|
||||
}
|
||||
data: getAttrsArray(props.data, 'tokens_num'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'starCharts',
|
||||
|
|
@ -139,7 +140,7 @@ const statisticsType = computed(() => [
|
|||
color: '#F54A45',
|
||||
sum: [
|
||||
getSum(getAttrsArray(props.data, 'star_num') || 0),
|
||||
getSum(getAttrsArray(props.data, 'trample_num') || 0)
|
||||
getSum(getAttrsArray(props.data, 'trample_num') || 0),
|
||||
],
|
||||
option: {
|
||||
title: t('views.applicationOverview.monitor.charts.userSatisfaction'),
|
||||
|
|
@ -148,16 +149,16 @@ const statisticsType = computed(() => [
|
|||
{
|
||||
name: t('views.applicationOverview.monitor.charts.approval'),
|
||||
type: 'line',
|
||||
data: getAttrsArray(props.data, 'star_num')
|
||||
data: getAttrsArray(props.data, 'star_num'),
|
||||
},
|
||||
{
|
||||
name: t('views.applicationOverview.monitor.charts.disapproval'),
|
||||
type: 'line',
|
||||
data: getAttrsArray(props.data, 'trample_num')
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
data: getAttrsArray(props.data, 'trample_num'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
])
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ import AddKnowledgeDialog from './component/AddKnowledgeDialog.vue'
|
|||
import EditAvatarDialog from '@/views/application-overview/component/EditAvatarDialog.vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type { ApplicationFormType } from '@/api/type/application'
|
||||
import { relatedObject } from '@/utils/utils'
|
||||
import { relatedObject } from '@/utils/array'
|
||||
import { MsgSuccess, MsgWarning } from '@/utils/message'
|
||||
import useStore from '@/stores'
|
||||
import { t } from '@/locales'
|
||||
|
|
|
|||
|
|
@ -98,7 +98,11 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import useStore from '@/stores'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
import { uniqueArray } from '@/utils/array'
|
||||
const route = useRoute()
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array<any>,
|
||||
|
|
@ -108,19 +112,29 @@ const props = defineProps({
|
|||
})
|
||||
|
||||
const emit = defineEmits(['addData', 'refresh'])
|
||||
const { folder, user, knowledge } = useStore()
|
||||
const { folder, user } = useStore()
|
||||
const apiType = computed(() => {
|
||||
if (route.path.includes('shared')) {
|
||||
return 'systemShare'
|
||||
} else if (route.path.includes('resource-management')) {
|
||||
return 'systemManage'
|
||||
} else {
|
||||
return 'workspace'
|
||||
}
|
||||
})
|
||||
|
||||
const dialogVisible = ref<boolean>(false)
|
||||
const checkList = ref<Array<string>>([])
|
||||
const currentEmbedding = ref('')
|
||||
const searchValue = ref('')
|
||||
const searchDate = ref<any[]>([])
|
||||
const searchData = ref<Array<any>>([])
|
||||
const knowledgeList = ref<Array<any>>([])
|
||||
const loading = ref(false)
|
||||
|
||||
const filterData = computed(() => {
|
||||
return currentEmbedding.value
|
||||
? searchDate.value.filter((v) => v.embedding_model_id === currentEmbedding.value)
|
||||
: searchDate.value
|
||||
? searchData.value.filter((v) => v.embedding_model_id === currentEmbedding.value)
|
||||
: searchData.value
|
||||
})
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
|
|
@ -128,22 +142,24 @@ watch(dialogVisible, (bool) => {
|
|||
checkList.value = []
|
||||
currentEmbedding.value = ''
|
||||
searchValue.value = ''
|
||||
searchData.value = []
|
||||
knowledgeList.value = []
|
||||
}
|
||||
})
|
||||
|
||||
watch(searchValue, (val) => {
|
||||
if (val) {
|
||||
searchDate.value = props.data.filter((v) => v.name.includes(val))
|
||||
searchData.value = knowledgeList.value.filter((v) => v.name.includes(val))
|
||||
} else {
|
||||
searchDate.value = props.data
|
||||
searchData.value = knowledgeList.value
|
||||
}
|
||||
})
|
||||
|
||||
function changeHandle() {
|
||||
if (checkList.value.length > 0) {
|
||||
currentEmbedding.value = props.data.filter(
|
||||
currentEmbedding.value = knowledgeList.value?.find(
|
||||
(v) => v.id === checkList.value[0],
|
||||
)[0].embedding_model_id
|
||||
)?.embedding_model_id
|
||||
} else if (checkList.value.length === 0) {
|
||||
currentEmbedding.value = ''
|
||||
}
|
||||
|
|
@ -168,7 +184,7 @@ const open = (checked: any) => {
|
|||
const submitHandle = () => {
|
||||
emit(
|
||||
'addData',
|
||||
searchDate.value.filter((item: any) => checkList.value.includes(item.id)),
|
||||
knowledgeList.value.filter((item: any) => checkList.value.includes(item.id)),
|
||||
)
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
|
@ -178,14 +194,14 @@ const refresh = () => {
|
|||
}
|
||||
|
||||
const folderList = ref<any[]>([])
|
||||
const knowledgeList = ref<any[]>([])
|
||||
const currentFolder = ref<any>({})
|
||||
const folderLoading = ref(false)
|
||||
// 文件
|
||||
function folderClickHandle(row: any) {
|
||||
if (row.id === currentFolder.value?.id) {
|
||||
return
|
||||
}
|
||||
currentFolder.value = row
|
||||
knowledgeList.value = []
|
||||
if (currentFolder.value.id === 'share') return
|
||||
getList()
|
||||
}
|
||||
|
||||
|
|
@ -200,9 +216,16 @@ function getFolder() {
|
|||
|
||||
function getList() {
|
||||
const folder_id = currentFolder.value?.id || user.getWorkspaceId()
|
||||
knowledge.asyncGetFolderKnowledge(folder_id, loading).then((res: any) => {
|
||||
searchDate.value = res.data
|
||||
loadSharedApi({
|
||||
type: 'knowledge',
|
||||
isShared: folder_id === 'share',
|
||||
systemType: apiType.value,
|
||||
})
|
||||
.getKnowledgeList({ folder_id }, loading)
|
||||
.then((res: any) => {
|
||||
knowledgeList.value = uniqueArray([...knowledgeList.value, ...res.data], 'id')
|
||||
searchData.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
|
|
|
|||
|
|
@ -222,7 +222,8 @@
|
|||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click.stop="getAccessToken(item.id)"
|
||||
<el-dropdown-item
|
||||
@click.stop="getAccessToken(item.id)"
|
||||
v-if="permissionPrecise.overview_access(item.id)"
|
||||
>
|
||||
<AppIcon iconName="app-create-chat"></AppIcon>
|
||||
|
|
@ -339,7 +340,7 @@ const MoveToDialogRef = ref()
|
|||
function openMoveToDialog(data: any) {
|
||||
const obj = {
|
||||
id: data.id,
|
||||
folder_id: data.folder
|
||||
folder_id: data.folder,
|
||||
}
|
||||
MoveToDialogRef.value?.open(obj)
|
||||
}
|
||||
|
|
@ -512,6 +513,9 @@ function clickFolder(item: any) {
|
|||
getList()
|
||||
}
|
||||
function folderClickHandle(row: any) {
|
||||
if (row.id === folder.currentFolder?.id) {
|
||||
return
|
||||
}
|
||||
folder.setCurrentFolder(row)
|
||||
applicationList.value = []
|
||||
getList()
|
||||
|
|
|
|||
|
|
@ -78,8 +78,7 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { numberFormat } from '@/utils/utils'
|
||||
import { filesize, getImgUrl } from '@/utils/utils'
|
||||
import { getImgUrl, filesize, numberFormat } from '@/utils/common'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@
|
|||
import { ref, computed, onMounted, reactive, watch } from 'vue'
|
||||
import ParagraphPreview from '@/views/knowledge/component/ParagraphPreview.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { cutFilename } from '@/utils/utils'
|
||||
import { cutFilename } from '@/utils/common'
|
||||
import useStore from '@/stores'
|
||||
import type { KeyValue } from '@/api/type/common'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@
|
|||
import { ref, reactive, onUnmounted, onMounted, computed, watch, nextTick } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import type { UploadFiles } from 'element-plus'
|
||||
import { filesize, getImgUrl, isRightType } from '@/utils/utils'
|
||||
import { filesize, getImgUrl, isRightType } from '@/utils/common'
|
||||
import { MsgError } from '@/utils/message'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
import useStore from '@/stores'
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ import { nextTick, ref, onMounted, computed } from 'vue'
|
|||
import { useRoute } from 'vue-router'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import ParagraphDialog from '@/views/paragraph/component/ParagraphDialog.vue'
|
||||
import { arraySort } from '@/utils/common'
|
||||
import { arraySort } from '@/utils/array'
|
||||
import emptyImg from '@/assets/hit-test-empty.png'
|
||||
import { t } from '@/locales'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
|
|
|
|||
|
|
@ -73,7 +73,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="openCreateDialog(CreateLarkKnowledgeDialog)">
|
||||
<el-dropdown-item
|
||||
@click="openCreateDialog(CreateLarkKnowledgeDialog)"
|
||||
v-if="user.isPE() || user.isEE()"
|
||||
>
|
||||
<div class="flex">
|
||||
<el-avatar
|
||||
class="avatar-purple mt-4"
|
||||
|
|
@ -388,7 +391,7 @@ function openMoveToDialog(data: any) {
|
|||
// 仅2个参数就行
|
||||
const obj = {
|
||||
id: data.id,
|
||||
folder_id: data.folder
|
||||
folder_id: data.folder,
|
||||
}
|
||||
MoveToDialogRef.value?.open(obj)
|
||||
}
|
||||
|
|
@ -527,7 +530,7 @@ onMounted(() => {
|
|||
})
|
||||
getList()
|
||||
}
|
||||
loadSharedApi({type: 'workspace', isShared: isShared.value, systemType: apiType.value })
|
||||
loadSharedApi({ type: 'workspace', isShared: isShared.value, systemType: apiType.value })
|
||||
.getAllMemberList(user.getWorkspaceId(), loading)
|
||||
.then((res: any) => {
|
||||
user_options.value = res.data
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { getImgUrl } from '@/utils/utils'
|
||||
import { getImgUrl } from '@/utils/common'
|
||||
import ParagraphList from './ParagraphList.vue'
|
||||
|
||||
defineProps({
|
||||
|
|
|
|||
|
|
@ -70,10 +70,7 @@ const submitHandle = async () => {
|
|||
.then((res: any) => {
|
||||
MsgSuccess(t('common.createSuccess'))
|
||||
router.push({
|
||||
path: `/knowledge/${res.data.id}/${currentFolder.value.id}/document`,
|
||||
query: {
|
||||
type: apiType.value,
|
||||
},
|
||||
path: `/knowledge/${res.data.id}/${currentFolder.value.id || 'shared'}/document`,
|
||||
})
|
||||
emit('refresh')
|
||||
})
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ const submitHandle = async () => {
|
|||
.then((res: any) => {
|
||||
MsgSuccess(t('common.createSuccess'))
|
||||
router.push({
|
||||
path: `/knowledge/${res.data.id}/${currentFolder.value.id}/document`,
|
||||
path: `/knowledge/${res.data.id}/${currentFolder.value.id || 'shared'}/document`,
|
||||
query: {
|
||||
type: apiType.value,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ const submitHandle = async () => {
|
|||
.then((res: any) => {
|
||||
MsgSuccess(t('common.createSuccess'))
|
||||
router.push({
|
||||
path: `/knowledge/${res.data.id}/${currentFolder.value.id}/document`,
|
||||
path: `/knowledge/${res.data.id}/${currentFolder.value.id || 'shared'}/document`,
|
||||
query: {
|
||||
type: apiType.value,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ function getFolder(bool?: boolean) {
|
|||
}
|
||||
|
||||
function folderClickHandle(row: any) {
|
||||
if (row.id === folder.currentFolder?.id) {
|
||||
return
|
||||
}
|
||||
folder.setCurrentFolder(row)
|
||||
knowledge.setKnowledgeList([])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-if="showQrCodeTab">
|
||||
<QrCodeTab :tabs="orgOptions"/>
|
||||
<QrCodeTab :tabs="orgOptions" />
|
||||
</div>
|
||||
<div class="login-gradient-divider lighter mt-24" v-if="modeList.length > 1">
|
||||
<span>{{ $t('views.login.moreMethod') }}</span>
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
'font-size': item === 'OAUTH2' ? '8px' : '10px',
|
||||
color: theme.themeInfo?.theme,
|
||||
}"
|
||||
>{{ item }}</span
|
||||
>{{ item }}</span
|
||||
>
|
||||
</el-button>
|
||||
<el-button
|
||||
|
|
@ -108,7 +108,7 @@
|
|||
class="login-button-circle color-secondary"
|
||||
@click="changeMode('QR_CODE')"
|
||||
>
|
||||
<img src="@/assets/scan/icon_qr_outlined.svg" width="25px"/>
|
||||
<img src="@/assets/scan/icon_qr_outlined.svg" width="25px" />
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="item === '' && loginMode !== ''"
|
||||
|
|
@ -125,25 +125,25 @@
|
|||
</login-layout>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref, onBeforeMount} from 'vue'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
import type {FormInstance, FormRules} from 'element-plus'
|
||||
import type {LoginRequest} from '@/api/type/login'
|
||||
import { onMounted, ref, onBeforeMount } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type { LoginRequest } from '@/api/type/login'
|
||||
import LoginContainer from '@/layout/login-layout/LoginContainer.vue'
|
||||
import LoginLayout from '@/layout/login-layout/LoginLayout.vue'
|
||||
import loginApi from '@/api/user/login'
|
||||
import authApi from '@/api/system-settings/auth-setting'
|
||||
import {t, getBrowserLang} from '@/locales'
|
||||
import { t, getBrowserLang } from '@/locales'
|
||||
import useStore from '@/stores'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import QrCodeTab from '@/views/login/scanCompinents/QrCodeTab.vue'
|
||||
import {MsgConfirm, MsgError} from '@/utils/message.ts'
|
||||
import { MsgConfirm, MsgError } from '@/utils/message.ts'
|
||||
import * as dd from 'dingtalk-jsapi'
|
||||
import {loadScript} from '@/utils/utils'
|
||||
import { loadScript } from '@/utils/common'
|
||||
|
||||
const router = useRouter()
|
||||
const {login, user, theme} = useStore()
|
||||
const {locale} = useI18n({useScope: 'global'})
|
||||
const { login, user, theme } = useStore()
|
||||
const { locale } = useI18n({ useScope: 'global' })
|
||||
const loading = ref<boolean>(false)
|
||||
|
||||
const identifyCode = ref<string>('')
|
||||
|
|
@ -184,13 +184,13 @@ const loginHandle = () => {
|
|||
if (loginMode.value === 'LDAP') {
|
||||
login.asyncLdapLogin(loginForm.value, loading).then(() => {
|
||||
locale.value = localStorage.getItem('MaxKB-locale') || getBrowserLang() || 'en-US'
|
||||
router.push({name: 'home'})
|
||||
router.push({ name: 'home' })
|
||||
})
|
||||
} else {
|
||||
login.asyncLogin(loginForm.value, loading).then(() => {
|
||||
locale.value = localStorage.getItem('MaxKB-locale') || getBrowserLang() || 'en-US'
|
||||
localStorage.setItem('workspace_id', 'default')
|
||||
router.push({name: 'home'})
|
||||
router.push({ name: 'home' })
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
@ -273,8 +273,7 @@ function redirectAuth(authType: string) {
|
|||
window.location.href = url
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
})
|
||||
.catch(() => {})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -349,10 +348,10 @@ onMounted(() => {
|
|||
const handleDingTalk = () => {
|
||||
const code = params.get('corpId')
|
||||
if (code) {
|
||||
dd.runtime.permission.requestAuthCode({corpId: code}).then((res) => {
|
||||
dd.runtime.permission.requestAuthCode({ corpId: code }).then((res) => {
|
||||
console.log('DingTalk client request success:', res)
|
||||
login.dingOauth2Callback(res.code).then(() => {
|
||||
router.push({name: 'home'})
|
||||
router.push({ name: 'home' })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -365,7 +364,7 @@ onMounted(() => {
|
|||
appId: appId,
|
||||
success: (res: any) => {
|
||||
login.larkCallback(res.code).then(() => {
|
||||
router.push({name: 'home'})
|
||||
router.push({ name: 'home' })
|
||||
})
|
||||
},
|
||||
fail: (error: any) => {
|
||||
|
|
@ -385,11 +384,11 @@ onMounted(() => {
|
|||
scopeList: [],
|
||||
success: (res: any) => {
|
||||
login.larkCallback(res.code).then(() => {
|
||||
router.push({name: 'home'})
|
||||
router.push({ name: 'home' })
|
||||
})
|
||||
},
|
||||
fail: (error: any) => {
|
||||
const {errno} = error
|
||||
const { errno } = error
|
||||
if (errno === 103) {
|
||||
callRequestAuthCode()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ import { onMounted, ref, computed } from 'vue'
|
|||
import type { Provider, Model } from '@/api/type/model'
|
||||
import ModelCard from '@/views/model/component/ModelCard.vue'
|
||||
import ProviderComponent from '@/views/model/component/Provider.vue'
|
||||
import { splitArray } from '@/utils/common'
|
||||
import { splitArray } from '@/utils/array'
|
||||
import { modelTypeList, allObj } from '@/views/model/component/data'
|
||||
import CreateModelDialog from '@/views/model/component/CreateModelDialog.vue'
|
||||
import SelectProviderDialog from '@/views/model/component/SelectProviderDialog.vue'
|
||||
|
|
@ -205,7 +205,7 @@ const list_model = () => {
|
|||
.then((ok: any) => {
|
||||
model_list.value = ok.data
|
||||
})
|
||||
loadSharedApi({type: 'workspace', isShared: isShared.value, systemType: apiType.value })
|
||||
loadSharedApi({ type: 'workspace', isShared: isShared.value, systemType: apiType.value })
|
||||
.getAllMemberList(user.getWorkspaceId(), loading)
|
||||
.then((res: any) => {
|
||||
user_options.value = res.data
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ function getFolder(bool?: boolean) {
|
|||
}
|
||||
|
||||
function folderClickHandle(row: any) {
|
||||
if (row.id === folder.currentFolder?.id) {
|
||||
return
|
||||
}
|
||||
folder.setCurrentFolder(row)
|
||||
tool.setToolList([])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ import NodeContainer from '@/workflow/common/NodeContainer.vue'
|
|||
import NodeCascader from '@/workflow/common/NodeCascader.vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { ref, computed, onMounted, nextTick } from 'vue'
|
||||
import { randomId } from '@/utils/utils'
|
||||
import { randomId } from '@/utils/common'
|
||||
import { compareList } from '@/workflow/common/data'
|
||||
import { VueDraggable } from 'vue-draggable-plus'
|
||||
|
||||
|
|
|
|||
|
|
@ -260,29 +260,28 @@ function getTools() {
|
|||
MsgError(t('views.applicationWorkflow.nodes.mcpNode.mcpServerTip'))
|
||||
return
|
||||
}
|
||||
// todo
|
||||
applicationApi.getMcpTools(id, loading).then((res: any) => {
|
||||
form_data.value.mcp_tools = res.data
|
||||
MsgSuccess(t('views.applicationWorkflow.nodes.mcpNode.getToolsSuccess'))
|
||||
// 修改了json,刷新mcp_server
|
||||
form_data.value.mcp_server = form_data.value.mcp_tools.filter(
|
||||
form_data.value.mcp_server = form_data.value.mcp_tools.find(
|
||||
(item: any) => item.name === form_data.value.mcp_tool,
|
||||
)[0].server
|
||||
)?.server
|
||||
})
|
||||
}
|
||||
|
||||
function changeTool() {
|
||||
form_data.value.mcp_server = form_data.value.mcp_tools.filter(
|
||||
form_data.value.mcp_server = form_data.value.mcp_tools.find(
|
||||
(item: any) => item.name === form_data.value.mcp_tool,
|
||||
)[0].server
|
||||
)?.server
|
||||
// console.log(form_data.value.mcp_server)
|
||||
|
||||
const args_schema = form_data.value.mcp_tools.filter(
|
||||
const args_schema = form_data.value.mcp_tools.find(
|
||||
(item: any) => item.name === form_data.value.mcp_tool,
|
||||
)[0].args_schema
|
||||
)?.args_schema
|
||||
form_data.value.tool_form_field = []
|
||||
for (const item in args_schema.properties) {
|
||||
const params = args_schema.properties[item].properties
|
||||
for (const item in args_schema?.properties) {
|
||||
const params = args_schema?.properties[item].properties
|
||||
if (params) {
|
||||
form_data.value.params_nested = item
|
||||
for (const item2 in params) {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,11 @@
|
|||
<template v-for="(item, index) in form_data.knowledge_id_list" :key="index" v-else>
|
||||
<div class="flex-between border border-r-6 white-bg mb-4" style="padding: 5px 8px">
|
||||
<div class="flex align-center" style="line-height: 20px">
|
||||
<KnowledgeIcon :type="relatedObject(knowledgeList, item, 'id')?.type" class="mr-8" :size="20"/>
|
||||
<KnowledgeIcon
|
||||
:type="relatedObject(knowledgeList, item, 'id')?.type"
|
||||
class="mr-8"
|
||||
:size="20"
|
||||
/>
|
||||
|
||||
<div class="ellipsis" :title="relatedObject(knowledgeList, item, 'id')?.name">
|
||||
{{ relatedObject(knowledgeList, item, 'id')?.name }}
|
||||
|
|
@ -122,7 +126,7 @@ import AddknowledgeDialog from '@/views/application/component/AddKnowledgeDialog
|
|||
import ParamSettingDialog from '@/views/application/component/ParamSettingDialog.vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { relatedObject } from '@/utils/utils'
|
||||
import { relatedObject } from '@/utils/array'
|
||||
import { SearchMode } from '@/enums/application'
|
||||
import useStore from '@/stores'
|
||||
const { knowledge, application, user } = useStore()
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ import NodeContainer from '@/workflow/common/NodeContainer.vue'
|
|||
import NodeCascader from '@/workflow/common/NodeCascader.vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { isLastNode } from '@/workflow/common/data'
|
||||
import { randomId } from '@/utils/utils'
|
||||
import { randomId } from '@/utils/common'
|
||||
import { t } from '@/locales'
|
||||
|
||||
const props = defineProps<{ nodeModel: any }>()
|
||||
|
|
|
|||
Loading…
Reference in New Issue