feat: 添加菜单管理页面
parent
2f49f3814c
commit
5f7e71ae90
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<a-dropdown position="br">
|
<a-dropdown position="br">
|
||||||
<span class="inline-flex items-center cursor-pointer rounded hover:bg-gray-100 px-2 py-1.5">
|
<span class="inline-flex items-center cursor-pointer rounded hover:bg-gray-100 px-2 py-1.5">
|
||||||
<a-avatar :size="20">
|
<a-avatar :size="24">
|
||||||
<img :src="userStore.avatar || 'https://github.com/juetan.png'" :alt="userStore.nickname" />
|
<img :src="userStore.avatar || 'https://github.com/juetan.png'" :alt="userStore.nickname" />
|
||||||
</a-avatar>
|
</a-avatar>
|
||||||
<span class="mx-2">
|
<span class="mx-2">
|
||||||
|
|
@ -11,9 +11,14 @@
|
||||||
</span>
|
</span>
|
||||||
<template #content>
|
<template #content>
|
||||||
<a-doption>
|
<a-doption>
|
||||||
<div class="w-[160px] leading-4 my-1">
|
<div class="w-[200px] flex items-center gap-2">
|
||||||
{{ userStore.nickname }}
|
<a-avatar :size="32">
|
||||||
<div class="text-xs text-gray-500">@{{ userStore.username }}</div>
|
<img :src="userStore.avatar || 'https://github.com/juetan.png'" :alt="userStore.nickname" />
|
||||||
|
</a-avatar>
|
||||||
|
<div class="leading-4 my-2">
|
||||||
|
{{ userStore.nickname }}
|
||||||
|
<div class="text-xs text-gray-500">@{{ userStore.username }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-doption>
|
</a-doption>
|
||||||
<a-divider :margin="4"></a-divider>
|
<a-divider :margin="4"></a-divider>
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,6 @@
|
||||||
<a-form-item label="个人描述">
|
<a-form-item label="个人描述">
|
||||||
<a-textarea v-model="user.description" placeholder="请输入" class="!w-[432px] h-24"></a-textarea>
|
<a-textarea v-model="user.description" placeholder="请输入" class="!w-[432px] h-24"></a-textarea>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="密码">
|
|
||||||
<a-button>修改密码</a-button>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="性别">
|
<a-form-item label="性别">
|
||||||
<a-radio-group v-model="user.gender" type="button">
|
<a-radio-group v-model="user.gender" type="button">
|
||||||
<a-radio :value="1">男</a-radio>
|
<a-radio :value="1">男</a-radio>
|
||||||
|
|
@ -38,6 +35,7 @@
|
||||||
<a-form-item label="出生日期">
|
<a-form-item label="出生日期">
|
||||||
<a-date-picker v-model="user.birth"></a-date-picker>
|
<a-date-picker v-model="user.birth"></a-date-picker>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-button type="primary">保存修改</a-button>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="5" title="消息推送">
|
<a-tab-pane key="5" title="消息推送">
|
||||||
|
|
@ -63,6 +61,24 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="8" title="账号密码">
|
||||||
|
<template #title>
|
||||||
|
<i class="icon-park-outline-lock"></i>
|
||||||
|
账号密码
|
||||||
|
</template>
|
||||||
|
<a-form :model="user" layout="vertical">
|
||||||
|
<a-form-item label="原密码">
|
||||||
|
<a-input placeholder="请输入原密码"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="新密码">
|
||||||
|
<a-input placeholder="请输入新密码"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="确认新密码">
|
||||||
|
<a-input placeholder="请再次输入新密码"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-button type="primary">修改密码</a-button>
|
||||||
|
</a-form>
|
||||||
|
</a-tab-pane>
|
||||||
<a-tab-pane key="2" title="主题偏好">
|
<a-tab-pane key="2" title="主题偏好">
|
||||||
<template #title>
|
<template #title>
|
||||||
<i class="icon-park-outline-theme"></i>
|
<i class="icon-park-outline-theme"></i>
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
<BreadPage>
|
<BreadPage>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<a-alert :closable="true" class="mb-2">
|
<a-alert :closable="true" class="mb-2"> 仅展示近 90 天内的数据,如需查看更多数据,请联系管理员。 </a-alert>
|
||||||
仅展示近 90 天内的数据,如需查看更多数据,请联系管理员。
|
|
||||||
</a-alert>
|
|
||||||
<div class="bg-white p-4">
|
<div class="bg-white p-4">
|
||||||
<Table v-bind="table"></Table>
|
<Table v-bind="table"></Table>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -17,7 +15,6 @@
|
||||||
import { api } from "@/api";
|
import { api } from "@/api";
|
||||||
import { Table, useTable } from "@/components";
|
import { Table, useTable } from "@/components";
|
||||||
import { dayjs } from "@/libs/dayjs";
|
import { dayjs } from "@/libs/dayjs";
|
||||||
import { Tag } from "@arco-design/web-vue";
|
|
||||||
|
|
||||||
const table = useTable({
|
const table = useTable({
|
||||||
data: async (model, paging) => {
|
data: async (model, paging) => {
|
||||||
|
|
@ -35,9 +32,13 @@ const table = useTable({
|
||||||
render: ({ record: { status, description } }) => {
|
render: ({ record: { status, description } }) => {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
<Tag color={status === null || status ? "green" : "red"} class="mr-2">
|
<span
|
||||||
{status === null || status ? "成功" : "失败"}
|
class={
|
||||||
</Tag>
|
status === null || status
|
||||||
|
? "text-base text-green-500 icon-park-outline-check-one mr-2"
|
||||||
|
: "text-base text-red-500 icon-park-outline-close-one mr-2"
|
||||||
|
}
|
||||||
|
></span>
|
||||||
{description}
|
{description}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
@ -62,7 +63,7 @@ const table = useTable({
|
||||||
{
|
{
|
||||||
title: "登陆时间",
|
title: "登陆时间",
|
||||||
dataIndex: "createdAt",
|
dataIndex: "createdAt",
|
||||||
width: 120,
|
width: 160,
|
||||||
render: ({ record }) => dayjs(record.createdAt).fromNow(),
|
render: ({ record }) => dayjs(record.createdAt).fromNow(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -71,10 +72,10 @@ const table = useTable({
|
||||||
{
|
{
|
||||||
field: "nickname",
|
field: "nickname",
|
||||||
label: "登陆账号",
|
label: "登陆账号",
|
||||||
type: "input",
|
type: "search",
|
||||||
required: false,
|
required: false,
|
||||||
nodeProps: {
|
nodeProps: {
|
||||||
placeholder: "请输入登陆账号",
|
// placeholder: "请输入登陆账号",
|
||||||
},
|
},
|
||||||
itemProps: {
|
itemProps: {
|
||||||
hideLabel: true,
|
hideLabel: true,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
<template>
|
||||||
|
<bread-page class="">
|
||||||
|
<Table v-bind="table"></Table>
|
||||||
|
</bread-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import { api } from "@/api";
|
||||||
|
import { Table, useTable } from "@/components";
|
||||||
|
import { dayjs } from "@/libs/dayjs";
|
||||||
|
import { menus } from "@/router";
|
||||||
|
import { cloneDeep } from "lodash-es";
|
||||||
|
|
||||||
|
const items = cloneDeep(menus) as any;
|
||||||
|
for (const item of items) {
|
||||||
|
item.checked = false;
|
||||||
|
// if (item.icon) {
|
||||||
|
// const icon = item.icon;
|
||||||
|
// item.icon = () => <i class={icon}></i>;
|
||||||
|
// }
|
||||||
|
item.switcherIcon = () => null;
|
||||||
|
if (item.children) {
|
||||||
|
for (const child of item.children) {
|
||||||
|
// if (child.icon) {
|
||||||
|
// const icon = child.icon;
|
||||||
|
// child.icon = () => <i class={icon}></i>;
|
||||||
|
// }
|
||||||
|
child.checked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
menus: items,
|
||||||
|
visible: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const indeter = (items: any[]) => {
|
||||||
|
if (!items) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const checked = items.filter((item) => item.checked);
|
||||||
|
return checked.length > 0 && checked.length < items.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onItemChange = (item: any, menu: any) => {
|
||||||
|
const checked = menu.children.filter((item: any) => item.checked);
|
||||||
|
if (checked === 0) {
|
||||||
|
menu.checked = false;
|
||||||
|
} else if (checked === menu.children.length) {
|
||||||
|
menu.checked = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const table = useTable({
|
||||||
|
data: items,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: "角色名称",
|
||||||
|
dataIndex: "title",
|
||||||
|
width: 180,
|
||||||
|
render: ({ record }) => {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<i class={`${record.icon} mr-1 ml-1 vertical-[-2px]`}></i>
|
||||||
|
{ record.title }
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "类型",
|
||||||
|
dataIndex: "description",
|
||||||
|
align: 'center',
|
||||||
|
width: 80,
|
||||||
|
render: () => <a-tag color="blue">菜单</a-tag>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "访问路径",
|
||||||
|
dataIndex: "path",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "启用",
|
||||||
|
dataIndex: "createdAt",
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
render: ({ record }) => <a-switch size="small" checked-color="#3c9"></a-switch>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "创建时间",
|
||||||
|
dataIndex: "createdAt",
|
||||||
|
width: 200,
|
||||||
|
render: ({ record }) => dayjs(record.createdAt).format(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
type: "button",
|
||||||
|
width: 184,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: "modify",
|
||||||
|
text: "修改",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "分配权限",
|
||||||
|
onClick: ({ record }) => {
|
||||||
|
console.log(record);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "删除",
|
||||||
|
type: "delete",
|
||||||
|
onClick: ({ record }) => {
|
||||||
|
return api.role.delRole(record.id);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
visible: false
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
extend: "name",
|
||||||
|
required: false,
|
||||||
|
nodeProps: {
|
||||||
|
placeholder: "请输入角色名称",
|
||||||
|
},
|
||||||
|
itemProps: {
|
||||||
|
hideLabel: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
title: "新建角色",
|
||||||
|
modalProps: {
|
||||||
|
width: 580,
|
||||||
|
maskClosable: false,
|
||||||
|
},
|
||||||
|
formProps: {
|
||||||
|
layout: "vertical",
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
field: "name",
|
||||||
|
label: "角色名称",
|
||||||
|
type: "input",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "slug",
|
||||||
|
label: "角色标识",
|
||||||
|
type: "input",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "description",
|
||||||
|
label: "个人描述",
|
||||||
|
type: "textarea",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "permissionIds",
|
||||||
|
label: "关联权限",
|
||||||
|
type: "select",
|
||||||
|
options: () => api.permission.getPermissions(),
|
||||||
|
nodeProps: {
|
||||||
|
multiple: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
submit: ({ model }) => {
|
||||||
|
return api.role.addRole(model);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modify: {
|
||||||
|
extend: true,
|
||||||
|
title: "修改角色",
|
||||||
|
submit: ({ model }) => {
|
||||||
|
return api.role.updateRole(model.id, model);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less"></style>
|
||||||
|
|
||||||
|
<route lang="json">
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"sort": 10201,
|
||||||
|
"title": "菜单管理",
|
||||||
|
"icon": "icon-park-outline-add-subtract"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
|
@ -22,7 +22,7 @@ const table = useTable({
|
||||||
return (
|
return (
|
||||||
<div class="flex flex-col overflow-hidden">
|
<div class="flex flex-col overflow-hidden">
|
||||||
<span>{record.name}</span>
|
<span>{record.name}</span>
|
||||||
<span class="text-gray-400 text-xs truncate">{record.slug}</span>
|
<span class="text-gray-400 text-xs truncate">@{record.slug}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -112,7 +112,7 @@ const table = useTable({
|
||||||
extend: true,
|
extend: true,
|
||||||
title: "修改权限",
|
title: "修改权限",
|
||||||
submit: ({ model }) => {
|
submit: ({ model }) => {
|
||||||
return api.permission.updatePermission(model.id, model);
|
return api.permission.setPermission(model.id, model);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<BreadPage>
|
<BreadPage>
|
||||||
<Table v-bind="table">
|
<Table v-bind="table">
|
||||||
<template #action>
|
<template #action>
|
||||||
<a-button status="danger" type="outline" :disabled="true">
|
<a-button status="danger" :disabled="true">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<i class="icon-park-outline-delete"></i>
|
<i class="icon-park-outline-delete"></i>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -24,6 +24,11 @@ const table = useTable({
|
||||||
data: async (model, paging) => {
|
data: async (model, paging) => {
|
||||||
return api.user.getUsers({ ...model, ...paging });
|
return api.user.getUsers({ ...model, ...paging });
|
||||||
},
|
},
|
||||||
|
tableProps: {
|
||||||
|
rowSelection: {
|
||||||
|
showCheckedAll: true
|
||||||
|
}
|
||||||
|
},
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
title: "用户昵称",
|
title: "用户昵称",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ body {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.arco-layout-sider {
|
.arco-layout-sider {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
|
@ -39,6 +42,7 @@ body {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
[class^="icon-"] {
|
[class^="icon-"] {
|
||||||
|
font-size: 16px;
|
||||||
vertical-align: -2px;
|
vertical-align: -2px;
|
||||||
}
|
}
|
||||||
.arco-menu-item {
|
.arco-menu-item {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue