表单设计和表单发布前端页面
parent
eff00e8c29
commit
11a118c28a
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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),
|
||||
// },
|
||||
];
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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),
|
||||
// },
|
||||
];
|
||||
|
|
@ -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>
|
||||
Loading…
Reference in New Issue