表单设计和表单发布前端页面

main
滕嵩 2024-03-08 10:12:21 +08:00
parent eff00e8c29
commit 11a118c28a
8 changed files with 1076 additions and 0 deletions

View File

@ -0,0 +1,90 @@
<template>
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
showFooter
:title="getTitle"
width="50%"
@ok="handleSubmit"
>
<BasicForm @register="registerForm" />
</BasicDrawer>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicForm, useForm } from '@/components/Form';
import { formSchema } from './formModule.data';
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
import { getMenuList, addMenu, editMenu, addButton, editButton } from '@/api/demo/system';
defineOptions({ name: 'MenuDrawer' });
const emit = defineEmits(['success', 'register']);
const isUpdate = ref(true);
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
labelWidth: 100,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { lg: 12, md: 24 },
});
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
resetFields();
setDrawerProps({ confirmLoading: false });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
setFieldsValue({
...data.record,
});
}
const treeData = await getMenuList();
updateSchema({
field: 'parentId',
componentProps: { treeData },
});
updateSchema({
field: 'moduleId',
componentProps: { treeData },
});
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增菜单' : '编辑菜单'));
async function handleSubmit() {
try {
const values = await validate();
setDrawerProps({ confirmLoading: true });
// TODO custom api
console.log(values);
if (values.type == '1') {
console.log('新增菜单');
delete values.type;
//
if (!unref(isUpdate)) {
const data = await addMenu(values);
} else {
const data = await editMenu(values);
}
closeDrawer();
emit('success');
} else {
console.log('新增按钮');
//
delete values.type;
if (!unref(isUpdate)) {
const data = await addButton(values);
} else {
const data = await editButton(values);
}
closeDrawer();
emit('success');
}
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>

View File

@ -0,0 +1,111 @@
<template>
<div class="m-4 mr-0 overflow-hidden bg-white">
<BasicTree
ref="asyncExpandTreeRef"
title="菜单列表"
toolbar
search
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData
:actionList="actionList"
:renderIcon="createIcon"
:clickRowToExpand="false"
:treeData="treeData"
:fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true"
@select="handleSelect"
/>
<BasicModal
@register="register"
title="删除"
:helpMessage="['提示1', '提示2']"
@ok="handleSubmit"
>
确认要删除菜单吗
</BasicModal>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, h, nextTick, unref } from 'vue';
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
import { getMenuList, deleteMenu } from '@/api/demo/system';
import { FormOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { BasicModal, useModal } from '@/components/Modal';
import { router } from '@/router';
const [register, { closeModal, openModal }] = useModal();
defineOptions({ name: 'DeptTree' });
const emit = defineEmits(['select', 'edit']);
const treeData = ref<TreeItem[]>([]);
let selectItemId = ref('');
const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
async function handleSubmit() {
var query = [selectItemId.value];
const data = await deleteMenu(query);
closeModal();
}
async function fetch() {
treeData.value = (await getMenuList()) as unknown as TreeItem[];
//
nextTick(() => {
unref(asyncExpandTreeRef)?.expandAll(true);
});
}
function handleSelect(keys) {
emit('select', keys[0]);
}
const btnList = router.currentRoute.value.meta.elements;
const actionList: TreeActionItem[] = [];
btnList.forEach((element) => {
if (element.domId == 'btnEdit') {
actionList.push({
render: (node) => {
return h(FormOutlined, {
class: 'ml-2',
onClick: () => {
emit('edit', node);
},
});
},
});
} else if (element.domId == 'btnDelete') {
actionList.push({
render: (node) => {
return h(DeleteOutlined, {
class: 'ml-2',
onClick: () => {
selectItemId.value = node.id;
openModal(true, {
isUpdate: false,
});
},
});
},
});
}
});
function createIcon({ level }) {
if (level === 1) {
return 'ion:git-compare-outline';
}
if (level === 2) {
return 'ion:home';
}
if (level === 3) {
return 'ion:airplane';
}
return '';
}
onMounted(() => {
fetch();
});
defineExpose({
fetch,
});
</script>

View File

@ -0,0 +1,197 @@
import { BasicColumn, FormSchema } from '@/components/Table';
import { h } from 'vue';
import { Tag } from 'ant-design-vue';
import Icon from '@/components/Icon/Icon.vue';
export const columns: BasicColumn[] = [
{
title: '按钮名称',
dataIndex: 'name',
},
{
title: 'DOMID',
dataIndex: 'domId',
},
{
title: '排序',
dataIndex: 'sort',
},
];
const isDir = (type: string) => type === '0';
const isMenu = (type: string) => type === '1';
const isButton = (type: string) => type === '2';
export const searchFormSchema: FormSchema[] = [
{
field: 'key',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
];
export const formSchema: FormSchema[] = [
{
field: 'type',
label: '类型',
component: 'RadioButtonGroup',
defaultValue: '1',
componentProps: {
options: [
// { label: '目录', value: '0' },
{ label: '菜单', value: '1' },
{ label: '按钮', value: '2' },
],
},
colProps: { lg: 24, md: 24 },
},
{
field: 'id',
label: '名称',
component: 'Input',
ifShow: false,
},
{
field: 'name',
label: '名称',
component: 'Input',
required: true,
},
{
field: 'parentId',
label: '上级',
component: 'TreeSelect',
componentProps: {
fieldNames: {
label: 'name',
key: 'id',
value: 'id',
},
getPopupContainer: () => document.body,
},
ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'moduleId',
label: '菜单',
component: 'TreeSelect',
componentProps: {
fieldNames: {
label: 'name',
key: 'id',
value: 'id',
},
getPopupContainer: () => document.body,
},
ifShow: ({ values }) => isButton(values.type),
required: true,
},
{
field: 'domId',
label: 'DMOID',
component: 'Input',
required: true,
ifShow: ({ values }) => isButton(values.type),
},
{
field: 'sortNo',
label: '排序',
component: 'InputNumber',
ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'sort',
label: '排序',
component: 'InputNumber',
ifShow: ({ values }) => isButton(values.type),
},
{
field: 'class',
helpMessage: ['参考参数值', 'success、warning、error'],
label: '样式',
component: 'Input',
ifShow: ({ values }) => isButton(values.type),
},
{
field: 'iconName',
label: '图标',
component: 'IconPicker',
ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'url',
label: '路由地址',
component: 'Input',
required: true,
ifShow: ({ values }) => !isButton(values.type),
},
// {
// field: 'component',
// label: '组件路径',
// component: 'Input',
// ifShow: ({ values }) => isMenu(values.type),
// },
{
field: 'code',
label: '权限标识',
component: 'Input',
ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'status',
label: '是否系统',
component: 'RadioButtonGroup',
defaultValue: 1,
componentProps: {
options: [
{ label: '是', value: 0 },
{ label: '否', value: 1 },
],
},
ifShow: ({ values }) => !isButton(values.type),
},
// {
// field: 'isExt',
// label: '是否外链',
// component: 'RadioButtonGroup',
// defaultValue: '0',
// componentProps: {
// options: [
// { label: '否', value: '0' },
// { label: '是', value: '1' },
// ],
// },
// ifShow: ({ values }) => !isButton(values.type),
// },
// {
// field: 'keepalive',
// label: '是否缓存',
// component: 'RadioButtonGroup',
// defaultValue: '0',
// componentProps: {
// options: [
// { label: '否', value: '0' },
// { label: '是', value: '1' },
// ],
// },
// ifShow: ({ values }) => isMenu(values.type),
// },
// {
// field: 'show',
// label: '是否显示',
// component: 'RadioButtonGroup',
// defaultValue: '0',
// componentProps: {
// options: [
// { label: '是', value: '0' },
// { label: '否', value: '1' },
// ],
// },
// ifShow: ({ values }) => !isButton(values.type),
// },
];

View File

@ -0,0 +1,140 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<MenuTree ref="childRef" class="w-1/4 xl:w-1/5" @select="handleSelect" @edit="editMenu" />
<BasicTable
class="w-3/4 xl:w-4/5"
@register="registerTable"
@fetch-success="onFetchSuccess"
:searchInfo="searchInfo"
>
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btn-event="onBtnClicked" />
</template>
</BasicTable>
<MenuDrawer @register="registerDrawer" @success="handleSuccess" />
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, nextTick, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getMenuList, getButtonList, getMenuDetail, deleteButton } from '@/api/demo/system';
import { PageWrapper } from '@/components/Page';
import MenuTree from './FormModuleTree.vue';
import { useDrawer } from '@/components/Drawer';
import MenuDrawer from './FormModuleDrawer.vue';
import { columns, searchFormSchema } from './formModule.data';
import PermissionBtn from '@/components/PermissionBtn/index.vue';
import { useMessage } from '@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
defineOptions({ name: 'MenuManagement' });
const searchInfo = reactive<Recordable>({});
const [registerDrawer, { openDrawer }] = useDrawer();
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
title: '按钮列表',
api: getButtonList,
columns,
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
isTreeTable: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
rowSelection: {
//
// type: 'checkbox',
type: 'radio',
},
handleSearchInfoFn(info) {
return info;
},
});
const childRef = ref<any>();
function handleCreate() {
openDrawer(true, {
isUpdate: false,
});
}
function handleEdit() {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一个按钮进行编辑');
}
const record = rows[0];
record.type = '2';
openDrawer(true, {
record,
isUpdate: true,
});
}
async function editMenu(node: Recordable) {
var query = {
id: node.id,
};
const record = await getMenuDetail(query);
record.type = '1';
openDrawer(true, {
record,
isUpdate: true,
});
}
function handleSelect(ModuleId = '') {
searchInfo.ModuleId = ModuleId;
clearSelectedRowKeys();
reload();
}
async function handleDelete(record: Recordable) {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一个按钮进行删除');
}
const query = [rows[0].id];
createConfirm({
iconType: 'info',
title: '删除',
content: '确定要删除当前按钮吗',
onOk: async () => {
const data = await deleteButton(query);
reload();
},
});
}
function handleSuccess() {
childRef.value.fetch();
clearSelectedRowKeys();
reload();
}
function onFetchSuccess() {
//
nextTick(expandAll);
}
function onBtnClicked(domId) {
console.log(domId);
switch (domId) {
case 'btnAdd':
handleCreate();
break;
case 'btnEdit':
handleEdit();
break;
case 'btnDelete':
handleDelete();
break;
default:
break;
}
}
</script>

