瀏覽代碼

feat: 优化后台角色列表 编辑和删除 逻辑

lanjianrong 3 年之前
父節點
當前提交
86b27ba6fc
共有 4 個文件被更改,包括 139 次插入104 次删除
  1. 1 3
      .stylelintrc.js
  2. 25 24
      src/global.less
  3. 17 0
      src/pages/Role/System/components/RoleMenu/index.less
  4. 96 77
      src/pages/Role/System/components/RoleMenu/index.tsx

+ 1 - 3
.stylelintrc.js

@@ -1,7 +1,5 @@
-const fabric = require('@umijs/fabric')
-
 module.exports = {
-  ...fabric.stylelint,
+  extends: [require.resolve('@umijs/fabric/dist/stylelint')],
   rules: {
     indentation: 2,
     'block-no-empty': null,

+ 25 - 24
src/global.less

@@ -92,29 +92,30 @@ ol {
 }
 
 .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;
+  @apply text-white bg-primary rounded-4px;
+  // -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;
-  }
-}
+// @-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;
+//   }
+// }

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

@@ -0,0 +1,17 @@
+.node {
+  .title {
+    // max-width: 110px;
+    @apply line-clamp-1;
+  }
+  .extra {
+    display: none;
+    right: 0;
+    @apply mr-1 hover:cursor-pointer;
+  }
+
+  &:hover {
+    .extra {
+      @apply flex justify-between items-center flex-nowrap;
+    }
+  }
+}

+ 96 - 77
src/pages/Role/System/components/RoleMenu/index.tsx

