diff --git a/public/locales/zh/account.json b/public/locales/zh/account.json index a7caf37..35c0dc0 100644 --- a/public/locales/zh/account.json +++ b/public/locales/zh/account.json @@ -8,5 +8,24 @@ "CurrentPassword": "请输入密码。", "NewPassword": "请输入新密码。", "ReenterPassword": "请重复输入密码。" - } + }, + "createdOn": "创建时间", + "action": "操作", + "action.edit": "编辑", + "action.disable": "禁用", + "action.resetPassword": "重置密码", + + "accountList": "管理账号", + "newAccount": "新增账号", + "detail": "详细信息", + "username": "用户名", + "realname": "姓名", + "travelAgencyName": "供应商名称", + "email": "邮箱地址", + "lastLogin": "最后登陆时间", + + "roleList": "管理角色", + "newRole": "新增角色", + "roleName": "角色名称", + "permission": "权限" } \ No newline at end of file diff --git a/src/main.jsx b/src/main.jsx index eb70c92..f7a0b42 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -9,7 +9,6 @@ import App from "@/views/App"; import Standlone from "@/views/Standlone"; import Login from "@/views/Login"; import Logout from "@/views/Logout"; -import Index from "@/views/index"; import ErrorPage from "@/components/ErrorPage"; import RequireAuth from '@/components/RequireAuth' import ReservationNewest from "@/views/reservation/Newest"; @@ -49,6 +48,8 @@ const initAppliction = async () => { if (isNotEmpty(loginToken)) { appendRequestParams('token', loginToken) + appendRequestParams('lmi_sn', userId) + } if (isNotEmpty(userId)) { @@ -65,7 +66,7 @@ const router = createBrowserRouter([ element: , errorElement: , children: [ - { index: true, element: }, + { index: true, element: }, { path: "account/change-password", element: }, { path: "account/profile", element: }, { path: "account/management", element: }, @@ -76,14 +77,14 @@ const router = createBrowserRouter([ { path: "feedback/:GRI_SN/:CII_SN/:RefNo", element: }, { path: "feedback/:GRI_SN/:RefNo", element: }, { path: "report", element: }, - { path: "notice", element: }, - { path: "notice/:CCP_BLID", element: }, + { path: "notice", element: }, + { path: "notice/:CCP_BLID", element: }, { path: "invoice",element:}, { path: "invoice/detail/:GMDSN/:GSN",element:}, { path: "invoice/paid",element:}, { path: "invoice/paid/detail/:flid", element: }, { path: "airticket",element: }, - { path: "airticket/plan/:coli_sn",element:}, + { path: "airticket/plan/:coli_sn",element:}, { path: "products",element: }, { path: "products/:travel_agency_id/:use_year/:audit_state/audit",element:}, { path: "products/:travel_agency_id/:use_year/:audit_state/edit",element:}, diff --git a/src/stores/Account.js b/src/stores/Account.js index 804299a..01010d8 100644 --- a/src/stores/Account.js +++ b/src/stores/Account.js @@ -70,11 +70,11 @@ const useAccountStore = create((set, get) => ({ accountList: [], - disableAccount: async (accountId) => { + disableAccount: async (userId) => { const formData = new FormData() - formData.append('wu_id', accountId) - // enable disable + formData.append('lmi_sn', userId) + // enable | disable formData.append('account_status', 'disable') const result = await postAccountStatus(formData) @@ -82,10 +82,10 @@ const useAccountStore = create((set, get) => ({ console.info(result) }, - resetAccountPassword: async (accountId, password) => { + resetAccountPassword: async (userId, password) => { const formData = new FormData() - formData.append('wu_id', accountId) + formData.append('lmi_sn', userId) formData.append('newPassword', password) return postAccountPassword(formData) @@ -111,8 +111,8 @@ const useAccountStore = create((set, get) => ({ saveOrUpdateAccount: async (formValues) => { const { userId } = usingStorage() const formData = new FormData() - formData.append('wu_id', formValues.userId) - formData.append('lmi_sn', formValues.lmi_sn) + formData.append('wu_id', formValues.accountId) + formData.append('lmi_sn', formValues.userId) formData.append('lmi2_sn', formValues.lmi2_sn) formData.append('user_name', formValues.username) formData.append('real_name', formValues.realname) @@ -138,8 +138,8 @@ const useAccountStore = create((set, get) => ({ const mapAccoutList = resultArray.map((r) => { return { - userId: r.wu_id, - lmi_sn: r.lmi_sn, + accountId: r.wu_id, + userId: r.lmi_sn, lmi2_sn: r.lmi2_sn, username: r.user_name, realname: r.real_name, diff --git a/src/stores/Auth.js b/src/stores/Auth.js index c413edb..421d4cb 100644 --- a/src/stores/Auth.js +++ b/src/stores/Auth.js @@ -36,7 +36,7 @@ export const fetchUserDetail = async (loginToken) => { export const fetchPermissionListByUserId = async (userId) => { const { errcode, result } = await fetchJSON( - `${HT_HOST}/service-CooperateSOA/get_account_permission_list`, { wu_id: userId}) + `${HT_HOST}/service-CooperateSOA/get_account_permission_list`, { lmi_sn: userId}) return errcode !== 0 ? {} : result } @@ -71,7 +71,7 @@ const useAuthStore = create(obervseLifecycle((set, get) => ({ // 以上是 Hardcode 判断 // 以下是权限列表从数据库读取后使用的方法 return permissionList.some((value) => { - if (value.indexOf(WILDCARD_TOKEN) > -1) { + if (value.indexOf(WILDCARD_TOKEN) == 0) { return true } if (value === perm) { @@ -85,9 +85,9 @@ const useAuthStore = create(obervseLifecycle((set, get) => ({ const { startTokenInterval, loadUserPermission } = get() const { setStorage } = usingStorage() - const { token: loginToken, WU_ID: userId } = await fetchLoginToken(usr, pwd) + const { token: loginToken } = await fetchLoginToken(usr, pwd) const userDetail = await fetchUserDetail(loginToken) - await loadUserPermission(userId) + await loadUserPermission(userDetail.LMI_SN) set(() => ({ tokenTimeout: false, @@ -95,7 +95,7 @@ const useAuthStore = create(obervseLifecycle((set, get) => ({ })) setStorage(KEY_LOGIN_TOKEN, loginToken) - setStorage(KEY_USER_ID, userId) + setStorage(KEY_USER_ID, userDetail.LMI_SN) setStorage(KEY_TRAVEL_AGENCY_ID, userDetail.LMI_VEI_SN) appendRequestParams('token', loginToken) appendRequestParams('wu_id', userDetail.LMI_SN) @@ -131,7 +131,7 @@ const useAuthStore = create(obervseLifecycle((set, get) => ({ const now = new Date() const diffTime = now.getTime() - lastReqDate.getTime() const diffHours = diffTime/1000/60/60 - if (diffHours > 4) { + if (diffHours > 1) { loginTimeout() } } @@ -144,7 +144,8 @@ const useAuthStore = create(obervseLifecycle((set, get) => ({ loginTimeout: () => { const { tokenInterval } = get() - // TODO: 这里没有清理 token,刷新后可以正常使用系统 + const { clearStorage } = usingStorage() + clearStorage() clearInterval(tokenInterval) set(() => ({ tokenTimeout: true diff --git a/src/views/App.jsx b/src/views/App.jsx index 0ebcff4..3541d9b 100644 --- a/src/views/App.jsx +++ b/src/views/App.jsx @@ -4,7 +4,7 @@ import { Layout, Menu, ConfigProvider, theme, Dropdown, Space, Row, Col, Badge, import { DownOutlined } from '@ant-design/icons'; import 'antd/dist/reset.css'; import AppLogo from '@/assets/logo-gh.png'; -import { isEmpty } from '@/utils/commons'; +import { isEmpty, isNotEmpty } from '@/utils/commons'; import Language from '../i18n/LanguageSwitcher'; import { useTranslation } from 'react-i18next'; import zhLocale from 'antd/locale/zh_CN'; @@ -43,13 +43,15 @@ function App() { const needToLogin = href !== '/login' && isEmpty(loginToken) useEffect(() => { - fetchUserDetail(loginToken) - .then(u => { - setUserDetail({ - username: u.LoginName, - travelAgencyName: u.VName, + if (isNotEmpty(loginToken)) { + fetchUserDetail(loginToken) + .then(u => { + setUserDetail({ + username: u.LoginName, + travelAgencyName: u.VName, + }) }) - }) + } }, [loginToken]) useEffect(() => { @@ -58,10 +60,6 @@ function App() { } }, [href]) - useEffect(() => { - window.gtag('event', 'page_view', { page_location: window.location.href }); - }, [location]) - const onSubmit = () => { validateUserPassword(userDetail?.username, password) .catch(ex => { @@ -69,23 +67,24 @@ function App() { alert(t('Validation.LoginFailed')) }) setPassword('') - }; + } - const splitPath = href.split('/'); - let defaultPath = 'reservation'; + const splitPath = href.split('/') + let defaultPath = 'notice' if (splitPath.length > 1) { - defaultPath = splitPath[1]; + defaultPath = splitPath[1] } const { token: { colorBgContainer }, - } = theme.useToken(); + } = theme.useToken() const [antdLng, setAntdLng] = useState(enLocale); useEffect(() => { setAntdLng(i18n.language === 'en' ? enLocale : zhLocale); - }, [i18n.language]); + }, [i18n.language]) + return ( {t('ChangePassword')}, key: '0' }, { label: {t('Profile')}, key: '1' }, - 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' }, + isPermitted(PERM_ACCOUNT_MANAGEMENT) ? { label: {t('account:accountList')}, key: '3' } : null, + isPermitted(PERM_ROLE_NEW) ? { label: {t('account:roleList')}, key: '4' } : null, { type: 'divider' }, { label: {t('Logout')}, key: '99' }, ] @@ -195,7 +195,7 @@ function App() { - ); + ) } export default App diff --git a/src/views/Index.jsx b/src/views/Index.jsx deleted file mode 100644 index 9034490..0000000 --- a/src/views/Index.jsx +++ /dev/null @@ -1,13 +0,0 @@ -export default function Index() { - return ( -

- Global Highlights Hub -
- Check out{" "} - - the docs at chinahighlights.com - - . -

- ); -} \ No newline at end of file diff --git a/src/views/Login.jsx b/src/views/Login.jsx index b973b96..f9c3008 100644 --- a/src/views/Login.jsx +++ b/src/views/Login.jsx @@ -17,7 +17,7 @@ function Login() { useEffect (() => { if (loginStatus === 302) { - navigate('/reservation/newest') + navigate('/') } }, [loginStatus]) diff --git a/src/views/account/Management.jsx b/src/views/account/Management.jsx index f58a125..d3e3d2d 100644 --- a/src/views/account/Management.jsx +++ b/src/views/account/Management.jsx @@ -1,14 +1,12 @@ -import { useState, useEffect } from 'react' -import { Row, Col, Space, Button, Table, Select, TreeSelect, Typography, Modal, App, Form, Input } from 'antd' +import SearchForm from '@/components/SearchForm' +import useAccountStore, { fetchRoleList, fetchTravelAgencyByName } from '@/stores/Account' +import useFormStore from '@/stores/Form' +import { isEmpty } from '@/utils/commons' import { ExclamationCircleFilled } from '@ant-design/icons' -import { useTranslation } from 'react-i18next' -import { fetchTravelAgencyByName } from '@/stores/Account' +import { App, Button, Col, Form, Input, Modal, Row, Select, Space, Table, Typography } from 'antd' 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 { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' const { Title } = Typography @@ -26,7 +24,7 @@ function Management() { dataIndex: 'realname', }, { - title: t('account:travelAgency'), + title: t('account:travelAgencyName'), dataIndex: 'travelAgencyName', }, { @@ -34,7 +32,7 @@ function Management() { dataIndex: 'email', }, { - title: t('account:role'), + title: t('account:roleName'), dataIndex: 'role' }, { @@ -43,7 +41,7 @@ function Management() { render: (text) => (isEmpty(text) ? '' : dayjs(text).format('YYYY-MM-DD HH:mm:ss')) }, { - title: t('account:action'), + title: t('account:action.edit'), dataIndex: 'account:action', render: actionRender }, @@ -78,7 +76,7 @@ function Management() { const formValues = useFormStore(state => state.formValues) const { notification, modal } = App.useApp() - useEffect (() => { + useEffect(() => { fetchRoleList() .then((roleList) => { setRoleAllList(roleList.map(r => { @@ -108,7 +106,6 @@ function Management() { } const onAccountSeleted = async (account) => { - console.info(account) setTravelAgencyList([{ label: account.travelAgencyName, value: account.travelAgencyId @@ -156,7 +153,6 @@ function Management() { } const handleTravelAgencyChange = (newValue) => { - console.info(newValue) setCurrentTravelAgency(newValue) } @@ -189,7 +185,6 @@ function Management() { duration: 60, }) }) - console.log('ResetPassword') }, onCancel() { }, @@ -204,32 +199,32 @@ function Management() { autoFocus: true, htmlType: 'submit', }} - title={t('account:management.newAccount')} + title={t('account:detail')} open={isAccountModalOpen} onOk={() => setAccountModalOpen(false)} onCancel={() => setAccountModalOpen(false)} destroyOnClose={true} clearOnDestroy={true} modalRender={(dom) => (
+ name='AccountForm' + form={accountForm} + layout='vertical' + size='large' + style={{ + maxWidth: 600, + }} + onFinish={onAccountFinish} + onFinishFailed={onAccountFailed} + autoComplete='off' + > {dom}
)} > - - - + + + - - {t('account:management.tile')} + {t('account:accountList')} - + diff --git a/src/views/account/RoleList.jsx b/src/views/account/RoleList.jsx index 13a1501..71909f1 100644 --- a/src/views/account/RoleList.jsx +++ b/src/views/account/RoleList.jsx @@ -1,12 +1,14 @@ -import { useState, useEffect } from 'react' -import { Row, Col, Space, Button, Table, TreeSelect, Typography, Modal, App, Form, Input } from 'antd' -import { useTranslation } from 'react-i18next' -import useAccountStore from '@/stores/Account' -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' +import useAccountStore, { fetchPermissionList, fetchPermissionListByRoleId, fetchRoleList } from '@/stores/Account' +import { isEmpty } from '@/utils/commons' +import { + SyncOutlined, +} from '@ant-design/icons' +import { App, Button, Col, Form, Input, Modal, Row, Space, Table, Tag, TreeSelect, Typography } from 'antd' +import dayjs from 'dayjs' +import { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' const { Title } = Typography @@ -15,7 +17,7 @@ function RoleList() { const roleListColumns = [ { - title: t('account:rolename'), + title: t('account:roleName'), dataIndex: 'role_name', }, { @@ -30,8 +32,10 @@ function RoleList() { }, ] - function actionRender(text, role) { - if (role.role_id > 1) { + function actionRender(_, role) { + if (role.role_id == 1) { + return (} color='warning'>不能修改) + } else { return ( ) @@ -49,7 +53,7 @@ function RoleList() { }, {}) } - useEffect (() => { + useEffect(() => { setDataLoading(true) fetchRoleList() .then(r => { @@ -110,7 +114,7 @@ function RoleList() { const { notification, modal } = App.useApp() const onRoleSeleted = (role) => { - fetchPermissionListByRoleId({role_id: role.role_id}) + fetchPermissionListByRoleId({ role_id: role.role_id }) .then(result => { role.res_array = result.map(r => r.res_id) roleForm.setFieldsValue(role) @@ -154,71 +158,71 @@ function RoleList() { autoFocus: true, htmlType: 'submit', }} - title={t('account:management.newRole')} + title={t('account:detail')} open={isRoleModalOpen} onOk={() => setRoleModalOpen(false)} onCancel={() => setRoleModalOpen(false)} destroyOnClose={true} clearOnDestroy={true} modalRender={(dom) => (
+ name='RoleForm' + form={roleForm} + layout='vertical' + size='large' + style={{ + maxWidth: 600, + }} + onFinish={onRoleFinish} + onFinishFailed={onRoleFailed} + autoComplete='off' + > {dom}
)} > - - - - - - - + + + + + + + - {t('account:management.roleList')} + {t('account:roleList')} - + @@ -230,6 +234,7 @@ function RoleList() { loading={dataLoading} rowKey='role_id' pagination={{ + pageSize: 20, showQuickJumper: true, showLessItems: true, showSizeChanger: true,