feat: tool
This commit is contained in:
parent
aa7bc349ab
commit
e50b5cc051
@ -2,6 +2,7 @@ import { Result } from '@/request/Result'
|
|||||||
import { get, post, del, put } from '@/request/index'
|
import { get, post, del, put } from '@/request/index'
|
||||||
import { type Ref } from 'vue'
|
import { type Ref } from 'vue'
|
||||||
import type { pageRequest } from '@/api/type/common'
|
import type { pageRequest } from '@/api/type/common'
|
||||||
|
import type { toolData } from '@/api/type/tool'
|
||||||
const prefix = '/workspace'
|
const prefix = '/workspace'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,7 +39,37 @@ const getToolList: (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改工具
|
||||||
|
* @param 参数
|
||||||
|
|
||||||
|
*/
|
||||||
|
const putToolLib: (
|
||||||
|
wordspace_id: string,
|
||||||
|
tool_id: string,
|
||||||
|
data: toolData,
|
||||||
|
loading?: Ref<boolean>,
|
||||||
|
) => Promise<Result<any>> = (wordspace_id, tool_id, data, loading) => {
|
||||||
|
return put(`${prefix}/${wordspace_id}/tool/${tool_id}`, data, undefined, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取工具详情
|
||||||
|
* @param tool_id 工具id
|
||||||
|
* @param loading 加载器
|
||||||
|
* @returns 函数详情
|
||||||
|
*/
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getToolByFolder,
|
getToolByFolder,
|
||||||
getToolList,
|
getToolList,
|
||||||
|
putToolLib,
|
||||||
|
getToolById
|
||||||
}
|
}
|
||||||
|
|||||||
13
ui/src/api/type/tool.ts
Normal file
13
ui/src/api/type/tool.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
interface toolData {
|
||||||
|
id?: String
|
||||||
|
name?: String
|
||||||
|
icon?: String
|
||||||
|
desc?: String
|
||||||
|
code?: String
|
||||||
|
input_field_list?: Array<any>
|
||||||
|
init_field_list?: Array<any>
|
||||||
|
is_active?: Boolean
|
||||||
|
folder_id?: String
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { toolData }
|
||||||
@ -117,7 +117,27 @@ export const iconMap: any = {
|
|||||||
])
|
])
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'app-disabled': {
|
||||||
|
iconReader: () => {
|
||||||
|
return h('i', [
|
||||||
|
h(
|
||||||
|
'svg',
|
||||||
|
{
|
||||||
|
style: { height: '100%', width: '100%' },
|
||||||
|
viewBox: '0 0 1024 1024',
|
||||||
|
version: '1.1',
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg',
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('path', {
|
||||||
|
d: 'M512 21.333333C241.024 21.333333 21.333333 241.024 21.333333 512S241.024 1002.666667 512 1002.666667 1002.666667 782.976 1002.666667 512 782.976 21.333333 512 21.333333z m297.685333 697.856L304.810667 214.314667a362.666667 362.666667 0 0 1 504.874666 504.874666zM149.333333 512c0-77.056 24.021333-148.48 64.981334-207.189333l504.874666 504.874666A362.666667 362.666667 0 0 1 149.333333 512z',
|
||||||
|
fill: 'currentColor',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
},
|
||||||
// 动态加载的图标
|
// 动态加载的图标
|
||||||
...dynamicIcons,
|
...dynamicIcons,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,14 @@
|
|||||||
<el-card shadow="hover" class="card-box" @mouseenter="cardEnter()" @mouseleave="cardLeave()">
|
<el-card shadow="hover" class="card-box" @mouseenter="cardEnter()" @mouseleave="cardLeave()">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<slot name="header">
|
<slot name="header">
|
||||||
<div class="title flex align-center" :class="$slots.subTitle ? 'mt-4' : ''">
|
<div class="title flex align-center">
|
||||||
<slot name="icon">
|
<div class="mr-12 flex align-center" v-if="showIcon">
|
||||||
<el-avatar v-if="showIcon" class="mr-12 avatar-blue" shape="square" :size="32">
|
<slot name="icon">
|
||||||
<img src="@/assets/knowledge/icon_document.svg" style="width: 58%" alt="" />
|
<el-avatar shape="square" :size="32" class="avatar-blue">
|
||||||
</el-avatar>
|
<img src="@/assets/knowledge/icon_document.svg" style="width: 58%" alt="" />
|
||||||
</slot>
|
</el-avatar>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
<div style="width: 90%">
|
<div style="width: 90%">
|
||||||
<slot name="title">
|
<slot name="title">
|
||||||
<div>
|
<div>
|
||||||
@ -21,16 +23,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description break-all mt-12">
|
<div class="description break-all mt-12">
|
||||||
<slot>
|
<slot>
|
||||||
<div class="content">
|
<div class="content color-secondary">
|
||||||
{{ description }}
|
{{ description }}
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
<div @mouseenter="subHoveredEnter">
|
|
||||||
<slot name="mouseEnter" v-if="$slots.mouseEnter && show" />
|
<div class="card-footer flex-between" v-if="$slots.footer || $slots.mouseEnter">
|
||||||
</div>
|
<div>
|
||||||
<div class="card-footer" v-if="$slots.footer">
|
<slot name="footer"></slot>
|
||||||
<slot name="footer" />
|
</div>
|
||||||
|
<div @mouseenter="subHoveredEnter">
|
||||||
|
<slot name="mouseEnter" v-if="$slots.mouseEnter && show" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
@ -80,11 +85,12 @@ function subHoveredEnter() {
|
|||||||
min-width: var(--card-min-width);
|
min-width: var(--card-min-width);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
.card-header {
|
.card-header {
|
||||||
margin-top: -10px;
|
margin-top: -5px;
|
||||||
}
|
}
|
||||||
.description {
|
.description {
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
min-height: 70px;
|
||||||
.content {
|
.content {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
height: var(--app-card-box-description-height, 40px);
|
height: var(--app-card-box-description-height, 40px);
|
||||||
@ -96,7 +102,7 @@ function subHoveredEnter() {
|
|||||||
|
|
||||||
.card-footer {
|
.card-footer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 4px;
|
bottom: 8px;
|
||||||
left: 0;
|
left: 0;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|||||||
@ -55,7 +55,7 @@ const option_list = computed(() => {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #1f2329;
|
color: var(--el-text-color-primary);
|
||||||
padding: 3px 4px;
|
padding: 3px 4px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@ -193,7 +193,7 @@ const activeText = computed(() => {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
.title {
|
.title {
|
||||||
color: #1f2329;
|
color: var(--el-text-color-primary);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
|
|||||||
@ -181,7 +181,7 @@ const activeText = computed(() => {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
.title {
|
.title {
|
||||||
color: #1f2329;
|
color: var(--el-text-color-primary);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
|
|||||||
@ -44,12 +44,14 @@ export default {
|
|||||||
document: 'Documents',
|
document: 'Documents',
|
||||||
image: 'Image',
|
image: 'Image',
|
||||||
audio: 'Audio',
|
audio: 'Audio',
|
||||||
video: 'Video'
|
video: 'Video',
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
label: 'Status',
|
label: 'Status',
|
||||||
|
enabled: 'Enabled',
|
||||||
|
disabled: 'Disabled',
|
||||||
enableSuccess: 'Successful',
|
enableSuccess: 'Successful',
|
||||||
disableSuccess: 'Successful'
|
disableSuccess: 'Successful',
|
||||||
},
|
},
|
||||||
param: {
|
param: {
|
||||||
outputParam: 'Output Parameters',
|
outputParam: 'Output Parameters',
|
||||||
@ -60,5 +62,5 @@ export default {
|
|||||||
inputPlaceholder: 'Please input',
|
inputPlaceholder: 'Please input',
|
||||||
title: 'Title',
|
title: 'Title',
|
||||||
content: 'Content',
|
content: 'Content',
|
||||||
rename: 'Rename'
|
rename: 'Rename',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,8 +52,10 @@ export default {
|
|||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
label: '状态',
|
label: '状态',
|
||||||
|
enabled: '已启用',
|
||||||
|
disabled: '已禁用',
|
||||||
enableSuccess: '启用成功',
|
enableSuccess: '启用成功',
|
||||||
disableSuccess: '禁用成功'
|
disableSuccess: '禁用成功',
|
||||||
},
|
},
|
||||||
inputPlaceholder: '请输入',
|
inputPlaceholder: '请输入',
|
||||||
title: '标题',
|
title: '标题',
|
||||||
@ -61,7 +63,7 @@ export default {
|
|||||||
param: {
|
param: {
|
||||||
outputParam: '输出参数',
|
outputParam: '输出参数',
|
||||||
inputParam: '输入参数',
|
inputParam: '输入参数',
|
||||||
initParam: '启动参数'
|
initParam: '启动参数',
|
||||||
},
|
},
|
||||||
rename: '重命名'
|
rename: '重命名',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,12 +44,14 @@ export default {
|
|||||||
document: '文檔',
|
document: '文檔',
|
||||||
image: '圖片',
|
image: '圖片',
|
||||||
audio: '音頻',
|
audio: '音頻',
|
||||||
video: '視頻'
|
video: '視頻',
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
label: '狀態',
|
label: '狀態',
|
||||||
|
enabled: '已啟用',
|
||||||
|
disabled: '已停用',
|
||||||
enableSuccess: '啟用成功',
|
enableSuccess: '啟用成功',
|
||||||
disableSuccess: '停用成功'
|
disableSuccess: '停用成功',
|
||||||
},
|
},
|
||||||
inputPlaceholder: '請輸入',
|
inputPlaceholder: '請輸入',
|
||||||
title: '標題',
|
title: '標題',
|
||||||
@ -59,5 +61,5 @@ export default {
|
|||||||
inputParam: '輸入參數',
|
inputParam: '輸入參數',
|
||||||
initParam: '啟動參數',
|
initParam: '啟動參數',
|
||||||
},
|
},
|
||||||
rename: '重命名'
|
rename: '重命名',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -386,6 +386,9 @@ h5 {
|
|||||||
.color-secondary {
|
.color-secondary {
|
||||||
color: var(--app-text-color-secondary);
|
color: var(--app-text-color-secondary);
|
||||||
}
|
}
|
||||||
|
.color-success {
|
||||||
|
color: var(--el-color-success);
|
||||||
|
}
|
||||||
.avatar-purple {
|
.avatar-purple {
|
||||||
background: #7f3bf5;
|
background: #7f3bf5;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,6 @@ $primary-color: #3370ff;
|
|||||||
// --el-menu-item-height: 45px;
|
// --el-menu-item-height: 45px;
|
||||||
// --el-box-shadow-light: 0px 2px 4px 0px rgba(31, 35, 41, 0.12);
|
// --el-box-shadow-light: 0px 2px 4px 0px rgba(31, 35, 41, 0.12);
|
||||||
// --el-border-color: #dee0e3;
|
// --el-border-color: #dee0e3;
|
||||||
// --el-text-color-regular: #1f2329;
|
|
||||||
// --el-color-info: #8f959e !important;
|
// --el-color-info: #8f959e !important;
|
||||||
// --el-disabled-bg-color: #eff0f1 !important;
|
// --el-disabled-bg-color: #eff0f1 !important;
|
||||||
|
|
||||||
@ -79,19 +78,20 @@ $primary-color: #3370ff;
|
|||||||
|
|
||||||
// dropdown
|
// dropdown
|
||||||
.el-dropdown {
|
.el-dropdown {
|
||||||
color: var(--app-text-color);
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
.el-dropdown-menu__item {
|
.el-dropdown-menu__item {
|
||||||
color: var(--app-text-color);
|
color: var(--el-text-color-primary);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
padding: 5px 11px;
|
padding: 5px 11px;
|
||||||
|
min-width: 80px;
|
||||||
i {
|
i {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
&:not(.is-disabled):focus,
|
&:not(.is-disabled):focus,
|
||||||
&:not(.is-active):focus {
|
&:not(.is-active):focus {
|
||||||
background-color: var(--app-text-color-light-1);
|
background-color: var(--app-text-color-light-1);
|
||||||
color: var(--app-text-color);
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
&.is-active,
|
&.is-active,
|
||||||
&.is-active:hover {
|
&.is-active:hover {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<card-box :title="model.name" shadow="hover" class="model-card">
|
<card-box :title="model.name" shadow="hover" class="model-card">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<span style="height: 32px; width: 32px" :innerHTML="icon" class="mr-12"></span>
|
<span style="height: 32px; width: 32px" :innerHTML="icon"></span>
|
||||||
</template>
|
</template>
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex" style="height: 22px">
|
<div class="flex" style="height: 22px">
|
||||||
@ -23,12 +23,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #subTitle>
|
<template #subTitle>
|
||||||
<el-text class="color-secondary" size="small">
|
<el-text class="color-secondary lighter" size="small">
|
||||||
{{ $t('common.creator') }}: {{ model.username }}
|
{{ $t('common.creator') }}: {{ model.username }}
|
||||||
</el-text>
|
</el-text>
|
||||||
</template>
|
</template>
|
||||||
<ul>
|
<ul>
|
||||||
<li class="flex">
|
<li class="flex mb-4">
|
||||||
<el-text type="info" class="color-secondary">{{
|
<el-text type="info" class="color-secondary">{{
|
||||||
$t('views.model.modelForm.model_type.label')
|
$t('views.model.modelForm.model_type.label')
|
||||||
}}</el-text>
|
}}</el-text>
|
||||||
@ -63,48 +63,46 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #mouseEnter>
|
<template #mouseEnter>
|
||||||
<div class="operation-button">
|
<el-dropdown trigger="click">
|
||||||
<el-dropdown trigger="click">
|
<el-button text @click.stop>
|
||||||
<el-button text @click.stop>
|
<el-icon><MoreFilled /></el-icon>
|
||||||
<el-icon><MoreFilled /></el-icon>
|
</el-button>
|
||||||
</el-button>
|
<template #dropdown>
|
||||||
<template #dropdown>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-item
|
||||||
<el-dropdown-item
|
icon="EditPen"
|
||||||
icon="EditPen"
|
:disabled="!is_permisstion"
|
||||||
:disabled="!is_permisstion"
|
text
|
||||||
text
|
@click.stop="openEditModel"
|
||||||
@click.stop="openEditModel"
|
>
|
||||||
>
|
{{ $t('common.modify') }}
|
||||||
{{ $t('common.modify') }}
|
</el-dropdown-item>
|
||||||
</el-dropdown-item>
|
|
||||||
|
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
v-if="
|
v-if="
|
||||||
currentModel.model_type === 'TTS' ||
|
currentModel.model_type === 'TTS' ||
|
||||||
currentModel.model_type === 'LLM' ||
|
currentModel.model_type === 'LLM' ||
|
||||||
currentModel.model_type === 'IMAGE' ||
|
currentModel.model_type === 'IMAGE' ||
|
||||||
currentModel.model_type === 'TTI'
|
currentModel.model_type === 'TTI'
|
||||||
"
|
"
|
||||||
:disabled="!is_permisstion"
|
:disabled="!is_permisstion"
|
||||||
icon="Setting"
|
icon="Setting"
|
||||||
@click.stop="openParamSetting"
|
@click.stop="openParamSetting"
|
||||||
>
|
>
|
||||||
{{ $t('views.model.modelForm.title.paramSetting') }}
|
{{ $t('views.model.modelForm.title.paramSetting') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
divided
|
divided
|
||||||
icon="Delete"
|
icon="Delete"
|
||||||
:disabled="!is_permisstion"
|
:disabled="!is_permisstion"
|
||||||
text
|
text
|
||||||
@click.stop="deleteModel"
|
@click.stop="deleteModel"
|
||||||
>
|
>
|
||||||
{{ $t('common.delete') }}
|
{{ $t('common.delete') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<EditModel ref="editModelRef" @submit="emit('change')"></EditModel>
|
<EditModel ref="editModelRef" @submit="emit('change')"></EditModel>
|
||||||
<ParamSettingDialog ref="paramSettingRef" :model="model" />
|
<ParamSettingDialog ref="paramSettingRef" :model="model" />
|
||||||
|
|||||||
@ -96,7 +96,7 @@ import { modelTypeList, allObj } from '@/views/model/component/data'
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: Array<Provider>
|
data: Array<Provider>
|
||||||
loading: boolean
|
loading: boolean
|
||||||
active: Provider
|
active?: Provider
|
||||||
}>()
|
}>()
|
||||||
const emit = defineEmits(['click'])
|
const emit = defineEmits(['click'])
|
||||||
|
|
||||||
|
|||||||
88
ui/src/views/tool/component/AddInternalFunctionDialog.vue
Normal file
88
ui/src/views/tool/component/AddInternalFunctionDialog.vue
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="$t('views.functionLib.functionForm.form.functionName.name')"
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
append-to-body
|
||||||
|
width="450"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
label-position="top"
|
||||||
|
ref="fieldFormRef"
|
||||||
|
:rules="rules"
|
||||||
|
:model="form"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
>
|
||||||
|
<el-form-item prop="name">
|
||||||
|
<el-input v-model="form.name" maxlength="64" show-word-limit></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
|
||||||
|
<el-button type="primary" @click="submit(fieldFormRef)" :loading="loading">
|
||||||
|
{{ isEdit ? $t('common.save') : $t('common.add') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, watch } from 'vue'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
const fieldFormRef = ref()
|
||||||
|
const loading = ref<boolean>(false)
|
||||||
|
const isEdit = ref<boolean>(false)
|
||||||
|
|
||||||
|
const form = ref<any>({
|
||||||
|
name: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
name: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t('views.functionLib.functionForm.form.functionName.placeholder'),
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
|
||||||
|
watch(dialogVisible, (bool) => {
|
||||||
|
if (!bool) {
|
||||||
|
form.value = {
|
||||||
|
name: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = (row: any, edit: boolean) => {
|
||||||
|
if (row) {
|
||||||
|
form.value = cloneDeep(row)
|
||||||
|
}
|
||||||
|
isEdit.value = edit || false
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return
|
||||||
|
await formEl.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
emit('refresh', form.value, isEdit.value)
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
127
ui/src/views/tool/component/EditAvatarDialog.vue
Normal file
127
ui/src/views/tool/component/EditAvatarDialog.vue
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="`Logo ${$t('common.setting')}`"
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
width="550"
|
||||||
|
>
|
||||||
|
<el-radio-group v-model="radioType" class="radio-block mb-16">
|
||||||
|
<el-radio value="default">
|
||||||
|
<p>{{ $t('views.applicationOverview.appInfo.EditAvatarDialog.default') }}</p>
|
||||||
|
<AppAvatar
|
||||||
|
v-if="detail?.name"
|
||||||
|
:name="detail?.name"
|
||||||
|
pinyinColor
|
||||||
|
class="mt-8 mb-8"
|
||||||
|
shape="square"
|
||||||
|
:size="32"
|
||||||
|
/>
|
||||||
|
</el-radio>
|
||||||
|
|
||||||
|
<el-radio value="custom">
|
||||||
|
<p>{{ $t('views.applicationOverview.appInfo.EditAvatarDialog.customizeUpload') }}</p>
|
||||||
|
<div class="flex mt-8">
|
||||||
|
<AppAvatar
|
||||||
|
v-if="fileURL"
|
||||||
|
shape="square"
|
||||||
|
:size="32"
|
||||||
|
style="background: none"
|
||||||
|
class="mr-16"
|
||||||
|
>
|
||||||
|
<img :src="fileURL" alt="" />
|
||||||
|
</AppAvatar>
|
||||||
|
<el-upload
|
||||||
|
ref="uploadRef"
|
||||||
|
action="#"
|
||||||
|
:auto-upload="false"
|
||||||
|
:show-file-list="false"
|
||||||
|
accept="image/jpeg, image/png, image/gif"
|
||||||
|
:on-change="onChange"
|
||||||
|
>
|
||||||
|
<el-button icon="Upload" :disabled="radioType !== 'custom'"
|
||||||
|
>{{ $t('views.applicationOverview.appInfo.EditAvatarDialog.upload') }}
|
||||||
|
</el-button>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
<div class="el-upload__tip info mt-8">
|
||||||
|
{{ $t('views.applicationOverview.appInfo.EditAvatarDialog.sizeTip') }}
|
||||||
|
</div>
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submit" :loading="loading">
|
||||||
|
{{ $t('common.save') }}</el-button
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import functionLibApi from '@/api/function-lib'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
import { MsgError, MsgSuccess } from '@/utils/message'
|
||||||
|
import { defaultIcon, isAppIcon } from '@/utils/application'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
const iconFile = ref<any>(null)
|
||||||
|
const fileURL = ref<any>(null)
|
||||||
|
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
const loading = ref(false)
|
||||||
|
const detail = ref<any>(null)
|
||||||
|
const radioType = ref('default')
|
||||||
|
|
||||||
|
watch(dialogVisible, (bool) => {
|
||||||
|
if (!bool) {
|
||||||
|
iconFile.value = null
|
||||||
|
fileURL.value = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = (data: any) => {
|
||||||
|
radioType.value = isAppIcon(data.icon) ? 'custom' : 'default'
|
||||||
|
fileURL.value = isAppIcon(data.icon) ? data.icon : null
|
||||||
|
detail.value = cloneDeep(data)
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChange = (file: any) => {
|
||||||
|
//1、判断文件大小是否合法,文件限制不能大于10MB
|
||||||
|
const isLimit = file?.size / 1024 / 1024 < 10
|
||||||
|
if (!isLimit) {
|
||||||
|
// @ts-ignore
|
||||||
|
MsgError(t('views.applicationOverview.appInfo.EditAvatarDialog.fileSizeExceeded'))
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
iconFile.value = file
|
||||||
|
fileURL.value = URL.createObjectURL(file.raw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submit() {
|
||||||
|
if (radioType.value === 'default') {
|
||||||
|
emit('refresh', '/ui/favicon.ico')
|
||||||
|
dialogVisible.value = false
|
||||||
|
} else if (radioType.value === 'custom' && iconFile.value) {
|
||||||
|
let fd = new FormData()
|
||||||
|
fd.append('file', iconFile.value.raw)
|
||||||
|
functionLibApi.putFunctionLibIcon(detail.value.id, fd, loading).then((res: any) => {
|
||||||
|
emit('refresh', res.data)
|
||||||
|
dialogVisible.value = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
MsgError(t('views.applicationOverview.appInfo.EditAvatarDialog.uploadImagePrompt'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
129
ui/src/views/tool/component/FieldFormDialog.vue
Normal file
129
ui/src/views/tool/component/FieldFormDialog.vue
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="
|
||||||
|
isEdit
|
||||||
|
? $t('views.template.templateForm.title.editParam')
|
||||||
|
: $t('views.template.templateForm.title.addParam')
|
||||||
|
"
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
append-to-body
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
label-position="top"
|
||||||
|
ref="fieldFormRef"
|
||||||
|
:rules="rules"
|
||||||
|
:model="form"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
>
|
||||||
|
<el-form-item :label="$t('views.functionLib.functionForm.form.paramName.label')" prop="name">
|
||||||
|
<el-input
|
||||||
|
v-model="form.name"
|
||||||
|
:placeholder="$t('views.functionLib.functionForm.form.paramName.placeholder')"
|
||||||
|
maxlength="64"
|
||||||
|
show-word-limit
|
||||||
|
@blur="form.name = form.name.trim()"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('views.functionLib.functionForm.form.dataType.label')">
|
||||||
|
<el-select v-model="form.type">
|
||||||
|
<el-option v-for="item in typeOptions" :key="item" :label="item" :value="item" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('views.functionLib.functionForm.form.source.label')">
|
||||||
|
<el-select v-model="form.source">
|
||||||
|
<el-option
|
||||||
|
:label="$t('views.functionLib.functionForm.form.source.reference')"
|
||||||
|
value="reference"
|
||||||
|
/>
|
||||||
|
<el-option
|
||||||
|
:label="$t('views.functionLib.functionForm.form.source.custom')"
|
||||||
|
value="custom"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('views.functionLib.functionForm.form.required.label')"
|
||||||
|
@click.prevent
|
||||||
|
>
|
||||||
|
<el-switch size="small" v-model="form.is_required"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
|
||||||
|
<el-button type="primary" @click="submit(fieldFormRef)" :loading="loading">
|
||||||
|
{{ isEdit ? $t('common.save') : $t('common.add') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, watch } from 'vue'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
const typeOptions = ['string', 'int', 'dict', 'array', 'float']
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
const fieldFormRef = ref()
|
||||||
|
const loading = ref<boolean>(false)
|
||||||
|
const isEdit = ref(false)
|
||||||
|
|
||||||
|
const form = ref<any>({
|
||||||
|
name: '',
|
||||||
|
type: typeOptions[0],
|
||||||
|
source: 'reference',
|
||||||
|
is_required: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
name: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t('views.functionLib.functionForm.form.paramName.placeholder'),
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
|
||||||
|
watch(dialogVisible, (bool) => {
|
||||||
|
if (!bool) {
|
||||||
|
form.value = {
|
||||||
|
name: '',
|
||||||
|
type: typeOptions[0],
|
||||||
|
source: 'reference',
|
||||||
|
is_required: true
|
||||||
|
}
|
||||||
|
isEdit.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = (row: any) => {
|
||||||
|
if (row) {
|
||||||
|
form.value = cloneDeep(row)
|
||||||
|
isEdit.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return
|
||||||
|
await formEl.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
emit('refresh', form.value)
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
184
ui/src/views/tool/component/FunctionDebugDrawer.vue
Normal file
184
ui/src/views/tool/component/FunctionDebugDrawer.vue
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer v-model="debugVisible" size="60%" :append-to-body="true">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex align-center" style="margin-left: -8px">
|
||||||
|
<el-button class="cursor mr-4" link @click.prevent="debugVisible = false">
|
||||||
|
<el-icon :size="20">
|
||||||
|
<Back />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
<h4>{{ $t('common.debug') }}</h4>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<div v-if="form.init_field_list.length > 0">
|
||||||
|
<h4 class="title-decoration-1 mb-16">
|
||||||
|
{{ $t('common.param.initParam') }}
|
||||||
|
</h4>
|
||||||
|
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
|
||||||
|
<DynamicsForm
|
||||||
|
v-model="form.init_params"
|
||||||
|
:model="form.init_params"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
:render_data="form.init_field_list"
|
||||||
|
ref="dynamicsFormRef"
|
||||||
|
>
|
||||||
|
</DynamicsForm>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
<div v-if="form.debug_field_list.length > 0" class="mb-16">
|
||||||
|
<h4 class="title-decoration-1 mb-16">
|
||||||
|
{{ $t('common.param.inputParam') }}
|
||||||
|
</h4>
|
||||||
|
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
|
||||||
|
<el-form
|
||||||
|
ref="FormRef"
|
||||||
|
:model="form"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
hide-required-asterisk
|
||||||
|
v-loading="loading"
|
||||||
|
@submit.prevent
|
||||||
|
>
|
||||||
|
<template v-for="(item, index) in form.debug_field_list" :key="index">
|
||||||
|
<el-form-item
|
||||||
|
:label="item.name"
|
||||||
|
:prop="'debug_field_list.' + index + '.value'"
|
||||||
|
:rules="{
|
||||||
|
required: item.is_required,
|
||||||
|
message: $t('views.functionLib.functionForm.form.param.inputPlaceholder'),
|
||||||
|
trigger: 'blur'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<div class="flex">
|
||||||
|
<span
|
||||||
|
>{{ item.name }} <span class="danger" v-if="item.is_required">*</span></span
|
||||||
|
>
|
||||||
|
<el-tag type="info" class="info-tag ml-4">{{ item.type }}</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-input
|
||||||
|
v-model="item.value"
|
||||||
|
:placeholder="$t('views.functionLib.functionForm.form.param.inputPlaceholder')"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-button type="primary" @click="submit(FormRef)" :loading="loading">
|
||||||
|
{{ $t('views.functionLib.functionForm.form.debug.run') }}
|
||||||
|
</el-button>
|
||||||
|
<div v-if="showResult" class="mt-8">
|
||||||
|
<h4 class="title-decoration-1 mb-16 mt-16">
|
||||||
|
{{ $t('views.functionLib.functionForm.form.debug.runResult') }}
|
||||||
|
</h4>
|
||||||
|
<div class="mb-16">
|
||||||
|
<el-alert
|
||||||
|
v-if="isSuccess"
|
||||||
|
:title="$t('views.functionLib.functionForm.form.debug.runSuccess')"
|
||||||
|
type="success"
|
||||||
|
show-icon
|
||||||
|
:closable="false"
|
||||||
|
/>
|
||||||
|
<el-alert
|
||||||
|
v-else
|
||||||
|
:title="$t('views.functionLib.functionForm.form.debug.runFailed')"
|
||||||
|
type="error"
|
||||||
|
show-icon
|
||||||
|
:closable="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="lighter mb-8">{{ $t('views.functionLib.functionForm.form.debug.output') }}</p>
|
||||||
|
|
||||||
|
<el-card
|
||||||
|
:class="isSuccess ? '' : 'danger'"
|
||||||
|
class="pre-wrap"
|
||||||
|
shadow="never"
|
||||||
|
style="max-height: 350px; overflow: scroll"
|
||||||
|
>
|
||||||
|
{{ String(result) == '0' ? 0 : result || '-' }}
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, watch } from 'vue'
|
||||||
|
import functionLibApi from '@/api/function-lib'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import DynamicsForm from '@/components/dynamics-form/index.vue'
|
||||||
|
|
||||||
|
const FormRef = ref()
|
||||||
|
const dynamicsFormRef = ref()
|
||||||
|
const loading = ref(false)
|
||||||
|
const debugVisible = ref(false)
|
||||||
|
const showResult = ref(false)
|
||||||
|
const isSuccess = ref(false)
|
||||||
|
const result = ref('')
|
||||||
|
|
||||||
|
const form = ref<any>({
|
||||||
|
debug_field_list: [],
|
||||||
|
code: '',
|
||||||
|
input_field_list: [],
|
||||||
|
init_field_list: [],
|
||||||
|
init_params: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(debugVisible, (bool) => {
|
||||||
|
if (!bool) {
|
||||||
|
showResult.value = false
|
||||||
|
isSuccess.value = false
|
||||||
|
result.value = ''
|
||||||
|
form.value = {
|
||||||
|
debug_field_list: [],
|
||||||
|
code: '',
|
||||||
|
input_field_list: [],
|
||||||
|
init_field_list: [],
|
||||||
|
init_params: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
const validate = formEl ? formEl.validate() : Promise.resolve()
|
||||||
|
Promise.all([dynamicsFormRef.value?.validate(), validate]).then(() => {
|
||||||
|
functionLibApi.postFunctionLibDebug(form.value, loading).then((res) => {
|
||||||
|
if (res.code === 500) {
|
||||||
|
showResult.value = true
|
||||||
|
isSuccess.value = false
|
||||||
|
result.value = res.message
|
||||||
|
} else {
|
||||||
|
showResult.value = true
|
||||||
|
isSuccess.value = true
|
||||||
|
result.value = res.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = (data: any) => {
|
||||||
|
if (data.input_field_list.length > 0) {
|
||||||
|
data.input_field_list.forEach((item: any) => {
|
||||||
|
form.value.debug_field_list.push({
|
||||||
|
value: '',
|
||||||
|
...item
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
form.value.code = data.code
|
||||||
|
form.value.input_field_list = data.input_field_list
|
||||||
|
form.value.init_field_list = data.init_field_list
|
||||||
|
debugVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
518
ui/src/views/tool/component/FunctionFormDrawer.vue
Normal file
518
ui/src/views/tool/component/FunctionFormDrawer.vue
Normal file
@ -0,0 +1,518 @@
|
|||||||
|
<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.functionLib.functionForm.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.functionLib.functionForm.form.functionName.label')"
|
||||||
|
prop="name"
|
||||||
|
>
|
||||||
|
<div class="flex w-full">
|
||||||
|
<div
|
||||||
|
v-if="form.id"
|
||||||
|
class="edit-avatar mr-12"
|
||||||
|
@mouseenter="showEditIcon = true"
|
||||||
|
@mouseleave="showEditIcon = false"
|
||||||
|
>
|
||||||
|
<AppAvatar
|
||||||
|
v-if="isAppIcon(form.icon)"
|
||||||
|
:id="form.id"
|
||||||
|
shape="square"
|
||||||
|
:size="32"
|
||||||
|
style="background: none"
|
||||||
|
>
|
||||||
|
<img :src="String(form.icon)" alt="" />
|
||||||
|
</AppAvatar>
|
||||||
|
<AppAvatar
|
||||||
|
v-else-if="form.name"
|
||||||
|
:id="form.id"
|
||||||
|
:name="form.name"
|
||||||
|
pinyinColor
|
||||||
|
shape="square"
|
||||||
|
:size="32"
|
||||||
|
/>
|
||||||
|
<AppAvatar
|
||||||
|
v-if="showEditIcon"
|
||||||
|
:id="form.id"
|
||||||
|
shape="square"
|
||||||
|
class="edit-mask"
|
||||||
|
:size="32"
|
||||||
|
@click="openEditAvatar"
|
||||||
|
>
|
||||||
|
<el-icon><EditPen /></el-icon>
|
||||||
|
</AppAvatar>
|
||||||
|
</div>
|
||||||
|
<AppAvatar shape="square" style="background: #34c724" class="mr-12" v-else>
|
||||||
|
<img src="@/assets/icon_function_outlined.svg" style="width: 75%" alt="" />
|
||||||
|
</AppAvatar>
|
||||||
|
<el-input
|
||||||
|
v-model="form.name"
|
||||||
|
:placeholder="$t('views.functionLib.functionForm.form.functionName.placeholder')"
|
||||||
|
maxlength="64"
|
||||||
|
show-word-limit
|
||||||
|
@blur="form.name = form.name?.trim()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="$t('views.functionLib.functionForm.form.functionDescription.label')">
|
||||||
|
<el-input
|
||||||
|
v-model="form.desc"
|
||||||
|
type="textarea"
|
||||||
|
:placeholder="$t('views.functionLib.functionForm.form.functionDescription.placeholder')"
|
||||||
|
maxlength="128"
|
||||||
|
show-word-limit
|
||||||
|
:autosize="{ minRows: 3 }"
|
||||||
|
@blur="form.desc = form.desc?.trim()"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<!--
|
||||||
|
<el-form-item prop="permission_type">
|
||||||
|
<template #label>
|
||||||
|
<span>{{ $t('views.functionLib.functionForm.form.permission_type.label') }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-radio-group v-model="form.permission_type" class="card__radio">
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<template v-for="(value, key) of PermissionType" :key="key">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card
|
||||||
|
shadow="never"
|
||||||
|
class="mb-16"
|
||||||
|
:class="form.permission_type === key ? 'active' : ''"
|
||||||
|
>
|
||||||
|
<el-radio :value="key" size="large">
|
||||||
|
<p class="mb-4">{{ $t(value) }}</p>
|
||||||
|
<el-text type="info">
|
||||||
|
{{ $t(PermissionDesc[key]) }}
|
||||||
|
</el-text>
|
||||||
|
</el-radio>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</template>
|
||||||
|
</el-row>
|
||||||
|
</el-radio-group>
|
||||||
|
</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()">
|
||||||
|
<el-icon class="mr-4"><Plus /></el-icon> {{ $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)">
|
||||||
|
<el-icon><EditPen /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</span>
|
||||||
|
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
||||||
|
<el-button type="primary" text @click="deleteInitField($index)">
|
||||||
|
<el-icon>
|
||||||
|
<Delete />
|
||||||
|
</el-icon>
|
||||||
|
</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.functionLib.functionForm.form.param.paramInfo1') }}
|
||||||
|
</el-text>
|
||||||
|
</h4>
|
||||||
|
<el-button link type="primary" @click="openAddDialog()">
|
||||||
|
<el-icon class="mr-4"><Plus /></el-icon> {{ $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.functionLib.functionForm.form.paramName.label')"
|
||||||
|
/>
|
||||||
|
<el-table-column :label="$t('views.functionLib.functionForm.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.functionLib.functionForm.form.source.label')"
|
||||||
|
>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{
|
||||||
|
row.source === 'custom'
|
||||||
|
? $t('views.functionLib.functionForm.form.source.custom')
|
||||||
|
: $t('views.functionLib.functionForm.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)">
|
||||||
|
<el-icon><EditPen /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</span>
|
||||||
|
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
||||||
|
<el-button type="primary" text @click="deleteField($index)">
|
||||||
|
<el-icon>
|
||||||
|
<Delete />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<h4 class="title-decoration-1 mb-16">
|
||||||
|
{{ $t('views.functionLib.functionForm.form.param.code') }}
|
||||||
|
<span style="color: red; margin-left: -10px">*</span>
|
||||||
|
<el-text type="info" class="color-secondary">
|
||||||
|
{{ $t('views.functionLib.functionForm.form.param.paramInfo2') }}
|
||||||
|
</el-text>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div class="mb-8" v-if="showEditor">
|
||||||
|
<CodemirrorEditor
|
||||||
|
:title="$t('views.functionLib.functionForm.form.param.code')"
|
||||||
|
v-model="form.code"
|
||||||
|
@submitDialog="submitCodemirrorEditor"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h4 class="title-decoration-1 mb-16 mt-16">
|
||||||
|
{{ $t('common.param.outputParam') }}
|
||||||
|
<el-text type="info" class="color-secondary">
|
||||||
|
{{ $t('views.functionLib.functionForm.form.param.paramInfo1') }}
|
||||||
|
</el-text>
|
||||||
|
</h4>
|
||||||
|
<div class="flex-between border-r-4 p-8-12 mb-8 layout-bg lighter">
|
||||||
|
<span>{{ $t('common.result') }} {result}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div>
|
||||||
|
<el-button :loading="loading" @click="visible = false">{{ $t('common.cancel') }}</el-button>
|
||||||
|
<el-button :loading="loading" @click="openDebug">{{ $t('common.debug') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submit(FormRef)" :loading="loading">
|
||||||
|
{{ isEdit ? $t('common.save') : $t('common.create') }}</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<FunctionDebugDrawer ref="FunctionDebugDrawerRef" />
|
||||||
|
<FieldFormDialog ref="FieldFormDialogRef" @refresh="refreshFieldList" />
|
||||||
|
<UserFieldFormDialog ref="UserFieldFormDialogRef" @refresh="refreshInitFieldList" />
|
||||||
|
<EditAvatarDialog ref="EditAvatarDialogRef" @refresh="refreshFunctionLib" />
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, watch, nextTick } from 'vue'
|
||||||
|
import FieldFormDialog from './FieldFormDialog.vue'
|
||||||
|
import FunctionDebugDrawer from './FunctionDebugDrawer.vue'
|
||||||
|
import type { functionLibData } from '@/api/type/function-lib'
|
||||||
|
import functionLibApi from '@/api/function-lib'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
import { PermissionType, PermissionDesc } from '@/enums/model'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
import UserFieldFormDialog from '@/workflow/nodes/base-node/component/UserFieldFormDialog.vue'
|
||||||
|
import { isAppIcon } from '@/utils/application'
|
||||||
|
import EditAvatarDialog from './EditAvatarDialog.vue'
|
||||||
|
import Sortable from 'sortablejs'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
title: String
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
const FieldFormDialogRef = ref()
|
||||||
|
const FunctionDebugDrawerRef = 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<functionLibData>({
|
||||||
|
name: '',
|
||||||
|
desc: '',
|
||||||
|
code: '',
|
||||||
|
icon: '',
|
||||||
|
input_field_list: [],
|
||||||
|
init_field_list: [],
|
||||||
|
permission_type: 'PRIVATE'
|
||||||
|
})
|
||||||
|
|
||||||
|
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: [],
|
||||||
|
permission_type: 'PRIVATE'
|
||||||
|
}
|
||||||
|
FormRef.value?.clearValidate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
name: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t('views.functionLib.functionForm.form.functionName.requiredMessage'),
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
permission_type: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t('views.functionLib.functionForm.form.permission_type.requiredMessage'),
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
function onDragHandle() {
|
||||||
|
// For init_field_list table
|
||||||
|
if (initFieldTableRef.value) {
|
||||||
|
const el = initFieldTableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
|
||||||
|
Sortable.create(el, {
|
||||||
|
animation: 150,
|
||||||
|
ghostClass: 'sortable-ghost',
|
||||||
|
onEnd: ({ newIndex, oldIndex }) => {
|
||||||
|
if (newIndex === undefined || oldIndex === undefined) return
|
||||||
|
if (newIndex !== oldIndex) {
|
||||||
|
const item = form.value.init_field_list?.splice(oldIndex, 1)[0]
|
||||||
|
form.value.init_field_list?.splice(newIndex, 0, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// For input_field_list table
|
||||||
|
if (inputFieldTableRef.value) {
|
||||||
|
const el = inputFieldTableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
|
||||||
|
Sortable.create(el, {
|
||||||
|
animation: 150,
|
||||||
|
ghostClass: 'sortable-ghost',
|
||||||
|
onEnd: ({ newIndex, oldIndex }) => {
|
||||||
|
if (newIndex === undefined || oldIndex === undefined) return
|
||||||
|
if (newIndex !== oldIndex) {
|
||||||
|
const item = form.value.input_field_list?.splice(oldIndex, 1)[0]
|
||||||
|
form.value.input_field_list?.splice(newIndex, 0, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitCodemirrorEditor(val: string) {
|
||||||
|
form.value.code = val
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
if (isEdit.value || !areAllValuesNonEmpty(form.value)) {
|
||||||
|
visible.value = false
|
||||||
|
} else {
|
||||||
|
MsgConfirm(t('common.tip'), t('views.functionLib.tip.saveMessage'), {
|
||||||
|
confirmButtonText: t('common.confirm'),
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.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 openDebug() {
|
||||||
|
FunctionDebugDrawerRef.value.open(form.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 refreshFunctionLib(data: any) {
|
||||||
|
form.value.icon = data
|
||||||
|
// console.log(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) {
|
||||||
|
// console.log(form.value)
|
||||||
|
if (isEdit.value) {
|
||||||
|
functionLibApi.putFunctionLib(form.value?.id as string, form.value, loading).then((res) => {
|
||||||
|
MsgSuccess(t('common.editSuccess'))
|
||||||
|
emit('refresh', res.data)
|
||||||
|
visible.value = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
functionLibApi.postFunctionLib(form.value, loading).then((res) => {
|
||||||
|
MsgSuccess(t('common.createSuccess'))
|
||||||
|
emit('refresh')
|
||||||
|
visible.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>
|
||||||
94
ui/src/views/tool/component/InitParamDrawer.vue
Normal file
94
ui/src/views/tool/component/InitParamDrawer.vue
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer v-model="debugVisible" size="60%" :append-to-body="true">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex align-center" style="margin-left: -8px">
|
||||||
|
<el-button class="cursor mr-4" link @click.prevent="debugVisible = false">
|
||||||
|
<el-icon :size="20">
|
||||||
|
<Back />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
<h4>{{ $t('common.param.initParam') }}</h4>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<div v-if="form.init_field_list?.length > 0">
|
||||||
|
<DynamicsForm
|
||||||
|
v-model="form.init_params"
|
||||||
|
:model="form.init_params"
|
||||||
|
label-position="top"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
:render_data="form.init_field_list"
|
||||||
|
ref="dynamicsFormRef"
|
||||||
|
>
|
||||||
|
</DynamicsForm>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" @click="submit()" :loading="loading">
|
||||||
|
{{ $t('common.save') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import ToolApi from '@/api/tool/tool'
|
||||||
|
import DynamicsForm from '@/components/dynamics-form/index.vue'
|
||||||
|
import { MsgSuccess } from '@/utils/message'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
const dynamicsFormRef = ref()
|
||||||
|
const loading = ref(false)
|
||||||
|
const debugVisible = ref(false)
|
||||||
|
|
||||||
|
const form = ref<any>({
|
||||||
|
init_params: {},
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(debugVisible, (bool) => {
|
||||||
|
if (!bool) {
|
||||||
|
form.value = {
|
||||||
|
init_params: {},
|
||||||
|
is_active: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
dynamicsFormRef.value.validate().then(() => {
|
||||||
|
ToolApi.putToolLib('default', form.value?.id as string, form.value, loading).then((res) => {
|
||||||
|
MsgSuccess(t('common.editSuccess'))
|
||||||
|
emit('refresh')
|
||||||
|
debugVisible.value = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = (data: any, is_active: boolean) => {
|
||||||
|
if (data) {
|
||||||
|
form.value = cloneDeep(data)
|
||||||
|
form.value.is_active = is_active
|
||||||
|
}
|
||||||
|
const init_params = form.value.init_field_list
|
||||||
|
.map((item: any) => {
|
||||||
|
if (item.show_default_value === false) {
|
||||||
|
return { [item.field]: undefined }
|
||||||
|
}
|
||||||
|
return { [item.field]: item.default_value }
|
||||||
|
})
|
||||||
|
.reduce((x: any, y: any) => ({ ...x, ...y }), {})
|
||||||
|
form.value.init_params = { ...init_params, ...form.value.init_params }
|
||||||
|
debugVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
100
ui/src/views/tool/component/InternalDescDrawer.vue
Normal file
100
ui/src/views/tool/component/InternalDescDrawer.vue
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer v-model="visibleInternalDesc" size="60%" :append-to-body="true">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex align-center" style="margin-left: -8px">
|
||||||
|
<el-button class="cursor mr-4" link @click.prevent="visibleInternalDesc = false">
|
||||||
|
<el-icon :size="20">
|
||||||
|
<Back />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
<h4>详情</h4>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="flex-between">
|
||||||
|
<div class="title flex align-center">
|
||||||
|
<AppAvatar
|
||||||
|
v-if="isAppIcon(functionDetail?.icon)"
|
||||||
|
shape="square"
|
||||||
|
:size="64"
|
||||||
|
style="background: none"
|
||||||
|
class="mr-8"
|
||||||
|
>
|
||||||
|
<img :src="functionDetail?.icon" alt="" />
|
||||||
|
</AppAvatar>
|
||||||
|
<AppAvatar
|
||||||
|
v-else-if="functionDetail?.name"
|
||||||
|
:name="functionDetail?.name"
|
||||||
|
pinyinColor
|
||||||
|
shape="square"
|
||||||
|
:size="64"
|
||||||
|
class="mr-8"
|
||||||
|
/>
|
||||||
|
<div class="ml-16">
|
||||||
|
<h3 class="mb-8">{{ functionDetail.name }}</h3>
|
||||||
|
<el-text type="info" v-if="functionDetail?.desc">
|
||||||
|
{{ functionDetail.desc }}
|
||||||
|
</el-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div @click.stop>
|
||||||
|
<el-button type="primary" @click="addInternalFunction(functionDetail)">
|
||||||
|
{{ $t('common.add') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-16">
|
||||||
|
<el-text type="info">
|
||||||
|
<div>{{ $t('common.author') }}: MaxKB</div>
|
||||||
|
</el-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<MdPreview
|
||||||
|
ref="editorRef"
|
||||||
|
editorId="preview-only"
|
||||||
|
:modelValue="markdownContent"
|
||||||
|
style="background: none"
|
||||||
|
noImgZoomIn
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
import { isAppIcon } from '@/utils/application'
|
||||||
|
const emit = defineEmits(['refresh', 'addFunction'])
|
||||||
|
|
||||||
|
const visibleInternalDesc = ref(false)
|
||||||
|
const markdownContent = ref('')
|
||||||
|
const functionDetail = ref<any>({})
|
||||||
|
|
||||||
|
watch(visibleInternalDesc, (bool) => {
|
||||||
|
if (!bool) {
|
||||||
|
markdownContent.value = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = (data: any, detail: any) => {
|
||||||
|
functionDetail.value = detail
|
||||||
|
if (data) {
|
||||||
|
markdownContent.value = cloneDeep(data)
|
||||||
|
}
|
||||||
|
visibleInternalDesc.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const addInternalFunction = (data: any) => {
|
||||||
|
emit('addFunction', data)
|
||||||
|
visibleInternalDesc.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
106
ui/src/views/tool/component/PermissionDialog.vue
Normal file
106
ui/src/views/tool/component/PermissionDialog.vue
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="$t('views.functionLib.functionForm.form.permission_type.label')"
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
append-to-body
|
||||||
|
width="450"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
label-position="top"
|
||||||
|
ref="fieldFormRef"
|
||||||
|
:rules="rules"
|
||||||
|
:model="form"
|
||||||
|
require-asterisk-position="right"
|
||||||
|
>
|
||||||
|
<el-radio-group v-model="form.permission_type" class="radio-block">
|
||||||
|
<el-radio value="PRIVATE" size="large">
|
||||||
|
{{ $t('common.private') }}
|
||||||
|
<el-text type="info">{{
|
||||||
|
$t('views.template.templateForm.form.permissionType.privateDesc')
|
||||||
|
}}</el-text>
|
||||||
|
</el-radio>
|
||||||
|
<el-radio value="PUBLIC" size="large">
|
||||||
|
{{ $t('common.public') }}
|
||||||
|
<el-text type="info">{{
|
||||||
|
$t('views.template.templateForm.form.permissionType.publicDesc')
|
||||||
|
}}</el-text>
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
|
||||||
|
<el-button type="primary" @click="submit(fieldFormRef)" :loading="loading">
|
||||||
|
{{ isEdit ? $t('common.save') : $t('common.add') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, watch } from 'vue'
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
import functionLibApi from '@/api/function-lib'
|
||||||
|
import { MsgSuccess } from '@/utils/message'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
|
const fieldFormRef = ref()
|
||||||
|
const loading = ref<boolean>(false)
|
||||||
|
const isEdit = ref(false)
|
||||||
|
|
||||||
|
const form = ref<any>({
|
||||||
|
permission_type: 'PRIVATE'
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
permission_type: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t('views.functionLib.functionForm.form.paramName.placeholder'),
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialogVisible = ref<boolean>(false)
|
||||||
|
|
||||||
|
watch(dialogVisible, (bool) => {
|
||||||
|
if (!bool) {
|
||||||
|
form.value = {
|
||||||
|
permission_type: 'PRIVATE'
|
||||||
|
}
|
||||||
|
isEdit.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = (row: any) => {
|
||||||
|
if (row) {
|
||||||
|
form.value = cloneDeep(row)
|
||||||
|
isEdit.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return
|
||||||
|
await formEl.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
functionLibApi.putFunctionLib(form.value?.id as string, form.value, loading).then((res) => {
|
||||||
|
MsgSuccess(t('common.editSuccess'))
|
||||||
|
emit('refresh')
|
||||||
|
dialogVisible.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@ -48,22 +48,111 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<el-row v-if="toolList.length > 0" :gutter="15">
|
<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">
|
||||||
|
<CardBox
|
||||||
|
:title="item.name"
|
||||||
|
:description="item.desc || $t('common.noData')"
|
||||||
|
class="cursor"
|
||||||
|
>
|
||||||
|
<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.username }}
|
||||||
|
</el-text>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</el-col>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template v-for="(item, index) in toolList" :key="index">
|
<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 :xs="24" :sm="12" :md="12" :lg="8" :xl="6" class="mb-16">
|
||||||
<CardBox :title="item.name" :description="item.desc" class="cursor">
|
<CardBox :title="item.name" :description="item.desc" class="cursor">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<el-avatar class="mr-8 avatar-green" shape="square" :size="32">
|
<el-avatar class="avatar-green" shape="square" :size="32">
|
||||||
<img src="@/assets/node/icon_tool.svg" style="width: 58%" alt="" />
|
<img src="@/assets/node/icon_tool.svg" style="width: 58%" alt="" />
|
||||||
</el-avatar>
|
</el-avatar>
|
||||||
</template>
|
</template>
|
||||||
<template #subTitle>
|
<template #subTitle>
|
||||||
<el-text class="color-secondary" size="small">
|
<el-text class="color-secondary lighter" size="small">
|
||||||
<auto-tooltip :content="item.username">
|
{{ $t('common.creator') }}: {{ item.username }}
|
||||||
{{ $t('common.creator') }}: {{ item.username }}
|
|
||||||
</auto-tooltip>
|
|
||||||
</el-text>
|
</el-text>
|
||||||
</template>
|
</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>
|
||||||
|
<el-switch
|
||||||
|
v-model="item.is_active"
|
||||||
|
:before-change="() => changeState(item)"
|
||||||
|
size="small"
|
||||||
|
class="mr-4"
|
||||||
|
/>
|
||||||
|
<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="openCreateDialog(item)"
|
||||||
|
>
|
||||||
|
<el-icon><EditPen /></el-icon>
|
||||||
|
{{ $t('common.edit') }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item
|
||||||
|
:disabled="item.permission_type === 'PUBLIC' && !canEdit(item)"
|
||||||
|
v-if="!item.template_id"
|
||||||
|
@click.stop="copyFunctionLib(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"
|
||||||
|
@click.stop="exportFunctionLib(item)"
|
||||||
|
>
|
||||||
|
<AppIcon iconName="app-export"></AppIcon>
|
||||||
|
{{ $t('common.export') }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item divided @click.stop="deleteFunctionLib(item)">
|
||||||
|
<el-icon><Delete /></el-icon>
|
||||||
|
{{ $t('common.delete') }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template> -->
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</CardBox>
|
</CardBox>
|
||||||
</el-col>
|
</el-col>
|
||||||
</template>
|
</template>
|
||||||
@ -71,6 +160,7 @@
|
|||||||
<el-empty :description="$t('common.noData')" v-else />
|
<el-empty :description="$t('common.noData')" v-else />
|
||||||
</div>
|
</div>
|
||||||
</ContentContainer>
|
</ContentContainer>
|
||||||
|
<InitParamDrawer ref="InitParamDrawerRef" @refresh="refresh" />
|
||||||
</LayoutContainer>
|
</LayoutContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -78,11 +168,14 @@
|
|||||||
import { onMounted, ref, reactive, computed } from 'vue'
|
import { onMounted, ref, reactive, computed } from 'vue'
|
||||||
import ToolApi from '@/api/tool/tool'
|
import ToolApi from '@/api/tool/tool'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
import { numberFormat } from '@/utils/common'
|
import { MsgConfirm } from '@/utils/message'
|
||||||
|
import InitParamDrawer from '@/views/tool/component/InitParamDrawer.vue'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
|
|
||||||
const { folder } = useStore()
|
const { folder } = useStore()
|
||||||
|
|
||||||
|
const InitParamDrawerRef = ref()
|
||||||
|
|
||||||
const search_type = ref('name')
|
const search_type = ref('name')
|
||||||
const search_form = ref<{
|
const search_form = ref<{
|
||||||
name: string
|
name: string
|
||||||
@ -94,6 +187,7 @@ const search_form = ref<{
|
|||||||
const user_options = ref<any[]>([])
|
const user_options = ref<any[]>([])
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
const changeStateloading = ref(false)
|
||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
current_page: 1,
|
current_page: 1,
|
||||||
page_size: 30,
|
page_size: 30,
|
||||||
@ -102,6 +196,7 @@ const paginationConfig = reactive({
|
|||||||
|
|
||||||
const folderList = ref<any[]>([])
|
const folderList = ref<any[]>([])
|
||||||
const toolList = ref<any[]>([])
|
const toolList = ref<any[]>([])
|
||||||
|
const toolFolderList = ref<any[]>([])
|
||||||
const currentFolder = ref<any>({})
|
const currentFolder = ref<any>({})
|
||||||
|
|
||||||
const search_type_change = () => {
|
const search_type_change = () => {
|
||||||
@ -114,8 +209,9 @@ function getList() {
|
|||||||
tool_type: 'CUSTOM',
|
tool_type: 'CUSTOM',
|
||||||
}
|
}
|
||||||
ToolApi.getToolList('default', paginationConfig, params, loading).then((res) => {
|
ToolApi.getToolList('default', paginationConfig, params, loading).then((res) => {
|
||||||
paginationConfig.total = res.data.total
|
toolFolderList.value = res.data?.folders
|
||||||
toolList.value = [...toolList.value, ...res.data.records]
|
paginationConfig.total = res.data?.tools.total
|
||||||
|
toolList.value = [...toolList.value, ...res.data?.tools.records]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +224,61 @@ function getFolder() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function changeState(row: any) {
|
||||||
|
// if (!bool) {
|
||||||
|
// MsgConfirm(
|
||||||
|
// `${t('views.functionLib.disabled.confirmTitle')}${row.name} ?`,
|
||||||
|
// t('views.functionLib.disabled.confirmMessage'),
|
||||||
|
// {
|
||||||
|
// confirmButtonText: t('views.functionLib.setting.disabled'),
|
||||||
|
// confirmButtonClass: 'danger',
|
||||||
|
// },
|
||||||
|
// )
|
||||||
|
// .then(() => {
|
||||||
|
// const obj = {
|
||||||
|
// is_active: bool,
|
||||||
|
// }
|
||||||
|
// ToolApi.putToolLib('default', row.id, obj, changeStateloading).then((res) => {})
|
||||||
|
// })
|
||||||
|
// .catch(() => {
|
||||||
|
// row.is_active = true
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// const res = await ToolApi.getToolById('default', 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
|
||||||
|
// ) {
|
||||||
|
// row.is_active = false
|
||||||
|
// InitParamDrawerRef.value.open(res.data, bool)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// const obj = {
|
||||||
|
// is_active: bool,
|
||||||
|
// }
|
||||||
|
// ToolApi.putToolLib('default', row.id, obj, changeStateloading).then((res) => {})
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
function folderClickHandel(row: any) {
|
function folderClickHandel(row: any) {
|
||||||
// currentFolder.value = row
|
// currentFolder.value = row
|
||||||
// toolList.value = []
|
// toolList.value = []
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user