@@ -1,6 +1,6 @@
-import React, { useState, useEffect } from 'react'
-import { PlusOutlined, DownOutlined } from '@ant-design/icons'
-import { Button, message, Popconfirm, Popover, Input, Switch } from 'antd'
+import React, { useState, useEffect, useRef } from 'react'
+import { PlusOutlined, InfoCircleOutlined, FormOutlined, DeleteOutlined } from '@ant-design/icons'
+import { Button, message, Popconfirm, Switch, Tooltip } from 'antd'
 import { useRequest } from 'umi'
 import {
   createRoleWithMenuId,
@@ -8,25 +8,44 @@ import {
   deleteRole,
   updateStaff
 } from '@/services/user/api'
+import type { ProFormInstance } from '@ant-design/pro-form'
 import { ModalForm, ProFormText } from '@ant-design/pro-form'
 import classNames from 'classnames'
-
+import styles from './index.less'
 type RoleMenuProps = {
   menuId: string
   onSelect?: (id: string) => void
   itemCount?: number
 }
-
+enum ModalType {
+  ADD,
+  UPDATE
+}
+type RoleMenuState = {
+  menuRoles: API.MenuRoleItem[]
+  activeId: Nullable<string>
+  visible: boolean
+  modalType: ModalType
+  defaultMenuData: Nullable<{ id: string; name: string }>
+}
 const RoleMenu: React.FC<RoleMenuProps> = ({ menuId, onSelect, itemCount }) => {
-  const [state, setState] = useState({
-    value: ''
+  const formRef = useRef<ProFormInstance>(null)
+  const [state, setState] = useState<RoleMenuState>({
+    menuRoles: [],
+    activeId: null,
+    visible: false,
+    modalType: ModalType.ADD,
+    defaultMenuData: null
   })
-  const [activeId, setActiveId] = useState('')
-  const [menuRoles, setMenuRoles] = useState<API.MenuRoleItem[]>([])
+
+  useEffect(() => {
+    formRef.current?.setFieldsValue({ ...state.defaultMenuData })
+  }, [state.defaultMenuData])
+
   const { run: tryFetchMenuRoles } = useRequest((id: string) => fetchRoleListByMenuId(id), {
     manual: true,
     onSuccess: result => {
-      setMenuRoles(result)
+      setState({ ...state, menuRoles: result })
     }
   })
 
@@ -44,25 +63,13 @@ const RoleMenu: React.FC<RoleMenuProps> = ({ menuId, onSelect, itemCount }) => {
       }
     }
   )
-  const { run: tryUpdateStaff } = useRequest(
-    (id: string, name: string) => {
-      if (activeId === id) {
-        setActiveId('')
-      }
-      return updateStaff({ id, name })
-    },
-    {
-      manual: true,
-      onSuccess: () => {
-        message.success('修改成功')
-        tryFetchMenuRoles(menuId)
-      }
+  const { run: tryUpdateStaff } = useRequest(updateStaff, {
+    manual: true,
+    onSuccess: () => {
+      message.success('修改成功')
+      tryFetchMenuRoles(menuId)
     }
-  )
-
-  const onChangeName = value => {
-    setState({ ...state, name: value })
-  }
+  })
 
   const { run: tryAddRole } = useRequest(
     (params: API.CreateRoleParams) => createRoleWithMenuId(params),
@@ -70,6 +77,7 @@ const RoleMenu: React.FC<RoleMenuProps> = ({ menuId, onSelect, itemCount }) => {
       manual: true,
       onSuccess: () => {
         tryFetchMenuRoles(menuId)
+        message.success('添加成功')
       }
     }
   )
@@ -78,19 +86,30 @@ const RoleMenu: React.FC<RoleMenuProps> = ({ menuId, onSelect, itemCount }) => {
   }, [])
 
   const handleItemClick = (id: string) => {
-    setActiveId(id)
+    setState({ ...state, activeId: id })
     if (onSelect) {
       onSelect(id)
     }
   }
 
+  const handleEditIconClick = (id: string, text: string) => {
+    setState({
+      ...state,
+      visible: true,
+      modalType: ModalType.UPDATE,
+      defaultMenuData: { id, name: text }
+    })
+  }
   return (
     <div className="h-full w-max-234px rounded-4px">
-      <div className="p-4 border-b-1 border-solid border-black border-opacity-10 bg-[#f7f9fa] flex items-center justify-around">
+      <div className="p-4 border-b-1 border-solid border-black border-opacity-10 bg-hex-f7f9fa flex items-center justify-around">
         <span className="text-[0.9375rem]">角色列表</span>
 
         <ModalForm<{ name: string; backstageMenuId: string }>
-          title="添加新的角色"
+          visible={state.visible}
+          formRef={formRef}
+          onVisibleChange={visible => setState({ ...state, visible })}
+          title={state.modalType === ModalType.ADD ? '添加新的角色' : '更新角色'}
           width="500px"
           layout="horizontal"
           trigger={
@@ -100,68 +119,68 @@ const RoleMenu: React.FC<RoleMenuProps> = ({ menuId, onSelect, itemCount }) => {
             </Button>
           }
           onFinish={async values => {
-            await tryAddRole(values)
-            message.success('添加成功')
+            if (state.modalType === ModalType.ADD) {
+              await tryAddRole(values)
+            } else {
+              console.log(values)
+
+              await tryUpdateStaff(values)
+            }
             return true
           }}
           initialValues={{ backstageMenuId: menuId }}>
           <ProFormText name="backstageMenuId" hidden />
+          <ProFormText name="id" hidden />
           <ProFormText
             name="name"
             label="名称"
             placeholder="请输入角色名称"
             rules={[{ required: true, message: '请输入角色名' }]}
           />
-          <Switch onChange={checked => {}} />
+          {state.modalType === ModalType.ADD ? (
+            <>
+              <Switch onChange={checked => {}} />
+              <span className="mx-2">复制角色</span>
+              <Tooltip title="该操作允许复制其他栏目的角色并且将所绑定的用户一并复制">
+                <InfoCircleOutlined />
+              </Tooltip>
+            </>
+          ) : null}
         </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">
-          {menuRoles.map(item => (
+          {state.menuRoles.map(item => (
             <li
               key={item.id}
-              className={classNames('flex justify-between items-center py-2 px-5 cursor-pointer', {
-                'scale-up-center': item.id === activeId
-              })}
-              onClick={() => handleItemClick(item.id)}>
-              <span>{item.name}</span>
-              <Popover
-                placement="bottomRight"
-                content={
-                  <div className="popoverList">
-                    <ul>
-                      <Popconfirm
-                        title={
-                          <Input
-                            placeholder="角色名称"
-                            name="name"
-                            onChange={e => onChangeName(e.currentTarget.value)}
-                          />
-                        }
-                        okText="确认"
-                        cancelText="取消"
-                        onConfirm={() => tryUpdateStaff(item.id, state.name)}
-                        icon="">
-                        <li>编辑</li>
-                      </Popconfirm>
-                      <Popconfirm
-                        title="确认删除吗?"
-                        okText="确认"
-                        cancelText="取消"
-                        onConfirm={() => {
-                          if (itemCount && itemCount !== 0) {
-                            return message.warning('请先移除已经关联的员工')
-                          }
-                          return tryDeleteRole(item.id)
-                        }}>
-                        <li className="text-red-500">删除</li>
-                      </Popconfirm>
-                    </ul>
-                  </div>
-                }
-                trigger="click">
-                <DownOutlined />
-              </Popover>
+              className={classNames(
+                'flex justify-between items-center py-2 px-5 cursor-pointer',
+                {
+                  'scale-up-center': item.id === state.activeId
+                },
+                styles.node
+              )}>
+              <div className={styles.title} onClick={() => handleItemClick(item.id)}>
+                {item.name}
+              </div>
+              <div className={styles.extra}>
+                <FormOutlined
+                  className="pr-2"
+                  onClick={() => handleEditIconClick(item.id, item.name)}
+                />
+                <Popconfirm
+                  title="确认删除吗?"
+                  okText="确认"
+                  cancelText="取消"
+                  onConfirm={() => {
+                    if (itemCount && itemCount !== 0) {
+                      return message.warning('请先移除已经关联的员工')
+                    }
+                    return tryDeleteRole(item.id)
+                  }}>
+                  <DeleteOutlined />
+                </Popconfirm>
+              </div>
             </li>
           ))}
         </ul>