diff --git a/doc/价格管理平台.bmpr b/doc/价格管理平台.bmpr
index 2e3bd02..e1065f7 100644
Binary files a/doc/价格管理平台.bmpr and b/doc/价格管理平台.bmpr differ
diff --git a/package.json b/package.json
index 7b26815..dd39be7 100644
--- a/package.json
+++ b/package.json
@@ -15,8 +15,6 @@
"i18next": "^23.11.5",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.5.2",
- "mobx": "^6.9.0",
- "mobx-react": "^7.6.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-i18next": "^14.1.2",
diff --git a/src/components/RequireAuth.jsx b/src/components/RequireAuth.jsx
index d8feee7..cabef0b 100644
--- a/src/components/RequireAuth.jsx
+++ b/src/components/RequireAuth.jsx
@@ -1,19 +1,21 @@
import { Result } from 'antd'
+import { usingStorage } from '@/hooks/usingStorage'
import useAuthStore from '@/stores/Auth'
-export default function RequireAuth({ children, ...props }, ) {
+export default function RequireAuth({ children, ...props }) {
const isPermitted = useAuthStore((state) => state.isPermitted)
+ const { userId } = usingStorage()
if (isPermitted(props.subject)) {
- // if (props.subject === '/account/management') {
+ // if (props.subject === '/account/management1') {
return children
} else if (props.result) {
return (
)
}
diff --git a/src/components/SearchForm.jsx b/src/components/SearchForm.jsx
index 0e33c82..46021f9 100644
--- a/src/components/SearchForm.jsx
+++ b/src/components/SearchForm.jsx
@@ -176,6 +176,22 @@ function getFields(props) {
,
fieldProps?.dates?.col || midCol
),
+ item(
+ 'username',
+ 3,
+
+
+ ,
+ fieldProps?.username?.col || 4
+ ),
+ item(
+ 'realname',
+ 4,
+
+
+ ,
+ fieldProps?.realname?.col || 4
+ ),
];
baseChildren = baseChildren
diff --git a/src/config.js b/src/config.js
index 24fbdff..fc69f82 100644
--- a/src/config.js
+++ b/src/config.js
@@ -12,8 +12,22 @@ const __BUILD_VERSION__ = `__BUILD_VERSION__`.replace(/"/g, '')
export const BUILD_VERSION = import.meta.env.PROD ? __BUILD_VERSION__ : import.meta.env.MODE;
// 权限常量定义
+// 账号、权限管理
+// category: system
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'
+
+// 海外供应商
+// category: oversea
+export const PERM_OVERSEA = '/oversea/all'
+
+// 国内供应商
+// category: domestic
+export const PERM_DOMESTIC = '/domestic/all'
+
+// 机票供应商
+// category: air-ticket
+export const PERM_AIR_TICKET = '/air-ticket/all'
diff --git a/src/main.jsx b/src/main.jsx
index 8c1c1bd..9114460 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -5,8 +5,6 @@ import {
createBrowserRouter,
RouterProvider,
} from "react-router-dom";
-import RootStore from "@/stores/Root";
-import { StoreContext } from '@/stores/StoreContext';
import "@/assets/global.css";
import App from "@/views/App";
import Standlone from "@/views/Standlone";
@@ -20,6 +18,7 @@ import ReservationDetail from "@/views/reservation/Detail";
import ChangePassword from "@/views/account/ChangePassword";
import AccountProfile from "@/views/account/Profile";
import AccountManagement from "@/views/account/Management";
+import RoleList from "@/views/account/RoleList";
import FeedbackIndex from "@/views/feedback/Index";
import FeedbackDetail from "@/views/feedback/Detail";
import FeedbackCustomerDetail from "@/views/feedback/CustomerDetail";
@@ -32,8 +31,9 @@ import InvoicePaid from "@/views/invoice/Paid";
import InvoicePaidDetail from "@/views/invoice/PaidDetail";
import Airticket from "@/views/airticket/Index";
import AirticketPlan from "@/views/airticket/Plan";
+import { ThemeContext } from '@/stores/ThemeContext'
-import { PERM_ACCOUNT_MANAGEMENT } from '@/config'
+import { PERM_ACCOUNT_MANAGEMENT, PERM_ROLE_NEW, PERM_OVERSEA, PERM_AIR_TICKET } from '@/config'
import './i18n';
@@ -53,22 +53,23 @@ const router = createBrowserRouter([
errorElement: ,
children: [
{ index: true, element: },
- { path: "reservation/newest", element: },
- { path: "reservation/:reservationId", element: },
{ path: "account/change-password", element: },
{ path: "account/profile", element: },
{ path: "account/management", element: },
- { path: "feedback", element: },
- { 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: "invoice",element:},
- { path: "invoice/detail/:GMDSN/:GSN",element:},
- { path: "invoice/paid",element:},
- { path: "invoice/paid/detail/:flid",element:},
- { path: "airticket",element:},
+ { path: "account/role-list", element: },
+ { path: "reservation/newest", element: },
+ { path: "reservation/:reservationId", element: },
+ { path: "feedback", element: },
+ { 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: "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:},
]
},
@@ -81,15 +82,14 @@ const router = createBrowserRouter([
}
]);
-const rootStore = new RootStore();
ReactDOM.createRoot(document.getElementById("root")).render(
//
-
- Loading...
}
- />
-
+
+ Loading...
}
+ />
+
//
);
diff --git a/src/stores/Account.js b/src/stores/Account.js
new file mode 100644
index 0000000..a2391be
--- /dev/null
+++ b/src/stores/Account.js
@@ -0,0 +1,124 @@
+import { create } from 'zustand'
+import { fetchJSON, postForm } from '@/utils/request'
+import { HT_HOST } from "@/config"
+import { usingStorage } from '@/hooks/usingStorage'
+
+export const postAccountStatus = async (formData) => {
+
+ const { errcode, result } = await postForm(
+ `${HT_HOST}/service-CooperateSOA/set_account_status`, formData)
+ return errcode !== 0 ? {} : result
+}
+
+export const fetchAccountList = async (params) => {
+
+ const { errcode, result } = await fetchJSON(
+ `${HT_HOST}/service-CooperateSOA/search_account`, params)
+ return errcode !== 0 ? {} : result
+}
+
+export const postAccountForm = async (formData) => {
+
+ const { errcode, result } = await postForm(
+ `${HT_HOST}/service-CooperateSOA/new_or_update_account`, formData)
+ return errcode !== 0 ? {} : result
+}
+
+export const postRoleForm = async (formData) => {
+
+ const { errcode, result } = await postForm(
+ `${HT_HOST}/service-CooperateSOA/new_or_update_role`, formData)
+ return errcode !== 0 ? {} : result
+}
+
+export const fetchRoleList = async () => {
+
+ const { errcode, result } = await fetchJSON(
+ `${HT_HOST}/service-CooperateSOA/get_role_list`)
+ return errcode !== 0 ? {} : result
+}
+
+const useAccountStore = create((set, get) => ({
+
+ accountList: [],
+
+ selectedAccount: null,
+
+ selectAccount: (account) => {
+ set(() => ({
+ selectedAccount: account
+ }))
+ },
+
+ disableAccount: async (accountId) => {
+
+ const formData = new FormData()
+ formData.append('wu_id', accountId)
+ formData.append('account_status', 'enable')
+
+ const result = await postAccountStatus(formData)
+
+ console.info(result)
+ },
+
+ saveOrUpdateRole: async (formValues) => {
+ const formData = new FormData()
+ formData.append('role_id', formValues.role_id)
+ formData.append('role_name', formValues.role_name)
+ formData.append('res_ids', '2,3')
+
+ return postRoleForm(formData)
+ },
+
+ saveOrUpdateAccount: async (formValues) => {
+ const { selectedAccount } = get()
+ const { userId } = usingStorage()
+ const formData = new FormData()
+ formData.append('wu_id', selectedAccount.userId)
+ formData.append('lmi_sn', selectedAccount.lmi_sn)
+ formData.append('lmi2_sn', selectedAccount.lmi2_sn)
+ formData.append('user_name', formValues.username)
+ formData.append('real_name', formValues.realname)
+ formData.append('email', formValues.email)
+
+ formData.append('travel_agency_id', formValues.travelAgencyId)
+ formData.append('roles', formValues.roleId)
+
+ formData.append('opi_sn', userId)
+
+ return postAccountForm(formData)
+ },
+
+ searchAccountByCriteria: async (formValues) => {
+
+ const searchParams = {
+ username: formValues.username,
+ realname: formValues.realname,
+ lgc: 2
+ }
+
+ const resultArray = await fetchAccountList(searchParams)
+
+ const mapAccoutList = resultArray.map((r) => {
+ return {
+ userId: r.wu_id,
+ lmi_sn: r.lmi_sn,
+ lmi2_sn: r.lmi2_sn,
+ username: r.user_name,
+ realname: r.real_name,
+ email: r.email,
+ lastLogin: r.wu_lastlogindate,
+ travelAgency: r.travel_agency_name,
+ travelAgencyId: r.travel_agency_id,
+ roleId: r.roles,
+ role: r.roles_name,
+ }
+ })
+
+ set(() => ({
+ accountList: mapAccoutList
+ }))
+ },
+}))
+
+export default useAccountStore
\ No newline at end of file
diff --git a/src/stores/Auth.js b/src/stores/Auth.js
index f7f31f3..fe0900e 100644
--- a/src/stores/Auth.js
+++ b/src/stores/Auth.js
@@ -55,13 +55,13 @@ const useAuthStore = create((set, get) => ({
// 以下是权限列表从数据库读取后使用的方法
// return this.permissionList.some((value, key, arry) => {
// if (value.indexOf(WILDCARD_TOKEN) > -1) {
- // return true;
+ // return true
// }
// if (value === perm) {
- // return true;
+ // return true
// }
- // return false;
- // });
+ // return false
+ // })
},
@@ -154,19 +154,4 @@ const useAuthStore = create((set, get) => ({
},
}))
-export default useAuthStore
-
-export class Auth {
- // TODO: 等待所有获取用户信息修改完后删除
- login = {
- token: '',
- userId: 0, // LMI_SN
- username: '0',
- travelAgencyId: 0, // VEI_SN
- travelAgencyName: '',
- telephone: '',
- emailAddress: '',
- cityId: 0,
- timeout: false
- }
-}
+export default useAuthStore
\ No newline at end of file
diff --git a/src/stores/Root.js b/src/stores/Root.js
deleted file mode 100644
index a24bd54..0000000
--- a/src/stores/Root.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { makeAutoObservable } from "mobx";
-import { Auth } from "./Auth";
-
-class Root {
- constructor() {
- this.authStore = new Auth(this);
- makeAutoObservable(this);
- }
-
- clearSession() {
- if (window.sessionStorage) {
- const sessionStorage = window.sessionStorage;
- sessionStorage.clear();
- } else {
- console.error('browser not support sessionStorage!');
- }
- }
-
- getSession(key) {
- if (window.sessionStorage) {
- const sessionStorage = window.sessionStorage;
- return sessionStorage.getItem(key);
- } else {
- console.error('browser not support sessionStorage!');
- return null;
- }
- }
-
- putSession(key, value) {
- if (window.sessionStorage) {
- const sessionStorage = window.sessionStorage;
- return sessionStorage.setItem(key, value);
- } else {
- console.error('browser not support sessionStorage!');
- }
- }
-}
-
-export default Root;
diff --git a/src/stores/StoreContext.js b/src/stores/StoreContext.js
deleted file mode 100644
index aca4a62..0000000
--- a/src/stores/StoreContext.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import { createContext, useContext } from "react";
-
-export const StoreContext = createContext();
-
-export function useStore() {
- return useContext(StoreContext);
-}
\ No newline at end of file
diff --git a/src/stores/ThemeContext.js b/src/stores/ThemeContext.js
new file mode 100644
index 0000000..f4f7aa7
--- /dev/null
+++ b/src/stores/ThemeContext.js
@@ -0,0 +1,7 @@
+import { createContext, useContext } from 'react'
+
+export const ThemeContext = createContext({})
+
+export function useThemeContext() {
+ return useContext(ThemeContext)
+}
\ No newline at end of file
diff --git a/src/utils/request.js b/src/utils/request.js
index 68d80a6..ac97803 100644
--- a/src/utils/request.js
+++ b/src/utils/request.js
@@ -106,6 +106,7 @@ export function postForm(url, data) {
}
}).then(checkStatus)
.then(response => response.json())
+ .then(checkBizCode)
.catch(error => {
throw error
})
diff --git a/src/views/App.jsx b/src/views/App.jsx
index dd2dec6..779993c 100644
--- a/src/views/App.jsx
+++ b/src/views/App.jsx
@@ -149,8 +149,9 @@ function App() {
{ label: {t('ChangePassword')}, key: '0' },
{ label: {t('Profile')}, key: '1' },
{ label: {t('account:management.tile')}, key: '3' },
+ { label: {t('account:management.roleList')}, key: '4' },
{ type: 'divider' },
- { label: {t('Logout')}, key: '4' },
+ { label: {t('Logout')}, key: '99' },
],
{ type: 'divider' },
{ label: <>v{BUILD_VERSION}>, key: 'BUILD_VERSION' },
diff --git a/src/views/account/Management.jsx b/src/views/account/Management.jsx
index d98dbd8..f0e7b9f 100644
--- a/src/views/account/Management.jsx
+++ b/src/views/account/Management.jsx
@@ -4,7 +4,8 @@ import { ExclamationCircleFilled } from '@ant-design/icons'
import { useTranslation } from 'react-i18next'
import useFormStore from '@/stores/Form'
import useAuthStore from '@/stores/Auth'
-import useReservationStore from '@/stores/Reservation'
+import useAccountStore from '@/stores/Account'
+import { fetchRoleList } from '@/stores/Account'
import SearchForm from '@/components/SearchForm'
import RequireAuth from '@/components/RequireAuth'
import { PERM_ROLE_NEW } from '@/config'
@@ -12,6 +13,18 @@ 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',
@@ -29,6 +42,11 @@ const permissionData = [
value: '0-1',
key: '0-1',
children: [
+ {
+ title: '搜索供应商产品',
+ value: 'B-1-0',
+ key: 'B-1-0',
+ },
{
title: '录入产品价格',
value: '0-1-0',
@@ -52,19 +70,29 @@ const permissionData = [
key: '2-1',
children: [
{
- title: '重置账号密码',
- value: '2-1-0',
- key: '2-1-0',
+ title: '搜索账号',
+ value: '2-1-01',
+ key: '2-1-01',
+ },
+ {
+ title: '新增账号',
+ value: '2-1-11',
+ key: '2-1-11',
},
{
title: '禁用账号',
- value: '2-1-1',
- key: '2-1-1',
+ value: '2-1-21',
+ key: '2-1-21',
+ },
+ {
+ title: '重置账号密码',
+ value: '2-1-31',
+ key: '2-1-31',
},
{
- title: '分配账号角色',
- value: '2-1-2',
- key: '2-1-2',
+ title: '新增角色',
+ value: '2-1-41',
+ key: '2-1-41',
},
],
},
@@ -83,6 +111,10 @@ function Management() {
title: t('account:realname'),
dataIndex: 'realname',
},
+ {
+ title: t('account:travelAgency'),
+ dataIndex: 'travelAgency',
+ },
{
title: t('account:email'),
dataIndex: 'email',
@@ -103,9 +135,9 @@ function Management() {
},
]
- function accountRender(text) {
+ function accountRender(text, account) {
return (
-
+
)
}
@@ -115,11 +147,11 @@ function Management() {
)
}
- function actionRender() {
+ function actionRender(text, account) {
return (
-
-
+
+
)
}
@@ -133,112 +165,71 @@ function Management() {
const [isAccountModalOpen, setAccountModalOpen] = useState(false)
const [isRoleModalOpen, setRoleModalOpen] = useState(false)
const [dataLoading, setDataLoading] = useState(false)
- const [accountList, setaccountList] = useState([
- {
- key: 1,
- username: 'bjyiran',
- realname: '怡小芳',
- email: 'xiaofang@yiran.com',
- role: '国内供应商',
- lastLogin: '2024-06-12 13:53'
- },
- {
- key: 2,
- username: 'int-robin',
- realname: 'Robin',
- email: 'robin@int.com',
- role: '海外供应商',
- lastLogin: '2024-06-12 13:53'
- },
- {
- key: 3,
- username: 'betty-wu',
- realname: '吴雪',
- email: 'betty@hainatravel.com',
- role: '客服组',
- lastLogin: '2024-06-12 13:53'
- },
- {
- key: 4,
- username: 'lancy',
- realname: '吴金倩',
- email: 'lancy@hainatravel.com',
- role: '产品组',
- lastLogin: '2024-06-12 13:53'
- },
- {
- key: 5,
- username: 'LYJ',
- realname: '廖一军',
- email: 'lyj@hainatravel.com',
- role: 'Web 开发组,海外测试供应商',
- lastLogin: '2024-06-12 13:53'
- }
- ])
-
- const formValuesToSub = useFormStore((state) => state.formValuesToSub)
-
-
- const isPermitted = useAuthStore((state) => state.isPermitted)
+ const [roleAllList, setRoleAllList] = useState([])
- const [editAccountForm, editRoleForm] = Form.useForm()
- const [fetchReservationList] =
- useReservationStore((state) =>
- [state.fetchAllGuideList, state.fetchReservationList, state.reservationList, state.reservationPage, state.cityList, state.selectReservation, state.getCityListByReservationId])
+ const [accountForm] = Form.useForm()
+ const [searchAccountByCriteria, accountList, disableAccount, selectedAccount, saveOrUpdateAccount, selectAccount] =
+ useAccountStore((state) =>
+ [state.searchAccountByCriteria, state.accountList, state.disableAccount, state.selectedAccount, state.saveOrUpdateAccount, state.selectAccount])
const { notification, modal } = App.useApp()
- const handleAccountOk = () => {
+ const onAccountSeleted = async (account) => {
+ accountForm.setFieldsValue(account)
+ selectAccount(account)
+ console.info(account)
+ const roleList = await fetchRoleList()
+ setRoleAllList(roleList.map(r => {
+ return {
+ value: r.role_id,
+ label: r.role_name,
+ disabled: r.role_id === 1
+ }
+ }))
+ setAccountModalOpen(true)
}
- const handleAccountCancel = () => {
- setAccountModalOpen(false)
- }
-
- const handleRoleOk = () => {
- }
-
- const handleRoleCancel = () => {
- setRoleModalOpen(false)
- }
-
- const onFinish = (values) => {
+ const onAccountFinish = (values) => {
console.log(values)
+ saveOrUpdateAccount(values)
+ .catch(ex => {
+ console.info(ex.message)
+ notification.error({
+ message: 'Notification',
+ description: ex.message,
+ placement: 'top',
+ duration: 4,
+ })
+ })
}
- const onFinishFailed = (error) => {
+ const onAccountFailed = (error) => {
console.log('Failed:', error)
// form.resetFields()
}
- // 默认重新搜索第一页,所有状态的计划
- const onSearchClick = (current = 1, status = null) => {
- }
-
- const showDisableConfirm = () => {
+ const showDisableConfirm = (account) => {
modal.confirm({
title: 'Do you want to disable this account?',
icon: ,
- content: 'Username: Ivy, Realname: 怡小芳',
+ content: `Username: ${account.username}, Realname: ${account.realname}`,
onOk() {
- console.log('OK')
+ disableAccount(account.userId)
},
onCancel() {
- console.log('Cancel')
},
})
}
- const showResetPasswordConfirm = () => {
+ const showResetPasswordConfirm = (account) => {
modal.confirm({
title: 'Do you want to reset password?',
icon: ,
- content: 'Username: Ivy, Realname: 怡小芳',
+ content: `Username: ${account.username}, Realname: ${account.realname}`,
onOk() {
- console.log('OK')
+ console.log('ResetPassword')
},
onCancel() {
- console.log('Cancel')
},
})
}
@@ -247,137 +238,106 @@ function Management() {
<>
- {t('account:management.newAccount')}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Role Edit */}
-
+ )}
>
- {t('account:management.newRole')}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{t('account:management.tile')}
{
+ onSubmit={(err, formValues, filedsVal) => {
+ console.info(formValues)
setDataLoading(true)
- fetchReservationList(formVal)
+ searchAccountByCriteria(formValues)
.catch(ex => {
notification.error({
message: 'Notification',
@@ -395,9 +355,6 @@ function Management() {
-
-
-
@@ -406,6 +363,7 @@ function Management() {
onRoleSeleted(role)}>{text}
+ )
+ }
+
+ function actionRender(text, account) {
+ return (
+
+
+
+
+ )
+ }
+
+ const onPermissionChange = (newValue) => {
+ console.log('onChange ', newValue)
+ setPermissionValue(newValue)
+ }
+
+ useEffect (() => {
+ fetchRoleList()
+ .then(r => {
+ setRoleAllList(r)
+ })
+ }, [])
+
+ const [permissionValue, setPermissionValue] = useState(['0-0-0'])
+ const [isRoleModalOpen, setRoleModalOpen] = useState(false)
+ const [dataLoading, setDataLoading] = useState(false)
+ const [roleAllList, setRoleAllList] = useState([])
+
+ const [roleForm] = Form.useForm()
+ const [saveOrUpdateRole] =
+ useAccountStore((state) =>
+ [state.saveOrUpdateRole])
+
+ const { notification, modal } = App.useApp()
+
+ const onRoleSeleted = async (role) => {
+ roleForm.setFieldsValue(role)
+ // selectAccount(account)
+ // console.info(account)
+ setRoleModalOpen(true)
+ }
+
+ const onRoleFinish = (values) => {
+ console.log(values)
+ saveOrUpdateRole(values)
+ .catch(ex => {
+ console.info(ex.message)
+ notification.error({
+ message: 'Notification',
+ description: ex.message,
+ placement: 'top',
+ duration: 4,
+ })
+ })
+ }
+
+ const onRoleFailed = (error) => {
+ console.log('Failed:', error)
+ // form.resetFields()
+ }
+
+ return (
+ <>
+ setRoleModalOpen(false)} onCancel={() => setRoleModalOpen(false)}
+ destroyOnClose={true}
+ clearOnDestroy={true}
+ modalRender={(dom) => (
+
+ )}
+ >
+
+
+
+
+
+
+
+
+
+
+
+ {t('account:management.roleList')}
+
+
+
+
+
+
+
+
+
+
+
+ { return t('Total') + `:${total}` }
+ }}
+ onChange={(pagination) => { onSearchClick(pagination.current) }}
+ columns={roleListColumns} dataSource={roleAllList}
+ />
+
+
+
+ >
+ )
+}
+
+export default RoleList