Compare commits

...

68 Commits
master ... dev

Author SHA1 Message Date
陈博文 9103f7ea64 修改
3 years ago
陈博文 5806392844 修改
3 years ago
陈博文 bcee1fa9f6 修改重置页面
3 years ago
陈博文 2dbc23d094 修改初装传值
3 years ago
陈博文 f23648ab35 修改文案
3 years ago
陈博文 550f3e8621 修改文案
3 years ago
陈博文 a20f6a7ff6 修改地址
3 years ago
陈博文 c8d2bdef14 修改地址
3 years ago
陈博文 482e48b195 修改下载地址
3 years ago
陈博文 2c4cf97d5b 修改后端下拉框
3 years ago
陈博文 870de2fe74 修改上传
3 years ago
陈博文 dc1d9f9281 导航完成
3 years ago
陈博文 6a31462dfc 加入查询
3 years ago
陈博文 7ae1438d8b 修改界面2
3 years ago
陈博文 19a64db035 修改界面
3 years ago
陈博文 a7bcf0d7d2 修改接口参数
3 years ago
陈博文 4953dcb997 本地上传xml
3 years ago
陈博文 4d0ebe7503 修改
3 years ago
陈博文 795a06679e 上传xml文件
3 years ago
陈博文 3e5033d403 修改接口数据
3 years ago
陈博文 ceca3e4ead 修改虚拟仿真
3 years ago
陈博文 c06ef2e9dc 修改新需求
3 years ago
陈博文 d331ae58a4 修改issue
3 years ago
陈博文 df7f97406c 修改地址2
3 years ago
陈博文 6f23ab6d50 修改地址
3 years ago
陈博文 3b610c722c 修改大部分功能
3 years ago
陈博文 f4ac688d50 修改文案
3 years ago
陈博文 8d1b0d9696 容错
3 years ago
陈博文 c389cb93b3 虚拟仿真完成
3 years ago
陈博文 41213e1077 虚拟仿真完成
3 years ago
陈博文 d2cb27988f 调试
3 years ago
陈博文 365bd2b29d 保存
3 years ago
陈博文 9237cdc572 保存页面
3 years ago
陈博文 00f67bc7c6 加入404
3 years ago
陈博文 61fbf0383f 加入404
3 years ago
陈博文 cb259fee0a 修改UI对齐
3 years ago
陈博文 13e9c7438e 修改展开
3 years ago
陈博文 8c94ab1450 修改错位
3 years ago
陈博文 2eb9bcba52 修改图标
3 years ago
陈博文 cae9ef9fee 型号管理完成
3 years ago
陈博文 5af575607d 注册登记完成
3 years ago
陈博文 bb4d63cd30 保存代码
3 years ago
陈博文 5aa21e77b3 修改样式
3 years ago
陈博文 6ec00d1d7b 配发管理完成2
3 years ago
陈博文 24e0fda473 配发管理完成
3 years ago
陈博文 04282bcf03 修改配置地址
3 years ago
陈博文 c717620e0a 厂商信息管理完成
3 years ago
陈博文 008dd0f51c 保存代码
3 years ago
陈博文 201ad07cd0 基础设施管理完成
3 years ago
陈博文 214f93d0ad 列表完成
3 years ago
陈博文 520eb0750b 修改密码管理页面
3 years ago
陈博文 a0130b493d 密码管理开通成功
3 years ago
陈博文 8f71dd2f76 创建路径
3 years ago
陈博文 5c4c86429b 修改basic地址
3 years ago
陈博文 842a217234 3个开通完成
3 years ago
陈博文 bb13fc02c1 隐藏收起
3 years ago
陈博文 f049f164b4 第二个开通成功
3 years ago
陈博文 156b984599 开通主页面2
3 years ago
陈博文 ce1b50bb36 开通主页面
3 years ago
陈博文 0912e03f6d 数据中心
3 years ago
陈博文 8b9c4d08d7 第一个系统完成
3 years ago
陈博文 2b74bdbce9 步骤
3 years ago
陈博文 eccae16d68 上传完成
3 years ago
陈博文 c2ea6a3811 管理设备2
3 years ago
陈博文 10de1e2718 保存代码
3 years ago
陈博文 1b4482ef34 请求封装完成
3 years ago
陈博文 cd80917350 测试
3 years ago
linlu 97f1ee43cd 1.1.1
3 years ago

@ -0,0 +1,16 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab

20
.gitignore vendored

@ -0,0 +1,20 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/npm-debug.log*
/yarn-error.log
/yarn.lock
/package-lock.json
# production
/dist
# misc
.DS_Store
# umi
/src/.umi
/src/.umi-production
/src/.umi-test
/.env.local

@ -0,0 +1,8 @@
**/*.md
**/*.svg
**/*.ejs
**/*.html
package.json
.umi
.umi-production
.umi-test

@ -0,0 +1,11 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80,
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
}
]
}

@ -0,0 +1,122 @@
import { defineConfig } from 'umi';
let publicPath = process.env.NODE_ENV === 'development' ? '/' : '/react/build/';
export default defineConfig({
publicPath,
title: false,
nodeModulesTransform: {
type: 'none',
},
theme: {
'@primary-color': '#165DFF',
},
dva: {
hmr: true,
// immer: true,
},
routes: [
{
path: '/',
component: '@/pages/index',
routes: [
{
path: '/basic',
component: '@/pages/Basic/Header',
routes: [
{
path: '/basic',
component: '@/pages/Basic/List/Index',
},
{
path: '/basic/device',
component: '@/pages/Basic/List/Device',
},
{
path: '/basic/certificate',
component: '@/pages/Basic/List/Certificate',
},
{ component: '@/pages/HttpStatus/404' },
],
},
{
path: '/dataCenter',
component: '@/pages/Equipment/List/DataCenter',
exact: true,
},
{
path: '/terminal',
component: '@/pages/Equipment/List/LocalManager',
exact: true,
},
{
path: '/equipment',
component: '@/pages/Equipment/Header',
routes: [
{
path: '/equipment',
component: '@/pages/Equipment/List/Index',
},
{ component: '@/pages/HttpStatus/404' },
],
},
{
path: '/encrypt',
component: '@/pages/Equipment/Header',
routes: [
{
path: '/encrypt',
component: '@/pages/Encrypt/List/Index',
},
{ component: '@/pages/HttpStatus/404' },
],
},
{
path: '/manager',
component: '@/pages/Manager/Header',
routes: [
{
path: '/manager/passwordManager',
component: '@/pages/Manager/PasswordManager',
},
{
path: '/manager/basicManager',
component: '@/pages/Manager/BasicManager',
routes: [
{
path: '/manager/basicManager/register',
component: '@/pages/Manager/BasicManager/List/Register',
},
{
path: '/manager/basicManager/model',
component: '@/pages/Manager/BasicManager/List/Model',
},
{
path: '/manager/basicManager/manufacturer',
component: '@/pages/Manager/BasicManager/List/Manufacturer',
},
{
path: '/manager/basicManager/allotment',
component: '@/pages/Manager/BasicManager/List/Allotment',
},
{
path: '/manager/basicManager/demand',
component: '@/pages/Manager/BasicManager/List/Demand',
},
{ component: '@/pages/HttpStatus/404' },
],
},
{ component: '@/pages/HttpStatus/404' },
],
},
{
path: '/simulation',
component: '@/pages/Simulation',
exact: true,
},
{ component: '@/pages/HttpStatus/404' },
],
},
],
fastRefresh: {},
});

@ -0,0 +1,3 @@
{
"cSpell.words": ["iconfont"]
}

@ -1,2 +1,15 @@
# datacenter
# 信工大数据中心项目
## 开始使用
安装依赖,
```bash
$ yarn
```
启动服务,
```bash
$ yarn start
```

@ -0,0 +1,42 @@
{
"private": true,
"scripts": {
"start": "umi dev",
"build": "umi build",
"postinstall": "umi generate tmp",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"test": "umi-test",
"test:coverage": "umi-test --coverage"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"dependencies": {
"@ant-design/pro-layout": "^6.5.0",
"echarts": "^5.3.3",
"echarts-for-react": "^3.0.2",
"react": "17.x",
"react-dom": "17.x",
"umi": "^3.5.32",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@types/lodash": "^4.14.182",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@umijs/preset-react": "1.x",
"@umijs/test": "^3.5.32",
"lint-staged": "^10.0.7",
"prettier": "^2.2.0",
"typescript": "^4.1.2",
"yorkie": "^2.0.0"
}
}

Binary file not shown.

@ -0,0 +1,24 @@
.nav {
display: flex;
justify-content: space-between;
width: 1200px;
margin: auto;
padding-bottom: 20px;
> div {
width: 280px;
height: 260px;
background: #fff;
cursor: pointer;
b {
font-size: 18px;
text-align: center;
height: 40px;
line-height: 40px;
background: #d9d9d9;
display: inline-block;
width: 100%;
}
}
}

@ -0,0 +1,208 @@
import styles from './index.less';
import { Fragment, useEffect, FC } from 'react';
import Fetch from '@/utils/fetch';
import {
connect,
ConnectProps,
Dispatch,
history,
useLocation,
BasicInfoModelState,
} from 'umi';
import ReactEcharts from 'echarts-for-react';
interface PageProps {
dispatch: Dispatch;
basic: BasicInfoModelState;
}
const Nav: FC<PageProps> = ({ dispatch, basic }) => {
const {
echartsData: { resourceData },
} = basic;
const location: any = useLocation();
const getData = async () => {};
console.log(resourceData, 'resourceData');
const option1 = {
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top: 20,
containLabel: true,
},
xAxis: {
type: 'category',
data: resourceData?.xData || [
'15',
'20',
'64',
'91',
'128',
'ECC2',
'ECC3',
],
axisLabel: {
rotate: 45,
},
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value}M',
},
},
series: [
{
data: resourceData?.yData || [15, 8, 20, 91, 20, 15, 128],
type: 'bar',
},
],
};
const option2Data = [
{
value: 335,
name: '已出库',
},
{
value: 310,
name: '已注册',
},
{
value: 234,
name: '已入库',
},
];
const option2 = {
startAngle: 180,
color: ['#5470c6', '#91cc75', '#fac858', 'transparent'],
series: [
{
name: '',
type: 'pie',
radius: ['45%', '90%'],
avoidLabelOverlap: false,
startAngle: 180,
center: ['50%', '70%'],
label: {
normal: {
position: 'inner',
textStyle: {
color: '#fff',
fontSize: 12,
},
},
},
labelLine: {
normal: {
show: false,
},
},
data: option2Data.concat({
value:
option2Data[0].value + option2Data[1].value + option2Data[2].value,
name: '',
}),
},
],
};
const option3 = {
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top: 20,
containLabel: true,
},
xAxis: {
type: 'category',
data: ['等待执行', '执行成功', '执行失败'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [
{ itemStyle: { color: '#fac858' }, value: 15 },
{ itemStyle: { color: '#5470c6' }, value: 5 },
{ itemStyle: { color: '#ee6666' }, value: 34 },
],
type: 'bar',
},
],
};
return (
<div className={styles.nav}>
<div
onClick={() => {
history.push('/manager/passwordManager');
}}
>
<b
className={
location.pathname?.includes('/manager/passwordManager')
? 'primary-color'
: ''
}
>
</b>
<ReactEcharts
option={option1}
style={{ height: 220 }}
opts={{ renderer: 'svg' }}
/>
</div>
<div
onClick={() => {
history.push('/manager/basicManager/register');
}}
>
<b
className={
location.pathname?.includes('/manager/basicManager')
? 'primary-color'
: ''
}
>
</b>
<ReactEcharts
option={option2}
style={{ height: 220 }}
opts={{ renderer: 'svg' }}
/>
</div>
<div>
<b></b>
<ReactEcharts
option={option3}
style={{ height: 220 }}
opts={{ renderer: 'svg' }}
/>
</div>
<div>
<b></b>
<div className="font18 ml20 mt20">
<a style={{ fontWeight: 'bold' }}></a>
</div>
<div className="font18 ml20 mt20">
<strong className="primary-color"></strong>
</div>
<div className="font18 ml20 mt20">
<strong className="primary-color">1.0.0.0</strong>
</div>
</div>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Nav);

@ -0,0 +1,159 @@
import { Effect, Reducer } from 'umi';
import { getSelectData } from '@/service/index';
export interface BasicInfo {
resource: string;
cert: string;
dataName: string;
dbPasswd: string;
dbServerIp: string;
dbUser: string;
deviceNo: string;
managerNode: string;
nodeName: string;
supportUnit: string;
type: string;
file1: any;
file2: any;
file3: any;
file4: any;
}
export interface CertificateInfo {
step: number;
certCycle: number;
certNum: number;
certUrl: string;
company: string;
dbDrive: string;
dbIp: string;
dbIsConn: boolean;
dbName: string;
dbPasswd: string;
dbPort: string;
dbType: string;
dbUser: string;
importCertFile1: string;
importCertFile2: string;
targetIp: string;
targetPort: string;
targetPasswd: string;
targetUserdn: string;
result: any;
}
export interface BasicInfoModelState {
basicInfo: BasicInfo;
certificateInfo: CertificateInfo;
initData: any;
echartsData: any;
}
export interface BasicModelType {
namespace: 'basic';
state: BasicInfoModelState;
effects: {
setActionData: Effect;
setCertificateInfo: Effect;
getSelectData: Effect;
setEchartsData: Effect;
};
reducers: {
save: Reducer<any>;
};
}
const BasicModel: BasicModelType = {
namespace: 'basic',
state: {
basicInfo: {
resource: '',
cert: '',
dbUser: '',
dbPasswd: '',
dbServerIp: '',
type: '1',
dataName: '',
nodeName: '',
deviceNo: '',
supportUnit: '',
managerNode: '',
file1: null,
file2: null,
file3: null,
file4: null,
},
certificateInfo: {
step: 1,
company: '',
dbType: '',
dbDrive: '',
dbIp: '',
dbPort: '',
dbName: '',
dbUser: '',
dbPasswd: '',
dbIsConn: false,
targetIp: '',
targetPort: '',
targetUserdn: '',
targetPasswd: '',
certUrl: '',
certNum: 0,
certCycle: 0,
importCertFile1: '',
importCertFile2: '',
result: [],
},
initData: [],
echartsData: {
resourceData: {},
},
},
effects: {
*setEchartsData({ payload }, { call, put, select }): any {
const echartsData = yield select((state: any) => state.basic.echartsData);
yield put({
type: 'save',
payload: { echartsData: { ...echartsData, resourceData: payload } },
});
},
*getSelectData({ payload }, { call, put }): any {
const response = yield call(getSelectData, payload);
if (response?.result === 'success') {
yield put({
type: 'save',
payload: { initData: response?.data?.[0] },
});
}
return response;
},
*setActionData({ payload }, { call, put, select }): any {
const basicInfo = yield select((state: any) => state.basic.basicInfo);
yield put({
type: 'save',
payload: { basicInfo: { ...basicInfo, ...payload } },
});
},
*setCertificateInfo({ payload }, { call, put, select }): any {
const certificateInfo = yield select(
(state: any) => state.basic.certificateInfo,
);
yield put({
type: 'save',
payload: { certificateInfo: { ...certificateInfo, ...payload } },
});
},
},
reducers: {
save(state, action) {
return {
...state,
...action.payload,
};
},
},
};
export default BasicModel;

@ -0,0 +1,21 @@
.head {
height: 60px;
background: #001628;
font-size: 18px;
font-weight: 500;
color: #ffffff;
line-height: 60px;
padding-left: 40px;
display: flex;
align-items: center;
i {
font-size: 26px;
}
}
.content {
height: calc(100vh - 60px);
background-color: #fafafa;
overflow: auto;
}

@ -0,0 +1,15 @@
import styles from './index.less';
import { Fragment, useEffect } from 'react';
const Header = ({ ...props }) => {
return (
<Fragment>
<div className={styles.head}>
<i className="iconfont icon-a-dashujushujujiegouguanxiguanxifenxigongtonglianxirenzuzhi1 mr10" />
</div>
<div className={styles.content}>{props.children}</div>
</Fragment>
);
};
export default Header;

@ -0,0 +1,29 @@
.page {
background-color: #fff;
width: 1200px;
margin: 0 auto;
min-height: 600px;
overflow: hidden;
padding-bottom: 20px;
.name {
display: flex;
align-items: center;
margin-bottom: 50px;
margin-top: 30px;
b {
width: 6px;
height: 20px;
background: #464f66;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 24px;
font-weight: 500;
color: #232b40;
}
}
}

