Commit f50baf25 authored by 夏敏伟's avatar 夏敏伟

首次提交

parents
Pipeline #471 failed with stages
in 1 second
{
"compact": false,
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["@babel/plugin-transform-runtime"]
}
\ No newline at end of file
node_modules
dist
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<style>
html body,
#app {
min-width: 1000px;
height: 100%;
margin: 0px !important;
}
</style>
</head>
<body>
<div id="app">
</div>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
{
"name": "zjzz",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --color --progress",
"dev": "webpack-dev-server"
},
"author": "",
"license": "ISC",
"dependencies": {
"@antv/data-set": "^0.11.8",
"@babel/runtime": "^7.17.2",
"antd": "^4.19.1",
"axios": "^0.27.2",
"better-xlsx": "^0.7.6",
"bizcharts": "^4.1.15",
"esri-loader": "^3.6.0",
"file-saver": "^2.0.5",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^5.0.6",
"react-router-dom": "^6.2.2",
"react-websocket": "^2.1.0",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0"
},
"devDependencies": {
"@babel/core": "^7.17.5",
"@babel/plugin-transform-runtime": "^7.17.0",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"babel-loader": "^8.2.3",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^9.1.0",
"css-loader": "^5.2.6",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.2",
"style-loader": "^2.0.0",
"ts-loader": "^9.2.8",
"typescript": "^4.6.2",
"webpack": "^5.40.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4"
}
}
This diff is collapsed.
import React, { Component } from 'react';
import { BrowserRouter, Link, Route, Routes, HashRouter } from 'react-router-dom'
import { Router } from "./router/index"
export default class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<HashRouter>
<Router/>
</HashRouter>
);
}
}
\ No newline at end of file
import {GET, POST} from "../axios"
/**
* 登录请求服务
* @param username
* @param password
* @returns
*/
export const API_Login = (username:string, password:string) => {
return GET('api/api-auth/rest/user/login', {account: username, password: btoa(password)});
}
/**
* 查询菜单列表
* @param body
* @returns
*/
export const API_queryMenu = (body) => {
return POST('api/api-auth/rest/menu/queryList', body);
}
/**
* 查询用户列表
* @param body
* @returns
*/
export const API_queryUserList = (body) => {
return GET('api/api-auth/rest/user/queryList', body);
}
/**
* 新增用户
* @param body
* @returns
*/
export const API_addUser = (body) => {
return POST('api/api-auth/rest/user/add', body);
}
/**
* 编辑用户
* @param body
* @returns
*/
export const API_updateUser = (body) => {
return POST('api/api-auth/rest/user/updateInfo', body);
}
/**
* 修改密码
* @param body
* @returns
*/
export const API_updatePassword = (params) => {
return GET('api/api-auth/rest/user/updatePassword', null, { params });
}
/**
* 删除用户
* @param body
* @returns
*/
export const API_removeUser = (body) => {
return GET('api/api-auth/rest/user/remove', body);
}
/**
* 查询角色列表
* @param body
* @returns
*/
export const API_queryRoleList = (body) => {
return GET('api/api-auth/rest/role/queryList', body);
}
/**
* 新增角色
* @param body
* @returns
*/
export const API_addRole = (body) => {
return POST('api/api-auth/rest/role/add', body);
}
/**
* 编辑角色
* @param body
* @returns
*/
export const API_updateRole = (body) => {
return POST('api/api-auth/rest/role/updateInfo', body);
}
/**
* 授予角色权限
* @param body
* @returns
*/
export const API_grantMenu = (param,body) => {
return POST(`api/api-auth/rest/role/grantMenu/${param}`, body);
}
/**
* 删除角色
* @param body
* @returns
*/
export const API_removeRole = (body) => {
return POST(`api/api-auth/rest/role/bulkRemove`, body);
}
const devBaseUrl = ''
const proBaseUrl = 'http://192.168.168.211:9001'
export const BASE_URL = process.env.NODE_ENV === 'development' ? devBaseUrl : proBaseUrl
export const TIMEOUT = 5000
\ No newline at end of file
import axios from "axios";
import { BASE_URL, TIMEOUT } from "./config";
//添加配置
const INSTANCE = axios.create({
baseURL: BASE_URL,
timeout: TIMEOUT,
});
//添加拦截
INSTANCE.interceptors.request.use(
(config) => {
if (sessionStorage.getItem("token")) {
config.headers["TOKENFLAG"] = sessionStorage.getItem("token");
}
if (sessionStorage.getItem("username")) {
config.headers["USERFLAG"] = sessionStorage.getItem("username");
}
return config;
},
(error) => {
throw error.message;
}
);
//添加拦截
INSTANCE.interceptors.response.use(
(res) => {
if (res.data instanceof Blob) {
return res;
} else if (res.data.code == 9000) {
return res.data.data;
} else {
throw res.data.message;
}
},
(error) => {
throw error.message;
}
);
/* 统一封装get请求 */
export const GET = (url, params, config = {}) => {
return new Promise((resolve, reject) => {
INSTANCE({
method: "get",
url,
params,
...config,
})
.then((response) => {
resolve(response);
})
.catch((error) => {
reject(error);
});
});
};
/* 统一封装post请求 */
export const POST = (url, data, config = {}) => {
return new Promise((resolve, reject) => {
INSTANCE({
method: "post",
url,
data,
...config,
})
.then((response) => {
resolve(response);
})
.catch((error) => {
reject(error);
});
});
};
//下载
export const DOWNLOAD = (url, params, filename, config = {}) => {
return new Promise((resolve: any, reject) => {
INSTANCE({
method: "post",
url,
params,
responseType: "blob",
...config,
})
.then((response) => {
if (!filename) {
let content_disposition = response.headers["content-disposition"];
if (content_disposition && content_disposition.match("filename=")) {
filename = decodeURIComponent(
content_disposition.split("filename=")[1]
);
} else {
filename = new Date().getTime();
}
}
let href = window.URL.createObjectURL(response.data); //创建下载链接
let downloadElement = document.createElement("a");
downloadElement.href = href;
downloadElement.download = filename;
downloadElement.click();
window.URL.revokeObjectURL(href);
resolve();
})
.catch((error) => {
reject(error);
});
});
};
interface result {
code: number;
msg: string;
data: object;
}
\ No newline at end of file
import React, { Component } from 'react';
import { render } from 'react-dom';
import App from "./App"
render(
<App />
,
document.getElementById('app')
);
\ No newline at end of file
import { Button, Result } from 'antd';
import React from 'react';
import './default.css';
const App = () => (
<Result
status="404"
title="404"
subTitle="对不起,您访问的页面不存在。"
// extra={<Button type="primary">返回</Button>}
/>
);
export default App;
\ No newline at end of file
.ant-result-title {
color: white;
}
.ant-result-subtitle {
color: white;
}
\ No newline at end of file
import React from "react";
import { Button, Input, Form } from 'antd';
export default (props) => {
const [form] = Form.useForm();
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 12,
},
};
const tailLayout = {
wrapperCol: {
offset: 10,
span: 14,
},
};
form.setFields([
{
name: ['username'],
value: props.username
},
{
name: ['oldPassword'],
value: props.password
}
])
const cancelClick = () => {
props.showModal();
}
const saveClick = () => {
const formData = form.getFieldsValue();
props.changePasswordModal(formData);
}
return (
<div>
<Form form={form}>
<Form.Item
name={['username']}
label="用户名"
rules={[
{
required: true,
},
]}
{...layout}
>
<Input disabled />
</Form.Item>
<Form.Item
name={['oldPassword']}
label="旧密码"
rules={[
{
required: true,
},
]}
{...layout}
>
<Input disabled />
</Form.Item>
<Form.Item
name={['newPassword']}
label="新密码"
rules={[
{
required: true,
},
]}
{...layout}
>
<Input />
</Form.Item>
<Form.Item {...tailLayout}>
<Button onClick={cancelClick} >取消</Button>
<Button type="primary" onClick={saveClick} style={{ marginLeft: 20 }}>确定</Button>
</Form.Item>
</Form>
</div>
)
}
\ No newline at end of file
import React, { useState } from 'react';
import { connect } from 'react-redux';
import * as actionTypes from '@/store/action-types';
import { Avatar, Menu, Dropdown, Space, Modal, message } from 'antd'
import { useNavigate } from 'react-router-dom'
import { SlackOutlined } from '@ant-design/icons';
import 'antd/dist/antd.css';
import ModalPassword from './ModalPassword';
import { API_updatePassword } from '@/api';
function Info(props) {
const navigate = useNavigate();
const logout = () => {
sessionStorage.setItem("login", false);
navigate("/login");
sessionStorage.clear();
}
const [isModalVisible, setIsModalVisible] = useState(false);
const menu1 = (
<Menu
items={[
{
key: '1',
label: (
<a target="_blank" rel="noopener noreferrer" onClick={() => showModal()}>
修改密码
</a>
),
},
{
key: '2',
label: (
<a target="_blank" rel="noopener noreferrer" onClick={() => logout()}>
注销
</a>
),
}
]}
/>
);
const menu2 = [];
const chooseMenu = (e) => {
}
const changePasswordModal = (data) => {
data.oldPassword = btoa(data.oldPassword);
data.newPassword = btoa(data.newPassword);
API_updatePassword(data).then(res => {
if (res == 1) {
setIsModalVisible(false);
message.success('密码修改成功,请重新登录!');
logout();
}
})
}
const showModal = () => {
setIsModalVisible(true);
};
const handleOk = () => {
setIsModalVisible(false);
};
const handleCancel = () => {
setIsModalVisible(false);
};
return (
<div style={{ height: "80px", lineHeight: "80px", display: "-webkit-box" }}>
<Menu items={menu2} mode="horizontal" onClick={chooseMenu} style={{ marginRight: "50px", lineHeight: "80px", color: "white", background: "none", borderBottom: "none" }}></Menu>
<Avatar style={{ marginRight: "20px", backgroundColor: '#ff3131ab' }} icon={<SlackOutlined />} />
<Modal width={500} title="修改密码" visible={isModalVisible} footer={false} destroyOnClose={true} onCancel={handleCancel}>
<ModalPassword
showModal={handleCancel}
changePasswordModal={changePasswordModal}
username={sessionStorage.getItem('username')}
password={sessionStorage.getItem('password')}
>
</ModalPassword>
</Modal>
<Dropdown overlay={menu1} arrow>
<a onClick={(e) => e.preventDefault()} style={{ marginRight: "20px" }}>
<Space style={{ color: "white" }}>
{sessionStorage.getItem('username')}
</Space>
</a>
</Dropdown>
</div>
)
}
//把state映射到props中去,意思就是把Redux中的数据映射到React中的props中去
//React想把Redux中的哪些数据拿过来用。
const mapStateToProps = (state, ownProps) => {
return {
name: state.formData.name,
path: state.formData.imgpath
}
}
//把action映射到props中去,这样使用props中方法触发action
const mapDispatchToProps = (dispatch, ownProps) => {
return {
saveFormData: (type, value) => dispatch({ type: actionTypes.SAVEFORMDATA, value: value, datatype: type }),
saveImg: (path) => dispatch({ type: actionTypes.SAVEIMG, path: path })
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Info)
.site-layout {
background: none;
}
.ant-layout-content {
background: none;
}
.ant-menu-item-selected {
color: #ff7a04;
}
.ant-menu-submenu-selected {
color: #ff7a04;
}
.ant-menu-submenu-expand-icon,
.ant-menu-submenu-arrow {
color: white;
}
.ant-menu-submenu:hover>.ant-menu-submenu-title>.ant-menu-submenu-expand-icon,
.ant-menu-submenu:hover>.ant-menu-submenu-title>.ant-menu-submenu-arrow {
color: #ff7a04;
}
.ant-menu-submenu-selected>.ant-menu-submenu-title>.ant-menu-submenu-expand-icon,
.ant-menu-submenu-selected>.ant-menu-submenu-title>.ant-menu-submenu-arrow {
color: #ff7a04;
}
.ant-menu-item.ant-menu-item-selected {
/* padding-left: 60px; */
background-image: url("../../../public/img/6.png");
background-size: 100% 100%;
}
.ant-menu-inline,
.ant-menu-vertical,
.ant-menu-vertical-left {
border: none;
}
.ant-menu-vertical .ant-menu-item::after,
.ant-menu-vertical-left .ant-menu-item::after,
.ant-menu-vertical-right .ant-menu-item::after,
.ant-menu-inline .ant-menu-item::after {
border: none;
}
.ant-menu-light .ant-menu-item:hover,
.ant-menu-light .ant-menu-item-active,
.ant-menu-light .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,
.ant-menu-light .ant-menu-submenu-active,
.ant-menu-light .ant-menu-submenu-title:hover {
color: #ff7a04;
}
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
background-color: transparent;
}
.ant-menu-item:active,
.ant-menu-submenu-title:active {
background-color: transparent;
}
.ant-menu-vertical>.ant-menu-item,
.ant-menu-vertical-left>.ant-menu-item,
.ant-menu-vertical-right>.ant-menu-item,
.ant-menu-inline>.ant-menu-item,
.ant-menu-vertical>.ant-menu-submenu>.ant-menu-submenu-title,
.ant-menu-vertical-left>.ant-menu-submenu>.ant-menu-submenu-title,
.ant-menu-vertical-right>.ant-menu-submenu>.ant-menu-submenu-title,
.ant-menu-inline>.ant-menu-submenu>.ant-menu-submenu-title {
font-size: 15px;
height: 60px;
line-height: 60px;
}
.ant-menu-item .ant-menu-item-icon,
.ant-menu-submenu-title .ant-menu-item-icon,
.ant-menu-item .anticon,
.ant-menu-submenu-title .anticon {
font-size: 18px;
}
.ant-layout-sider-trigger {
background: #26293e;
}
.ant-menu-sub.ant-menu-inline {
background-color: transparent;
}
.ant-menu-sub.ant-menu-inline>.ant-menu-item,
.ant-menu-sub.ant-menu-inline>.ant-menu-submenu>.ant-menu-submenu-title {
color: white;
}
.ant-menu-light .ant-menu-item:hover,
.ant-menu-light .ant-menu-item-active,
.ant-menu-light .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open,
.ant-menu-light .ant-menu-submenu-active,
.ant-menu-light .ant-menu-submenu-title:hover {
color: #ff7a04;
}
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
color: #ff7a04;
}
.ant-menu-vertical .ant-menu-submenu-selected,
.ant-menu-vertical-left .ant-menu-submenu-selected,
.ant-menu-vertical-right .ant-menu-submenu-selected {
color: #ff7a04;
}
.ant-menu-submenu-popup>.ant-menu {
color: white;
background-image: url(../../../public/img/5.png);
background-repeat: no-repeat;
box-shadow: 2px 2px 3px black;
}
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom'
import { Provider } from 'react-redux';
import { message, Layout, Menu, Button } from 'antd'
import Info from "./components/info"
import store from "../../store/store"
import RouterBeforeEach from '../../router/RouterBeforeEach.js'
import { API_queryMenu } from '@/api';
import { DatabaseOutlined, AppstoreAddOutlined, SettingOutlined, CodepenOutlined, MacCommandOutlined } from '@ant-design/icons'
const { Header, Content, Sider } = Layout;
import './index.css';
const STYLE = {
Layout: {
width: "100%",
height: "100vh",
backgroundImage: "url(../../public/img/4.png)",
Header: {
width: "100%",
height: "80px",
boxShadow: "2px 2px 3px black",
backgroundImage: "url(../../public/img/5.png)",
backgroundRepeat: "no-repeat",
backgroundSize: "100% 100%",
title: {
width: "260px",
fontSize: "30px",
float: "left",
color: "white",
textAlign: "center",
height: "80px",
lineHeight: "80px",
fontWeight: "700"
},
},
Layout: {
width: "100%",
height: "calc(100% - 82px)",
marginTop: "2px",
Sider: {
height: "100%",
boxShadow: "2px 2px 3px black",
backgroundImage: "url(../../public/img/5.png)",
title: {
width: "100%",
height: "100px",
padding: "10px 0px",
color: "white",
textAlign: "center",
fontSize: "23px",
fontWeight: "700"
},
Menu: {
width: "100%",
height: "calc(100% - 100px)",
color: "white",
background: "none",
listStyleType: "none",
transition: "background-color 0.3s ease 0s, min-width 0.3s ease 0s, max-width 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) 0s",
boxShadow: "2px 0 8px 0 rgb(29 35 41 / 5%)"
}
},
Content: {
width: "100%",
height: "100%",
padding: "20px"
}
}
}
}
const data = [
{
label: '数据接入', path: 'sjjr',
children: [
{ label: '文件接入', path: 'wjjr' },
{ label: '接口服务', path: 'jkfw' },
{ label: '数据探查', path: 'sjtc' },
]
},
{
label: '数据处理', path: 'sjcl',
children: [
{ label: '离线开发', path: 'lxkf' },
{ label: '实时开发', path: 'sskf' }
]
}
]
const App = (() => {
const [res, setRes] = useState(data);
const [items, setItems] = useState([]);
const navigate = useNavigate();
const [selectKeys, setSelectKeys] = useState([]);
const [openKeys, setOpenKeys] = useState([]);
const [collapsed, setCollapsed] = useState(false);
const [firstOpenKey, setFirstOpenKey] = useState([]);
const icons = [<DatabaseOutlined />, <AppstoreAddOutlined />]
const generateMenu = (data) => {
let data_list = [];
for (let i = 0; i < data.length; i++) {
let obj = {};
if (data[i].children && data[i].children.length) {
obj = { label: data[i].label, key: data[i].path, icon: icons[i % icons.length], children: [] };
obj.children = generateMenu(data[i].children);
} else {
obj = { label: data[i].label, key: data[i].path };
data[i].label == '自由配置' ? obj.icon = <SettingOutlined /> :
(data[i].label == '开发中心' ? obj.icon = <CodepenOutlined /> :
((data[i].label == '主题展示' ? obj.icon = <MacCommandOutlined /> : '')
)
)
}
data_list.push(obj);
}
return data_list;
}
useEffect(() => {
// API_queryMenu({ "value": sessionStorage.getItem('username'), "type": "USER" }).then(res => {
// setItems(generateMenu(res));
// debugger;
// if (res.length > 0) {
// setFirstOpenKey([res[0].path]);
// }
// if ((!sessionStorage.getItem('selectKeys') && !sessionStorage.getItem('openKeys'))) {
// setSelectKeys([res[0].children ? res[0].children[0].path : res[0].path]);
// setOpenKeys([res[0].path]);
// sessionStorage.setItem('openKeys', [res[0].path]);
// sessionStorage.setItem('selectKeys', res[0].children ? [res[0].children[0].path] : [res[0].path]);
// navigate((sessionStorage.getItem('selectKeys') && sessionStorage.getItem('selectKeys')) ? sessionStorage.getItem('selectKeys') : res[0].children ? res[0].children[0].path : res[0].path);
// } else {
// let openKey = [];
// if (sessionStorage.getItem('openKeys')) {
// openKey = (sessionStorage.getItem('openKeys').indexOf(',') != -1) ? sessionStorage.getItem('openKeys').split(',') :
// (sessionStorage.getItem('openKeys').indexOf(',') == -1) ? [sessionStorage.getItem('openKeys')] :
// []
// sessionStorage.setItem('openKeys', openKey);
// } else {
// if (sessionStorage.getItem('openKeys') != '') {
// openKey = [res[0].path];
// sessionStorage.setItem('openKeys', openKey);
// }
// }
// setSelectKeys([(sessionStorage.getItem('selectKeys') && sessionStorage.getItem('selectKeys')) ? sessionStorage.getItem('selectKeys') : res[0].children ? res[0].children[0].path : res[0].path]);
// sessionStorage.setItem('selectKeys', [(sessionStorage.getItem('selectKeys') && sessionStorage.getItem('selectKeys')) ? sessionStorage.getItem('selectKeys') : res[0].children ? res[0].children[0].path : res[0].path]);
// setOpenKeys(openKey);
// }
// }).catch(err => {
// message.warn(err);
// });
// sessionStorage.setItem("login", false);
// navigate("/login");
// sessionStorage.clear();
setItems(generateMenu(data));
if (res.length > 0) {
setFirstOpenKey([res[0].path]);
}
if ((!sessionStorage.getItem('selectKeys') && !sessionStorage.getItem('openKeys'))) {
setSelectKeys([res[0].children ? res[0].children[0].path : res[0].path]);
setOpenKeys([res[0].path]);
sessionStorage.setItem('openKeys', [res[0].path]);
sessionStorage.setItem('selectKeys', res[0].children ? [res[0].children[0].path] : [res[0].path]);
debugger
navigate((sessionStorage.getItem('selectKeys') && sessionStorage.getItem('selectKeys')) ? sessionStorage.getItem('selectKeys') : res[0].children ? res[0].children[0].path : res[0].path);
} else {
let openKey = [];
if (sessionStorage.getItem('openKeys')) {
openKey = (sessionStorage.getItem('openKeys').indexOf(',') != -1) ? sessionStorage.getItem('openKeys').split(',') :
(sessionStorage.getItem('openKeys').indexOf(',') == -1) ? [sessionStorage.getItem('openKeys')] :
[]
sessionStorage.setItem('openKeys', openKey);
} else {
if (sessionStorage.getItem('openKeys') != '') {
openKey = [res[0].path];
sessionStorage.setItem('openKeys', openKey);
}
}
setSelectKeys([(sessionStorage.getItem('selectKeys') && sessionStorage.getItem('selectKeys')) ? sessionStorage.getItem('selectKeys') : res[0].children ? res[0].children[0].path : res[0].path]);
sessionStorage.setItem('selectKeys', [(sessionStorage.getItem('selectKeys') && sessionStorage.getItem('selectKeys')) ? sessionStorage.getItem('selectKeys') : res[0].children ? res[0].children[0].path : res[0].path]);
setOpenKeys(openKey);
}
}, []);
const onClick = (e, a) => {
navigate(e.key);
setSelectKeys([e.key]);
setFirstOpenKey([e.keyPath[e.keyPath.length - 1]]);
sessionStorage.setItem("selectKeys", [e.key]);
};
const toggleCollapsed = (value) => {
setCollapsed(value);
if (!value) {
let openKey = [];
if (sessionStorage.getItem('openKeys')) {
openKey = (sessionStorage.getItem('openKeys').indexOf(',') != -1) ? sessionStorage.getItem('openKeys').split(',') :
(sessionStorage.getItem('openKeys').indexOf(',') == -1) ? [sessionStorage.getItem('openKeys')] :
[]
sessionStorage.setItem('openKeys', openKey);
} else {
if (sessionStorage.getItem('openKeys') != '') {
openKey = firstOpenKey;
sessionStorage.setItem('openKeys', openKey);
}
}
setOpenKeys(openKey);
}
};
const onOpenChange = (data) => {
setOpenKeys(data);
if (!collapsed) {
sessionStorage.setItem("openKeys", data);
}
};
return (
<Layout style={STYLE.Layout}>
<Header style={STYLE.Layout.Header}>
<div style={STYLE.Layout.Header.title}>台州公安数智中枢</div>
<Provider store={store}>
<div style={{ float: "right" }}>
<Info />
</div>
</Provider>
</Header>
<Layout className="site-layout" style={STYLE.Layout.Layout}>
<Sider width={220} collapsible collapsed={collapsed} onCollapse={(value) => toggleCollapsed(value)} style={STYLE.Layout.Layout.Sider}>
<Menu
openKeys={openKeys}
selectedKeys={selectKeys}
mode="inline"
items={items}
style={STYLE.Layout.Layout.Sider.Menu}
onClick={onClick}
onOpenChange={onOpenChange}
/>
</Sider>
<Content style={STYLE.Layout.Layout.Content}>
<RouterBeforeEach />
</Content>
</Layout>
</Layout>
)
})
export default App
\ No newline at end of file
/* .ant-form-item-label > label{
color: white;
} */
.systemName {
font-size: 18px;
color: white;
}
.login .ant-input {
color: white;
background: none !important;
}
.login .ant-input:hover {
border: none;
}
.login input:-webkit-autofill,
.login input:-webkit-autofill:hover,
.login input:-webkit-autofill:focus,
.login input:-webkit-autofill:active {
transition-delay: 111111s;
transition: color 11111s ease-out, background-color 111111s ease-out;
}
.login .ant-input-affix-wrapper {
border: none;
border-bottom: 1px solid #d9d9d9;
background: none;
}
.login .ant-input-affix-wrapper:hover,
.login .ant-input-affix-wrapper:focus,
.login .ant-input-affix-wrapper:active {
border: none;
border-bottom: 1px solid #d9d9d9;
background: none;
box-shadow: none;
}
\ No newline at end of file
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom'
import { API_Login } from '@/api'
import { Form, Button, Input, message } from 'antd'
import 'antd/dist/antd.css'
import { UserOutlined, LockOutlined } from '@ant-design/icons';
import './index.css'
const STYLE = {
container: {
width: "100%",
height: "100%",
textAlign: 'center',
backgroundImage: "url(../../public/img/1.png)",
bgContent: {
width: "60%",
height: "100%",
float: "left",
marginLeft: "20%",
paddingTop: "10%",
textAlign: "left",
img: {
width: "80%",
marginLeft: "10%"
},
form: {
width: "60%",
marginTop: "50px",
marginLeft: "20%",
color: "white",
item: {
height: "50px",
input: {
height: "50px",
color: "whtie !important",
// backgroundColor: "#ddd",
icon: {
width: "30px",
color: "white"
}
},
button: {
height: "50px",
marginTop: "20px",
fontSize: "28px",
fontWeight: "600",
letterSpacing: "15px",
border: "none",
color: "white",
borderRadius: "10px",
background: "none",
backgroundImage: "url(../../public/img/3.png)",
backgroundRepeat: "no-repeat",
backgroundSize: "100% 100%"
}
},
}
}
}
}
export default function login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const handleClick = (path) => {
// debugger
// API_Login(username, password).then(res => {
// sessionStorage.setItem("username", username);
// sessionStorage.setItem("password", password);
// message.success('登录成功');
// sessionStorage.setItem("token", res);
// sessionStorage.setItem("login", true);
// sessionStorage.removeItem("openKeys");
// sessionStorage.removeItem("selectKeys");
// navigate(path);
// }).catch(err => {
// message.warn(err);
// });
sessionStorage.setItem("username", username);
sessionStorage.setItem("password", password);
message.success('登录成功');
// sessionStorage.setItem("token", res);
sessionStorage.setItem("login", true);
sessionStorage.removeItem("openKeys");
sessionStorage.removeItem("selectKeys");
navigate(path);
}
return (
<div className='login' style={STYLE.container}>
<div style={STYLE.container.bgContent}>
<img src='../../public/img/2.png' style={STYLE.container.bgContent.img}></img>
<Form
name="basic"
labelCol={{ span: 4 }}
wrapperCol={{ span: 16 }}
initialValues={{ remember: true }}
autoComplete="off"
style={STYLE.container.bgContent.form}
>
<Form.Item wrapperCol={{ offset: 4, span: 16 }} style={STYLE.container.bgContent.form.item}>
<Input size="middle"
style={STYLE.container.bgContent.form.item.input}
prefix={<UserOutlined className="site-form-item-icon" style={STYLE.container.bgContent.form.item.input.icon} />}
placeholder="用户名" value={username} onChange={e => { setUsername(e.target.value) }}></Input>
</Form.Item>
<Form.Item wrapperCol={{ offset: 4, span: 16 }} style={STYLE.container.bgContent.form.item}>
<Input.Password size="middle"
style={STYLE.container.bgContent.form.item.input}
prefix={<LockOutlined className="site-form-item-icon" style={STYLE.container.bgContent.form.item.input.icon} />}
placeholder="密码" value={password} onChange={e => { setPassword(e.target.value) }}></Input.Password>
</Form.Item>
<Form.Item wrapperCol={{ offset: 4, span: 16 }}>
<Button onClick={() => handleClick('/')} block style={STYLE.container.bgContent.form.item.button}>登录</Button>
</Form.Item>
</Form>
</div>
</div>
)
}
\ No newline at end of file
.ant-breadcrumb-separator {
color: white;
}
.ant-breadcrumb-link {
color: white;
}
.ant-tree {
color: white;
background: transparent;
}
.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected {
color: #ff7a04 !important;
background-color: transparent;
}
.ant-tree .ant-tree-node-content-wrapper:hover {
color: #ff7a04 !important;
background-color: transparent;
}
.ant-table{
color: white;
background-color: transparent;
}
.ant-table-thead > tr > th{
color: white;
background-color: transparent;
}
.ant-table-tbody > tr.ant-table-row:hover > td, .ant-table-tbody > tr > td.ant-table-cell-row-hover{
background-color: #da756285;
cursor: pointer;
}
.ant-table-thead > tr > th{
border-bottom: 1px solid #2d375e;
}
.ant-table-tbody > tr > td{
border-top: 10px solid #141830;
border-bottom: 10px solid #141830;
background-color: #232645;
}
.actionImg{
width: 22px;
}
/* 分页样式修改 */
.ant-pagination-item a{
color: white;
}
.ant-pagination-item-active{
font-size: 20px;
background: none;
border: none;
}
.ant-pagination-prev button, .ant-pagination-next button{
color: white;
}
import React from "react";
import { Breadcrumb, Input, Tree, Table, Tag, Space } from 'antd';
const { Search } = Input;
import '../index.css';
import { DoubleRightOutlined, DownOutlined } from '@ant-design/icons';
const STYLE = {
Container: {
width: "100%",
height: "100%",
Header: {
width: "100%",
height: "60px",
padding: "15px",
color: "white",
Breadcrumb: {
width: "250px",
height: "30px",
float: "left",
fontSize: "16px",
color: "white",
Icon: {
fontSize: "16px",
fontWeight: "600"
}
},
Search: {
width: "40%",
float: "right"
}
},
Content: {
width: "100%",
height: "calc(100% - 60px)",
padding: "10px",
LeftContent: {
width: "200px",
height: "100%",
float: "left",
padding: "5px",
border: "1px solid #2d375e",
backgroundImage: "url(../../../public/img/8.png)",
boxShadow: "black 2px 2px 3px"
},
RightContent: {
width: "calc(100% - 220px)",
height: "100%",
float: "left",
marginLeft: "20px",
padding: "10px",
border: "1px solid #2d375e",
backgroundImage: "url(../../../public/img/8.png)",
boxShadow: "black 2px 2px 3px"
}
}
}
}
export default () => {
const onSearch = (value) => console.log(value);
const onSelect = (selectedKeys, info) => {
console.log('selected', selectedKeys, info);
};
const treeData = [
{
title: '基础设施',
key: '0-0',
children: [
{
title: '公路',
key: '0-0-0'
},
{
title: '水路',
key: '0-0-1',
},
{
title: '轨迹',
key: '0-0-2',
},
{
title: '场站',
key: '0-0-3',
},
]
},
{
title: '道路运输',
key: '1-0'
}
,
{
title: '公共交通',
key: '2-0'
}
,
{
title: '水路运输',
key: '3-0'
}
];
const columns = [
{
title: '序号',
dataIndex: 'index',
key: 'index',
align: 'center'
},
{
title: '名称',
dataIndex: 'name',
key: 'name',
align: 'center'
},
{
title: '编码(ID)',
dataIndex: 'id',
key: 'id',
align: 'center'
},
{
title: '类型',
dataIndex: 'type',
key: 'type',
align: 'center'
},
{
title: '管养单位',
dataIndex: 'department',
key: 'department',
align: 'center'
},
{
title: '位置',
dataIndex: 'address',
key: 'address',
align: 'center'
},
{
title: '定位',
key: 'action',
align: 'center',
render: (_, record) => (
<Space size="middle">
<a>
<img className="actionImg" src="../../../public/img/7.png"></img>
</a>
</Space>
),
},
];
const data = [
{
key: '1',
index: 1,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '2',
index: 2,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '3',
index: 3,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '4',
index: 4,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '5',
index: 5,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '6',
index: 6,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '7',
index: 7,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '8',
index: 8,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '9',
index: 9,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '10',
index: 10,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '11',
index: 11,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '12',
index: 12,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '13',
index: 13,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '14',
index: 14,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
{
key: '15',
index: 15,
name: '港口',
id: 564536,
type: '港口',
department: '水路运输局',
address: "水路运输局",
},
];
return (
<div style={STYLE.Container}>
<div style={STYLE.Container.Header}>
<Breadcrumb style={STYLE.Container.Header.Breadcrumb}>
<Breadcrumb.Item><DoubleRightOutlined style={STYLE.Container.Header.Breadcrumb.Icon} />&emsp;数据资源</Breadcrumb.Item>
<Breadcrumb.Item>目录管理</Breadcrumb.Item>
</Breadcrumb>
<Search
placeholder="请输入关键词"
onSearch={onSearch}
style={STYLE.Container.Header.Search}
/>
</div>
<div style={STYLE.Container.Content}>
<div style={STYLE.Container.Content.LeftContent}>
<Tree
// showLine
// showIcon={false}
onSelect={onSelect}
treeData={treeData}
/>
</div>
<div style={STYLE.Container.Content.RightContent}>
<Table
columns={columns}
dataSource={data}
size={"small"}
pagination={{
hideOnSinglePage:true
}}
/>
</div>
</div>
</div>
)
}
\ No newline at end of file
import { File } from 'better-xlsx';
import { saveAs } from 'file-saver';
function excelGet(column, dataSource, sheet1, fileName) {
// 新建工作谱
const file = new File();
// 新建表
let sheet = file.addSheet(sheet1);
let data = dataSource ? dataSource : []
// 获取表头行数
let depth = getDepth(column);
// 获取表头的列数
let columnNum = getColumns(column);
// 新建表头行数
let rowArr = [];
for (let k = 0; k < depth; k++) {
rowArr.push(sheet.addRow());
}
// 根据列数填充单元格
rowArr.map(ele => {
for (let j = 0; j < columnNum; j++) {
let cell = ele.addCell();
cell.value = j;
}
});
// 初始化表头
init(column, 0, 0);
// 按顺序展平column
let columnLineArr = [];
columnLine(column);
// 根据column,将dataSource里面的数据排序,并且转化为二维数组
let dataSourceArr = [];
data.map(ele => {
let dataTemp = [];
columnLineArr.map(item => {
dataTemp.push({
[item.dataIndex]: ele[item.dataIndex],
value: ele[item.dataIndex],
});
});
dataSourceArr.push(dataTemp);
});
// 绘画表格数据
dataSourceArr.forEach((item, index) => {
//根据数据,创建对应个数的行
let row = sheet.addRow();
row.setHeightCM(0.8);
//创建对应个数的单元格
item.map(ele => {
let cell = row.addCell();
if (ele.hasOwnProperty('num')) {
cell.value = index + 1;
} else {
cell.value = ele.value;
}
cell.style.align.v = 'center';
cell.style.align.h = 'right';
});
});
//设置每列的宽度
for (var i = 0; i < 50; i++) {
sheet.col(i).width = 15;
}
// 按顺序展平column
function columnLine(column) {
column.map(ele => {
if (ele.children === undefined || ele.children.length === 0) {
columnLineArr.push(ele);
} else {
columnLine(ele.children);
}
});
}
// 初始化表头
function init(column, rowIndex, columnIndex) {
// console.log(column)
column.map((item, index) => {
let hCell = sheet.cell(rowIndex, columnIndex);
// 如果没有子元素, 撑满列
if (item.title === '操作') {
hCell.value = '';
return;
} else if (item.children === undefined || item.children.length === 0) {
// 第一行加一个单元格
let title = "";
if (typeof item.title === 'string') {
title = item.title;
} else {
title = item.title.props.children[0];
}
hCell.value = title;
hCell.vMerge = depth - rowIndex - 1;
hCell.style.align.h = 'center';
hCell.style.align.v = 'center';
columnIndex++;
// rowIndex++
} else {
let childrenNum = 0;
function getColumns(arr) {
arr.map(ele => {
if (ele.children) {
getColumns(ele.children);
} else {
childrenNum++;
}
});
}
let title = "";
if (typeof item.title === 'string') {
title = item.title;
} else {
// console.log()
title = item.title.props.children[0];
}
getColumns(item.children);
hCell.hMerge = childrenNum - 1;
hCell.value = title;
hCell.style.align.h = 'center';
hCell.style.align.v = 'center';
let rowCopy = rowIndex;
rowCopy++;
init(item.children, rowCopy, columnIndex);
// 下次单元格起点
columnIndex = columnIndex + childrenNum;
}
});
}
// 获取表头rows
function getDepth(arr) {
const eleDepths = [];
arr.forEach(ele => {
let depth = 0;
if (Array.isArray(ele.children)) {
depth = getDepth(ele.children);
}
eleDepths.push(depth);
});
return 1 + max(eleDepths);
}
function max(arr) {
return arr.reduce((accu, curr) => {
if (curr > accu) return curr;
return accu;
});
}
// 计算表头列数
function getColumns(arr) {
let columnNum = 0;
arr.map(ele => {
if (ele.children) {
getColumns(ele.children);
} else {
columnNum++;
}
});
return columnNum;
}
file.saveAs('blob').then(function (content) {
saveAs(content, fileName + '.xlsx');
});
}
export default excelGet;
import React, { Component, Suspense } from 'react';
import { useNavigate, useLocation, useResolvedPath } from "react-router-dom";
import { Outlet } from 'react-router-dom'
import { checkRouterAuth } from './index'
import { useEffect, useState } from 'react'
const RouterBeforeEach = (props) => {
const navigate = useNavigate()
const location = useLocation()
const [auth, setAuth] = useState(false)
useEffect(() => {
console.log(location);
let obj = checkRouterAuth(location.pathname)
let blLogin = sessionStorage.getItem('login')
if (blLogin != 'true') {
setAuth(false)
navigate('/login', { replace: true })
} else {
setAuth(true)
}
}, [])
return auth ? <Outlet /> : null
}
export default RouterBeforeEach
\ No newline at end of file
import React, { Component, Suspense, lazy } from 'react';
import { useRoutes } from "react-router-dom";
const routes = [
{
path: '/login',
auth: false,
component: lazy(() => import('../pages/login'))
},
{
path: '/',
auth: false,
component: lazy(() => import('../pages/home')),
children: [
{
path: '/wjjr',
auth: false,
component: lazy(() => import('../pages/sjjr/wjjr'))
},
{
path: '*',
auth: false,
component: lazy(() => import('../pages/404.js'))
}
]
},
{
path: '*',
auth: false,
component: lazy(() => import('../pages/404.js'))
}
]
//根据路径获取路由
const checkAuth = (routers, path) => {
for (const data of routers) {
if (data.path == path) return data
if (data.children) {
const res = checkAuth(data.children, path)
if (res) return res
}
}
return null
}
const checkRouterAuth = (path) => {
let auth = null
auth = checkAuth(routes, path)
return auth
}
// 路由处理方式
const generateRouter = (routers) => {
return routers.map((item) => {
if (item.children) {
item.children = generateRouter(item.children)
}
item.element = <Suspense fallback={<div>loading...</div>}>
<item.component />
</Suspense>
return item
})
}
const Router = () => useRoutes(generateRouter(routes))
export { Router, checkRouterAuth }
\ No newline at end of file
// 保存表单数据
export const SAVEFORMDATA = 'SAVEFORMDATA';
// 保存图片
export const SAVEIMG = 'SAVEIMG';
// 清空数据
export const CLEARDATA = 'CLEARDATA';
\ No newline at end of file
import * as actionTypes from './action-type';
// 保存表单数据
export const saveFormData = (value, datatype) => {
return {
type: actionTypes.SAVEFORMDATA,
value,
datatype,
}
}
// 保存图片地址
export const saveImg = path => {
return {
type: actionTypes.SAVEIMG,
path,
}
}
// 保存图片地址
export const clearData = () => {
return {
type: actionTypes.CLEARDATA,
}
}
\ No newline at end of file
import * as actionTypes from './action-types';
let defaultState = {
orderSum: '', //金额
name: '1', //姓名
phoneNo: '', //手机号
imgpath: '', //图片地址
}
// 首页表单数据
//state+action=newstate
export const formData = (state = defaultState, action = {}) => {
switch (action.type) {
case actionTypes.SAVEFORMDATA:
return { ...state, ...{ [action.datatype]: action.value } };
case actionTypes.SAVEIMG:
return { ...state, ...{ imgpath: action.path } };
case actionTypes.CLEARDATA:
return { ...state, ...defaultState };
default:
return state;
}
}
\ No newline at end of file
import { createStore, combineReducers, applyMiddleware } from 'redux';
import * as home from './reduce';
import thunk from 'redux-thunk';
let store = createStore(
combineReducers({ ...home }),
applyMiddleware(thunk)
);
export default store;
\ No newline at end of file
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
}
}
\ No newline at end of file
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');
const Webpack = require('webpack');
module.exports = {
mode: 'development', // 开发模式
// mode: 'production',
entry: path.resolve(__dirname, './src/index.js'), // 项目入口文件
output: {
filename: '[name].[contenthash:8].js',
path: path.resolve(__dirname, './dist') // 打包后的目录
},
resolve: {
extensions: ['.ts', '.js'],//模块主文件包含index.ts
alias: {
"public": path.resolve(__dirname, './public'),
'@': path.resolve('src')
},
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './index.html'),
inject: true,
favicon: path.join('public/img/favicon.ico')
}),
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
{ from: path.resolve(__dirname, './public'), to: 'public' },
// { from: path.join(cesiumSource, "Assets"), to: 'Assets' },
]
}),
new Webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify('./')
})
],
devtool: 'eval',
// devtool:'inline-source-map',
module: {
// 配置模块的读取和解析规则,通常用来配置 Loader。其类型是一个数组,数组里每一项都描述了如何去处理部分文件
rules: [
{
test: /\.(js|jsx)$/,
use: [{
loader: 'babel-loader'
}]
},
// css样式解析
{
test: /\.css$/,
// 处理顺序为从后到前,即先交给 css-loader 最后再给 style-loader。
use: ['style-loader', 'css-loader']
},
// 图片解析
{
test: /\.(eot|svg|ttf|woff|woff2|jpg|png|jpeg)$/,
use: [{
loader: "file-loader",
options: {
esModule: false
}
}]
},
{
test: /\.ts?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
devServer: {
port: 8086,
hot: true,
static: './',
//后台代理
proxy: {
'/api/': {
target: 'http://192.168.168.135:10010',
// target: 'http://localhost:10010',
ws: true,
secure: false,
changeOrigin: true,
pathRewrite: {
'^/api/': '/'
}
}
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment