Bladeren bron

feat: 完善角色列表组件

lanjianrong 4 jaren geleden
bovenliggende
commit
2ab43a4846

+ 31 - 14
src/app.tsx

@@ -6,7 +6,7 @@ import { getIntl, getLocale, history, Link } from 'umi'
 import RightContent from '@/components/RightContent'
 import Footer from '@/components/Footer'
 import type { RequestOptionsInit, ResponseError } from 'umi-request'
-import { currentUser as queryCurrentUser } from './services/user/api'
+import { currentUser as queryCurrentUser, queryMenuList, queryMenuRole } from './services/user/api'
 import { BookOutlined, LinkOutlined } from '@ant-design/icons'
 import consts from './utils/consts'
 
@@ -24,30 +24,47 @@ export const initialStateConfig = {
 export async function getInitialState(): Promise<{
   settings?: Partial<LayoutSettings>
   currentUser?: API.CurrentUser
+  menuList?: API.MenuListItem[]
+  roles?: API.Roles
   fetchUserInfo?: () => Promise<API.CurrentUser | undefined>
 }> {
   // eslint-disable-next-line react-hooks/rules-of-hooks
+  // 获取用户信息
   const fetchUserInfo = async () => {
-    try {
-      const currentUser = await queryCurrentUser()
+    const currentUser = await queryCurrentUser()
+    return currentUser
+  }
 
-      return currentUser
-    } catch (error) {
-      history.push(loginPath)
-    }
-    return undefined
+  // 获取菜单列表id
+  const fetchMenuList = async () => {
+    const menuList = await queryMenuList()
+    return menuList
+  }
+
+  // 获取用户权限
+  const fetchRoles = async () => {
+    const roles = await queryMenuRole()
+    return roles
   }
   // 如果是登录页面,不执行
   if (history.location.pathname !== loginPath) {
-    const currentUser = await fetchUserInfo()
-    return {
-      fetchUserInfo,
-      currentUser: currentUser.data,
-      settings: {}
+    try {
+      const currentUser = await fetchUserInfo()
+      const menuList = await fetchMenuList()
+      const roles = await fetchRoles()
+      return {
+        fetchUserInfo,
+        menuList: menuList.data,
+        roles: roles.data,
+        currentUser: currentUser.data,
+        settings: {}
+      }
+    } catch (error) {
+      history.push(loginPath)
     }
+    return undefined
   }
   return {
-    fetchUserInfo,
     settings: {}
   }
 }

+ 8 - 3
src/pages/Role/Customer/index.tsx

@@ -1,10 +1,15 @@
-import React from 'react'
+import { useModel } from 'umi'
+import React, { useMemo } from 'react'
 import RoleMenu from '../System/components/roleMenu'
 
 const Customer = () => {
+  const { initialState } = useModel('@@initialState')
+  const menuId = useMemo(() => {
+    return initialState?.menuList?.find(item => item.name === '客户')?.id
+  }, initialState.menuList)
   return (
-    <div className="h-full w-full">
-      <RoleMenu menuId={'123'} />
+    <div className="h-full w-full flex flex-row">
+      <RoleMenu menuId={menuId} />
     </div>
   )
 }

+ 28 - 0
src/pages/Role/System/components/index.less

@@ -5,3 +5,31 @@
     @apply text-white bg-primary rounded-4px;
   }
 }
+
+.scale-up-center {
+  -webkit-animation: scale-up-center 0.4s cubic-bezier(0.39, 0.575, 0.565, 1) both;
+  animation: scale-up-center 0.4s cubic-bezier(0.39, 0.575, 0.565, 1) both;
+}
+
+@-webkit-keyframes scale-up-center {
+  0% {
+    -webkit-transform: scale(0.5);
+    transform: scale(0.5);
+  }
+  100% {
+    -webkit-transform: scale(1);
+    transform: scale(1);
+    @apply text-white bg-primary rounded-4px;
+  }
+}
+@keyframes scale-up-center {
+  0% {
+    -webkit-transform: scale(0.5);
+    transform: scale(0.5);
+  }
+  100% {
+    -webkit-transform: scale(1);
+    transform: scale(1);
+    @apply text-white bg-primary rounded-4px;
+  }
+}

+ 68 - 16
src/pages/Role/System/components/roleMenu.tsx

@@ -1,15 +1,46 @@
-import React from 'react'
+import React, { useState, useEffect } from 'react'
 import { PlusOutlined, DownOutlined } from '@ant-design/icons'
-import { Button, Popover } from 'antd'
+import { Button, message, Popover } from 'antd'
 import './index.less'
+import { useRequest } from 'umi'
+import { createRoleWithMenuId, fetchRoleListByMenuId } from '@/services/user/api'
+import { ModalForm, ProFormText } from '@ant-design/pro-form'
 
 type RoleMenuProps = {
   menuId: string
   onSelect?: (id: string) => void
 }
 
