feat: tool

This commit is contained in:
wangdan-fit2cloud 2025-06-04 11:24:04 +08:00
parent 7a34ba6fe3
commit a0291bea88
6 changed files with 176 additions and 23 deletions

View File

@ -14,6 +14,7 @@
},
"dependencies": {
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-python": "^6.2.1",
"@codemirror/theme-one-dark": "^6.1.2",
"axios": "^1.8.4",
"element-plus": "^2.9.10",

View File

@ -75,8 +75,16 @@ const getToolById: (
wordspace_id: string,
tool_id: String,
loading?: Ref<boolean>,
) => Promise<Result<any>> = (wordspace_id, function_lib_id, loading) => {
return get(`${prefix}/${wordspace_id}/tool/${function_lib_id}`, undefined, loading)
) => Promise<Result<any>> = (wordspace_id, tool_id, loading) => {
return get(`${prefix}/${wordspace_id}/tool/${tool_id}`, undefined, loading)
}
const postPylint: (
wordspace_id: string,
code: string,
loading?: Ref<boolean>,
) => Promise<Result<any>> = (wordspace_id, code, loading) => {
return post(`${prefix}/${wordspace_id}/tool/pylint`, { code }, {}, loading)
}
/**
@ -96,5 +104,6 @@ export default {
getToolList,
putTool,
getToolById,
postTool
postTool,
postPylint
}

View File

@ -0,0 +1,133 @@
<template>
<div class="codemirror-editor w-full">
<Codemirror
v-model="data"
ref="cmRef"
:extensions="extensions"
:style="codemirrorStyle"
:tab-size="4"
:autofocus="true"
v-bind="$attrs"
/>
<div class="codemirror-editor__footer">
<el-button text type="info" @click="openCodemirrorDialog" class="magnify">
<AppIcon iconName="app-magnify" style="font-size: 16px"></AppIcon>
</el-button>
</div>
<!-- Codemirror 弹出层 -->
<el-dialog v-model="dialogVisible" :title="title" append-to-body fullscreen>
<Codemirror
v-model="cloneContent"
:extensions="extensions"
:style="codemirrorStyle"
:tab-size="4"
:autofocus="true"
style="
height: calc(100vh - 160px) !important;
border: 1px solid #bbbfc4;
border-radius: 4px;
"
/>
<template #footer>
<div class="dialog-footer mt-24">
<el-button type="primary" @click="submitDialog"> {{ $t('common.confirm') }}</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { Codemirror } from 'vue-codemirror'
import { python } from '@codemirror/lang-python'
import { oneDark } from '@codemirror/theme-one-dark'
import { linter, type Diagnostic } from '@codemirror/lint'
import ToolApi from '@/api/tool/tool'
defineOptions({ name: 'CodemirrorEditor' })
const props = defineProps<{
title: String
modelValue: any
}>()
const emit = defineEmits(['update:modelValue', 'submitDialog'])
const data = computed({
set: (value) => {
emit('update:modelValue', value)
},
get: () => {
return props.modelValue
},
})
function getRangeFromLineAndColumn(state: any, line: number, column: number, end_column?: number) {
const l = state.doc.line(line)
const form = l.from + column
const to_end_column = l.from + end_column
return {
form: form > l.to ? l.to : form,
to: end_column && to_end_column < l.to ? to_end_column : l.to,
}
}
const regexpLinter = linter(async (view) => {
let diagnostics: Diagnostic[] = []
await ToolApi.postPylint('default', view.state.doc.toString()).then((ok) => {
ok.data.forEach((element: any) => {
const range = getRangeFromLineAndColumn(
view.state,
element.line,
element.column,
element.endColumn,
)
diagnostics.push({
from: range.form,
to: range.to,
severity: element.type,
message: element.message,
})
})
})
return diagnostics
})
const extensions = [python(), regexpLinter, oneDark]
const codemirrorStyle = {
height: '210px!important',
width: '100%',
}
const cmRef = ref<InstanceType<typeof Codemirror>>()
//
const dialogVisible = ref<boolean>(false)
const cloneContent = ref<string>('')
watch(dialogVisible, (bool) => {
if (!bool) {
emit('submitDialog', cloneContent.value)
}
})
const openCodemirrorDialog = () => {
cloneContent.value = props.modelValue
dialogVisible.value = true
}
function submitDialog() {
emit('submitDialog', cloneContent.value)
dialogVisible.value = false
}
</script>
<style lang="scss" scoped>
.codemirror-editor {
position: relative;
&__footer {
position: absolute;
bottom: 10px;
right: 10px;
}
}
</style>

View File

@ -11,6 +11,7 @@ import FolderTree from './folder-tree/index.vue'
import CommonList from './common-list/index.vue'
import BackButton from './back-button/index.vue'
import AppTable from './app-table/index.vue'
import CodemirrorEditor from './codemirror-editor/index.vue'
export default {
install(app: App) {
app.component('LogoFull', LogoFull)
@ -25,5 +26,6 @@ export default {
app.component('CommonList', CommonList)
app.component('BackButton', BackButton)
app.component('AppTable', AppTable)
app.component('CodemirrorEditor', CodemirrorEditor)
},
}

View File

@ -45,9 +45,17 @@
</div>
</template>
<div>
<el-row v-if="datasetList.length > 0 || datasetFolderList.length > 0" :gutter="15">
<template v-for="(item, index) in datasetFolderList" :key="index">
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="6" class="mb-16">
<el-row v-if="datasetList.length > 0" :gutter="15">
<template v-for="(item, index) in datasetList" :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')"
@ -65,9 +73,7 @@
</template>
</CardBox>
</el-col>
</template>
<template v-for="(item, index) in datasetList" :key="index">
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="6" class="mb-16">
<el-col v-else :xs="24" :sm="12" :md="12" :lg="8" :xl="6" class="mb-16">
<CardBox
:title="item.name"
:description="item.desc"
@ -235,9 +241,8 @@ function getList() {
folder_id: currentFolder.value?.id || 'root',
}
KnowledgeApi.getKnowledgeList('default', paginationConfig, params, loading).then((res) => {
datasetFolderList.value = res.data?.folders
paginationConfig.total = res.data.total
datasetList.value = [...datasetList.value, ...res.data.knowledge.records]
datasetList.value = [...datasetList.value, ...res.data.records]
})
}
@ -252,7 +257,7 @@ function getFolder() {
function folderClickHandel(row: any) {
currentFolder.value = row
datasetFolderList.value = []
datasetList.value = []
getList()
}

View File

@ -46,9 +46,17 @@
</template>
<div>
<el-row v-if="toolFolderList.length > 0 || toolList.length > 0" :gutter="15">
<template v-for="(item, index) in toolFolderList" :key="index">
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="6" class="mb-16">
<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')"
@ -66,10 +74,7 @@
</template>
</CardBox>
</el-col>
</template>
<template v-for="(item, index) in toolList" :key="index">
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="6" class="mb-16">
<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">
<template #icon>
<el-avatar
@ -212,7 +217,6 @@ const paginationConfig = reactive({
const folderList = ref<any[]>([])
const toolList = ref<any[]>([])
const toolFolderList = ref<any[]>([])
const currentFolder = ref<any>({})
const search_type_change = () => {
@ -247,9 +251,8 @@ function getList() {
tool_type: 'CUSTOM',
}
ToolApi.getToolList('default', paginationConfig, params, loading).then((res) => {
toolFolderList.value = res.data?.folders
paginationConfig.total = res.data?.tools.total
toolList.value = [...toolList.value, ...res.data?.tools.records]
paginationConfig.total = res.data?.total
toolList.value = [...toolList.value, ...res.data?.records]
})
}