diff --git a/doc/RBAC 权限.sql b/doc/RBAC 权限.sql index 6e70db9..b463af5 100644 --- a/doc/RBAC 权限.sql +++ b/doc/RBAC 权限.sql @@ -45,14 +45,34 @@ VALUES ('技术研发部') INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) VALUES ('所有权限', '*', 'system') INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) -VALUES ('最新团计划', '/reservation/newest', 'oversea') +VALUES ('管理账号', '/account/management', 'system') INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) -VALUES ('账单', '/invoice', 'oversea') +VALUES ('新增账号', '/account/new', 'system') +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('禁用账号', '/account/disable', 'system') +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('重置密码', '/account/reset-password', 'system') +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('管理角色', '/account/role-new', 'system') + +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('所有海外功能', '/oversea/all', 'oversea') +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('所有国内功能', '/domestic/all', 'domestic') +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('所有机票功能', '/air-ticket/all', 'air-ticket') +-- 价格管理 +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('管理产品', '/products/*', 'products') +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('审核信息', '/products/info/audit', 'products') +INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) +VALUES ('录入信息', '/products/info/put', 'products') INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) -VALUES ('账号权限管理', '/account/management', 'system') +VALUES ('审核价格', '/products/offer/audit', 'products') INSERT INTO [dbo].[auth_resource] ([res_name] ,[res_pattern], [res_category]) -VALUES ('新增角色', '/account/new-role', 'system') +VALUES ('录入价格', '/products/offer/put', 'products') INSERT INTO [dbo].[auth_permission] ([role_id] ,[res_id]) VALUES (1, 1) diff --git a/src/config.js b/src/config.js index 03d67fd..36a5ea0 100644 --- a/src/config.js +++ b/src/config.js @@ -18,7 +18,7 @@ export const PERM_ACCOUNT_MANAGEMENT = '/account/management' export const PERM_ACCOUNT_NEW = '/account/new' export const PERM_ACCOUNT_DISABLE = '/account/disable' export const PERM_ACCOUNT_RESET_PASSWORD = '/account/reset-password' -export const PERM_ROLE_NEW = '/account/role/new' +export const PERM_ROLE_NEW = '/account/role-new' // 海外供应商 // category: oversea diff --git a/src/main.jsx b/src/main.jsx index 0346c3c..6e84eb9 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -31,6 +31,10 @@ import InvoicePaidDetail from "@/views/invoice/PaidDetail"; import Airticket from "@/views/airticket/Index"; import AirticketPlan from "@/views/airticket/Plan"; import { ThemeContext } from '@/stores/ThemeContext' +import { usingStorage } from '@/hooks/usingStorage' +import { isNotEmpty } from '@/utils/commons' +import { appendRequestParams } from '@/utils/request' +import { fireAuth } from "./utils/lifecycle" import ProductsManage from '@/views/products/Manage'; import ProductsDetail from '@/views/products/Detail'; @@ -39,6 +43,20 @@ import { PERM_ACCOUNT_MANAGEMENT, PERM_ROLE_NEW, PERM_OVERSEA, PERM_AIR_TICKET, import './i18n'; +const { loginToken, userId } = usingStorage() + +const initAppliction = async () => { + if (isNotEmpty(loginToken)) { + appendRequestParams('token', loginToken) + } + + if (isNotEmpty(userId)) { + await fireAuth() + } +} + +await initAppliction() + const router = createBrowserRouter([ { path: "/", @@ -76,7 +94,7 @@ const router = createBrowserRouter([ { path: "/logout", element: }, ] } -]); +]) ReactDOM.createRoot(document.getElementById("root")).render( @@ -88,4 +106,4 @@ ReactDOM.createRoot(document.getElementById("root")).render( /> // -); +) diff --git a/src/stores/Account.js b/src/stores/Account.js index 6c6410e..804299a 100644 --- a/src/stores/Account.js +++ b/src/stores/Account.js @@ -45,6 +45,27 @@ export const fetchRoleList = async () => { return errcode !== 0 ? {} : result } +export const fetchPermissionList = async () => { + + const { errcode, result } = await fetchJSON( + `${HT_HOST}/service-CooperateSOA/get_all_permission_list`) + return errcode !== 0 ? {} : result +} + +export const fetchPermissionListByRoleId = async (params) => { + + const { errcode, result } = await fetchJSON( + `${HT_HOST}/service-CooperateSOA/get_role_permission_list`, params) + return errcode !== 0 ? {} : result +} + +export const fetchTravelAgencyByName = async (name) => { + + const { errcode, result } = await fetchJSON( + `${HT_HOST}/Service_BaseInfoWeb/VendorList`, {q: name}) + return errcode !== 0 ? {} : result +} + const useAccountStore = create((set, get) => ({ accountList: [], @@ -82,7 +103,7 @@ const useAccountStore = create((set, get) => ({ const formData = new FormData() formData.append('role_id', formValues.role_id) formData.append('role_name', formValues.role_name) - formData.append('res_ids', '2,3') + formData.append('res_ids', formValues.res_array.join(',')) return postRoleForm(formData) }, @@ -124,7 +145,7 @@ const useAccountStore = create((set, get) => ({ realname: r.real_name, email: r.email, lastLogin: r.wu_lastlogindate, - travelAgency: r.travel_agency_name, + travelAgencyName: r.travel_agency_name, travelAgencyId: r.travel_agency_id, // 数据库支持逗号分隔多角色(5,6,7),目前界面只需单个。 roleId: parseInt(r.roles), diff --git a/src/stores/Auth.js b/src/stores/Auth.js index c82a3c5..c413edb 100644 --- a/src/stores/Auth.js +++ b/src/stores/Auth.js @@ -3,12 +3,17 @@ import { appendRequestParams, fetchJSON, postForm } from '@/utils/request' import { HT_HOST } from "@/config" import { loadPageSpy } from '@/pageSpy' import { usingStorage } from '@/hooks/usingStorage' +import { devtools } from 'zustand/middleware' + +import { obervseLifecycle } from '@/utils/lifecycle' const KEY_LOGIN_TOKEN = 'G-STR:LOGIN_TOKEN' const KEY_TRAVEL_AGENCY_ID = 'G-INT:TRAVEL_AGENCY_ID' const KEY_USER_ID = 'G-INT:USER_ID' const KEY_USER_DETAIL = 'G-JSON:USER_DETAIL' +const WILDCARD_TOKEN = '*' + export const fetchLoginToken = async (username, password) => { const formData = new FormData() @@ -28,12 +33,26 @@ export const fetchUserDetail = async (loginToken) => { return errcode !== 0 ? {} : Result } +export const fetchPermissionListByUserId = async (userId) => { + + const { errcode, result } = await fetchJSON( + `${HT_HOST}/service-CooperateSOA/get_account_permission_list`, { wu_id: userId}) + return errcode !== 0 ? {} : result +} + async function fetchLastRequet() { const { errcode, result } = await fetchJSON(`${HT_HOST}/service-CooperateSOA/GetLastReqDate`) return errcode !== 0 ? {} : result } -const useAuthStore = create((set, get) => ({ +const useAuthStore = create(obervseLifecycle((set, get) => ({ + + onAuth: () => { + const { startTokenInterval, loadUserPermission } = get() + const { userId } = usingStorage() + loadUserPermission(userId) + startTokenInterval() + }, tokenInterval: null, @@ -41,66 +60,62 @@ const useAuthStore = create((set, get) => ({ loginStatus: 0, - loginUser: { - token: '', - telephone: '', - emailAddress: '', - cityId: 0, - permissionList: [], - }, + permissionList: [], isPermitted: (perm) => { - return true + const { permissionList } = get() + // 测试权限使用: + // if (perm === '/account/management') return false + // if (perm === '/account/role/new') return false + // return true // 以上是 Hardcode 判断 // 以下是权限列表从数据库读取后使用的方法 - // return this.permissionList.some((value, key, arry) => { - // if (value.indexOf(WILDCARD_TOKEN) > -1) { - // return true - // } - // if (value === perm) { - // return true - // } - // return false - // }) - + return permissionList.some((value) => { + if (value.indexOf(WILDCARD_TOKEN) > -1) { + return true + } + if (value === perm) { + return true + } + return false + }) }, validateUserPassword: async (usr, pwd) => { - const { startTokenInterval } = get() + const { startTokenInterval, loadUserPermission } = get() const { setStorage } = usingStorage() - const { token: loginToken } = await fetchLoginToken(usr, pwd) - + const { token: loginToken, WU_ID: userId } = await fetchLoginToken(usr, pwd) const userDetail = await fetchUserDetail(loginToken) + await loadUserPermission(userId) set(() => ({ - loginUser: { - telephone: userDetail.LkPhone, - emailAddress: userDetail.LMI_listmail, - cityId: userDetail.citysn, - }, tokenTimeout: false, loginStatus: 302 })) setStorage(KEY_LOGIN_TOKEN, loginToken) - setStorage(KEY_USER_ID, userDetail.LMI_SN) + setStorage(KEY_USER_ID, userId) setStorage(KEY_TRAVEL_AGENCY_ID, userDetail.LMI_VEI_SN) - setStorage(KEY_USER_DETAIL, {username: userDetail.LoginName, travelAgencyName: userDetail.VName}) appendRequestParams('token', loginToken) appendRequestParams('wu_id', userDetail.LMI_SN) // loadPageSpy(`${json.Result.VName}-${json.Result.LoginName}`) startTokenInterval() }, + loadUserPermission: async(userId) => { + const permissionResult = await fetchPermissionListByUserId(userId) + set(() => ({ + permissionList: permissionResult.map(p => p.res_pattern) + })) + }, + logout: () => { const { tokenInterval } = get() const { clearStorage } = usingStorage() clearStorage() clearInterval(tokenInterval) set(() => ({ - loginUser: { - }, loginStatus: 0, tokenInterval: null, tokenTimeout: true @@ -153,6 +168,7 @@ const useAuthStore = create((set, get) => ({ } }); }, -})) + +}))) export default useAuthStore \ No newline at end of file diff --git a/src/utils/lifecycle.js b/src/utils/lifecycle.js new file mode 100644 index 0000000..a2de514 --- /dev/null +++ b/src/utils/lifecycle.js @@ -0,0 +1,42 @@ +const initListener = [] +const authListener = [] + +export const onInit = (fn) => { + initListener.push(fn) +} + +export const onAuth = (fn) => { + authListener.push(fn) +} + +export const fireInit = async () => { + initListener.forEach(async (fn) => { + await fn() + }) +} + +export const fireAuth = (obj) => { + authListener.forEach(fn => fn(obj)) +} + +// Zustand 中间件,用于订阅前端应用的生命周期,实验阶段 +export const obervseLifecycle = (fn) => (set, get, store) => { + + onInit(() => { + if (store.getState().hasOwnProperty('onInit')) { + store.getState().onInit() + } else { + console.info('store has no function: onInit.') + } + }) + + onAuth(() => { + if (store.getState().hasOwnProperty('onAuth')) { + store.getState().onAuth() + } else { + console.info('store has no function: onAuth.') + } + }) + + return fn(set, get, store) +} \ No newline at end of file diff --git a/src/views/App.jsx b/src/views/App.jsx index 190067b..f9a37ad 100644 --- a/src/views/App.jsx +++ b/src/views/App.jsx @@ -5,7 +5,6 @@ import { DownOutlined } from '@ant-design/icons'; import 'antd/dist/reset.css'; import AppLogo from '@/assets/logo-gh.png'; import { isEmpty } from '@/utils/commons'; -import { appendRequestParams } from '@/utils/request' import Language from '../i18n/LanguageSwitcher'; import { useTranslation } from 'react-i18next'; import zhLocale from 'antd/locale/zh_CN'; @@ -15,18 +14,23 @@ import ErrorBoundary from '@/components/ErrorBoundary' import { BUILD_VERSION, } from '@/config'; import useNoticeStore from '@/stores/Notice'; import useAuthStore from '@/stores/Auth' +import { fetchUserDetail} from '@/stores/Auth' import { usingStorage } from '@/hooks/usingStorage' +import { PERM_ACCOUNT_MANAGEMENT, PERM_ROLE_NEW, PERM_OVERSEA, PERM_AIR_TICKET } from '@/config' + const { Header, Content, Footer } = Layout; const { Title } = Typography; function App() { + const { t, i18n } = useTranslation(); const [password, setPassword] = useState('') + const [userDetail, setUserDetail] = useState({}) - const [validateUserPassword, tokenTimeout] = useAuthStore( - (state) => [state.validateUserPassword, state.tokenTimeout]) + const [validateUserPassword, tokenTimeout, isPermitted] = useAuthStore( + (state) => [state.validateUserPassword, state.tokenTimeout, state.isPermitted]) const { loginToken, userDetail, userId } = usingStorage() @@ -42,6 +46,15 @@ function App() { appendRequestParams('token', loginToken) appendRequestParams('wu_id', userId) } + useEffect(() => { + fetchUserDetail(loginToken) + .then(u => { + setUserDetail({ + username: u.LoginName, + travelAgencyName: u.VName, + }) + }) + }, [loginToken]) useEffect(() => { if (needToLogin) { @@ -51,7 +64,7 @@ function App() { useEffect(() => { window.gtag('event', 'page_view', { page_location: window.location.href }); - }, [location]); + }, [location]) const onSubmit = () => { validateUserPassword(userDetail?.username, password) @@ -121,11 +134,11 @@ function App() { mode='horizontal' selectedKeys={[defaultPath]} items={[ - { key: 'reservation', label: {t('menu.Reservation')} }, - { key: 'invoice', label: {t('menu.Invoice')} }, - { key: 'feedback', label: {t('menu.Feedback')} }, - { key: 'report', label: {t('menu.Report')} }, - { key: 'airticket', label: {t('menu.Airticket')} }, + isPermitted(PERM_OVERSEA) ? { key: 'reservation', label: {t('menu.Reservation')} } : null, + isPermitted(PERM_OVERSEA) ? { key: 'invoice', label: {t('menu.Invoice')} } : null, + isPermitted(PERM_OVERSEA) ? { key: 'feedback', label: {t('menu.Feedback')} } : null, + isPermitted(PERM_OVERSEA) ? { key: 'report', label: {t('menu.Report')} } : null, + isPermitted(PERM_AIR_TICKET) ? { key: 'airticket', label: {t('menu.Airticket')} } : null, { key: 'products', label: {t('menu.Products')} }, { key: 'notice', @@ -150,13 +163,11 @@ function App() { items: [...[ { label: {t('ChangePassword')}, key: '0' }, { label: {t('Profile')}, key: '1' }, - { label: {t('account:management.tile')}, key: '3' }, - { label: {t('account:management.roleList')}, key: '4' }, + isPermitted(PERM_ACCOUNT_MANAGEMENT) ? { label: {t('account:management.tile')}, key: '3' } : null, + isPermitted(PERM_ROLE_NEW) ? { label: {t('account:management.roleList')}, key: '4' } : null, { type: 'divider' }, { label: {t('Logout')}, key: '99' }, - ], - { type: 'divider' }, - { label: <>v{BUILD_VERSION}, key: 'BUILD_VERSION' }, + ] ], }} trigger={['click']} @@ -183,7 +194,7 @@ function App() { }}> {needToLogin ? <>login... : } -
+
China Highlights International Travel Service Co., LTD, Version: {BUILD_VERSION}
diff --git a/src/views/account/Management.jsx b/src/views/account/Management.jsx index 6c2c323..517f03f 100644 --- a/src/views/account/Management.jsx +++ b/src/views/account/Management.jsx @@ -1,14 +1,14 @@ -import { useState } from 'react' +import { useState, useEffect } from 'react' import { Row, Col, Space, Button, Table, Select, TreeSelect, Typography, Modal, App, Form, Input } from 'antd' import { ExclamationCircleFilled } from '@ant-design/icons' import { useTranslation } from 'react-i18next' -import useFormStore from '@/stores/Form' -import useAuthStore from '@/stores/Auth' +import { fetchTravelAgencyByName } from '@/stores/Account' +import dayjs from 'dayjs' +import { isEmpty } from '@/utils/commons' import useAccountStore from '@/stores/Account' +import useFormStore from '@/stores/Form' import { fetchRoleList } from '@/stores/Account' import SearchForm from '@/components/SearchForm' -import RequireAuth from '@/components/RequireAuth' -import { PERM_ROLE_NEW } from '@/config' const { Title } = Typography @@ -27,7 +27,7 @@ function Management() { }, { title: t('account:travelAgency'), - dataIndex: 'travelAgency', + dataIndex: 'travelAgencyName', }, { title: t('account:email'), @@ -40,6 +40,7 @@ function Management() { { title: t('account:lastLogin'), dataIndex: 'lastLogin', + render: (text) => (isEmpty(text) ? '' : dayjs(text).format('YYYY-MM-DD HH:mm:ss')) }, { title: t('account:action'), @@ -66,30 +67,63 @@ function Management() { const [isAccountModalOpen, setAccountModalOpen] = useState(false) const [dataLoading, setDataLoading] = useState(false) const [roleAllList, setRoleAllList] = useState([]) + const [travelAgencyList, setTravelAgencyList] = useState([]) + const [currentTravelAgency, setCurrentTravelAgency] = useState(null) const [accountForm] = Form.useForm() const [searchAccountByCriteria, accountList, disableAccount, saveOrUpdateAccount, resetAccountPassword] = useAccountStore((state) => [state.searchAccountByCriteria, state.accountList, state.disableAccount, state.saveOrUpdateAccount, state.resetAccountPassword]) + const formValues = useFormStore(state => state.formValues) const { notification, modal } = App.useApp() + useEffect (() => { + fetchRoleList() + .then((roleList) => { + setRoleAllList(roleList.map(r => { + return { + value: r.role_id, + label: r.role_name, + disabled: r.role_id === 1 + } + })) + }) + }, []) + + const handelAccountSearch = () => { + setDataLoading(true) + searchAccountByCriteria(formValues) + .catch(ex => { + notification.error({ + message: 'Notification', + description: ex.message, + placement: 'top', + duration: 4, + }) + }) + .finally(() => { + setDataLoading(false) + }) + } + const onAccountSeleted = async (account) => { + console.info(account) + setTravelAgencyList([{ + label: account.travelAgencyName, + value: account.travelAgencyId + }]) accountForm.setFieldsValue(account) - const roleList = await fetchRoleList() - setRoleAllList(roleList.map(r => { - return { - value: r.role_id, - label: r.role_name, - disabled: r.role_id === 1 - } - })) + setCurrentTravelAgency(account.travelAgencyId) setAccountModalOpen(true) } const onAccountFinish = (values) => { console.log(values) saveOrUpdateAccount(values) + .then(() => { + handelAccountSearch() + }) .catch(ex => { notification.error({ message: 'Notification', @@ -105,6 +139,27 @@ function Management() { // form.resetFields() } + const handleTravelAgencySearch = (newValue) => { + setDataLoading(true) + fetchTravelAgencyByName(newValue) + .then(result => { + setTravelAgencyList(result.map(r => { + return { + label: r.travel_agency_name, + value: r.travel_agency_id + } + })) + }) + .finally(() => { + setDataLoading(false) + }) + } + + const handleTravelAgencyChange = (newValue) => { + console.info(newValue) + setCurrentTravelAgency(newValue) + } + const showDisableConfirm = (account) => { modal.confirm({ title: 'Do you want to disable this account?', @@ -219,7 +274,17 @@ function Management() { }, ]} > - + { - console.info(formValues) - setDataLoading(true) - searchAccountByCriteria(formValues) - .catch(ex => { - notification.error({ - message: 'Notification', - description: ex.message, - placement: 'top', - duration: 4, - }) - }) - .finally(() => { - setDataLoading(false) - }) + onSubmit={() => { + handelAccountSearch() }} /> diff --git a/src/views/account/RoleList.jsx b/src/views/account/RoleList.jsx index 9686304..13a1501 100644 --- a/src/views/account/RoleList.jsx +++ b/src/views/account/RoleList.jsx @@ -1,103 +1,15 @@ import { useState, useEffect } from 'react' -import { Row, Col, Space, Button, Table, Select, TreeSelect, Typography, Modal, App, Form, Input } from 'antd' -import { ExclamationCircleFilled } from '@ant-design/icons' +import { Row, Col, Space, Button, Table, TreeSelect, Typography, Modal, App, Form, Input } from 'antd' import { useTranslation } from 'react-i18next' -import useFormStore from '@/stores/Form' -import useAuthStore from '@/stores/Auth' import useAccountStore from '@/stores/Account' -import { fetchRoleList } from '@/stores/Account' -import SearchForm from '@/components/SearchForm' +import { fetchRoleList, fetchPermissionList, fetchPermissionListByRoleId } from '@/stores/Account' +import dayjs from 'dayjs' +import { isEmpty } from '@/utils/commons' import RequireAuth from '@/components/RequireAuth' import { PERM_ROLE_NEW } from '@/config' const { Title } = Typography -const permissionData = [ - { - title: '海外供应商', - value: 'oversea-0', - key: 'oversea-0', - children: [ - { - title: '所有海外功能', - value: 'oversea-0-0', - key: 'oversea-0-0', - }, - ], - }, - { - title: '机票管理', - value: '0-0', - key: '0-0', - children: [ - { - title: '录入机票价格', - value: '0-0-0', - key: '0-0-0', - }, - ], - }, - { - title: '产品管理', - value: '0-1', - key: '0-1', - children: [ - { - title: '搜索供应商产品', - value: 'B-1-0', - key: 'B-1-0', - }, - { - title: '录入产品价格', - value: '0-1-0', - key: '0-1-0', - }, - { - title: '新增产品描述', - value: '0-1-1', - key: '0-1-1', - }, - { - title: '复制供应商产品信息', - value: '0-1-2', - key: '0-1-2', - }, - ], - }, - { - title: '账号管理', - value: '2-1', - key: '2-1', - children: [ - { - title: '搜索账号', - value: '2-1-01', - key: '2-1-01', - }, - { - title: '新增账号', - value: '2-1-11', - key: '2-1-11', - }, - { - title: '禁用账号', - value: '2-1-21', - key: '2-1-21', - }, - { - title: '重置账号密码', - value: '2-1-31', - key: '2-1-31', - }, - { - title: '新增角色', - value: '2-1-41', - key: '2-1-41', - }, - ], - }, -] - function RoleList() { const { t } = useTranslation() @@ -109,6 +21,7 @@ function RoleList() { { title: t('account:createdOn'), dataIndex: 'created_on', + render: (text) => (isEmpty(text) ? '' : dayjs(text).format('YYYY-MM-DD HH:mm:ss')) }, { title: t('account:action'), @@ -126,10 +39,16 @@ function RoleList() { } const onPermissionChange = (newValue) => { - console.log('onChange ', newValue) setPermissionValue(newValue) } + function groupByParam(array, param) { + return array.reduce((result, item) => { + (result[item[param]] = result[item[param]] || []).push(item) + return result + }, {}) + } + useEffect (() => { setDataLoading(true) fetchRoleList() @@ -139,9 +58,46 @@ function RoleList() { .finally(() => { setDataLoading(false) }) + + const categoryMap = new Map([ + ['system', '系统管理'], + ['oversea', '海外供应商'], + ['domestic', '国内供应商'], + ['air-ticket', '机票供应商'], + ['products', '产品价格'], + ]); + + const permissionTree = [] + fetchPermissionList() + .then(r => { + + const groupPermissionData = groupByParam(r, 'res_category') + const categoryKeys = Object.keys(groupPermissionData) + + categoryKeys.forEach((categoryName) => { + const permissisonList = groupPermissionData[categoryName] + const categoryGroup = { + title: categoryMap.get(categoryName), + value: categoryName, + key: categoryName, + children: permissisonList.map(p => { + return { + disableCheckbox: p.res_id == 1, + title: p.res_name, + value: p.res_id, + key: p.res_id, + } + }) + } + permissionTree.push(categoryGroup) + }) + + setPermissionTreeData(permissionTree) + }) }, []) - const [permissionValue, setPermissionValue] = useState(['0-0-0']) + const [permissionValue, setPermissionValue] = useState([]) + const [permissionTreeData, setPermissionTreeData] = useState([]) const [isRoleModalOpen, setRoleModalOpen] = useState(false) const [dataLoading, setDataLoading] = useState(false) const [roleAllList, setRoleAllList] = useState([]) @@ -154,7 +110,11 @@ function RoleList() { const { notification, modal } = App.useApp() const onRoleSeleted = (role) => { - roleForm.setFieldsValue(role) + fetchPermissionListByRoleId({role_id: role.role_id}) + .then(result => { + role.res_array = result.map(r => r.res_id) + roleForm.setFieldsValue(role) + }) setRoleModalOpen(true) } @@ -165,10 +125,14 @@ function RoleList() { } const onRoleFinish = (values) => { - console.log(values) saveOrUpdateRole(values) + .then(() => { + fetchRoleList() + .then(r => { + setRoleAllList(r) + }) + }) .catch(ex => { - console.info(ex.message) notification.error({ message: 'Notification', description: ex.message, @@ -179,7 +143,6 @@ function RoleList() { } const onRoleFailed = (error) => { - console.log('Failed:', error) // form.resetFields() } @@ -225,8 +188,11 @@ function RoleList() { > - - +