feat: tool
This commit is contained in:
parent
2ab57802f4
commit
11fa3c4814
51
ui/src/components/folder-breadcrumb/index.vue
Normal file
51
ui/src/components/folder-breadcrumb/index.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-breadcrumb separator-icon="ArrowRight" style="line-height: 22px">
|
||||
<h4 v-if="breadcrumbData?.length === 1">{{ breadcrumbData[0]?.name }}</h4>
|
||||
<el-breadcrumb-item v-for="(item, index) in breadcrumbData" :key="index" v-else>
|
||||
<h5 class="ml-4" v-if="index === breadcrumbData.length - 1">{{ item.name }}</h5>
|
||||
<el-button v-else link @click="handleClick(item)">{{ item.name }}</el-button>
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { TreeToFlatten } from '@/utils/array'
|
||||
defineOptions({ name: 'FolderBreadcrumb' })
|
||||
import useStore from '@/stores'
|
||||
const { folder, user } = useStore()
|
||||
|
||||
const props = defineProps({
|
||||
folderList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const breadcrumbData = computed(() => {
|
||||
return folder.currentFolder?.id && getBreadcrumbData()
|
||||
})
|
||||
|
||||
const emit = defineEmits(['click'])
|
||||
|
||||
function getBreadcrumbData() {
|
||||
const targetId = folder.currentFolder?.id
|
||||
const list = TreeToFlatten(props.folderList)
|
||||
if (!folder.currentFolder) return [] // 如果没有 id,返回空数组
|
||||
const breadcrumbList: any[] = []
|
||||
let currentId: string | null = targetId
|
||||
while (currentId) {
|
||||
const currentNode = list.find((item: any) => item.id === currentId)
|
||||
if (!currentNode) break // 如果找不到节点,终止循环
|
||||
breadcrumbList.unshift(currentNode) // 添加到面包屑
|
||||
currentId = currentNode.parent_id // 继续查找父级
|
||||
}
|
||||
return breadcrumbList
|
||||
}
|
||||
|
||||
function handleClick(item: any) {
|
||||
emit('click', item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -52,6 +52,8 @@ import { ref, watch, reactive } from 'vue'
|
||||
import folderApi from '@/api/folder'
|
||||
import { MsgSuccess, MsgAlert } from '@/utils/message'
|
||||
import { t } from '@/locales'
|
||||
import useStore from '@/stores'
|
||||
const { tool } = useStore()
|
||||
const emit = defineEmits(['refresh'])
|
||||
|
||||
const props = defineProps({
|
||||
@ -122,12 +124,14 @@ const submitHandle = async () => {
|
||||
.then((res) => {
|
||||
MsgSuccess(t('common.editSuccess'))
|
||||
emit('refresh')
|
||||
tool.setToolList([])
|
||||
dialogVisible.value = false
|
||||
})
|
||||
} else {
|
||||
folderApi.postFolder(sourceType.value, folderForm.value, loading).then((res) => {
|
||||
MsgSuccess(t('common.createSuccess'))
|
||||
emit('refresh')
|
||||
tool.setToolList([])
|
||||
dialogVisible.value = false
|
||||
})
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
:class="currentNodeKey === 'share' && 'active'"
|
||||
>
|
||||
<AppIcon :iconName="iconName" style="font-size: 18px"></AppIcon>
|
||||
<span class="ml-8 lighter">{{ $t(shareTitle) }}</span>
|
||||
<span class="ml-8 lighter">{{ shareTitle }}</span>
|
||||
</div>
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
@ -37,7 +37,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="canOperation"
|
||||
v-if="canOperation && node.level !== 3"
|
||||
@click.stop
|
||||
v-show="hoverNodeId === data.id"
|
||||
@mouseenter.stop="handleMouseEnter(data)"
|
||||
@ -61,7 +61,7 @@
|
||||
<el-dropdown-item
|
||||
divided
|
||||
@click.stop="deleteFolder(data)"
|
||||
:disabled="data.id === 'default'"
|
||||
:disabled="!data.parent_id"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
{{ $t('common.delete') }}
|
||||
@ -109,7 +109,7 @@ const props = defineProps({
|
||||
},
|
||||
shareTitle: {
|
||||
type: String,
|
||||
default: 'views.system.share_knowledge',
|
||||
default: 'views.system.shared.shared_knowledge',
|
||||
},
|
||||
canOperation: {
|
||||
type: Boolean,
|
||||
@ -162,7 +162,7 @@ const handleNodeClick = (data: Tree) => {
|
||||
|
||||
const handleSharedNodeClick = () => {
|
||||
treeRef.value?.setCurrentKey(undefined)
|
||||
emit('handleNodeClick', { id: 'share', name: t(props.shareTitle) })
|
||||
emit('handleNodeClick', { id: 'share', name: props.shareTitle })
|
||||
}
|
||||
|
||||
function deleteFolder(row: Tree) {
|
||||
|
||||
@ -25,6 +25,7 @@ import AiChat from './ai-chat/index.vue'
|
||||
import KnowledgeIcon from './app-icon/KnowledgeIcon.vue'
|
||||
import TagGroup from './tag-group/index.vue'
|
||||
import WorkspaceDropdown from './workspace-dropdown/index.vue'
|
||||
import FolderBreadcrumb from './folder-breadcrumb/index.vue'
|
||||
export default {
|
||||
install(app: App) {
|
||||
app.component('LogoFull', LogoFull)
|
||||
@ -53,5 +54,6 @@ export default {
|
||||
app.component('KnowledgeIcon', KnowledgeIcon)
|
||||
app.component('TagGroup', TagGroup)
|
||||
app.component('WorkspaceDropdown', WorkspaceDropdown)
|
||||
app.component('FolderBreadcrumb', FolderBreadcrumb)
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
export default {
|
||||
title: 'System',
|
||||
subTitle: 'Syetem Settings',
|
||||
shared: 'Shared',
|
||||
shared_resources: 'Shared Resources',
|
||||
share_knowledge: 'Shared Knowledge',
|
||||
authorized_workspace: 'Authorize Workspace',
|
||||
test: 'Test Connection',
|
||||
testSuccess: 'Successful',
|
||||
testFailed: 'Test connection failed',
|
||||
@ -23,7 +19,7 @@ export default {
|
||||
ldap_filterPlaceholder: 'Please enter user filter',
|
||||
ldap_mapping: 'LDAP Attribute Mapping',
|
||||
ldap_mappingPlaceholder: 'Please enter LDAP attribute mapping',
|
||||
enableAuthentication: 'Enable LDAP Authentication'
|
||||
enableAuthentication: 'Enable LDAP Authentication',
|
||||
},
|
||||
cas: {
|
||||
title: 'CAS',
|
||||
@ -33,7 +29,7 @@ export default {
|
||||
validateUrlPlaceholder: 'Please enter validation address',
|
||||
redirectUrl: 'Callback Address',
|
||||
redirectUrlPlaceholder: 'Please enter callback address',
|
||||
enableAuthentication: 'Enable CAS Authentication'
|
||||
enableAuthentication: 'Enable CAS Authentication',
|
||||
},
|
||||
oidc: {
|
||||
title: 'OIDC',
|
||||
@ -52,7 +48,7 @@ export default {
|
||||
logoutEndpointPlaceholder: 'Please enter logout endpoint',
|
||||
redirectUrl: 'Redirect URL',
|
||||
redirectUrlPlaceholder: 'Please enter redirect URL',
|
||||
enableAuthentication: 'Enable OIDC Authentication'
|
||||
enableAuthentication: 'Enable OIDC Authentication',
|
||||
},
|
||||
|
||||
oauth2: {
|
||||
@ -73,7 +69,7 @@ export default {
|
||||
redirectUrlPlaceholder: 'Please enter redirect URL',
|
||||
filedMapping: 'Field Mapping',
|
||||
filedMappingPlaceholder: 'Please enter field mapping',
|
||||
enableAuthentication: 'Enable OAuth2 Authentication'
|
||||
enableAuthentication: 'Enable OAuth2 Authentication',
|
||||
},
|
||||
scanTheQRCode: {
|
||||
title: 'Scan the QR code',
|
||||
@ -95,10 +91,10 @@ export default {
|
||||
larkQrCode: 'Lark Scan Code Login',
|
||||
dingtalkQrCode: 'DingTalk Scan Code Login',
|
||||
setting: ' Setting',
|
||||
access: 'Access'
|
||||
}
|
||||
access: 'Access',
|
||||
},
|
||||
},
|
||||
theme: {
|
||||
theme: {
|
||||
title: 'Appearance Settings',
|
||||
platformDisplayTheme: 'Platform Display Theme',
|
||||
customTheme: 'Custom Theme',
|
||||
@ -115,8 +111,10 @@ export default {
|
||||
loginLogo: 'Login Logo',
|
||||
websiteLogo: 'Website Logo',
|
||||
replacePicture: 'Replace Picture',
|
||||
websiteLogoTip: "The logo displayed on the top of the website. The recommended size is 48*48. It supports JPG, PNG, and GIF formats, with a size not exceeding 10MB.",
|
||||
loginLogoTip: "Login page right-side logo. Recommended size is 204*52. Supports JPG, PNG, GIF formats, with a maximum file size of 10 MB.",
|
||||
websiteLogoTip:
|
||||
'The logo displayed on the top of the website. The recommended size is 48*48. It supports JPG, PNG, and GIF formats, with a size not exceeding 10MB.',
|
||||
loginLogoTip:
|
||||
'Login page right-side logo. Recommended size is 204*52. Supports JPG, PNG, GIF formats, with a maximum file size of 10 MB.',
|
||||
loginBackgroundTip:
|
||||
'Left background image, vector image recommended size 576 * 900, bitmap recommended size 1152 * 1800; Supports JPG, PNG, GIF, with a size not exceeding 10 MB.',
|
||||
websiteName: 'Website Name',
|
||||
@ -146,14 +144,14 @@ export default {
|
||||
smtpPortPlaceholder: 'Please enter SMTP port',
|
||||
smtpUser: 'SMTP User',
|
||||
smtpUserPlaceholder: 'Please enter SMTP user',
|
||||
sendEmail: 'Sender\'s Email',
|
||||
sendEmailPlaceholder: 'Please enter the sender\'s email',
|
||||
sendEmail: "Sender's Email",
|
||||
sendEmailPlaceholder: "Please enter the sender's email",
|
||||
smtpPassword: 'SMTP Password',
|
||||
smtpPasswordPlaceholder: 'Please enter SMTP password',
|
||||
enableSSL: 'Enable SSL (if the SMTP port is 465, you usually need to enable SSL)',
|
||||
enableTLS: 'Enable TLS (if the SMTP port is 587, you usually need to enable TLS)'
|
||||
enableTLS: 'Enable TLS (if the SMTP port is 587, you usually need to enable TLS)',
|
||||
},
|
||||
group: {
|
||||
group: {
|
||||
title: 'Team Member',
|
||||
member: 'Member',
|
||||
manage: 'Owner',
|
||||
@ -166,7 +164,8 @@ export default {
|
||||
delete: {
|
||||
button: 'Remove',
|
||||
confirmTitle: 'Wheather to remove the member:',
|
||||
confirmMessage: "After removal, the member's knowledge base and application permissions will be revoked.",
|
||||
confirmMessage:
|
||||
"After removal, the member's knowledge base and application permissions will be revoked.",
|
||||
},
|
||||
setting: {
|
||||
management: 'manegement',
|
||||
@ -180,5 +179,16 @@ export default {
|
||||
requiredMessage: 'Please enter Username/Email',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
shared: {
|
||||
label: 'Shared',
|
||||
shared_resources: 'Shared Resources',
|
||||
shared_tool: 'Shared Tool',
|
||||
shared_model: 'Shared Model',
|
||||
shared_knowledge: 'Shared Knowledge',
|
||||
authorized_workspace: 'Authorize Workspace',
|
||||
},
|
||||
resource_management: {
|
||||
label: 'Resource Management',
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,13 +1,6 @@
|
||||
export default {
|
||||
title: '系统管理',
|
||||
subTitle: '系统设置',
|
||||
shared: '共享',
|
||||
shared_resources: '共享资源',
|
||||
resource_management: '资源管理',
|
||||
share_tool: '共享工具',
|
||||
share_model: '共享模型',
|
||||
share_knowledge: '共享知识库',
|
||||
authorized_workspace: '授权工作空间',
|
||||
test: '测试连接',
|
||||
testSuccess: '测试连接成功',
|
||||
testFailed: '测试连接失败',
|
||||
@ -184,4 +177,15 @@ export default {
|
||||
},
|
||||
},
|
||||
},
|
||||
shared: {
|
||||
label: '共享',
|
||||
shared_resources: '共享资源',
|
||||
shared_tool: '共享工具',
|
||||
shared_model: '共享模型',
|
||||
shared_knowledge: '共享知识库',
|
||||
authorized_workspace: '授权工作空间',
|
||||
},
|
||||
resource_management: {
|
||||
label: '资源管理',
|
||||
},
|
||||
}
|
||||
|
||||
@ -110,4 +110,15 @@ export default {
|
||||
enableSSL: '啟用 SSL(如果 SMTP 端口是 465,通常需要啟用 SSL)',
|
||||
enableTLS: '啟用 TLS(如果 SMTP 端口是 587,通常需要啟用 TLS)',
|
||||
},
|
||||
shared: {
|
||||
label: '共享',
|
||||
shared_resources: '共享资源',
|
||||
shared_tool: '共享工具',
|
||||
shared_model: '共享模型',
|
||||
shared_knowledge: '共享知识',
|
||||
authorized_workspace: '授权工作区',
|
||||
},
|
||||
resource_management: {
|
||||
label: '资源管理',
|
||||
},
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ const systemRouter = {
|
||||
meta: {
|
||||
icon: 'app-folder-share',
|
||||
iconActive: 'app-folder-share-active',
|
||||
title: 'views.system.resource_management',
|
||||
title: 'views.system.resource_management.label',
|
||||
activeMenu: '/system',
|
||||
parentPath: '/system',
|
||||
parentName: 'system',
|
||||
@ -119,7 +119,7 @@ const systemRouter = {
|
||||
meta: {
|
||||
icon: 'app-folder-share',
|
||||
iconActive: 'app-folder-share-active',
|
||||
title: 'views.system.shared_resources',
|
||||
title: 'views.system.shared.shared_resources',
|
||||
activeMenu: '/system',
|
||||
parentPath: '/system',
|
||||
parentName: 'system',
|
||||
@ -146,7 +146,7 @@ const systemRouter = {
|
||||
parentPath: '/system',
|
||||
parentName: 'system',
|
||||
},
|
||||
component: () => import('@/views/shared/tool-shared/index.vue'),
|
||||
component: () => import('@/views/system-shared/ToolSharedIndex.vue'),
|
||||
},
|
||||
{
|
||||
path: '/system/shared/model',
|
||||
|
||||
@ -12,6 +12,7 @@ import useDocumentStore from './modules/document'
|
||||
import useApplicationStore from './modules/application'
|
||||
import useChatLogStore from './modules/chat-log'
|
||||
import useChatUserStore from './modules/chat-user'
|
||||
import useToolStore from './modules/tool'
|
||||
const useStore = () => ({
|
||||
common: useCommonStore(),
|
||||
login: useLoginStore(),
|
||||
@ -27,6 +28,7 @@ const useStore = () => ({
|
||||
application: useApplicationStore(),
|
||||
chatLog: useChatLogStore(),
|
||||
chatUser: useChatUserStore(),
|
||||
tool: useToolStore(),
|
||||
})
|
||||
|
||||
export default useStore
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
import {defineStore} from 'pinia'
|
||||
import {type Ref} from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { type Ref } from 'vue'
|
||||
import folderApi from '@/api/folder'
|
||||
|
||||
const useFolderStore = defineStore('folder', {
|
||||
state: () => ({}),
|
||||
state: () => ({
|
||||
currentFolder: {} as any,
|
||||
}),
|
||||
actions: {
|
||||
setCurrentFolder(folder: any) {
|
||||
this.currentFolder = folder
|
||||
},
|
||||
async asyncGetFolder(source: string, data: any, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
folderApi
|
||||
|
||||
42
ui/src/stores/modules/tool.ts
Normal file
42
ui/src/stores/modules/tool.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { type Ref } from 'vue'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
import type { pageRequest } from '@/api/type/common'
|
||||
import useUserStore from './user'
|
||||
import useFolderStore from './folder'
|
||||
|
||||
const useToolStore = defineStore('tool', {
|
||||
state: () => ({
|
||||
toolList: [] as any[],
|
||||
}),
|
||||
actions: {
|
||||
setToolList(list: any[]) {
|
||||
this.toolList = list
|
||||
},
|
||||
async asyncGetToolListPage(
|
||||
page: pageRequest,
|
||||
isShared?: boolean | undefined,
|
||||
systemType: 'systemShare' | 'workspace' | 'systemManage' = 'workspace',
|
||||
loading?: Ref<boolean>,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const folder = useFolderStore()
|
||||
const user = useUserStore()
|
||||
const params = {
|
||||
folder_id: folder.currentFolder?.id || user.getWorkspaceId(),
|
||||
scope: systemType === 'systemShare' ? 'SHARED' : 'WORKSPACE',
|
||||
}
|
||||
loadSharedApi({ type: 'tool', isShared, systemType })
|
||||
.getToolListPage(page, params, loading)
|
||||
.then((res: any) => {
|
||||
resolve(res)
|
||||
})
|
||||
.catch((error: any) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default useToolStore
|
||||
7
ui/src/utils/array.ts
Normal file
7
ui/src/utils/array.ts
Normal file
@ -0,0 +1,7 @@
|
||||
// 树形结构转平
|
||||
export function TreeToFlatten(treeData: any[]) {
|
||||
return treeData.reduce((acc, node) => {
|
||||
const { children, ...rest } = node
|
||||
return [...acc, rest, ...(children ? TreeToFlatten(children) : [])]
|
||||
}, [])
|
||||
}
|
||||
@ -2,6 +2,9 @@ import knowledgeWorkspaceApi from '@/api/knowledge/knowledge'
|
||||
import modelWorkspaceApi from '@/api/model/model'
|
||||
import toolWorkspaceApi from '@/api/tool/tool'
|
||||
import sharedWorkspaceApi from '@/api/shared-workspace'
|
||||
import toolSystemShareApi from '@/api/system-shared/tool'
|
||||
import modelSystemShareApi from '@/api/system-shared/model'
|
||||
import knowledgeSystemShareApi from '@/api/system-shared/knowledge'
|
||||
|
||||
// 普通 API
|
||||
const workspaceApiMap = {
|
||||
@ -10,15 +13,41 @@ const workspaceApiMap = {
|
||||
tool: toolWorkspaceApi,
|
||||
} as any
|
||||
|
||||
/** 动态导入 API 模块的函数
|
||||
* loadSharedApi('knowledge', true)
|
||||
*/
|
||||
// 系统分享 API
|
||||
const systemShareApiMap = {
|
||||
knowledge: knowledgeSystemShareApi,
|
||||
model: modelSystemShareApi,
|
||||
tool: toolSystemShareApi,
|
||||
} as any
|
||||
|
||||
export function loadSharedApi(type: string, isShared?: boolean) {
|
||||
// 资源管理 API
|
||||
const systemManageApiMap = {
|
||||
// knowledge: knowledgeWorkspaceApi,
|
||||
// model: modelWorkspaceApi,
|
||||
// tool: toolSystemShareApi,
|
||||
} as any
|
||||
|
||||
const data = {
|
||||
systemShare: systemShareApiMap,
|
||||
workspace: workspaceApiMap,
|
||||
systemManage: systemManageApiMap,
|
||||
}
|
||||
/** 动态导入 API 模块的函数
|
||||
* loadSharedApi('knowledge', true,'systemShare')
|
||||
*/
|
||||
export function loadSharedApi({
|
||||
type,
|
||||
isShared,
|
||||
systemType,
|
||||
}: {
|
||||
type: string
|
||||
isShared?: boolean | undefined
|
||||
systemType?: 'systemShare' | 'workspace' | 'systemManage'
|
||||
}) {
|
||||
if (isShared) {
|
||||
// 共享 API
|
||||
return sharedWorkspaceApi
|
||||
} else {
|
||||
return workspaceApiMap[type]
|
||||
return data[systemType || 'workspace'][type]
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<template #left>
|
||||
<h4 class="p-16 pb-0">{{ $t('views.application.title') }}</h4>
|
||||
<folder-tree
|
||||
:source="FolderSource.TOOL"
|
||||
:source="FolderSource.APPLICATION"
|
||||
:data="folderList"
|
||||
:currentNodeKey="currentFolder?.id"
|
||||
@handleNodeClick="folderClickHandel"
|
||||
|
||||
@ -199,10 +199,14 @@
|
||||
router.push({ path: `/knowledge/${item.id}/${currentFolder.id}/document` })
|
||||
"
|
||||
v-hasPermission="[
|
||||
RoleConst.ADMIN,
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_READ.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_READ.getKnowledgeWorkspaceResourcePermission(item.id),]"
|
||||
RoleConst.ADMIN,
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_READ
|
||||
.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_DOCUMENT_READ.getKnowledgeWorkspaceResourcePermission(
|
||||
item.id,
|
||||
),
|
||||
]"
|
||||
>
|
||||
<template #icon>
|
||||
<KnowledgeIcon :type="item.type" />
|
||||
@ -214,7 +218,7 @@
|
||||
</template>
|
||||
<template #tag>
|
||||
<el-tag v-if="isShared" type="info" class="info-tag">
|
||||
{{ t('views.system.shared') }}
|
||||
{{ t('views.system.shared.label') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<template #footer>
|
||||
@ -248,12 +252,21 @@
|
||||
<el-dropdown-item
|
||||
icon="Refresh"
|
||||
@click.stop="syncKnowledge(item)"
|
||||
v-if="item.type === 1 &&
|
||||
hasPermission([
|
||||
RoleConst.ADMIN,
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_SYNC.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_SYNC.getKnowledgeWorkspaceResourcePermission(item.id)],'OR')"
|
||||
v-if="
|
||||
item.type === 1 &&
|
||||
hasPermission(
|
||||
[
|
||||
RoleConst.ADMIN,
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
PermissionConst.KNOWLEDGE_SYNC
|
||||
.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_SYNC.getKnowledgeWorkspaceResourcePermission(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
"
|
||||
>{{ $t('views.knowledge.setting.sync') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
@ -263,8 +276,11 @@
|
||||
[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
RoleConst.ADMIN,
|
||||
PermissionConst.KNOWLEDGE_VECTOR.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_VECTOR.getKnowledgeWorkspaceResourcePermission(item.id),
|
||||
PermissionConst.KNOWLEDGE_VECTOR
|
||||
.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_VECTOR.getKnowledgeWorkspaceResourcePermission(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
@ -282,8 +298,11 @@
|
||||
[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
RoleConst.ADMIN,
|
||||
PermissionConst.KNOWLEDGE_PROBLEM_CREATE.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_PROBLEM_CREATE.getKnowledgeWorkspaceResourcePermission(item.id),
|
||||
PermissionConst.KNOWLEDGE_PROBLEM_CREATE
|
||||
.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_PROBLEM_CREATE.getKnowledgeWorkspaceResourcePermission(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
@ -302,8 +321,11 @@
|
||||
[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
RoleConst.ADMIN,
|
||||
PermissionConst.KNOWLEDGE_EDIT.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_EDIT.getKnowledgeWorkspaceResourcePermission(item.id),
|
||||
PermissionConst.KNOWLEDGE_EDIT
|
||||
.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_EDIT.getKnowledgeWorkspaceResourcePermission(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
@ -318,8 +340,11 @@
|
||||
[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
RoleConst.ADMIN,
|
||||
PermissionConst.KNOWLEDGE_EXPORT.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_EXPORT.getKnowledgeWorkspaceResourcePermission(item.id),
|
||||
PermissionConst.KNOWLEDGE_EXPORT
|
||||
.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_EXPORT.getKnowledgeWorkspaceResourcePermission(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
@ -335,8 +360,11 @@
|
||||
[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
RoleConst.ADMIN,
|
||||
PermissionConst.KNOWLEDGE_EXPORT.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_EXPORT.getKnowledgeWorkspaceResourcePermission(item.id),
|
||||
PermissionConst.KNOWLEDGE_EXPORT
|
||||
.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_EXPORT.getKnowledgeWorkspaceResourcePermission(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
@ -354,8 +382,11 @@
|
||||
[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
RoleConst.ADMIN,
|
||||
PermissionConst.KNOWLEDGE_DELETE.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_DELETE.getKnowledgeWorkspaceResourcePermission(item.id),
|
||||
PermissionConst.KNOWLEDGE_DELETE
|
||||
.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.KNOWLEDGE_DELETE.getKnowledgeWorkspaceResourcePermission(
|
||||
item.id,
|
||||
),
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
@ -476,7 +507,7 @@ function getList() {
|
||||
[search_type.value]: search_form.value[search_type.value],
|
||||
}
|
||||
|
||||
loadSharedApi('knowledge', isShared.value)
|
||||
loadSharedApi({ type: 'knowledge', isShared: isShared.value })
|
||||
.getKnowledgeListPage(paginationConfig, params, loading)
|
||||
.then((res: any) => {
|
||||
paginationConfig.total = res.data.total
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
</template>
|
||||
<template #tag>
|
||||
<el-tag v-if="isShared" type="info" class="info-tag">
|
||||
{{ t('views.system.shared') }}
|
||||
{{ t('views.system.shared.label') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
<ul>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
:class="active?.provider === 'share' && 'active'"
|
||||
>
|
||||
<AppIcon iconName="app-folder-share-active" style="font-size: 18px"></AppIcon>
|
||||
<span class="ml-8 lighter">{{ $t('views.system.share_model') }}</span>
|
||||
<span class="ml-8 lighter">{{ $t('views.system.shared.shared_model') }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="all-mode flex cursor"
|
||||
@ -145,7 +145,7 @@ const clickListHandle = (item: Provider) => {
|
||||
}
|
||||
|
||||
const handleSharedNodeClick = () => {
|
||||
emit('click', { provider: 'share', name: t('views.system.share_model') })
|
||||
emit('click', { provider: 'share', name: t('views.system.shared.shared_model') })
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
:data="provider_list"
|
||||
@click="clickListHandle"
|
||||
:loading="loading"
|
||||
shareTitle="views.system.share_tool"
|
||||
shareTitle="views.system.shared.shared_tool"
|
||||
:showShared="permissionPrecise['is_share']()"
|
||||
:active="active_provider"
|
||||
/>
|
||||
@ -55,8 +55,8 @@
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="!isShared &&
|
||||
permissionPrecise.addModel()
|
||||
v-if="!isShared &&
|
||||
permissionPrecise.addModel()
|
||||
"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@ -202,7 +202,7 @@ const openCreateModel = (provider?: Provider, model_type?: string) => {
|
||||
|
||||
const list_model = () => {
|
||||
const params = active_provider.value?.provider ? { provider: active_provider.value.provider } : {}
|
||||
loadSharedApi('model', isShared.value)
|
||||
loadSharedApi({ type: 'model', isShared: isShared.value })
|
||||
.getModel({ ...model_search_form.value, ...params }, list_model_loading)
|
||||
.then((ok: any) => {
|
||||
model_list.value = ok.data
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="resource-manage_knowledge">
|
||||
<div class="shared-header">
|
||||
<span class="title">{{ t('views.system.resource_management') }}</span>
|
||||
<span class="title">{{ t('views.system.resource_management.label') }}</span>
|
||||
<el-icon size="12">
|
||||
<rightOutlined></rightOutlined>
|
||||
</el-icon>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="resource-manage_tool">
|
||||
<div class="shared-header">
|
||||
<span class="title">{{ t('views.system.resource_management') }}</span>
|
||||
<span class="title">{{ t('views.system.resource_management.label') }}</span>
|
||||
<el-icon size="12">
|
||||
<rightOutlined></rightOutlined>
|
||||
</el-icon>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="knowledge-shared">
|
||||
<ContentContainer :header="$t('views.system.share_knowledge')">
|
||||
<ContentContainer :header="$t('views.system.shared.shared_knowledge')">
|
||||
<template #search>
|
||||
<div class="flex">
|
||||
<div class="flex-between complex-search">
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<ContentContainer>
|
||||
<template #header>
|
||||
<div class="shared-header">
|
||||
<span class="title">{{ t('views.system.shared_resources') }}</span>
|
||||
<span class="title">{{ t('views.system.shared.shared_resources') }}</span>
|
||||
<el-icon size="12">
|
||||
<rightOutlined></rightOutlined>
|
||||
</el-icon>
|
||||
@ -230,7 +230,7 @@
|
||||
<el-dropdown-item
|
||||
icon="Lock"
|
||||
@click.stop="openAuthorizedWorkspaceDialog(item)"
|
||||
>{{ $t('views.system.authorized_workspace') }}</el-dropdown-item
|
||||
>{{ $t('views.system.shared.authorized_workspace') }}</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
icon="Setting"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="model-shared">
|
||||
<ContentContainer
|
||||
:header="t('views.system.share_model')"
|
||||
:header="t('views.system.shared.shared_model')"
|
||||
v-loading="list_model_loading"
|
||||
>
|
||||
<template #search>
|
||||
|
||||
@ -85,7 +85,7 @@
|
||||
{{ $t('common.modify') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item icon="Lock" @click.stop="openAuthorizedWorkspaceDialog(model)">{{
|
||||
$t('views.system.authorized_workspace')
|
||||
$t('views.system.shared.authorized_workspace')
|
||||
}}</el-dropdown-item>
|
||||
|
||||
<el-dropdown-item
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="model-shared">
|
||||
<div class="shared-header">
|
||||
<span class="title">{{ t('views.system.shared_resources') }}</span>
|
||||
<span class="title">{{ t('views.system.shared.shared_resources') }}</span>
|
||||
<el-icon size="12">
|
||||
<rightOutlined></rightOutlined>
|
||||
</el-icon>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="tool-shared">
|
||||
<ContentContainer :header="$t('views.system.share_tool')">
|
||||
<ContentContainer :header="$t('views.system.shared.shared_tool')">
|
||||
<template #search>
|
||||
<div class="flex">
|
||||
<div class="flex-between complex-search">
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<ContentContainer>
|
||||
<template #header>
|
||||
<div class="shared-header">
|
||||
<span class="title">{{ t('views.system.shared_resources') }}</span>
|
||||
<span class="title">{{ t('views.system.shared.shared_resources') }}</span>
|
||||
<el-icon size="12">
|
||||
<rightOutlined></rightOutlined>
|
||||
</el-icon>
|
||||
@ -132,7 +132,7 @@
|
||||
<el-dropdown-item
|
||||
icon="Lock"
|
||||
@click.stop="openAuthorizedWorkspaceDialog(item)"
|
||||
>{{ $t('views.system.authorized_workspace') }}</el-dropdown-item
|
||||
>{{ $t('views.system.shared.authorized_workspace') }}</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
v-if="!item.template_id"
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<ContentContainer>
|
||||
<template #header>
|
||||
<div class="shared-header">
|
||||
<span class="title">{{ t('views.system.shared_resources') }}</span>
|
||||
<span class="title">{{ t('views.system.shared.shared_resources') }}</span>
|
||||
<el-icon size="12">
|
||||
<rightOutlined></rightOutlined>
|
||||
</el-icon>
|
||||
@ -17,7 +17,7 @@
|
||||
:data="provider_list"
|
||||
@click="clickListHandle"
|
||||
:loading="loading"
|
||||
shareTitle="views.system.share_tool"
|
||||
:shareTitle="$t('views.system.shared.shared_tool')"
|
||||
isShared
|
||||
:active="active_provider"
|
||||
/>
|
||||
|
||||
46
ui/src/views/system-shared/ToolSharedIndex.vue
Normal file
46
ui/src/views/system-shared/ToolSharedIndex.vue
Normal file
@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div class="tool-shared">
|
||||
<ToolListContainer>
|
||||
<template #header>
|
||||
<el-breadcrumb separator-icon="ArrowRight">
|
||||
<el-breadcrumb-item>{{ t('views.system.shared.shared_resources') }}</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>
|
||||
{{ t('views.tool.title') }}
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
</ToolListContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, reactive, computed } from 'vue'
|
||||
|
||||
import ToolListContainer from '@/views/tool/component/ToolListContainer.vue'
|
||||
|
||||
import { t } from '@/locales'
|
||||
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tool-shared {
|
||||
padding-left: 8px;
|
||||
.shared-header {
|
||||
color: #646a73;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:deep(.el-icon i) {
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
color: #1f2329;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
583
ui/src/views/tool/component/ToolListContainer.vue
Normal file
583
ui/src/views/tool/component/ToolListContainer.vue
Normal file
@ -0,0 +1,583 @@
|
||||
<template>
|
||||
<ContentContainer>
|
||||
<template #header>
|
||||
<slot name="header"> </slot>
|
||||
</template>
|
||||
<template #search>
|
||||
<div class="flex">
|
||||
<div class="flex-between complex-search">
|
||||
<el-select
|
||||
class="complex-search__left"
|
||||
v-model="search_type"
|
||||
style="width: 120px"
|
||||
@change="search_type_change"
|
||||
>
|
||||
<el-option :label="$t('common.creator')" value="create_user" />
|
||||
|
||||
<el-option :label="$t('views.model.modelForm.modeName.label')" value="name" />
|
||||
</el-select>
|
||||
<el-input
|
||||
v-if="search_type === 'name'"
|
||||
v-model="search_form.name"
|
||||
@change="getList"
|
||||
:placeholder="$t('common.searchBar.placeholder')"
|
||||
style="width: 220px"
|
||||
clearable
|
||||
/>
|
||||
<el-select
|
||||
v-else-if="search_type === 'create_user'"
|
||||
v-model="search_form.create_user"
|
||||
@change="getList"
|
||||
clearable
|
||||
style="width: 220px"
|
||||
>
|
||||
<el-option v-for="u in user_options" :key="u.id" :value="u.id" :label="u.username" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-dropdown trigger="click" v-if="!isShared">
|
||||
<el-button type="primary" class="ml-8" v-if="permissionPrecise.create()">
|
||||
{{ $t('common.create') }}
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="create-dropdown">
|
||||
<el-dropdown-item @click="openCreateDialog()">
|
||||
<div class="flex align-center">
|
||||
<el-avatar class="avatar-green" shape="square" :size="32">
|
||||
<img src="@/assets/node/icon_tool.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<div class="pre-wrap ml-8">
|
||||
<div class="lighter">空白创建</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
<el-upload
|
||||
ref="elUploadRef"
|
||||
:file-list="[]"
|
||||
action="#"
|
||||
multiple
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:limit="1"
|
||||
:on-change="(file: any, fileList: any) => importTool(file)"
|
||||
class="import-button"
|
||||
>
|
||||
<el-dropdown-item class="w-full">
|
||||
<div class="flex align-center w-full">
|
||||
<el-avatar shape="square" class="mt-4" :size="36" style="background: none">
|
||||
<img src="@/assets/icon_import.svg" alt="" />
|
||||
</el-avatar>
|
||||
<div class="pre-wrap ml-8">
|
||||
<div class="lighter">{{ $t('common.importCreate') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-upload>
|
||||
<el-dropdown-item @click="openToolStoreDialog()">
|
||||
<div class="flex align-center">
|
||||
<el-avatar class="avatar-green" shape="square" :size="32">
|
||||
<img src="@/assets/node/icon_tool.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<div class="pre-wrap ml-8">
|
||||
<div class="lighter">
|
||||
{{ $t('views.tool.toolStore.createFromToolStore') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="openCreateFolder" divided>
|
||||
<div class="flex align-center">
|
||||
<AppIcon iconName="app-folder" style="font-size: 32px"></AppIcon>
|
||||
<div class="pre-wrap ml-4">
|
||||
<div class="lighter">
|
||||
{{ $t('components.folder.addFolder') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-loading.fullscreen.lock="paginationConfig.current_page === 1 && loading"
|
||||
style="max-height: calc(100vh - 140px)"
|
||||
>
|
||||
<InfiniteScroll
|
||||
:size="tool.toolList.length"
|
||||
:total="paginationConfig.total"
|
||||
:page_size="paginationConfig.page_size"
|
||||
v-model:current_page="paginationConfig.current_page"
|
||||
@load="getList"
|
||||
:loading="loading"
|
||||
>
|
||||
<el-row v-if="tool.toolList.length > 0" :gutter="15">
|
||||
<template v-for="(item, index) in tool.toolList" :key="index">
|
||||
<el-col
|
||||
v-if="item.resource_type === 'folder'"
|
||||
:xs="24"
|
||||
:sm="12"
|
||||
:md="12"
|
||||
:lg="8"
|
||||
:xl="6"
|
||||
class="mb-16"
|
||||
>
|
||||
<CardBox
|
||||
:title="item.name"
|
||||
:description="item.desc || $t('common.noData')"
|
||||
class="cursor"
|
||||
@click="clickFolder(item)"
|
||||
>
|
||||
<template #icon>
|
||||
<el-avatar shape="square" :size="32" style="background: none">
|
||||
<AppIcon iconName="app-folder" style="font-size: 32px"></AppIcon>
|
||||
</el-avatar>
|
||||
</template>
|
||||
<template #subTitle>
|
||||
<el-text class="color-secondary lighter" size="small">
|
||||
{{ $t('common.creator') }}: {{ item.nick_name }}
|
||||
</el-text>
|
||||
</template>
|
||||
</CardBox>
|
||||
</el-col>
|
||||
<el-col v-else :xs="24" :sm="12" :md="12" :lg="8" :xl="6" class="mb-16">
|
||||
<CardBox
|
||||
:title="item.name"
|
||||
:description="item.desc"
|
||||
class="cursor"
|
||||
@click.stop="openCreateDialog(item)"
|
||||
:disabled="
|
||||
hasPermission(
|
||||
[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
RoleConst.USER.getWorkspaceRole,
|
||||
PermissionConst.TOOL_EDIT.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.TOOL_EDIT.getWorkspacePermission,
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
"
|
||||
>
|
||||
<template #icon>
|
||||
<el-avatar
|
||||
v-if="isAppIcon(item?.icon)"
|
||||
shape="square"
|
||||
:size="32"
|
||||
style="background: none"
|
||||
class="mr-8"
|
||||
>
|
||||
<img :src="item?.icon" alt="" />
|
||||
</el-avatar>
|
||||
<el-avatar v-else class="avatar-green" shape="square" :size="32">
|
||||
<img src="@/assets/node/icon_tool.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
</template>
|
||||
<template #subTitle>
|
||||
<el-text class="color-secondary lighter" size="small">
|
||||
{{ $t('common.creator') }}: {{ item.nick_name }}
|
||||
</el-text>
|
||||
</template>
|
||||
<template #tag>
|
||||
<el-tag v-if="isShared" type="info" class="info-tag">
|
||||
{{ t('views.system.shared.label') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div v-if="item.is_active" class="flex align-center">
|
||||
<el-icon class="color-success mr-8" style="font-size: 16px">
|
||||
<SuccessFilled />
|
||||
</el-icon>
|
||||
<span class="color-secondary">
|
||||
{{ $t('common.status.enabled') }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-else class="flex align-center">
|
||||
<AppIcon iconName="app-disabled" class="color-secondary mr-8"></AppIcon>
|
||||
<span class="color-secondary">
|
||||
{{ $t('common.status.disabled') }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #mouseEnter>
|
||||
<div @click.stop v-if="!isShared">
|
||||
<el-switch
|
||||
v-model="item.is_active"
|
||||
:before-change="() => changeState(item)"
|
||||
size="small"
|
||||
class="mr-4"
|
||||
v-if="permissionPrecise.switch()"
|
||||
/>
|
||||
<el-divider direction="vertical" />
|
||||
<el-dropdown trigger="click">
|
||||
<el-button text @click.stop>
|
||||
<el-icon>
|
||||
<MoreFilled />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-if="item.template_id"
|
||||
@click.stop="addInternalFunction(item, true)"
|
||||
>
|
||||
<el-icon>
|
||||
<EditPen />
|
||||
</el-icon>
|
||||
{{ $t('common.edit') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="!item.template_id && permissionPrecise.edit()"
|
||||
@click.stop="openCreateDialog(item)"
|
||||
>
|
||||
<el-icon>
|
||||
<EditPen />
|
||||
</el-icon>
|
||||
{{ $t('common.edit') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="!item.template_id && permissionPrecise.copy()"
|
||||
@click.stop="copyTool(item)"
|
||||
>
|
||||
<AppIcon iconName="app-copy"></AppIcon>
|
||||
{{ $t('common.copy') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="item.init_field_list?.length > 0"
|
||||
@click.stop="configInitParams(item)"
|
||||
>
|
||||
<AppIcon iconName="app-operation" class="mr-4"></AppIcon>
|
||||
{{ $t('common.param.initParam') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="!item.template_id && permissionPrecise.export()"
|
||||
@click.stop="exportTool(item)"
|
||||
>
|
||||
<AppIcon iconName="app-export"></AppIcon>
|
||||
{{ $t('common.export') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="permissionPrecise.delete()"
|
||||
divided
|
||||
@click.stop="deleteTool(item)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
{{ $t('common.delete') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</CardBox>
|
||||
</el-col>
|
||||
</template>
|
||||
</el-row>
|
||||
<el-empty :description="$t('common.noData')" v-else />
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</ContentContainer>
|
||||
<InitParamDrawer ref="InitParamDrawerRef" @refresh="refresh" />
|
||||
<ToolFormDrawer ref="ToolFormDrawerRef" @refresh="refresh" :title="ToolDrawertitle" />
|
||||
<CreateFolderDialog ref="CreateFolderDialogRef" v-if="!isShared" />
|
||||
<ToolStoreDialog ref="toolStoreDialogRef" @refresh="refresh" />
|
||||
<AddInternalFunctionDialog
|
||||
ref="addInternalFunctionDialogRef"
|
||||
@refresh="confirmAddInternalFunction"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, reactive, computed, watch } from 'vue'
|
||||
import { cloneDeep, get } from 'lodash'
|
||||
import ToolApi from '@/api/tool/tool'
|
||||
import { useRoute } from 'vue-router'
|
||||
import InitParamDrawer from '@/views/tool/component/InitParamDrawer.vue'
|
||||
import ToolFormDrawer from '@/views/tool/ToolFormDrawer.vue'
|
||||
import CreateFolderDialog from '@/components/folder-tree/CreateFolderDialog.vue'
|
||||
import { isAppIcon } from '@/utils/common'
|
||||
import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message'
|
||||
import { EditionConst, PermissionConst, RoleConst } from '@/utils/permission/data'
|
||||
import { hasPermission } from '@/utils/permission/index'
|
||||
import { FolderSource } from '@/enums/common'
|
||||
import ToolStoreDialog from '@/views/tool/component/ToolStoreDialog.vue'
|
||||
import AddInternalFunctionDialog from '@/views/tool/component/AddInternalFunctionDialog.vue'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
import permissionMap from '@/permission'
|
||||
import useStore from '@/stores'
|
||||
import { t } from '@/locales'
|
||||
const route = useRoute()
|
||||
const { folder, user, tool } = useStore()
|
||||
|
||||
const type = computed(() => {
|
||||
if (route.path.includes('shared')) {
|
||||
return 'systemShare'
|
||||
} else if (route.path.includes('resource-management')) {
|
||||
return 'systemManage'
|
||||
} else {
|
||||
return 'workspace'
|
||||
}
|
||||
})
|
||||
const permissionPrecise = computed(() => {
|
||||
return permissionMap['tool'][type.value]
|
||||
})
|
||||
|
||||
const InitParamDrawerRef = ref()
|
||||
const search_type = ref('name')
|
||||
const search_form = ref<{
|
||||
name: string
|
||||
create_user: string
|
||||
}>({
|
||||
name: '',
|
||||
create_user: '',
|
||||
})
|
||||
const user_options = ref<any[]>([])
|
||||
|
||||
const loading = ref(false)
|
||||
const changeStateloading = ref(false)
|
||||
const paginationConfig = reactive({
|
||||
current_page: 1,
|
||||
page_size: 30,
|
||||
total: 0,
|
||||
})
|
||||
|
||||
const currentFolder = ref<any>({})
|
||||
|
||||
const isShared = computed(() => {
|
||||
return folder.currentFolder.id === 'share'
|
||||
})
|
||||
|
||||
const search_type_change = () => {
|
||||
search_form.value = { name: '', create_user: '' }
|
||||
}
|
||||
const ToolFormDrawerRef = ref()
|
||||
const ToolDrawertitle = ref('')
|
||||
|
||||
function openCreateDialog(data?: any) {
|
||||
// 有template_id的不允许编辑,是模板转换来的
|
||||
if (data?.template_id) {
|
||||
return
|
||||
}
|
||||
ToolDrawertitle.value = data ? t('views.tool.editTool') : t('views.tool.createTool')
|
||||
if (data) {
|
||||
loadSharedApi({ type: 'tool', systemType: type.value })
|
||||
.getToolById(data?.id, loading)
|
||||
.then((res) => {
|
||||
ToolFormDrawerRef.value.open(res.data)
|
||||
})
|
||||
} else {
|
||||
ToolFormDrawerRef.value.open(data)
|
||||
}
|
||||
}
|
||||
|
||||
async function changeState(row: any) {
|
||||
if (row.is_active) {
|
||||
MsgConfirm(
|
||||
`${t('views.tool.disabled.confirmTitle')}${row.name} ?`,
|
||||
t('views.tool.disabled.confirmMessage'),
|
||||
{
|
||||
confirmButtonText: t('common.status.disable'),
|
||||
confirmButtonClass: 'danger',
|
||||
},
|
||||
).then(() => {
|
||||
const obj = {
|
||||
is_active: !row.is_active,
|
||||
}
|
||||
ToolApi.putTool(row.id, obj, changeStateloading)
|
||||
.then(() => {
|
||||
const list = cloneDeep(tool.toolList)
|
||||
const index = list.findIndex((v) => v.id === row.id)
|
||||
list[index].is_active = !row.is_active
|
||||
tool.setToolList(list)
|
||||
return true
|
||||
})
|
||||
.catch(() => {
|
||||
return false
|
||||
})
|
||||
})
|
||||
} else {
|
||||
const res = await loadSharedApi({ type: 'tool', systemType: type.value }).getToolById(
|
||||
row.id,
|
||||
changeStateloading,
|
||||
)
|
||||
if (
|
||||
!res.data.init_params &&
|
||||
res.data.init_field_list &&
|
||||
res.data.init_field_list.length > 0 &&
|
||||
res.data.init_field_list.filter((item: any) => item.default_value && item.show_default_value)
|
||||
.length !== res.data.init_field_list.length
|
||||
) {
|
||||
InitParamDrawerRef.value.open(res.data, !row.is_active)
|
||||
return false
|
||||
}
|
||||
const obj = {
|
||||
is_active: !row.is_active,
|
||||
}
|
||||
loadSharedApi({ type: 'tool', systemType: type.value })
|
||||
.putTool(row.id, obj, changeStateloading)
|
||||
.then(() => {
|
||||
const list = cloneDeep(tool.toolList)
|
||||
const index = list.findIndex((v) => v.id === row.id)
|
||||
list[index].is_active = !row.is_active
|
||||
tool.setToolList(list)
|
||||
return true
|
||||
})
|
||||
.catch(() => {
|
||||
return false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function refresh(data?: any) {
|
||||
if (data) {
|
||||
const list = cloneDeep(tool.toolList)
|
||||
const index = list.findIndex((v) => v.id === data.id)
|
||||
list.splice(index, 1, data)
|
||||
tool.setToolList(list)
|
||||
} else {
|
||||
paginationConfig.total = 0
|
||||
paginationConfig.current_page = 1
|
||||
tool.setToolList([])
|
||||
getList()
|
||||
}
|
||||
}
|
||||
|
||||
function copyTool(row: any) {
|
||||
ToolDrawertitle.value = t('views.tool.copyTool')
|
||||
const obj = cloneDeep(row)
|
||||
delete obj['id']
|
||||
obj['name'] = obj['name'] + ` ${t('views.tool.form.title.copy')}`
|
||||
ToolFormDrawerRef.value.open(obj)
|
||||
}
|
||||
|
||||
function exportTool(row: any) {
|
||||
loadSharedApi({ type: 'tool', systemType: type.value })
|
||||
.exportTool(row.id, row.name, loading)
|
||||
.catch((e: any) => {
|
||||
if (e.response.status !== 403) {
|
||||
e.response.data.text().then((res: string) => {
|
||||
MsgError(`${t('views.application.tip.ExportError')}:${JSON.parse(res).message}`)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function deleteTool(row: any) {
|
||||
MsgConfirm(
|
||||
`${t('views.tool.delete.confirmTitle')}${row.name} ?`,
|
||||
t('views.tool.delete.confirmMessage'),
|
||||
{
|
||||
confirmButtonText: t('common.confirm'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
confirmButtonClass: 'danger',
|
||||
},
|
||||
)
|
||||
.then(() => {
|
||||
loadSharedApi({ type: 'tool', systemType: type.value })
|
||||
.delTool(row.id, loading)
|
||||
.then(() => {
|
||||
const list = cloneDeep(tool.toolList)
|
||||
const index = list.findIndex((v) => v.id === row.id)
|
||||
list.splice(index, 1)
|
||||
tool.setToolList(list)
|
||||
MsgSuccess(t('common.deleteSuccess'))
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function configInitParams(item: any) {
|
||||
loadSharedApi({ type: 'tool', systemType: type.value })
|
||||
.getToolById(item?.id, changeStateloading)
|
||||
.then((res) => {
|
||||
InitParamDrawerRef.value.open(res.data)
|
||||
})
|
||||
}
|
||||
|
||||
const toolStoreDialogRef = ref<InstanceType<typeof ToolStoreDialog>>()
|
||||
function openToolStoreDialog() {
|
||||
toolStoreDialogRef.value?.open(currentFolder.value.id)
|
||||
}
|
||||
|
||||
const addInternalFunctionDialogRef = ref<InstanceType<typeof AddInternalFunctionDialog>>()
|
||||
function addInternalFunction(data?: any, isEdit?: boolean) {
|
||||
addInternalFunctionDialogRef.value?.open(data, isEdit)
|
||||
}
|
||||
|
||||
function confirmAddInternalFunction(data?: any, isEdit?: boolean) {
|
||||
if (isEdit) {
|
||||
loadSharedApi({ type: 'tool', systemType: type.value })
|
||||
.putTool(data?.id as string, { name: data.name }, loading)
|
||||
.then((res) => {
|
||||
MsgSuccess(t('common.saveSuccess'))
|
||||
refresh()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const elUploadRef = ref()
|
||||
function importTool(file: any) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file.raw, file.name)
|
||||
elUploadRef.value.clearFiles()
|
||||
loadSharedApi({ type: 'tool', systemType: type.value })
|
||||
.postImportTool(formData, loading)
|
||||
.then(async (res: any) => {
|
||||
if (res?.data) {
|
||||
tool.setToolList([])
|
||||
getList()
|
||||
}
|
||||
})
|
||||
.catch((e: any) => {
|
||||
if (e.code === 400) {
|
||||
MsgConfirm(t('common.tip'), t('views.application.tip.professionalMessage'), {
|
||||
cancelButtonText: t('common.confirm'),
|
||||
confirmButtonText: t('common.professional'),
|
||||
}).then(() => {
|
||||
window.open('https://maxkb.cn/pricing.html', '_blank')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 文件夹相关
|
||||
const CreateFolderDialogRef = ref()
|
||||
function openCreateFolder() {
|
||||
CreateFolderDialogRef.value.open(FolderSource.TOOL, folder.currentFolder.id)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => folder.currentFolder,
|
||||
(newValue) => {
|
||||
if (newValue && newValue.id) {
|
||||
tool.setToolList([])
|
||||
getList()
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
)
|
||||
function getList() {
|
||||
tool
|
||||
.asyncGetToolListPage(paginationConfig, isShared.value, type.value, loading)
|
||||
.then((res: any) => {
|
||||
paginationConfig.total = res.data?.total
|
||||
tool.setToolList([...tool.toolList, ...res.data?.records])
|
||||
})
|
||||
}
|
||||
|
||||
function clickFolder(item: any) {
|
||||
folder.setCurrentFolder(item)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (type.value !== 'workspace') {
|
||||
getList()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -8,321 +8,23 @@
|
||||
:currentNodeKey="currentFolder?.id"
|
||||
@handleNodeClick="folderClickHandel"
|
||||
@refreshTree="refreshFolder"
|
||||
:shareTitle="$t('views.system.share_tool')"
|
||||
:shareTitle="$t('views.system.shared.shared_tool')"
|
||||
:showShared="permissionPrecise['is_share']()"
|
||||
class="p-8"
|
||||
/>
|
||||
</template>
|
||||
<ContentContainer :header="currentFolder?.name">
|
||||
<template #search>
|
||||
<div class="flex">
|
||||
<div class="flex-between complex-search">
|
||||
<el-select
|
||||
class="complex-search__left"
|
||||
v-model="search_type"
|
||||
style="width: 120px"
|
||||
@change="search_type_change"
|
||||
>
|
||||
<el-option :label="$t('common.creator')" value="create_user" />
|
||||
|
||||
<el-option :label="$t('views.model.modelForm.modeName.label')" value="name" />
|
||||
</el-select>
|
||||
<el-input
|
||||
v-if="search_type === 'name'"
|
||||
v-model="search_form.name"
|
||||
@change="getList"
|
||||
:placeholder="$t('common.searchBar.placeholder')"
|
||||
style="width: 220px"
|
||||
clearable
|
||||
/>
|
||||
<el-select
|
||||
v-else-if="search_type === 'create_user'"
|
||||
v-model="search_form.create_user"
|
||||
@change="getList"
|
||||
clearable
|
||||
style="width: 220px"
|
||||
>
|
||||
<el-option v-for="u in user_options" :key="u.id" :value="u.id" :label="u.username" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-dropdown trigger="click" v-if="!isShared">
|
||||
<el-button
|
||||
type="primary"
|
||||
class="ml-8"
|
||||
v-if="permissionPrecise.create()"
|
||||
>
|
||||
{{ $t('common.create') }}
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="create-dropdown">
|
||||
<el-dropdown-item @click="openCreateDialog()">
|
||||
<div class="flex align-center">
|
||||
<el-avatar class="avatar-green" shape="square" :size="32">
|
||||
<img src="@/assets/node/icon_tool.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<div class="pre-wrap ml-8">
|
||||
<div class="lighter">空白创建</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
<el-upload
|
||||
ref="elUploadRef"
|
||||
:file-list="[]"
|
||||
action="#"
|
||||
multiple
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:limit="1"
|
||||
:on-change="(file: any, fileList: any) => importTool(file)"
|
||||
class="import-button"
|
||||
>
|
||||
<el-dropdown-item class="w-full">
|
||||
<div class="flex align-center w-full">
|
||||
<el-avatar shape="square" class="mt-4" :size="36" style="background: none">
|
||||
<img src="@/assets/icon_import.svg" alt="" />
|
||||
</el-avatar>
|
||||
<div class="pre-wrap ml-8">
|
||||
<div class="lighter">{{ $t('common.importCreate') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-upload>
|
||||
<el-dropdown-item @click="openToolStoreDialog()">
|
||||
<div class="flex align-center">
|
||||
<el-avatar class="avatar-green" shape="square" :size="32">
|
||||
<img src="@/assets/node/icon_tool.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<div class="pre-wrap ml-8">
|
||||
<div class="lighter">
|
||||
{{ $t('views.tool.toolStore.createFromToolStore') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="openCreateFolder" divided>
|
||||
<div class="flex align-center">
|
||||
<AppIcon iconName="app-folder" style="font-size: 32px"></AppIcon>
|
||||
<div class="pre-wrap ml-4">
|
||||
<div class="lighter">
|
||||
{{ $t('components.folder.addFolder') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<ToolListContainer>
|
||||
<template #header>
|
||||
<FolderBreadcrumb :folderList="folderList" @click="folderClickHandel" />
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-loading.fullscreen.lock="paginationConfig.current_page === 1 && loading"
|
||||
style="max-height: calc(100vh - 140px)"
|
||||
>
|
||||
<InfiniteScroll
|
||||
:size="toolList.length"
|
||||
:total="paginationConfig.total"
|
||||
:page_size="paginationConfig.page_size"
|
||||
v-model:current_page="paginationConfig.current_page"
|
||||
@load="getList"
|
||||
:loading="loading"
|
||||
>
|
||||
<el-row v-if="toolList.length > 0" :gutter="15">
|
||||
<template v-for="(item, index) in toolList" :key="index">
|
||||
<el-col
|
||||
v-if="item.resource_type === 'folder'"
|
||||
:xs="24"
|
||||
:sm="12"
|
||||
:md="12"
|
||||
:lg="8"
|
||||
:xl="6"
|
||||
class="mb-16"
|
||||
>
|
||||
<CardBox
|
||||
:title="item.name"
|
||||
:description="item.desc || $t('common.noData')"
|
||||
class="cursor"
|
||||
@click="clickFolder(item)"
|
||||
>
|
||||
<template #icon>
|
||||
<el-avatar shape="square" :size="32" style="background: none">
|
||||
<AppIcon iconName="app-folder" style="font-size: 32px"></AppIcon>
|
||||
</el-avatar>
|
||||
</template>
|
||||
<template #subTitle>
|
||||
<el-text class="color-secondary lighter" size="small">
|
||||
{{ $t('common.creator') }}: {{ item.nick_name }}
|
||||
</el-text>
|
||||
</template>
|
||||
</CardBox>
|
||||
</el-col>
|
||||
<el-col v-else :xs="24" :sm="12" :md="12" :lg="8" :xl="6" class="mb-16">
|
||||
<CardBox
|
||||
:title="item.name"
|
||||
:description="item.desc"
|
||||
class="cursor"
|
||||
@click.stop="openCreateDialog(item)"
|
||||
:disabled="
|
||||
hasPermission(
|
||||
[
|
||||
RoleConst.WORKSPACE_MANAGE.getWorkspaceRole,
|
||||
RoleConst.USER.getWorkspaceRole,
|
||||
PermissionConst.TOOL_EDIT.getWorkspacePermissionWorkspaceManageRole,
|
||||
PermissionConst.TOOL_EDIT.getWorkspacePermission,
|
||||
],
|
||||
'OR',
|
||||
)
|
||||
"
|
||||
>
|
||||
<template #icon>
|
||||
<el-avatar
|
||||
v-if="isAppIcon(item?.icon)"
|
||||
shape="square"
|
||||
:size="32"
|
||||
style="background: none"
|
||||
class="mr-8"
|
||||
>
|
||||
<img :src="item?.icon" alt="" />
|
||||
</el-avatar>
|
||||
<el-avatar v-else class="avatar-green" shape="square" :size="32">
|
||||
<img src="@/assets/node/icon_tool.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
</template>
|
||||
<template #subTitle>
|
||||
<el-text class="color-secondary lighter" size="small">
|
||||
{{ $t('common.creator') }}: {{ item.nick_name }}
|
||||
</el-text>
|
||||
</template>
|
||||
<template #tag>
|
||||
<el-tag v-if="isShared" type="info" class="info-tag">
|
||||
{{ t('views.system.shared') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div v-if="item.is_active" class="flex align-center">
|
||||
<el-icon class="color-success mr-8" style="font-size: 16px">
|
||||
<SuccessFilled />
|
||||
</el-icon>
|
||||
<span class="color-secondary">
|
||||
{{ $t('common.status.enabled') }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-else class="flex align-center">
|
||||
<AppIcon iconName="app-disabled" class="color-secondary mr-8"></AppIcon>
|
||||
<span class="color-secondary">
|
||||
{{ $t('common.status.disabled') }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #mouseEnter>
|
||||
<div @click.stop v-if="!isShared">
|
||||
<el-switch
|
||||
v-model="item.is_active"
|
||||
:before-change="() => changeState(item)"
|
||||
size="small"
|
||||
class="mr-4"
|
||||
v-if="permissionPrecise.switch()"
|
||||
/>
|
||||
<el-divider direction="vertical" />
|
||||
<el-dropdown trigger="click">
|
||||
<el-button text @click.stop>
|
||||
<el-icon>
|
||||
<MoreFilled />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-if="item.template_id" @click.stop="addInternalFunction(item, true)">
|
||||
<el-icon>
|
||||
<EditPen />
|
||||
</el-icon>
|
||||
{{ $t('common.edit') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="
|
||||
!item.template_id &&
|
||||
permissionPrecise.edit()
|
||||
"
|
||||
@click.stop="openCreateDialog(item)"
|
||||
>
|
||||
<el-icon>
|
||||
<EditPen />
|
||||
</el-icon>
|
||||
{{ $t('common.edit') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="
|
||||
!item.template_id &&
|
||||
permissionPrecise.copy()
|
||||
"
|
||||
@click.stop="copyTool(item)"
|
||||
>
|
||||
<AppIcon iconName="app-copy"></AppIcon>
|
||||
{{ $t('common.copy') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="item.init_field_list?.length > 0"
|
||||
@click.stop="configInitParams(item)"
|
||||
>
|
||||
<AppIcon iconName="app-operation" class="mr-4"></AppIcon>
|
||||
{{ $t('common.param.initParam') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="
|
||||
!item.template_id &&
|
||||
permissionPrecise.export()
|
||||
"
|
||||
@click.stop="exportTool(item)"
|
||||
>
|
||||
<AppIcon iconName="app-export"></AppIcon>
|
||||
{{ $t('common.export') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="permissionPrecise.delete()"
|
||||
divided
|
||||
@click.stop="deleteTool(item)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
{{ $t('common.delete') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</CardBox>
|
||||
</el-col>
|
||||
</template>
|
||||
</el-row>
|
||||
<el-empty :description="$t('common.noData')" v-else />
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</ContentContainer>
|
||||
<InitParamDrawer ref="InitParamDrawerRef" @refresh="refresh" />
|
||||
<ToolFormDrawer ref="ToolFormDrawerRef" @refresh="refresh" :title="ToolDrawertitle" />
|
||||
<CreateFolderDialog ref="CreateFolderDialogRef" @refresh="refreshFolder" v-if="!isShared" />
|
||||
<ToolStoreDialog ref="toolStoreDialogRef" @refresh="refresh" />
|
||||
<AddInternalFunctionDialog ref="addInternalFunctionDialogRef" @refresh="confirmAddInternalFunction" />
|
||||
</ToolListContainer>
|
||||
</LayoutContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, reactive, computed } from 'vue'
|
||||
import { cloneDeep, get } from 'lodash'
|
||||
import ToolApi from '@/api/tool/tool'
|
||||
import useStore from '@/stores'
|
||||
import InitParamDrawer from '@/views/tool/component/InitParamDrawer.vue'
|
||||
import ToolFormDrawer from './ToolFormDrawer.vue'
|
||||
import ToolListContainer from '@/views/tool/component/ToolListContainer.vue'
|
||||
import CreateFolderDialog from '@/components/folder-tree/CreateFolderDialog.vue'
|
||||
import { t } from '@/locales'
|
||||
import { isAppIcon } from '@/utils/common'
|
||||
import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message'
|
||||
import { EditionConst, PermissionConst, RoleConst } from '@/utils/permission/data'
|
||||
import { hasPermission } from '@/utils/permission/index'
|
||||
import { FolderSource } from '@/enums/common'
|
||||
import { ComplexPermission } from '@/utils/permission/type'
|
||||
import ToolStoreDialog from './toolStore/ToolStoreDialog.vue'
|
||||
@ -330,8 +32,9 @@ import AddInternalFunctionDialog from './toolStore/AddInternalFunctionDialog.vue
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
import permissionMap from '@/permission'
|
||||
import { useRoute } from 'vue-router'
|
||||
import useStore from '@/stores'
|
||||
const route = useRoute()
|
||||
const { folder, user } = useStore()
|
||||
const { folder, tool } = useStore()
|
||||
|
||||
const type = computed(() => {
|
||||
if (route.path.includes('shared')) {
|
||||
@ -346,231 +49,11 @@ const permissionPrecise = computed(() => {
|
||||
return permissionMap['tool'][type.value]
|
||||
})
|
||||
|
||||
const InitParamDrawerRef = ref()
|
||||
const search_type = ref('name')
|
||||
const search_form = ref<{
|
||||
name: string
|
||||
create_user: string
|
||||
}>({
|
||||
name: '',
|
||||
create_user: '',
|
||||
})
|
||||
const user_options = ref<any[]>([])
|
||||
|
||||
const loading = ref(false)
|
||||
const changeStateloading = ref(false)
|
||||
const paginationConfig = reactive({
|
||||
current_page: 1,
|
||||
page_size: 30,
|
||||
total: 0,
|
||||
})
|
||||
|
||||
const folderList = ref<any[]>([])
|
||||
const toolList = ref<any[]>([])
|
||||
const currentFolder = ref<any>({})
|
||||
|
||||
const isShared = computed(() => {
|
||||
return currentFolder.value.id === 'share'
|
||||
})
|
||||
|
||||
const search_type_change = () => {
|
||||
search_form.value = { name: '', create_user: '' }
|
||||
}
|
||||
const ToolFormDrawerRef = ref()
|
||||
const ToolDrawertitle = ref('')
|
||||
|
||||
function openCreateDialog(data?: any) {
|
||||
// 有template_id的不允许编辑,是模板转换来的
|
||||
if (data?.template_id) {
|
||||
return
|
||||
}
|
||||
ToolDrawertitle.value = data ? t('views.tool.editTool') : t('views.tool.createTool')
|
||||
if (data) {
|
||||
ToolApi.getToolById(data?.id, loading).then((res) => {
|
||||
ToolFormDrawerRef.value.open(res.data)
|
||||
})
|
||||
} else {
|
||||
ToolFormDrawerRef.value.open(data)
|
||||
}
|
||||
}
|
||||
|
||||
function getList() {
|
||||
const params = {
|
||||
folder_id: currentFolder.value?.id || user.getWorkspaceId(),
|
||||
scope: 'WORKSPACE',
|
||||
}
|
||||
loadSharedApi('tool', isShared.value)
|
||||
.getToolListPage(paginationConfig, params, loading)
|
||||
.then((res: any) => {
|
||||
paginationConfig.total = res.data?.total
|
||||
toolList.value = [...toolList.value, ...res.data?.records]
|
||||
})
|
||||
}
|
||||
|
||||
function clickFolder(item: any) {
|
||||
currentFolder.value.id = item.id
|
||||
toolList.value = []
|
||||
getList()
|
||||
}
|
||||
async function changeState(row: any) {
|
||||
if (row.is_active) {
|
||||
MsgConfirm(
|
||||
`${t('views.tool.disabled.confirmTitle')}${row.name} ?`,
|
||||
t('views.tool.disabled.confirmMessage'),
|
||||
{
|
||||
confirmButtonText: t('common.status.disable'),
|
||||
confirmButtonClass: 'danger',
|
||||
},
|
||||
).then(() => {
|
||||
const obj = {
|
||||
is_active: !row.is_active,
|
||||
}
|
||||
ToolApi.putTool(row.id, obj, changeStateloading)
|
||||
.then(() => {
|
||||
const index = toolList.value.findIndex((v) => v.id === row.id)
|
||||
toolList.value[index].is_active = !row.is_active
|
||||
return true
|
||||
})
|
||||
.catch(() => {
|
||||
return false
|
||||
})
|
||||
})
|
||||
} else {
|
||||
const res = await ToolApi.getToolById(row.id, changeStateloading)
|
||||
if (
|
||||
(!res.data.init_params || Object.keys(res.data.init_params).length === 0) &&
|
||||
res.data.init_field_list &&
|
||||
res.data.init_field_list.length > 0 &&
|
||||
res.data.init_field_list.filter((item: any) => item.default_value && item.show_default_value)
|
||||
.length !== res.data.init_field_list.length
|
||||
) {
|
||||
InitParamDrawerRef.value.open(res.data, !row.is_active)
|
||||
return false
|
||||
}
|
||||
const obj = {
|
||||
is_active: !row.is_active,
|
||||
}
|
||||
ToolApi.putTool(row.id, obj, changeStateloading)
|
||||
.then(() => {
|
||||
const index = toolList.value.findIndex((v) => v.id === row.id)
|
||||
toolList.value[index].is_active = !row.is_active
|
||||
return true
|
||||
})
|
||||
.catch(() => {
|
||||
return false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function refresh(data?: any) {
|
||||
if (data) {
|
||||
const index = toolList.value.findIndex((v) => v.id === data.id)
|
||||
// if (user.userInfo && data.user_id === user.userInfo.id) {
|
||||
// data.username = user.userInfo.username
|
||||
// } else {
|
||||
// data.username = userOptions.value.find((v) => v.value === data.user_id)?.label
|
||||
// }
|
||||
toolList.value.splice(index, 1, data)
|
||||
}
|
||||
paginationConfig.total = 0
|
||||
paginationConfig.current_page = 1
|
||||
toolList.value = []
|
||||
getList()
|
||||
}
|
||||
|
||||
async function copyTool(row: any) {
|
||||
ToolDrawertitle.value = t('views.tool.copyTool')
|
||||
const res = await ToolApi.getToolById(row.id, changeStateloading)
|
||||
const obj = cloneDeep(res.data)
|
||||
delete obj['id']
|
||||
obj['name'] = obj['name'] + ` ${t('views.tool.form.title.copy')}`
|
||||
ToolFormDrawerRef.value.open(obj)
|
||||
}
|
||||
|
||||
function exportTool(row: any) {
|
||||
ToolApi.exportTool(row.id, row.name, loading).catch((e: any) => {
|
||||
if (e.response.status !== 403) {
|
||||
e.response.data.text().then((res: string) => {
|
||||
MsgError(`${t('views.application.tip.ExportError')}:${JSON.parse(res).message}`)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function deleteTool(row: any) {
|
||||
MsgConfirm(
|
||||
`${t('views.tool.delete.confirmTitle')}${row.name} ?`,
|
||||
t('views.tool.delete.confirmMessage'),
|
||||
{
|
||||
confirmButtonText: t('common.confirm'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
confirmButtonClass: 'danger',
|
||||
},
|
||||
)
|
||||
.then(() => {
|
||||
ToolApi.delTool(row.id, loading).then(() => {
|
||||
const index = toolList.value.findIndex((v) => v.id === row.id)
|
||||
toolList.value.splice(index, 1)
|
||||
MsgSuccess(t('common.deleteSuccess'))
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
function configInitParams(item: any) {
|
||||
ToolApi.getToolById(item?.id, changeStateloading).then((res) => {
|
||||
InitParamDrawerRef.value.open(res.data)
|
||||
})
|
||||
}
|
||||
|
||||
const toolStoreDialogRef = ref<InstanceType<typeof ToolStoreDialog>>()
|
||||
function openToolStoreDialog() {
|
||||
toolStoreDialogRef.value?.open(currentFolder.value.id)
|
||||
}
|
||||
|
||||
const addInternalFunctionDialogRef = ref<InstanceType<typeof AddInternalFunctionDialog>>()
|
||||
function addInternalFunction(data?: any, isEdit?: boolean) {
|
||||
addInternalFunctionDialogRef.value?.open(data, isEdit)
|
||||
}
|
||||
|
||||
function confirmAddInternalFunction(data?: any, isEdit?: boolean) {
|
||||
if (isEdit) {
|
||||
ToolApi.putTool(data?.id as string, { name: data.name }, loading).then((res) => {
|
||||
MsgSuccess(t('common.saveSuccess'))
|
||||
refresh()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const elUploadRef = ref()
|
||||
function importTool(file: any) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file.raw, file.name)
|
||||
elUploadRef.value.clearFiles()
|
||||
ToolApi.postImportTool(formData, loading)
|
||||
.then(async (res: any) => {
|
||||
if (res?.data) {
|
||||
toolList.value = []
|
||||
getList()
|
||||
}
|
||||
})
|
||||
.catch((e: any) => {
|
||||
if (e.code === 400) {
|
||||
MsgConfirm(t('common.tip'), t('views.application.tip.professionalMessage'), {
|
||||
cancelButtonText: t('common.confirm'),
|
||||
confirmButtonText: t('common.professional'),
|
||||
}).then(() => {
|
||||
window.open('https://maxkb.cn/pricing.html', '_blank')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 文件夹相关
|
||||
const CreateFolderDialogRef = ref()
|
||||
function openCreateFolder() {
|
||||
CreateFolderDialogRef.value.open(FolderSource.TOOL, currentFolder.value.id)
|
||||
}
|
||||
function getFolder(bool?: boolean) {
|
||||
const params = {}
|
||||
folder.asyncGetFolder(FolderSource.TOOL, params, loading).then((res: any) => {
|
||||
@ -578,19 +61,19 @@ function getFolder(bool?: boolean) {
|
||||
if (bool) {
|
||||
// 初始化刷新
|
||||
currentFolder.value = res.data?.[0] || {}
|
||||
folder.setCurrentFolder(currentFolder.value)
|
||||
}
|
||||
getList()
|
||||
})
|
||||
}
|
||||
function refreshFolder() {
|
||||
toolList.value = []
|
||||
getFolder()
|
||||
}
|
||||
|
||||
function folderClickHandel(row: any) {
|
||||
currentFolder.value = row
|
||||
toolList.value = []
|
||||
getList()
|
||||
folder.setCurrentFolder(currentFolder.value)
|
||||
tool.setToolList([])
|
||||
}
|
||||
|
||||
function refreshFolder() {
|
||||
getFolder()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@ -17,7 +17,7 @@ export default defineConfig(({ mode }) => {
|
||||
const prefix = process.env.VITE_DYNAMIC_PREFIX || ENV.VITE_BASE_PATH
|
||||
const proxyConf: Record<string, string | ProxyOptions> = {}
|
||||
proxyConf['/api'] = {
|
||||
// target: 'http://43.166.1.146:8080',
|
||||
// target: 'http://47.92.195.88:8080',
|
||||
target: 'http://127.0.0.1:8080',
|
||||
changeOrigin: true,
|
||||
rewrite: (path: string) => path.replace(ENV.VITE_BASE_PATH, '/'),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user