From e6eedf941cdff49e9827d4e162dceaaf56fecd82 Mon Sep 17 00:00:00 2001 From: mac Date: Thu, 11 Jul 2024 16:57:46 +0800 Subject: [PATCH] commit --- src/api/index.ts | 28 ++- src/assets/js/publicFunc.ts | 36 ++- src/components/Header/index.tsx | 3 +- src/components/Menu/index.tsx | 3 +- src/components/TabPanes/index.tsx | 2 +- src/pages/config-admin/admin-manage.tsx | 228 +++++++++++++++++++ src/pages/config-admin/admin-permissions.tsx | 124 ++++++++++ src/pages/container/index.tsx | 11 +- src/pages/login/index.tsx | 4 +- src/pages/system/withdraw.tsx | 4 +- src/pages/vip-manage/proxy-list.tsx | 34 ++- src/route/routes.ts | 29 ++- src/utils/axios.ts | 5 + 13 files changed, 468 insertions(+), 43 deletions(-) create mode 100644 src/pages/config-admin/admin-manage.tsx create mode 100644 src/pages/config-admin/admin-permissions.tsx diff --git a/src/api/index.ts b/src/api/index.ts index d212055..3e0599e 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -164,5 +164,31 @@ export default { copy_tradeapi(data: object) { return $axios.post('/admin/copytradeapi', data) }, + cancel_follow(data: object) { + return $axios.post('/admin/copytradeapiDelete', data) + }, + get_adminList(data: object) { + return $axios.post('/admin/administratorList', data) + }, + add_adminList(data: object) { + return $axios.post('/admin/addAdministratorList', data) + }, + delete_adminList(data: object) { + return $axios.post('/admin/delAdministratorList', data) + }, + update_adminList(data: object) { + return $axios.post('/admin/updAdministratorList', data) + }, + update_adminPassword(data: object) { + return $axios.post('/admin/updAdministratorPassword', data) + }, + get_adminPermissionList(data: object) { + return $axios.post('/admin/permissionsList', data) + }, + get_adminPermissionsUser(data: object) { + return $axios.post('/admin/permissionsUser', data) + }, + set_adminPermissionList(data: object) { + return $axios.post('/admin/setPermissions', data) + }, } - diff --git a/src/assets/js/publicFunc.ts b/src/assets/js/publicFunc.ts index 951f2a6..7b5ad63 100644 --- a/src/assets/js/publicFunc.ts +++ b/src/assets/js/publicFunc.ts @@ -14,7 +14,7 @@ export const commonConfirm = (title: string, cb: () => void) => { onOk() { cb() }, - onCancel() {} + onCancel() { } }) } @@ -52,7 +52,7 @@ export const getKeyName = (path: string = '/403') => { const curRoute = flattenRoutes(routes).filter( (item: { path: string | string[] }) => item.path.includes(truePath) ) - + if (!curRoute[0]) return { title: '暂无权限', tabKey: '403', component: ErrorPage } const { name, key, component } = curRoute[0] @@ -214,8 +214,12 @@ export const getPermission = () => localStorage.getItem('permissions') || [] * 根据权限判断是否有权限 */ export const isAuthorized = (val: string): boolean => { - const permissions = getPermission(); - return permissions.includes(val) + let permissions: any = getPermission(); + if (typeof permissions === 'string') { + permissions = JSON.parse(permissions) + } + + return permissions.map(v => v.key).includes(val) } /** @@ -297,18 +301,8 @@ export const setUserInfo = ( oldToken?: string ) => { const { permission, userName, token } = userInfo - - console.log(permission); - - const permissionArray = permission.reduce( - (prev: CommonObjectType[], next: CommonObjectType) => [ - ...prev, - next.code - ], - [] - ); - - localStorage.setItem('permissions', permissionArray) + + localStorage.setItem('permissions', JSON.stringify(flattenRoutes(permission))) const result = { userName, @@ -422,18 +416,18 @@ export const treeFindParentById = (tree: Array, id: string | number): Array const forFn = function (tree, id) { for (let i = 0; i < tree.length; i++) { const data = tree[i] - + if (data.id === id) { return path } - + path.push(data.id) - + if (data.children) { const findChildren = forFn(data.children, id); if (findChildren && findChildren.length > 0) return findChildren } - + path.pop() } } @@ -446,7 +440,7 @@ export const treeFindParentById = (tree: Array, id: string | number): Array * @param arr1 * @param arr2 */ -export const diffArray = (arr1: Array, arr2: Array): Array< number | string>=> { +export const diffArray = (arr1: Array, arr2: Array): Array => { const diff: Array = [] for (let idx = 0; idx < arr1.length; idx++) { if (!arr2.includes(arr1[idx])) { diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 4ae3f5e..268a049 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -7,7 +7,7 @@ import { connect } from 'react-redux' import * as actions from '@/store/actions' import style from './Header.module.less' -interface Props extends ReduxProps {} +interface Props extends ReduxProps { } const Header: FC = ({ storeData: { collapsed, theme, userInfo }, @@ -18,6 +18,7 @@ const Header: FC = ({ const firstWord = userName.slice(0, 1) const logout = async () => { await setStoreData('SET_USERINFO', {}) + localStorage.setItem('permissions', '') history.replace({ pathname: '/login' }) } diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx index 8c3455e..500988a 100644 --- a/src/components/Menu/index.tsx +++ b/src/components/Menu/index.tsx @@ -22,6 +22,7 @@ const MenuView: FC = ({ storeData: { theme, userInfo, collapsed } }) => { const { tabKey: curKey = 'home' } = getKeyName(pathname) const [current, setCurrent] = useState(curKey) const { permission = [] } = userInfo + // 递归逐级向上获取最近一级的菜单,并高亮 const higherMenuKey = useCallback( (checkKey = 'home', path = pathname) => { @@ -133,7 +134,7 @@ const MenuView: FC = ({ storeData: { theme, userInfo, collapsed } }) => { selectedKeys={[current]} theme={theme === 'default' ? 'light' : 'dark'} > - {renderMenuMap(menus)} + {renderMenuMap(permission)} ) diff --git a/src/components/TabPanes/index.tsx b/src/components/TabPanes/index.tsx index deb1b94..cbb6d7e 100644 --- a/src/components/TabPanes/index.tsx +++ b/src/components/TabPanes/index.tsx @@ -46,7 +46,7 @@ const TabPanes: FC = (props) => { const [isReload, setIsReload] = useState(false) const [selectedPanel, setSelectedPanel] = useState({}) const pathRef: RefType = useRef('') - + const { storeData: { curTab, reloadPath }, setStoreData, diff --git a/src/pages/config-admin/admin-manage.tsx b/src/pages/config-admin/admin-manage.tsx new file mode 100644 index 0000000..697962a --- /dev/null +++ b/src/pages/config-admin/admin-manage.tsx @@ -0,0 +1,228 @@ +import api from "@/api" +import MyTable from "@/components/MyTable" +import { DeleteOutlined, EditOutlined } from "@ant-design/icons"; +import { Button, Form, Input, Modal, Popconfirm, Radio, Switch, notification } from "antd"; +import React, { useRef, useState } from "react" + +const AdminManage = () => { + + const tableRef = useRef(null) + const currentItem = useRef({} as any) + const [visible, setVisible] = useState(false) + const [visibleUpdate, setVisibleUpdate] = useState(false) + const [form] = Form.useForm() + const [updateForm] = Form.useForm() + const [path, setPath] = useState('info') + + const createAdmin = async (values) => { + setVisible(false) + const params = { + ...values, + status_code: values.status_code ? 1 : 2 + } + const res: any = await api.add_adminList(params) + if (res.code === 0) { + tableRef.current.update() + form.resetFields() + notification.success({ + message: '添加成功' + }) + } + } + + const updateAdmin = async (values) => { + setVisibleUpdate(false) + const params = { + ...values, + id: currentItem.current.id + } + if (path === 'info') { + params.status_code = values.status_code ? 1 : 2; + } + let res: any = {} + if (path === 'info') { + res = await api.update_adminList(params) + } else { + res = await api.update_adminPassword(params) + } + if (res.code === 0) { + tableRef.current.update() + updateForm.resetFields() + notification.success({ + message: '修改成功' + }) + } + } + + const columns = [ + { + title: '操作', + width: 200, + render: (row) => ( +
+ {/* deleteAdmin(row)}> + + */} + { + currentItem.current = row + setVisibleUpdate(true) + updateForm.setFieldsValue({ + ...row, + status_code: row.status_code === 1 ? true : false + }) + }} /> +
+ ) + }, + { + dataIndex: 'user_name', + title: '帐号', + width: 200 + }, + { + dataIndex: 'email', + title: '邮箱', + width: 200 + }, + { + dataIndex: 'name', + title: '姓名', + width: 200 + }, + { + dataIndex: 'phone', + title: '手机', + width: 200 + }, + { + dataIndex: 'position', + title: '职位', + width: 200 + }, + { + dataIndex: 'status', + title: '状态', + }, + // { + // dataIndex: 'status_code', + // title: '状态码 1:正常 2:锁定', + // width: 200 + // }, + + ]; + + + return ( +
+ { + setVisible(true) + }}>添加管理员 + } + /> + + setVisible(false)} + title="添加管理员" + footer={() => null} + > +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + null} + onCancel={() => setVisibleUpdate(false)} + title={`修改管理员信息:${currentItem.current.name}`} + > + + setPath(e.target.value)} style={{ marginBottom: 20 }}> + 修改信息 + 修改密码 + + +
+ { + path === 'info' ? ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + ) : ( + + + + ) + } + + + + + +
+
+
+ ) +} + +export default AdminManage \ No newline at end of file diff --git a/src/pages/config-admin/admin-permissions.tsx b/src/pages/config-admin/admin-permissions.tsx new file mode 100644 index 0000000..02c7feb --- /dev/null +++ b/src/pages/config-admin/admin-permissions.tsx @@ -0,0 +1,124 @@ +import api from "@/api" +import MyTable from "@/components/MyTable" +import { EditOutlined } from "@ant-design/icons" +import { Modal, Tree, notification } from "antd" +import React, { useRef, useState } from "react" + +const AdminPermissions = () => { + + const tableRef = useRef(null) + const currentItem = useRef({} as any) + const [visible, setVisible] = useState(false) + const [treeData, setTreeData] = useState([] as any) + const [checkedKeys, setCheckedKeys] = useState([]); + const treeDataKey = useRef({} as any) + + const getPermissions = async (row) => { + currentItem.current = row + const res: any = await api.get_adminPermissionList({ id: row.id }) + console.log(res); + if (res.code === 0) { + setTreeData(res.data) + getAllChecked(res.data) + setVisible(true) + } + } + + // 获取所有选中的key + const getAllChecked = (data) => { + let keys = []; + let stack = [...data]; + + while (stack.length > 0) { + const node = stack.pop(); + treeDataKey.current[node.key] = node.id + if (node.flag) { + keys.push(node.key); + } + + if (node.children) { + stack = stack.concat(node.children); + } + } + setCheckedKeys(keys) + } + + const setPermission = async () => { + const ids = checkedKeys.map(item => treeDataKey.current[item]) + if (ids.length <= 0) return notification.warning({ + message: '请选择权限' + }) + const params = { + adminId: currentItem.current.id, + menuId: ids.join(',') + } + setVisible(false) + setCheckedKeys([]) + currentItem.current = {} + treeDataKey.current = {} + setTreeData([]) + + const res: any = await api.set_adminPermissionList(params) + if (res.code === 0) { + tableRef.current.update() + notification.success({ + message: '修改成功' + }) + } + } + + const columns = [ + { + title: '操作', + render: (row) => ( +
+ getPermissions(row)} /> +
+ ) + }, + { + title: 'ID', + dataIndex: 'id' + }, + { + title: '名称', + dataIndex: 'name' + } + ] + + const onCheck = (checkedKeysValue) => { + console.log('onCheck', checkedKeysValue); + setCheckedKeys(checkedKeysValue as React.Key[]); + }; + + return ( +
+ + + + + setVisible(false)} + onOk={setPermission} + > + + + + +
+ ) +} + +export default AdminPermissions \ No newline at end of file diff --git a/src/pages/container/index.tsx b/src/pages/container/index.tsx index d075f9e..5f8b604 100644 --- a/src/pages/container/index.tsx +++ b/src/pages/container/index.tsx @@ -14,16 +14,11 @@ const noNewTab = ['/login'] // 不需要新建 tab的页面 const noCheckAuth = ['/', '/403'] // 不需要检查权限的页面 // 检查权限 const checkAuth = (newPathname: string): boolean => { - // 不需要检查权限的 - // if (noCheckAuth.includes(newPathname)) { - // return true - // } - // const { tabKey: currentKey } = getKeyName(newPathname) - // return isAuthorized(currentKey) - return true; + const { tabKey: currentKey } = getKeyName(newPathname) + return isAuthorized(currentKey) } -interface Props extends ReduxProps {} +interface Props extends ReduxProps { } interface PanesItemProps { title: string; diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index c073450..00cd3b9 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -64,7 +64,7 @@ const LoginForm: FC = ({ const resData = { userName: username, token: res.data.token, - permission: res.data.c || [] + permission: res.data.routes || [] } setUserInfo(resData, setStoreData) @@ -128,7 +128,7 @@ const LoginForm: FC = ({ const resData = { userName: nameRef.current, token: res.data.token, - permission: res.data.c || [] + permission: res.data.routes || [] } setUserInfo(resData, setStoreData) history.push('/') diff --git a/src/pages/system/withdraw.tsx b/src/pages/system/withdraw.tsx index 3f7a51b..eb294bc 100644 --- a/src/pages/system/withdraw.tsx +++ b/src/pages/system/withdraw.tsx @@ -113,10 +113,10 @@ const SystemWithdraw = () => { - + - + diff --git a/src/pages/vip-manage/proxy-list.tsx b/src/pages/vip-manage/proxy-list.tsx index 35e5614..5b2c851 100644 --- a/src/pages/vip-manage/proxy-list.tsx +++ b/src/pages/vip-manage/proxy-list.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef, useState } from "react"; import api from "@/api"; import MyTable from "@/components/MyTable"; -import { DeleteFilled, EditOutlined, RightCircleFilled, SolutionOutlined } from "@ant-design/icons"; +import { DeleteFilled, EditOutlined, RightCircleFilled, SolutionOutlined, StopTwoTone } from "@ant-design/icons"; import { Button, Form, Input, Modal, Popconfirm, Radio, Select, Switch, notification } from "antd"; import { getBaseUrl, getOriginUrl } from "@/utils/axios"; @@ -116,6 +116,16 @@ const ProxyList = () => { } }; + const cancelFollow = async (item) => { + const res: any = await api.cancel_follow({ id: item.id }) + if (res.code === 0) { + tableRef.current.update() + notification.success({ + message: '取消成功' + }) + } + } + const onFinishAddAccount = async (values) => { const res: any = await api.add_account({ ...values }); if (res.code === 0) { @@ -159,10 +169,19 @@ const ProxyList = () => { { getToken(row); }} /> - { - currentAccount.current = row - setModalFollow(true) - }} /> + { + row.account_follow ? ( + cancelFollow(row)} title="确认取消跟单吗?"> + + + ) : ( + { + currentAccount.current = row + setModalFollow(true) + }} /> + ) + } + {/* deleteAccount(row)}> */} @@ -194,6 +213,11 @@ const ProxyList = () => { return (
+ }]} apiFun={api.get_userList} columns={columns} ref={tableRef} diff --git a/src/route/routes.ts b/src/route/routes.ts index 13a4240..aae1598 100644 --- a/src/route/routes.ts +++ b/src/route/routes.ts @@ -20,6 +20,8 @@ import EmailLog from "@/pages/system-log/emailLog" import OperationLog from "@/pages/system-log/operationLog" import WalletLog from "@/pages/system-log/walletLog" import GoogleBind from "@/pages/google" +import AdminManage from "@/pages/config-admin/admin-manage" +import AdminPermissions from "@/pages/config-admin/admin-permissions" const routes = [ { @@ -90,6 +92,30 @@ const routes = [ } ] }, + { + path: '/config-admin', + name: '配置管理员', + exact: true, + key: 'config-admin', + icon: SolutionOutlined, + type: 'subMenu', + routes: [ + { + path: '/admin-manage', + name: '管理员设置', + exact: true, + key: 'admin-manage', + component: AdminManage, + }, + { + path: '/admin-permissions', + name: '分配权限', + exact: true, + key: 'admin-permissions', + component: AdminPermissions, + }, + ] + }, { path: '/vip-manage', name: '会员管理', @@ -249,7 +275,8 @@ const routes = [ key: 'google-bind', component: GoogleBind, icon: SolutionOutlined, - } + }, + ] diff --git a/src/utils/axios.ts b/src/utils/axios.ts index 83582b6..28650ee 100644 --- a/src/utils/axios.ts +++ b/src/utils/axios.ts @@ -38,6 +38,8 @@ const clearAll = () => { type: 'SET_USERINFO', payload: {} }) + localStorage.setItem('permissions', '') + router.history.replace({ pathname: '/login' }) } @@ -57,6 +59,9 @@ axios.interceptors.request.use( // 返回后拦截 axios.interceptors.response.use( ({ data }): Promise => { + if (data.code === 101) { + clearAll() + } if (data.code !== 0) { message.error(data.message || data.msg) return Promise.reject(data)