View File

@ -0,0 +1,90 @@
<template>
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
showFooter
:title="getTitle"
width="50%"
@ok="handleSubmit"
>
<BasicForm @register="registerForm" />
</BasicDrawer>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicForm, useForm } from '@/components/Form';
import { formSchema } from './formScheme.data';
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
import { getMenuList, addMenu, editMenu, addButton, editButton } from '@/api/demo/system';
defineOptions({ name: 'MenuDrawer' });
const emit = defineEmits(['success', 'register']);
const isUpdate = ref(true);
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
labelWidth: 100,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { lg: 12, md: 24 },
});
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
resetFields();
setDrawerProps({ confirmLoading: false });
isUpdate.value = !!data?.isUpdate;
if (unref(isUpdate)) {
setFieldsValue({
...data.record,
});
}
const treeData = await getMenuList();
updateSchema({
field: 'parentId',
componentProps: { treeData },
});
updateSchema({
field: 'moduleId',
componentProps: { treeData },
});
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增菜单' : '编辑菜单'));
async function handleSubmit() {
try {
const values = await validate();
setDrawerProps({ confirmLoading: true });
// TODO custom api
console.log(values);
if (values.type == '1') {
console.log('新增菜单');
delete values.type;
//
if (!unref(isUpdate)) {
const data = await addMenu(values);
} else {
const data = await editMenu(values);
}
closeDrawer();
emit('success');
} else {
console.log('新增按钮');
//
delete values.type;
if (!unref(isUpdate)) {
const data = await addButton(values);
} else {
const data = await editButton(values);
}
closeDrawer();
emit('success');
}
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>

View File

@ -0,0 +1,111 @@
<template>
<div class="m-4 mr-0 overflow-hidden bg-white">
<BasicTree
ref="asyncExpandTreeRef"
title="菜单列表"
toolbar
search
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData
:actionList="actionList"
:renderIcon="createIcon"
:clickRowToExpand="false"
:treeData="treeData"
:fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true"
@select="handleSelect"
/>
<BasicModal
@register="register"
title="删除"
:helpMessage="['提示1', '提示2']"
@ok="handleSubmit"
>
确认要删除菜单吗
</BasicModal>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, h, nextTick, unref } from 'vue';
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
import { getMenuList, deleteMenu } from '@/api/demo/system';
import { FormOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { BasicModal, useModal } from '@/components/Modal';
import { router } from '@/router';
const [register, { closeModal, openModal }] = useModal();
defineOptions({ name: 'DeptTree' });
const emit = defineEmits(['select', 'edit']);
const treeData = ref<TreeItem[]>([]);
let selectItemId = ref('');
const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
async function handleSubmit() {
var query = [selectItemId.value];
const data = await deleteMenu(query);
closeModal();
}
async function fetch() {
treeData.value = (await getMenuList()) as unknown as TreeItem[];
//
nextTick(() => {
unref(asyncExpandTreeRef)?.expandAll(true);
});
}
function handleSelect(keys) {
emit('select', keys[0]);
}
const btnList = router.currentRoute.value.meta.elements;
const actionList: TreeActionItem[] = [];
btnList.forEach((element) => {
if (element.domId == 'btnEdit') {
actionList.push({
render: (node) => {
return h(FormOutlined, {
class: 'ml-2',
onClick: () => {
emit('edit', node);
},
});
},
});
} else if (element.domId == 'btnDelete') {
actionList.push({
render: (node) => {
return h(DeleteOutlined, {
class: 'ml-2',
onClick: () => {
selectItemId.value = node.id;
openModal(true, {
isUpdate: false,
});
},
});
},
});
}
});
function createIcon({ level }) {
if (level === 1) {
return 'ion:git-compare-outline';
}
if (level === 2) {
return 'ion:home';
}
if (level === 3) {
return 'ion:airplane';
}
return '';
}
onMounted(() => {
fetch();
});
defineExpose({
fetch,
});
</script>

View File

@ -0,0 +1,197 @@
import { BasicColumn, FormSchema } from '@/components/Table';
import { h } from 'vue';
import { Tag } from 'ant-design-vue';
import Icon from '@/components/Icon/Icon.vue';
export const columns: BasicColumn[] = [
{
title: '按钮名称',
dataIndex: 'name',
},
{
title: 'DOMID',
dataIndex: 'domId',
},
{
title: '排序',
dataIndex: 'sort',
},
];
const isDir = (type: string) => type === '0';
const isMenu = (type: string) => type === '1';
const isButton = (type: string) => type === '2';
export const searchFormSchema: FormSchema[] = [
{
field: 'key',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
];
export const formSchema: FormSchema[] = [
{
field: 'type',
label: '类型',
component: 'RadioButtonGroup',
defaultValue: '1',
componentProps: {
options: [
// { label: '目录', value: '0' },
{ label: '菜单', value: '1' },
{ label: '按钮', value: '2' },
],
},
colProps: { lg: 24, md: 24 },
},
{
field: 'id',
label: '名称',
component: 'Input',
ifShow: false,
},
{
field: 'name',
label: '名称',
component: 'Input',
required: true,
},
{
field: 'parentId',
label: '上级',
component: 'TreeSelect',
componentProps: {
fieldNames: {
label: 'name',
key: 'id',
value: 'id',
},
getPopupContainer: () => document.body,
},
ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'moduleId',
label: '菜单',
component: 'TreeSelect',
componentProps: {
fieldNames: {
label: 'name',
key: 'id',
value: 'id',
},
getPopupContainer: () => document.body,
},
ifShow: ({ values }) => isButton(values.type),
required: true,
},
{
field: 'domId',
label: 'DMOID',
component: 'Input',
required: true,
ifShow: ({ values }) => isButton(values.type),
},
{
field: 'sortNo',
label: '排序',
component: 'InputNumber',
ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'sort',
label: '排序',
component: 'InputNumber',
ifShow: ({ values }) => isButton(values.type),
},
{
field: 'class',
helpMessage: ['参考参数值', 'success、warning、error'],
label: '样式',
component: 'Input',
ifShow: ({ values }) => isButton(values.type),
},
{
field: 'iconName',
label: '图标',
component: 'IconPicker',
ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'url',
label: '路由地址',
component: 'Input',
required: true,
ifShow: ({ values }) => !isButton(values.type),
},
// {
// field: 'component',
// label: '组件路径',
// component: 'Input',
// ifShow: ({ values }) => isMenu(values.type),
// },
{
field: 'code',
label: '权限标识',
component: 'Input',
ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'status',
label: '是否系统',
component: 'RadioButtonGroup',
defaultValue: 1,
componentProps: {
options: [
{ label: '是', value: 0 },
{ label: '否', value: 1 },
],
},
ifShow: ({ values }) => !isButton(values.type),
},
// {
// field: 'isExt',
// label: '是否外链',
// component: 'RadioButtonGroup',
// defaultValue: '0',
// componentProps: {
// options: [
// { label: '否', value: '0' },
// { label: '是', value: '1' },
// ],
// },
// ifShow: ({ values }) => !isButton(values.type),
// },
// {
// field: 'keepalive',
// label: '是否缓存',
// component: 'RadioButtonGroup',
// defaultValue: '0',
// componentProps: {
// options: [
// { label: '否', value: '0' },
// { label: '是', value: '1' },
// ],
// },
// ifShow: ({ values }) => isMenu(values.type),
// },
// {
// field: 'show',
// label: '是否显示',
// component: 'RadioButtonGroup',
// defaultValue: '0',
// componentProps: {
// options: [
// { label: '是', value: '0' },
// { label: '否', value: '1' },
// ],
// },
// ifShow: ({ values }) => !isButton(values.type),
// },
];

View File

@ -0,0 +1,140 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<MenuTree ref="childRef" class="w-1/4 xl:w-1/5" @select="handleSelect" @edit="editMenu" />
<BasicTable
class="w-3/4 xl:w-4/5"
@register="registerTable"
@fetch-success="onFetchSuccess"
:searchInfo="searchInfo"
>
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btn-event="onBtnClicked" />
</template>
</BasicTable>
<MenuDrawer @register="registerDrawer" @success="handleSuccess" />
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, nextTick, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getMenuList, getButtonList, getMenuDetail, deleteButton } from '@/api/demo/system';
import { PageWrapper } from '@/components/Page';
import MenuTree from './FormSchemeTree.vue';
import { useDrawer } from '@/components/Drawer';
import MenuDrawer from './FormSchemeDrawer.vue';
import { columns, searchFormSchema } from './formScheme.data';
import PermissionBtn from '@/components/PermissionBtn/index.vue';
import { useMessage } from '@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
defineOptions({ name: 'MenuManagement' });
const searchInfo = reactive<Recordable>({});
const [registerDrawer, { openDrawer }] = useDrawer();
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
title: '按钮列表',
api: getButtonList,
columns,
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
isTreeTable: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
rowSelection: {
//
// type: 'checkbox',
type: 'radio',
},
handleSearchInfoFn(info) {
return info;
},
});
const childRef = ref<any>();
function handleCreate() {
openDrawer(true, {
isUpdate: false,
});
}
function handleEdit() {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一个按钮进行编辑');
}
const record = rows[0];
record.type = '2';
openDrawer(true, {
record,
isUpdate: true,
});
}
async function editMenu(node: Recordable) {
var query = {
id: node.id,
};
const record = await getMenuDetail(query);
record.type = '1';
openDrawer(true, {
record,
isUpdate: true,
});
}
function handleSelect(ModuleId = '') {
searchInfo.ModuleId = ModuleId;
clearSelectedRowKeys();
reload();
}
async function handleDelete(record: Recordable) {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一个按钮进行删除');
}
const query = [rows[0].id];
createConfirm({
iconType: 'info',
title: '删除',
content: '确定要删除当前按钮吗',
onOk: async () => {
const data = await deleteButton(query);
reload();
},
});
}
function handleSuccess() {
childRef.value.fetch();
clearSelectedRowKeys();
reload();
}
function onFetchSuccess() {
//
nextTick(expandAll);
}
function onBtnClicked(domId) {
console.log(domId);
switch (domId) {
case 'btnAdd':
handleCreate();
break;
case 'btnEdit':
handleEdit();
break;
case 'btnDelete':
handleDelete();
break;
default:
break;
}
}
</script>