@ -0,0 +1,181 @@
import styles from './index.less';
import { Input, Button, Row, Form, Select, message } from 'antd';
import { FC } from 'react';
import { connect, Dispatch, BasicInfoModelState } from 'umi';
import Fetch from '@/utils/fetch';
import { getInitData } from '@/utils/util';
interface PageProps {
basic: BasicInfoModelState;
dispatch: Dispatch;
}
const Page: FC<PageProps> = ({ basic, dispatch }) => {
const [form] = Form.useForm();
const { certificateInfo } = basic;
const { step } = certificateInfo;
const handleValuesChange = (v: any) => {
dispatch({
type: 'basic/setCertificateInfo',
payload: v,
});
};
const testLink = async () => {
const res = await Fetch('/openi/resource/dbTestConnection', {
method: 'post',
data: {
dbType: certificateInfo.dbType,
dbDrive: certificateInfo.dbDrive,
dbIp: certificateInfo.dbIp,
dbPort: certificateInfo.dbPort,
dbName: certificateInfo.dbName,
dbUser: certificateInfo.dbUser,
dbPasswd: certificateInfo.dbPasswd,
},
});
if (res.result === 'success') {
const data = res?.data?.[0];
dispatch({
type: 'basic/setCertificateInfo',
payload: {
dbIsConn: data?.isConn,
},
});
} else {
message.error(res.errorMsg);
}
};
return (
<div
style={{ display: step === 1 ? 'block' : 'none' }}
className={styles.page}
>
<div className={styles.name}>
<b /> <span></span>
</div>
<Form
form={form}
colon={false}
layout="horizontal"
labelCol={{ span: 5 }}
size="large"
wrapperCol={{ span: 14 }}
onValuesChange={handleValuesChange}
onFinish={() => {
dispatch({
type: 'basic/setCertificateInfo',
payload: { step: 2 },
});
}}
>
<Form.Item
label="数据库类型"
name="dbType"
rules={[
{
required: true,
message: `请输入数据库类型`,
},
]}
>
<Select>
{getInitData('dbTypeList')?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label="数据库驱动"
name="dbDrive"
rules={[
{
required: true,
message: `请输入数据库驱动`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="IP地址"
name="dbIp"
rules={[
{
required: true,
message: `请输入IP地址`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="端口号"
name="dbPort"
rules={[
{
required: true,
message: `请输入端口号`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="数据库名"
name="dbName"
rules={[
{
required: true,
message: `请输入数据库名`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="数据库用户名"
name="dbUser"
rules={[
{
required: true,
message: `请输入数据库用户名`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="数据库密码"
name="dbPasswd"
rules={[
{
required: true,
message: `请输入数据库密码`,
},
]}
>
<Input.Password autoComplete="new-password" />
</Form.Item>
</Form>
<Row justify="end">
<Button onClick={testLink} type="primary">
</Button>
<Button
type="primary"
ghost
onClick={() => form.submit()}
className="ml20"
>
</Button>
</Row>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,51 @@
.page {
background-color: #fff;
width: 1200px;
margin: 0 auto;
min-height: 600px;
overflow: hidden;
padding-bottom: 20px;
.name {
display: flex;
align-items: center;
margin-bottom: 50px;
margin-top: 30px;
b {
width: 6px;
height: 20px;
background: #464f66;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 24px;
font-weight: 500;
color: #232b40;
}
}
.title {
display: flex;
align-items: center;
margin-left: 60px;
margin-bottom: 30px;
b {
width: 4px;
height: 14px;
background: #464f66;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 18px;
font-weight: 500;
color: #464f66;
}
}
}

@ -0,0 +1,175 @@
import styles from './index.less';
import { Input, Button, Row, Form, InputNumber } from 'antd';
import { FC } from 'react';
import { connect, Dispatch, BasicInfoModelState } from 'umi';
interface PageProps {
basic: BasicInfoModelState;
dispatch: Dispatch;
}
const Page: FC<PageProps> = ({ basic, dispatch }) => {
const [form] = Form.useForm();
const { certificateInfo } = basic;
const { step } = certificateInfo;
console.log(certificateInfo, 'certificateInfo');
const handleValuesChange = (v: any) => {
dispatch({
type: 'basic/setCertificateInfo',
payload: v,
});
};
return (
<div
style={{ display: step === 2 ? 'block' : 'none' }}
className={styles.page}
>
<div className={styles.name}>
<b /> <span></span>
</div>
<Form
form={form}
colon={false}
layout="horizontal"
labelCol={{ span: 5 }}
size="large"
wrapperCol={{ span: 14 }}
onValuesChange={handleValuesChange}
onFinish={() => {
dispatch({
type: 'basic/setCertificateInfo',
payload: { step: 3 },
});
}}
>
<div className={styles.title}>
<b /> <span></span>
</div>
<Form.Item
label="服务器地址"
name="targetIp"
rules={[
{
required: true,
message: `请输入服务器地址`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="服务器端口"
name="targetPort"
rules={[
{
required: true,
message: `请输入服务器端口`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="用户DN"
name="targetUserdn"
rules={[
{
required: true,
message: `请输入用户DN`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="用户口令"
name="targetPasswd"
rules={[
{
required: true,
message: `请输入用户口令`,
},
]}
>
<Input.Password autoComplete="new-password" />
</Form.Item>
<div className={styles.title}>
<b /> <span></span>
</div>
<Form.Item
label="文件路径"
name="certUrl"
rules={[
{
required: true,
message: `请输入文件路径`,
},
]}
>
<Input />
</Form.Item>
<div className={styles.title}>
<b /> <span>CRL</span>
</div>
<Form.Item label="CRL发布点中的证书数量">
<Form.Item
noStyle
name="certNum"
rules={[
{
required: true,
message: `请输入CRL发布点中的证书数量`,
},
]}
>
<InputNumber min={0} precision={0} />
</Form.Item>
<span className="ant-form-text"> 500</span>
</Form.Item>
<Form.Item label="CRL发布周期">
<Form.Item
noStyle
name="certCycle"
rules={[
{
required: true,
message: `请输入CRL发布周期`,
},
]}
>
<InputNumber min={0} precision={0} />
</Form.Item>
<span className="ant-form-text"></span>
</Form.Item>
</Form>
<Row justify="end">
<Button
onClick={() => {
dispatch({
type: 'basic/setCertificateInfo',
payload: { step: 1 },
});
}}
type="primary"
ghost
>
</Button>
<Button
type="primary"
ghost
onClick={() => form.submit()}
className="ml20"
>
</Button>
</Row>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,48 @@
.page {
background-color: #fff;
width: 1200px;
margin: 0 auto;
min-height: 600px;
overflow: hidden;
padding-bottom: 20px;
.name {
display: flex;
align-items: center;
margin-bottom: 50px;
margin-top: 30px;
b {
width: 6px;
height: 20px;
background: #464f66;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 24px;
font-weight: 500;
color: #232b40;
}
}
.row {
display: flex;
align-items: center;
justify-content: center;
padding: 30px 0;
sup {
color: red;
margin-top: 13px;
margin-right: 4px;
font-size: 14px;
}
button {
margin-left: 30px;
margin-right: 10px;
}
}
}

@ -0,0 +1,141 @@
import styles from './index.less';
import { message, Button, Row, Form } from 'antd';
import Fetch from '@/utils/fetch';
import { useState, FC } from 'react';
import { connect, Dispatch, BasicInfoModelState } from 'umi';
interface PageProps {
basic: BasicInfoModelState;
dispatch: Dispatch;
}
const Page: FC<PageProps> = ({ basic, dispatch }) => {
const { certificateInfo } = basic;
const { step, importCertFile1, importCertFile2 } = certificateInfo;
const [file1, setFile1] = useState<any>(null);
const [file2, setFile2] = useState<any>(null);
const [upload, setUpload] = useState<boolean>(true);
console.log(certificateInfo, 'certificateInfo');
const handleFile = (type: string) => {
var inputObj = document.createElement('input');
inputObj.setAttribute('id', '_ef');
inputObj.setAttribute('type', 'file');
inputObj.setAttribute('style', 'visibility:hidden');
document.body.appendChild(inputObj);
inputObj.click();
inputObj.onchange = (e: any) => {
if (type === 'file1') {
setFile1(e?.target?.files?.[0]);
} else {
setFile2(e?.target?.files?.[0]);
}
};
};
const uploadFile = async () => {
const data: any = new FormData();
data.append('files', file1);
data.append('files', file2);
const res = await Fetch('/openi/resource/importFiles', {
method: 'post',
data,
});
if (res.result === 'success') {
message.success('上传成功');
const data = res?.data?.[0];
dispatch({
type: 'basic/setCertificateInfo',
payload: {
importCertFile1: data[0],
importCertFile2: data[1],
},
});
setUpload(false);
}
};
const skip = async () => {
const res = await Fetch('/openi/resource/getCertInfomation');
if (res.errorCode === 500) {
message.error(res?.errorMsg);
return;
}
if (res.result === 'success') {
const data = res?.data?.[0];
dispatch({
type: 'basic/setCertificateInfo',
payload: {
result: data,
},
});
dispatch({
type: 'basic/setCertificateInfo',
payload: { step: 4 },
});
}
};
return (
<div
style={{ display: step === 3 ? 'block' : 'none' }}
className={styles.page}
>
<div className={styles.name}>
<b /> <span></span>
</div>
<div className={styles.row}>
<sup>*</sup>
<div>ECCDSA359*.p7b</div>
<Button onClick={() => handleFile('file1')} type="primary" ghost>
{!!file1 ? '已选择' : '浏览'}
</Button>
<span>{importCertFile1}</span>
</div>
<div className={styles.row}>
<sup>*</sup>
<div>ECCDSA279*.p7b</div>
<Button onClick={() => handleFile('file2')} type="primary" ghost>
{!!file2 ? '已选择' : '浏览'}
</Button>
<span>{importCertFile2}</span>
</div>
<div className={styles.row}>
<Button
disabled={!(file1 && file2)}
onClick={uploadFile}
type="primary"
>
</Button>
</div>
<Row justify="end">
<Button
onClick={() => {
dispatch({
type: 'basic/setCertificateInfo',
payload: { step: 2 },
});
}}
type="primary"
ghost
>
</Button>
<Button
disabled={upload}
type="primary"
ghost
className="ml20"
onClick={skip}
>
</Button>
</Row>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,71 @@
.page {
background-color: #fff;
width: 1200px;
margin: 0 auto;
min-height: 600px;
overflow: hidden;
padding-bottom: 20px;
.name {
display: flex;
align-items: center;
margin-bottom: 50px;
margin-top: 30px;
b {
width: 6px;
height: 20px;
background: #464f66;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 24px;
font-weight: 500;
color: #232b40;
}
}
.title {
display: flex;
align-items: center;
margin-left: 60px;
margin-bottom: 10px;
b {
width: 4px;
height: 14px;
background: #464f66;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 18px;
font-weight: 500;
color: #464f66;
}
}
.row {
display: flex;
align-items: center;
justify-content: center;
padding: 15px 0;
span {
margin: 0 10px;
width: 50%;
font-size: 14px;
color: #333;
}
span:first-child {
text-align: right;
color: #464f66;
}
}
}

@ -0,0 +1,107 @@
import styles from './index.less';
import { Button, Row, message } from 'antd';
import { FC } from 'react';
import Fetch from '@/utils/fetch';
import { connect, Dispatch, BasicInfoModelState, history } from 'umi';
interface PageProps {
basic: BasicInfoModelState;
dispatch: Dispatch;
}
const Page: FC<PageProps> = ({ basic, dispatch }) => {
const { certificateInfo } = basic;
const { step, result } = certificateInfo;
const handleClick = async () => {
const { step, ...data } = certificateInfo;
const res = await Fetch('/openi/resource/openCertNow', {
method: 'post',
data,
});
if (res.result === 'success') {
message.success('开通证书体系成功');
history.replace('/equipment');
}
};
return (
<div
style={{ display: step === 4 ? 'block' : 'none' }}
className={styles.page}
>
<div className={styles.name}>
<b /> <span></span>
</div>
<div className={styles.title}>
<b /> <span>ECCDSA359</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[0]}</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[1]}</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[2]}</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[3]}</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[4]}</span>
</div>
<div className={styles.title}>
<b /> <span>ECCDSA281</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[5]}</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[6]}</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[7]}</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[8]}</span>
</div>
<div className={styles.row}>
<span></span>
<span>{result?.[9]}</span>
</div>
<Row justify="end">
<Button
onClick={() => {
dispatch({
type: 'basic/setCertificateInfo',
payload: { step: 3 },
});
}}
type="primary"
ghost
>
</Button>
<Button type="primary" ghost className="ml20" onClick={handleClick}>
</Button>
</Row>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,4 @@
.page {
background-color: #fff;
margin-top: 20px;
}

@ -0,0 +1,18 @@
import styles from './index.less';
import { FC } from 'react';
import Step1 from './Step1';
import Step2 from './Step2';
import Step3 from './Step3';
import Step4 from './Step4';
const Page: FC<{}> = () => {
return (
<div className={styles.page}>
<Step1 />
<Step2 />
<Step3 />
<Step4 />
</div>
);
};
export default Page;

@ -0,0 +1,56 @@
.page {
background-color: #fff;
padding: 40px 0;
.wrap {
width: 1200px;
margin: 0 auto;
}
sup {
color: red;
margin-top: 10px;
margin-right: 4px;
font-size: 14px;
}
.name {
display: flex;
align-items: center;
margin-bottom: 32px;
b {
width: 6px;
height: 20px;
background: #464f66;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 24px;
font-weight: 500;
color: #232b40;
}
}
.status {
font-size: 14px;
font-weight: 500;
color: #464f66;
margin-bottom: 30px;
span {
color: #e30000;
}
}
.box3 {
border-top: 1px solid #e3e4e6;
border-bottom: 1px solid #e3e4e6;
margin-top: 20px;
padding-top: 20px;
padding-bottom: 20px;
}
}

@ -0,0 +1,333 @@
import styles from './index.less';
import { message, Input, Button, Row, Modal, Select, Tabs } from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC } from 'react';
import {
connect,
ConnectProps,
Dispatch,
BasicInfoModelState,
history,
} from 'umi';
import { cloneDeep } from 'lodash';
import { getInitData } from '@/utils/util';
interface PageProps extends ConnectProps {
basic: BasicInfoModelState;
dispatch: Dispatch;
match: any;
}
const Page: FC<PageProps> = ({ basic, dispatch }) => {
const { basicInfo } = basic;
const [uploadDisabled, setUploadDisabled] = useState<boolean>(false);
const {
type,
dataName,
nodeName,
deviceNo,
supportUnit,
managerNode,
file1,
file2,
file3,
file4,
} = basicInfo;
const btnDisabled =
dataName &&
nodeName &&
deviceNo &&
supportUnit &&
managerNode &&
file1?.name &&
file2?.name &&
file3?.name &&
file4?.name;
console.log(basicInfo, 'basicInfo');
const handleFile = (type: string) => {
var inputObj = document.createElement('input');
inputObj.setAttribute('id', '_ef');
inputObj.setAttribute('type', 'file');
inputObj.setAttribute('style', 'visibility:hidden');
document.body.appendChild(inputObj);
inputObj.click();
inputObj.onchange = (e: any) => {
dispatch({
type: 'basic/setActionData',
payload: {
[type]: {
file: e?.target?.files?.[0],
path: inputObj.value,
},
},
});
};
};
const handleInput = (type: string, value: string) => {
dispatch({
type: 'basic/setActionData',
payload: {
[type]: value,
},
});
};
const uploadFile = async () => {
const data: any = new FormData();
data.append('files', file1.file);
data.append('files', file2.file);
data.append('files', file3.file);
data.append('files', file4.file);
const res = await Fetch('/openi/resource/importFiles', {
method: 'post',
data,
});
if (res.result === 'success') {
message.success('上传成功');
const data = res?.data?.[0];
dispatch({
type: 'basic/setActionData',
payload: {
file1: {
file: file1.file,
name: data[0],
},
file2: {
file: file2.file,
name: data[1],
},
file3: {
file: file3.file,
name: data[2],
},
file4: {
file: file4.file,
name: data[3],
},
},
});
setUploadDisabled(true);
}
};
const open = async () => {
const sendData: any = cloneDeep(basicInfo);
sendData.type = Number(sendData.type);
sendData.file1 = sendData.file1.name;
sendData.file2 = sendData.file2.name;
sendData.file3 = sendData.file3.name;
sendData.file4 = sendData.file4.name;
delete sendData.cert;
delete sendData.resource;
const res = await Fetch('/openi/resource/openResourceNow', {
method: 'post',
data: sendData,
});
if (res.result === 'success') {
message.success('成功开通设施管理设备');
history.replace('/basic');
}
};
return (
<div className={styles.page}>
<div className={styles.wrap}>
<div className={styles.name}>
{' '}
<b /> <span></span>
</div>
<div className={styles.status}>
<span>{'未开通'}</span>
</div>
<Tabs
activeKey={type}
onChange={(k: string) => {
dispatch({
type: 'basic/setActionData',
payload: { type: k },
});
}}
>
<Tabs.TabPane key={'1'} tab="总部级" />
<Tabs.TabPane key={'2'} tab="大单位级别" />
</Tabs>
<div style={{ margin: '20px 0', fontWeight: 'bold', color: '#464F66' }}>
</div>
<Row align="middle">
<Row align="middle" className="mr40">
<sup>*</sup>
<span></span>
<Input
value={dataName}
onChange={(e) => handleInput('dataName', e.target.value)}
size="large"
style={{ width: 255, margin: '20px 10px' }}
/>
</Row>
<Row align="middle">
<sup>*</sup>
<span></span>
<Input
value={deviceNo}
onChange={(e) => handleInput('deviceNo', e.target.value)}
size="large"
style={{ width: 255, margin: '20px 10px' }}
/>
</Row>
</Row>
<Row align="middle">
<Row align="middle" className="mr40">
<sup>*</sup>
<span></span>
<Input
value={nodeName}
onChange={(e) => handleInput('nodeName', e.target.value)}
size="large"
style={{ width: 255, margin: '20px 10px' }}
/>
</Row>
<Row align="middle">
<sup>*</sup>
<span></span>
<Select
size="large"
value={supportUnit}
onChange={(k: any) => {
handleInput('supportUnit', k);
}}
style={{ width: 255, margin: '20px 10px' }}
>
{getInitData('supportUnitList')?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</Row>
</Row>
<Row align="middle">
<Row align="middle" className="mr40">
<sup>*</sup>
<span></span>
<Select
size="large"
value={managerNode}
onChange={(k: any) => {
handleInput('managerNode', k);
}}
style={{ width: 255, margin: '20px 10px' }}
>
{getInitData('managerNodeList')?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</Row>
</Row>
<div className={styles.box3}>
<Button
onClick={uploadFile}
disabled={
!(file1?.file && file2?.file && file3?.file && file4?.file)
}
type="primary"
>
</Button>
<Row align="middle">
<Row align="middle" className="mr40">
<sup>*</sup>
<span>64</span>
<Input
readOnly
value={file1?.name || file1?.path}
size="large"
style={{ width: 255, margin: '20px 10px' }}
/>
<Button
disabled={uploadDisabled}
onClick={() => handleFile('file1')}
type="primary"
ghost
size="large"
>
{!!file1?.file ? '已选择' : '浏览'}
</Button>
</Row>
<Row align="middle">
<sup>*</sup>
<span>32</span>
<Input
readOnly
value={file2?.name || file2?.path}
size="large"
style={{ width: 255, margin: '20px 10px' }}
/>
<Button
disabled={uploadDisabled}
onClick={() => handleFile('file2')}
type="primary"
ghost
size="large"
>
{!!file2?.file ? '已选择' : '浏览'}
</Button>
</Row>
</Row>
<Row align="middle">
<Row align="middle" className="mr40">
<sup>*</sup>
<span>20</span>
<Input
readOnly
value={file3?.name || file3?.path}
size="large"
style={{ width: 255, margin: '20px 10px' }}
/>
<Button
disabled={uploadDisabled}
onClick={() => handleFile('file3')}
type="primary"
ghost
size="large"
>
{!!file3?.file ? '已选择' : '浏览'}
</Button>
</Row>
<Row align="middle">
<sup>*</sup>
<span>16</span>
<Input
readOnly
value={file4?.name || file4?.path}
size="large"
style={{ width: 255, margin: '20px 10px' }}
/>
<Button
disabled={uploadDisabled}
onClick={() => handleFile('file4')}
type="primary"
ghost
size="large"
>
{!!file4?.file ? '已选择' : '浏览'}
</Button>
</Row>
</Row>
</div>
<Button
onClick={open}
disabled={!btnDisabled}
className="mt20"
type="primary"
>
</Button>
</div>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,134 @@
.login {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
overflow: hidden;
.left {
width: 480px;
height: 400px;
background: #fff;
box-shadow: 0px 10px 28px 2px rgba(231, 231, 231, 0.5);
border-radius: 8px;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
.name {
display: flex;
align-items: center;
margin-top: 42px;
margin-bottom: 52px;
b {
width: 6px;
height: 20px;
background: #165dff;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 24px;
font-weight: 500;
color: #232b40;
}
}
.status {
font-size: 14px;
font-weight: 500;
color: #464f66;
span {
color: #e30000;
}
}
.btn {
width: 240px;
height: 40px;
border-radius: 4px;
cursor: pointer;
text-align: center;
font-size: 14px;
font-weight: 400;
margin-top: 52px;
}
.tip {
font-size: 14px;
color: #fa6400;
position: absolute;
z-index: 2;
left: 0;
bottom: -45px;
width: 1400px;
}
}
> aside {
width: 56px;
height: 34px;
color: #165dff;
font-size: 26px;
padding-left: 7px;
}
.right {
width: 480px;
height: 400px;
background: #fff;
box-shadow: 0px 10px 28px 2px rgba(231, 231, 231, 0.5);
border-radius: 8px;
display: flex;
flex-direction: column;
align-items: center;
.name {
display: flex;
align-items: center;
margin-top: 42px;
margin-bottom: 52px;
b {
width: 6px;
height: 20px;
background: #165dff;
border-radius: 4px;
display: inline-block;
margin-right: 4px;
}
span {
font-size: 24px;
font-weight: 500;
color: #232b40;
}
}
.status {
font-size: 14px;
font-weight: 500;
color: #464f66;
span {
color: #e30000;
}
}
.btn {
width: 240px;
height: 40px;
border-radius: 4px;
cursor: pointer;
text-align: center;
font-size: 14px;
font-weight: 400;
margin-top: 22px;
margin-bottom: 20px;
}
}
}

@ -0,0 +1,229 @@
import styles from './index.less';
import { Select, Input, Button, Row, Modal, Form, message } from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC } from 'react';
import {
connect,
ConnectProps,
Dispatch,
BasicInfoModelState,
history,
} from 'umi';
import { downLoadLink } from '@/utils/download';
import url from '@/utils/url';
import { getInitData } from '@/utils/util';
interface PageProps extends ConnectProps {
basic: BasicInfoModelState;
dispatch: Dispatch;
match: any;
}
const Page: FC<PageProps> = ({ basic, dispatch }) => {
const [visible, setVisible] = useState<boolean>(false);
const [certSign, setCertSign] = useState<boolean>(false);
const [form] = Form.useForm();
const { basicInfo, certificateInfo } = basic;
const { dbUser, dbPasswd, dbServerIp, resource, cert } = basicInfo;
const { company } = certificateInfo;
const isResource = resource === '已开通' || resource === '';
const isCert = cert === '已开通' || cert === '';
console.log(certificateInfo, 'certificateInfo');
useEffect(() => {
getData();
}, []);
const getData = async () => {
const res = await Fetch('/openi/resource/getResourceStatus');
if (res.result === 'success') {
document.title = '设施管理设备';
if (res?.data?.[0]?.resource && res?.data?.[0]?.cert) {
// message.warn('当前设备已开通,已为你跳转至管理设备界面!');
history.replace('/equipment');
return;
}
dispatch({
type: 'basic/setActionData',
payload: {
resource: res?.data?.[0]?.resource ? '已开通' : '未开通',
cert: res?.data?.[0]?.cert ? '已开通' : '未开通',
},
});
}
};
const open = async () => {
const res = await Fetch.post('/openi/resource/clickOpenResource');
if (res.result === 'success') {
form.setFieldsValue({ dbUser, dbPasswd, dbServerIp });
setVisible(true);
}
};
const certificateOpen = async () => {
if (!company) {
message.warn('选择单位不能为空');
return;
}
if (!certSign) {
message.warn('请先下载证书');
return;
}
const res = await Fetch.post('/openi/resource/openCertSystem');
if (res.result === 'success') {
history.replace('/basic/certificate');
}
};
const handleFinish = (v: any) => {
const { dbUser, dbPasswd, dbServerIp } = v;
dispatch({
type: 'basic/setActionData',
payload: { dbUser, dbPasswd, dbServerIp },
});
setVisible(false);
history.replace('/basic/device');
};
return (
<div className={styles.login}>
<div className={styles.left}>
<div className={styles.name}>
<b />
<span></span>
</div>
<div className={styles.status}>
<span>{resource}</span>
</div>
<Button
disabled={isResource}
type="primary"
onClick={open}
className={styles.btn}
>
</Button>
<div className={styles.tip}>
</div>
</div>
<aside className="iconfont icon-jiantou" />
<div className={styles.right}>
<div className={styles.name}>
<b />
<span></span>
</div>
<div className={styles.status}>
<span>{cert}</span>
</div>
<Button
type="primary"
disabled={isCert}
onClick={certificateOpen}
className={styles.btn}
>
</Button>
<div style={{ marginLeft: -66 }}>
<span></span>
<Select
disabled={isCert}
size="large"
value={company}
onChange={(k: any) => {
dispatch({
type: 'basic/setCertificateInfo',
payload: { company: k },
});
}}
style={{ width: 240, marginLeft: 10 }}
>
{getInitData('firstUnitList')?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</div>
<Row align="middle">
<Button
onClick={() => {
setCertSign(true);
downLoadLink(url + '/openi/resource/downloadCertFile');
}}
className="mt20"
style={{ width: 240 }}
type="primary"
ghost
disabled={isCert}
size="large"
>
</Button>
</Row>
</div>
<Modal
centered
title="填写用户信息"
visible={visible}
okText="保存"
cancelText="取消"
onOk={() => {
form.submit();
}}
onCancel={() => {
setVisible(false);
}}
>
<Form
form={form}
layout="horizontal"
onFinish={handleFinish}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="数据库用户名"
name="dbUser"
rules={[
{
required: true,
message: `请输入数据库用户名`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="数据库密码"
name="dbPasswd"
rules={[
{
required: true,
message: `请输入数据库密码`,
},
]}
>
<Input.Password autoComplete="new-password" />
</Form.Item>
<Form.Item
label="数据库服务器IP地址"
name="dbServerIp"
rules={[
{
required: true,
message: `请输入数据库服务器IP地址`,
},
]}
>
<Input />
</Form.Item>
</Form>
</Modal>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,57 @@
.head {
height: 60px;
background: #001628;
> section {
margin: 0 auto;
height: 100%;
font-size: 18px;
display: flex;
align-items: center;
color: #fff;
width: 1200px;
> span {
font-size: 18px;
font-weight: 500;
color: #ffffff;
line-height: 18px;
letter-spacing: 2px;
}
> ul {
margin: 0;
padding: 0;
flex: 1;
display: flex;
align-items: center;
li {
list-style: none;
margin-left: 100px;
font-size: 14px;
font-weight: 600;
color: #28b1ff;
position: relative;
cursor: default;
}
b {
position: absolute;
z-index: 1;
left: 50%;
transform: translateX(-50%);
bottom: -9px;
width: 40px;
height: 2px;
background: #28b1ff;
}
}
}
}
.content {
height: calc(100vh - 60px);
background-color: #fafafa;
overflow: auto;
}

@ -0,0 +1,38 @@
//此文件已废弃
//保留只是为了做参照
import styles from './index.less';
import { Fragment } from 'react';
const Header = ({ ...props }) => {
const menu = [
{
id: 1,
name: '基础设施开通',
},
// {
// id: 2,
// name: '基础设施开通2',
// }
];
return (
<Fragment>
<div className={styles.head}>
<section>
<i className="iconfont icon-a-dashujushujujiegouguanxiguanxifenxigongtonglianxirenzuzhi1 mr10 font26" />
<span></span>
<ul>
{menu.map((e: any) => (
<li key={e.id}>
<span>{e.name}</span>
<b />
</li>
))}
</ul>
<div className="font14">V0.4.0.0</div>
</section>
</div>
<div className={styles.content}>{props.children}</div>
</Fragment>
);
};
export default Header;

@ -0,0 +1,136 @@
.page {
width: 1200px;
margin: 22px auto;
display: flex;
justify-content: space-between;
.left {
width: 146px;
height: 334px;
background: #ffffff;
border-radius: 4px;
padding-top: 18px;
> div {
height: 44px;
display: flex;
align-items: center;
font-size: 16px;
font-weight: 400;
color: #464f66;
padding: 20px 0;
cursor: pointer;
b {
display: inline-block;
width: 3px;
height: 16px;
background: @primary-color;
margin-right: 10px;
visibility: hidden;
}
&:hover {
color: @primary-color;
}
i {
padding-right: 10px;
font-size: 16px;
}
}
.active {
color: @primary-color;
b {
visibility: visible;
}
i {
color: @primary-color;
}
}
}
.right {
width: 1034px;
border-radius: 4px;
.info {
background: #ffffff;
border-radius: 4px;
.name {
width: 250px;
height: 36px;
border-radius: 4px 4px 0 0;
background: #eef2f8;
line-height: 48px;
font-size: 14px;
font-weight: 500;
color: #165dff;
text-align: center;
}
.wrap {
background: #eef2f8;
padding: 20px;
display: flex;
align-items: center;
justify-content: center;
> aside {
width: 994px;
background: #ffffff;
padding-bottom: 40px;
> div:nth-child(1) {
height: 36px;
background: #98bdf7;
line-height: 36px;
text-align: center;
font-size: 14px;
font-weight: 400;
color: #232b40;
}
> div:nth-child(2),
> div:nth-child(3),
> div:nth-child(4) {
display: flex;
margin-top: 40px;
margin-left: 40px;
align-items: center;
sup {
color: red;
margin-top: 10px;
margin-right: 4px;
}
> span {
font-size: 14px;
color: #464f66;
margin-right: 10px;
}
}
}
}
}
.annotation {
background: #eef2f8;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px 20px 20px;
sup {
color: red;
margin-top: 10px;
margin-right: 4px;
}
}
}
}

@ -0,0 +1,208 @@
import styles from './index.less';
import {
InputNumber,
Input,
Button,
Select,
Row,
Modal,
Form,
message,
Empty,
Spin,
} from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, useRef } from 'react';
import { Link, history, connect, BasicInfoModelState } from 'umi';
import { downLoadLink } from '@/utils/download';
import url from '@/utils/url';
import { getInitData } from '@/utils/util';
interface PageProps {}
const Page: FC<PageProps> = () => {
const [type, setType] = useState<string>('1');
const [algorithm, setAlgorithm] = useState<string>('');
const [length, setLength] = useState<any>('');
const [file, setFile] = useState<any>([]);
const item: any = [
{
icon: 'iconfont icon-yuzhimiyuejiami',
name: '预制密钥加密',
key: '1',
},
{
icon: 'iconfont icon-chanshenggongsiyuedui',
name: '产生公私钥对',
key: '2',
},
{
icon: 'iconfont icon-suanfacanshujiami',
name: '算法参数加密',
key: '3',
},
{
icon: 'iconfont icon-suanfaluojijiami',
name: '算法逻辑加密',
key: '4',
},
{
icon: 'iconfont icon-mimaruanjianjiami',
name: '密码软件加密',
key: '5',
},
];
const handleFile = () => {
var inputObj = document.createElement('input');
inputObj.setAttribute('id', '_ef');
inputObj.setAttribute('type', 'file');
inputObj.setAttribute('style', 'visibility:hidden');
inputObj.setAttribute('multiple', 'multiple');
document.body.appendChild(inputObj);
inputObj.click();
inputObj.onchange = async (e: any) => {
setFile(e?.target?.files);
};
};
const upload = async () => {
if (!file.length) {
message.warn('请选择导入文件');
return;
}
if (type !== '2' && !length) {
message.warn('请输入密钥长度');
return;
}
if (type === '2' && !algorithm) {
message.warn('请输入算法类型');
return;
}
let item = undefined;
for (let i = 0; i < file.length; i++) {
if (file[i].name === '数据文件.txt') {
item = file[i];
break;
}
}
if (item) {
var reader = new FileReader();
reader.readAsText(file[0], 'UTF-8');
reader.onload = function (e: any) {
let val = e.target.result;
try {
val = JSON.parse(val);
if (val.count !== undefined) {
downLoadLink(
`${url}/openi/secretKey/encryption?type=${type}&algorithm=${algorithm}&length=${length}&count=${val.count}`,
);
} else {
message.warn('数据文件内容格式错误,请重新导入!');
}
} catch (s) {
message.warn('数据文件内容格式错误,请重新导入!');
}
};
} else {
message.warn('导入文件没有包含数据文件(数据文件.txt),请重新导入!');
}
};
const renderText = () => {
let text: string = '';
file.forEach((e: any) => {
text = text + e.name + ';';
});
return text;
};
const title = item.find((e: any) => e.key === type).name;
return (
<div className={styles.page}>
<div className={styles.left}>
{item.map((e: any) => (
<div
key={e.key}
className={type === e.key ? styles.active : ''}
onClick={() => {
setType(e.key);
setLength('');
setFile([]);
setAlgorithm('');
}}
>
<b />
<i className={e.icon} />
{e.name}
</div>
))}
</div>
<div className={styles.right}>
<div className={styles.info}>
<div className={styles.name}>{title}</div>
<div className={styles.wrap}>
<aside>
<div> </div>
<div>
<sup>*</sup>
<span></span>
<Input value={renderText()} readOnly style={{ width: 700 }} />
<Button
onClick={handleFile}
className="ml10"
type="primary"
ghost
>
</Button>
</div>
{type === '2' && (
<div>
<sup>*</sup>
<span></span>
<Select
value={algorithm}
onChange={(k) => setAlgorithm(k)}
style={{ width: 400 }}
>
{getInitData('algorithmList')?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</div>
)}
{type !== '2' && (
<div>
<sup>*</sup>
<span></span>
<Select
value={length}
onChange={(k) => setLength(k)}
style={{ width: 400 }}
>
{getInitData('keyLengthList')?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</div>
)}
</aside>
</div>
<div className={styles.annotation}>
<span>
<sup>*</sup>
</span>
<Button onClick={upload} type="primary">
{title}
</Button>
</div>
</div>
</div>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,66 @@
.head {
height: 60px;
background: #001628;
> section {
margin: 0 auto;
height: 100%;
font-size: 18px;
display: flex;
align-items: center;
color: #fff;
width: 1200px;
> span {
font-size: 18px;
font-weight: 500;
color: #ffffff;
line-height: 18px;
letter-spacing: 2px;
}
> ul {
margin: 0;
padding: 0;
flex: 1;
display: flex;
align-items: center;
.active {
color: #28b1ff;
b {
visibility: visible;
}
}
li {
list-style: none;
margin-left: 100px;
font-size: 14px;
font-weight: 600;
color: #fff;
position: relative;
cursor: pointer;
}
b {
position: absolute;
z-index: 1;
left: 50%;
transform: translateX(-50%);
bottom: -9px;
width: 40px;
height: 2px;
background: #28b1ff;
visibility: hidden;
}
}
}
}
.content {
height: calc(100vh - 60px);
background-color: #fafafa;
overflow: auto;
}

@ -0,0 +1,82 @@
import styles from './index.less';
import { Fragment, useEffect } from 'react';
import { history } from 'umi';
import Fetch from '@/utils/fetch';
import { message } from 'antd';
const Header = ({ ...props }) => {
const pathname = props.location.pathname;
const menu = [
{
id: 11,
name: '用户操作',
url: '',
},
{
id: '/encrypt',
name: '原始密码资源加密',
url: '/encrypt',
},
{
id: '/equipment',
name: '基础设施开通',
url: '/equipment',
},
{
id: 22,
name: '审计信息',
url: '',
},
{
id: 33,
name: '系统设置',
url: '',
},
];
useEffect(() => {
getData();
}, []);
const getData = async () => {
//判断否跳转
const res = await Fetch('/openi/resource/getResourceStatus');
if (res.result === 'success') {
document.title = '设施密码管理设备';
if (!(res?.data?.[0]?.resource && res?.data?.[0]?.cert)) {
// message.warn('当前设备未开通,已为你跳转至开通界面!');
history.replace('/basic');
}
}
};
return (
<Fragment>
<div className={styles.head}>
<section>
<i className="iconfont icon-a-dashujushujujiegouguanxiguanxifenxigongtonglianxirenzuzhi1 mr10 font26" />
<span></span>
<ul>
{menu.map((e: any) => (
<li
className={pathname?.includes(e.id) ? styles.active : ''}
key={e.id}
onClick={() => {
if (e.url) {
history.push(e.url);
}
}}
>
<span>{e.name}</span>
<b />
</li>
))}
</ul>
<div className="font14">V0.4.0.0</div>
</section>
</div>
<div className={styles.content}>{props.children}</div>
</Fragment>
);
};
export default Header;

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

@ -0,0 +1,185 @@
.page {
height: 100vh;
background: url('./img/bg.png') no-repeat center center;
background-size: cover;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
.box {
width: 800px;
height: 400px;
background: #ffffff;
border-radius: 20px;
display: flex;
.left {
width: 380px;
height: 100%;
background: url('./img/l.png') no-repeat center center;
background-size: cover;
font-size: 20px;
font-weight: bold;
color: #ffffff;
letter-spacing: 2px;
text-align: center;
padding-top: 40px;
}
.right {
width: 420px;
height: 100%;
.one {
height: 100%;
display: flex;
align-items: center;
flex-direction: column;
> span {
width: 144px;
font-size: 24px;
font-weight: 600;
color: #464f66;
margin-top: 80px;
}
div {
color: #e30000;
font-size: 16px;
font-weight: bold;
margin-top: 32px;
i {
margin-right: 10px;
}
}
button {
margin-top: 82px;
width: 240px;
height: 40px;
// background: #165dff;
border-radius: 4px;
margin-bottom: 20px;
}
aside {
font-size: 14px;
font-weight: 400;
color: #464f66;
}
}
.two {
height: 100%;
display: flex;
align-items: center;
flex-direction: column;
> span {
font-size: 24px;
font-weight: 600;
color: #464f66;
margin-top: 80px;
}
div {
width: 340px;
font-size: 14px;
color: #464f66;
margin-top: 40px;
}
input {
width: 340px;
height: 40px;
}
button {
margin-top: 20px;
width: 340px;
height: 40px;
background: #165dff;
border-radius: 4px;
}
aside {
font-size: 14px;
font-weight: 400;
color: #464f66;
margin-top: 20px;
}
section {
width: 340px;
font-size: 14px;
color: #9096a3;
text-align: right;
margin-top: 36px;
}
}
.three {
height: 100%;
display: flex;
align-items: center;
flex-direction: column;
> span {
font-size: 24px;
font-weight: 600;
color: #464f66;
margin-top: 80px;
}
div {
width: 340px;
font-size: 14px;
color: #464f66;
margin-top: 40px;
}
p {
margin-bottom: 0px;
input {
width: 250px;
height: 40px;
}
> button {
width: 80px;
height: 40px;
border-radius: 4px;
margin-left: 10px;
}
}
> button {
margin-top: 20px;
width: 340px;
height: 40px;
background: #165dff;
border-radius: 4px;
}
aside {
font-size: 14px;
font-weight: 400;
color: #464f66;
margin-top: 20px;
}
section {
width: 340px;
font-size: 14px;
color: #9096a3;
text-align: right;
margin-top: 36px;
}
}
}
}
}

@ -0,0 +1,168 @@
import styles from './index.less';
import { message, Input, Button, Row, Modal, Form, Tabs } from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, Fragment } from 'react';
import {
connect,
ConnectProps,
Dispatch,
BasicInfoModelState,
history,
} from 'umi';
import { cloneDeep, divide } from 'lodash';
interface PageProps {}
const Page: FC<PageProps> = () => {
const [active, setActive] = useState<number>(1);
const [value, setValue] = useState<string>('');
const [file, setFile] = useState<any>(null);
const [disable, setDisable] = useState<boolean>(false);
useEffect(() => {
getData();
}, []);
const getData = async () => {
const res = await Fetch('/openi/dataCenter/isOpen');
if (res.result === 'success') {
document.title = '数据中心开通';
if (res?.data?.[0]) {
setDisable(true);
return;
}
}
};
const oneClick = async () => {
const res = await Fetch.post('/openi/dataCenter/startOpen');
if (res.result === 'success') {
setActive(2);
}
};
const twoClick = async () => {
if (!value) {
message.warn('物理标识不能为空');
return;
}
const res = await Fetch('/openi/dataCenter/setHostFlag', {
method: 'post',
params: {
hostFlag: value,
},
});
if (res.result === 'success') {
setActive(3);
}
};
const threeClick = async () => {
if (!file?.name) {
message.warn('初装资源不能为空');
return;
}
const data: any = new FormData();
data.append('file', file);
const res = await Fetch('/openi/dataCenter/resourceImport', {
method: 'post',
data,
});
if (res.errorCode === 500) {
message.error(res?.errorMsg);
return;
}
if (res.result === 'success') {
message.success('开通成功');
setDisable(true);
setActive(1);
}
};
const handleFile = () => {
var inputObj = document.createElement('input');
inputObj.setAttribute('id', '_ef');
inputObj.setAttribute('type', 'file');
inputObj.setAttribute('style', 'visibility:hidden');
document.body.appendChild(inputObj);
inputObj.click();
inputObj.onchange = (e: any) => {
setFile(e?.target?.files?.[0]);
};
};
const renderOne = () => {
return (
<div className={styles.one}>
<span></span>
{disable ? (
<div style={{ color: 'green' }}></div>
) : (
<div>
<i className="iconfont icon-weitongguo" />
</div>
)}
<Button disabled={disable} type="primary" onClick={oneClick}>
</Button>
<aside></aside>
</div>
);
};
const renderTwo = () => {
return (
<div className={styles.two}>
<span>宿</span>
<div></div>
<Input value={value} onChange={(e: any) => setValue(e.target.value)} />
<Button type="primary" onClick={twoClick}>
</Button>
<aside>宿便</aside>
{/* <section>开通过程共 6 步,当前第 1 步</section> */}
</div>
);
};
const renderThree = () => {
return (
<div className={styles.three}>
<span></span>
<div></div>
<p>
<Input
readOnly
value={file?.name || ''}
onChange={(e: any) => setValue(e.target.value)}
/>
<Button type="primary" ghost onClick={handleFile}>
</Button>
</p>
<Button type="primary" onClick={threeClick}>
</Button>
<aside></aside>
{/* <section>开通过程共 6 步,当前第 3 步</section> */}
</div>
);
};
return (
<div className={styles.page}>
<div className={styles.box}>
<div className={styles.left}></div>
<div className={styles.right}>
{active === 1 && renderOne()}
{active === 2 && renderTwo()}
{active === 3 && renderThree()}
</div>
</div>
</div>
);
};
export default Page;

@ -0,0 +1,205 @@
.page {
width: 1200px;
margin: 22px auto;
display: flex;
justify-content: space-between;
.left {
width: 146px;
height: 334px;
background: #ffffff;
border-radius: 4px;
padding-top: 18px;
> div {
height: 44px;
display: flex;
align-items: center;
font-size: 16px;
font-weight: 400;
color: #464f66;
padding: 20px 0;
cursor: pointer;
b {
display: inline-block;
width: 3px;
height: 16px;
background: @primary-color;
margin-right: 10px;
visibility: hidden;
}
&:hover {
color: @primary-color;
}
i {
padding-right: 10px;
font-size: 16px;
}
}
.active {
color: @primary-color;
b {
visibility: visible;
}
i {
color: @primary-color;
}
}
}
.right {
width: 1034px;
border-radius: 4px;
.info {
background: #ffffff;
border-radius: 4px;
.name {
width: 250px;
height: 36px;
border-radius: 4px 4px 0 0;
background: #eef2f8;
line-height: 48px;
font-size: 14px;
font-weight: 500;
color: #165dff;
text-align: center;
}
.wrap {
background: #eef2f8;
height: 196px;
padding: 20px;
display: flex;
align-items: center;
flex-direction: column;
// justify-content: center;
> aside {
width: 994px;
height: 124px;
background: #ffffff;
> div:first-child {
height: 36px;
background: #98bdf7;
line-height: 36px;
text-align: center;
font-size: 14px;
font-weight: 400;
color: #232b40;
}
}
> button {
margin-left: auto;
margin-top: 10px;
}
.li {
display: flex;
> div {
width: 50%;
padding: 16px;
color: #464f66;
span:first-child {
color: #9096a3;
margin-right: 10px;
}
}
> div:first-child {
border-right: 1px solid #e3effc;
}
}
}
}
.list {
margin-top: 10px;
.head {
height: 62px;
background: #ffffff;
border-radius: 4px 4px 0 0;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 10px;
div {
font-size: 14px;
font-weight: 500;
color: #464f66;
}
}
.content {
overflow: hidden;
background: #ffffff;
border-radius: 0 0 4px 4px;
padding: 0 20px 10px 20px;
> aside {
background: #ffffff;
> div:first-child {
height: 36px;
background: #e3effc;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
color: #232b40;
padding: 0 20px;
margin-top: 10px;
div {
color: @primary-color;
cursor: pointer;
i {
display: inline-block;
font-size: 14px;
transform: scale(0.7);
margin-right: 4px;
}
}
}
}
.li {
display: flex;
border: 1px solid #ebf3ff;
border-top: 0;
i {
font-size: 34px;
color: #a0a4f7;
padding: 16px 50px 16px 16px;
}
> div {
padding: 16px 80px 16px 16px;
color: #464f66;
span:first-child {
color: #9096a3;
margin-right: 10px;
}
}
}
}
}
}
}

@ -0,0 +1,489 @@
import styles from './index.less';
import {
Select,
Input,
Button,
Row,
Modal,
Form,
message,
Empty,
Spin,
} from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, useRef, Fragment } from 'react';
import {
connect,
ConnectProps,
Dispatch,
BasicInfoModelState,
history,
Link,
} from 'umi';
import { downLoadLink } from '@/utils/download';
import url from '@/utils/url';
interface PageProps extends ConnectProps {
basic: BasicInfoModelState;
dispatch: Dispatch;
match: any;
}
const Page: FC<PageProps> = ({ basic, dispatch }) => {
const [facilityList, setFacilityList] = useState<any[]>([]);
const [localList, setLocalList] = useState<any[]>([]);
const [firmList, setFirmList] = useState<any[]>([]);
const [packList, setPackList] = useState<any[]>([]);
const [visible, setVisible] = useState<any>(false);
const [type, setType] = useState<string>('1');
const [loading, setLoading] = useState<boolean>(true);
const [form] = Form.useForm();
const editId = useRef(null);
useEffect(() => {
getData('1');
getData('2');
getFirmList();
}, []);
const getData = async (type: string) => {
setLoading(true);
const res = await Fetch(
`/openi/${type === '1' ? 'dataCenter' : 'localManager'}/page`,
{
method: 'get',
params: {
type,
pageSize: 1000000,
pageNumber: 1,
},
},
);
if (res.result === 'success') {
const data = res?.data?.[0];
if (type === '1') {
setFacilityList(data.list || []);
} else {
setLocalList(data.list || []);
}
setPackList([]);
}
setLoading(false);
};
const getFirmList = async () => {
const res = await Fetch('/openi/producer/list');
if (res.result === 'success') {
const data = res?.data?.[0];
setFirmList(data);
}
};
const handleFinish = async (v: any) => {
const res = await Fetch(
`/openi/${visible === '1' ? 'dataCenter' : 'localManager'}/editOrAdd`,
{
method: 'post',
data: {
...v,
type: visible,
id: editId.current,
},
},
);
if (res.result === 'success') {
getData(visible);
setVisible(false);
}
};
const addList = (type: string) => {
setVisible(type);
};
const deleteList = (type: string, id: any) => {
Modal.confirm({
title: '提示',
okText: '确认',
cancelText: '取消',
content: '确认删除吗?',
onOk: async () => {
const res = await Fetch(
`/openi/${type === '1' ? 'dataCenter' : 'localManager'}/delete/${id}`,
{
method: 'post',
},
);
if (res.result === 'success') {
getData(type);
}
},
});
};
const editList = (type: string, param: any) => {
form.setFieldsValue({ ...param });
editId.current = param.id;
setVisible(type);
};
const pack = (id: any) => {
if (packList.includes(id)) {
setPackList(packList.filter((e: any) => e !== id));
} else {
setPackList([...packList, id]);
}
};
const item: any = [
{
icon: 'iconfont icon-shuju',
name: '数据中心',
key: '1',
},
{
icon: 'iconfont icon-jiedian',
name: '管理节点',
key: '2',
},
];
return (
<div className={styles.page}>
<div className={styles.left}>
{item.map((e: any) => (
<div
key={e.key}
className={type === e.key ? styles.active : ''}
onClick={() => {
if (e.key === '1') {
setType(e.key);
}
}}
>
<b />
<i className={e.icon} />
{e.name}
</div>
))}
</div>
<div className={styles.right}>
<div className={styles.info}>
<div className={styles.name}></div>
<div className={styles.wrap}>
<aside>
<div></div>
<div className={styles.li}>
<div>
<p>
<span></span>
<span>22</span>
</p>
<p>
<span></span>
<span></span>
</p>
</div>
<div>
<p>
<span></span>
<span></span>
</p>
<p>
<span></span>
<span>NO.88888888888</span>
</p>
</div>
</div>
</aside>
<Button type="primary"></Button>
</div>
</div>
<Spin spinning={loading}>
<div className={styles.list}>
<div className={styles.head}>
<div></div>
<Button onClick={() => addList('1')} type="primary" ghost>
</Button>
</div>
<div className={styles.content}>
{!facilityList.length && <Empty style={{ margin: '20px 0' }} />}
{!!facilityList.length &&
facilityList.map((e: any, i: number) => {
const bool = packList.includes(e.id);
return (
<aside key={i}>
<div>
<span>{e.name}</span>
<div onClick={() => pack(e.id)}>
{bool ? (
<>
<i className="iconfont icon-zhankaixiaojiantou" />
<span></span>
</>
) : (
<>
<i className="iconfont icon-shouqixiaojiantou" />
<span></span>
</>
)}
</div>
</div>
{!bool && (
<Fragment>
<div className={styles.li}>
<i className="iconfont icon-fuwuqi"></i>
<div>
<p>
<span></span>
<span>{e.physicsNum}</span>
</p>
<p>
<span></span>
<span>{e.number}</span>
</p>
</div>
<div>
<p>
<span></span>
<span>{e.managerNum}</span>
</p>
<p>
<span></span>
<span>{e.producerId}</span>
</p>
</div>
</div>
<Row justify="end" className="mt10 mb20">
<Button
onClick={() => editList('1', e)}
type="primary"
ghost
>
</Button>
<Button
onClick={() =>
downLoadLink(
url +
`/openi/dataCenter/resourceExport/${e.id}`,
)
}
className="ml10"
type="primary"
ghost
>
</Button>
<Button
onClick={() => deleteList('1', e.id)}
className="ml10"
type="primary"
danger
>
</Button>
</Row>
</Fragment>
)}
</aside>
);
})}
</div>
</div>
<div className={styles.list}>
<div className={styles.head}>
<div></div>
<Button onClick={() => addList('2')} type="primary" ghost>
</Button>
</div>
<div className={styles.content}>
{!localList.length && <Empty style={{ margin: '20px 0' }} />}
{!!localList.length &&
localList.map((e: any, i: number) => {
const bool = packList.includes(e.id);
return (
<aside key={i}>
<div>
<span>{e.name}</span>
<div onClick={() => pack(e.id)}>
{bool ? (
<>
<i className="iconfont icon-zhankaixiaojiantou" />
<span></span>
</>
) : (
<>
<i className="iconfont icon-shouqixiaojiantou" />
<span></span>
</>
)}
</div>
</div>
{!bool && (
<Fragment>
<div className={styles.li}>
<i className="iconfont icon-zhongduan"></i>
<div>
<p>
<span></span>
<span>{e.physicsNum}</span>
</p>
<p>
<span></span>
<span>{e.number}</span>
</p>
</div>
<div>
<p>
<span></span>
<span>{e.managerNum}</span>
</p>
<p>
<span></span>
<span>{e.producerId}</span>
</p>
</div>
</div>
<Row justify="end" className="mt10 mb20">
<Button
onClick={() => editList('2', e)}
type="primary"
ghost
>
</Button>
<Button
onClick={() =>
downLoadLink(
url +
`/openi/localManager/resourceExport/${e.id}`,
)
}
className="ml10"
type="primary"
ghost
>
</Button>
<Button
onClick={() => deleteList('2', e.id)}
className="ml10"
type="primary"
danger
>
</Button>
</Row>
</Fragment>
)}
</aside>
);
})}
</div>
</div>
</Spin>
</div>
<Modal
centered
title="新增设备"
visible={visible}
afterClose={() => {
form.resetFields();
editId.current = null;
}}
okText="保存"
cancelText="取消"
onOk={() => {
form.submit();
}}
onCancel={() => {
setVisible(false);
}}
>
<Form
form={form}
layout="horizontal"
colon={false}
onFinish={handleFinish}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="名称"
name="name"
rules={[
{
required: true,
message: `请输入名称`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="物理标识"
name="physicsNum"
rules={[
{
required: true,
message: `请输入物理标识`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="铭牌编码"
name="number"
rules={[
{
required: true,
message: `请输入铭牌编码`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="管理标识"
name="managerNum"
rules={[
{
required: true,
message: `请输入管理标识`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="生产厂商"
name="producerId"
rules={[
{
required: true,
message: `请输入生产厂商`,
},
]}
>
<Select>
{firmList?.map((e) => (
<Select.Option value={e.id} key={e.id}>
{e.name}
</Select.Option>
))}
</Select>
</Form.Item>
</Form>
</Modal>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 KiB

@ -0,0 +1,211 @@
.page {
height: 100vh;
background: url('./img/bg.png') no-repeat center center;
background-size: cover;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
.red {
color: #ff3f41;
}
.box {
width: 902px;
height: 611px;
background: #ffffff;
border-radius: 20px;
display: flex;
background: url('./img/c.png') no-repeat center center;
background-size: cover;
.one {
width: 100%;
height: 470px;
margin-top: 130px;
display: flex;
flex-direction: column;
align-items: center;
> div {
font-size: 16px;
font-weight: bold;
color: #ffffff;
margin-top: 50px;
padding-right: 110px;
}
aside {
display: flex;
margin-top: 50px;
font-size: 16px;
font-weight: bold;
color: #ffffff;
ul {
padding-left: 15px;
li {
list-style: none;
display: flex;
align-items: center;
margin-bottom: 20px;
cursor: pointer;
b {
display: inline-block;
width: 18px;
height: 18px;
background: #376042;
border: 2px solid #2fffdb;
border-radius: 50%;
margin-right: 10px;
}
.a {
position: relative;
&::after {
content: '';
width: 10px;
height: 10px;
position: absolute;
background-color: #2fffdb;
border-radius: 50%;
right: 2px;
top: 2px;
}
}
}
}
}
button {
width: 208px;
height: 42px;
background: rgba(22, 93, 255, 0.5);
border-radius: 4px;
}
> b {
color: #fff;
margin-top: 76px;
}
}
.two {
width: 100%;
height: 470px;
margin-top: 130px;
display: flex;
flex-direction: column;
align-items: center;
> span {
font-size: 22px;
font-weight: bold;
color: #ffffff;
margin-top: 38px;
}
> div {
font-size: 16px;
font-weight: bold;
color: #ffffff;
margin-top: 52px;
}
input {
width: 208px;
height: 40px;
border-radius: 4px;
border: 2px solid #2fffdb;
margin-top: 30px;
background-color: transparent;
color: #2fffdb;
}
button {
width: 208px;
height: 42px;
border-radius: 4px;
margin-top: 70px;
background: rgba(22, 93, 255, 0.5);
}
aside {
font-size: 16px;
font-weight: bold;
color: #ffffff;
margin-top: 66px;
}
}
.three {
width: 100%;
height: 470px;
margin-top: 130px;
display: flex;
flex-direction: column;
align-items: center;
> span {
font-size: 22px;
font-weight: bold;
color: #ffffff;
margin-top: 38px;
}
> div {
font-size: 16px;
font-weight: bold;
color: #ffffff;
margin-top: 52px;
}
p {
display: flex;
align-items: center;
margin-top: 10px;
input {
width: 160px;
height: 40px;
border-radius: 4px;
border: 2px solid #2fffdb;
background-color: transparent;
color: #2fffdb;
}
.btn {
width: 40px;
height: 40px;
background: #2fffdb;
border-radius: 4px;
border: 2px solid #2fffdb;
color: #10291d;
margin-left: 10px;
line-height: 38px;
text-align: center;
cursor: pointer;
}
}
> button {
width: 208px;
height: 42px;
border-radius: 4px;
margin-top: 70px;
background: rgba(22, 93, 255, 0.5);
}
aside {
font-size: 16px;
font-weight: bold;
color: #ffffff;
margin-top: 66px;
}
}
}
}

@ -0,0 +1,192 @@
import styles from './index.less';
import { message, Input, Button, Row, Modal, Form, Tabs } from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, Fragment } from 'react';
import {
connect,
ConnectProps,
Dispatch,
BasicInfoModelState,
history,
} from 'umi';
import { cloneDeep } from 'lodash';
interface PageProps {}
const Page: FC<PageProps> = () => {
const [active, setActive] = useState<number>(1);
const [value, setValue] = useState<string>('');
const [file, setFile] = useState<any>(null);
const [terminalType, setTerminalType] = useState<string>('');
useEffect(() => {
getData();
}, []);
const getData = async () => {
const res = await Fetch('/openi/localManager/isOpen');
if (res.result === 'success') {
document.title = '管理基础设施';
if (res?.data?.[0]) {
// message.warn('当前本地管理终端已开通,已为你跳转至管理基础设施界面!');
history.replace('/manager/passwordManager');
return;
}
}
};
const oneClick = async () => {
if (!terminalType) {
message.warn('请选择终端类型');
return;
}
const res = await Fetch('/openi/localManager/startOpen', {
method: 'post',
data: {
terminalType,
},
});
if (res.result === 'success') {
setActive(2);
}
};
const twoClick = async () => {
if (!value) {
message.warn('物理标识不能为空');
return;
}
const res = await Fetch('/openi/localManager/setHostFlag', {
method: 'post',
params: {
hostFlag: value,
},
});
if (res.result === 'success') {
setActive(3);
}
};
const threeClick = async () => {
if (!file?.name) {
message.warn('初装资源不能为空');
return;
}
const data: any = new FormData();
data.append('file', file);
const res = await Fetch('/openi/localManager/resourceImport', {
method: 'post',
data,
});
if (res.errorCode === 500) {
message.error(res?.errorMsg);
return;
}
if (res.result === 'success') {
message.success('操作成功');
history.replace('/manager/passwordManager');
}
};
const handleFile = () => {
var inputObj = document.createElement('input');
inputObj.setAttribute('id', '_ef');
inputObj.setAttribute('type', 'file');
inputObj.setAttribute('style', 'visibility:hidden');
document.body.appendChild(inputObj);
inputObj.click();
inputObj.onchange = (e: any) => {
setFile(e?.target?.files?.[0]);
};
};
const items = [
{
name: '远程管理终端',
},
{
name: '本地管理终端',
},
{
name: '初装设备',
},
];
const renderOne = () => {
return (
<div className={styles.one}>
<div>
<span className="mr15"></span>
<span className={styles.red}></span>
</div>
<aside>
<span></span>
<ul>
{items.map((e: any) => (
<li key={e.name} onClick={() => setTerminalType(e.name)}>
<b className={terminalType === e.name ? styles.a : ''} />
<span>{e.name}</span>
</li>
))}
</ul>
</aside>
<Button onClick={oneClick} type="primary">
</Button>
<b>
<span className={styles.red}></span>/
<span className={styles.red}></span>/
<span className={styles.red}></span>
</b>
</div>
);
};
const renderTwo = () => {
return (
<div className={styles.two}>
<span>宿</span>
<div>宿</div>
<Input value={value} onChange={(e: any) => setValue(e.target.value)} />
<Button type="primary" onClick={twoClick}>
</Button>
<aside>宿便</aside>
</div>
);
};
const renderThree = () => {
return (
<div className={styles.three}>
<span></span>
<div></div>
<p>
<Input
readOnly
value={file?.name || ''}
onChange={(e: any) => setValue(e.target.value)}
/>
<div className={styles.btn} onClick={handleFile}>
</div>
</p>
<Button type="primary" onClick={threeClick}>
</Button>
<aside>宿便</aside>
</div>
);
};
return (
<div className={styles.page}>
<div className={styles.box}>
{active === 1 && renderOne()}
{active === 2 && renderTwo()}
{active === 3 && renderThree()}
</div>
</div>
);
};
export default Page;

@ -0,0 +1,13 @@
import { Button, Result } from 'antd';
import React from 'react';
const App: React.FC = () => (
<Result
status="404"
title="404"
subTitle="抱歉,你访问的页面不存在"
// extra={<Button type="primary"></Button>}
/>
);
export default App;

@ -0,0 +1,53 @@
.page {
.title {
height: 36px;
background: #e3effc;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
font-weight: 500;
color: #464f66;
i {
cursor: pointer;
}
}
.btn {
padding: 20px 20px 0 0;
i {
font-size: 14px;
margin-right: 5px;
}
}
}
.action {
cursor: pointer;
color: #6b758b;
padding: 0 10px;
&:hover {
color: @primary-color;
}
}
.name {
display: flex;
align-items: center;
b {
display: inline-block;
width: 5px;
height: 5px;
background: #464f66;
border-radius: 50%;
margin-right: 5px;
}
span {
font-size: 14px;
color: #232b40;
}
}

@ -0,0 +1,599 @@
import styles from './index.less';
import {
Button,
Select,
Row,
Modal,
Form,
message,
Empty,
Table,
DatePicker,
Input,
Col,
} from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, useRef } from 'react';
import { downLoadLink } from '@/utils/download';
import url from '@/utils/url';
import moment from 'moment';
import { ColumnsType } from 'antd/lib/table';
import { getInitData } from '@/utils/util';
import { Link, BasicInfoModelState, connect } from 'umi';
const RangePicker: any = DatePicker.RangePicker;
interface PageProps {}
const Page: FC<PageProps> = () => {
const distributionNode = getInitData('distributionNodeList');
const [data, setData] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(true);
const [total, setTotal] = useState<number>(0);
//编辑新增弹框
const [visible, setVisible] = useState<boolean>(false);
const [modalData, setModalData] = useState<any>([]);
// const [selectKey, setSelectKey] = useState<any>([]);
//选择设备弹框
const [facilityVisible, setFacilityVisible] = useState<boolean>(false);
const [facilityData, setFacilityData] = useState<any>([]);
const [facilityKey, setFacilityKey] = useState<any>([]);
const [facilityKeyData, setFacilityKeyData] = useState<any>([]);
const [form] = Form.useForm();
const [formInquire] = Form.useForm();
const [formFacility] = Form.useForm();
let [params, setParams] = useState<any>({
pageNumber: 1,
pageSize: 20,
type: '2',
status: '',
time: '',
startDate: '',
endDate: '',
});
const editId = useRef(null);
useEffect(() => {
getData(params);
}, []);
const getFacilityData = async (record: any) => {
const res = await Fetch('/openi/device/page', {
method: 'get',
params: {
pageNumber: 1,
pageSize: 100000,
...record,
},
});
if (res.result === 'success') {
const item = res?.data?.[0]?.list?.filter((e: any) => e.status !== '0');
setFacilityData(item);
}
};
const getData = async (record: any) => {
setLoading(true);
const { time, ...sendData } = record;
const res = await Fetch('/openi/deviceDistribution/page', {
method: 'get',
params: sendData,
});
if (res.result === 'success') {
setData(res?.data?.[0]?.list);
setTotal(res?.data?.[0]?.total);
}
setLoading(false);
};
const columns: ColumnsType<any> = [
{
title: '序号',
align: 'center',
dataIndex: 'index',
render: (text: string, record: any, index: number) =>
params.pageSize * (params.pageNumber - 1) + index + 1,
},
{
width: 220,
title: '调拨单编号',
dataIndex: 'number',
},
{
width: 220,
title: '调拨单时间',
dataIndex: 'beginTime',
},
{
title: '调拨单节点',
dataIndex: 'sendNode',
},
{
title: '状态',
dataIndex: 'status',
render: (v: any, r: any) =>
v === '1' ? (
<span style={{ color: 'green' }}></span>
) : (
<span></span>
),
},
{
title: '依据',
dataIndex: 'basis',
},
{
title: '设备数量/(台)',
dataIndex: 'deviceCount',
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: 110,
render: (v: any, r: any) => (
<span>
<i
onClick={() => handleEdit(r)}
title="修改"
className={'iconfont icon-xiugaikucundixian ' + styles.action}
/>
<i
onClick={() => handleDelete(r.id)}
title="删除"
className={'iconfont icon-shanchuzhuangbeixinghao ' + styles.action}
/>
</span>
),
},
];
const modalColumns: ColumnsType<any> = [
{
title: '序号',
align: 'center',
width: 90,
dataIndex: 'index',
render: (_: string, __: any, index: number) => index + 1,
},
{
title: '装备型号',
dataIndex: 'deviceType',
render: (v: any) => v?.name,
},
{
title: '装备名称',
dataIndex: 'name',
},
{
title: '铭牌编号',
dataIndex: 'deviceId',
},
{
title: '管理标识',
dataIndex: 'sign',
render: (v: any) => v || '--',
},
{
title: '生产厂商',
dataIndex: 'producer',
render: (v: any) => v?.name,
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
render: (v: any, r: any) => (
<span>
<i
onClick={() => {
setModalData(modalData.filter((e: any) => e.id !== r.id));
}}
title="删除"
className={'iconfont icon-shanchuzhuangbeixinghao ' + styles.action}
/>
</span>
),
},
];
const handleChangePage = (param: any) => {
params.pageNumber = param?.current;
params.pageSize = param?.pageSize;
setParams({ ...params });
getData(params);
};
const handleFinish = async (v: any) => {
if (modalData.length === 0) {
message.warn('请选择配发设备');
return;
}
const res = await Fetch(`/openi/deviceDistribution/editOrAdd`, {
method: 'post',
data: {
...v,
type: '2',
deviceList: modalData.map((e: any) => ({ id: e.id })),
id: editId.current,
},
});
if (res.result === 'success') {
params.pageNumber = editId.current ? params.pageNumber : 1;
setParams({ ...params });
getData(params);
setVisible(false);
}
};
//按钮查询
const handleInquire = async (v: any) => {
params = { ...params, ...v };
if (v.time) {
params.startDate = moment(v?.time?.[0]).format('YYYY-MM-DD HH:mm:ss');
params.endDate = moment(v?.time?.[1]).format('YYYY-MM-DD HH:mm:ss');
}
console.log(v, params, 222);
setParams({ ...params });
getData(params);
};
const handleFacility = async (v: any) => {
getFacilityData(v);
};
const handleEdit = (param: any) => {
form.setFieldsValue({ ...param });
setModalData(param?.deviceList);
editId.current = param.id;
setVisible(true);
};
const handleDelete = (id: any) => {
Modal.confirm({
title: '提示',
okText: '确认',
cancelText: '取消',
content: '确认删除吗?',
onOk: async () => {
const res = await Fetch(`/openi/deviceDistribution/delete/${id}`, {
method: 'post',
});
if (res.result === 'success') {
const page =
1 === data.length && params.pageNumber > 1
? params.pageNumber - 1
: params.pageNumber;
params.pageNumber = page;
setParams({ ...params });
getData(params);
}
},
});
};
return (
<div className={styles.page}>
<div className={styles.title}>
<span></span>
<i
onClick={() => getData(params)}
className="iconfont icon-a-shuaxin2"
/>
</div>
<Row justify="space-between" className={styles.btn}>
<Form
form={formInquire}
colon={false}
layout="inline"
onFinish={handleInquire}
initialValues={{
status: '',
time: '',
}}
style={{ padding: '0 20px 20px 20px' }}
>
{/* <Form.Item
label="类型"
name="type"
className='mr20'
>
<Select style={{ width: 100 }}>
<Select.Option key={''}></Select.Option>
<Select.Option key={'1'}></Select.Option>
<Select.Option key={'2'}></Select.Option>
</Select>
</Form.Item> */}
<Form.Item label="时间" name="time" className="mr20">
<RangePicker format="YYYY-MM-DD HH:mm:ss" showTime />
</Form.Item>
<Form.Item label="状态" name="status" className="mr20">
<Select style={{ width: 100 }}>
<Select.Option key={''}></Select.Option>
<Select.Option key={'1'}></Select.Option>
<Select.Option key={'0'}></Select.Option>
</Select>
</Form.Item>
<Form.Item>
<Button
onClick={() => {
formInquire.resetFields();
params = {
...params,
status: '',
time: '',
startDate: '',
endDate: '',
};
setParams({ ...params });
getData(params);
}}
>
</Button>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
</Button>
</Form.Item>
</Form>
<Button
onClick={() => setVisible(true)}
icon={<i className="iconfont icon-tianjia" />}
>
</Button>
</Row>
<Table
dataSource={data}
bordered={false}
rowKey="id"
columns={columns}
scroll={{ x: 1200 }}
loading={loading}
className="pr20 pl20"
onChange={handleChangePage}
pagination={{
pageSize: params.per_page,
total: total,
current: params.page,
showQuickJumper: true,
hideOnSinglePage: true,
position: ['bottomCenter'],
showTotal: (total) => (
<span className="mr10">
<span>{total}</span>
</span>
),
}}
/>
<Modal
centered
title={`${editId.current ? '编辑' : '新建'}调拨单`}
visible={visible}
okText="保存"
width={924}
afterClose={() => {
form.resetFields();
editId.current = null;
setModalData([]);
}}
cancelText="取消"
onOk={() => {
form.submit();
}}
onCancel={() => {
setVisible(false);
}}
>
<Form
form={form}
colon={false}
layout="horizontal"
onFinish={handleFinish}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<div className={styles.name + ' mb10'}>
<b />
<span></span>
</div>
<Row align="middle">
<Col span={12}>
<Form.Item
label="发往节点"
name="sendNode"
rules={[
{
required: true,
message: `请输入发往节点`,
},
]}
>
<Select>
{distributionNode?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="配发依据"
name="basis"
rules={[
{
required: true,
message: `请输入配发依据`,
},
]}
>
<Input />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item
label="领用人"
name="userName"
rules={[
{
required: true,
message: `请输入领用人`,
},
]}
>
<Input />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="联系方式"
name="phone"
rules={[
{
required: true,
message: `请输入联系方式`,
},
]}
>
<Input />
</Form.Item>
</Col>
</Row>
</Form>
<Row align="middle" justify="end">
<div style={{ marginRight: 'auto' }} className={styles.name}>
<b />
<span></span>
</div>
<Button
icon={<i className="iconfont icon-daorushebei font14 mr5" />}
type="primary"
ghost
>
</Button>
<Button
icon={<i className="iconfont icon-xiazai font14 mr5" />}
className="ml10 mr10"
type="primary"
ghost
>
</Button>
<Button
ghost
icon={<i className="iconfont icon-xuanzeshebei font14 mr5" />}
onClick={() => {
getFacilityData({});
setFacilityVisible(true);
setFacilityKey(modalData.map((e: any) => e.id));
setFacilityKeyData(modalData);
}}
type="primary"
>
</Button>
</Row>
<Table
dataSource={modalData}
bordered={false}
rowKey="id"
columns={modalColumns}
scroll={{ y: 400 }}
className="mt20"
pagination={false}
/>
</Modal>
{/* 选择设备弹框 */}
<Modal
centered
title="选择设备"
visible={facilityVisible}
okText="确认"
width={924}
afterClose={() => {
formFacility.resetFields();
setFacilityKey([]);
setFacilityKeyData([]);
}}
cancelText="取消"
onOk={() => {
setModalData(facilityKeyData);
setFacilityVisible(false);
}}
onCancel={() => {
setFacilityVisible(false);
}}
>
<Form
form={formFacility}
colon={false}
layout="inline"
onFinish={handleFacility}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Row align="middle">
<Col span={12}>
<Form.Item label="装备代号" name="type">
<Input style={{ width: 200 }} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="铭牌编号" name="deviceId">
<Input style={{ width: 200 }} />
</Form.Item>
</Col>
</Row>
<Form.Item>
<Button
className="ml20"
onClick={() => {
formFacility.resetFields();
getFacilityData({});
}}
>
</Button>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
</Button>
</Form.Item>
</Form>
<Table
dataSource={facilityData}
rowSelection={{
type: 'checkbox',
selectedRowKeys: facilityKey,
onChange: (selectedRowKeys: any[], selectedRows: any[]) => {
setFacilityKey(selectedRowKeys);
setFacilityKeyData(selectedRows);
},
}}
bordered={false}
rowKey="id"
columns={modalColumns.filter((e: any) => e.dataIndex !== 'action')}
scroll={{ y: 400 }}
className="mt20"
pagination={false}
/>
</Modal>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,53 @@
.page {
.title {
height: 36px;
background: #e3effc;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
font-weight: 500;
color: #464f66;
i {
cursor: pointer;
}
}
.btn {
padding: 13px 20px;
i {
font-size: 14px;
margin-right: 5px;
}
}
.action {
cursor: pointer;
color: #6b758b;
padding: 0 10px;
&:hover {
color: @primary-color;
}
}
}
.li {
border-bottom: 1px solid #f5f5f5;
padding-bottom: 10px;
margin-bottom: 10px;
.name {
font-size: 14px;
font-weight: bold;
color: #333;
}
}
.li:last-child {
border-bottom: 0;
margin-bottom: 0;
padding-bottom: 0;
}

@ -0,0 +1,214 @@
import styles from './index.less';
import {
Button,
Select,
Row,
Modal,
Form,
message,
Empty,
Table,
InputNumber,
Input,
Col,
DatePicker,
} from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, useRef, Fragment } from 'react';
import { ColumnsType } from 'antd/lib/table';
const RangePicker: any = DatePicker.RangePicker;
import moment from 'moment';
interface PageProps {}
const Page: FC<PageProps> = () => {
const [data, setData] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(true);
const [total, setTotal] = useState<number>(0);
const [deviceList, setDeviceList] = useState<any[]>([]);
const [form] = Form.useForm();
let [params, setParams] = useState<any>({
pageNumber: 1,
pageSize: 20,
});
useEffect(() => {
getData(params);
getDeviceList();
}, []);
const getData = async (record: any) => {
setLoading(true);
const res = await Fetch('/openi/device/page', {
method: 'get',
params: record,
});
if (res.result === 'success') {
setData(res?.data?.[0]?.list);
setTotal(res?.data?.[0]?.total);
}
setLoading(false);
};
const getDeviceList = async () => {
const res = await Fetch('/openi/deviceType/list');
if (res.result === 'success') {
const data = res?.data?.[0];
setDeviceList(data);
}
};
const columns: ColumnsType<any> = [
{
title: '序号',
align: 'center',
dataIndex: 'index',
render: (text: string, record: any, index: number) =>
params.pageSize * (params.pageNumber - 1) + index + 1,
},
{
title: '装备型号',
dataIndex: 'deviceType',
render: (v: any) => v?.name,
},
{
title: '装备名称',
dataIndex: 'name',
},
{
title: '铭牌编号',
dataIndex: 'deviceId',
},
{
title: '管理标识',
dataIndex: 'sign',
render: (v: any) => v || '--',
},
{
title: '生产厂商',
dataIndex: 'producer',
render: (v: any) => v?.name,
},
];
const handleChangePage = (param: any) => {
params.pageNumber = param?.current;
params.pageSize = param?.pageSize;
setParams({ ...params });
getData(params);
};
const handleFinish = async (v: any) => {
params = { ...params, ...v };
if (v.time) {
params.startDate = moment(v?.time?.[0]).format('YYYY-MM-DD HH:mm:ss');
params.endDate = moment(v?.time?.[1]).format('YYYY-MM-DD HH:mm:ss');
}
delete params.time;
setParams({ ...params });
getData(params);
};
return (
<div className={styles.page}>
<div className={styles.title}>
<span></span>
<i
onClick={() => getData(params)}
className="iconfont icon-a-shuaxin2"
/>
</div>
<Form
form={form}
colon={false}
layout="inline"
onFinish={handleFinish}
initialValues={{
time: '',
}}
style={{ padding: '0 20px 20px 20px' }}
>
<Row className="mt10 mb10">
<Form.Item label="设备类型" name="type" className="mr20">
<Input style={{ width: 200 }} />
</Form.Item>
<Form.Item label="铭牌号" name="deviceId" className="mr20">
<Input placeholder="支持模糊查询" style={{ width: 200 }} />
</Form.Item>
<Form.Item label="初装资源" name="status" className="mr20">
<Select
allowClear
placeholder="请选择初始资源状态"
style={{ width: 200 }}
>
<Select.Option key={'0'}></Select.Option>
<Select.Option key={'1'}></Select.Option>
</Select>
</Form.Item>
</Row>
<Row>
<Form.Item label="流转状态" name="distributionId" className="mr20">
<Select
allowClear
placeholder="请选择设备流转状态"
style={{ width: 200 }}
>
<Select.Option key={'0'}></Select.Option>
<Select.Option key={'1'}></Select.Option>
</Select>
</Form.Item>
<Form.Item label="注册时间" name="time" className="mr20">
<RangePicker
placeholder={['请选择起始时间', '请选择结束时间']}
format="YYYY-MM-DD HH:mm:ss"
showTime
/>
</Form.Item>
<Form.Item>
<Button
onClick={() => {
form.resetFields();
params = {
pageNumber: 1,
pageSize: 20,
};
setParams({ ...params });
getData(params);
}}
>
</Button>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
</Button>
</Form.Item>
</Row>
</Form>
<Table
dataSource={data}
bordered={false}
rowKey="id"
columns={columns}
loading={loading}
className="pr20 pl20"
onChange={handleChangePage}
pagination={{
pageSize: params.per_page,
total: total,
current: params.page,
showQuickJumper: true,
hideOnSinglePage: true,
position: ['bottomCenter'],
showTotal: (total) => (
<span className="mr10">
<span>{total}</span>
</span>
),
}}
/>
</div>
);
};
export default Page;

@ -0,0 +1,35 @@
.page {
.title {
height: 36px;
background: #e3effc;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
font-weight: 500;
color: #464f66;
i {
cursor: pointer;
}
}
.btn {
padding: 13px 20px;
i {
font-size: 14px;
margin-right: 5px;
}
}
.action {
cursor: pointer;
color: #6b758b;
padding: 0 10px;
&:hover {
color: @primary-color;
}
}
}

@ -0,0 +1,388 @@
import styles from './index.less';
import {
Button,
Select,
Row,
Modal,
Form,
message,
Empty,
Table,
InputNumber,
Input,
Col,
} from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, useRef } from 'react';
import { downLoadLink } from '@/utils/download';
import url from '@/utils/url';
import { ColumnsType } from 'antd/lib/table';
interface PageProps {}
const Page: FC<PageProps> = () => {
const [data, setData] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(true);
const [total, setTotal] = useState<number>(0);
const [visible, setVisible] = useState<boolean>(false);
const [form] = Form.useForm();
const [params, setParams] = useState<any>({
pageNumber: 1,
pageSize: 20,
});
const editId = useRef(null);
useEffect(() => {
getData(params);
}, []);
const getData = async (record: any) => {
setLoading(true);
const res = await Fetch('/openi/producer/page', {
method: 'get',
params: record,
});
if (res.result === 'success') {
setData(res?.data?.[0]?.list);
setTotal(res?.data?.[0]?.total);
}
setLoading(false);
};
const columns: ColumnsType<any> = [
{
title: '序号',
align: 'center',
dataIndex: 'index',
render: (text: string, record: any, index: number) =>
params.pageSize * (params.pageNumber - 1) + index + 1,
},
{
title: '厂商编号',
dataIndex: 'producerNumber',
},
{
title: '生产厂商全名',
dataIndex: 'name',
},
{
title: '生产厂商简称',
dataIndex: 'simpleName',
},
{
title: '生产厂商地址',
dataIndex: 'address',
},
{
title: '联系人1姓名',
dataIndex: 'contacts1',
},
{
title: '联系人1电话',
dataIndex: 'tel1',
},
{
title: '联系人1手机',
dataIndex: 'phone1',
},
{
title: '联系人2姓名',
dataIndex: 'contacts2',
render: (text: string) => text || '--',
},
{
title: '联系人2电话',
dataIndex: 'tel2',
render: (text: string) => text || '--',
},
{
title: '联系人2手机',
dataIndex: 'phone2',
render: (text: string) => text || '--',
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: 110,
render: (v: any, r: any) => (
<span>
<i
onClick={() => handleEdit(r)}
title="修改"
className={'iconfont icon-xiugaikucundixian ' + styles.action}
/>
<i
onClick={() => handleDelete(r.id)}
title="删除"
className={'iconfont icon-shanchuzhuangbeixinghao ' + styles.action}
/>
</span>
),
},
];
const handleChangePage = (param: any) => {
params.pageNumber = param?.current;
params.pageSize = param?.pageSize;
setParams({ ...params });
getData(params);
};
const handleFinish = async (v: any) => {
const res = await Fetch(`/openi/producer/editOrAdd`, {
method: 'post',
data: {
...v,
id: editId.current,
},
});
if (res.result === 'success') {
params.pageNumber = editId.current ? params.pageNumber : 1;
setParams({ ...params });
getData(params);
setVisible(false);
}
};
const handleEdit = (param: any) => {
form.setFieldsValue({ ...param });
editId.current = param.id;
setVisible(true);
};
const handleDelete = (id: any) => {
Modal.confirm({
title: '提示',
okText: '确认',
cancelText: '取消',
content: '确认删除吗?',
onOk: async () => {
const res = await Fetch(`/openi/producer/delete/${id}`, {
method: 'post',
});
if (res.result === 'success') {
const page =
1 === data.length && params.pageNumber > 1
? params.pageNumber - 1
: params.pageNumber;
params.pageNumber = page;
setParams({ ...params });
getData(params);
}
},
});
};
return (
<div className={styles.page}>
<div className={styles.title}>
<span></span>
<i
onClick={() => getData(params)}
className="iconfont icon-a-shuaxin2"
/>
</div>
<Row justify="end" className={styles.btn}>
<Button
onClick={() => setVisible(true)}
icon={<i className="iconfont icon-tianjia" />}
>
</Button>
{/* <Button icon={<i className='iconfont icon-daorushuju2' />} className='ml10'>导出厂商信息</Button> */}
</Row>
<Table
dataSource={data}
bordered={false}
rowKey="id"
columns={columns}
scroll={{ x: 1800 }}
loading={loading}
className="pr20 pl20"
onChange={handleChangePage}
pagination={{
pageSize: params.per_page,
total: total,
current: params.page,
showQuickJumper: true,
hideOnSinglePage: true,
position: ['bottomCenter'],
showTotal: (total) => (
<span className="mr10">
<span>{total}</span>
</span>
),
}}
/>
<Modal
centered
title={`${editId.current ? '编辑' : '添加'}厂商信息`}
visible={visible}
okText="保存"
width={924}
afterClose={() => {
form.resetFields();
editId.current = null;
}}
cancelText="取消"
onOk={() => {
form.submit();
}}
onCancel={() => {
setVisible(false);
}}
>
<Form
form={form}
colon={false}
layout="horizontal"
onFinish={handleFinish}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Row align="middle">
<Col span={12}>
<Form.Item
label="生产厂商代号"
name="producerNumber"
rules={[
{
required: true,
message: `请输入生产厂商代号`,
},
]}
>
<Input />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="生产厂商全名"
name="name"
rules={[
{
required: true,
message: `请输入生产厂商全名`,
},
]}
>
<Input />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item label="生产厂商简称" name="simpleName">
<Input />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="生产厂商地址"
name="address"
rules={[
{
required: true,
message: `请输入生产厂商地址`,
},
]}
>
<Input />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item
label="联系人1姓名"
name="contacts1"
rules={[
{
required: true,
message: `请输入联系人1姓名`,
},
]}
>
<Input />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="联系人1电话"
name="tel1"
rules={[
{
required: true,
message: `请输入联系人1电话`,
},
]}
>
<Input />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item
label="联系人1手机"
name="phone1"
rules={[
{
required: true,
message: `请输入联系人1手机`,
},
]}
>
<Input />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="联系人1邮箱" name="email1">
<Input />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item label="联系人2姓名" name="contacts2">
<Input />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="联系人2电话" name="tel2">
<Input />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item label="联系人2手机" name="phone2">
<Input />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="联系人2邮箱" name="email2">
<Input />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={24}>
<Form.Item
labelCol={{ span: 4 }}
wrapperCol={{ span: 20 }}
label="详情备注"
name="remarks"
>
<Input.TextArea />
</Form.Item>
</Col>
</Row>
</Form>
</Modal>
</div>
);
};
export default Page;

@ -0,0 +1,45 @@
.page {
.title {
height: 36px;
background: #e3effc;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
font-weight: 500;
color: #464f66;
i {
cursor: pointer;
}
}
.btn {
padding: 13px 20px;
i {
font-size: 14px;
margin-right: 5px;
}
}
.action {
cursor: pointer;
color: #6b758b;
padding: 0 10px;
&:hover {
color: @primary-color;
}
}
}
.li {
div[class~='ant-form-item-control'] {
width: 388px;
}
}
.colorBlue {
color: @primary-color;
}

@ -0,0 +1,769 @@
import styles from './index.less';
import {
Button,
Select,
Row,
Modal,
Form,
message,
Empty,
Table,
Upload,
Input,
Col,
} from 'antd';
import Fetch from '@/utils/fetch';
import React, { useEffect, useState, FC, useRef, Fragment } from 'react';
import { downLoadLink } from '@/utils/download';
import { publicPath } from '@/utils/url';
import { ColumnsType } from 'antd/lib/table';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { uniqWith, isEqual } from 'lodash';
import * as XLSX from 'xlsx';
const { Dragger } = Upload;
interface PageProps {}
const Page: FC<PageProps> = () => {
const [data, setData] = useState<any>([]);
const [firmList, setFirmList] = useState<any[]>([]);
const [fileList, setFileList] = useState<any[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [total, setTotal] = useState<number>(0);
const [value, setValue] = useState<string>('');
const [visible, setVisible] = useState<any>(false);
const [form] = Form.useForm();
const [formAdd] = Form.useForm();
const [params, setParams] = useState<any>({
pageNumber: 1,
pageSize: 20,
keywords: '',
});
const editId = useRef(null);
const savedFileList = useRef<any>([]);
useEffect(() => {
getData(params);
getFirmList();
}, []);
const getData = async (record: any) => {
setLoading(true);
const res = await Fetch('/openi/deviceType/page', {
method: 'get',
params: record,
});
if (res.result === 'success') {
setData(res?.data?.[0]?.list);
setTotal(res?.data?.[0]?.total);
}
setLoading(false);
};
const getFirmList = async () => {
const res = await Fetch('/openi/producer/list');
if (res.result === 'success') {
const data = res?.data?.[0];
setFirmList(data);
}
};
const columns: ColumnsType<any> = [
{
title: '序号',
align: 'center',
dataIndex: 'index',
render: (text: string, record: any, index: number) =>
params.pageSize * (params.pageNumber - 1) + index + 1,
},
{
title: '装备代号',
dataIndex: 'typeNumber',
},
{
title: '装备名称',
dataIndex: 'name',
},
{
title: '工作模式',
dataIndex: 'pattern',
},
{
title: '管理层级',
dataIndex: 'managementLevel',
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: 110,
render: (v: any, r: any) => (
<span>
<i
onClick={() => handleEdit(r)}
title="修改"
className={'iconfont icon-xiugaikucundixian ' + styles.action}
/>
<i
onClick={() => handleDelete(r.id)}
title="删除"
className={'iconfont icon-shanchuzhuangbeixinghao ' + styles.action}
/>
</span>
),
},
];
const handleChangePage = (param: any) => {
params.pageNumber = param?.current;
params.pageSize = param?.pageSize;
setParams({ ...params });
getData(params);
};
const handleFinish = async (v: any) => {
console.log(v, 22222);
if (!v?.producerIdList?.length) {
message.warn('厂商不能为空');
return;
}
const res = await Fetch(`/openi/deviceType/editOrAdd`, {
method: 'post',
data: {
...v,
id: editId.current,
},
});
if (res.result === 'success') {
params.pageNumber = editId.current ? params.pageNumber : 1;
setParams({ ...params });
getData(params);
setVisible(false);
}
};
const handleAddFinish = async (v: any) => {
console.log(v, 22);
const res = await Fetch(`/openi/deviceType/addList`, {
method: 'post',
data: v.sights || [],
});
if (res.result === 'success') {
params.pageNumber = editId.current ? params.pageNumber : 1;
setParams({ ...params });
getData(params);
setVisible(false);
}
};
const handleEdit = (param: any) => {
form.setFieldsValue({
...param,
producerIdList: param?.producerList?.map((e: any) => e.id),
});
editId.current = param.id;
setVisible('编辑');
};
const handleAdd = () => {
setVisible('新增');
};
const handleDelete = (id: any) => {
Modal.confirm({
title: '提示',
okText: '确认',
cancelText: '取消',
content: '确认删除吗?',
onOk: async () => {
const res = await Fetch(`/openi/deviceType/delete/${id}`, {
method: 'post',
});
if (res.result === 'success') {
const page =
1 === data.length && params.pageNumber > 1
? params.pageNumber - 1
: params.pageNumber;
params.pageNumber = page;
setParams({ ...params });
getData(params);
}
},
});
};
const handleRemoveFile = async (info: any) => {
const newFileList = fileList.filter((item) => item.uid !== info.uid);
setFileList(newFileList);
savedFileList.current = [...newFileList];
message.info('删除成功');
};
const handleBeforeUpload = (info: any) => {
if (fileList?.some((e: any) => e.name === info.name)) {
message.info(`${info.name}文件已存在`);
return false;
}
let fileText = info?.name?.substring(
info?.name?.lastIndexOf('.'),
info?.name?.length,
);
fileText = fileText?.toLowerCase();
if (fileText !== '.xlsx' && fileText !== '.XLSX') {
message.error('只能上传.xml,.XML格式的文档');
return false;
}
const param = { name: info.name, uid: info.uid, file: info, percent: 0 };
fileList.push(param);
savedFileList.current = [...fileList];
setFileList([...fileList]);
return false;
};
const draggerProps = {
height: 40,
multiple: true,
withCredentials: true,
fileList,
disabled: fileList.length > 10,
maxCount: 10,
accept: '.xlsx, .XLSX',
// action: `${ENV.API_SERVER}/api/attachments.json`,
// onChange: handleChangeFile,
onRemove: handleRemoveFile,
beforeUpload: handleBeforeUpload,
};
const returnDom = () => {
return (
<div style={{ marginTop: -8 }} className={`font14`}>
<span className={`${styles.colorBlue} ml5`}></span>
</div>
);
};
const loadXML = function (file: any, fileType?: string, fuc?: any) {
const item: any = [];
const cb = () => {
const dealItem = uniqWith(item.flat(Infinity), isEqual);
fuc(dealItem);
};
// 将 xml 报文转化为dom对象注意去掉xml的协议头
const parseXML = (xml: any) => {
return new DOMParser().parseFromString(xml, 'text/xml');
};
// XML 转为 Json对象
const xml2Json = (xmlString: any) => {
let xmlDoc = parseXML(xmlString);
// 准备JSON字符串和缓存提升性能
//获取xml文档的所有子节点
var nodeList = xmlDoc.childNodes;
let buffer = {};
buffer = getXML(nodeList);
function getXML(nodes: any) {
let tmp: any = {};
for (let i in nodes) {
var curNode = nodes[i];
if (curNode.nodeType === 1) {
//如果子节点还包括子节点,则继续进行遍历
if (curNode.childNodes.length > 1) {
if (tmp.hasOwnProperty(curNode.nodeName)) {
let temp = getXML(curNode.childNodes);
if (Array.isArray(tmp[curNode.nodeName])) {
tmp[curNode.nodeName] = [...tmp[curNode.nodeName], temp];
} else {
tmp[curNode.nodeName] = [tmp[curNode.nodeName], temp];
}
} else {
tmp[curNode.nodeName] = getXML(curNode.childNodes);
}
} else {
var firstChild = curNode.childNodes[0];
if (firstChild != null) {
// nodeValue不为null
tmp[curNode.nodeName] = firstChild.nodeValue;
} else {
// nodeValue为null
tmp[curNode.nodeName] = '';
}
}
}
}
return tmp;
}
return buffer;
};
const excel2Json = (file: any) => {
let dataItem: any = []; // 存储获取到的数据
try {
// 以二进制流方式读取得到整份excel表格对象
const workbook = XLSX.read(file, { type: 'binary' });
// 遍历每张工作表进行读取(这里默认只读取第一张表)
for (const sheet in workbook.Sheets) {
if (workbook.Sheets.hasOwnProperty(sheet)) {
// 利用 sheet_to_json 方法将 excel 转成 json 数据
dataItem = dataItem.concat(
XLSX.utils.sheet_to_json(workbook.Sheets[sheet]),
);
// break; // 如果只取第一张表,就取消注释这行
}
}
console.log(dataItem);
} catch (e) {
// 这里可以抛出文件类型错误不正确的相关提示
console.log('文件类型不正确', e);
return [];
}
return dataItem;
};
const convertText = (dataFile: any, cb: any) => {
const reader = new FileReader();
if (fileType === 'excel') {
reader.readAsBinaryString(dataFile.file); //二进制
} else {
reader.readAsText(dataFile.file, 'utf8');
}
reader.onload = () => {
if (fileType === 'excel') {
item.push(excel2Json(reader.result));
} else {
item.push(xml2Json(reader.result));
}
if (item.length === file.length) {
cb();
}
};
};
for (let i = 0; i < file.length; i++) {
convertText(file[i], cb);
}
};
const handleLoad = () => {
// const k = [
// {
// name: 'U盘',
// typeNumber: '8782',
// pattern: '国家保密机',
// secretLevel: '3级',
// managementLevel: '公司 ',
// producerIdList: [''],
// },
// ];
const fnc = (k: any) => {
const sights = k?.map((e: any) => ({
name: e?.['装备名称'] || '',
typeNumber: e?.['装备代号'] || '',
pattern: e?.['工作模式'] || '',
secretLevel: e?.['装备密级'] || '',
managementLevel: e?.['管理层级'] || '',
producerIdList: [''],
}));
formAdd.setFieldsValue({
sights,
});
};
loadXML(fileList, 'excel', fnc);
};
return (
<div className={styles.page}>
<div className={styles.title}>
<span></span>
<i
onClick={() => getData(params)}
className="iconfont icon-a-shuaxin2"
/>
</div>
<Row justify="end" className={styles.btn}>
<Input.Search
placeholder="搜索装备代号/装备名称"
value={value}
onChange={(k) => setValue(k.target.value)}
onSearch={(e) => {
params.keywords = e;
params.pageNumber = 1;
setParams({ ...params });
getData(params);
}}
style={{ width: 400 }}
/>
<Button
onClick={handleAdd}
style={{ marginLeft: 'auto' }}
icon={<i className="iconfont icon-tianjia" />}
>
</Button>
<Button href={`${publicPath}装备型号模板.xlsx`} className="ml10">
</Button>
</Row>
<Table
dataSource={data}
bordered={false}
rowKey="id"
columns={columns}
// scroll={{ x: 1800 }}
loading={loading}
className="pr20 pl20"
onChange={handleChangePage}
pagination={{
pageSize: params.per_page,
total: total,
current: params.page,
showQuickJumper: true,
hideOnSinglePage: true,
position: ['bottomCenter'],
showTotal: (total) => (
<span className="mr10">
<span>{total}</span>
</span>
),
}}
/>
<Modal
centered
title={`新增设备型号`}
visible={visible === '新增'}
okText="保存"
width={924}
afterClose={() => {
formAdd.resetFields();
editId.current = null;
setFileList([]);
savedFileList.current = [];
}}
cancelText="取消"
onOk={() => {
formAdd.submit();
}}
onCancel={() => {
setVisible(false);
}}
>
<Dragger {...draggerProps}> {returnDom()}</Dragger>
<Row align="middle" justify="center" className="mt10">
<Button
type="dashed"
disabled={fileList.length === 0}
onClick={handleLoad}
style={{ width: 400 }}
>
</Button>
</Row>
<Form
form={formAdd}
colon={false}
layout="horizontal"
onFinish={handleAddFinish}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
style={{
maxHeight: 500,
overflow: 'auto',
marginTop: 10,
}}
>
<Form.List name="sights">
{(fields) =>
fields.map(({ key, name, ...restField }: any, index: number) => {
return (
<div key={key}>
<b>{index + 1}</b>
<Row align="middle">
<Col span={12}>
<Form.Item
{...restField}
label="装备名称"
name={[name, 'name']}
rules={[
{
required: true,
message: `请输入装备名称`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
{...restField}
label="装备代号"
name={[name, 'typeNumber']}
rules={[
{
required: true,
message: `请输入装备代号`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item
{...restField}
label="工作模式"
name={[name, 'pattern']}
rules={[
{
required: true,
message: `请输入工作模式`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
{...restField}
label="装备密级"
name={[name, 'secretLevel']}
rules={[
{
required: true,
message: `请输入装备密级`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item
{...restField}
label="管理层级"
name={[name, 'managementLevel']}
rules={[
{
required: true,
message: `请输入管理层级`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
</Row>
<Form.List name={[name, 'producerIdList']}>
{(fields, { add, remove }, { errors }) => (
<>
{fields.map(({ key, name, ...restField }, index) => (
<Row align="middle" key={key}>
<Form.Item
className={styles.li}
{...restField}
label="厂商"
name={[name]}
rules={[
{
required: true,
message: '请输入厂商',
},
]}
>
<Select>
{firmList?.map((e) => (
<Select.Option value={e.id} key={e.id}>
{e.name}
</Select.Option>
))}
</Select>
</Form.Item>
{fields.length > 1 ? (
<MinusCircleOutlined
style={{ margin: '0px 0px 23px 10px' }}
onClick={() => remove(name)}
/>
) : null}
</Row>
))}
<Row align="middle" justify="center">
<Button
type="dashed"
onClick={() => add()}
style={{ width: 400 }}
icon={<PlusOutlined />}
>
</Button>
</Row>
</>
)}
</Form.List>
</div>
);
})
}
</Form.List>
</Form>
</Modal>
<Modal
centered
title={'编辑设备型号'}
visible={visible === '编辑'}
okText="保存"
width={924}
afterClose={() => {
form.resetFields();
editId.current = null;
}}
cancelText="取消"
onOk={() => {
form.submit();
}}
onCancel={() => {
setVisible(false);
}}
>
<Form
form={form}
colon={false}
layout="horizontal"
onFinish={handleFinish}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
style={{
maxHeight: 500,
overflow: 'auto',
}}
>
<Row align="middle">
<Col span={12}>
<Form.Item
label="装备名称"
name="name"
rules={[
{
required: true,
message: `请输入装备名称`,
},
]}
>
<Input />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="装备代号"
name="typeNumber"
rules={[
{
required: true,
message: `请输入装备代号`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item
label="工作模式"
name="pattern"
rules={[
{
required: true,
message: `请输入工作模式`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="装备密级"
name="secretLevel"
rules={[
{
required: true,
message: `请输入装备密级`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item
label="管理层级"
name="managementLevel"
rules={[
{
required: true,
message: `请输入管理层级`,
},
]}
>
<Input disabled />
</Form.Item>
</Col>
</Row>
<Form.List name="producerIdList">
{(fields, { add, remove }, { errors }) => (
<>
{fields.map(({ key, name, ...restField }, index) => (
<Row align="middle" key={key}>
<Form.Item
className={styles.li}
{...restField}
label="厂商"
name={[name]}
rules={[
{
required: true,
message: '请输入厂商',
},
]}
>
<Select>
{firmList?.map((e) => (
<Select.Option value={e.id} key={e.id}>
{e.name}
</Select.Option>
))}
</Select>
</Form.Item>
{fields.length > 1 ? (
<MinusCircleOutlined
style={{ margin: '0px 0px 23px 10px' }}
onClick={() => remove(name)}
/>
) : null}
</Row>
))}
<Row align="middle" justify="center">
<Button
type="dashed"
onClick={() => add()}
style={{ width: 400 }}
icon={<PlusOutlined />}
>
</Button>
</Row>
</>
)}
</Form.List>
</Form>
</Modal>
</div>
);
};
export default Page;

@ -0,0 +1,53 @@
.page {
.title {
height: 36px;
background: #e3effc;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
font-weight: 500;
color: #464f66;
i {
cursor: pointer;
}
}
.btn {
padding: 13px 20px;
i {
font-size: 14px;
margin-right: 5px;
}
}
.action {
cursor: pointer;
color: #6b758b;
padding: 0 10px;
&:hover {
color: @primary-color;
}
}
}
.li {
border-bottom: 1px solid #f5f5f5;
padding-bottom: 10px;
margin-bottom: 10px;
.name {
font-size: 14px;
font-weight: bold;
color: #333;
}
}
.li:last-child {
border-bottom: 0;
margin-bottom: 0;
padding-bottom: 0;
}

@ -0,0 +1,416 @@
import styles from './index.less';
import {
Button,
Select,
Row,
Modal,
Form,
message,
Empty,
Table,
InputNumber,
Input,
Col,
Space,
} from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, useRef, Fragment } from 'react';
import { downLoadLink } from '@/utils/download';
import url from '@/utils/url';
import { ColumnsType } from 'antd/lib/table';
import { uniq } from 'lodash';
interface PageProps {}
const Page: FC<PageProps> = () => {
const [data, setData] = useState<any>([]);
const [loading, setLoading] = useState<boolean>(true);
const [total, setTotal] = useState<number>(0);
const [visible, setVisible] = useState<boolean>(false);
const [value, setValue] = useState<number>(1);
const [firmList, setFirmList] = useState<any[]>([]);
const [deviceList, setDeviceList] = useState<any[]>([]);
const [form] = Form.useForm();
const [params, setParams] = useState<any>({
pageNumber: 1,
pageSize: 20,
});
const editId = useRef(null);
useEffect(() => {
getData(params);
getFirmList();
getDeviceList();
}, []);
const getData = async (record: any) => {
setLoading(true);
const res = await Fetch('/openi/device/page', {
method: 'get',
params: record,
});
if (res.result === 'success') {
setData(res?.data?.[0]?.list);
setTotal(res?.data?.[0]?.total);
}
setLoading(false);
};
const getFirmList = async () => {
const res = await Fetch('/openi/producer/list');
if (res.result === 'success') {
const data = res?.data?.[0];
setFirmList(data);
}
};
const getDeviceList = async () => {
const res = await Fetch('/openi/deviceType/list');
if (res.result === 'success') {
const data = res?.data?.[0];
setDeviceList(data);
}
};
const columns: ColumnsType<any> = [
{
title: '序号',
align: 'center',
dataIndex: 'index',
render: (text: string, record: any, index: number) =>
params.pageSize * (params.pageNumber - 1) + index + 1,
},
{
title: '装备型号',
dataIndex: 'deviceType',
render: (v: any) => v?.name,
},
{
title: '装备名称',
dataIndex: 'name',
},
{
title: '铭牌编号',
dataIndex: 'deviceId',
},
{
title: '管理标识',
dataIndex: 'sign',
render: (v: any) => v || '--',
},
{
title: '生产厂商',
dataIndex: 'producer',
render: (v: any) => v?.name,
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: 110,
render: (v: any, r: any) => (
<span>
<i
onClick={() => handleEdit(r)}
title="修改"
className={'iconfont icon-xiugaikucundixian ' + styles.action}
/>
<i
onClick={() => handleDelete(r.id)}
title="删除"
className={'iconfont icon-shanchuzhuangbeixinghao ' + styles.action}
/>
</span>
),
},
];
const handleChangePage = (param: any) => {
params.pageNumber = param?.current;
params.pageSize = param?.pageSize;
setParams({ ...params });
getData(params);
};
const handleFinish = async (v: any) => {
const sights = v?.sights?.map((e: any) => e.deviceId);
if (uniq(sights).length !== sights.length) {
message.warn('铭牌编号不能重复');
return;
}
if (editId.current) {
const res = await Fetch(`/openi/device/editOrAdd`, {
method: 'post',
data: { ...v?.sights?.[0] },
});
if (res.result === 'success') {
getData(params);
setVisible(false);
}
return;
}
const res = await Fetch(`/openi/device/addList`, {
method: 'post',
data: v.sights,
});
if (res.result === 'success') {
params.pageNumber = 1;
setParams({ ...params });
getData(params);
setVisible(false);
}
};
const handleAdd = () => {
if (!value) {
message.warn('请输入添加设备台数');
return;
}
const num = String(Math.random())?.slice(-8);
const sights = [];
for (let i = 0; i < value; i++) {
sights.push({ deviceId: num + i });
}
form.setFieldsValue({ sights });
setVisible(true);
};
const handleEdit = (param: any) => {
form.setFieldsValue({
sights: [
{
name: param.name,
deviceId: param.deviceId,
type: param.type,
producerId: param.producerId,
},
],
});
editId.current = param.id;
setVisible(true);
};
const handleDelete = (id: any) => {
Modal.confirm({
title: '提示',
okText: '确认',
cancelText: '取消',
content: '确认删除吗?',
onOk: async () => {
const res = await Fetch(`/openi/device/delete/${id}`, {
method: 'post',
});
if (res.result === 'success') {
const page =
1 === data.length && params.pageNumber > 1
? params.pageNumber - 1
: params.pageNumber;
params.pageNumber = page;
setParams({ ...params });
getData(params);
}
},
});
};
const handleFile = () => {
var inputObj = document.createElement('input');
inputObj.setAttribute('id', '_ef');
inputObj.setAttribute('type', 'file');
inputObj.setAttribute('style', 'visibility:hidden');
document.body.appendChild(inputObj);
inputObj.click();
inputObj.onchange = async (e: any) => {
const data: any = new FormData();
data.append('file', e?.target?.files?.[0]);
const res = await Fetch('/openi/device/import', {
method: 'post',
data,
});
if (res.result === 'success') {
message.success('导入成功');
getData(params);
} else {
message.warn(res?.errorMsg);
}
};
};
return (
<div className={styles.page}>
<div className={styles.title}>
<span></span>
<i
onClick={() => getData(params)}
className="iconfont icon-a-shuaxin2"
/>
</div>
<Row justify="end" className={styles.btn}>
<Row align="middle">
<span></span>
<InputNumber
precision={0}
value={value}
min={1}
className="ml10"
onChange={(k) => setValue(k)}
style={{ width: 90 }}
/>
</Row>
<Button
className="ml10"
onClick={handleAdd}
icon={<i className="iconfont icon-tianjia" />}
>
</Button>
<Button onClick={handleFile} style={{ marginLeft: 'auto' }}>
EXCEL
</Button>
<Button
onClick={() => downLoadLink(`${url}/openi/device/model`)}
className="ml10"
>
</Button>
</Row>
<Table
dataSource={data}
bordered={false}
rowKey="id"
columns={columns}
// scroll={{ x: 1800 }}
loading={loading}
className="pr20 pl20"
onChange={handleChangePage}
pagination={{
pageSize: params.per_page,
total: total,
current: params.page,
showQuickJumper: true,
hideOnSinglePage: true,
position: ['bottomCenter'],
showTotal: (total) => (
<span className="mr10">
<span>{total}</span>
</span>
),
}}
/>
<Modal
centered
title={`${editId.current ? '编辑' : '注册'}设备`}
visible={visible}
okText="保存"
width={1180}
afterClose={() => {
form.resetFields();
editId.current = null;
}}
cancelText="取消"
onOk={() => {
form.submit();
}}
onCancel={() => {
setVisible(false);
}}
>
<Form
form={form}
colon={false}
layout="inline"
onFinish={handleFinish}
style={{
maxHeight: 500,
overflow: 'auto',
}}
// labelCol={{ span: 8 }}
// wrapperCol={{ span: 16 }}
>
<Form.List name="sights">
{(fields) =>
fields.map(({ key, name, ...restField }: any, index: number) => {
return (
<div className={styles.li} key={key}>
{!editId.current && (
<div className={styles.name}>{index + 1}</div>
)}
<Row>
<Form.Item
{...restField}
className="mb10"
label="装备名称"
name={[name, 'name']}
rules={[
{
required: true,
message: `请输入装备名称`,
},
]}
>
<Input />
</Form.Item>
<Form.Item
{...restField}
label="装备型号"
name={[name, 'type']}
rules={[
{
required: true,
message: `请输入装备型号`,
},
]}
>
<Select style={{ width: 200 }}>
{deviceList?.map((e) => (
<Select.Option value={e.id} key={e.id}>
{e.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
{...restField}
label="生产厂商"
name={[name, 'producerId']}
rules={[
{
required: true,
message: `请输入生产厂商`,
},
]}
>
<Select style={{ width: 200 }}>
{firmList?.map((e) => (
<Select.Option value={e.id} key={e.id}>
{e.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
{...restField}
label="铭牌编号"
name={[name, 'deviceId']}
rules={[
{
required: true,
message: `请输入装备名称`,
},
]}
>
<Input />
</Form.Item>
</Row>
</div>
);
})
}
</Form.List>
</Form>
</Modal>
</div>
);
};
export default Page;

@ -0,0 +1,61 @@
.page {
width: 1200px;
margin: 22px auto;
display: flex;
justify-content: space-between;
.left {
width: 146px;
height: 334px;
background: #ffffff;
border-radius: 4px;
padding-top: 18px;
> div {
height: 44px;
display: flex;
align-items: center;
font-size: 16px;
font-weight: 400;
color: #464f66;
padding: 20px 0;
cursor: pointer;
b {
display: inline-block;
width: 3px;
height: 16px;
background: @primary-color;
margin-right: 10px;
visibility: hidden;
}
&:hover {
color: @primary-color;
}
i {
padding-right: 10px;
font-size: 16px;
}
}
.active {
color: @primary-color;
b {
visibility: visible;
}
i {
color: @primary-color;
}
}
}
.right {
width: 1034px;
border-radius: 4px;
background-color: #ffffff;
}
}

@ -0,0 +1,63 @@
import styles from './index.less';
import { history } from 'umi';
const Page = ({ ...props }) => {
const pathname = props.location.pathname;
const item: any = [
{
icon: 'iconfont icon-tongji',
name: '装备信息统计',
key: '2',
},
{
icon: 'iconfont icon-chaxun',
name: '装备信息查询',
key: '/demand',
},
{
icon: 'iconfont icon-zhucedengji',
name: '装备注册登记',
key: '/register',
},
{
icon: 'iconfont icon-xinghaoguanli',
name: '装备型号管理',
key: '/model',
},
{
icon: 'iconfont icon-peifaguanli',
name: '装备配发管理',
key: '/allotment',
},
{
icon: 'iconfont icon-changshangxinxiguanli',
name: '厂商信息管理',
key: '/manufacturer',
},
];
return (
<div className={styles.page}>
<div className={styles.left}>
{item.map((e: any) => (
<div
key={e.key}
className={pathname?.includes(e.key) ? styles.active : ''}
onClick={() => {
if (e.key !== '2') {
history.push(`/manager/basicManager${e.key}`);
}
}}
>
<b />
<i className={e.icon} />
{e.name}
</div>
))}
</div>
<div className={styles.right}>{props.children}</div>
</div>
);
};
export default Page;

@ -0,0 +1,66 @@
.head {
height: 60px;
background: #001628;
> section {
margin: 0 auto;
height: 100%;
font-size: 18px;
display: flex;
align-items: center;
color: #fff;
width: 1200px;
> span {
font-size: 18px;
font-weight: 500;
color: #ffffff;
line-height: 18px;
letter-spacing: 2px;
}
> ul {
margin: 0;
padding: 0;
flex: 1;
display: flex;
align-items: center;
.active {
color: #28b1ff;
b {
visibility: visible;
}
}
li {
list-style: none;
margin-left: 100px;
font-size: 14px;
font-weight: 600;
color: #fff;
position: relative;
cursor: pointer;
}
b {
position: absolute;
z-index: 1;
left: 50%;
transform: translateX(-50%);
bottom: -9px;
width: 40px;
height: 2px;
background: #28b1ff;
visibility: hidden;
}
}
}
}
.content {
height: calc(100vh - 60px);
background-color: #fafafa;
overflow: auto;
}

@ -0,0 +1,89 @@
import styles from './index.less';
import { Fragment, useEffect } from 'react';
import { history } from 'umi';
import Fetch from '@/utils/fetch';
import Nav from '@/components/Nav';
import { message } from 'antd';
const Header = ({ ...props }) => {
useEffect(() => {
getData();
}, []);
const getData = async () => {
const res = await Fetch('/openi/localManager/isOpen');
if (res.result === 'success') {
document.title = '栅格化密码管理基础设施';
if (!res?.data?.[0]) {
// message.warn('当前本地管理终端未开通,已为你跳转至终端界面!');
history.replace('/terminal');
return;
}
}
};
const pathname = props.location.pathname;
const menu = [
{
id: '1',
name: '首页',
url: '',
},
{
id: '2',
name: '计划管理',
url: '',
},
{
id: '/passwordManager',
name: '密码管理',
url: '/manager/passwordManager',
},
// {
// id: '/basicManager',
// name: '基础设施管理',
// url: '/manager/basicManager/register',
// },
{
id: '3',
name: '证书管理',
url: '',
},
{
id: '4',
name: '运维管理',
url: '',
},
];
return (
<Fragment>
<div className={styles.head}>
<section>
<i className="iconfont icon-a-dashujushujujiegouguanxiguanxifenxigongtonglianxirenzuzhi1 mr10 font26" />
<span></span>
<ul>
{menu.map((e: any) => (
<li
className={e.name === '密码管理' ? styles.active : ''}
key={e.id}
onClick={() => {
if (e.url) {
history.push(e.url);
}
}}
>
<span>{e.name}</span>
<b />
</li>
))}
</ul>
<div className="font14">V0.4.0.0</div>
</section>
</div>
<div className={styles.content}>
{props.children}
<Nav />
</div>
</Fragment>
);
};
export default Header;

@ -0,0 +1,89 @@
.page {
width: 1200px;
margin: 22px auto;
display: flex;
justify-content: space-between;
.left {
width: 146px;
height: 334px;
background: #ffffff;
border-radius: 4px;
padding-top: 18px;
> div {
height: 44px;
display: flex;
align-items: center;
font-size: 16px;
font-weight: 400;
color: #464f66;
padding: 20px 0;
cursor: pointer;
b {
display: inline-block;
width: 3px;
height: 16px;
background: @primary-color;
margin-right: 10px;
visibility: hidden;
}
&:hover {
color: @primary-color;
}
i {
padding-right: 10px;
font-size: 16px;
}
}
.active {
color: @primary-color;
b {
visibility: visible;
}
i {
color: @primary-color;
}
}
}
.right {
width: 1034px;
border-radius: 4px;
background-color: #ffffff;
.title {
height: 36px;
background: #e3effc;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
font-weight: 500;
color: #464f66;
i {
cursor: pointer;
}
}
.box {
height: 500px;
margin-top: 20px;
}
.btn {
border-top: 1px solid #ebf3ff;
height: 58px;
display: flex;
align-items: center;
padding: 0 20px;
}
}
}

@ -0,0 +1,305 @@
import styles from './index.less';
import {
InputNumber,
Input,
Button,
Select,
Row,
Modal,
Form,
message,
Empty,
Spin,
} from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, useRef } from 'react';
import { Link, BasicInfoModelState, connect, Dispatch } from 'umi';
import { downLoadLink } from '@/utils/download';
import url from '@/utils/url';
import ReactEcharts from 'echarts-for-react';
import { getInitData } from '@/utils/util';
interface PageProps {
dispatch: Dispatch;
}
const Page: FC<PageProps> = ({ dispatch }) => {
const algorithmList = getInitData('algorithmList');
const keyLengthList = getInitData('keyLengthList');
const keyNodeList = getInitData('keyNodeList');
const [type, setType] = useState<string>('1');
const [algorithm, setAlgorithm] = useState<string>('');
const [length, setLength] = useState<string>('');
const [pushNode, setPushNode] = useState<string>('');
const [count, setCount] = useState<number>(1000);
const [data, setData] = useState<any>([]);
useEffect(() => {
getData();
}, [type]);
const getData = async () => {
const res = await Fetch('/openi/secretKey/statistics', {
method: 'get',
params: {
type,
},
});
if (res.result === 'success') {
setData(res?.data?.[0]);
// const xData = res?.data?.[0]?.map((e: any) => {
// if (type !== '2') {
// return e.length;
// }
// return e.algorithm;
// })
// const yData = res?.data?.[0]?.map((e: any) => e.count)
// dispatch({
// type: 'basic/setEchartsData',
// payload: {
// xData,
// yData
// },
// });
}
};
const item: any = [
{
icon: 'iconfont icon-yuzhiziyuan',
name: '预制秘钥资源',
key: '1',
},
{
icon: 'iconfont icon-gongsiyueduiziyuan',
name: '公私钥对资源',
key: '2',
},
{
icon: 'iconfont icon-suanfacanshuziyuan',
name: '算法参数资源',
key: '3',
},
{
icon: 'iconfont icon-suanfaluojiziyuan',
name: '算法逻辑资源',
key: '4',
},
{
icon: 'iconfont icon-ruanjianziyuan',
name: '密码软件资源',
key: '5',
},
];
const handleFile = () => {
var inputObj = document.createElement('input');
inputObj.setAttribute('id', '_ef');
inputObj.setAttribute('type', 'file');
inputObj.setAttribute('style', 'visibility:hidden');
document.body.appendChild(inputObj);
inputObj.click();
inputObj.onchange = async (e: any) => {
const data: any = new FormData();
data.append('file', e?.target?.files?.[0]);
const res = await Fetch(`/openi/secretKey/resourceImport/${type}`, {
method: 'post',
data,
});
if (res.result === 'success') {
message.success('导入成功');
getData();
} else {
message.error(res.errorMsg);
}
};
};
const title = item.find((e: any) => e.key === type).name;
// const items = [
// {
// key: '1',
// name: 'ECC359',
// },
// {
// key: '2',
// name: 'ECC281',
// },
// ];
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
legend: {},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: {
type: 'value',
boundaryGap: [0, 0.01],
},
yAxis: {
type: 'category',
data: data?.map((e: any) => {
if (type !== '2') {
return e.length;
}
return e.algorithm;
}),
},
series: [
{
name: '库存数量',
type: 'bar',
barMaxWidth: 12,
data: data?.map((e: any) => e.count),
},
],
};
const push = async () => {
if (!count) {
message.warn('推送组数不能为空');
return;
}
if (!algorithm && type === '2') {
message.warn('算法类型不能为空');
return;
}
if (!length) {
message.warn('密码长度不能为空');
return;
}
if (!pushNode) {
message.warn('推送节点不能为空');
return;
}
const res = await Fetch('/openi/secretKey/pushKey', {
method: 'post',
data: {
pushNode,
type,
length: Number(length),
count,
algorithm,
},
});
if (res.errorCode === 500) {
message.warn(res.errorMsg);
return;
}
if (res.result === 'success') {
message.success('推出成功');
getData();
}
};
const mr = type === '2' ? 'mr15' : 'mr30';
return (
<div className={styles.page}>
<div className={styles.left}>
{item.map((e: any) => (
<div
key={e.key}
className={type === e.key ? styles.active : ''}
onClick={() => {
setType(e.key);
}}
>
<b />
<i className={e.icon} />
{e.name}
</div>
))}
</div>
<div className={styles.right}>
<div className={styles.title}>
<span>{title} </span>
<i onClick={() => getData()} className="iconfont icon-a-shuaxin2" />
</div>
<div className={styles.box}>
<ReactEcharts
option={option}
style={{ height: 500 }}
opts={{ renderer: 'svg' }}
/>
</div>
<div className={styles.btn}>
<Button
onClick={handleFile}
className={mr}
icon={
<i
className="iconfont icon-daorushuju2 mr5"
style={{ fontSize: 14 }}
/>
}
>
</Button>
<Row align="middle" className={mr}>
<span className="mr10"></span>
<Select
style={{ width: 96 }}
value={length}
onChange={(k) => setLength(k)}
>
{keyLengthList?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</Row>
<Row align="middle" className={mr}>
<span className="mr10"></span>
<Select
style={{ width: 160 }}
value={pushNode}
onChange={(k) => setPushNode(k)}
>
{keyNodeList?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</Row>
{type === '2' && (
<Row align="middle" className={mr}>
<span className="mr10"></span>
<Select
value={algorithm}
onChange={(k) => setAlgorithm(k)}
style={{ width: 100 }}
>
{algorithmList?.map((e: any) => (
<Select.Option key={e}>{e}</Select.Option>
))}
</Select>
</Row>
)}
<Row align="middle" className={mr}>
<span className="mr10"></span>
<InputNumber
precision={0}
value={count}
style={{ width: type === '2' ? 98 : 218 }}
onChange={(k) => setCount(k)}
/>
</Row>
<Button onClick={push} type="primary">
</Button>
</div>
</div>
</div>
);
};
export default connect(({ basic }: { basic: BasicInfoModelState }) => ({
basic,
}))(Page);

@ -0,0 +1,166 @@
.page {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.iframe {
width: 100%;
flex: 1;
}
.wrap {
height: 300px;
position: relative;
width: 100%;
.list {
height: 100%;
overflow-x: hidden;
overflow-y: auto;
}
.btn {
margin: 20px;
float: right;
}
.bar {
height: 2px;
width: 100%;
background: #000;
cursor: ns-resize;
position: absolute;
top: -1px;
left: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
i {
color: #000000;
font-size: 12px;
margin-top: 4px;
}
}
}
}
.s0 {
flex: 0 0 50px !important;
text-align: center !important;
> i {
cursor: pointer;
color: @primary-color;
}
}
.s1 {
flex: 1 !important;
}
.s2 {
flex: 2 !important;
}
.s3 {
flex: 3 !important;
}
.progress {
display: flex;
align-items: center;
.pw {
width: 100%;
height: 8px;
background: #f5f5f5;
border-radius: 4px;
display: flex;
align-items: flex-start;
align-items: center;
span {
display: inline-block;
height: 8px;
background: #07c160;
border-radius: 4px;
}
}
.t {
margin-left: 10px;
}
}
.head {
height: 60px;
background: #e6e6e6;
display: flex;
> div {
height: 60px;
line-height: 60px;
text-align: center;
font-size: 14px;
font-weight: 500;
color: #232b40;
border-left: 1px solid #979797;
}
> div:first-child {
border-left: 0;
}
}
.headTitle {
height: 38px;
background: #f5f5f5;
display: flex;
> div {
height: 38px;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
font-weight: 500;
color: #232b40;
> div {
flex: 1;
text-align: left;
padding: 0 10px;
}
}
}
.row {
height: 58px;
display: flex;
border-bottom: 1px solid #eef2f8;
> div {
height: 58px;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
font-weight: 500;
color: #232b40;
> div {
flex: 1;
text-align: left;
padding: 0 10px;
}
}
}
.no {
pointer-events: none !important;
user-select: none;
}

@ -0,0 +1,665 @@
import styles from './index.less';
import {
message,
Input,
Button,
Row,
Modal,
Form,
Table,
Empty,
Col,
Select,
DatePicker,
} from 'antd';
import Fetch from '@/utils/fetch';
import { useEffect, useState, FC, Fragment, useRef } from 'react';
import { cloneDeep } from 'lodash';
import { ColumnsType } from 'antd/lib/table';
const RangePicker: any = DatePicker.RangePicker;
import moment from 'moment';
const testData = {
id: 1,
createTime: null,
updateTime: null,
deviceId: 'h55g66',
name: '测试设备1',
type: 1,
producerId: 1,
status: '0',
distributionId: 0,
addTime: '2022-08-11 08:50',
producer: null,
deviceType: null,
deviceList: null,
aText: '正在封装资源',
aProgress: 0,
bText: '正在封装资源',
bProgress: 0,
cText: '正在封装资源',
cProgress: 0,
};
const Progress = ({ item, onFinish, start, setVisible }: any) => {
const [data, setData] = useState<any>({});
const timer = useRef<any>(null);
const dataSave = useRef<any>({});
useEffect(() => {
if (item.id) {
dataSave.current = item;
setData(item);
}
}, [item]);
useEffect(() => {
if (start) {
recursionFun();
}
return () => {
clearTimeout(timer.current);
};
}, [start]);
const rand = (m: number, n: number) => {
return Math.ceil(Math.random() * (n - m + 1) + m - 1);
};
const recursionFun = () => {
clearTimeout(timer.current);
const newItem = cloneDeep(dataSave.current);
const array = [
['aText', 'aProgress'],
['bText', 'bProgress'],
['cText', 'cProgress'],
];
const arrayIndex = newItem.type > 2 ? 0 : newItem.type;
const arrayItem = array[arrayIndex];
const dataNum = rand(5, 10);
let total = newItem[arrayItem[1]] + dataNum;
if (total >= 100) {
newItem[arrayItem[1]] = 100;
newItem[arrayItem[0]] = '资源写入完成';
} else if (total < 15) {
newItem[arrayItem[1]] = total;
newItem[arrayItem[0]] = '正在封装资源';
} else {
newItem[arrayItem[1]] = total;
newItem[arrayItem[0]] = '正在写入';
}
if (newItem.aProgress + newItem.bProgress + newItem.cProgress !== 100) {
timer.current = setTimeout(() => {
recursionFun();
}, (10 - dataNum) * 1000);
} else {
newItem.state = 'done';
console.log(newItem, 'newItem');
onFinish(newItem);
}
setData(newItem);
dataSave.current = newItem;
};
return (
<div className={styles.row}>
<div className={styles.s2}>
<div className={styles.s1}>{data.deviceId}</div>
<div className={styles.s2}>{data.name}</div>
<div
className={styles.s0}
style={{ pointerEvents: start ? 'none' : 'auto' }}
>
{data.type !== 3 ? (
<i
onClick={() => setVisible(data)}
className="iconfont icon-bianji10"
/>
) : (
<i
className="iconfont icon-bianji10"
style={{ cursor: 'not-allowed', color: '#999' }}
/>
)}
</div>
</div>
<div className={styles.s1}>
<div>{data.aText}</div>
<div className={styles.progress}>
<div className={styles.pw}>
<span
style={{ width: `${data.aProgress}%` }}
className={styles.p}
></span>
</div>
<div className={styles.t}>{data.aProgress}%</div>
</div>
</div>
<div className={styles.s1}>
<div>{data.bText}</div>
<div className={styles.progress}>
<div className={styles.pw}>
<span
style={{ width: `${data.bProgress}%` }}
className={styles.p}
></span>
</div>
<div className={styles.t}>{data.bProgress}%</div>
</div>
<div
className={styles.s0}
style={{ pointerEvents: start ? 'none' : 'auto' }}
>
{data.type === 1 ? (
<i
// onClick={() => setVisible(data)}
className="iconfont icon-bianji10"
/>
) : (
<i
className="iconfont icon-bianji10"
style={{ cursor: 'not-allowed', color: '#999' }}
/>
)}
</div>
</div>
<div className={styles.s1}>
<div>{data.cText}</div>
<div className={styles.progress}>
<div className={styles.pw}>
<span
style={{ width: `${data.cProgress}%` }}
className={styles.p}
></span>
</div>
<div className={styles.t}>{data.cProgress}%</div>
</div>
<div
className={styles.s0}
style={{ pointerEvents: start ? 'none' : 'auto' }}
>
{data.type === 2 ? (
<i
// onClick={() => setVisible(data)}
className="iconfont icon-bianji10"
/>
) : (
<i
className="iconfont icon-bianji10"
style={{ cursor: 'not-allowed', color: '#999' }}
/>
)}
</div>
</div>
</div>
);
};
const Page = () => {
const [form] = Form.useForm();
const [data, setData] = useState<any>([]);
const [disabled, setDisabled] = useState<boolean>(false);
const [start, setStart] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
const [visible, setVisible] = useState<any>(false);
const [modalData, setModalData] = useState<any>([]);
const [modalSelectKey, setModalSelectKey] = useState<any>([]);
const [deviceList, setDeviceList] = useState<any[]>([]);
const resizeBar = useRef<any>(null);
const resizeBox = useRef<any>(null);
const iframeBox = useRef<any>(null);
const dataSave = useRef<any>([]);
console.log(data, 'data');
useEffect(() => {
document.title = '栅格化密码管理基础设施';
getDeviceList();
}, []);
useEffect(() => {
if (visible) {
getModalData({});
setModalSelectKey(visible?.keys || []);
}
}, [visible]);
useEffect(() => {
window.addEventListener('message', getData, false);
return () => {
window.removeEventListener('message', getData, false);
};
}, []);
const getDeviceList = async () => {
const res = await Fetch('/openi/deviceType/list');
if (res.result === 'success') {
const data = res?.data?.[0];
setDeviceList(data);
}
};
const getData = (e: any) => {
if (
e.origin === 'https://edu-xnfz.educoder.net' ||
e.origin === 'http://localhost:81'
) {
console.log(e.data, 22222);
let newData: any = [];
try {
if (e.data) {
newData = JSON.parse(e.data);
}
} catch (s) {
newData = eval('(' + e.data + ')');
}
if (dataSave.current.length === newData.length) return;
let realData = [];
if (dataSave.current.length > newData.length) {
realData = dataSave.current.filter((e: any) => {
if (newData.some((l: any) => l?.id === e?.id)) {
return true;
}
return false;
});
}
if (dataSave.current.length < newData.length) {
const param = newData.find((e: any) => {
if (!dataSave.current.map((l: any) => l?.id).includes(e?.id)) {
return true;
}
return false;
});
param.name = '';
param.keys = [];
if (param.u3dType === 2) {
param.type = 1;
param.bText = '开机棒连接成功';
} else if (param.u3dType === 3) {
param.type = 2;
param.cText = '授启棒连接成功';
} else if (param.u3dType === 1) {
param.type = 4;
param.aText = '注入器连接成功';
} else {
param.type = 3;
param.aText = '密码设备连接成功';
param.name = `${param.deviceType?.typeNumber}_${param.deviceId}`;
}
realData = [
...dataSave.current,
{
...param,
aProgress: 0,
bProgress: 0,
cProgress: 0,
},
];
}
setData(realData);
dataSave.current = cloneDeep(realData);
}
};
useEffect(() => {
if (resizeBar.current) {
let h = 0;
let dragging = false;
let startY = 0;
function onMouseDown(e: any) {
dragging = true;
iframeBox.current.style.pointerEvents = 'none';
document.body.style.cursor = 'ns-resize';
h = resizeBox.current.offsetHeight;
startY = e.clientY;
document.onselectstart = function () {
return false;
};
}
function onMouseUp() {
dragging = false;
iframeBox.current.style.pointerEvents = 'auto';
document.body.style.cursor = 'initial';
document.onselectstart = null;
}
function onMouseMove(e: any) {
if (dragging) {
let delta = startY - e.clientY;
let resizeH = h + delta;
if (resizeH < 10) {
resizeH = 10;
}
if (resizeH > window.innerHeight - 30) {
resizeH = window.innerHeight - 30;
}
resizeBox.current.style.height = resizeH + 'px';
}
}
const dom: any = resizeBar.current;
dom.addEventListener('mousedown', onMouseDown);
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
return () => {
const dom: any = resizeBar.current;
dom.removeEventListener('mousedown', onMouseDown);
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);
};
}
}, [resizeBar]);
const handleFinish = (v: any) => {
const newData = dataSave.current.map((e: any) => {
if (e.id === v.id) {
return { ...v };
}
return e;
});
if (newData.every((e: any) => e.state === 'done')) {
setDisabled(true);
setLoading(false);
// setStart(false);
message.success('初装成功,正在重置页面');
setTimeout(() => {
window.location.reload();
}, 500);
}
setData(newData);
dataSave.current = newData;
};
const handleClick = async () => {
const bool = dataSave.current.every((e: any) => e.name);
if (!bool) {
message.warn('请添加设备物理标志');
return;
}
let deviceList: any = [];
dataSave.current.forEach((e: any) => {
deviceList.push(e.id);
deviceList = deviceList.concat(e.keys || []);
});
deviceList = deviceList.map((id: any) => {
return { id, status: '1' };
});
const res = await Fetch(`/openi/device/configureDevice`, {
method: 'post',
data: {
deviceList,
},
});
if (res.result === 'success') {
iframeBox.current.className = styles.iframe + ' ' + styles.no;
setStart(true);
setLoading(true);
setDisabled(false);
}
};
const handleModalFinish = async (v: any) => {
const params = { ...v };
if (v.time) {
params.startDate =
moment(v?.time?.[0]).format('YYYY-MM-DD') + ' 00:00:00';
params.endDate = moment(v?.time?.[1]).format('YYYY-MM-DD') + ' 23:59:59';
delete params.time;
}
getModalData(params);
};
const columns: ColumnsType<any> = [
{
width: 120,
title: '编号',
dataIndex: 'index',
render: (_: string, __: any, index: number) => index + 1,
},
{
title: '设备物理标识',
dataIndex: 'deviceType',
render: (v: any, r: any) => (
<span>
{v?.typeNumber}_{r.deviceId}
</span>
),
},
{
title: '注册时间',
dataIndex: 'addTime',
},
{
width: 120,
title: '状态',
dataIndex: 'status',
render: (v: any, r: any) =>
v === '1' ? (
<span style={{ color: 'green' }}></span>
) : (
<span></span>
),
},
];
const getModalData = async (record: any) => {
const res = await Fetch('/openi/device/page', {
method: 'get',
params: {
pageNumber: 1,
pageSize: 100000,
...record,
},
});
if (res.result === 'success') {
const item = res?.data?.[0]?.list;
setModalData(item);
} else {
message.warn(res.errorMsg);
}
};
const handleOk = async () => {
if (!modalSelectKey.length) {
message.warn('请选择一个设备');
return;
}
const items = modalData.filter((e: any) => modalSelectKey.includes(e.id));
let str = '';
if (items.length === 1) {
str = `${items[0]?.deviceType?.typeNumber}_${items[0]?.deviceId}`;
}
if (items.length > 1) {
str = `${items[0]?.deviceType?.typeNumber}_${items[0]?.deviceId} ~ ${
items[items.length - 1]?.deviceType?.typeNumber
}_${items[items.length - 1]?.deviceId}`;
}
const param = cloneDeep(visible);
param.name = str;
param.keys = items.map((e: any) => e.id);
const newData = cloneDeep(data).map((e: any) => {
if (e.id === param.id) {
return param;
}
return e;
});
console.log(newData, 22244);
setData(newData);
dataSave.current = newData;
setVisible(false);
};
return (
<div className={styles.page}>
<iframe
className={styles.iframe}
src={
process.env.NODE_ENV === 'development' ||
window.location.origin === 'http://47.111.130.18:56841'
? 'https://edu-xnfz.educoder.net/Test/Hejidong/SheBeiChuZhuang1_0/index.html'
: 'http://localhost:81'
}
ref={iframeBox}
frameBorder={0}
></iframe>
<div ref={resizeBox} className={styles.wrap}>
<div className={styles.bar} ref={resizeBar} draggable={false}>
<i className="iconfont icon-guangbiao" draggable={false}></i>
</div>
<div className={styles.list}>
<div className={styles.head}>
<div className={styles.s2}></div>
<div className={styles.s1}></div>
<div className={styles.s1}></div>
<div className={styles.s1}></div>
</div>
<div className={styles.headTitle}>
<div className={styles.s2}>
<div className={styles.s1}></div>
<div className={styles.s2}></div>
<div className={styles.s0}></div>
</div>
<div className={styles.s1}>
<div></div>
<div></div>
</div>
<div className={styles.s1}>
<div></div>
<div></div>
<div className={styles.s0}></div>
</div>
<div className={styles.s1}>
<div></div>
<div></div>
<div className={styles.s0}></div>
</div>
</div>
{!!data.length ? (
data.map((e: any) => (
<Progress
key={e.id}
item={e}
start={start}
setVisible={setVisible}
onFinish={handleFinish}
/>
))
) : (
<Empty className="mt10" />
)}
<Button
onClick={handleClick}
loading={loading}
type="primary"
ghost
disabled={disabled || data.length === 0}
className={styles.btn}
>
</Button>
</div>
</div>
<Modal
centered
title="设备详细信息"
visible={visible}
okText="确认"
width={924}
afterClose={() => {
form.resetFields();
setModalSelectKey([]);
setModalData([]);
}}
cancelText="取消"
onOk={handleOk}
onCancel={() => {
setVisible(false);
}}
>
<Form
form={form}
colon={false}
onFinish={handleModalFinish}
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<Row align="middle">
<Col span={12}>
<Form.Item label="装备类型" name="type" initialValue={''}>
<Select>
<Select.Option key={''}></Select.Option>
{deviceList?.map((e) => (
<Select.Option value={e.id} key={e.id}>
{e.name}
</Select.Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="注册时间" name="time" initialValue={''}>
<RangePicker style={{ width: 328 }} />
</Form.Item>
</Col>
</Row>
<Row align="middle">
<Col span={12}>
<Form.Item label="资源状态" name="status" initialValue={''}>
<Select>
<Select.Option key={''}></Select.Option>
<Select.Option key={'0'}></Select.Option>
<Select.Option key={'1'}></Select.Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="铭牌号" name="deviceId" initialValue={''}>
<Input />
</Form.Item>
</Col>
</Row>
<Row justify="end">
<Form.Item>
<Button
className="mr20"
onClick={() => {
form.resetFields();
getModalData({});
}}
>
</Button>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
</Button>
</Form.Item>
</Row>
</Form>
<Table
dataSource={modalData}
rowSelection={{
hideSelectAll: true,
type: visible?.type === 4 ? 'checkbox' : 'radio',
selectedRowKeys: modalSelectKey,
onChange: (selectedRowKeys: any[], selectedRows: any[]) => {
setModalSelectKey(selectedRowKeys);
},
}}
bordered={false}
rowKey="id"
columns={columns}
scroll={{ y: 400 }}
pagination={false}
/>
</Modal>
</div>
);
};
export default Page;

@ -0,0 +1,23 @@
import { useEffect } from 'react';
import { history, getDvaApp } from 'umi';
import { ConfigProvider } from 'antd';
import zhCN from 'antd/es/locale/zh_CN';
import '@/styles/base.less';
import '@/styles/iconfont/iconfont.css';
const IndexPage = ({ ...props }) => {
//重定向页面
useEffect(() => {
const basic = ['/', '/basic/device', '/basic/certificate'];
if (basic.includes(props.location.pathname)) {
history.replace('/basic');
}
getDvaApp()._store.dispatch({
type: 'basic/getSelectData',
payload: {},
});
}, []);
return <ConfigProvider locale={zhCN}>{props.children}</ConfigProvider>;
};
export default IndexPage;

@ -0,0 +1,8 @@
import Fetch from '@/utils/fetch';
export async function getSelectData(params: any) {
return Fetch(`/openi/sysDict/all`, {
method: 'get',
params,
});
}

@ -0,0 +1,564 @@
.bold {
font-weight: bold;
}
.primary-color {
color: @primary-color;
}
.mt0 {
margin-top: 0px;
}
.mt3 {
margin-top: 3px;
}
.mt4 {
margin-top: 4px;
}
.mt5 {
margin-top: 5px;
}
.mt6 {
margin-top: 6px;
}
.mt8 {
margin-top: 8px;
}
.mt10 {
margin-top: 10px !important;
}
.mt12 {
margin-top: 12px;
}
.mt15 {
margin-top: 15px;
}
.mt17 {
margin-top: 17px;
}
.mt20 {
margin-top: 20px !important;
}
.mt25 {
margin-top: 25px;
}
.mt30 {
margin-top: 30px;
}
.mt35 {
margin-top: 35px;
}
.mt40 {
margin-top: 40px;
}
.mt50 {
margin-top: 50px;
}
.mt60 {
margin-top: 60px;
}
.mt70 {
margin-top: 70px;
}
.mt75 {
margin-top: 75px;
}
.mt80 {
margin-top: 80px;
}
.mt100 {
margin-top: 100px;
}
.ml0 {
margin-left: 0;
}
.ml2 {
margin-left: 2px;
}
.ml5 {
margin-left: 5px;
}
.ml8 {
margin-left: 8px;
}
.ml10 {
margin-left: 10px !important;
}
.ml10soft {
margin-left: 10px;
}
.ml15 {
margin-left: 15px;
}
.ml20 {
margin-left: 20px !important;
}
.ml25 {
margin-left: 25px;
}
.ml30 {
margin-left: 30px;
}
.ml35 {
margin-left: 35px;
}
.ml40 {
margin-left: 40px;
}
.ml50 {
margin-left: 50px;
}
.ml60 {
margin-left: 60px;
}
.ml90 {
margin-left: 90px;
}
.ml100 {
margin-left: 100px;
}
.mr0 {
margin-right: 0px;
}
.mr1 {
margin-right: 1px;
}
.mr3 {
margin-right: 3px;
}
.mr5 {
margin-right: 5px;
}
.mr8 {
margin-right: 8px;
}
.mr10 {
margin-right: 10px !important;
}
.mr15 {
margin-right: 15px;
}
.mr20 {
margin-right: 20px !important;
}
.mr25 {
margin-right: 25px;
}
.mr30 {
margin-right: 30px;
}
.mr32 {
margin-right: 32px;
}
.mr40 {
margin-right: 40px;
}
.mr50 {
margin-right: 50px;
}
.mb0 {
margin-bottom: 0px;
}
.mb5 {
margin-bottom: 5px;
}
.mb10 {
margin-bottom: 10px !important;
}
.mb16 {
margin-bottom: 16px;
}
.mb20 {
margin-bottom: 20px;
}
.mb25 {
margin-bottom: 25px;
}
.mb30 {
margin-bottom: 30px;
}
.mb50 {
margin-bottom: 50px;
}
.mb60 {
margin-bottom: 60px;
}
.mb80 {
margin-bottom: 80px;
}
.mb100 {
margin-bottom: 100px;
}
.mtb20 {
margin-top: 20px;
margin-bottom: 20px;
}
.p0 {
padding: 0;
}
.p12 {
padding: 12px;
}
.p16 {
padding: 16px;
}
.p20 {
padding: 20px;
}
.p30 {
padding: 30px;
}
.pt2 {
padding-top: 2px;
}
.pt5 {
padding-top: 5px;
}
.pt8 {
padding-top: 8px;
}
.pt10 {
padding-top: 10px;
}
.pt20 {
padding-top: 20px;
}
.pt30 {
padding-top: 30px;
}
.pt40 {
padding-top: 40px;
}
.pt60 {
padding-top: 60px;
}
.pb0 {
padding-bottom: 0px;
}
.pb5 {
padding-bottom: 5px;
}
.pb8 {
padding-bottom: 8px;
}
.pb10 {
padding-bottom: 10px;
}
.pb12 {
padding-bottom: 12px;
}
.pb20 {
padding-bottom: 20px;
}
.pb30 {
padding-bottom: 30px;
}
.pb40 {
padding-bottom: 40px;
}
.pb50 {
padding-bottom: 50px;
}
.pb60 {
padding-bottom: 60px;
}
.pr5 {
padding-right: 5px;
}
.pr10 {
padding-right: 10px;
}
.pr20 {
padding-right: 20px;
}
.pr25 {
padding-right: 25px;
}
.pr30 {
padding-right: 30px;
}
.pr40 {
padding-right: 40px;
}
.pl0 {
padding-left: 0px;
}
.pl8 {
padding-left: 8px;
}
.pl10 {
padding-left: 10px;
}
.pl12 {
padding-left: 12px;
}
.pl15 {
padding-left: 15px;
}
.pl20 {
padding-left: 20px;
}
.pl25 {
padding-left: 25px;
}
.pl30 {
padding-left: 30px;
}
.pl40 {
padding-left: 40px;
}
.pl60 {
padding-left: 60px;
}
.pl70 {
padding-left: 70px;
}
.pl80 {
padding-left: 80px;
}
.plr20 {
padding-left: 20px;
padding-right: 20px;
}
.plr30 {
padding-left: 30px;
padding-right: 30px;
}
.tl {
text-align: left;
}
.tc {
text-align: center;
}
.tr {
text-align: right;
}
.c-green-shixun {
color: #43d7b5;
}
.show {
display: block;
_display: block;
}
.minHb100 {
min-height: 100%;
}
.minH200 {
min-height: 200px;
}
.minH500 {
min-height: 500px;
}
.minH1000 {
min-height: 1000px;
}
.minH1050 {
min-height: 1050px;
}
.hide {
display: none;
_display: none;
}
.hidden {
visibility: hidden;
}
.overflow_hidden {
overflow: hidden;
}
.zIndexf1 {
z-index: -1;
}
.font8 {
font-size: 8px;
}
.font12 {
font-size: 12px;
}
.font13 {
font-size: 13px;
}
.font14 {
font-size: 14px !important;
}
.font15 {
font-size: 15px;
}
.font16 {
font-size: 16px;
}
.font17 {
font-size: 17px;
}
.font18 {
font-size: 18px;
}
.font19 {
font-size: 19px;
}
.font20 {
font-size: 20px;
}
.font22 {
font-size: 22px;
}
.font24 {
font-size: 24px;
}
.font26 {
font-size: 26px !important;
}
.font28 {
font-size: 28px;
}
.font40 {
font-size: 40px;
}
.font50 {
font-size: 50px;
}
.line14 {
line-height: 1.4;
}
.line24 {
line-height: 24px;
}
.line26 {
line-height: 26px;
}

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke viewBox IE
normalize.css */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,234 @@
@font-face {
font-family: "iconfont"; /* Project id 3579477 */
src: url('iconfont.eot?t=1663901035581'); /* IE9 */
src: url('iconfont.eot?t=1663901035581#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('iconfont.woff2?t=1663901035581') format('woff2'),
url('iconfont.woff?t=1663901035581') format('woff'),
url('iconfont.ttf?t=1663901035581') format('truetype'),
url('iconfont.svg?t=1663901035581#iconfont') format('svg');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-chaxun:before {
content: "\ec4c";
}
.icon-tongji:before {
content: "\e89e";
}
.icon-piliangshanchubeifen:before {
content: "\e9e3";
}
.icon-bianji10:before {
content: "\ea4b";
}
.icon-fujian:before {
content: "\e671";
}
.icon-guangbiao:before {
content: "\e7c4";
}
.icon-xiazai:before {
content: "\e670";
}
.icon-xuanzeshebei:before {
content: "\e66e";
}
.icon-daorushebei:before {
content: "\e66f";
}
.icon-daorushuju2:before {
content: "\e716";
}
.icon-weitongguo:before {
content: "\e66c";
}
.icon-jingxiang:before {
content: "\e9e7";
}
.icon-wodegongzuotai:before {
content: "\e9ee";
}
.icon-chuangjianjiahao:before {
content: "\ea79";
}
.icon-chakan2:before {
content: "\ea7a";
}
.icon-zhongduan:before {
content: "\ea7b";
}
.icon-fuwuqi:before {
content: "\ea7c";
}
.icon-shouqixiaojiantou:before {
content: "\ea7d";
}
.icon-zhankaixiaojiantou:before {
content: "\ea7e";
}
.icon-a-dashujushujujiegouguanxiguanxifenxigongtonglianxirenzuzhi1:before {
content: "\e715";
}
.icon-changshangxinxiguanli:before {
content: "\e701";
}
.icon-peifaguanli:before {
content: "\e702";
}
.icon-gongsiyueduiziyuan:before {
content: "\e707";
}
.icon-ruanjianziyuan:before {
content: "\e709";
}
.icon-suanfacanshuziyuan:before {
content: "\e70a";
}
.icon-xinghaoguanli:before {
content: "\e70b";
}
.icon-xinxichaxun:before {
content: "\e70d";
}
.icon-xinxitongji:before {
content: "\e70e";
}
.icon-yuzhiziyuan:before {
content: "\e712";
}
.icon-zhucedengji:before {
content: "\e713";
}
.icon-suanfaluojiziyuan:before {
content: "\e714";
}
.icon-shouqi:before {
content: "\e700";
}
.icon-guanbi:before {
content: "\e703";
}
.icon-sousuo:before {
content: "\e704";
}
.icon-shanchuzhuangbeixinghao:before {
content: "\e705";
}
.icon-a-shuaxin2:before {
content: "\e706";
}
.icon-tianjia:before {
content: "\e708";
}
.icon-xiala:before {
content: "\e70c";
}
.icon-xiugaikucundixian:before {
content: "\e70f";
}
.icon-tuichu:before {
content: "\e710";
}
.icon-zhongzhi:before {
content: "\e711";
}
.icon-jiantou:before {
content: "\e66b";
}
.icon-bianzu:before {
content: "\e65f";
}
.icon-mimaruanjianjiami:before {
content: "\e660";
}
.icon-jiedian:before {
content: "\e661";
}
.icon-chanshenggongsiyuedui:before {
content: "\e662";
}
.icon-suanfaluojijiami:before {
content: "\e663";
}
.icon-shuju:before {
content: "\e664";
}
.icon-shujuji:before {
content: "\e665";
}
.icon-suanfacanshujiami:before {
content: "\e666";
}
.icon-rengongzhineng:before {
content: "\e667";
}
.icon-yuzhimiyuejiami:before {
content: "\e668";
}
.icon-suanfasheji:before {
content: "\e669";
}
.icon-yunjisuan:before {
content: "\e66a";
}

Binary file not shown.

File diff suppressed because one or more lines are too long

@ -0,0 +1,387 @@
{
"id": "3579477",
"name": "信工大图标库",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "5961297",
"name": "查询",
"font_class": "chaxun",
"unicode": "ec4c",
"unicode_decimal": 60492
},
{
"icon_id": "10520233",
"name": "统计",
"font_class": "tongji",
"unicode": "e89e",
"unicode_decimal": 59550
},
{
"icon_id": "27904347",
"name": "批量删除备份",
"font_class": "piliangshanchubeifen",
"unicode": "e9e3",
"unicode_decimal": 59875
},
{
"icon_id": "29889324",
"name": "编辑",
"font_class": "bianji10",
"unicode": "ea4b",
"unicode_decimal": 59979
},
{
"icon_id": "826201",
"name": "附件",
"font_class": "fujian",
"unicode": "e671",
"unicode_decimal": 58993
},
{
"icon_id": "17272329",
"name": "光标",
"font_class": "guangbiao",
"unicode": "e7c4",
"unicode_decimal": 59332
},
{
"icon_id": "31306044",
"name": "下载",
"font_class": "xiazai",
"unicode": "e670",
"unicode_decimal": 58992
},
{
"icon_id": "31305208",
"name": "选择设备",
"font_class": "xuanzeshebei",
"unicode": "e66e",
"unicode_decimal": 58990
},
{
"icon_id": "31305209",
"name": "导入设备",
"font_class": "daorushebei",
"unicode": "e66f",
"unicode_decimal": 58991
},
{
"icon_id": "31258224",
"name": "导入数据",
"font_class": "daorushuju2",
"unicode": "e716",
"unicode_decimal": 59158
},
{
"icon_id": "31225732",
"name": "未通过",
"font_class": "weitongguo",
"unicode": "e66c",
"unicode_decimal": 58988
},
{
"icon_id": "31206162",
"name": "镜像",
"font_class": "jingxiang",
"unicode": "e9e7",
"unicode_decimal": 59879
},
{
"icon_id": "31206163",
"name": "我的工作台",
"font_class": "wodegongzuotai",
"unicode": "e9ee",
"unicode_decimal": 59886
},
{
"icon_id": "31207787",
"name": "创建加号",
"font_class": "chuangjianjiahao",
"unicode": "ea79",
"unicode_decimal": 60025
},
{
"icon_id": "31207788",
"name": "查看",
"font_class": "chakan2",
"unicode": "ea7a",
"unicode_decimal": 60026
},
{
"icon_id": "31219592",
"name": "终端",
"font_class": "zhongduan",
"unicode": "ea7b",
"unicode_decimal": 60027
},
{
"icon_id": "31219593",
"name": "服务器",
"font_class": "fuwuqi",
"unicode": "ea7c",
"unicode_decimal": 60028
},
{
"icon_id": "31222118",
"name": "收起小箭头",
"font_class": "shouqixiaojiantou",
"unicode": "ea7d",
"unicode_decimal": 60029
},
{
"icon_id": "31222119",
"name": "展开小箭头",
"font_class": "zhankaixiaojiantou",
"unicode": "ea7e",
"unicode_decimal": 60030
},
{
"icon_id": "31215787",
"name": "大数据",
"font_class": "a-dashujushujujiegouguanxiguanxifenxigongtonglianxirenzuzhi1",
"unicode": "e715",
"unicode_decimal": 59157
},
{
"icon_id": "31175964",
"name": "厂商信息管理",
"font_class": "changshangxinxiguanli",
"unicode": "e701",
"unicode_decimal": 59137
},
{
"icon_id": "31175965",
"name": "配发管理",
"font_class": "peifaguanli",
"unicode": "e702",
"unicode_decimal": 59138
},
{
"icon_id": "31175966",
"name": "公私钥对资源",
"font_class": "gongsiyueduiziyuan",
"unicode": "e707",
"unicode_decimal": 59143
},
{
"icon_id": "31175967",
"name": "软件资源",
"font_class": "ruanjianziyuan",
"unicode": "e709",
"unicode_decimal": 59145
},
{
"icon_id": "31175968",
"name": "算法参数资源",
"font_class": "suanfacanshuziyuan",
"unicode": "e70a",
"unicode_decimal": 59146
},
{
"icon_id": "31175969",
"name": "型号管理",
"font_class": "xinghaoguanli",
"unicode": "e70b",
"unicode_decimal": 59147
},
{
"icon_id": "31175970",
"name": "信息查询",
"font_class": "xinxichaxun",
"unicode": "e70d",
"unicode_decimal": 59149
},
{
"icon_id": "31175971",
"name": "信息统计",
"font_class": "xinxitongji",
"unicode": "e70e",
"unicode_decimal": 59150
},
{
"icon_id": "31175972",
"name": "预制资源",
"font_class": "yuzhiziyuan",
"unicode": "e712",
"unicode_decimal": 59154
},
{
"icon_id": "31175973",
"name": "注册登记",
"font_class": "zhucedengji",
"unicode": "e713",
"unicode_decimal": 59155
},
{
"icon_id": "31175976",
"name": "算法逻辑资源",
"font_class": "suanfaluojiziyuan",
"unicode": "e714",
"unicode_decimal": 59156
},
{
"icon_id": "31169141",
"name": "收起",
"font_class": "shouqi",
"unicode": "e700",
"unicode_decimal": 59136
},
{
"icon_id": "31169144",
"name": "关闭",
"font_class": "guanbi",
"unicode": "e703",
"unicode_decimal": 59139
},
{
"icon_id": "31169145",
"name": "搜索",
"font_class": "sousuo",
"unicode": "e704",
"unicode_decimal": 59140
},
{
"icon_id": "31169146",
"name": "删除装备型号",
"font_class": "shanchuzhuangbeixinghao",
"unicode": "e705",
"unicode_decimal": 59141
},
{
"icon_id": "31169147",
"name": "刷新 (2)",
"font_class": "a-shuaxin2",
"unicode": "e706",
"unicode_decimal": 59142
},
{
"icon_id": "31169149",
"name": "添加",
"font_class": "tianjia",
"unicode": "e708",
"unicode_decimal": 59144
},
{
"icon_id": "31169153",
"name": "下拉",
"font_class": "xiala",
"unicode": "e70c",
"unicode_decimal": 59148
},
{
"icon_id": "31169156",
"name": "修改库存底线",
"font_class": "xiugaikucundixian",
"unicode": "e70f",
"unicode_decimal": 59151
},
{
"icon_id": "31169157",
"name": "退出 ",
"font_class": "tuichu",
"unicode": "e710",
"unicode_decimal": 59152
},
{
"icon_id": "31169158",
"name": "重置",
"font_class": "zhongzhi",
"unicode": "e711",
"unicode_decimal": 59153
},
{
"icon_id": "31164284",
"name": "箭头",
"font_class": "jiantou",
"unicode": "e66b",
"unicode_decimal": 58987
},
{
"icon_id": "31161856",
"name": "编组",
"font_class": "bianzu",
"unicode": "e65f",
"unicode_decimal": 58975
},
{
"icon_id": "31161857",
"name": "密码软件加密",
"font_class": "mimaruanjianjiami",
"unicode": "e660",
"unicode_decimal": 58976
},
{
"icon_id": "31161858",
"name": "节点",
"font_class": "jiedian",
"unicode": "e661",
"unicode_decimal": 58977
},
{
"icon_id": "31161859",
"name": "产生公私钥对",
"font_class": "chanshenggongsiyuedui",
"unicode": "e662",
"unicode_decimal": 58978
},
{
"icon_id": "31161860",
"name": "算法逻辑加密",
"font_class": "suanfaluojijiami",
"unicode": "e663",
"unicode_decimal": 58979
},
{
"icon_id": "31161861",
"name": "数据",
"font_class": "shuju",
"unicode": "e664",
"unicode_decimal": 58980
},
{
"icon_id": "31161862",
"name": "数据集",
"font_class": "shujuji",
"unicode": "e665",
"unicode_decimal": 58981
},
{
"icon_id": "31161863",
"name": "算法参数加密",
"font_class": "suanfacanshujiami",
"unicode": "e666",
"unicode_decimal": 58982
},
{
"icon_id": "31161864",
"name": "人工智能",
"font_class": "rengongzhineng",
"unicode": "e667",
"unicode_decimal": 58983
},
{
"icon_id": "31161865",
"name": "预制密钥加密",
"font_class": "yuzhimiyuejiami",
"unicode": "e668",
"unicode_decimal": 58984
},
{
"icon_id": "31161866",
"name": "算法设计",
"font_class": "suanfasheji",
"unicode": "e669",
"unicode_decimal": 58985
},
{
"icon_id": "31161867",
"name": "云集算",
"font_class": "yunjisuan",
"unicode": "e66a",
"unicode_decimal": 58986
}
]
}

@ -0,0 +1,127 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Created by iconfont</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024">
<font-face
font-family="iconfont"
font-weight="400"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="chaxun" unicode="&#60492;" d="M896 832H128c-35.296 0-64-28.704-64-64v-768c0-35.296 28.704-64 64-64h592a32 32 0 1 1 0 64H128V768h768v-592a32 32 0 1 1 64 0V768c0 35.296-28.704 64-64 64zM791.744 149.50400000000002A206.752 206.752 0 0 1 832 272c0 114.688-93.312 208-208 208S416 386.688 416 272s93.312-208 208-208a206.752 206.752 0 0 1 122.496 40.256l110.88-110.88a31.904 31.904 0 0 1 45.248 0 31.968 31.968 0 0 1 0 45.248l-110.88 110.88zM480 272c0 79.392 64.608 144 144 144s144-64.608 144-144-64.608-144-144-144-144 64.608-144 144zM800 632a32 32 0 0 1-32 32H256a32 32 0 0 1 0-64h512a32 32 0 0 1 32 32zM256 473.344a32 32 0 0 1 0-64h96a32 32 0 0 1 0 64H256z" horiz-adv-x="1024" />
<glyph glyph-name="tongji" unicode="&#59550;" d="M1008.241778-44.714667c0-20.992-18.432-38.115556-40.049778-38.115555H62.179556A38.912 38.912 0 0 0 22.755556-44.714667C22.755556-23.665778 40.561778-6.542222 62.179556-6.542222H968.248889c21.617778 0 40.049778-17.180444 40.049778-38.115556M896.341333 705.592889c22.243556 0 40.049778-17.180444 40.049778-38.115556v-578.56c0-21.048889-17.806222-38.229333-40.049778-38.229333h-166.570666a38.968889 38.968889 0 0 0-39.424 38.172444V667.420444c0 21.048889 17.806222 38.172444 39.424 38.172445h166.570666z m-127.146666-578.56h87.722666v502.328889h-87.722666v-502.328889zM598.812444 572.074667c21.617778 0 39.424-17.180444 39.424-38.115556v-445.098667a38.968889 38.968889 0 0 0-39.424-38.115555h-167.253333a38.968889 38.968889 0 0 0-39.367111 38.115555V533.902222c0 21.048889 17.806222 38.172444 39.367111 38.172445h167.253333z m-127.146666-445.098667h87.096889V495.729778H471.665778v-368.753778zM300.600889 839.111111c21.617778 0 40.049778-17.180444 40.049778-38.115555v-712.135112c0-20.992-18.432-38.115556-40.049778-38.115555H133.404444a38.968889 38.968889 0 0 0-39.424 38.115555V800.995556c0 21.048889 17.806222 38.172444 39.424 38.172444h167.196445zM173.454222 126.976H260.551111V762.88H173.454222v-635.847111z" horiz-adv-x="1024" />
<glyph glyph-name="piliangshanchubeifen" unicode="&#59875;" d="M0 676.571429h1024v-73.142858H0zM899.657143-128H124.342857V618.057143h73.142857V-54.857143h629.028572V618.057143h73.142857zM292.571429 896h438.857142v-73.142857H292.571429zM358.4 618.057143h73.142857v-709.485714h-73.142857zM592.457143 618.057143h73.142857v-709.485714h-73.142857z" horiz-adv-x="1024" />
<glyph glyph-name="bianji10" unicode="&#59979;" d="M936.228571 384H877.714286c-7.314286 0-7.314286-7.314286-7.314286-7.314286v-351.085714H153.6V742.4h351.085714L512 749.714286v65.828571V822.857143H109.714286c-7.314286 0-21.942857 0-29.257143-7.314286s-7.314286-21.942857-7.314286-29.257143v-804.571428c0-14.628571 14.628571-36.571429 36.571429-36.571429h804.571428c7.314286 0 14.628571 7.314286 21.942857 7.314286 7.314286 7.314286 7.314286 14.628571 7.314286 21.942857V376.685714c7.314286 7.314286 0 7.314286-7.314286 7.314286zM336.457143 362.057143v-131.657143c0-7.314286 0-7.314286 7.314286-14.628571s7.314286-7.314286 14.628571-7.314286H497.371429L950.857143 661.942857V676.571429l-138.971429 146.285714h-14.628571L336.457143 362.057143c7.314286 0 0 0 0 0z m73.142857-29.257143L804.571429 727.771429l51.2-51.2-394.971429-387.657143h-51.2v43.885714z" horiz-adv-x="1024" />
<glyph glyph-name="fujian" unicode="&#58993;" d="M902.656 389.079c-1.044-1.004-2.13-2.068-3.256-3.256l-371.241-371.343c-0.942-0.655-1.802-1.475-2.642-2.314-92.57-89.682-241.684-88.617-332.8 2.519-91.279 91.238-92.18 240.62-2.048 333.107 6.349 6.431 421.356 421.765 425.513 425.923 65.004 64.922 170.701 64.922 235.643 0 31.293-31.355 48.62-73.052 48.62-117.453-0.082-44.564-17.49-86.446-49.070-117.924l-427.233-427.151c-36.065-32.748-91.156-31.355-125.747 3.215-34.591 34.529-35.717 89.825-2.683 125.891 0.635 0.594 1.188 1.311 1.679 2.068l0.143 0.061c0.164 0.164 0.307 0.307 0.43 0.451l1.085 1.106c0.082 0.061 0.205 0.102 0.307 0.266l371.425 371.446c9.81 9.83 9.81 25.743 0 35.594-9.81 9.83-25.784 9.83-35.615 0l-372.879-372.838c-0.287-0.307-0.635-0.635-0.963-0.983l-4.178-4.116c-1.659-1.638-3.011-3.523-4.116-5.489-45.65-55.972-42.004-137.523 9.646-189.153 53.924-53.821 139.899-55.726 195.953-4.28 0.225 0.225 0.492 0.451 0.758 0.696l427.54 427.54c41.124 40.98 63.775 95.539 63.775 153.58 0.041 57.856-22.385 112.23-63.304 153.068-84.562 84.541-222.29 84.541-306.913 0l-425.349-425.718c-0.164-0.225-0.348-0.389-0.492-0.553v0c-109.404-112.067-108.319-293.315 2.396-403.948 55.808-55.828 129.516-83.763 203.264-83.763 71.352 0 142.848 26.173 198.124 78.643 0.43 0.307 0.819 0.696 1.208 1.004 0.43 0.369 0.717 0.696 1.147 1.065l2.683 2.58c0.102 0.164 0.184 0.164 0.307 0.328l371.405 371.446c0.041 0.061 0.184 0.266 0.225 0.328 0.635 0.512 1.188 1.208 1.925 1.843 10.015 9.544 10.486 25.416 1.004 35.533-9.646 10.056-25.58 10.527-35.676 0.983v0 0zM902.656 389.079z" horiz-adv-x="1024" />
<glyph glyph-name="guangbiao" unicode="&#59332;" d="M0 541.675558m59.054074 0l1653.514063 0q59.054074 0 59.054074-59.054074l0 0q0-59.054074-59.054074-59.054074l-1653.514063 0q-59.054074 0-59.054074 59.054074l0 0q0 59.054074 59.054074 59.054074ZM874.827048 891.629999a29.527037 29.527037 0 0 0 21.909061 0l437.000145-174.859113a29.527037 29.527037 0 0 0-10.925003-56.987181h-874.000291a29.527037 29.527037 0 0 0-10.984058 56.928127zM896.795163 73.61297a29.527037 29.527037 0 0 0-21.909061 0l-437.000146 174.859112a29.527037 29.527037 0 0 0 10.925004 56.987181h874.000291a29.527037 29.527037 0 0 0 10.984057-56.928127z" horiz-adv-x="2194" />
<glyph glyph-name="xiazai" unicode="&#58992;" d="M620.8 51.2c-6.4 0-12.8 0-19.2 6.4l-172.8 128 32 32 160-121.6 160 121.6 38.4-32-179.2-128c-6.4-6.4-12.8-6.4-19.2-6.4zM268.8 96H128c-51.2 0-96 44.8-96 96V768C32 819.2 76.8 864 128 864h576c51.2 0 96-44.8 96-96v-140.8h-64V768c0 19.2-12.8 32-32 32H128c-19.2 0-32-12.8-32-32v-576c0-19.2 12.8-32 32-32h140.8v-64zM896-96H320c-51.2 0-96 44.8-96 96V576c0 51.2 44.8 96 96 96h576c51.2 0 96-44.8 96-96v-576c0-51.2-44.8-96-96-96z m-576 704c-19.2 0-32-12.8-32-32v-576c0-19.2 12.8-32 32-32h576c19.2 0 32 12.8 32 32V576c0 19.2-12.8 32-32 32H320zM582.4 480h64v-403.2h-64z" horiz-adv-x="1024" />
<glyph glyph-name="xuanzeshebei" unicode="&#58990;" d="M279.272727 616.727273h279.272728v-93.090909H279.272727zM651.636364 616.727273h93.090909v-93.090909H651.636364zM651.636364 430.545455h93.090909v-93.09091H651.636364zM279.272727 430.545455h279.272728v-93.09091H279.272727zM763.345455-72.145455H130.327273c-46.545455 0-83.781818 37.236364-83.781818 74.472728V765.672727c0 46.545455 37.236364 83.781818 83.781818 83.781818h1238.109091c46.545455 0 74.472727-37.236364 74.472727-83.781818v-279.272727h-93.090909V756.363636h-1210.181818v-735.418181h623.709091v-93.09091zM1284.654545-81.454545c-9.309091 0-27.927273 9.309091-37.236363 18.618181L912.290909 356.072727c-18.618182 18.618182-18.618182 46.545455 0 65.163637 27.927273 18.618182 55.854545 9.309091 74.472727-9.309091l335.127273-418.909091c18.618182-18.618182 9.309091-46.545455-9.309091-65.163637-9.309091-9.309091-18.618182-9.309091-27.927273-9.30909zM949.527273 67.490909c-27.927273 0-46.545455 18.618182-46.545455 46.545455V384c0 9.309091 9.309091 27.927273 18.618182 37.236364 9.309091 9.309091 18.618182 9.309091 27.927273 9.309091l297.890909-55.854546c27.927273 0 46.545455-27.927273 37.236363-55.854545-9.309091-27.927273-27.927273-37.236364-55.854545-37.236364l-232.727273 46.545455v-214.109091c0-27.927273-27.927273-46.545455-46.545454-46.545455z" horiz-adv-x="1489" />
<glyph glyph-name="daorushebei" unicode="&#58991;" d="M850.707692 486.4H252.061538c-63.015385 0-118.153846 55.138462-118.153846 118.153846V777.846154C141.784615 840.861538 189.046154 896 252.061538 896h590.769231c63.015385 0 118.153846-55.138462 118.153846-118.153846v-173.292308c0-70.892308-47.261538-118.153846-110.276923-118.153846zM252.061538 817.230769c-15.753846 0-31.507692-15.753846-31.507692-39.384615v-173.292308c0-23.630769 15.753846-39.384615 31.507692-39.384615h590.769231c23.630769 0 39.384615 15.753846 39.384616 39.384615V777.846154c0 23.630769-15.753846 39.384615-31.507693 39.384615H252.061538zM519.876923 486.4h78.769231v-315.076923h-78.769231zM1008.246154 194.953846h-78.769231V313.107692H181.169231v-118.153846h-78.769231V391.876923h905.846154zM204.8-64.984615H70.892308c-39.384615 0-70.892308 31.507692-70.892308 70.892307V131.938462c0 39.384615 31.507692 70.892308 70.892308 70.892307h133.907692c39.384615 0 70.892308-31.507692 70.892308-70.892307v-133.907693c0-31.507692-31.507692-63.015385-70.892308-63.015384z m-126.030769 78.76923h118.153846V124.061538H78.769231v-110.276923zM622.276923-64.984615H480.492308c-39.384615 0-70.892308 31.507692-70.892308 70.892307V131.938462c0 39.384615 31.507692 70.892308 70.892308 70.892307h133.907692c39.384615 0 70.892308-31.507692 70.892308-70.892307v-133.907693c7.876923-31.507692-31.507692-63.015385-63.015385-63.015384z m-133.907692 78.76923h118.153846V124.061538H488.369231v-110.276923zM1031.876923-64.984615h-133.907692c-39.384615 0-70.892308 31.507692-70.892308 70.892307V131.938462c0 39.384615 31.507692 70.892308 70.892308 70.892307h133.907692c39.384615 0 70.892308-31.507692 70.892308-70.892307v-133.907693c0-31.507692-31.507692-63.015385-70.892308-63.015384z m-126.030769 78.76923H1024V124.061538h-118.153846v-110.276923zM346.584615 691.2m-78.76923 0a78.769231 78.769231 0 1 1 157.538461 0 78.769231 78.769231 0 1 1-157.538461 0Z" horiz-adv-x="1102" />
<glyph glyph-name="daorushuju2" unicode="&#59158;" d="M526.848-54.784H102.4c-14.848 0-29.184 14.848-29.184 36.352V808.448c0 22.016 14.848 36.352 29.184 36.352h834.048c14.848 0 29.184-14.848 29.184-36.352v-467.968c0-14.848-14.848-29.184-29.184-29.184s-29.184 14.848-29.184 36.352V778.752H131.584v-768h394.752c14.848 0 29.184-14.848 29.184-36.352 0.512-14.848-7.168-29.184-28.672-29.184zM680.448-47.616c-7.168 0-14.848 7.168-22.016 7.168l-131.584 153.6c-14.848 14.848-14.848 36.352 0 51.2l131.584 153.6c14.848 14.848 29.184 14.848 44.032 0 14.848-14.848 14.848-36.352 0-51.2l-109.568-124.416 109.568-124.416c14.848-14.848 14.848-36.352 0-51.2-0.512-7.168-7.68-14.336-22.016-14.336zM936.448 105.984h-256c-14.848 0-29.184 14.848-29.184 36.352 0 22.016 14.848 36.352 29.184 36.352h256c14.848 0 29.184-14.848 29.184-36.352 0-21.504-14.848-36.352-29.184-36.352zM745.984 588.8H300.032c-22.016 0-36.352 14.848-36.352 29.184s14.848 29.184 29.184 29.184h445.952c14.848 0 29.184-14.848 29.184-29.184s-7.168-29.184-22.016-29.184z m0-189.952H300.032c-14.848 0-22.016 7.168-29.184 14.848-7.168 7.168-7.168 22.016 0 29.184 7.168 14.848 14.848 14.848 29.184 14.848h445.952c14.848 0 29.184-14.848 29.184-29.184 0-15.36-14.336-29.696-29.184-29.696z" horiz-adv-x="1024" />
<glyph glyph-name="weitongguo" unicode="&#58988;" d="M721.92 552.96l-153.6-153.6 153.6-153.6-56.32-56.32-153.6 153.6-153.6-153.6-56.32 56.32 153.6 153.6-153.6 153.6 56.32 51.2 153.6-153.6 153.6 153.6 56.32-51.2zM512-128C230.4-128 0 102.4 0 384S230.4 896 512 896s512-230.4 512-512-230.4-512-512-512z m0 947.2c-240.64 0-435.2-194.56-435.2-435.2s194.56-435.2 435.2-435.2 435.2 194.56 435.2 435.2-194.56 435.2-435.2 435.2z" horiz-adv-x="1024" />
<glyph glyph-name="jingxiang" unicode="&#59879;" d="M544-57.6L57.6 172.8V384h76.8v-160l409.6-198.4 409.6 198.4V384h76.8v-211.2zM544 537.6L140.8 710.4 544 864l403.2-153.6-403.2-172.8zM307.2 704l236.8-96L780.8 704 544 793.6 307.2 704zM524.8 76.8L160 249.6V665.6l364.8-147.2v-441.6zM224 288l236.8-108.8V473.6L224 569.6v-281.6zM288 486.4m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM288 307.2m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM181.056 398.208l24.704 59.072 289.28-121.024-24.704-59.072zM569.6 307.2V518.4l352 147.2v-204.8L569.6 307.2z m64 166.4v-70.4l224 102.4v64L633.6 473.6zM569.6 83.2v192l352 153.6v-185.6l-352-160z m64 147.2v-51.2l224 108.8v44.8l-224-102.4z" horiz-adv-x="1088" />
<glyph glyph-name="wodegongzuotai" unicode="&#59886;" d="M1024 164.571429H0V896h1024v-731.428571zM87.771429 252.342857h848.457142V808.228571H87.771429v-555.885714zM219.428571 676.571429h585.142858v-87.771429H219.428571zM219.428571 457.142857h292.571429v-87.771428H219.428571zM877.714286-120.685714H146.285714v219.428571h731.428572v-219.428571z m-643.657143 87.771428h555.885714v43.885715H234.057143v-43.885715z" horiz-adv-x="1024" />
<glyph glyph-name="chuangjianjiahao" unicode="&#60025;" d="M563.2 896v-460.8H1024v-102.4H563.2V-128h-102.4V332.8H0v102.4h460.8V896z" horiz-adv-x="1024" />
<glyph glyph-name="chakan2" unicode="&#60026;" d="M612.7616-126.5664c-124.928 0-248.0128 45.7728-355.1232 132.5056C154.624 88.9856 68.1984 207.6672 7.168 349.184a90.112 90.112 0 0 0 0 69.9392c60.8256 141.6192 147.5584 260.3008 250.368 343.4496C364.7488 849.3056 487.6288 895.1808 612.7616 895.1808c124.928 0 247.9104-45.8752 355.328-132.5056 102.7072-83.1488 189.2352-201.8304 250.2656-343.4496a90.112 90.112 0 0 0 0-69.9392c-61.0304-141.5168-147.5584-260.3008-250.368-343.3472-107.3152-86.7328-230.1952-132.5056-355.328-132.5056zM103.2192 384.3072c52.9408-116.9408 125.5424-214.6304 210.7392-283.3408 44.6464-36.0448 92.5696-64 142.0288-82.8416a439.9104 439.9104 0 0 1 156.672-29.0816c53.3504 0 106.0864 9.728 156.8768 29.0816 49.5616 18.8416 97.28 46.6944 142.1312 82.8416 84.992 68.9152 157.696 166.5024 210.6368 283.3408-52.9408 116.736-125.5424 214.4256-210.6368 283.2384a521.8304 521.8304 0 0 1-142.1312 82.944 439.9104 439.9104 0 0 1-156.7744 29.0816c-53.248 0-105.984-9.9328-156.7744-29.184-49.4592-18.7392-97.28-46.6944-142.0288-82.944-85.1968-68.608-157.7984-166.4-210.7392-283.136zM612.7616 108.9536c-130.048 0-235.8272 123.4944-235.8272 275.3536s105.7792 275.456 235.8272 275.456 235.8272-123.5968 235.8272-275.456c0-151.8592-105.7792-275.456-235.8272-275.456v0.1024z m0 435.0976c-75.4688 0-136.8064-71.68-136.8064-159.744 0-88.064 61.44-159.744 136.8064-159.744 75.3664 0 136.8064 71.68 136.8064 159.744 0 88.064-61.44 159.744-136.8064 159.744z" horiz-adv-x="1228" />
<glyph glyph-name="zhongduan" unicode="&#60027;" d="M693.3248 514.56c0.4096-47.104 48.512-85.0432 107.4176-84.7104 58.9056 0.3328 106.3424 38.784 105.9328 85.9136l137.216 0.7936c14.5408 0.0768 28.4928-4.5824 38.6048-12.928L1280 341.1712H0l197.888 158.2336c9.8816 7.936 23.296 12.416 37.2992 12.5184l458.1376 2.6368zM0 255.872h1280v-213.248C1280-51.6352 1184.4864-128 1066.6752-128H213.3248C95.5136-128 0-51.6096 0 42.5984v213.2736z m1066.6752-298.5728c58.88 0 106.6496 38.1952 106.6496 85.2992 0 47.104-47.744 85.3248-106.6496 85.3248-58.9312 0-106.6752-38.1952-106.6752-85.3248 0-47.104 47.744-85.2992 106.6752-85.2992z m0 42.6496c-19.072 0-36.6848 8.1408-46.208 21.3248a35.4048 35.4048 0 0 0 0 42.6752c9.5232 13.184 27.136 21.3248 46.208 21.3248 29.44 0 53.3248-19.0976 53.3248-42.6752 0-23.552-23.8848-42.6496-53.3248-42.6496zM160 170.5728c-29.44 0-53.3248-19.0976-53.3248-42.6496v-127.9744c0-23.552 23.8592-42.6496 53.3248-42.6496h373.3248c29.44 0 53.3504 19.0976 53.3504 42.6496v127.9744c0 23.552-23.8848 42.6496-53.3504 42.6496H160z m506.6752 0c-14.7456 0-26.6752-9.5488-26.6752-21.3248 0-11.776 11.9296-21.3248 26.6752-21.3248h160c14.72 0 26.6496 9.5488 26.6496 21.3248 0 11.776-11.9296 21.3248-26.6496 21.3248h-160z m0-85.2992c-14.7456 0-26.6752-9.5488-26.6752-21.3248 0-11.776 11.9296-21.3504 26.6752-21.3504h160c14.72 0 26.6496 9.5488 26.6496 21.3504 0 11.776-11.9296 21.3248-26.6496 21.3248h-160z m0-85.3248c-14.7456 0-26.6752-9.5488-26.6752-21.3248 0-11.776 11.9296-21.3248 26.6752-21.3248h160c14.72 0 26.6496 9.5488 26.6496 21.3248 0 11.776-11.9296 21.3248-26.6496 21.3248h-160z m133.3248 742.656c29.44 0 53.3248-19.072 53.3248-42.624v-183.296c0-15.232-10.1632-29.312-26.6496-36.9408a65.0752 65.0752 0 0 0-53.3504 0c-16.4864 7.6288-26.6496 21.7088-26.6496 36.9408v183.296c0 23.552 23.8592 42.6496 53.3248 42.6496z m291.4048-8.5248c0-64.8192-36.1472-122.8288-93.1072-161.9456l-34.7136 32.4096c47.3088 32.384 74.5472 79.6928 74.496 129.5104 0.0512 49.8176-27.1616 97.152-74.496 129.536L998.2464 896c59.1872-40.4736 93.2352-99.6608 93.184-161.9456v0.0256z m-106.6496 0c0-38.912-21.7088-73.7024-55.9104-97.2032L894.208 669.312c22.784 15.6416 37.2224 38.8096 37.2224 64.7424s-14.4384 49.152-37.2736 64.768l34.6624 32.4352c35.5584-24.2944 56.0128-59.8272 55.9616-97.2032v0.0256z m-336.128 129.5104c-47.3344-32.384-74.5472-79.7184-74.496-129.536 0-51.84 28.928-98.2272 74.496-129.536l-34.6624-32.4096c-59.1872 40.448-93.2352 99.6608-93.184 161.9456 0 64.768 36.1216 122.8288 93.1328 161.9456l34.6624-32.4096h0.0512z m69.4528-64.768c-23.68-16.1792-37.2992-39.8592-37.2736-64.768 0-25.9072 14.4384-49.1008 37.2736-64.768l-34.7136-32.4096c-35.5328 24.2944-55.936 59.8016-55.9104 97.1776 0 38.8608 21.6576 73.7024 55.9104 97.152l34.6624-32.4096 0.0512 0.0512z" horiz-adv-x="1280" />
<glyph glyph-name="fuwuqi" unicode="&#60028;" d="M0 120.5504v-166.8864c0-43.3152 35.8656-78.5152 80-78.5152h1120c44.1344 0 80 35.2 80 78.5152V120.576a9.9328 9.9328 0 0 1-9.984 9.8048H9.984a9.9328 9.9328 0 0 1-9.984-9.8048z m967.5008-117.8112c0-5.376-4.5056-9.8048-9.984-9.8048h-427.52a9.9328 9.9328 0 0 0-9.984 9.8048v58.9056c0 5.376 4.48 9.8048 9.984 9.8048h427.52c5.4784 0 9.984-4.4032 9.984-9.8048v-58.88z m152.4992 0c0-5.376-4.5056-9.8048-9.984-9.8048h-60.0064a9.9328 9.9328 0 0 0-10.0096 9.8048v58.9056c0 5.376 4.5056 9.8048 9.984 9.8048h60.0064c5.504 0 10.0096-4.4032 10.0096-9.8048v-58.88zM0 356.1216v-176.6912c0-5.376 4.5056-9.8048 9.984-9.8048h1260.032c5.4784 0 9.984 4.4032 9.984 9.8048v176.6912a9.9328 9.9328 0 0 1-9.984 9.8048H9.984a9.9328 9.9328 0 0 1-9.984-9.8048z m967.5008-117.7856c0-5.4016-4.5056-9.8304-9.984-9.8304h-427.52a9.9328 9.9328 0 0 0-9.984 9.8304v58.88c0 5.4016 4.48 9.8304 9.984 9.8304h427.52c5.4784 0 9.984-4.4288 9.984-9.8304v-58.88z m152.4992 0c0-5.4016-4.5056-9.8304-9.984-9.8304h-60.0064a9.9328 9.9328 0 0 0-10.0096 9.8304v58.88c0 5.4016 4.5056 9.8304 9.984 9.8304h60.0064c5.504 0 10.0096-4.4288 10.0096-9.8304v-58.88zM0 591.6928v-176.6656c0-5.4016 4.5056-9.8304 9.984-9.8304h1260.032c5.4784 0 9.984 4.4288 9.984 9.8304v176.6656a9.9328 9.9328 0 0 1-9.984 9.8304H9.984a9.9328 9.9328 0 0 1-9.984-9.8304z m967.5008-117.76c0-5.4272-4.5056-9.8304-9.984-9.8304h-427.52a9.9328 9.9328 0 0 0-9.984 9.8048v58.88c0 5.4272 4.48 9.8304 9.984 9.8304h427.52c5.4784 0 9.984-4.4032 9.984-9.8048v-58.88z m152.4992 0c0-5.4272-4.5056-9.8304-9.984-9.8304h-60.0064a9.9328 9.9328 0 0 0-10.0096 9.8048v58.88c0 5.4272 4.5056 9.8304 9.984 9.8304h60.0064c5.504 0 10.0096-4.4032 10.0096-9.8048v-58.88zM1200 896H80C35.8656 896 0 860.7744 0 817.4848v-166.8864c0-5.376 4.5056-9.8048 9.984-9.8048h1260.032c5.4784 0 9.984 4.4032 9.984 9.8048V817.4848C1280 860.7744 1244.1344 896 1200 896z m-232.4992-186.496c0-5.4016-4.5056-9.8304-9.984-9.8304h-427.52a9.9328 9.9328 0 0 0-9.984 9.8304v58.88c0 5.4016 4.48 9.8304 9.984 9.8304h427.52c5.4784 0 9.984-4.4288 9.984-9.8304v-58.88z m152.4992 0c0-5.4016-4.5056-9.8304-9.984-9.8304h-60.0064a9.9328 9.9328 0 0 0-10.0096 9.8304v58.88c0 5.4016 4.5056 9.8304 9.984 9.8304h60.0064c5.504 0 10.0096-4.4288 10.0096-9.8304v-58.88z" horiz-adv-x="1280" />
<glyph glyph-name="shouqixiaojiantou" unicode="&#60029;" d="M1580.246914-64.790123L884.938272 617.876543 189.62963-64.790123l-126.419753 126.419753L884.938272 896l821.728395-834.37037z" horiz-adv-x="1769" />
<glyph glyph-name="zhankaixiaojiantou" unicode="&#60030;" d="M884.938272-128L63.209877 706.37037l126.419753 126.419753L884.938272 150.123457 1580.246914 832.790123l126.419753-126.419753z" horiz-adv-x="1769" />
<glyph glyph-name="a-dashujushujujiegouguanxiguanxifenxigongtonglianxirenzuzhi1" unicode="&#59157;" d="M819.2 515.072c16.384-32.768 28.672-69.632 28.672-110.592 0-57.344-20.48-110.592-57.344-151.552-4.096-4.096-4.096-12.288 0-20.48l40.96-69.632c4.096-4.096 8.192-8.192 16.384-8.192h20.48c73.728 0 135.168-61.44 131.072-131.072 0-69.632-61.44-126.976-131.072-131.072-73.728 0-135.168 57.344-135.168 131.072 0 40.96 16.384 73.728 45.056 98.304l-40.96 69.632c-4.096 8.192-12.288 8.192-20.48 8.192-28.672-16.384-65.536-24.576-102.4-24.576-28.672 0-53.248 4.096-77.824 12.288-8.192 4.096-16.384 0-20.48-8.192l-24.576-40.96c-4.096-4.096-4.096-12.288 0-16.384 16.384-20.48 24.576-49.152 24.576-77.824 0-69.632-61.44-131.072-131.072-131.072-73.728 0-135.168 57.344-135.168 131.072 0 69.632 61.44 131.072 131.072 131.072 12.288 0 24.576 0 36.864-4.096 8.192-4.096 16.384 0 20.48 8.192l24.576 36.864c4.096 8.192 4.096 16.384-4.096 20.48-36.864 32.768-61.44 73.728-69.632 122.88 0 8.192-8.192 12.288-16.384 12.288H274.432c-8.192 0-12.288-4.096-16.384-12.288-16.384-53.248-65.536-90.112-126.976-90.112C57.344 273.408 0 330.752 0 404.48c0 73.728 61.44 131.072 135.168 131.072 57.344 0 102.4-36.864 122.88-86.016 4.096-8.192 8.192-12.288 16.384-12.288h98.304c8.192 0 16.384 4.096 16.384 12.288 12.288 57.344 45.056 102.4 86.016 135.168 8.192 4.096 8.192 12.288 4.096 20.48l-4.096 4.096c-4.096 4.096-12.288 8.192-16.384 8.192-8.192 0-20.48-4.096-28.672-4.096-73.728 0-131.072 61.44-131.072 131.072C299.008 818.176 360.448 875.52 434.176 875.52c73.728 0 131.072-57.344 131.072-131.072 0-32.768-12.288-61.44-28.672-86.016-4.096-4.096-4.096-12.288 0-20.48l8.192-12.288c4.096-8.192 12.288-8.192 16.384-8.192 16.384 4.096 36.864 8.192 57.344 8.192 53.248 0 102.4-16.384 143.36-49.152 8.192-4.096 16.384-4.096 20.48 0l24.576 24.576c4.096 4.096 8.192 12.288 4.096 16.384-8.192 16.384-12.288 32.768-12.288 53.248C798.72 756.736 860.16 814.08 929.792 814.08 1003.52 814.08 1064.96 756.736 1064.96 683.008c0-73.728-61.44-131.072-135.168-131.072-20.48 0-40.96 4.096-61.44 12.288-8.192 4.096-12.288 0-20.48-4.096l-28.672-28.672s-4.096-8.192 0-16.384z" horiz-adv-x="1064" />
<glyph glyph-name="changshangxinxiguanli" unicode="&#59137;" d="M467.2 652.8L332.8 896H0v-985.6h1024V652.8H467.2z m460.8-646.4h-832V800h179.2l128-243.2h524.8v-550.4zM512 844.8h448v-96H512z" horiz-adv-x="1024" />
<glyph glyph-name="peifaguanli" unicode="&#59138;" d="M332.8 780.8V896H243.2v-115.2H0v-89.6h243.2V576h89.6V691.2H1024V780.8zM332.8 192H243.2v-115.2H0v-89.6h243.2V-128h89.6v115.2H1024v89.6H332.8zM844.8 544h-89.6v-108.8H0v-102.4h755.2v-108.8h89.6V332.8H1024V435.2h-179.2z" horiz-adv-x="1024" />
<glyph glyph-name="gongsiyueduiziyuan" unicode="&#59143;" d="M1024 576c0 179.2-140.8 320-320 320S384 755.2 384 576c0-70.4 25.6-134.4 64-185.6l-121.6-185.6-96 64-57.6-76.8 96-64-57.6-89.6-102.4 70.4-57.6-76.8 179.2-128L512 320c44.8-32 102.4-57.6 160-57.6V192H550.4v-96h121.6v-108.8H550.4v-96H768V262.4c147.2 32 256 160 256 313.6z m-320-224C582.4 352 480 454.4 480 576S582.4 800 704 800s224-102.4 224-224-102.4-224-224-224z" horiz-adv-x="1024" />
<glyph glyph-name="ruanjianziyuan" unicode="&#59145;" d="M960 896H64C25.6 896 0 851.2 0 800v-838.4c0-44.8 25.6-89.6 64-89.6h896c38.4 0 64 44.8 64 96v832c0 51.2-25.6 96-64 96z m-32-928h-832V524.8h832v-556.8zM96 627.2V800h832v-179.2h-832zM332.8 256l-102.4-102.4c-12.8-12.8-12.8-38.4 0-51.2 6.4-6.4 19.2-12.8 25.6-12.8s19.2 6.4 25.6 12.8l128 128c12.8 12.8 12.8 38.4 0 51.2l-128 128c-12.8 12.8-38.4 12.8-51.2 0s-12.8-38.4 0-51.2L332.8 256zM512 217.6h192c19.2 0 38.4 19.2 38.4 38.4s-19.2 38.4-38.4 38.4H512c-19.2 0-38.4-19.2-38.4-38.4s19.2-38.4 38.4-38.4z" horiz-adv-x="1024" />
<glyph glyph-name="suanfacanshuziyuan" unicode="&#59146;" d="M460.8 716.8L332.8 896H0v-992h1024V716.8H460.8z m96-633.6h140.8l32-76.8H524.8l32 76.8z m32 76.8l38.4 102.4 38.4-102.4H588.8z m339.2-153.6h-115.2L665.6 384c-6.4 12.8-19.2 25.6-38.4 25.6s-32-12.8-38.4-25.6L448 6.4H96V428.8h832v-422.4z m-832 518.4V800h185.6l134.4-179.2h512v-96h-832z" horiz-adv-x="1024" />
<glyph glyph-name="xinghaoguanli" unicode="&#59147;" d="M1017.6 896H0v-1024h1024l-6.4 1024z m-96-96v-396.8h-832V800h832z m-825.6-832V307.2h832v-332.8h-832zM192 614.4h256v-76.8H192z" horiz-adv-x="1024" />
<glyph glyph-name="xinxichaxun" unicode="&#59149;" d="M960 883.2H64C38.4 883.2 12.8 857.6 12.8 832v-896c0-25.6 19.2-51.2 51.2-51.2h896c25.6 0 51.2 19.2 51.2 51.2V832L960 883.2zM115.2 780.8h800v-748.8l-102.4 102.4c38.4 64 32 140.8-25.6 198.4-64 64-166.4 64-224 0-64-64-64-166.4 0-224 32-32 70.4-44.8 115.2-44.8 25.6 0 57.6 6.4 83.2 25.6l102.4-102.4H115.2V780.8z m614.4-614.4c-32-32-83.2-32-115.2 0s-32 83.2 0 115.2 83.2 32 115.2 0 32-83.2 0-115.2z m153.6-179.2l32 32v-32h-32zM256 652.8h384v-96H256zM256 460.8h192v-96H256z" horiz-adv-x="1024" />
<glyph glyph-name="xinxitongji" unicode="&#59150;" d="M563.2 883.2H512C236.8 883.2 12.8 659.2 12.8 384s224-499.2 499.2-499.2 499.2 224 499.2 499.2v51.2h-448v448z m345.6-550.4c-25.6-198.4-192-352-396.8-352-217.6 0-396.8 179.2-396.8 396.8 0 204.8 153.6 371.2 352 396.8v-448h441.6zM704 883.2h-51.2v-352h352V576C1011.2 742.4 870.4 883.2 704 883.2z m51.2-256V780.8c76.8-19.2 134.4-76.8 153.6-153.6h-153.6z" horiz-adv-x="1024" />
<glyph glyph-name="yuzhiziyuan" unicode="&#59154;" d="M192 524.8c70.4 0 128 38.4 153.6 96H960c25.6 0 51.2 19.2 51.2 51.2s-25.6 44.8-51.2 44.8H364.8C358.4 806.4 281.6 883.2 192 883.2 96 883.2 12.8 800 12.8 704S96 524.8 192 524.8z m0 256c44.8 0 76.8-38.4 76.8-76.8S236.8 627.2 192 627.2 115.2 659.2 115.2 704 147.2 780.8 192 780.8zM960 12.8h-320c-25.6 0-51.2-19.2-51.2-51.2s19.2-51.2 51.2-51.2h320c25.6 0 51.2 19.2 51.2 51.2s-25.6 51.2-51.2 51.2zM960 524.8h-320c-25.6 0-51.2-19.2-51.2-51.2s25.6-38.4 51.2-38.4h320c25.6 0 51.2 19.2 51.2 51.2s-25.6 38.4-51.2 38.4zM960 204.8H364.8C358.4 294.4 281.6 371.2 192 371.2 96 371.2 12.8 294.4 12.8 192s76.8-179.2 179.2-179.2c70.4 0 128 38.4 153.6 96H960c25.6 0 51.2 19.2 51.2 51.2s-25.6 44.8-51.2 44.8zM192 115.2c-44.8 0-76.8 38.4-76.8 76.8S147.2 268.8 192 268.8s76.8-38.4 76.8-76.8-32-76.8-76.8-76.8z" horiz-adv-x="1024" />
<glyph glyph-name="zhucedengji" unicode="&#59155;" d="M0 896v-1024h1170.285714V896H0z m1060.571429-914.285714h-950.857143v804.571428h950.857143v-804.571428zM175.542857 164.571429c0-29.257143 14.628571-80.457143 95.085714-109.714286 43.885714-14.628571 102.4-21.942857 168.228572-21.942857 124.342857 0 263.314286 36.571429 263.314286 131.657143s-51.2 182.857143-131.657143 226.742857c36.571429 36.571429 58.514286 87.771429 58.514285 138.971428 0 102.4-87.771429 190.171429-190.171428 190.171429S248.685714 632.685714 248.685714 530.285714c0-51.2 21.942857-102.4 58.514286-138.971428-80.457143-43.885714-131.657143-131.657143-131.657143-226.742857z m160.914286 365.714285c0 58.514286 43.885714 102.4 102.4 102.4s102.4-43.885714 102.4-102.4S497.371429 427.885714 438.857143 427.885714 336.457143 471.771429 336.457143 530.285714zM438.857143 340.114286c95.085714 0 175.542857-80.457143 175.542857-175.542857 0-14.628571-58.514286-43.885714-175.542857-43.885715s-175.542857 29.257143-175.542857 43.885715c0 95.085714 80.457143 175.542857 175.542857 175.542857zM804.571429 501.028571h146.285714v-87.771428h-146.285714zM804.571429 274.285714h219.428571v-73.142857h-219.428571z" horiz-adv-x="1170" />
<glyph glyph-name="suanfaluojiziyuan" unicode="&#59156;" d="M665.6 684.8c-6.4 0-12.8-6.4-12.8-12.8V640H448c-19.2 0-38.4-19.2-38.4-38.4v-179.2H339.2c-12.8 25.6-38.4 38.4-70.4 38.4C230.4 460.8 192 428.8 192 384s38.4-76.8 76.8-76.8c32 0 57.6 19.2 70.4 38.4h70.4v-179.2c0-19.2 19.2-38.4 38.4-38.4h204.8v-44.8c6.4-6.4 12.8-6.4 19.2-6.4l121.6 76.8s6.4 0 6.4 6.4c6.4 6.4 0 12.8-6.4 19.2L672 256h-6.4c-6.4 0-12.8-6.4-12.8-12.8v-32H486.4V563.2h166.4v-44.8c6.4-6.4 12.8-6.4 19.2-6.4l121.6 76.8s6.4 0 6.4 6.4c6.4 6.4 0 12.8-6.4 19.2l-121.6 76.8c0-6.4 0-6.4-6.4-6.4zM761.6 896H0v-1024h1024V684.8L761.6 896z m166.4-928h-832v832h633.6L928 640v-672z" horiz-adv-x="1024" />
<glyph glyph-name="shouqi" unicode="&#59136;" d="M34.129408-89.316022A119.45293 119.45293 0 0 1 127.473341-127.882254l1276.439876 9.726882a119.45293 119.45293 0 0 1 93.514579 38.566231 153.582338 153.582338 0 0 1 0 202.899334L859.378505 847.706887c-8.532352 9.726881-25.597056 19.283116-34.129409 29.009997l-8.532352 9.556235a121.330047 121.330047 0 0 1-136.005692-29.009998L42.491114 123.48084A167.234101 167.234101 0 0 1 34.129408-89.316022z" horiz-adv-x="1535" />
<glyph glyph-name="guanbi" unicode="&#59139;" d="M59.026286-122.002286a58.075429 58.075429 0 0 0-40.96 99.035429L919.698286 878.665143a58.075429 58.075429 0 0 0 81.92-81.993143L100.059429-104.96a57.782857 57.782857 0 0 0-40.96-17.042286zM960.731429-122.002286a57.782857 57.782857 0 0 0-40.96 17.042286L17.993143 796.745143A58.075429 58.075429 0 0 0 99.986286 878.665143l901.778285-901.705143a58.075429 58.075429 0 0 0-40.96-98.962286z" horiz-adv-x="1024" />
<glyph glyph-name="sousuo" unicode="&#59140;" d="M1010.802237-65.439517l-161.69033 160.154601c86.585867 85.927697 138.581265 200.376077 138.581264 326.305859 0 263.267838-219.462995 474.979057-490.921387 474.979057C225.240261 896 0 684.215651 0 421.020943c0-263.267838 219.462995-475.052187 490.994517-475.052187 109.694932 0 213.685728 34.371079 300.344725 97.26284l167.467597-160.154602c17.331799-11.481403 40.440865-17.258669 51.995398 0 17.331799 17.112409 17.331799 40.002085 0 51.483489zM80.88173 421.020943c0 223.192622 184.799396 400.605893 415.890054 400.605893 231.017528 0 415.890054-183.190537 415.890054-400.605893 0-217.488486-184.872526-400.679023-415.890054-400.679023-231.090658 0-415.890054 183.190537-415.890054 400.679023z" horiz-adv-x="1024" />
<glyph glyph-name="shanchuzhuangbeixinghao" unicode="&#59141;" d="M0 676.571429h1024v-73.142858H0zM899.657143-128H124.342857V618.057143h73.142857V-54.857143h629.028572V618.057143h73.142857V-128zM292.571429 896h438.857142v-73.142857H292.571429V896zM358.4 618.057143h73.142857v-709.485714h-73.142857V618.057143z m234.057143 0h73.142857v-709.485714h-73.142857V618.057143z" horiz-adv-x="1024" />
<glyph glyph-name="a-shuaxin2" unicode="&#59142;" d="M219.258665 871.581244a36.713335 36.713335 0 0 1 22.159642-46.805845l79.204267-28.376044A476.030074 476.030074 0 0 1 131.132034 643.622151c-156.872716-212.600925-114.089248-515.59564 95.586313-675.02805a467.765916 467.765916 0 0 1 352.067717-91.710204 471.203221 471.203221 0 0 1 313.8917 188.539796A485.610645 485.610645 0 0 1 987.313333 353.937849a484.221096 484.221096 0 0 1-190.148747 386.660163A467.180843 467.180843 0 0 1 613.890448 825.799277a36.713335 36.713335 0 0 1-15.650704-71.671451 393.461637 393.461637 0 0 0 154.82496-71.890853c177.789078-135.151878 214.063608-392.437759 80.740083-573.005934a398.069087 398.069087 0 0 0-265.476904-159.578679 394.631783 394.631783 0 0 0-297.43652 77.522181C93.102285 162.107017 56.608353 419.027227 189.931877 599.887939A403.115343 403.115343 0 0 0 380.300026 740.890548l-48.999869-126.083246a36.567067 36.567067 0 1 1 68.234146-26.767093l72.256524 185.760699a35.250652 35.250652 0 0 1 2.559695 13.383546l-0.146268 1.75522c0.146268 1.389549 0.731341 2.779097 0.731341 4.095511a36.786469 36.786469 0 0 1-24.280532 34.665579L266.503315 893.814021A37.079006 37.079006 0 0 1 219.404933 871.581244h-0.073134z" horiz-adv-x="1024" />
<glyph glyph-name="tianjia" unicode="&#59144;" d="M1022.390857 424.082286H550.546286V896H471.917714v-471.917714H0v-78.628572h471.917714v-471.844571h78.628572V345.453714h471.844571z" horiz-adv-x="1024" />
<glyph glyph-name="xiala" unicode="&#59148;" d="M34.277832 857.31438A119.452731 119.452731 0 0 0 127.621608 895.880547l1276.437749-9.726865a119.452731 119.452731 0 0 0 93.514423-38.566167c51.023381-58.019898 51.023381-145.049744 0-202.898995l-638.218874-724.395488c-8.532338-9.726865-25.597014-19.283084-34.129352-29.009948l-8.532338-9.556219a121.329845 121.329845 0 0 0-136.005466 29.009949L42.639523 644.517873A167.233823 167.233823 0 0 0 34.277832 857.31438z" horiz-adv-x="1536" />
<glyph glyph-name="xiugaikucundixian" unicode="&#59151;" d="M1012.736-128H0V873.472h599.844571V796.525714H77.897143v-847.433143h856.941714V495.981714h77.897143zM370.322286 176.493714L416.914286 439.588571 790.528 896 1024 702.610286l-365.714286-441.051429-287.963428-85.065143z m124.489143 232.155429l-23.405715-123.830857 140.141715 38.765714 303.542857 363.52-108.982857 100.571429-311.296-379.026286z m-303.542858-301.714286h661.504v-77.385143H191.268571v77.385143z" horiz-adv-x="1024" />
<glyph glyph-name="tuichu" unicode="&#59152;" d="M811.902537 803.913143C784.620251 827.977143 750.462537 827.977143 726.47168 810.788571c-27.355429-17.115429-37.595429-44.617143-30.72-75.410285 0-27.428571 20.48-41.106286 40.96-54.857143 143.579429-113.005714 184.612571-301.421714 99.181714-465.92-75.264-143.872-246.198857-222.646857-403.456-188.416-160.621714 34.230857-283.721143 181.613714-287.158857 346.038857-3.364571 126.756571 44.470857 229.522286 147.017143 308.370286 37.595429 30.793143 44.470857 75.337143 17.115429 106.203428-27.355429 34.230857-68.388571 37.668571-109.421715 6.875429C29.054537 660.041143-42.698606 427.008 25.616823 228.205714 94.005394 15.945143 288.931109-128 511.139109-128c280.283429 0 512.731429 226.157714 512.731428 510.537143 3.437714 174.738286-71.753143 315.172571-211.968 421.376zM489.854537 315.245714c50.907429-17.115429 95.085714 17.261714 95.085714 75.629715V813.568C588.304823 865.060571 557.731109 896 513.47968 896 472.812251 896 442.238537 865.060571 438.873966 820.370286v-432.932572c3.364571-37.814857 23.771429-61.878857 50.980571-72.192z" horiz-adv-x="1024" />
<glyph glyph-name="zhongzhi" unicode="&#59153;" d="M1011.858286 316.196571c19.236571 134.363429-6.363429 256-89.6 364.763429C826.294857 821.76 583.094857 930.596571 474.258286 885.76c6.436571-25.6 6.436571-44.763429 12.8-70.363429 262.436571 0 428.836571-185.636571 448-371.2 19.236571-179.2-89.6-371.2-249.563429-428.836571V194.56c0 25.6-12.8 38.4-32.036571 38.4-38.4 0-51.2-12.8-38.4-57.563429 12.8-70.436571 6.436571-140.8 0-211.236571 0-38.4 19.236571-31.963429 64-31.963429h160.036571c83.163429 0 95.963429-12.8 95.963429 31.963429 0 25.6-6.363429 38.4-38.4 38.4h-70.363429c95.963429 76.8 166.4 179.2 185.563429 313.636571zM71.094857 399.36c0 153.6 115.2 345.6 223.963429 364.836571v-153.6c0-32.036571 6.436571-38.4 38.4-38.4 32.036571 0 38.4 6.363429 38.4 38.4V847.36c0 32.036571-6.363429 38.4-38.4 38.4H96.694857C64.658286 885.76 58.294857 879.396571 58.294857 847.36c0-31.963429 0-38.4 38.4-38.4h102.4C-31.305143 623.396571-44.105143 341.796571 71.094857 149.796571c108.763429-185.636571 326.363429-256 460.8-236.836571-6.436571 25.6-6.436571 44.836571-12.8 70.436571C243.858286-23.04 71.094857 200.996571 71.094857 399.36z" horiz-adv-x="1024" />
<glyph glyph-name="jiantou" unicode="&#58987;" d="M1626.352941 305.694118L1014.964706-91.858824c-51.2-33.129412-123.482353-24.094118-162.635294 18.070589-15.058824 18.070588-24.094118 39.152941-24.094118 60.235294V781.552941C828.235294 835.764706 879.435294 880.941176 945.694118 880.941176c24.094118 0 51.2-6.023529 69.270588-21.082352L1626.352941 462.305882c51.2-33.129412 60.235294-96.376471 21.082353-138.541176-6.023529-6.023529-12.047059-12.047059-21.082353-18.070588zM60.235294 564.705882h843.294118v-361.411764H60.235294c-33.129412 0-60.235294 27.105882-60.235294 60.235294v240.941176c0 33.129412 27.105882 60.235294 60.235294 60.235294z" horiz-adv-x="1686" />
<glyph glyph-name="bianzu" unicode="&#58975;" d="M524.8 134.4H512l-12.8-6.4-6.4 12.8-492.8 192 51.2 121.6L512 281.6l460.8 172.8 51.2-121.6-492.8-185.6-6.4-12.8z m-12.8 256l-512 192V697.6l512 192 512-192v-115.2l-512-192z m0 358.4L198.4 646.4 512 537.6l313.6 108.8L512 748.8zM51.2 198.4L512 25.6l460.8 172.8 51.2-121.6-492.8-185.6-6.4-12.8H512l-12.8-6.4-6.4 12.8-492.8 192 51.2 121.6z" horiz-adv-x="1024" />
<glyph glyph-name="mimaruanjianjiami" unicode="&#58976;" d="M48.188235-128L30.117647 516.517647 975.811765 534.588235l18.070588-644.517647L48.188235-128z m72.282353 560.188235l12.047059-469.835294 771.011765 12.047059-12.047059 469.835294-771.011765-12.047059zM512 293.647059c36.141176 0 60.235294-24.094118 60.235294-60.235294v-120.470589c0-36.141176-24.094118-60.235294-60.235294-60.235294s-60.235294 24.094118-60.235294 60.235294v120.470589c0 36.141176 24.094118 60.235294 60.235294 60.235294zM740.894118 474.352941h-90.352942V655.058824c0 72.282353-60.235294 132.517647-132.517647 132.517647-72.282353 0-132.517647-60.235294-132.517647-132.517647v-180.705883H283.105882V655.058824C283.105882 781.552941 385.505882 883.952941 512 883.952941c126.494118 0 228.894118-102.4 228.894118-228.894117v-180.705883z" horiz-adv-x="1024" />
<glyph glyph-name="jiedian" unicode="&#58977;" d="M512 780.8c51.2 0 89.6-38.4 89.6-83.2S563.2 614.4 512 614.4s-89.6 38.4-89.6 83.2 38.4 83.2 89.6 83.2M512 896C396.8 896 300.8 806.4 300.8 697.6S396.8 499.2 512 499.2s211.2 89.6 211.2 198.4c0 51.2-19.2 102.4-64 140.8S569.6 896 512 896zM358.4 12.8c0-51.2 25.6-96 76.8-121.6s102.4-25.6 147.2 0 76.8 70.4 76.8 121.6c0 51.2-25.6 96-76.8 121.6-44.8 25.6-102.4 25.6-147.2 0-44.8-25.6-76.8-70.4-76.8-121.6zM0 70.4c0-51.2 25.6-96 76.8-121.6s102.4-25.6 147.2 0 76.8 70.4 76.8 121.6c0 51.2-25.6 96-76.8 121.6s-102.4 25.6-147.2 0S0 121.6 0 70.4zM723.2 70.4c0-51.2 25.6-96 76.8-121.6s102.4-25.6 147.2 0 76.8 70.4 76.8 121.6c0 51.2-25.6 96-76.8 121.6s-102.4 25.6-147.2 0-76.8-70.4-76.8-121.6zM480 614.4h64v-512h-64zM486.4 422.4l44.8 38.4 313.6-300.8-38.4-38.4zM224 115.2l-44.8 38.4 326.4 307.2 38.4-38.4z" horiz-adv-x="1024" />
<glyph glyph-name="chanshenggongsiyuedui" unicode="&#58978;" d="M473.6 339.2c-32 44.8-44.8 96-44.8 147.2 0 160 128 281.6 294.4 281.6S1024 646.4 1024 486.4s-128-281.6-294.4-281.6c-64 0-121.6 19.2-172.8 51.2l-134.4-128 64-64-83.2-76.8-64 64-38.4-38.4 64-64L275.2-128 128 12.8l345.6 326.4z m256 313.6c-102.4 0-179.2-70.4-179.2-166.4S627.2 320 729.6 320s179.2 70.4 179.2 166.4-89.6 166.4-179.2 166.4zM633.6 403.2c32 51.2 44.8 108.8 44.8 172.8 0 179.2-147.2 320-339.2 320S0 755.2 0 576s147.2-320 339.2-320c76.8 0 134.4 19.2 198.4 57.6l153.6-147.2-76.8-70.4 96-89.6 76.8 70.4 44.8-44.8-76.8-70.4 96-89.6 166.4 160-384 371.2zM339.2 768c115.2 0 204.8-83.2 204.8-192S454.4 384 339.2 384 134.4 467.2 134.4 576s96 192 204.8 192z" horiz-adv-x="1024" />
<glyph glyph-name="suanfaluojijiami" unicode="&#58979;" d="M736 460.8c12.8 6.4 19.2 19.2 19.2 38.4V736c0 12.8-6.4 32-19.2 38.4L531.2 889.6c-12.8 6.4-25.6 6.4-38.4 0L288 774.4c-12.8-6.4-25.6-19.2-25.6-38.4v-236.8c0-12.8 6.4-25.6 19.2-38.4l204.8-115.2c12.8-6.4 19.2-6.4 25.6-6.4 6.4 0 12.8 0 19.2 6.4l204.8 115.2z m-384 64v192L512 806.4l166.4-96L512 620.8v-185.6L352 524.8z m121.6-217.6L268.8 422.4c-12.8 6.4-32 6.4-44.8 0L19.2 307.2c-12.8-6.4-19.2-25.6-19.2-38.4v-236.8c0-12.8 6.4-32 19.2-38.4l204.8-115.2c6.4-6.4 12.8-6.4 19.2-6.4 6.4 0 12.8 0 19.2 6.4l204.8 115.2c12.8 6.4 19.2 19.2 19.2 38.4V268.8c6.4 12.8 0 32-12.8 38.4z m-390.4-256v192l166.4 96 160-96-166.4-96v-185.6l-160 89.6z m921.6 256l-204.8 115.2c-12.8 6.4-25.6 6.4-38.4 0L550.4 307.2c-12.8-6.4-19.2-25.6-19.2-38.4v-236.8c0-12.8 6.4-25.6 19.2-38.4l204.8-115.2c6.4-6.4 12.8-6.4 19.2-6.4 6.4 0 12.8 0 19.2 6.4l204.8 115.2c12.8 6.4 19.2 19.2 19.2 38.4V268.8c6.4 12.8 0 32-12.8 38.4z m-390.4-256v192l166.4 96 160-96-166.4-96v-185.6l-160 89.6z" horiz-adv-x="1024" />
<glyph glyph-name="shuju" unicode="&#58980;" d="M1024 723.2v-44.8L512 512 0 684.8v38.4L512 896l512-172.8zM512 428.8l-384 128L0 512v-44.8l512-172.8 512 172.8V512l-128 44.8-384-128z m0-217.6l-384 128-128-38.4v-44.8l512-172.8 512 172.8v44.8l-128 44.8-384-134.4zM512 0l-384 128-128-44.8v-44.8L512-128l512 172.8v44.8l-128 38.4-384-128z" horiz-adv-x="1024" />
<glyph glyph-name="shujuji" unicode="&#58981;" d="M73.142857 581.485714h870.4V896H73.142857v-314.514286z m80.457143 80.457143h716.8V815.542857H153.6v-153.6zM219.428571 698.514286h73.142858V778.971429H219.428571zM73.142857 223.085714h870.4V544.914286H73.142857v-321.828572z m80.457143 80.457143h716.8V464.457143H153.6v-160.914286zM219.428571 340.114286h73.142858V420.571429H219.428571zM73.142857-128h870.4V186.514286H73.142857V-128z m80.457143 80.457143h716.8v160.914286H153.6v-160.914286zM219.428571-10.971429h73.142858v80.457143H219.428571z" horiz-adv-x="1024" />
<glyph glyph-name="suanfacanshujiami" unicode="&#58982;" d="M64 896h96v-256H64zM448 896h96v-320H448zM832 896h96v-384H832zM64 256h96v-384H64zM448 192h96v-320H448zM832 128h96v-256H832zM128 448m-128 0a128 128 0 1 1 256 0 128 128 0 1 1-256 0ZM512 384m-128 0a128 128 0 1 1 256 0 128 128 0 1 1-256 0ZM896 320m-128 0a128 128 0 1 1 256 0 128 128 0 1 1-256 0Z" horiz-adv-x="1024" />
<glyph glyph-name="rengongzhineng" unicode="&#58983;" d="M184.912482-115.358025c-6.320988 0-18.962963 6.320988-25.283951 12.641976-6.320988 6.320988-12.641975 18.962963-12.641975 25.28395v246.518519s0 6.320988-6.320988 6.320987c-37.925926 6.320988-113.777778 18.962963-139.061728 63.209877 0 18.962963-6.320988 44.246914 6.320988 69.530864 25.283951 63.209877 75.851852 113.777778 101.135802 132.740741C115.381618 523.061728 184.912482 896 545.208778 896c195.950617 0 360.296296-94.814815 429.827161-246.518519 75.851852-164.345679 31.604938-372.938272-120.098766-562.567901v-151.703703c0-18.962963-12.641975-37.925926-31.604938-37.925926s-31.604938 18.962963-31.604938 37.925926v164.345679c0 6.320988 0 18.962963 6.320987 25.28395 139.061728 176.987654 183.308642 353.975309 120.098766 499.358025C861.258161 756.938272 722.196433 832.790123 551.529766 832.790123 210.196433 832.790123 184.912482 447.209877 178.591494 428.246914c0-12.641975-6.320988-18.962963-12.641975-25.283951-12.641975-12.641975-63.209877-56.888889-94.814815-120.098765v-6.320988c6.320988-18.962963 69.530864-31.604938 113.777778-37.925926 18.962963 0 31.604938-18.962963 31.604938-37.925926v-246.518518s0-6.320988 6.320988-6.320988h195.950617c18.962963 0 31.604938-18.962963 31.604938-37.925926s-12.641975-37.925926-31.604938-37.925926L184.912482-115.358025z m398.222222 322.370371c-12.641975 0-25.283951 12.641975-31.604938 25.28395l-18.962963 63.209877H412.468038h-6.320988L380.863099 225.975309c-6.320988-12.641975-18.962963-25.283951-31.604938-25.283951h-12.641975c-18.962963 6.320988-25.283951 25.283951-18.962963 44.246914l120.098765 341.333333c6.320988 18.962963 18.962963 31.604938 31.604938 31.604938s25.283951-12.641975 31.604939-25.28395l113.777777-341.333334c6.320988-18.962963-6.320988-37.925926-18.962962-44.246913h-12.641976zM469.356926 466.17284s-6.320988 0 0 0l-37.925926-94.814815v-6.320988H507.282852v6.320988l-37.925926 94.814815z m227.555556-259.160494c-18.962963 0-31.604938 12.641975-31.604938 31.604938V579.950617c0 18.962963 12.641975 31.604938 31.604938 31.604939s31.604938-12.641975 31.604938-31.604939v-341.333333c6.320988-18.962963-12.641975-31.604938-31.604938-31.604938z" horiz-adv-x="1024" />
<glyph glyph-name="yuzhimiyuejiami" unicode="&#58984;" d="M390.4 403.2C358.4 454.4 345.6 512 345.6 576c0 179.2 147.2 320 339.2 320S1024 755.2 1024 576s-147.2-320-339.2-320c-76.8 0-134.4 19.2-198.4 57.6l-153.6-147.2 76.8-70.4-96-89.6-76.8 70.4-44.8-44.8 76.8-70.4L166.4-128 0 32l390.4 371.2zM684.8 768C569.6 768 480 684.8 480 576s89.6-192 204.8-192 204.8 83.2 204.8 192-96 192-204.8 192z" horiz-adv-x="1024" />
<glyph glyph-name="suanfasheji" unicode="&#58985;" d="M0 896h1024v-1016.685714H0zM1024 164.571429H0V896h1024v-731.428571zM87.771429 252.342857h848.457142V808.228571H87.771429v-555.885714zM219.428571 676.571429h585.142858v-87.771429H219.428571zM219.428571 457.142857h292.571429v-87.771428H219.428571zM877.714286-120.685714H146.285714v219.428571h731.428572v-219.428571z m-643.657143 87.771428h555.885714v43.885715H234.057143v-43.885715z" horiz-adv-x="1024" />
<glyph glyph-name="yunjisuan" unicode="&#58986;" d="M781.442985 166.019612l-6.39173 70.309038s121.442883 6.391731 159.793267 89.48423c44.742115 76.700768-44.742115 185.36019-44.742115 185.36019l-12.783461 12.783461 6.39173 19.175192c12.783461 51.133846 6.391731 89.48423-12.783461 115.051153-31.958653 38.350384-95.87596 38.350384-95.87596 38.350384h-25.566923l-6.391731 19.175192c-12.783461 25.566923-70.309038 102.267691-172.576729 108.659422-127.834614 12.783461-191.751921-95.87596-191.751921-95.87596l-12.783461-19.175193-25.566923 6.391731c-63.917307 12.783461-102.267691 12.783461-127.834614-12.783461-38.350384-38.350384-31.958653-115.051153-25.566923-140.618076l6.391731-25.566922-31.958654-12.783462c-6.391731 0-108.659422-51.133846-89.484229-159.793267 19.175192-108.659422 127.834614-121.442883 127.834614-121.442883L193.403761 172.411343c-57.525576 6.391731-166.184998 57.525576-191.751921 178.968459-12.783461 115.051153 51.133846 191.751921 108.659422 223.710575-6.391731 44.742115-6.391731 127.834614 44.742115 178.968459 44.742115 38.350384 102.267691 51.133846 172.576729 31.958654 31.958653 38.350384 115.051153 121.442883 242.885766 108.659422 121.442883-12.783461 191.751921-89.48423 217.318844-134.226345 31.958653 0 89.48423-12.783461 127.834614-57.525576 31.958653-38.350384 44.742115-89.48423 31.958653-159.793268 25.566923-38.350384 95.87596-153.401537 44.742115-249.277497-44.742115-115.051153-204.535382-127.834614-210.927113-127.834614zM749.484332 50.96846H250.929337c-38.350384 0-70.309038 31.958653-70.309037 70.309037V453.647494c0 38.350384 31.958653 70.309038 70.309037 70.309037h492.163264c38.350384 0 70.309038-31.958653 70.309038-70.309037V127.669228c6.391731-44.742115-25.566923-76.700768-63.917307-76.700768zM250.929337 453.647494V127.669228h492.163264V453.647494H250.929337zM749.484332 217.153458H250.929337c-31.958653 0-63.917307-25.566923-63.917307-63.917307v-31.958654c0-31.958653 25.566923-63.917307 63.917307-63.917307h492.163264c31.958653 0 63.917307 25.566923 63.917307 63.917307v31.958654c0 31.958653-25.566923 63.917307-57.525576 63.917307z m-57.525577-319.586535H314.846644c-19.175192 0-31.958653 19.175192-31.958653 31.958653 0 19.175192 19.175192 31.958653 31.958653 31.958654h377.112111c19.175192 0 31.958653-19.175192 31.958654-31.958654s-12.783461-31.958653-31.958654-31.958653zM672.783563-102.433077H327.630106l70.309037 217.318844h191.751921l83.092499-217.318844z m-249.277497 76.700768h147.009806l-25.566923 76.700769H455.46472l-31.958654-76.700769z" horiz-adv-x="1024" />
</font>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Binary file not shown.

@ -0,0 +1,75 @@
//get下载
export function downLoadLink(url: string, filename?: string) {
let link = document.createElement('a');
document.body.appendChild(link);
link.href = url;
if (filename) {
link.title = filename;
link.download = filename;
}
//兼容火狐浏览器
let evt = document.createEvent('MouseEvents');
evt.initEvent('click', false, false);
link.dispatchEvent(evt);
document.body.removeChild(link);
}
//post下载
/**
* blob
* @param {String} url
* @return {Promise}
*/
export function getBlob(url: any) {
return new Promise((resolve) => {
const xhr = new window.XMLHttpRequest();
xhr.open('GET', url, true);
xhr.withCredentials = true;
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
}
};
xhr.send();
});
}
/**
*
* @param {Blob} blob
* @param {String} filename
*/
export function saveAs(blob: any, filename: any) {
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
} else {
const link = document.createElement('a');
const body: any = document.querySelector('body');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
// fix Firefox
link.style.display = 'none';
body.appendChild(link);
link.click();
body.removeChild(link);
window.URL.revokeObjectURL(link.href);
}
}
/**
*
* @param {String} url
* @param {String} filename
*/
export function download(url: any, filename: any) {
getBlob(url).then((blob) => {
saveAs(blob, filename);
});
}

@ -0,0 +1,80 @@
/**
* request
* api : https://github.com/umijs/umi-request
*/
import { extend } from 'umi-request';
import { notification } from 'antd';
import publicUrl from '@/utils/url';
// import { history } from 'umi';
const codeMessage: any = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};
/**
*
*/
const errorHandler = (error: any) => {
const { response } = error;
console.log(error, 'error');
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
const { status, url } = response;
notification.error({
message: `请求错误 ${status}: ${url}`,
description: errorText,
});
} else if (!response) {
notification.error({
description: '您的网络发生异常,无法连接服务器',
message: '网络异常',
});
}
throw error;
};
/**
* request
*/
const request = extend({
errorHandler, // 默认错误处理
prefix: publicUrl, //地址
crossOrigin: true, // 开启CORS跨域
method: 'get', //默认get
credentials: 'include', // 默认请求是否带上cookie
});
// 中间件,对请求前添加 userId token 的基础参数
request.interceptors.request.use((url, options) => {
const newOptions = { ...options };
// if (!(newOptions.data instanceof FormData)) {
// newOptions.data = {
// ...newOptions.data,
// // token: 'adsadsafcdscd',
// };
// } else {
// // newOptions.data.append('token', 'adsadsafcdscd');
// }
return {
url: `${url}`,
options: { ...newOptions },
};
});
export default request;

@ -0,0 +1,13 @@
export const publicPath =
process.env.NODE_ENV === 'development' ? '/' : '/react/build/';
const env = {
dev: 'https://testxgd.educoder.net',
build:
window.location.origin === 'http://47.111.130.18:56841'
? 'https://testxgd.educoder.net'
: 'http://localhost:48982',
};
console.log('当前环境:', process.env.NODE_ENV);
const url = process.env.NODE_ENV === 'development' ? env.dev : env.build;
export default url;

@ -0,0 +1,9 @@
import { getDvaApp } from 'umi';
export const getInitData = (type: string) => {
const { basic }: any = getDvaApp()._store.getState();
const { initData }: any = basic;
const param = { ...initData[0], ...initData[1], ...initData[2] };
console.log(param, param[type], type, 'initData');
return param[type];
};

@ -0,0 +1,37 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"importHelpers": true,
"jsx": "react-jsx",
"esModuleInterop": true,
"sourceMap": true,
"baseUrl": "./",
"strict": true,
"paths": {
"@/*": ["src/*"],
"@@/*": ["src/.umi/*"]
},
"allowSyntheticDefaultImports": true
},
"include": [
"mock/**/*",
"src/**/*",
"config/**/*",
".umirc.ts",
"typings.d.ts"
],
"exclude": [
"node_modules",
"lib",
"es",
"dist",
"typings",
"**/__test__",
"test",
"docs",
"tests"
]
}

10
typings.d.ts vendored

@ -0,0 +1,10 @@
declare module '*.css';
declare module '*.less';
declare module '*.png';
declare module '*.svg' {
export function ReactComponent(
props: React.SVGProps<SVGSVGElement>,
): React.ReactElement;
const url: string;
export default url;
}
Loading…
Cancel
Save