完成顶栏,导航菜单分权展示
parent
62155de02d
commit
4cb396ee81
|
@ -2,6 +2,7 @@
|
||||||
export interface Token {
|
export interface Token {
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
|
clientSecret: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Staff {
|
export interface Staff {
|
||||||
|
|
|
@ -8,12 +8,13 @@ const tokenSlice = createSlice({
|
||||||
initialState: {
|
initialState: {
|
||||||
accessToken: '',
|
accessToken: '',
|
||||||
refreshToken: '',
|
refreshToken: '',
|
||||||
|
clientSecret: ''
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
setToken: (state, action: PayloadAction<Token>) => {
|
setToken: (state, action: PayloadAction<Token>) => {
|
||||||
state.accessToken = action.payload.accessToken
|
state.accessToken = action.payload.accessToken
|
||||||
state.refreshToken = action.payload.refreshToken
|
state.refreshToken = action.payload.refreshToken
|
||||||
console.log('action: '+action)
|
state.clientSecret = action.payload.clientSecret
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,15 +1,94 @@
|
||||||
import React, {FC, useEffect} from 'react';
|
import React, {useState, useEffect} from 'react';
|
||||||
import {UploadOutlined, UserOutlined, VideoCameraOutlined} from '@ant-design/icons';
|
import {UploadOutlined, UserOutlined, VideoCameraOutlined} from '@ant-design/icons';
|
||||||
import {Layout, Menu, theme, Typography } from 'antd';
|
import {Layout, Menu, theme, Typography, Button, Dropdown, MenuProps} from 'antd';
|
||||||
import {useAppSelector} from "../models/hooks";
|
import {useAppDispatch, useAppSelector} from "../models/hooks";
|
||||||
import {getToken, store} from "../models/store";
|
import {getToken, setToken, store} from "../models/store";
|
||||||
import {Link, Outlet, useNavigate} from "react-router-dom";
|
import {Link, Outlet, useNavigate} from "react-router-dom";
|
||||||
import Icon from '@ant-design/icons';
|
import Icon from '@ant-design/icons';
|
||||||
import {Logo} from "../assets/icons";
|
import {Logo} from "../assets/icons";
|
||||||
|
import axiosInstance from "../utils/axiosInstance";
|
||||||
|
import {Department, Staff} from "../models/Staff";
|
||||||
|
|
||||||
const {Title} = Typography;
|
const {Title} = Typography;
|
||||||
const {Header, Content, Footer, Sider} = Layout;
|
const {Header, Content, Footer, Sider} = Layout;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function HeaderBar(props: any) {
|
||||||
|
const {
|
||||||
|
token: {colorBgContainer, colorPrimary},
|
||||||
|
} = theme.useToken();
|
||||||
|
|
||||||
|
const dispatch = useAppDispatch()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
|
||||||
|
const onClick: MenuProps['onClick'] = ({key}) => {
|
||||||
|
switch (key) {
|
||||||
|
case 'password':
|
||||||
|
break
|
||||||
|
case 'logout':
|
||||||
|
dispatch(setToken({
|
||||||
|
accessToken: '',
|
||||||
|
refreshToken: '',
|
||||||
|
clientSecret: ''
|
||||||
|
}))
|
||||||
|
navigate("/login")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const items: MenuProps['items'] = [
|
||||||
|
{
|
||||||
|
key: 'password',
|
||||||
|
label: (
|
||||||
|
<span>修改密码</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'logout',
|
||||||
|
label: (
|
||||||
|
<span>退出登录</span>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const departmentToString = (staff:Staff) => {
|
||||||
|
let result = staff.managingDepartment===null?'':staff.managingDepartment.departmentName+'主管'
|
||||||
|
for(const department of staff.staffDepartments)
|
||||||
|
{
|
||||||
|
result+=' '+department.departmentName
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Header style={{
|
||||||
|
height: '48px',
|
||||||
|
padding: 0,
|
||||||
|
background: colorBgContainer,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row-reverse',
|
||||||
|
alignItems: 'center'
|
||||||
|
}}>
|
||||||
|
<Dropdown menu={{items, onClick}} placement="bottomRight" arrow>
|
||||||
|
<Button type="text" style={{
|
||||||
|
marginRight: '12px', height: '100%',
|
||||||
|
display: 'flex', justifyContent: 'center', alignItems: 'center'
|
||||||
|
}}>
|
||||||
|
<span style={{marginRight: '12px'}}>{departmentToString(props.staff)}</span>
|
||||||
|
<span style={{fontWeight: "bold", marginRight: '12px'}}>{props.staff.staffName}</span>
|
||||||
|
<div style={{
|
||||||
|
width: '24px', height: '24px', backgroundColor: colorPrimary, borderRadius: '12px',
|
||||||
|
display: 'flex', justifyContent: 'center', alignItems: 'center'
|
||||||
|
}}>
|
||||||
|
<span style={{color: 'white'}}>{props.staff.staffName[0]}</span>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</Dropdown>
|
||||||
|
</Header>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function HomeView() {
|
function HomeView() {
|
||||||
const token = useAppSelector(getToken);
|
const token = useAppSelector(getToken);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
@ -41,11 +120,98 @@ function HomeView() {
|
||||||
token: {colorBgContainer, colorPrimary},
|
token: {colorBgContainer, colorPrimary},
|
||||||
} = theme.useToken();
|
} = theme.useToken();
|
||||||
|
|
||||||
|
|
||||||
|
const [staff, setStaff] = useState({
|
||||||
|
staffName: "王司徒",
|
||||||
|
managingDepartment: {
|
||||||
|
departmentId: 3,
|
||||||
|
departmentName: "投影立体角部"
|
||||||
|
},
|
||||||
|
staffDepartments: []
|
||||||
|
})
|
||||||
|
|
||||||
|
const [menuItems, setMenuItems] = useState(
|
||||||
|
[{
|
||||||
|
key: "/invoice/mine",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/invoice/mine">我的发票</Link>
|
||||||
|
}, {
|
||||||
|
key: "/reimbursement/mine",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/reimbursement/mine">我的报销</Link>,
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
|
||||||
|
const getStaffInfo = () => {
|
||||||
|
axiosInstance({
|
||||||
|
url: 'staff',
|
||||||
|
method: 'get'
|
||||||
|
}).then(response => {
|
||||||
|
console.log(response.data)
|
||||||
|
setStaff( response.data)
|
||||||
|
}).catch(function (error) {
|
||||||
|
console.log(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (token.accessToken === '') {
|
if (token.accessToken === '') {
|
||||||
console.log("redirect")
|
console.log("redirect")
|
||||||
navigate("/login")
|
navigate("/login")
|
||||||
}
|
}
|
||||||
|
getStaffInfo()
|
||||||
|
if(staff.managingDepartment)
|
||||||
|
{
|
||||||
|
if(staff.managingDepartment.departmentName==='财务部')
|
||||||
|
{
|
||||||
|
setMenuItems([{
|
||||||
|
key: "/invoice/mine",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/invoice/mine">我的发票</Link>
|
||||||
|
}, {
|
||||||
|
key: "/reimbursement/mine",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/reimbursement/mine">我的报销</Link>,
|
||||||
|
}, {
|
||||||
|
key: "/invoice/management",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/reimbursement/mine">发票管理</Link>,
|
||||||
|
}, {
|
||||||
|
key: "/reimbursement/management",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/reimbursement/mine">报销审批</Link>,
|
||||||
|
}, {
|
||||||
|
key: "/stat",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/reimbursement/mine">财务统计</Link>,
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setMenuItems([{
|
||||||
|
key: "/invoice/mine",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/invoice/mine">我的发票</Link>
|
||||||
|
}, {
|
||||||
|
key: "/reimbursement/mine",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/reimbursement/mine">我的报销</Link>,
|
||||||
|
}, {
|
||||||
|
key: "/reimbursement/management",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/reimbursement/mine">报销审批</Link>,
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setMenuItems([{
|
||||||
|
key: "/invoice/mine",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/invoice/mine">我的发票</Link>
|
||||||
|
}, {
|
||||||
|
key: "/reimbursement/mine",
|
||||||
|
//icon: React.createElement(UserOutlined),
|
||||||
|
label: <Link to="/reimbursement/mine">我的报销</Link>,
|
||||||
|
}])
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<Layout style={{height: '100%'}}>
|
<Layout style={{height: '100%'}}>
|
||||||
|
@ -61,18 +227,29 @@ function HomeView() {
|
||||||
console.log(collapsed, type);
|
console.log(collapsed, type);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{height: '32px',margin: '17px 0 17px 0', display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
|
<div style={{
|
||||||
|
height: '32px',
|
||||||
|
margin: '17px 0 17px 0',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
}}>
|
||||||
<Icon component={Logo}/>
|
<Icon component={Logo}/>
|
||||||
<span style={{color: colorPrimary, fontSize: '16px', fontWeight: 'bold', marginLeft: '4px'}}>智能财务报销系统</span>
|
<span style={{
|
||||||
|
color: colorPrimary,
|
||||||
|
fontSize: '16px',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
marginLeft: '4px'
|
||||||
|
}}>智能财务报销系统</span>
|
||||||
</div>
|
</div>
|
||||||
<Menu
|
<Menu
|
||||||
mode="inline"
|
mode="inline"
|
||||||
defaultSelectedKeys={['/invoice/mine']}
|
defaultSelectedKeys={['/invoice/mine']}
|
||||||
items={items}
|
items={menuItems}
|
||||||
/>
|
/>
|
||||||
</Sider>
|
</Sider>
|
||||||
<Layout>
|
<Layout>
|
||||||
<Header style={{height: '48px', padding: 0, background: colorBgContainer }}/>
|
<HeaderBar staff={staff}/>
|
||||||
<Content style={{margin: '24px 16px 0'}}>
|
<Content style={{margin: '24px 16px 0'}}>
|
||||||
<Outlet/>
|
<Outlet/>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import {Card, Dropdown, List,Menu,Input,Button,Radio,Divider} from "antd";
|
import {Card, Dropdown, List,Menu,Input,Button,Radio,Divider} from "antd";
|
||||||
import type { MenuProps } from 'antd';
|
import type { MenuProps } from 'antd';
|
||||||
import { Icon } from '@ant-design/compatible'
|
|
||||||
import { DownOutlined,UploadOutlined } from '@ant-design/icons';
|
import { DownOutlined,UploadOutlined } from '@ant-design/icons';
|
||||||
import React, {ReactElement, JSXElementConstructor, ReactFragment, ReactPortal,useState } from "react";
|
import React, {ReactElement, JSXElementConstructor, ReactFragment, ReactPortal,useState } from "react";
|
||||||
import {Invoice,InvoiceSearchOption} from "../../../models/Staff"
|
import {Invoice,InvoiceSearchOption} from "../../../models/Staff"
|
||||||
|
@ -33,7 +32,20 @@ class InvoiceSearch extends React.Component<any, any> {
|
||||||
//const dispatch = useAppDispatch();
|
//const dispatch = useAppDispatch();
|
||||||
//const navigate = useNavigate();
|
//const navigate = useNavigate();
|
||||||
console.log(baseUrl + 'common/invoice/list?'+this.state.invoiceSearchOption.toString())
|
console.log(baseUrl + 'common/invoice/list?'+this.state.invoiceSearchOption.toString())
|
||||||
axiosInstance.get(baseUrl + 'common/invoice/list?'+this.state.invoiceSearchOption.toString()).then(function (response) {
|
let params = this.state.invoiceSearchOption
|
||||||
|
if(params.invoiceNo==="") params.invoiceNo=null
|
||||||
|
if(params.invoiceCode==="") params.invoiceCode=null
|
||||||
|
axiosInstance({
|
||||||
|
url: 'common/invoice/list',
|
||||||
|
method: 'get',
|
||||||
|
params: params
|
||||||
|
}).then(response => {
|
||||||
|
console.log(response.data)
|
||||||
|
handleSearchData(response.data.records)
|
||||||
|
}).catch(function (error) {
|
||||||
|
console.log(error)
|
||||||
|
})
|
||||||
|
/* axiosInstance.get(baseUrl + 'common/invoice/list?'+this.state.invoiceSearchOption.toString()).then(function (response) {
|
||||||
console.log(response.data)
|
console.log(response.data)
|
||||||
//console.log(this.state)
|
//console.log(this.state)
|
||||||
handleSearchData(response.data.records)
|
handleSearchData(response.data.records)
|
||||||
|
@ -43,7 +55,7 @@ class InvoiceSearch extends React.Component<any, any> {
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
//showAlert.value = true
|
//showAlert.value = true
|
||||||
});
|
});*/
|
||||||
//console.log(value)
|
//console.log(value)
|
||||||
//this.props.handleSearchData(value)
|
//this.props.handleSearchData(value)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,11 @@ function LoginView() {
|
||||||
console.log(response.data)
|
console.log(response.data)
|
||||||
dispatch(setToken({
|
dispatch(setToken({
|
||||||
accessToken: response.data.accessToken,
|
accessToken: response.data.accessToken,
|
||||||
refreshToken: response.data.refreshToken
|
refreshToken: response.data.refreshToken,
|
||||||
|
clientSecret: response.data.clientSecret
|
||||||
}))
|
}))
|
||||||
//models.commit('setStaff', response.data.data)
|
//models.commit('setStaff', response.data.data)
|
||||||
navigate('/')
|
navigate('/invoice/mine')
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
//showAlert.value = true
|
//showAlert.value = true
|
||||||
|
|
Loading…
Reference in New Issue