mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: add Data Source tool functionality and localization
This commit is contained in:
parent
39fd3657dd
commit
18194cc06b
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.2.8 on 2025-11-17 07:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tools', '0003_alter_tool_template_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tool',
|
||||
name='tool_type',
|
||||
field=models.CharField(choices=[('INTERNAL', '内置'), ('CUSTOM', '自定义'), ('MCP', 'MCP工具'), ('DATA_SOURCE', '数据源')], db_index=True, default='CUSTOM', max_length=20, verbose_name='工具类型'),
|
||||
),
|
||||
]
|
||||
|
|
@ -32,6 +32,7 @@ class ToolType(models.TextChoices):
|
|||
INTERNAL = "INTERNAL", '内置'
|
||||
CUSTOM = "CUSTOM", "自定义"
|
||||
MCP = "MCP", "MCP工具"
|
||||
DATA_SOURCE = "DATA_SOURCE", "数据源"
|
||||
|
||||
|
||||
class Tool(AppModelMixin):
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ export default {
|
|||
createTool: 'Create Tool',
|
||||
editTool: 'Edit Tool',
|
||||
createMcpTool: 'Create MCP',
|
||||
createDataSourceTool: 'Create Data Source',
|
||||
dataSource: 'Data Source',
|
||||
editDataSourceTool: 'Edit Data Source',
|
||||
editMcpTool: 'Edit MCP',
|
||||
copyTool: 'Copy Tool',
|
||||
importTool: 'Import Tool',
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ export default {
|
|||
createTool: '创建工具',
|
||||
editTool: '编辑工具',
|
||||
createMcpTool: '创建MCP',
|
||||
createDataSourceTool: '创建数据源',
|
||||
dataSource: '数据源',
|
||||
editDataSourceTool: '编辑数据源',
|
||||
editMcpTool: '编辑MCP',
|
||||
copyTool: '复制工具',
|
||||
importTool: '导入工具',
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ export default {
|
|||
createTool: '建立工具',
|
||||
editTool: '編輯工具',
|
||||
createMcpTool: '建立MCP',
|
||||
createDataSourceTool: '建立資料來源',
|
||||
dataSource: '資料來源',
|
||||
editDataSourceTool: '編輯資料來源',
|
||||
editMcpTool: '編輯MCP',
|
||||
copyTool: '複製工具',
|
||||
importTool: '匯入工具',
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@
|
|||
<el-table-column prop="tool_type" :label="$t('views.system.resource_management.type')">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.tool_type === 'MCP'"> MCP </span>
|
||||
<span v-else-if="scope.row.tool_type === 'DATA_SOURCE'"> {{ $t('views.tool.dataSource') }} </span>
|
||||
<span v-else-if="scope.row.version">{{ $t('views.tool.toolStore.title') }}</span>
|
||||
<span v-else>
|
||||
{{
|
||||
|
|
@ -248,6 +249,23 @@
|
|||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('common.edit')"
|
||||
placement="top"
|
||||
v-if="!row.template_id && row.tool_type === 'DATA_SOURCE' && permissionPrecise.edit()"
|
||||
>
|
||||
<span class="mr-8">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
@click.stop="openCreateDataSourceDialog(row)"
|
||||
:title="$t('common.edit')"
|
||||
>
|
||||
<AppIcon iconName="app-edit"></AppIcon>
|
||||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
|
|
@ -323,6 +341,7 @@
|
|||
<InitParamDrawer ref="InitParamDrawerRef" @refresh="refresh" />
|
||||
<ToolFormDrawer ref="ToolFormDrawerRef" @refresh="refresh" :title="ToolDrawertitle" />
|
||||
<McpToolFormDrawer ref="McpToolFormDrawerRef" @refresh="refresh" :title="McpToolDrawertitle" />
|
||||
<DataSourceToolFormDrawer ref="DataSourceToolFormDrawerRef" @refresh="refresh" :title="DataSourceToolDrawertitle" />
|
||||
<AddInternalToolDialog ref="AddInternalToolDialogRef" @refresh="confirmAddInternalTool" />
|
||||
<McpToolConfigDialog ref="McpToolConfigDialogRef" @refresh="refresh" />
|
||||
<ResourceAuthorizationDrawer :type="SourceTypeEnum.TOOL" ref="ResourceAuthorizationDrawerRef" />
|
||||
|
|
@ -337,6 +356,7 @@ import ToolResourceApi from '@/api/system-resource-management/tool'
|
|||
import AddInternalToolDialog from '@/views/tool/toolStore/AddInternalToolDialog.vue'
|
||||
import ToolFormDrawer from '@/views/tool/ToolFormDrawer.vue'
|
||||
import McpToolFormDrawer from '@/views/tool/McpToolFormDrawer.vue'
|
||||
import DataSourceToolFormDrawer from '@/views/tool/DataSourceToolFormDrawer.vue'
|
||||
import ResourceAuthorizationDrawer from '@/components/resource-authorization-drawer/index.vue'
|
||||
import { t } from '@/locales'
|
||||
import { SourceTypeEnum } from '@/enums/common'
|
||||
|
|
@ -460,8 +480,10 @@ async function copyTool(row: any) {
|
|||
|
||||
const ToolFormDrawerRef = ref()
|
||||
const McpToolFormDrawerRef = ref()
|
||||
const DataSourceToolFormDrawerRef = ref()
|
||||
const ToolDrawertitle = ref('')
|
||||
const McpToolDrawertitle = ref('')
|
||||
const DataSourceToolDrawertitle = ref('')
|
||||
|
||||
function openCreateDialog(data?: any) {
|
||||
// 有template_id的不允许编辑,是模板转换来的
|
||||
|
|
@ -495,6 +517,22 @@ function openCreateMcpDialog(data?: any) {
|
|||
}
|
||||
}
|
||||
|
||||
function openCreateDataSourceDialog(data?: any) {
|
||||
// 有template_id的不允许编辑,是模板转换来的
|
||||
if (data?.template_id) {
|
||||
return
|
||||
}
|
||||
|
||||
DataSourceToolDrawertitle.value = data ? t('views.tool.editDataSourceTool') : t('views.tool.createDataSourceTool')
|
||||
if (data) {
|
||||
ToolResourceApi.getToolById(data?.id, loading).then((res: any) => {
|
||||
DataSourceToolFormDrawerRef.value.open(res.data)
|
||||
})
|
||||
} else {
|
||||
DataSourceToolFormDrawerRef.value.open(data)
|
||||
}
|
||||
}
|
||||
|
||||
const AddInternalToolDialogRef = ref<InstanceType<typeof AddInternalToolDialog>>()
|
||||
function addInternalTool(data?: any, isEdit?: boolean) {
|
||||
AddInternalToolDialogRef.value?.open(data, isEdit)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
<el-radio-button value="">{{ $t('views.tool.all') }}</el-radio-button>
|
||||
<el-radio-button value="CUSTOM">{{ $t('views.tool.title') }}</el-radio-button>
|
||||
<el-radio-button value="MCP">MCP</el-radio-button>
|
||||
<el-radio-button value="DATA_SOURCE">{{ $t('views.tool.dataSource') }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-space>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,456 @@
|
|||
<template>
|
||||
<el-drawer v-model="visible" size="60%" :before-close="close">
|
||||
<template #header>
|
||||
<h4>{{ title }}</h4>
|
||||
</template>
|
||||
<div>
|
||||
<h4 class="title-decoration-1 mb-16">
|
||||
{{ $t('views.model.modelForm.title.baseInfo') }}
|
||||
</h4>
|
||||
<el-form
|
||||
ref="FormRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
v-loading="loading"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item :label="$t('views.tool.form.toolName.label')" prop="name">
|
||||
<div class="flex w-full">
|
||||
<div
|
||||
v-if="form.id"
|
||||
class="edit-avatar mr-12"
|
||||
@mouseenter="showEditIcon = true"
|
||||
@mouseleave="showEditIcon = false"
|
||||
>
|
||||
<el-Avatar
|
||||
v-if="isAppIcon(form.icon)"
|
||||
:id="form.id"
|
||||
shape="square"
|
||||
:size="32"
|
||||
style="background: none"
|
||||
>
|
||||
<img :src="String(form.icon)" alt="" />
|
||||
</el-Avatar>
|
||||
<el-avatar v-else class="avatar-green" shape="square" :size="32">
|
||||
<img src="@/assets/workflow/icon_tool.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<el-Avatar
|
||||
v-if="showEditIcon"
|
||||
:id="form.id"
|
||||
shape="square"
|
||||
class="edit-mask"
|
||||
:size="32"
|
||||
@click="openEditAvatar"
|
||||
>
|
||||
<AppIcon iconName="app-edit"></AppIcon>
|
||||
</el-Avatar>
|
||||
</div>
|
||||
<el-avatar v-else class="avatar-green mr-12" shape="square" :size="32">
|
||||
<img src="@/assets/workflow/icon_tool.svg" style="width: 58%" alt="" />
|
||||
</el-avatar>
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
:placeholder="$t('views.tool.form.toolName.placeholder')"
|
||||
maxlength="64"
|
||||
show-word-limit
|
||||
@blur="form.name = form.name?.trim()"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('common.desc')">
|
||||
<el-input
|
||||
v-model="form.desc"
|
||||
type="textarea"
|
||||
:placeholder="$t('views.tool.form.toolDescription.placeholder')"
|
||||
maxlength="128"
|
||||
show-word-limit
|
||||
:autosize="{ minRows: 3 }"
|
||||
@blur="form.desc = form.desc?.trim()"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="flex-between">
|
||||
<h4 class="title-decoration-1 mb-16">
|
||||
{{ $t('common.param.initParam') }}
|
||||
</h4>
|
||||
<el-button link type="primary" @click="openAddInitDialog()">
|
||||
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
|
||||
{{ $t('common.add') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table ref="initFieldTableRef" :data="form.init_field_list" class="mb-16">
|
||||
<el-table-column prop="field" :label="$t('dynamicsForm.paramForm.field.label')">
|
||||
<template #default="{ row }">
|
||||
<span :title="row.field" class="ellipsis-1">{{ row.field }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('dynamicsForm.paramForm.input_type.label')">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="info" class="info-tag" v-if="row.input_type === 'TextInput'"
|
||||
>{{ $t('dynamicsForm.input_type_list.TextInput') }}
|
||||
</el-tag>
|
||||
<el-tag type="info" class="info-tag" v-if="row.input_type === 'PasswordInput'"
|
||||
>{{ $t('dynamicsForm.input_type_list.PasswordInput') }}
|
||||
</el-tag>
|
||||
<el-tag type="info" class="info-tag" v-if="row.input_type === 'Slider'"
|
||||
>{{ $t('dynamicsForm.input_type_list.Slider') }}
|
||||
</el-tag>
|
||||
<el-tag type="info" class="info-tag" v-if="row.input_type === 'SwitchInput'"
|
||||
>{{ $t('dynamicsForm.input_type_list.SwitchInput') }}
|
||||
</el-tag>
|
||||
<el-tag type="info" class="info-tag" v-if="row.input_type === 'SingleSelect'"
|
||||
>{{ $t('dynamicsForm.input_type_list.SingleSelect') }}
|
||||
</el-tag>
|
||||
<el-tag type="info" class="info-tag" v-if="row.input_type === 'MultiSelect'"
|
||||
>{{ $t('dynamicsForm.input_type_list.MultiSelect') }}
|
||||
</el-tag>
|
||||
<el-tag type="info" class="info-tag" v-if="row.input_type === 'RadioCard'"
|
||||
>{{ $t('dynamicsForm.input_type_list.RadioCard') }}
|
||||
</el-tag>
|
||||
<el-tag type="info" class="info-tag" v-if="row.input_type === 'DatePicker'"
|
||||
>{{ $t('dynamicsForm.input_type_list.DatePicker') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.required')">
|
||||
<template #default="{ row }">
|
||||
<div @click.stop>
|
||||
<el-switch disabled size="small" v-model="row.required" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.operation')" align="left" width="90">
|
||||
<template #default="{ row, $index }">
|
||||
<span class="mr-4">
|
||||
<el-tooltip effect="dark" :content="$t('common.modify')" placement="top">
|
||||
<el-button type="primary" text @click.stop="openAddInitDialog(row, $index)">
|
||||
<AppIcon iconName="app-edit"></AppIcon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
||||
<el-button type="primary" text @click="deleteInitField($index)">
|
||||
<AppIcon iconName="app-delete"></AppIcon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex-between">
|
||||
<h4 class="title-decoration-1 mb-16">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
<el-text type="info" class="color-secondary">
|
||||
{{ $t('views.tool.form.param.paramInfo1') }}
|
||||
</el-text>
|
||||
</h4>
|
||||
<el-button link type="primary" @click="openAddDialog()">
|
||||
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
|
||||
{{ $t('common.add') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table ref="inputFieldTableRef" :data="form.input_field_list" class="mb-16">
|
||||
<el-table-column prop="name" :label="$t('views.tool.form.paramName.label')" />
|
||||
<el-table-column :label="$t('views.tool.form.dataType.label')">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="info" class="info-tag">{{ row.type }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.required')">
|
||||
<template #default="{ row }">
|
||||
<div @click.stop>
|
||||
<el-switch size="small" v-model="row.is_required" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="source" :label="$t('views.tool.form.source.label')">
|
||||
<template #default="{ row }">
|
||||
{{
|
||||
row.source === 'custom' ? $t('common.custom') : $t('views.tool.form.source.reference')
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.operation')" align="left" width="90">
|
||||
<template #default="{ row, $index }">
|
||||
<span class="mr-4">
|
||||
<el-tooltip effect="dark" :content="$t('common.modify')" placement="top">
|
||||
<el-button type="primary" text @click.stop="openAddDialog(row, $index)">
|
||||
<AppIcon iconName="app-edit"></AppIcon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
||||
<el-button type="primary" text @click="deleteField($index)">
|
||||
<AppIcon iconName="app-delete"></AppIcon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<h4 class="title-decoration-1 mb-16">
|
||||
{{ $t('views.tool.form.param.code') }}
|
||||
<span class="color-danger" style="margin-left: -10px">*</span>
|
||||
<el-text type="info" class="color-secondary">
|
||||
{{ $t('views.tool.form.param.paramInfo2') }}
|
||||
</el-text>
|
||||
</h4>
|
||||
|
||||
<div class="mb-8" v-if="showEditor">
|
||||
<CodemirrorEditor
|
||||
:title="$t('views.tool.form.param.code')"
|
||||
v-model="form.code"
|
||||
@submitDialog="submitCodemirrorEditor"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div>
|
||||
<el-button :loading="loading" @click="visible = false">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="submit(FormRef)"
|
||||
:loading="loading"
|
||||
v-if="isEdit ? permissionPrecise.edit(form?.id as string) : permissionPrecise.create()"
|
||||
>
|
||||
{{ isEdit ? $t('common.save') : $t('common.create') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<FieldFormDialog ref="FieldFormDialogRef" @refresh="refreshFieldList" />
|
||||
<UserFieldFormDialog ref="UserFieldFormDialogRef" @refresh="refreshInitFieldList" />
|
||||
<EditAvatarDialog ref="EditAvatarDialogRef" @refresh="refreshTool" />
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch, nextTick, computed } from 'vue'
|
||||
import FieldFormDialog from '@/views/tool/component/FieldFormDialog.vue'
|
||||
import UserFieldFormDialog from '@/views/tool/component/UserFieldFormDialog.vue'
|
||||
import EditAvatarDialog from '@/views/tool/component/EditAvatarDialog.vue'
|
||||
import type { toolData } from '@/api/type/tool'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { t } from '@/locales'
|
||||
import { isAppIcon } from '@/utils/common'
|
||||
import { useRoute } from 'vue-router'
|
||||
import useStore from '@/stores'
|
||||
import permissionMap from '@/permission'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
})
|
||||
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 permissionPrecise = computed(() => {
|
||||
return permissionMap['tool'][apiType.value]
|
||||
})
|
||||
|
||||
const emit = defineEmits(['refresh'])
|
||||
const FieldFormDialogRef = ref()
|
||||
const ToolDebugDrawerRef = ref()
|
||||
const UserFieldFormDialogRef = ref()
|
||||
const EditAvatarDialogRef = ref()
|
||||
const initFieldTableRef = ref()
|
||||
const inputFieldTableRef = ref()
|
||||
|
||||
const FormRef = ref()
|
||||
|
||||
const isEdit = ref(false)
|
||||
const loading = ref(false)
|
||||
const visible = ref(false)
|
||||
const showEditor = ref(false)
|
||||
const currentIndex = ref<any>(null)
|
||||
const showEditIcon = ref(false)
|
||||
|
||||
const form = ref<toolData>({
|
||||
name: '',
|
||||
desc: '',
|
||||
code: '',
|
||||
icon: '',
|
||||
input_field_list: [],
|
||||
init_field_list: [],
|
||||
tool_type: 'DATA_SOURCE',
|
||||
})
|
||||
|
||||
watch(visible, (bool) => {
|
||||
if (!bool) {
|
||||
isEdit.value = false
|
||||
showEditor.value = false
|
||||
currentIndex.value = null
|
||||
form.value = {
|
||||
name: '',
|
||||
desc: '',
|
||||
code: '',
|
||||
icon: '',
|
||||
input_field_list: [],
|
||||
init_field_list: [],
|
||||
tool_type: 'DATA_SOURCE',
|
||||
}
|
||||
FormRef.value?.clearValidate()
|
||||
}
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: t('views.tool.form.toolName.requiredMessage'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
function submitCodemirrorEditor(val: string) {
|
||||
form.value.code = val
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (!areAllValuesNonEmpty(form.value)) {
|
||||
visible.value = false
|
||||
} else {
|
||||
MsgConfirm(t('common.tip'), t('views.tool.tip.saveMessage'), {
|
||||
confirmButtonText: t('common.confirm'),
|
||||
})
|
||||
.then(() => {
|
||||
visible.value = false
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
function areAllValuesNonEmpty(obj: any) {
|
||||
return Object.values(obj).some((value) => {
|
||||
return Array.isArray(value)
|
||||
? value.length !== 0
|
||||
: value !== null && value !== undefined && value !== ''
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function deleteField(index: any) {
|
||||
form.value.input_field_list?.splice(index, 1)
|
||||
}
|
||||
|
||||
function openAddDialog(data?: any, index?: any) {
|
||||
if (typeof index !== 'undefined') {
|
||||
currentIndex.value = index
|
||||
}
|
||||
|
||||
FieldFormDialogRef.value.open(data)
|
||||
}
|
||||
|
||||
function refreshFieldList(data: any) {
|
||||
if (currentIndex.value !== null) {
|
||||
form.value.input_field_list?.splice(currentIndex.value, 1, data)
|
||||
} else {
|
||||
form.value.input_field_list?.push(data)
|
||||
}
|
||||
currentIndex.value = null
|
||||
}
|
||||
|
||||
function openAddInitDialog(data?: any, index?: any) {
|
||||
if (typeof index !== 'undefined') {
|
||||
currentIndex.value = index
|
||||
}
|
||||
|
||||
UserFieldFormDialogRef.value.open(data)
|
||||
}
|
||||
|
||||
function refreshInitFieldList(data: any) {
|
||||
if (currentIndex.value !== null) {
|
||||
form.value.init_field_list?.splice(currentIndex.value, 1, data)
|
||||
} else {
|
||||
form.value.init_field_list?.push(data)
|
||||
}
|
||||
currentIndex.value = null
|
||||
UserFieldFormDialogRef.value.close()
|
||||
}
|
||||
|
||||
function refreshTool(data: any) {
|
||||
form.value.icon = data
|
||||
}
|
||||
|
||||
function deleteInitField(index: any) {
|
||||
form.value.init_field_list?.splice(index, 1)
|
||||
}
|
||||
|
||||
function openEditAvatar() {
|
||||
EditAvatarDialogRef.value.open(form.value)
|
||||
}
|
||||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid: any) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
if (isEdit.value) {
|
||||
loadSharedApi({ type: 'tool', systemType: apiType.value })
|
||||
.putTool(form.value?.id as string, form.value)
|
||||
.then((res: any) => {
|
||||
MsgSuccess(t('common.editSuccess'))
|
||||
emit('refresh', res.data)
|
||||
return user.profile()
|
||||
})
|
||||
.then(() => {
|
||||
visible.value = false
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
const obj = {
|
||||
folder_id: folder.currentFolder?.id,
|
||||
...form.value,
|
||||
}
|
||||
loadSharedApi({ type: 'tool', systemType: apiType.value })
|
||||
.postTool(obj)
|
||||
.then((res: any) => {
|
||||
MsgSuccess(t('common.createSuccess'))
|
||||
emit('refresh')
|
||||
return user.profile()
|
||||
})
|
||||
.then(() => {
|
||||
visible.value = false
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const open = (data: any) => {
|
||||
if (data) {
|
||||
isEdit.value = data?.id ? true : false
|
||||
form.value = cloneDeep(data)
|
||||
}
|
||||
visible.value = true
|
||||
setTimeout(() => {
|
||||
showEditor.value = true
|
||||
}, 100)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -48,6 +48,16 @@
|
|||
</div>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="openCreateDataSourceDialog()">
|
||||
<div class="flex align-center">
|
||||
<el-avatar shape="square" :size="32">
|
||||
<img src="@/assets/workflow/icon_mcp.svg" style="width: 75%" alt="" />
|
||||
</el-avatar>
|
||||
<div class="pre-wrap ml-8">
|
||||
<div class="lighter">{{ $t('views.tool.createDataSourceTool') }}</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">
|
||||
|
|
@ -249,6 +259,7 @@
|
|||
<InitParamDrawer ref="InitParamDrawerRef" @refresh="refresh" />
|
||||
<ToolFormDrawer ref="ToolFormDrawerRef" @refresh="refresh" :title="ToolDrawertitle" />
|
||||
<McpToolFormDrawer ref="McpToolFormDrawerRef" @refresh="refresh" :title="McpToolDrawertitle" />
|
||||
<DataSourceToolFormDrawer ref="DataSourceToolFormDrawerRef" @refresh="refresh" :title="DataSourceToolDrawertitle" />
|
||||
<CreateFolderDialog ref="CreateFolderDialogRef" v-if="!isShared" @refresh="refreshFolder" />
|
||||
<ToolStoreDialog ref="toolStoreDialogRef" :api-type="apiType" @refresh="refresh" />
|
||||
<AddInternalToolDialog ref="AddInternalToolDialogRef" @refresh="confirmAddInternalTool" />
|
||||
|
|
@ -268,6 +279,7 @@ import { useRoute, onBeforeRouteLeave } from 'vue-router'
|
|||
import InitParamDrawer from '@/views/tool/component/InitParamDrawer.vue'
|
||||
import ToolFormDrawer from '@/views/tool/ToolFormDrawer.vue'
|
||||
import McpToolFormDrawer from '@/views/tool/McpToolFormDrawer.vue'
|
||||
import DataSourceToolFormDrawer from '@/views/tool/DataSourceToolFormDrawer.vue'
|
||||
import CreateFolderDialog from '@/components/folder-tree/CreateFolderDialog.vue'
|
||||
import AuthorizedWorkspace from '@/views/system-shared/AuthorizedWorkspaceDialog.vue'
|
||||
import ToolStoreDialog from '@/views/tool/toolStore/ToolStoreDialog.vue'
|
||||
|
|
@ -350,8 +362,10 @@ const search_type_change = () => {
|
|||
}
|
||||
const ToolFormDrawerRef = ref()
|
||||
const McpToolFormDrawerRef = ref()
|
||||
const DataSourceToolFormDrawerRef = ref()
|
||||
const ToolDrawertitle = ref('')
|
||||
const McpToolDrawertitle = ref('')
|
||||
const DataSourceToolDrawertitle = ref('')
|
||||
|
||||
const MoveToDialogRef = ref()
|
||||
function openMoveToDialog(data: any) {
|
||||
|
|
@ -384,6 +398,12 @@ function openCreateDialog(data?: any) {
|
|||
openCreateMcpDialog(data)
|
||||
return
|
||||
}
|
||||
// 数据源工具
|
||||
if (data?.tool_type === 'DATA_SOURCE') {
|
||||
bus.emit('select_node', data.folder_id)
|
||||
openCreateDataSourceDialog(data)
|
||||
return
|
||||
}
|
||||
// 有版本号的展示readme,是商店更新过来的
|
||||
if (data?.version) {
|
||||
let readMe = ''
|
||||
|
|
@ -440,6 +460,27 @@ function openCreateMcpDialog(data?: any) {
|
|||
}
|
||||
}
|
||||
|
||||
function openCreateDataSourceDialog(data?: any) {
|
||||
// 有template_id的不允许编辑,是模板转换来的
|
||||
if (data?.template_id) {
|
||||
return
|
||||
}
|
||||
// 共享过来的工具不让编辑
|
||||
if (isShared.value) {
|
||||
return
|
||||
}
|
||||
DataSourceToolDrawertitle.value = data ? t('views.tool.editDataSourceTool') : t('views.tool.createDataSourceTool')
|
||||
if (data) {
|
||||
loadSharedApi({ type: 'tool', systemType: apiType.value })
|
||||
.getToolById(data?.id, loading)
|
||||
.then((res: any) => {
|
||||
DataSourceToolFormDrawerRef.value.open(res.data)
|
||||
})
|
||||
} else {
|
||||
DataSourceToolFormDrawerRef.value.open(data)
|
||||
}
|
||||
}
|
||||
|
||||
async function changeState(row: any) {
|
||||
if (row.is_active) {
|
||||
MsgConfirm(
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
<el-radio-button value="">{{ $t('views.tool.all') }}</el-radio-button>
|
||||
<el-radio-button value="CUSTOM">{{ $t('views.tool.title') }}</el-radio-button>
|
||||
<el-radio-button value="MCP">MCP</el-radio-button>
|
||||
<el-radio-button value="DATA_SOURCE">{{ $t('views.tool.dataSource') }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-space>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in New Issue