[Feature][UI Next] Add udf function manage (#8126)
parent
8ef72fcffc
commit
62198fda24
|
|
@ -215,6 +215,38 @@ const resource = {
|
|||
enter_name_tips: 'Please enter name',
|
||||
enter_description_tips: 'Please enter description'
|
||||
},
|
||||
function: {
|
||||
udf_function: 'UDF Function',
|
||||
create_udf_function: 'Create UDF Function',
|
||||
edit_udf_function: 'Create UDF Function',
|
||||
id: '#',
|
||||
udf_function_name: 'UDF Function Name',
|
||||
class_name: 'Class Name',
|
||||
type: 'Type',
|
||||
description: 'Description',
|
||||
jar_package: 'Jar Package',
|
||||
update_time: 'Update Time',
|
||||
operation: 'Operation',
|
||||
rename: 'Rename',
|
||||
edit: 'Edit',
|
||||
delete: 'Delete',
|
||||
success: 'Success',
|
||||
package_name: 'Package Name',
|
||||
udf_resources: 'UDF Resources',
|
||||
instructions: 'Instructions',
|
||||
upload_resources: 'Upload Resources',
|
||||
udf_resources_directory: 'UDF resources directory',
|
||||
delete_confirm: 'Delete?',
|
||||
enter_keyword_tips: 'Please enter keyword',
|
||||
enter_udf_unction_name_tips: 'Please enter a UDF function name',
|
||||
enter_package_name_tips: 'Please enter a Package name',
|
||||
enter_select_udf_resources_tips: 'Please select UDF resources',
|
||||
enter_select_udf_resources_directory_tips:
|
||||
'Please select UDF resources directory',
|
||||
enter_instructions_tips: 'Please enter a instructions',
|
||||
enter_name_tips: 'Please enter name',
|
||||
enter_description_tips: 'Please enter description'
|
||||
},
|
||||
task_group_option: {
|
||||
id: 'No.',
|
||||
manage: 'Task group manage',
|
||||
|
|
|
|||
|
|
@ -217,6 +217,37 @@ const resource = {
|
|||
enter_name_tips: '请输入名称',
|
||||
enter_description_tips: '请输入描述'
|
||||
},
|
||||
function: {
|
||||
udf_function: 'UDF函数',
|
||||
create_udf_function: '创建UDF函数',
|
||||
edit_udf_function: '编辑UDF函数',
|
||||
id: '编号',
|
||||
udf_function_name: 'UDF函数名称',
|
||||
class_name: '类名',
|
||||
type: '类型',
|
||||
description: '描述',
|
||||
jar_package: 'jar包',
|
||||
update_time: '更新时间',
|
||||
operation: '操作',
|
||||
rename: '重命名',
|
||||
edit: '编辑',
|
||||
delete: '删除',
|
||||
success: '成功',
|
||||
package_name: '包名类名',
|
||||
udf_resources: 'UDF资源',
|
||||
instructions: '使用说明',
|
||||
upload_resources: '上传资源',
|
||||
udf_resources_directory: 'UDF资源目录',
|
||||
delete_confirm: '确定删除吗?',
|
||||
enter_keyword_tips: '请输入关键词',
|
||||
enter_udf_unction_name_tips: '请输入UDF函数名称',
|
||||
enter_package_name_tips: '请输入包名类名',
|
||||
enter_select_udf_resources_tips: '请选择UDF资源',
|
||||
enter_select_udf_resources_directory_tips: '请选择UDF资源目录',
|
||||
enter_instructions_tips: '请输入使用说明',
|
||||
enter_name_tips: '请输入名称',
|
||||
enter_description_tips: '请输入描述'
|
||||
},
|
||||
task_group_option: {
|
||||
id: '编号',
|
||||
manage: '任务组管理',
|
||||
|
|
|
|||
|
|
@ -101,6 +101,14 @@ export default {
|
|||
showSide: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/resource/function-manage',
|
||||
name: 'function-manage',
|
||||
component: components['function'],
|
||||
meta: {
|
||||
title: '函数管理'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/resource/task-group',
|
||||
name: 'task-group-manage',
|
||||
|
|
|
|||
|
|
@ -118,9 +118,7 @@ export function onlineCreateResource(
|
|||
})
|
||||
}
|
||||
|
||||
export function queryResourceByProgramType(
|
||||
params: ResourceTypeReq & ProgramTypeReq
|
||||
): any {
|
||||
export function queryResourceByProgramType(params: ResourceTypeReq): any {
|
||||
return axios({
|
||||
url: '/resources/query-by-type',
|
||||
method: 'get',
|
||||
|
|
@ -136,7 +134,7 @@ export function queryUdfFuncListPaging(params: ListReq): any {
|
|||
})
|
||||
}
|
||||
|
||||
export function queryUdfFuncList(params: UdfTypeReq): any {
|
||||
export function queryUdfFuncList(params: IdReq & ListReq): any {
|
||||
return axios({
|
||||
url: '/resources/udf-func/list',
|
||||
method: 'get',
|
||||
|
|
@ -152,7 +150,7 @@ export function verifyUdfFuncName(params: NameReq): any {
|
|||
})
|
||||
}
|
||||
|
||||
export function deleteUdfFunc(id: IdReq): any {
|
||||
export function deleteUdfFunc(id: number): any {
|
||||
return axios({
|
||||
url: `/resources/udf-func/${id}`,
|
||||
method: 'delete'
|
||||
|
|
@ -245,7 +243,7 @@ export function createUdfFunc(
|
|||
export function updateUdfFunc(
|
||||
data: UdfFuncReq,
|
||||
resourceId: ResourceIdReq,
|
||||
id: IdReq
|
||||
id: number
|
||||
): any {
|
||||
return axios({
|
||||
url: `/resources/${resourceId}/udf-func/${id}`,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ interface ResourceIdReq {
|
|||
resourceId: number
|
||||
}
|
||||
|
||||
interface UdfFuncReq extends UdfTypeReq, DescriptionReq {
|
||||
interface UdfFuncReq extends UdfTypeReq, DescriptionReq, ResourceIdReq {
|
||||
className: string
|
||||
funcName: string
|
||||
argTypes?: string
|
||||
|
|
|
|||
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineComponent, toRefs, PropType, watch, onMounted, ref } from 'vue'
|
||||
import {
|
||||
NUpload,
|
||||
NIcon,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NInputGroup,
|
||||
NRadio,
|
||||
NTreeSelect,
|
||||
NButton,
|
||||
NRadioGroup
|
||||
} from 'naive-ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { CloudUploadOutlined } from '@vicons/antd'
|
||||
import Modal from '@/components/modal'
|
||||
import { useForm } from './use-form'
|
||||
import { useModal } from './use-modal'
|
||||
import type { IUdf } from '../types'
|
||||
|
||||
const props = {
|
||||
row: {
|
||||
type: Object as PropType<IUdf>,
|
||||
default: {}
|
||||
},
|
||||
show: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ResourceFileFolder',
|
||||
props,
|
||||
emits: ['update:show', 'updateList'],
|
||||
setup(props, ctx) {
|
||||
const treeRef = ref()
|
||||
const { state, uploadState } = useForm()
|
||||
|
||||
const {
|
||||
variables,
|
||||
handleCreateFunc,
|
||||
handleRenameFunc,
|
||||
getUdfList,
|
||||
handleUploadFile
|
||||
} = useModal(state, uploadState, ctx)
|
||||
|
||||
const hideModal = () => {
|
||||
ctx.emit('update:show')
|
||||
}
|
||||
|
||||
const handleCreate = () => {
|
||||
handleCreateFunc()
|
||||
}
|
||||
|
||||
const handleRename = () => {
|
||||
handleRenameFunc(props.row.id)
|
||||
}
|
||||
|
||||
const handleUpload = () => {
|
||||
uploadState.uploadForm.currentDir = `/${treeRef.value.selectedOption?.fullName}`
|
||||
handleUploadFile()
|
||||
}
|
||||
|
||||
const customRequest = ({ file }: any) => {
|
||||
uploadState.uploadForm.name = file.name
|
||||
uploadState.uploadForm.file = file.file
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getUdfList()
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.row,
|
||||
() => {
|
||||
variables.uploadShow = false
|
||||
state.functionForm.type = props.row.type
|
||||
state.functionForm.funcName = props.row.funcName
|
||||
state.functionForm.className = props.row.className
|
||||
state.functionForm.resourceId = props.row.resourceId || -1
|
||||
state.functionForm.description = props.row.description
|
||||
}
|
||||
)
|
||||
return {
|
||||
treeRef,
|
||||
hideModal,
|
||||
handleCreate,
|
||||
handleRename,
|
||||
customRequest,
|
||||
handleUpload,
|
||||
...toRefs(state),
|
||||
...toRefs(uploadState),
|
||||
...toRefs(variables)
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { t } = useI18n()
|
||||
|
||||
return (
|
||||
<Modal
|
||||
show={this.$props.show}
|
||||
title={
|
||||
this.row.id
|
||||
? t('resource.function.edit_udf_function')
|
||||
: t('resource.function.create_udf_function')
|
||||
}
|
||||
onCancel={this.hideModal}
|
||||
onConfirm={this.row.id ? this.handleRename : this.handleCreate}
|
||||
>
|
||||
<NForm
|
||||
rules={this.rules}
|
||||
ref='functionFormRef'
|
||||
label-placement='left'
|
||||
label-width='160'
|
||||
>
|
||||
<NFormItem label={t('resource.function.type')} path='type'>
|
||||
<NRadioGroup
|
||||
v-model={[this.functionForm.type, 'value']}
|
||||
name='type'
|
||||
>
|
||||
<NRadio value='HIVE'>HIVE UDF</NRadio>
|
||||
</NRadioGroup>
|
||||
</NFormItem>
|
||||
<NFormItem
|
||||
label={t('resource.function.udf_function_name')}
|
||||
path='funcName'
|
||||
>
|
||||
<NInput
|
||||
v-model={[this.functionForm.funcName, 'value']}
|
||||
placeholder={t('resource.function.enter_udf_unction_name_tips')}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem
|
||||
label={t('resource.function.package_name')}
|
||||
path='className'
|
||||
>
|
||||
<NInput
|
||||
v-model={[this.functionForm.className, 'value']}
|
||||
placeholder={t('resource.function.enter_package_name_tips')}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem
|
||||
label={t('resource.function.udf_resources')}
|
||||
path='resourceId'
|
||||
>
|
||||
<NInputGroup>
|
||||
<NTreeSelect
|
||||
options={this.udfResourceList}
|
||||
label-field='fullName'
|
||||
key-field='id'
|
||||
v-model={[this.functionForm.resourceId, 'value']}
|
||||
placeholder={t(
|
||||
'resource.function.enter_select_udf_resources_tips'
|
||||
)}
|
||||
defaultValue={this.functionForm.resourceId}
|
||||
disabled={this.uploadShow}
|
||||
showPath={false}
|
||||
></NTreeSelect>
|
||||
<NButton
|
||||
type='primary'
|
||||
ghost
|
||||
onClick={() => (this.uploadShow = !this.uploadShow)}
|
||||
>
|
||||
{t('resource.function.upload_resources')}
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
</NFormItem>
|
||||
{this.uploadShow && (
|
||||
<NForm
|
||||
rules={this.uploadRules}
|
||||
ref='uploadFormRef'
|
||||
label-placement='left'
|
||||
label-width='160'
|
||||
>
|
||||
<NFormItem
|
||||
label={t('resource.function.udf_resources_directory')}
|
||||
path='pid'
|
||||
show-feedback={false}
|
||||
style={{ marginBottom: '5px' }}
|
||||
>
|
||||
<NTreeSelect
|
||||
ref='treeRef'
|
||||
options={this.udfResourceDirList}
|
||||
label-field='fullName'
|
||||
key-field='id'
|
||||
v-model={[this.uploadForm.pid, 'value']}
|
||||
placeholder={t(
|
||||
'resource.function.enter_select_udf_resources_directory_tips'
|
||||
)}
|
||||
defaultValue={this.uploadForm.pid}
|
||||
></NTreeSelect>
|
||||
</NFormItem>
|
||||
<NFormItem
|
||||
label=' '
|
||||
show-feedback={false}
|
||||
style={{ marginBottom: '5px' }}
|
||||
>
|
||||
<NInputGroup>
|
||||
<NInput
|
||||
v-model={[this.uploadForm.name, 'value']}
|
||||
placeholder={t('resource.function.enter_name_tips')}
|
||||
/>
|
||||
<NButton>
|
||||
<NUpload
|
||||
v-model={[this.uploadForm.file, 'value']}
|
||||
customRequest={this.customRequest}
|
||||
showFileList={false}
|
||||
>
|
||||
<NButton text>
|
||||
上传
|
||||
<NIcon>
|
||||
<CloudUploadOutlined />
|
||||
</NIcon>
|
||||
</NButton>
|
||||
</NUpload>
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
</NFormItem>
|
||||
<NFormItem
|
||||
label=' '
|
||||
path='description'
|
||||
show-feedback={false}
|
||||
style={{ marginBottom: '5px' }}
|
||||
>
|
||||
<NInput
|
||||
type='textarea'
|
||||
v-model={[this.uploadForm.description, 'value']}
|
||||
placeholder={t('resource.function.enter_description_tips')}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label=' '>
|
||||
<NButton onClick={this.handleUpload}>上传UDF资源</NButton>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
)}
|
||||
|
||||
<NFormItem
|
||||
label={t('resource.function.instructions')}
|
||||
path='description'
|
||||
>
|
||||
<NInput
|
||||
type='textarea'
|
||||
v-model={[this.functionForm.description, 'value']}
|
||||
placeholder={t('resource.function.enter_instructions_tips')}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { reactive, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { FormRules } from 'naive-ui'
|
||||
|
||||
export const useForm = () => {
|
||||
const { t } = useI18n()
|
||||
|
||||
const state = reactive({
|
||||
functionFormRef: ref(),
|
||||
functionForm: {
|
||||
type: 'HIVE',
|
||||
funcName: '',
|
||||
className: '',
|
||||
argTypes: '',
|
||||
database: '',
|
||||
description: '',
|
||||
resourceId: -1
|
||||
},
|
||||
rules: {
|
||||
type: {
|
||||
required: true,
|
||||
trigger: ['input', 'blur'],
|
||||
validator() {
|
||||
if (!state.functionForm.type) {
|
||||
return new Error(t('resource.function.enter_name_tips'))
|
||||
}
|
||||
}
|
||||
},
|
||||
funcName: {
|
||||
required: true,
|
||||
trigger: ['input', 'blur'],
|
||||
validator() {
|
||||
if (!state.functionForm.funcName) {
|
||||
return new Error(t('resource.function.enter_name_tips'))
|
||||
}
|
||||
}
|
||||
},
|
||||
className: {
|
||||
required: true,
|
||||
trigger: ['input', 'blur'],
|
||||
validator() {
|
||||
if (!state.functionForm.className) {
|
||||
return new Error(t('resource.function.enter_name_tips'))
|
||||
}
|
||||
}
|
||||
},
|
||||
resourceId: {
|
||||
required: true,
|
||||
trigger: ['input', 'blur'],
|
||||
validator() {
|
||||
if (state.functionForm.resourceId === -1) {
|
||||
return new Error(t('resource.function.enter_name_tips'))
|
||||
}
|
||||
}
|
||||
}
|
||||
} as FormRules
|
||||
})
|
||||
|
||||
const uploadState = reactive({
|
||||
uploadFormRef: ref(),
|
||||
uploadForm: {
|
||||
name: '',
|
||||
file: '',
|
||||
description: '',
|
||||
pid: -1,
|
||||
currentDir: '/'
|
||||
},
|
||||
uploadRules: {
|
||||
pid: {
|
||||
required: true,
|
||||
trigger: ['input', 'blur'],
|
||||
validator() {
|
||||
if (uploadState.uploadForm.pid === -1) {
|
||||
return new Error(t('resource.function.enter_name_tips'))
|
||||
}
|
||||
}
|
||||
}
|
||||
} as FormRules
|
||||
})
|
||||
|
||||
return {
|
||||
state,
|
||||
uploadState
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash'
|
||||
import { ref, reactive, SetupContext } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import {
|
||||
createResource,
|
||||
createUdfFunc,
|
||||
queryResourceList,
|
||||
updateUdfFunc
|
||||
} from '@/service/modules/resources'
|
||||
import { useAsyncState } from '@vueuse/core'
|
||||
|
||||
export function useModal(
|
||||
state: any,
|
||||
uploadState: any,
|
||||
ctx: SetupContext<('update:show' | 'updateList')[]>
|
||||
) {
|
||||
const { t } = useI18n()
|
||||
|
||||
const handleCreateFunc = async () => {
|
||||
submitRequest(
|
||||
async () =>
|
||||
await createUdfFunc(
|
||||
{
|
||||
...state.functionForm
|
||||
},
|
||||
state.functionForm.resourceId
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const handleRenameFunc = async (id: number) => {
|
||||
submitRequest(async () => {
|
||||
await updateUdfFunc(
|
||||
{
|
||||
...state.functionForm,
|
||||
id
|
||||
},
|
||||
state.functionForm.resourceId,
|
||||
id
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const submitRequest = (serviceHandle: any) => {
|
||||
state.functionFormRef.validate(async (valid: any) => {
|
||||
if (!valid) {
|
||||
try {
|
||||
await serviceHandle()
|
||||
window.$message.success(t('resource.udf.success'))
|
||||
ctx.emit('updateList')
|
||||
ctx.emit('update:show')
|
||||
} catch (error: any) {
|
||||
window.$message.error(error.message)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const variables = reactive({
|
||||
uploadShow: ref(false),
|
||||
udfResourceList: [],
|
||||
udfResourceDirList: []
|
||||
})
|
||||
|
||||
const filterEmptyDirectory = (list: any) => {
|
||||
for (const item of list) {
|
||||
if (item.children) {
|
||||
if (!/\.jar$/.test(item.name)) {
|
||||
item.disabled = true
|
||||
}
|
||||
filterEmptyDirectory(item.children)
|
||||
}
|
||||
}
|
||||
return list.filter(
|
||||
(n: any) =>
|
||||
(/\.jar$/.test(n.name) && n.children.length === 0) ||
|
||||
(!/\.jar$/.test(n.name) && n.children.length > 0)
|
||||
)
|
||||
}
|
||||
|
||||
// filterJarFile
|
||||
const filterJarFile = (array: any) => {
|
||||
for (const item of array) {
|
||||
if (item.children) {
|
||||
item.children = filterJarFile(item.children)
|
||||
}
|
||||
}
|
||||
return array.filter((n: any) => !/\.jar$/.test(n.name))
|
||||
}
|
||||
|
||||
// recursiveTree
|
||||
const recursiveTree = (item: any) => {
|
||||
// Recursive convenience tree structure
|
||||
item.forEach((item: any) => {
|
||||
item.children === '' ||
|
||||
item.children === undefined ||
|
||||
item.children === null ||
|
||||
item.children.length === 0
|
||||
? delete item.children
|
||||
: recursiveTree(item.children)
|
||||
})
|
||||
}
|
||||
|
||||
const getUdfList = () => {
|
||||
const { state } = useAsyncState(
|
||||
queryResourceList({ type: 'UDF' }).then((res: any) => {
|
||||
let item = res
|
||||
let item1 = _.cloneDeep(res)
|
||||
|
||||
filterEmptyDirectory(item)
|
||||
item = filterEmptyDirectory(item)
|
||||
recursiveTree(item)
|
||||
recursiveTree(filterJarFile(item1))
|
||||
item1 = item1.filter((item: any) => {
|
||||
if (item.dirctory) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
variables.udfResourceList = item
|
||||
variables.udfResourceDirList = item1
|
||||
}),
|
||||
{}
|
||||
)
|
||||
return state
|
||||
}
|
||||
|
||||
const resetUploadForm = () => {
|
||||
uploadState.uploadForm.name = ''
|
||||
uploadState.uploadForm.file = ''
|
||||
uploadState.uploadForm.pid = -1
|
||||
uploadState.uploadForm.currentDir = '/'
|
||||
uploadState.uploadForm.description = ''
|
||||
}
|
||||
|
||||
const handleUploadFile = () => {
|
||||
uploadState.uploadFormRef.validate(async (valid: any) => {
|
||||
if (!valid) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', uploadState.uploadForm.file)
|
||||
formData.append('type', 'UDF')
|
||||
formData.append('name', uploadState.uploadForm.name)
|
||||
formData.append('pid', uploadState.uploadForm.pid)
|
||||
formData.append('currentDir', uploadState.uploadForm.currentDir)
|
||||
formData.append('description', uploadState.uploadForm.description)
|
||||
|
||||
try {
|
||||
const res = await createResource(formData as any)
|
||||
window.$message.success(t('resource.function.success'))
|
||||
variables.uploadShow = false
|
||||
resetUploadForm()
|
||||
getUdfList()
|
||||
state.functionForm.resourceId = res.id
|
||||
} catch (error: any) {
|
||||
window.$message.error(error.message)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
variables,
|
||||
getUdfList,
|
||||
handleCreateFunc,
|
||||
handleRenameFunc,
|
||||
handleUploadFile
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
|
||||
.card {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 10px 0;
|
||||
.right {
|
||||
> .search {
|
||||
.list {
|
||||
float: right;
|
||||
margin: 3px 0 3px 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
table {
|
||||
width: 100%;
|
||||
tr {
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
th,
|
||||
td {
|
||||
&:nth-child(1) {
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
th {
|
||||
&:nth-child(1) {
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
}
|
||||
> span {
|
||||
font-size: 12px;
|
||||
color: #555;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineComponent, Ref, toRefs, onMounted, toRef } from 'vue'
|
||||
import {
|
||||
NIcon,
|
||||
NSpace,
|
||||
NDataTable,
|
||||
NButton,
|
||||
NPagination,
|
||||
NInput
|
||||
} from 'naive-ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { SearchOutlined } from '@vicons/antd'
|
||||
import Card from '@/components/card'
|
||||
import FolderModal from './components/function-modal'
|
||||
import { useTable } from './use-table'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'function-manage',
|
||||
setup() {
|
||||
const { variables, getTableData } = useTable()
|
||||
|
||||
const requestData = () => {
|
||||
getTableData({
|
||||
id: variables.id,
|
||||
pageSize: variables.pageSize,
|
||||
pageNo: variables.page,
|
||||
searchVal: variables.searchVal
|
||||
})
|
||||
}
|
||||
|
||||
const handleUpdateList = () => {
|
||||
requestData()
|
||||
}
|
||||
|
||||
const handleChangePageSize = () => {
|
||||
variables.page = 1
|
||||
requestData()
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
variables.page = 1
|
||||
requestData()
|
||||
}
|
||||
|
||||
const handleShowModal = (showRef: Ref<Boolean>) => {
|
||||
showRef.value = true
|
||||
}
|
||||
|
||||
const handleCreateFolder = () => {
|
||||
variables.row = {}
|
||||
handleShowModal(toRef(variables, 'showRef'))
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
requestData()
|
||||
})
|
||||
|
||||
return {
|
||||
requestData,
|
||||
handleSearch,
|
||||
handleUpdateList,
|
||||
handleCreateFolder,
|
||||
handleChangePageSize,
|
||||
...toRefs(variables)
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { t } = useI18n()
|
||||
|
||||
return (
|
||||
<div class={styles.content}>
|
||||
<Card class={styles.card}>
|
||||
<div class={styles.header}>
|
||||
<NSpace>
|
||||
<NButton type='primary' onClick={this.handleCreateFolder}>
|
||||
{t('resource.function.create_udf_function')}
|
||||
</NButton>
|
||||
</NSpace>
|
||||
<div class={styles.right}>
|
||||
<div class={styles.search}>
|
||||
<div class={styles.list}>
|
||||
<NButton type='primary' onClick={this.handleSearch}>
|
||||
<NIcon>
|
||||
<SearchOutlined />
|
||||
</NIcon>
|
||||
</NButton>
|
||||
</div>
|
||||
<div class={styles.list}>
|
||||
<NInput
|
||||
placeholder={t('resource.function.enter_keyword_tips')}
|
||||
v-model={[this.searchVal, 'value']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card title={t('resource.function.udf_function')}>
|
||||
<NDataTable
|
||||
columns={this.columns}
|
||||
data={this.tableData}
|
||||
striped
|
||||
size={'small'}
|
||||
class={styles.table}
|
||||
/>
|
||||
<div class={styles.pagination}>
|
||||
<NPagination
|
||||
v-model:page={this.page}
|
||||
v-model:page-size={this.pageSize}
|
||||
page-count={this.totalPage}
|
||||
show-size-picker
|
||||
page-sizes={[10, 30, 50]}
|
||||
show-quick-jumper
|
||||
onUpdatePage={this.requestData}
|
||||
onUpdatePageSize={this.handleChangePageSize}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
<FolderModal
|
||||
v-model:row={this.row}
|
||||
v-model:show={this.showRef}
|
||||
onUpdateList={this.handleUpdateList}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export interface IUdfFunctionParam {
|
||||
id: number
|
||||
pageSize: number
|
||||
pageNo: number
|
||||
searchVal: string | undefined
|
||||
}
|
||||
|
||||
export interface IUdf {
|
||||
id: number
|
||||
userId: number
|
||||
type: 'HIVE'
|
||||
funcName: string
|
||||
className: string
|
||||
resourceId: number
|
||||
resourceName: string
|
||||
argTypes: string
|
||||
database: string
|
||||
description: string
|
||||
createTime: string
|
||||
updateTime: string
|
||||
}
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { h, ref, reactive } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import type { Router } from 'vue-router'
|
||||
import type { TableColumns } from 'naive-ui/es/data-table/src/interface'
|
||||
import { NSpace, NTooltip, NButton, NPopconfirm } from 'naive-ui'
|
||||
import { EditOutlined, DeleteOutlined } from '@vicons/antd'
|
||||
import { useAsyncState } from '@vueuse/core'
|
||||
import {
|
||||
queryUdfFuncListPaging,
|
||||
deleteUdfFunc
|
||||
} from '@/service/modules/resources'
|
||||
import { IUdfFunctionParam } from './types'
|
||||
|
||||
export function useTable() {
|
||||
const { t } = useI18n()
|
||||
const router: Router = useRouter()
|
||||
|
||||
const columns: TableColumns<any> = [
|
||||
{
|
||||
title: t('resource.function.id'),
|
||||
key: 'id',
|
||||
width: 50,
|
||||
render: (_row, index) => index + 1
|
||||
},
|
||||
{
|
||||
title: t('resource.function.udf_function_name'),
|
||||
key: 'funcName'
|
||||
},
|
||||
{
|
||||
title: t('resource.function.class_name'),
|
||||
key: 'className'
|
||||
},
|
||||
{
|
||||
title: t('resource.function.type'),
|
||||
key: 'type'
|
||||
},
|
||||
{
|
||||
title: t('resource.function.description'),
|
||||
key: 'description'
|
||||
},
|
||||
{
|
||||
title: t('resource.function.jar_package'),
|
||||
key: 'resourceName'
|
||||
},
|
||||
{
|
||||
title: t('resource.function.update_time'),
|
||||
key: 'updateTime'
|
||||
},
|
||||
{
|
||||
title: t('resource.function.operation'),
|
||||
key: 'operation',
|
||||
render: (row) => {
|
||||
return h(NSpace, null, {
|
||||
default: () => [
|
||||
h(
|
||||
NTooltip,
|
||||
{},
|
||||
{
|
||||
trigger: () =>
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
circle: true,
|
||||
type: 'info',
|
||||
size: 'tiny',
|
||||
onClick: () => {
|
||||
handleEdit(row)
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: () => h(EditOutlined)
|
||||
}
|
||||
),
|
||||
default: () => t('resource.function.edit')
|
||||
}
|
||||
),
|
||||
h(
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => {
|
||||
handleDelete(row.id)
|
||||
}
|
||||
},
|
||||
{
|
||||
trigger: () =>
|
||||
h(
|
||||
NTooltip,
|
||||
{},
|
||||
{
|
||||
trigger: () =>
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
circle: true,
|
||||
type: 'error',
|
||||
size: 'tiny'
|
||||
},
|
||||
{
|
||||
icon: () => h(DeleteOutlined)
|
||||
}
|
||||
),
|
||||
default: () => t('resource.function.delete')
|
||||
}
|
||||
),
|
||||
default: () => t('resource.function.delete_confirm')
|
||||
}
|
||||
)
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const variables = reactive({
|
||||
columns,
|
||||
row: {},
|
||||
tableData: [],
|
||||
id: ref(Number(router.currentRoute.value.params.id) || -1),
|
||||
page: ref(1),
|
||||
pageSize: ref(10),
|
||||
searchVal: ref(),
|
||||
totalPage: ref(1),
|
||||
showRef: ref(false)
|
||||
})
|
||||
|
||||
const getTableData = (params: IUdfFunctionParam) => {
|
||||
const { state } = useAsyncState(
|
||||
queryUdfFuncListPaging({ ...params }).then((res: any) => {
|
||||
variables.totalPage = res.totalPage
|
||||
variables.tableData = res.totalList.map((item: any) => {
|
||||
return { ...item }
|
||||
})
|
||||
}),
|
||||
{ total: 0, table: [] }
|
||||
)
|
||||
return state
|
||||
}
|
||||
|
||||
const handleEdit = (row: any) => {
|
||||
variables.showRef = true
|
||||
variables.row = row
|
||||
}
|
||||
|
||||
const handleDelete = (id: number) => {
|
||||
/* after deleting data from the current page, you need to jump forward when the page is empty. */
|
||||
if (variables.tableData.length === 1 && variables.page > 1) {
|
||||
variables.page -= 1
|
||||
}
|
||||
|
||||
deleteUdfFunc(id).then(() =>
|
||||
getTableData({
|
||||
id: variables.id,
|
||||
pageSize: variables.pageSize,
|
||||
pageNo: variables.page,
|
||||
searchVal: variables.searchVal
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
variables,
|
||||
getTableData
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue