31 changed files with 852 additions and 52 deletions
@ -1,4 +1,2 @@ |
|||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; |
|||
export const PageFooter = createAsyncComponent(() => import('./src/PageFooter.vue')); |
|||
|
|||
export { default as PageFooter } from './src/PageFooter.vue'; |
|||
export { default as PageWrapper } from './src/PageWrapper.vue'; |
|||
|
|||
@ -1,4 +1,3 @@ |
|||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; |
|||
export const QrCode = createAsyncComponent(() => import('./src/index.vue')); |
|||
export { default as QrCode } from './src/index.vue'; |
|||
|
|||
export * from './src/types'; |
|||
|
|||
@ -1,3 +1 @@ |
|||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; |
|||
|
|||
export const StrengthMeter = createAsyncComponent(() => import('./src/index.vue')); |
|||
export { default as StrengthMeter } from './src/index.vue'; |
|||
|
|||
@ -0,0 +1,70 @@ |
|||
<template> |
|||
<BasicDrawer |
|||
v-bind="$attrs" |
|||
@register="registerDrawer" |
|||
showFooter |
|||
:title="getTitle" |
|||
width="50%" |
|||
@ok="handleSubmit" |
|||
> |
|||
<BasicForm @register="registerForm" /> |
|||
</BasicDrawer> |
|||
</template> |
|||
<script lang="ts"> |
|||
import { defineComponent, ref, computed, unref } from 'vue'; |
|||
import { BasicForm, useForm } from '/@/components/Form/index'; |
|||
import { formSchema } from './menu.data'; |
|||
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
|||
|
|||
import { getMenuList } from '/@/api/demo/system'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'MenuDrawer', |
|||
components: { BasicDrawer, BasicForm }, |
|||
emits: ['success', 'register'], |
|||
setup(_, { emit }) { |
|||
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: 'parentMenu', |
|||
componentProps: { treeData }, |
|||
}); |
|||
}); |
|||
|
|||
const getTitle = computed(() => (!unref(isUpdate) ? '新增菜单' : '编辑菜单')); |
|||
|
|||
async function handleSubmit() { |
|||
try { |
|||
const values = await validate(); |
|||
setDrawerProps({ confirmLoading: true }); |
|||
// TODO custom api |
|||
console.log(values); |
|||
closeDrawer(); |
|||
emit('success'); |
|||
} finally { |
|||
setDrawerProps({ confirmLoading: false }); |
|||
} |
|||
} |
|||
|
|||
return { registerDrawer, registerForm, getTitle, handleSubmit }; |
|||
}, |
|||
}); |
|||
</script> |
|||
@ -0,0 +1,100 @@ |
|||
<template> |
|||
<div> |
|||
<BasicTable @register="registerTable"> |
|||
<template #toolbar> |
|||
<a-button type="primary" @click="handleCreate"> 新增菜单 </a-button> |
|||
</template> |
|||
<template #action="{ record }"> |
|||
<TableAction |
|||
:actions="[ |
|||
{ |
|||
icon: 'clarity:note-edit-line', |
|||
onClick: handleEdit.bind(null, record), |
|||
}, |
|||
{ |
|||
icon: 'ant-design:delete-outlined', |
|||
color: 'error', |
|||
popConfirm: { |
|||
title: '是否确认删除', |
|||
confirm: handleDelete.bind(null, record), |
|||
}, |
|||
}, |
|||
]" |
|||
/> |
|||
</template> |
|||
</BasicTable> |
|||
<MenuDrawer @register="registerDrawer" @success="handleSuccess" /> |
|||
</div> |
|||
</template> |
|||
<script lang="ts"> |
|||
import { defineComponent } from 'vue'; |
|||
|
|||
import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
|||
import { getMenuList } from '/@/api/demo/system'; |
|||
|
|||
import { useDrawer } from '/@/components/Drawer'; |
|||
import MenuDrawer from './MenuDrawer.vue'; |
|||
|
|||
import { columns, searchFormSchema } from './menu.data'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'MenuManagement', |
|||
components: { BasicTable, MenuDrawer, TableAction }, |
|||
setup() { |
|||
const [registerDrawer, { openDrawer }] = useDrawer(); |
|||
const [registerTable, { reload }] = useTable({ |
|||
title: '菜单列表', |
|||
api: getMenuList, |
|||
columns, |
|||
formConfig: { |
|||
labelWidth: 120, |
|||
schemas: searchFormSchema, |
|||
}, |
|||
pagination: false, |
|||
striped: false, |
|||
useSearchForm: true, |
|||
showTableSetting: true, |
|||
bordered: true, |
|||
showIndexColumn: false, |
|||
canResize: false, |
|||
actionColumn: { |
|||
width: 80, |
|||
title: '操作', |
|||
dataIndex: 'action', |
|||
slots: { customRender: 'action' }, |
|||
fixed: undefined, |
|||
}, |
|||
}); |
|||
|
|||
function handleCreate() { |
|||
openDrawer(true, { |
|||
isUpdate: false, |
|||
}); |
|||
} |
|||
|
|||
function handleEdit(record: Recordable) { |
|||
openDrawer(true, { |
|||
record, |
|||
isUpdate: true, |
|||
}); |
|||
} |
|||
|
|||
function handleDelete(record: Recordable) { |
|||
console.log(record); |
|||
} |
|||
|
|||
function handleSuccess() { |
|||
reload(); |
|||
} |
|||
|
|||
return { |
|||
registerTable, |
|||
registerDrawer, |
|||
handleCreate, |
|||
handleEdit, |
|||
handleDelete, |
|||
handleSuccess, |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
@ -0,0 +1,202 @@ |
|||
import { BasicColumn } from '/@/components/Table'; |
|||
import { FormSchema } from '/@/components/Table'; |
|||
import { h } from 'vue'; |
|||
import { Tag } from 'ant-design-vue'; |
|||
import { Icon } from '/@/components/Icon'; |
|||
|
|||
export const columns: BasicColumn[] = [ |
|||
{ |
|||
title: '菜单名称', |
|||
dataIndex: 'menuName', |
|||
width: 200, |
|||
align: 'left', |
|||
}, |
|||
{ |
|||
title: '图标', |
|||
dataIndex: 'icon', |
|||
width: 50, |
|||
customRender: ({ record }) => { |
|||
return h(Icon, { icon: record.icon }); |
|||
}, |
|||
}, |
|||
{ |
|||
title: '权限标识', |
|||
dataIndex: 'permission', |
|||
width: 180, |
|||
}, |
|||
{ |
|||
title: '组件', |
|||
dataIndex: 'component', |
|||
}, |
|||
{ |
|||
title: '排序', |
|||
dataIndex: 'orderNo', |
|||
width: 50, |
|||
}, |
|||
{ |
|||
title: '状态', |
|||
dataIndex: 'status', |
|||
width: 80, |
|||
customRender: ({ record }) => { |
|||
const status = record.status; |
|||
const enable = ~~status === 0; |
|||
const color = enable ? 'green' : 'red'; |
|||
const text = enable ? '启用' : '停用'; |
|||
return h(Tag, { color: color }, () => text); |
|||
}, |
|||
}, |
|||
{ |
|||
title: '创建时间', |
|||
dataIndex: 'createTime', |
|||
width: 180, |
|||
}, |
|||
]; |
|||
|
|||
const isDir = (type: string) => type === '0'; |
|||
const isMenu = (type: string) => type === '1'; |
|||
const isButton = (type: string) => type === '2'; |
|||
|
|||
export const searchFormSchema: FormSchema[] = [ |
|||
{ |
|||
field: 'menuName', |
|||
label: '菜单名称', |
|||
component: 'Input', |
|||
colProps: { span: 8 }, |
|||
}, |
|||
{ |
|||
field: 'status', |
|||
label: '状态', |
|||
component: 'Select', |
|||
componentProps: { |
|||
options: [ |
|||
{ label: '启用', value: '0' }, |
|||
{ label: '停用', value: '1' }, |
|||
], |
|||
}, |
|||
colProps: { span: 8 }, |
|||
}, |
|||
]; |
|||
|
|||
export const formSchema: FormSchema[] = [ |
|||
{ |
|||
field: 'type', |
|||
label: '菜单类型', |
|||
component: 'RadioButtonGroup', |
|||
defaultValue: '0', |
|||
componentProps: { |
|||
options: [ |
|||
{ label: '目录', value: '0' }, |
|||
{ label: '菜单', value: '1' }, |
|||
{ label: '按钮', value: '2' }, |
|||
], |
|||
}, |
|||
colProps: { lg: 24, md: 24 }, |
|||
}, |
|||
{ |
|||
field: 'menuName', |
|||
label: '菜单名称', |
|||
component: 'Input', |
|||
required: true, |
|||
}, |
|||
|
|||
{ |
|||
field: 'parentMenu', |
|||
label: '上级菜单', |
|||
component: 'TreeSelect', |
|||
componentProps: { |
|||
replaceFields: { |
|||
title: 'menuName', |
|||
key: 'id', |
|||
value: 'id', |
|||
}, |
|||
getPopupContainer: () => document.body, |
|||
}, |
|||
}, |
|||
|
|||
{ |
|||
field: 'orderNo', |
|||
label: '排序', |
|||
component: 'InputNumber', |
|||
required: true, |
|||
}, |
|||
{ |
|||
field: 'icon', |
|||
label: '图标', |
|||
component: 'IconPicker', |
|||
required: true, |
|||
show: ({ values }) => !isButton(values.type), |
|||
}, |
|||
|
|||
{ |
|||
field: 'routePath', |
|||
label: '路由地址', |
|||
component: 'Input', |
|||
required: true, |
|||
show: ({ values }) => !isButton(values.type), |
|||
}, |
|||
{ |
|||
field: 'component', |
|||
label: '组件路径', |
|||
component: 'Input', |
|||
show: ({ values }) => isMenu(values.type), |
|||
}, |
|||
{ |
|||
field: 'permission', |
|||
label: '权限标识', |
|||
component: 'Input', |
|||
show: ({ values }) => !isDir(values.type), |
|||
}, |
|||
{ |
|||
field: 'status', |
|||
label: '状态', |
|||
component: 'RadioButtonGroup', |
|||
defaultValue: '0', |
|||
componentProps: { |
|||
options: [ |
|||
{ label: '启用', value: '0' }, |
|||
{ label: '禁用', value: '1' }, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'isExt', |
|||
label: '是否外链', |
|||
component: 'RadioButtonGroup', |
|||
defaultValue: '0', |
|||
componentProps: { |
|||
options: [ |
|||
{ label: '否', value: '0' }, |
|||
{ label: '是', value: '1' }, |
|||
], |
|||
}, |
|||
show: ({ values }) => !isButton(values.type), |
|||
}, |
|||
|
|||
{ |
|||
field: 'keepalive', |
|||
label: '是否缓存', |
|||
component: 'RadioButtonGroup', |
|||
defaultValue: '0', |
|||
componentProps: { |
|||
options: [ |
|||
{ label: '否', value: '0' }, |
|||
{ label: '是', value: '1' }, |
|||
], |
|||
}, |
|||
show: ({ values }) => isMenu(values.type), |
|||
}, |
|||
|
|||
{ |
|||
field: 'show', |
|||
label: '是否显示', |
|||
component: 'RadioButtonGroup', |
|||
defaultValue: '0', |
|||
componentProps: { |
|||
options: [ |
|||
{ label: '是', value: '0' }, |
|||
{ label: '否', value: '1' }, |
|||
], |
|||
}, |
|||
show: ({ values }) => !isButton(values.type), |
|||
}, |
|||
]; |
|||
@ -0,0 +1,69 @@ |
|||
<template> |
|||
<BasicDrawer |
|||
v-bind="$attrs" |
|||
@register="registerDrawer" |
|||
showFooter |
|||
:title="getTitle" |
|||
width="500px" |
|||
@ok="handleSubmit" |
|||
> |
|||
<BasicForm @register="registerForm" /> |
|||
</BasicDrawer> |
|||
</template> |
|||
<script lang="ts"> |
|||
import { defineComponent, ref, computed, unref } from 'vue'; |
|||
import { BasicForm, useForm } from '/@/components/Form/index'; |
|||
import { formSchema } from './role.data'; |
|||
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
|||
|
|||
import { getMenuList } from '/@/api/demo/system'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'RoleDrawer', |
|||
components: { BasicDrawer, BasicForm }, |
|||
emits: ['success', 'register'], |
|||
setup(_, { emit }) { |
|||
const isUpdate = ref(true); |
|||
|
|||
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({ |
|||
labelWidth: 90, |
|||
schemas: formSchema, |
|||
showActionButtonGroup: false, |
|||
}); |
|||
|
|||
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: 'parentMenu', |
|||
componentProps: { treeData }, |
|||
}); |
|||
}); |
|||
|
|||
const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色')); |
|||
|
|||
async function handleSubmit() { |
|||
try { |
|||
const values = await validate(); |
|||
setDrawerProps({ confirmLoading: true }); |
|||
// TODO custom api |
|||
console.log(values); |
|||
closeDrawer(); |
|||
emit('success'); |
|||
} finally { |
|||
setDrawerProps({ confirmLoading: false }); |
|||
} |
|||
} |
|||
|
|||
return { registerDrawer, registerForm, getTitle, handleSubmit }; |
|||
}, |
|||
}); |
|||
</script> |
|||
@ -0,0 +1,97 @@ |
|||
<template> |
|||
<div> |
|||
<BasicTable @register="registerTable"> |
|||
<template #toolbar> |
|||
<a-button type="primary" @click="handleCreate"> 新增角色 </a-button> |
|||
</template> |
|||
<template #action="{ record }"> |
|||
<TableAction |
|||
:actions="[ |
|||
{ |
|||
icon: 'clarity:note-edit-line', |
|||
onClick: handleEdit.bind(null, record), |
|||
}, |
|||
{ |
|||
icon: 'ant-design:delete-outlined', |
|||
color: 'error', |
|||
popConfirm: { |
|||
title: '是否确认删除', |
|||
confirm: handleDelete.bind(null, record), |
|||
}, |
|||
}, |
|||
]" |
|||
/> |
|||
</template> |
|||
</BasicTable> |
|||
<RoleDrawer @register="registerDrawer" @success="handleSuccess" /> |
|||
</div> |
|||
</template> |
|||
<script lang="ts"> |
|||
import { defineComponent } from 'vue'; |
|||
|
|||
import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
|||
import { getRoleList } from '/@/api/demo/system'; |
|||
|
|||
import { useDrawer } from '/@/components/Drawer'; |
|||
import RoleDrawer from './RoleDrawer.vue'; |
|||
|
|||
import { columns, searchFormSchema } from './role.data'; |
|||
|
|||
export default defineComponent({ |
|||
name: 'RoleManagement', |
|||
components: { BasicTable, RoleDrawer, TableAction }, |
|||
setup() { |
|||
const [registerDrawer, { openDrawer }] = useDrawer(); |
|||
const [registerTable, { reload }] = useTable({ |
|||
title: '角色列表', |
|||
api: getRoleList, |
|||
columns, |
|||
formConfig: { |
|||
labelWidth: 120, |
|||
schemas: searchFormSchema, |
|||
}, |
|||
useSearchForm: true, |
|||
showTableSetting: true, |
|||
bordered: true, |
|||
showIndexColumn: false, |
|||
actionColumn: { |
|||
width: 80, |
|||
title: '操作', |
|||
dataIndex: 'action', |
|||
slots: { customRender: 'action' }, |
|||
fixed: undefined, |
|||
}, |
|||
}); |
|||
|
|||
function handleCreate() { |
|||
openDrawer(true, { |
|||
isUpdate: false, |
|||
}); |
|||
} |
|||
|
|||
function handleEdit(record: Recordable) { |
|||
openDrawer(true, { |
|||
record, |
|||
isUpdate: true, |
|||
}); |
|||
} |
|||
|
|||
function handleDelete(record: Recordable) { |
|||
console.log(record); |
|||
} |
|||
|
|||
function handleSuccess() { |
|||
reload(); |
|||
} |
|||
|
|||
return { |
|||
registerTable, |
|||
registerDrawer, |
|||
handleCreate, |
|||
handleEdit, |
|||
handleDelete, |
|||
handleSuccess, |
|||
}; |
|||
}, |
|||
}); |
|||
</script> |
|||
@ -0,0 +1,102 @@ |
|||
import { BasicColumn } from '/@/components/Table'; |
|||
import { FormSchema } from '/@/components/Table'; |
|||
import { h } from 'vue'; |
|||
import { Tag } from 'ant-design-vue'; |
|||
|
|||
export const columns: BasicColumn[] = [ |
|||
{ |
|||
title: '角色名称', |
|||
dataIndex: 'roleName', |
|||
width: 200, |
|||
}, |
|||
{ |
|||
title: '角色值', |
|||
dataIndex: 'roleValue', |
|||
width: 180, |
|||
}, |
|||
{ |
|||
title: '排序', |
|||
dataIndex: 'orderNo', |
|||
width: 50, |
|||
}, |
|||
{ |
|||
title: '状态', |
|||
dataIndex: 'status', |
|||
width: 80, |
|||
customRender: ({ record }) => { |
|||
const status = record.status; |
|||
const enable = ~~status === 0; |
|||
const color = enable ? 'green' : 'red'; |
|||
const text = enable ? '启用' : '停用'; |
|||
return h(Tag, { color: color }, () => text); |
|||
}, |
|||
}, |
|||
{ |
|||
title: '创建时间', |
|||
dataIndex: 'createTime', |
|||
width: 180, |
|||
}, |
|||
{ |
|||
title: '备注', |
|||
dataIndex: 'remark', |
|||
}, |
|||
]; |
|||
|
|||
export const searchFormSchema: FormSchema[] = [ |
|||
{ |
|||
field: 'roleNme', |
|||
label: '角色名称', |
|||
component: 'Input', |
|||
colProps: { span: 8 }, |
|||
}, |
|||
{ |
|||
field: 'status', |
|||
label: '状态', |
|||
component: 'Select', |
|||
componentProps: { |
|||
options: [ |
|||
{ label: '启用', value: '0' }, |
|||
{ label: '停用', value: '1' }, |
|||
], |
|||
}, |
|||
colProps: { span: 8 }, |
|||
}, |
|||
]; |
|||
|
|||
export const formSchema: FormSchema[] = [ |
|||
{ |
|||
field: 'roleName', |
|||
label: '角色名称', |
|||
required: true, |
|||
component: 'Input', |
|||
}, |
|||
{ |
|||
field: 'roleValue', |
|||
label: '角色值', |
|||
required: true, |
|||
component: 'Input', |
|||
}, |
|||
{ |
|||
field: 'status', |
|||
label: '状态', |
|||
component: 'RadioButtonGroup', |
|||
defaultValue: '0', |
|||
componentProps: { |
|||
options: [ |
|||
{ label: '启用', value: '0' }, |
|||
{ label: '停用', value: '1' }, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
label: '备注', |
|||
field: 'remark', |
|||
component: 'InputTextArea', |
|||
}, |
|||
{ |
|||
label: '菜单分配', |
|||
field: 'menu', |
|||
slot: 'menu', |
|||
component: 'Render', |
|||
}, |
|||
]; |
|||
Loading…
Reference in new issue