fix: bugs
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run

This commit is contained in:
wangdan-fit2cloud 2025-07-02 22:41:33 +08:00
parent aa901c7fc7
commit 47368a5f99
37 changed files with 367 additions and 354 deletions

View File

@ -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)
}

View File

@ -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,

View File

@ -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'])

View File

@ -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'

View File

@ -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({

View File

@ -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'

View File

@ -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 || []
})

View File

@ -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'

View File

@ -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,

View File

@ -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'

View File

@ -25,10 +25,10 @@ import { useRoute } from 'vue-router'
const route = useRoute()
const {
params: { folderId }, // idknowledgeID
query: { type },
} = route as any
const isShared = computed(() => {
return folderId === 'shared'
return folderId === 'shared' || type === 'systemShare'
})
const { theme } = useStore()
const isDefaultTheme = computed(() => {

View File

@ -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 }, // idknowledgeID
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 />

View File

@ -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)
})
})
},
},
})

View File

@ -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)
})
}

View File

@ -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)}`

View File

@ -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)
}

View File

@ -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>

View File

@ -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'

View File

@ -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 })

View File

@ -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()

View File

@ -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: {

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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

View File

@ -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({

View File

@ -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')
})

View File

@ -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,
},

View File

@ -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,
},

View File

@ -58,6 +58,9 @@ function getFolder(bool?: boolean) {
}
function folderClickHandle(row: any) {
if (row.id === folder.currentFolder?.id) {
return
}
folder.setCurrentFolder(row)
knowledge.setKnowledgeList([])
}

View File

@ -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()
}

View File

@ -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

View File

@ -60,6 +60,9 @@ function getFolder(bool?: boolean) {
}
function folderClickHandle(row: any) {
if (row.id === folder.currentFolder?.id) {
return
}
folder.setCurrentFolder(row)
tool.setToolList([])
}

View File

@ -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'

View File

@ -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'))
// jsonmcp_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) {

View File

@ -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()

View File

@ -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 }>()