-const RoleMenu: React.FC<RoleMenuProps> = () => {
-  // const [activeId, setActiveId] = useState('')
+const RoleMenu: React.FC<RoleMenuProps> = ({ menuId, onSelect }) => {
+  const [menuRoles, setMenuRoles] = useState<API.MenuRoleItem[]>([])
+  const { run: tryFetchMenuRoles } = useRequest((id: string) => fetchRoleListByMenuId(id), {
+    manual: true,
+    onSuccess: result => {
+      setMenuRoles(result)
+    }
+  })
+
+  const { run: tryAddRole } = useRequest(
+    (params: API.CreateRoleParams) => createRoleWithMenuId(params),
+    {
+      manual: true,
+      onSuccess: () => {
+        tryFetchMenuRoles(menuId)
+      }
+    }
+  )
+  useEffect(() => {
+    tryFetchMenuRoles(menuId)
+  }, [])
+  const [activeId, setActiveId] = useState('')
+
+  const handleItemClick = (id: string) => {
+    setActiveId(id)
+    if (onSelect) {
+      onSelect()
+    }
+  }
+
   const content = (
     <div className="popoverList">
       <ul>
@@ -24,21 +55,42 @@ const RoleMenu: React.FC<RoleMenuProps> = () => {
     <div className="h-full w-max-234px rounded-4px roleMenu">
       <div className="p-4 border-b-1 border-solid border-black border-opacity-10 bg-[#f7f9fa] flex justify-around items-center">
         <span className="text-[0.9375rem]">角色列表</span>
-        <Button size="small" type="primary" ghost>
-          <PlusOutlined />
-          创建角色
-        </Button>
+
+        <ModalForm<{ name: string; backstageMenuId: string }>
+          title="添加新的角色"
+          width="500px"
+          trigger={
+            <Button size="small" type="primary" ghost>
+              <PlusOutlined />
+              创建角色
+            </Button>
+          }
+          onFinish={async values => {
+            await tryAddRole(values)
+            message.success('添加成功')
+            return true
+          }}
+          initialValues={{ backstageMenuId: menuId }}>
+          <ProFormText name="backstageMenuId" hidden />
+          <ProFormText name="name" rules={[{ required: true, message: '请输入角色名' }]} />
+        </ModalForm>
       </div>
       <div className="p-4 bg-white" style={{ height: 'calc(100% - 1rem*2 - 20px)' }}>
         <ul className="p-0 m-0 list-none text-primary flex flex-col flex-1">
-          <li
-            className="flex justify-between items-center  py-2 px-5"
-            onClick={() => setActiveId('1')}>
-            <span>客户管理员</span>
-            <Popover placement="bottomRight" content={content} trigger="click">
-              <DownOutlined />
-            </Popover>
-          </li>
+          {menuRoles.map(item => (
+            <li
+              key={item.id}
+              className={[
+                'flex justify-between items-center py-2 px-5 cursor-pointer',
+                item.id === activeId ? 'scale-up-center' : ''
+              ].join(' ')}
+              onClick={() => handleItemClick(item.id)}>
+              <span>{item.name}</span>
+              <Popover placement="bottomRight" content={content} trigger="click">
+                <DownOutlined />
+              </Popover>
+            </li>
+          ))}
         </ul>
       </div>
     </div>

+ 31 - 7
src/services/user/api.ts

@@ -27,13 +27,37 @@ export async function login(body: API.LoginParams, options?: { [key: string]: an
   })
 }
 
-/** 此处后端没有提供注释 GET /api/notices */
-// export async function getNotices(options?: { [key: string]: any }) {
-//   return request<API.NoticeIconList>('/api/notices', {
-//     method: 'GET',
-//     ...(options || {}),
-//   });
-// }
+/** 获取菜单id列表 */
+export async function queryMenuList() {
+  return request<API.MenuListItem[]>('/menu/list')
+}
+
+/** 获取菜单角色权限列表 */
+export async function queryMenuRole() {
+  return request<API.Roles>('/menu/role')
+}
+
+/** 获取菜单下的权限列表 */
+export async function fetchPermRoleByMenuId(id: string) {
+  return request('/permission/list', {
+    params: { backstageMenuId: id }
+  })
+}
+
+/** 获取单一菜单下的角色列表 */
+export async function fetchRoleListByMenuId(id: string) {
+  return request<API.MenuRoleItem[]>('/role/list', {
+    params: { backstageMenuId: id }
+  })
+}
+
+/** 新增单一菜单下角色 */
+export async function createRoleWithMenuId(params: API.CreateRoleParams) {
+  return request('/role/add', {
+    method: 'POST',
+    data: params
+  })
+}
 
 /** 获取规则列表 GET /api/rule */
 export async function rule(

+ 14 - 21
src/services/user/typings.d.ts

@@ -28,31 +28,24 @@ declare namespace API {
     pageSize?: number
   }
 
-  type RuleListItem = {
-    key?: number
-    disabled?: boolean
-    href?: string
-    avatar?: string
-    name?: string
-    owner?: string
-    desc?: string
-    callNo?: number
-    status?: number
-    updatedAt?: string
-    createdAt?: string
-    progress?: number
+  type MenuListItem = {
+    id: string
+    parend_id: string
+    name: string
+    sort: number
   }
 
-  type RuleList = {
-    data?: RuleListItem[]
-    /** 列表的内容总数 */
-    total?: number
-    success?: boolean
+  type Roles = string[]
+
+  type MenuRoleItem = {
+    backstageMenuId: string
+    id: string
+    name: string
   }
 
-  type FakeCaptcha = {
-    code?: number
-    status?: string
+  type CreateRoleParams = {
+    name: string
+    backstageMenuId: string
   }
 
   type LoginParams = {