custom-新弘农业/V2-薪资核算表格添加序号列
liyongshun 3 years ago
commit 8394cf8872

55
.gitignore vendored

@ -0,0 +1,55 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/slave/node_modules
/npm-debug.log*
/slave/npm-debug.log*
/yarn-error.log
/slave/yarn-error.log
/yarn.lock
/slave/yarn.lock
/package-lock.json
/slave/package-lock.json
# production
/dist
/slave/dist
# misc
.DS_Store
# umi
/src/.umi
/src/.umi-production
/src/.umi-test
/.env.local
/slave/src/.umi
/slave/src/.umi-production
/slave/src/.umi-test
/slave/.env.local
# production
/.vscode
# misc
npm-debug.log*
yarn-error.log
/coverage
.idea
*bak
# visual studio code
.history
*.log
functions/mock
.temp/**
# screenshot
screenshot
.firebase
/.temp/
/lib/

@ -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,67 @@
# 微前端Slave端框架
## 私服配置
- 安装nrm
```
npm i nrm -g
```
- 私服配置
```
# 1. 新增私服源
nrm add sz http://192.168.10.220:7070/repository/casic-frontend/
# 2. 切换到新源
nrm use sz
# 3. 增加认证
nrm add-auth bmpodHN6Om5qaHRzeg== sz
```
## 准备工作
- 请使用node v12 版本
- 框架采用umi@3.5
- 状态管理支持MobX和dva 详情请参考
```
https://umijs.org/zh-CN/plugins/plugin-model
```
- 服务统一在/api管理请参考样例
### 关于图片
从模板项目克隆过来可能会存在图片无法显示的问题,请到 http://192.168.10.236:81/public-htsz/micro-frontend-slave 下载后进行覆盖
## 开始
- 安装依赖
```bash
$ yarn i 或者 npm i
```
- 启动服务
```bash
$ npm start
```
## 开发环境配置
- config/config.dev.ts
```
proxy: {
'/gateway/idm': {
'target': 'http://{开发环境对应的微服务地址}:{端口号}/idm',
'changeOrigin': true,
'pathRewrite': {
'^/gateway/idm': ''
}
},
}
```
## 参数
* 各个应用系统需要后台参数 src/api/setting.service.tsx
* 目前配置的是 idm 的参数,各个应用系统根据实际业务需要进行调整
* 参数查询请使用 SettingService的getSystemParam的方法
* 根据环境变量配置,则需要配置全所有的参数
* 若需要多个微服务参数合并,请看 src/api/setting.service.tsx 中TODO

@ -0,0 +1,37 @@
import { defineConfig } from 'umi';
export default defineConfig({
define: {
ENV: 'dev',
},
base: '/',
publicPath: '/',
proxy: {
'/gateway': {
// 'target': 'http://gateway',
target: 'https://yule-dev.njhtsz.com',
changeOrigin: true,
},
// '/gateway/idm': {
// target: 'http://192.168.20.5:9110',
// changeOrigin: true,
// pathRewrite: {
// '^/gateway/idm': '',
// },
// },
// '/gateway/idm': {
// target: 'http://localhost:9110',
// changeOrigin: true,
// pathRewrite: {
// '^/gateway/idm': '',
// },
// },
// '/gateway/esoaservice': {
// target: 'http://192.168.20.215:10100',
// changeOrigin: true,
// pathRewrite: {
// '^/gateway/esoaservice': '',
// },
// },
},
});

@ -0,0 +1,40 @@
import { defineConfig } from 'umi';
export default defineConfig({
define: {
ENV: 'prod',
},
antd: false,
base: '/slave',
publicPath: '/slave/static/',
externals: {
echarts: 'echarts',
moment: 'moment',
react: 'React',
'react-dom': 'ReactDOM',
mobx: 'mobx',
antd: 'antd',
},
chunks: ['vendors', 'umi'],
chainWebpack: function(config, { webpack }) {
config.merge({
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
minChunks: 3,
automaticNameDelimiter: '.',
cacheGroups: {
vendor: {
name: 'vendors',
test({ resource }: any) {
return /[\\/]node_modules[\\/]/.test(resource);
},
priority: 10,
},
},
},
},
});
},
});

@ -0,0 +1,113 @@
import { defineConfig, utils } from 'umi';
import { resolve } from 'path';
const fs = require('fs');
const path = require('path');
const lessToJs = require('less-vars-to-js');
const { winPath } = utils;
export default defineConfig({
//mfsu配置暂时有问题
// mfsu: {
// mfName: 'micro-slave'
// },
title: 'hi demo',
runtimePublicPath: true,
webpack5: {},
qiankun: {
slave: {},
},
hash: true,
history: {
type: 'hash',
},
ignoreMomentLocale: true,
nodeModulesTransform: {
type: 'none',
exclude: [],
},
locale: {
default: 'zh-CN',
baseNavigator: true,
antd: true,
},
lessLoader: {
javascriptEnabled: true,
modifyVars: {
'root-entry-name': 'default', //解决 Variable @root-entry-name is undefined 错误
},
},
dynamicImport: {
loading: '@/lib/PageLoading',
},
extraBabelPlugins: [],
cssLoader: {
localsConvention: 'camelCase',
modules: {
getLocalIdent: (
context: {
resourcePath: string;
},
_: string,
localName: string,
) => {
if (
context.resourcePath.includes('pages/home') ||
context.resourcePath.includes('node_modules') ||
context.resourcePath.includes('ant.[id].pro.less') ||
context.resourcePath.includes('global.less')
) {
return localName;
}
const match = context.resourcePath.match(/src(.*)/);
if (match && match[1]) {
let antdProPath = match[1].replace('.less', '');
antdProPath = antdProPath.replace(/\[/g, '');
antdProPath = antdProPath.replace(/\]/g, '');
const arr = winPath(antdProPath)
.split('/')
.map((a: string) => a.replace(/([A-Z])/g, '-$1'))
.map((a: string) => a.toLowerCase());
return `sz-${arr.join('-')}-${localName}`.replace(/--/g, '-');
}
return localName;
},
},
},
define: {
_VERSION_: '1.1.0',
},
alias: {
themes: resolve(__dirname, '../src/themes'),
'@/common': resolve(__dirname, '../src/common/'),
'@/utils': resolve(__dirname, '../src/utils/'),
'@/config': resolve(__dirname, '../src/config/'),
'@/lib': resolve(__dirname, '../src/lib/'),
},
dva: {
disableModelsReExport: true,
lazyLoad: true,
immer: {
enableES5: true,
},
hmr: false,
},
theme: lessToJs(
fs.readFileSync(path.join(__dirname, '../src/themes/default.less'), 'utf8'),
),
externals: {
jquery: 'jQuery',
$: 'jQuery',
zTree: 'zTree',
},
authorize: [
{
guard: ['@/gard/UserGard.tsx'],
include: /\/.*/,
exclude: /\/passport\/.*/,
},
{
guard: ['@/gard/AdminGard.tsx'],
include: /\/manage.*/,
},
],
});

@ -0,0 +1,148 @@
import _ from 'lodash';
const menus = [
{
id: '1',
path: '/app',
name: '应用开发',
title: '应用开发',
icon: 'icon-appstore',
type: 'native',
},
{
id: '2',
path: '/email',
name: '邮箱',
title: '邮箱',
icon: 'icon-check-square',
type: 'native',
},
{
id: '3',
path: '/workbench',
name: '工作台',
title: '工作台',
icon: 'icon-laptop',
type: 'native',
},
{
id: '4',
path: '/idm/tenantManagement',
name: '租户管理',
title: '租户管理',
icon: 'icon-laptop',
type: 'native',
},
{
id: '5',
path: '/idm/orgManagement',
name: '组织管理',
title: '组织管理',
icon: 'icon-laptop',
type: 'native',
},
{
id: '6',
path: '/idm/posiManagement',
name: '岗位管理',
title: '岗位管理',
icon: 'icon-laptop',
type: 'native',
},
{
id: '7',
path: '/idm/groupManagement',
name: '群组管理',
title: '群组管理',
icon: 'icon-laptop',
type: 'native',
},
{
id: '8',
path: '/idm/posiGroupManagement',
name: '岗位组管理',
title: '岗位组管理',
icon: 'icon-laptop',
type: 'native',
},
{
id: '9',
path: '/idm/roleManagement',
name: '角色管理',
title: '角色管理',
icon: 'icon-laptop',
type: 'native',
},
{
id: '10',
path: '/idm/appManagement',
name: '应用管理',
title: '应用管理',
icon: 'icon-laptop',
type: 'native',
},
{
id: '11',
path: '/idm/resourceManagement',
name: '资源管理',
title: '资源管理',
icon: 'icon-laptop',
type: 'native',
},
{
id: '12',
path: '/idm/resGroupManagement',
name: '资源组管理',
title: '资源组管理',
icon: 'icon-laptop',
type: 'native',
},
];
export default {
// 支持值为 Object 和 Array
'GET /gateway/idm/api/menus': {
code: 0,
message: '成功',
data: menus,
},
'GET /gateway/idm/api/menus/:appId/menu': (req: any, res: any) => {
const { appId } = req.params;
if (appId) {
const result = _.filter(menus, (m) => m.appId === appId);
res.send({
code: 0,
message: '成功',
data: result,
});
} else {
res.end();
}
},
'GET /gateway/idm/api/menus/:id': (req: any, res: any) => {
const { id } = req.params;
if (id) {
const menu = _.find(menus, (m) => menu.id === id);
res.send({
code: 0,
message: '成功',
data: menu,
});
} else {
res.end();
}
},
'GET /gateway/idm/api/menus/:id/children': (req: any, res: any) => {
const { id } = req.params;
if (id) {
const result = _.filter(menus, (m) => m.pid === id);
res.send({
code: 0,
message: '成功',
data: result,
});
} else {
res.end();
}
},
};

@ -0,0 +1,75 @@
{
"name": "micro-frontend-slave",
"private": true,
"scripts": {
"start": "cross-env NODE_OPTIONS=--max-old-space-size=8192 NODE_ENV=development UMI_ENV=dev PORT=7607 umi dev",
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 NODE_ENV=production UMI_ENV=prod umi build",
"postinstall": "umi generate tmp",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"test": "umi-test",
"test:coverage": "umi-test --coverage",
"this-start": "npm start && cd demo && npm start"
},
"gitHooks": {},
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"dependencies": {
"@ant-design/pro-layout": "6.32.1",
"@formily/antd": "^2.0.6",
"@types/lodash": "^4.14.172",
"@ztree/ztree_v3": "^3.5.42",
"ahooks": "^3.1.3",
"antd": "^4.17.3",
"axios": "^0.22.0",
"fbemitter": "^3.0.0",
"js-base64": "^3.6.1",
"js-cookie": "^2.2.1",
"jsencrypt": "^3.2.1",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"mobx": "^6.3.2",
"mobx-react": "^7.2.0",
"qs": "^6.10.1",
"react-beautiful-dnd": "^13.1.0",
"react-container-query": "^0.12.0",
"react-contexify": "^5.0.0",
"react-dnd": "^14.0.3",
"react-dnd-html5-backend": "^14.0.1",
"react-fast-compare": "^3.2.0",
"react-media": "^1.10.0",
"react-sortable-hoc": "^2.0.0",
"simple-query-string": "^1.3.2",
"solarlunar": "^2.0.7",
"store": "^2.0.12",
"uuid": "^3.3.2"
},
"peerDependencies": {
"jquery": "^3.6.0",
"moment": "^2.25.3"
},
"devDependencies": {
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
"@umijs/plugin-access": "2.4.2",
"umi-plugin-authorize": "^2.8.12",
"@umijs/plugin-dva": "^0.13.0",
"@umijs/plugin-initial-state": "^2.4.0",
"@umijs/plugin-locale": "^0.15.0",
"@umijs/plugin-model": "^2.6.1",
"@umijs/plugin-qiankun": "^2.36.0",
"@umijs/test": "^3.5.20",
"cross-env": "^7.0.3",
"less-vars-to-js": "^1.3.0",
"lint-staged": "^10.0.7",
"prettier": "^2.2.0",
"typescript": "^4.3.5",
"umi": "^3.5.20",
"yorkie": "^2.0.0"
}
}

File diff suppressed because one or more lines are too long

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@ -0,0 +1 @@
<?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 t="1605174369977" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="927" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M743.2704 264.32l91.8784 53.0176v130.56l-156.5184 90.368-0.384-126.848-97.28-56.32zM404.9664 826.3936v-173.9008l103.7568 59.5456 102.912-59.3152-0.7936 173.0048-103.7056 59.5968-102.0928-58.88z m42.3168-472.704l-108.1088 61.9008v121.7024L179.2 444.0832v-126.6176l102.5792-59.264 165.6576 95.5136z m66.8928 38.7072l98.4576 56.8064-0.6144 127.4112-103.3728 59.6992-103.808-60.5952v-122.2656l109.3888-61.056z" fill="#0188FB" p-id="928"></path><path d="M673.5872 224.128l-160.4096 91.8272L347.52 220.16 507.1616 128zM338.7136 788.1472L179.2 695.9872v-172.9536l159.744 91.8272v173.44z m496.4352-264.576v172.4928l-155.8272 89.856-0.4608-172.2368 156.16-90.2144z" fill="#0188FB" opacity=".5" p-id="929"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

11658
public/js/less.min.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,36 @@
/**
* Copyright (c) 2014-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Immutable=e()}(this,function(){"use strict";function t(t,e){e&&(t.prototype=Object.create(e.prototype)),t.prototype.constructor=t}function e(t){return o(t)?t:O(t)}function r(t){return u(t)?t:x(t)}function n(t){return s(t)?t:k(t)}function i(t){return o(t)&&!a(t)?t:A(t)}function o(t){return!(!t||!t[ar])}function u(t){return!(!t||!t[hr])}function s(t){return!(!t||!t[fr])}function a(t){return u(t)||s(t)}function h(t){return!(!t||!t[cr])}function f(t){return t.value=!1,t}function c(t){t&&(t.value=!0)}function _(){}function p(t,e){e=e||0;for(var r=Math.max(0,t.length-e),n=Array(r),i=0;r>i;i++)n[i]=t[i+e];return n}function v(t){return void 0===t.size&&(t.size=t.__iterate(y)),t.size}function l(t,e){if("number"!=typeof e){var r=e>>>0;if(""+r!==e||4294967295===r)return NaN;e=r}return 0>e?v(t)+e:e}function y(){return!0}function d(t,e,r){return(0===t||void 0!==r&&-r>=t)&&(void 0===e||void 0!==r&&e>=r)}function m(t,e){return w(t,e,0)}function g(t,e){return w(t,e,e)}function w(t,e,r){return void 0===t?r:0>t?Math.max(0,e+t):void 0===e?t:Math.min(e,t)}function S(t){this.next=t}function z(t,e,r,n){var i=0===t?e:1===t?r:[e,r];return n?n.value=i:n={value:i,done:!1},n}function I(){return{value:void 0,done:!0}}function b(t){return!!M(t)}function q(t){return t&&"function"==typeof t.next}function D(t){var e=M(t);return e&&e.call(t)}function M(t){var e=t&&(zr&&t[zr]||t[Ir]);return"function"==typeof e?e:void 0}function E(t){return t&&"number"==typeof t.length}function O(t){return null===t||void 0===t?T():o(t)?t.toSeq():C(t)}function x(t){return null===t||void 0===t?T().toKeyedSeq():o(t)?u(t)?t.toSeq():t.fromEntrySeq():W(t)}function k(t){return null===t||void 0===t?T():o(t)?u(t)?t.entrySeq():t.toIndexedSeq():B(t)}function A(t){return(null===t||void 0===t?T():o(t)?u(t)?t.entrySeq():t:B(t)).toSetSeq()}function j(t){this._array=t,this.size=t.length}function K(t){var e=Object.keys(t);this._object=t,this._keys=e,
this.size=e.length}function R(t){this._iterable=t,this.size=t.length||t.size}function U(t){this._iterator=t,this._iteratorCache=[]}function L(t){return!(!t||!t[qr])}function T(){return Dr||(Dr=new j([]))}function W(t){var e=Array.isArray(t)?new j(t).fromEntrySeq():q(t)?new U(t).fromEntrySeq():b(t)?new R(t).fromEntrySeq():"object"==typeof t?new K(t):void 0;if(!e)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+t);return e}function B(t){var e=J(t);if(!e)throw new TypeError("Expected Array or iterable object of values: "+t);return e}function C(t){var e=J(t)||"object"==typeof t&&new K(t);if(!e)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+t);return e}function J(t){return E(t)?new j(t):q(t)?new U(t):b(t)?new R(t):void 0}function N(t,e,r,n){var i=t._cache;if(i){for(var o=i.length-1,u=0;o>=u;u++){var s=i[r?o-u:u];if(e(s[1],n?s[0]:u,t)===!1)return u+1}return u}return t.__iterateUncached(e,r)}function P(t,e,r,n){var i=t._cache;if(i){var o=i.length-1,u=0;return new S(function(){var t=i[r?o-u:u];return u++>o?I():z(e,n?t[0]:u-1,t[1])})}return t.__iteratorUncached(e,r)}function H(t,e){return e?V(e,t,"",{"":t}):Y(t)}function V(t,e,r,n){return Array.isArray(e)?t.call(n,r,k(e).map(function(r,n){return V(t,r,n,e)})):Q(e)?t.call(n,r,x(e).map(function(r,n){return V(t,r,n,e)})):e}function Y(t){return Array.isArray(t)?k(t).map(Y).toList():Q(t)?x(t).map(Y).toMap():t}function Q(t){return t&&(t.constructor===Object||void 0===t.constructor)}function X(t,e){if(t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1;if("function"==typeof t.valueOf&&"function"==typeof e.valueOf){if(t=t.valueOf(),e=e.valueOf(),t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1}return"function"==typeof t.equals&&"function"==typeof e.equals&&t.equals(e)?!0:!1}function F(t,e){if(t===e)return!0;if(!o(e)||void 0!==t.size&&void 0!==e.size&&t.size!==e.size||void 0!==t.__hash&&void 0!==e.__hash&&t.__hash!==e.__hash||u(t)!==u(e)||s(t)!==s(e)||h(t)!==h(e))return!1;if(0===t.size&&0===e.size)return!0;
var r=!a(t);if(h(t)){var n=t.entries();return e.every(function(t,e){var i=n.next().value;return i&&X(i[1],t)&&(r||X(i[0],e))})&&n.next().done}var i=!1;if(void 0===t.size)if(void 0===e.size)"function"==typeof t.cacheResult&&t.cacheResult();else{i=!0;var f=t;t=e,e=f}var c=!0,_=e.__iterate(function(e,n){return(r?t.has(e):i?X(e,t.get(n,yr)):X(t.get(n,yr),e))?void 0:(c=!1,!1)});return c&&t.size===_}function G(t,e){if(!(this instanceof G))return new G(t,e);if(this._value=t,this.size=void 0===e?1/0:Math.max(0,e),0===this.size){if(Mr)return Mr;Mr=this}}function Z(t,e){if(!t)throw Error(e)}function $(t,e,r){if(!(this instanceof $))return new $(t,e,r);if(Z(0!==r,"Cannot step a Range by 0"),t=t||0,void 0===e&&(e=1/0),r=void 0===r?1:Math.abs(r),t>e&&(r=-r),this._start=t,this._end=e,this._step=r,this.size=Math.max(0,Math.ceil((e-t)/r-1)+1),0===this.size){if(Er)return Er;Er=this}}function tt(){throw TypeError("Abstract")}function et(){}function rt(){}function nt(){}function it(t){return t>>>1&1073741824|3221225471&t}function ot(t){if(t===!1||null===t||void 0===t)return 0;if("function"==typeof t.valueOf&&(t=t.valueOf(),t===!1||null===t||void 0===t))return 0;if(t===!0)return 1;var e=typeof t;if("number"===e){var r=0|t;for(r!==t&&(r^=4294967295*t);t>4294967295;)t/=4294967295,r^=t;return it(r)}if("string"===e)return t.length>Ur?ut(t):st(t);if("function"==typeof t.hashCode)return t.hashCode();if("object"===e)return at(t);if("function"==typeof t.toString)return st(""+t);throw Error("Value type "+e+" cannot be hashed.")}function ut(t){var e=Wr[t];return void 0===e&&(e=st(t),Tr===Lr&&(Tr=0,Wr={}),Tr++,Wr[t]=e),e}function st(t){for(var e=0,r=0;t.length>r;r++)e=31*e+t.charCodeAt(r)|0;return it(e)}function at(t){var e;if(jr&&(e=Or.get(t),void 0!==e))return e;if(e=t[Rr],void 0!==e)return e;if(!Ar){if(e=t.propertyIsEnumerable&&t.propertyIsEnumerable[Rr],void 0!==e)return e;if(e=ht(t),void 0!==e)return e}if(e=++Kr,1073741824&Kr&&(Kr=0),jr)Or.set(t,e);else{if(void 0!==kr&&kr(t)===!1)throw Error("Non-extensible objects are not allowed as keys.");
if(Ar)Object.defineProperty(t,Rr,{enumerable:!1,configurable:!1,writable:!1,value:e});else if(void 0!==t.propertyIsEnumerable&&t.propertyIsEnumerable===t.constructor.prototype.propertyIsEnumerable)t.propertyIsEnumerable=function(){return this.constructor.prototype.propertyIsEnumerable.apply(this,arguments)},t.propertyIsEnumerable[Rr]=e;else{if(void 0===t.nodeType)throw Error("Unable to set a non-enumerable property on object.");t[Rr]=e}}return e}function ht(t){if(t&&t.nodeType>0)switch(t.nodeType){case 1:return t.uniqueID;case 9:return t.documentElement&&t.documentElement.uniqueID}}function ft(t){Z(t!==1/0,"Cannot perform this action with an infinite size.")}function ct(t){return null===t||void 0===t?zt():_t(t)&&!h(t)?t:zt().withMutations(function(e){var n=r(t);ft(n.size),n.forEach(function(t,r){return e.set(r,t)})})}function _t(t){return!(!t||!t[Br])}function pt(t,e){this.ownerID=t,this.entries=e}function vt(t,e,r){this.ownerID=t,this.bitmap=e,this.nodes=r}function lt(t,e,r){this.ownerID=t,this.count=e,this.nodes=r}function yt(t,e,r){this.ownerID=t,this.keyHash=e,this.entries=r}function dt(t,e,r){this.ownerID=t,this.keyHash=e,this.entry=r}function mt(t,e,r){this._type=e,this._reverse=r,this._stack=t._root&&wt(t._root)}function gt(t,e){return z(t,e[0],e[1])}function wt(t,e){return{node:t,index:0,__prev:e}}function St(t,e,r,n){var i=Object.create(Cr);return i.size=t,i._root=e,i.__ownerID=r,i.__hash=n,i.__altered=!1,i}function zt(){return Jr||(Jr=St(0))}function It(t,e,r){var n,i;if(t._root){var o=f(dr),u=f(mr);if(n=bt(t._root,t.__ownerID,0,void 0,e,r,o,u),!u.value)return t;i=t.size+(o.value?r===yr?-1:1:0)}else{if(r===yr)return t;i=1,n=new pt(t.__ownerID,[[e,r]])}return t.__ownerID?(t.size=i,t._root=n,t.__hash=void 0,t.__altered=!0,t):n?St(i,n):zt()}function bt(t,e,r,n,i,o,u,s){return t?t.update(e,r,n,i,o,u,s):o===yr?t:(c(s),c(u),new dt(e,n,[i,o]))}function qt(t){return t.constructor===dt||t.constructor===yt}function Dt(t,e,r,n,i){if(t.keyHash===n)return new yt(e,n,[t.entry,i]);var o,u=(0===r?t.keyHash:t.keyHash>>>r)&lr,s=(0===r?n:n>>>r)&lr,a=u===s?[Dt(t,e,r+pr,n,i)]:(o=new dt(e,n,i),
s>u?[t,o]:[o,t]);return new vt(e,1<<u|1<<s,a)}function Mt(t,e,r,n){t||(t=new _);for(var i=new dt(t,ot(r),[r,n]),o=0;e.length>o;o++){var u=e[o];i=i.update(t,0,void 0,u[0],u[1])}return i}function Et(t,e,r,n){for(var i=0,o=0,u=Array(r),s=0,a=1,h=e.length;h>s;s++,a<<=1){var f=e[s];void 0!==f&&s!==n&&(i|=a,u[o++]=f)}return new vt(t,i,u)}function Ot(t,e,r,n,i){for(var o=0,u=Array(vr),s=0;0!==r;s++,r>>>=1)u[s]=1&r?e[o++]:void 0;return u[n]=i,new lt(t,o+1,u)}function xt(t,e,n){for(var i=[],u=0;n.length>u;u++){var s=n[u],a=r(s);o(s)||(a=a.map(function(t){return H(t)})),i.push(a)}return jt(t,e,i)}function kt(t,e,r){return t&&t.mergeDeep&&o(e)?t.mergeDeep(e):X(t,e)?t:e}function At(t){return function(e,r,n){if(e&&e.mergeDeepWith&&o(r))return e.mergeDeepWith(t,r);var i=t(e,r,n);return X(e,i)?e:i}}function jt(t,e,r){return r=r.filter(function(t){return 0!==t.size}),0===r.length?t:0!==t.size||t.__ownerID||1!==r.length?t.withMutations(function(t){for(var n=e?function(r,n){t.update(n,yr,function(t){return t===yr?r:e(t,r,n)})}:function(e,r){t.set(r,e)},i=0;r.length>i;i++)r[i].forEach(n)}):t.constructor(r[0])}function Kt(t,e,r,n){var i=t===yr,o=e.next();if(o.done){var u=i?r:t,s=n(u);return s===u?t:s}Z(i||t&&t.set,"invalid keyPath");var a=o.value,h=i?yr:t.get(a,yr),f=Kt(h,e,r,n);return f===h?t:f===yr?t.remove(a):(i?zt():t).set(a,f)}function Rt(t){return t-=t>>1&1431655765,t=(858993459&t)+(t>>2&858993459),t=t+(t>>4)&252645135,t+=t>>8,t+=t>>16,127&t}function Ut(t,e,r,n){var i=n?t:p(t);return i[e]=r,i}function Lt(t,e,r,n){var i=t.length+1;if(n&&e+1===i)return t[e]=r,t;for(var o=Array(i),u=0,s=0;i>s;s++)s===e?(o[s]=r,u=-1):o[s]=t[s+u];return o}function Tt(t,e,r){var n=t.length-1;if(r&&e===n)return t.pop(),t;for(var i=Array(n),o=0,u=0;n>u;u++)u===e&&(o=1),i[u]=t[u+o];return i}function Wt(t){var e=Pt();if(null===t||void 0===t)return e;if(Bt(t))return t;var r=n(t),i=r.size;return 0===i?e:(ft(i),i>0&&vr>i?Nt(0,i,pr,null,new Ct(r.toArray())):e.withMutations(function(t){t.setSize(i),r.forEach(function(e,r){return t.set(r,e)})}))}function Bt(t){
return!(!t||!t[Vr])}function Ct(t,e){this.array=t,this.ownerID=e}function Jt(t,e){function r(t,e,r){return 0===e?n(t,r):i(t,e,r)}function n(t,r){var n=r===s?a&&a.array:t&&t.array,i=r>o?0:o-r,h=u-r;return h>vr&&(h=vr),function(){if(i===h)return Xr;var t=e?--h:i++;return n&&n[t]}}function i(t,n,i){var s,a=t&&t.array,h=i>o?0:o-i>>n,f=(u-i>>n)+1;return f>vr&&(f=vr),function(){for(;;){if(s){var t=s();if(t!==Xr)return t;s=null}if(h===f)return Xr;var o=e?--f:h++;s=r(a&&a[o],n-pr,i+(o<<n))}}}var o=t._origin,u=t._capacity,s=Gt(u),a=t._tail;return r(t._root,t._level,0)}function Nt(t,e,r,n,i,o,u){var s=Object.create(Yr);return s.size=e-t,s._origin=t,s._capacity=e,s._level=r,s._root=n,s._tail=i,s.__ownerID=o,s.__hash=u,s.__altered=!1,s}function Pt(){return Qr||(Qr=Nt(0,0,pr))}function Ht(t,e,r){if(e=l(t,e),e!==e)return t;if(e>=t.size||0>e)return t.withMutations(function(t){0>e?Xt(t,e).set(0,r):Xt(t,0,e+1).set(e,r)});e+=t._origin;var n=t._tail,i=t._root,o=f(mr);return e>=Gt(t._capacity)?n=Vt(n,t.__ownerID,0,e,r,o):i=Vt(i,t.__ownerID,t._level,e,r,o),o.value?t.__ownerID?(t._root=i,t._tail=n,t.__hash=void 0,t.__altered=!0,t):Nt(t._origin,t._capacity,t._level,i,n):t}function Vt(t,e,r,n,i,o){var u=n>>>r&lr,s=t&&t.array.length>u;if(!s&&void 0===i)return t;var a;if(r>0){var h=t&&t.array[u],f=Vt(h,e,r-pr,n,i,o);return f===h?t:(a=Yt(t,e),a.array[u]=f,a)}return s&&t.array[u]===i?t:(c(o),a=Yt(t,e),void 0===i&&u===a.array.length-1?a.array.pop():a.array[u]=i,a)}function Yt(t,e){return e&&t&&e===t.ownerID?t:new Ct(t?t.array.slice():[],e)}function Qt(t,e){if(e>=Gt(t._capacity))return t._tail;if(1<<t._level+pr>e){for(var r=t._root,n=t._level;r&&n>0;)r=r.array[e>>>n&lr],n-=pr;return r}}function Xt(t,e,r){void 0!==e&&(e=0|e),void 0!==r&&(r=0|r);var n=t.__ownerID||new _,i=t._origin,o=t._capacity,u=i+e,s=void 0===r?o:0>r?o+r:i+r;if(u===i&&s===o)return t;if(u>=s)return t.clear();for(var a=t._level,h=t._root,f=0;0>u+f;)h=new Ct(h&&h.array.length?[void 0,h]:[],n),a+=pr,f+=1<<a;f&&(u+=f,i+=f,s+=f,o+=f);for(var c=Gt(o),p=Gt(s);p>=1<<a+pr;)h=new Ct(h&&h.array.length?[h]:[],n),
a+=pr;var v=t._tail,l=c>p?Qt(t,s-1):p>c?new Ct([],n):v;if(v&&p>c&&o>u&&v.array.length){h=Yt(h,n);for(var y=h,d=a;d>pr;d-=pr){var m=c>>>d&lr;y=y.array[m]=Yt(y.array[m],n)}y.array[c>>>pr&lr]=v}if(o>s&&(l=l&&l.removeAfter(n,0,s)),u>=p)u-=p,s-=p,a=pr,h=null,l=l&&l.removeBefore(n,0,u);else if(u>i||c>p){for(f=0;h;){var g=u>>>a&lr;if(g!==p>>>a&lr)break;g&&(f+=(1<<a)*g),a-=pr,h=h.array[g]}h&&u>i&&(h=h.removeBefore(n,a,u-f)),h&&c>p&&(h=h.removeAfter(n,a,p-f)),f&&(u-=f,s-=f)}return t.__ownerID?(t.size=s-u,t._origin=u,t._capacity=s,t._level=a,t._root=h,t._tail=l,t.__hash=void 0,t.__altered=!0,t):Nt(u,s,a,h,l)}function Ft(t,e,r){for(var i=[],u=0,s=0;r.length>s;s++){var a=r[s],h=n(a);h.size>u&&(u=h.size),o(a)||(h=h.map(function(t){return H(t)})),i.push(h)}return u>t.size&&(t=t.setSize(u)),jt(t,e,i)}function Gt(t){return vr>t?0:t-1>>>pr<<pr}function Zt(t){return null===t||void 0===t?ee():$t(t)?t:ee().withMutations(function(e){var n=r(t);ft(n.size),n.forEach(function(t,r){return e.set(r,t)})})}function $t(t){return _t(t)&&h(t)}function te(t,e,r,n){var i=Object.create(Zt.prototype);return i.size=t?t.size:0,i._map=t,i._list=e,i.__ownerID=r,i.__hash=n,i}function ee(){return Fr||(Fr=te(zt(),Pt()))}function re(t,e,r){var n,i,o=t._map,u=t._list,s=o.get(e),a=void 0!==s;if(r===yr){if(!a)return t;u.size>=vr&&u.size>=2*o.size?(i=u.filter(function(t,e){return void 0!==t&&s!==e}),n=i.toKeyedSeq().map(function(t){return t[0]}).flip().toMap(),t.__ownerID&&(n.__ownerID=i.__ownerID=t.__ownerID)):(n=o.remove(e),i=s===u.size-1?u.pop():u.set(s,void 0))}else if(a){if(r===u.get(s)[1])return t;n=o,i=u.set(s,[e,r])}else n=o.set(e,u.size),i=u.set(u.size,[e,r]);return t.__ownerID?(t.size=n.size,t._map=n,t._list=i,t.__hash=void 0,t):te(n,i)}function ne(t,e){this._iter=t,this._useKeys=e,this.size=t.size}function ie(t){this._iter=t,this.size=t.size}function oe(t){this._iter=t,this.size=t.size}function ue(t){this._iter=t,this.size=t.size}function se(t){var e=Ee(t);return e._iter=t,e.size=t.size,e.flip=function(){return t},e.reverse=function(){var e=t.reverse.apply(this);
return e.flip=function(){return t.reverse()},e},e.has=function(e){return t.includes(e)},e.includes=function(e){return t.has(e)},e.cacheResult=Oe,e.__iterateUncached=function(e,r){var n=this;return t.__iterate(function(t,r){return e(r,t,n)!==!1},r)},e.__iteratorUncached=function(e,r){if(e===Sr){var n=t.__iterator(e,r);return new S(function(){var t=n.next();if(!t.done){var e=t.value[0];t.value[0]=t.value[1],t.value[1]=e}return t})}return t.__iterator(e===wr?gr:wr,r)},e}function ae(t,e,r){var n=Ee(t);return n.size=t.size,n.has=function(e){return t.has(e)},n.get=function(n,i){var o=t.get(n,yr);return o===yr?i:e.call(r,o,n,t)},n.__iterateUncached=function(n,i){var o=this;return t.__iterate(function(t,i,u){return n(e.call(r,t,i,u),i,o)!==!1},i)},n.__iteratorUncached=function(n,i){var o=t.__iterator(Sr,i);return new S(function(){var i=o.next();if(i.done)return i;var u=i.value,s=u[0];return z(n,s,e.call(r,u[1],s,t),i)})},n}function he(t,e){var r=Ee(t);return r._iter=t,r.size=t.size,r.reverse=function(){return t},t.flip&&(r.flip=function(){var e=se(t);return e.reverse=function(){return t.flip()},e}),r.get=function(r,n){return t.get(e?r:-1-r,n)},r.has=function(r){return t.has(e?r:-1-r)},r.includes=function(e){return t.includes(e)},r.cacheResult=Oe,r.__iterate=function(e,r){var n=this;return t.__iterate(function(t,r){return e(t,r,n)},!r)},r.__iterator=function(e,r){return t.__iterator(e,!r)},r}function fe(t,e,r,n){var i=Ee(t);return n&&(i.has=function(n){var i=t.get(n,yr);return i!==yr&&!!e.call(r,i,n,t)},i.get=function(n,i){var o=t.get(n,yr);return o!==yr&&e.call(r,o,n,t)?o:i}),i.__iterateUncached=function(i,o){var u=this,s=0;return t.__iterate(function(t,o,a){return e.call(r,t,o,a)?(s++,i(t,n?o:s-1,u)):void 0},o),s},i.__iteratorUncached=function(i,o){var u=t.__iterator(Sr,o),s=0;return new S(function(){for(;;){var o=u.next();if(o.done)return o;var a=o.value,h=a[0],f=a[1];if(e.call(r,f,h,t))return z(i,n?h:s++,f,o)}})},i}function ce(t,e,r){var n=ct().asMutable();return t.__iterate(function(i,o){n.update(e.call(r,i,o,t),0,function(t){
return t+1})}),n.asImmutable()}function _e(t,e,r){var n=u(t),i=(h(t)?Zt():ct()).asMutable();t.__iterate(function(o,u){i.update(e.call(r,o,u,t),function(t){return t=t||[],t.push(n?[u,o]:o),t})});var o=Me(t);return i.map(function(e){return be(t,o(e))})}function pe(t,e,r,n){var i=t.size;if(void 0!==e&&(e=0|e),void 0!==r&&(r=0|r),d(e,r,i))return t;var o=m(e,i),u=g(r,i);if(o!==o||u!==u)return pe(t.toSeq().cacheResult(),e,r,n);var s,a=u-o;a===a&&(s=0>a?0:a);var h=Ee(t);return h.size=0===s?s:t.size&&s||void 0,!n&&L(t)&&s>=0&&(h.get=function(e,r){return e=l(this,e),e>=0&&s>e?t.get(e+o,r):r}),h.__iterateUncached=function(e,r){var i=this;if(0===s)return 0;if(r)return this.cacheResult().__iterate(e,r);var u=0,a=!0,h=0;return t.__iterate(function(t,r){return a&&(a=u++<o)?void 0:(h++,e(t,n?r:h-1,i)!==!1&&h!==s)}),h},h.__iteratorUncached=function(e,r){if(0!==s&&r)return this.cacheResult().__iterator(e,r);var i=0!==s&&t.__iterator(e,r),u=0,a=0;return new S(function(){for(;u++<o;)i.next();if(++a>s)return I();var t=i.next();return n||e===wr?t:e===gr?z(e,a-1,void 0,t):z(e,a-1,t.value[1],t)})},h}function ve(t,e,r){var n=Ee(t);return n.__iterateUncached=function(n,i){var o=this;if(i)return this.cacheResult().__iterate(n,i);var u=0;return t.__iterate(function(t,i,s){return e.call(r,t,i,s)&&++u&&n(t,i,o)}),u},n.__iteratorUncached=function(n,i){var o=this;if(i)return this.cacheResult().__iterator(n,i);var u=t.__iterator(Sr,i),s=!0;return new S(function(){if(!s)return I();var t=u.next();if(t.done)return t;var i=t.value,a=i[0],h=i[1];return e.call(r,h,a,o)?n===Sr?t:z(n,a,h,t):(s=!1,I())})},n}function le(t,e,r,n){var i=Ee(t);return i.__iterateUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterate(i,o);var s=!0,a=0;return t.__iterate(function(t,o,h){return s&&(s=e.call(r,t,o,h))?void 0:(a++,i(t,n?o:a-1,u))}),a},i.__iteratorUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterator(i,o);var s=t.__iterator(Sr,o),a=!0,h=0;return new S(function(){var t,o,f;do{if(t=s.next(),t.done)return n||i===wr?t:i===gr?z(i,h++,void 0,t):z(i,h++,t.value[1],t);
var c=t.value;o=c[0],f=c[1],a&&(a=e.call(r,f,o,u))}while(a);return i===Sr?t:z(i,o,f,t)})},i}function ye(t,e){var n=u(t),i=[t].concat(e).map(function(t){return o(t)?n&&(t=r(t)):t=n?W(t):B(Array.isArray(t)?t:[t]),t}).filter(function(t){return 0!==t.size});if(0===i.length)return t;if(1===i.length){var a=i[0];if(a===t||n&&u(a)||s(t)&&s(a))return a}var h=new j(i);return n?h=h.toKeyedSeq():s(t)||(h=h.toSetSeq()),h=h.flatten(!0),h.size=i.reduce(function(t,e){if(void 0!==t){var r=e.size;if(void 0!==r)return t+r}},0),h}function de(t,e,r){var n=Ee(t);return n.__iterateUncached=function(n,i){function u(t,h){var f=this;t.__iterate(function(t,i){return(!e||e>h)&&o(t)?u(t,h+1):n(t,r?i:s++,f)===!1&&(a=!0),!a},i)}var s=0,a=!1;return u(t,0),s},n.__iteratorUncached=function(n,i){var u=t.__iterator(n,i),s=[],a=0;return new S(function(){for(;u;){var t=u.next();if(t.done===!1){var h=t.value;if(n===Sr&&(h=h[1]),e&&!(e>s.length)||!o(h))return r?t:z(n,a++,h,t);s.push(u),u=h.__iterator(n,i)}else u=s.pop()}return I()})},n}function me(t,e,r){var n=Me(t);return t.toSeq().map(function(i,o){return n(e.call(r,i,o,t))}).flatten(!0)}function ge(t,e){var r=Ee(t);return r.size=t.size&&2*t.size-1,r.__iterateUncached=function(r,n){var i=this,o=0;return t.__iterate(function(t,n){return(!o||r(e,o++,i)!==!1)&&r(t,o++,i)!==!1},n),o},r.__iteratorUncached=function(r,n){var i,o=t.__iterator(wr,n),u=0;return new S(function(){return(!i||u%2)&&(i=o.next(),i.done)?i:u%2?z(r,u++,e):z(r,u++,i.value,i)})},r}function we(t,e,r){e||(e=xe);var n=u(t),i=0,o=t.toSeq().map(function(e,n){return[n,e,i++,r?r(e,n,t):e]}).toArray();return o.sort(function(t,r){return e(t[3],r[3])||t[2]-r[2]}).forEach(n?function(t,e){o[e].length=2}:function(t,e){o[e]=t[1]}),n?x(o):s(t)?k(o):A(o)}function Se(t,e,r){if(e||(e=xe),r){var n=t.toSeq().map(function(e,n){return[e,r(e,n,t)]}).reduce(function(t,r){return ze(e,t[1],r[1])?r:t});return n&&n[0]}return t.reduce(function(t,r){return ze(e,t,r)?r:t})}function ze(t,e,r){var n=t(r,e);return 0===n&&r!==e&&(void 0===r||null===r||r!==r)||n>0}function Ie(t,r,n){
var i=Ee(t);return i.size=new j(n).map(function(t){return t.size}).min(),i.__iterate=function(t,e){for(var r,n=this.__iterator(wr,e),i=0;!(r=n.next()).done&&t(r.value,i++,this)!==!1;);return i},i.__iteratorUncached=function(t,i){var o=n.map(function(t){return t=e(t),D(i?t.reverse():t)}),u=0,s=!1;return new S(function(){var e;return s||(e=o.map(function(t){return t.next()}),s=e.some(function(t){return t.done})),s?I():z(t,u++,r.apply(null,e.map(function(t){return t.value})))})},i}function be(t,e){return L(t)?e:t.constructor(e)}function qe(t){if(t!==Object(t))throw new TypeError("Expected [K, V] tuple: "+t)}function De(t){return ft(t.size),v(t)}function Me(t){return u(t)?r:s(t)?n:i}function Ee(t){return Object.create((u(t)?x:s(t)?k:A).prototype)}function Oe(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):O.prototype.cacheResult.call(this)}function xe(t,e){return t>e?1:e>t?-1:0}function ke(t){var r=D(t);if(!r){if(!E(t))throw new TypeError("Expected iterable or array-like: "+t);r=D(e(t))}return r}function Ae(t,e){var r,n=function(o){if(o instanceof n)return o;if(!(this instanceof n))return new n(o);if(!r){r=!0;var u=Object.keys(t);Re(i,u),i.size=u.length,i._name=e,i._keys=u,i._defaultValues=t}this._map=ct(o)},i=n.prototype=Object.create(Gr);return i.constructor=n,n}function je(t,e,r){var n=Object.create(Object.getPrototypeOf(t));return n._map=e,n.__ownerID=r,n}function Ke(t){return t._name||t.constructor.name||"Record"}function Re(t,e){try{e.forEach(Ue.bind(void 0,t))}catch(r){}}function Ue(t,e){Object.defineProperty(t,e,{get:function(){return this.get(e)},set:function(t){Z(this.__ownerID,"Cannot set on an immutable record."),this.set(e,t)}})}function Le(t){return null===t||void 0===t?Ce():Te(t)&&!h(t)?t:Ce().withMutations(function(e){var r=i(t);ft(r.size),r.forEach(function(t){return e.add(t)})})}function Te(t){return!(!t||!t[Zr])}function We(t,e){return t.__ownerID?(t.size=e.size,t._map=e,t):e===t._map?t:0===e.size?t.__empty():t.__make(e)}function Be(t,e){var r=Object.create($r);
return r.size=t?t.size:0,r._map=t,r.__ownerID=e,r}function Ce(){return tn||(tn=Be(zt()))}function Je(t){return null===t||void 0===t?He():Ne(t)?t:He().withMutations(function(e){var r=i(t);ft(r.size),r.forEach(function(t){return e.add(t)})})}function Ne(t){return Te(t)&&h(t)}function Pe(t,e){var r=Object.create(en);return r.size=t?t.size:0,r._map=t,r.__ownerID=e,r}function He(){return rn||(rn=Pe(ee()))}function Ve(t){return null===t||void 0===t?Xe():Ye(t)?t:Xe().unshiftAll(t)}function Ye(t){return!(!t||!t[nn])}function Qe(t,e,r,n){var i=Object.create(on);return i.size=t,i._head=e,i.__ownerID=r,i.__hash=n,i.__altered=!1,i}function Xe(){return un||(un=Qe(0))}function Fe(t,e){var r=function(r){t.prototype[r]=e[r]};return Object.keys(e).forEach(r),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(e).forEach(r),t}function Ge(t,e){return e}function Ze(t,e){return[e,t]}function $e(t){return function(){return!t.apply(this,arguments)}}function tr(t){return function(){return-t.apply(this,arguments)}}function er(t){return"string"==typeof t?JSON.stringify(t):t}function rr(){return p(arguments)}function nr(t,e){return e>t?1:t>e?-1:0}function ir(t){if(t.size===1/0)return 0;var e=h(t),r=u(t),n=e?1:0,i=t.__iterate(r?e?function(t,e){n=31*n+ur(ot(t),ot(e))|0}:function(t,e){n=n+ur(ot(t),ot(e))|0}:e?function(t){n=31*n+ot(t)|0}:function(t){n=n+ot(t)|0});return or(i,n)}function or(t,e){return e=xr(e,3432918353),e=xr(e<<15|e>>>-15,461845907),e=xr(e<<13|e>>>-13,5),e=(e+3864292196|0)^t,e=xr(e^e>>>16,2246822507),e=xr(e^e>>>13,3266489909),e=it(e^e>>>16)}function ur(t,e){return t^e+2654435769+(t<<6)+(t>>2)|0}var sr=Array.prototype.slice;t(r,e),t(n,e),t(i,e),e.isIterable=o,e.isKeyed=u,e.isIndexed=s,e.isAssociative=a,e.isOrdered=h,e.Keyed=r,e.Indexed=n,e.Set=i;var ar="@@__IMMUTABLE_ITERABLE__@@",hr="@@__IMMUTABLE_KEYED__@@",fr="@@__IMMUTABLE_INDEXED__@@",cr="@@__IMMUTABLE_ORDERED__@@",_r="delete",pr=5,vr=1<<pr,lr=vr-1,yr={},dr={value:!1},mr={value:!1},gr=0,wr=1,Sr=2,zr="function"==typeof Symbol&&Symbol.iterator,Ir="@@iterator",br=zr||Ir;
S.prototype.toString=function(){return"[Iterator]"},S.KEYS=gr,S.VALUES=wr,S.ENTRIES=Sr,S.prototype.inspect=S.prototype.toSource=function(){return""+this},S.prototype[br]=function(){return this},t(O,e),O.of=function(){return O(arguments)},O.prototype.toSeq=function(){return this},O.prototype.toString=function(){return this.__toString("Seq {","}")},O.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},O.prototype.__iterate=function(t,e){return N(this,t,e,!0)},O.prototype.__iterator=function(t,e){return P(this,t,e,!0)},t(x,O),x.prototype.toKeyedSeq=function(){return this},t(k,O),k.of=function(){return k(arguments)},k.prototype.toIndexedSeq=function(){return this},k.prototype.toString=function(){return this.__toString("Seq [","]")},k.prototype.__iterate=function(t,e){return N(this,t,e,!1)},k.prototype.__iterator=function(t,e){return P(this,t,e,!1)},t(A,O),A.of=function(){return A(arguments)},A.prototype.toSetSeq=function(){return this},O.isSeq=L,O.Keyed=x,O.Set=A,O.Indexed=k;var qr="@@__IMMUTABLE_SEQ__@@";O.prototype[qr]=!0,t(j,k),j.prototype.get=function(t,e){return this.has(t)?this._array[l(this,t)]:e},j.prototype.__iterate=function(t,e){for(var r=this._array,n=r.length-1,i=0;n>=i;i++)if(t(r[e?n-i:i],i,this)===!1)return i+1;return i},j.prototype.__iterator=function(t,e){var r=this._array,n=r.length-1,i=0;return new S(function(){return i>n?I():z(t,i,r[e?n-i++:i++])})},t(K,x),K.prototype.get=function(t,e){return void 0===e||this.has(t)?this._object[t]:e},K.prototype.has=function(t){return this._object.hasOwnProperty(t)},K.prototype.__iterate=function(t,e){for(var r=this._object,n=this._keys,i=n.length-1,o=0;i>=o;o++){var u=n[e?i-o:o];if(t(r[u],u,this)===!1)return o+1}return o},K.prototype.__iterator=function(t,e){var r=this._object,n=this._keys,i=n.length-1,o=0;return new S(function(){var u=n[e?i-o:o];return o++>i?I():z(t,u,r[u])})},K.prototype[cr]=!0,t(R,k),R.prototype.__iterateUncached=function(t,e){if(e)return this.cacheResult().__iterate(t,e);
var r=this._iterable,n=D(r),i=0;if(q(n))for(var o;!(o=n.next()).done&&t(o.value,i++,this)!==!1;);return i},R.prototype.__iteratorUncached=function(t,e){if(e)return this.cacheResult().__iterator(t,e);var r=this._iterable,n=D(r);if(!q(n))return new S(I);var i=0;return new S(function(){var e=n.next();return e.done?e:z(t,i++,e.value)})},t(U,k),U.prototype.__iterateUncached=function(t,e){if(e)return this.cacheResult().__iterate(t,e);for(var r=this._iterator,n=this._iteratorCache,i=0;n.length>i;)if(t(n[i],i++,this)===!1)return i;for(var o;!(o=r.next()).done;){var u=o.value;if(n[i]=u,t(u,i++,this)===!1)break}return i},U.prototype.__iteratorUncached=function(t,e){if(e)return this.cacheResult().__iterator(t,e);var r=this._iterator,n=this._iteratorCache,i=0;return new S(function(){if(i>=n.length){var e=r.next();if(e.done)return e;n[i]=e.value}return z(t,i,n[i++])})};var Dr;t(G,k),G.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},G.prototype.get=function(t,e){return this.has(t)?this._value:e},G.prototype.includes=function(t){return X(this._value,t)},G.prototype.slice=function(t,e){var r=this.size;return d(t,e,r)?this:new G(this._value,g(e,r)-m(t,r))},G.prototype.reverse=function(){return this},G.prototype.indexOf=function(t){return X(this._value,t)?0:-1},G.prototype.lastIndexOf=function(t){return X(this._value,t)?this.size:-1},G.prototype.__iterate=function(t,e){for(var r=0;this.size>r;r++)if(t(this._value,r,this)===!1)return r+1;return r},G.prototype.__iterator=function(t,e){var r=this,n=0;return new S(function(){return r.size>n?z(t,n++,r._value):I()})},G.prototype.equals=function(t){return t instanceof G?X(this._value,t._value):F(t)};var Mr;t($,k),$.prototype.toString=function(){return 0===this.size?"Range []":"Range [ "+this._start+"..."+this._end+(this._step>1?" by "+this._step:"")+" ]"},$.prototype.get=function(t,e){return this.has(t)?this._start+l(this,t)*this._step:e},$.prototype.includes=function(t){var e=(t-this._start)/this._step;return e>=0&&this.size>e&&e===Math.floor(e);
},$.prototype.slice=function(t,e){return d(t,e,this.size)?this:(t=m(t,this.size),e=g(e,this.size),t>=e?new $(0,0):new $(this.get(t,this._end),this.get(e,this._end),this._step))},$.prototype.indexOf=function(t){var e=t-this._start;if(e%this._step===0){var r=e/this._step;if(r>=0&&this.size>r)return r}return-1},$.prototype.lastIndexOf=function(t){return this.indexOf(t)},$.prototype.__iterate=function(t,e){for(var r=this.size-1,n=this._step,i=e?this._start+r*n:this._start,o=0;r>=o;o++){if(t(i,o,this)===!1)return o+1;i+=e?-n:n}return o},$.prototype.__iterator=function(t,e){var r=this.size-1,n=this._step,i=e?this._start+r*n:this._start,o=0;return new S(function(){var u=i;return i+=e?-n:n,o>r?I():z(t,o++,u)})},$.prototype.equals=function(t){return t instanceof $?this._start===t._start&&this._end===t._end&&this._step===t._step:F(this,t)};var Er;t(tt,e),t(et,tt),t(rt,tt),t(nt,tt),tt.Keyed=et,tt.Indexed=rt,tt.Set=nt;var Or,xr="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function(t,e){t=0|t,e=0|e;var r=65535&t,n=65535&e;return r*n+((t>>>16)*n+r*(e>>>16)<<16>>>0)|0},kr=Object.isExtensible,Ar=function(){try{return Object.defineProperty({},"@",{}),!0}catch(t){return!1}}(),jr="function"==typeof WeakMap;jr&&(Or=new WeakMap);var Kr=0,Rr="__immutablehash__";"function"==typeof Symbol&&(Rr=Symbol(Rr));var Ur=16,Lr=255,Tr=0,Wr={};t(ct,et),ct.prototype.toString=function(){return this.__toString("Map {","}")},ct.prototype.get=function(t,e){return this._root?this._root.get(0,void 0,t,e):e},ct.prototype.set=function(t,e){return It(this,t,e)},ct.prototype.setIn=function(t,e){return this.updateIn(t,yr,function(){return e})},ct.prototype.remove=function(t){return It(this,t,yr)},ct.prototype.deleteIn=function(t){return this.updateIn(t,function(){return yr})},ct.prototype.update=function(t,e,r){return 1===arguments.length?t(this):this.updateIn([t],e,r)},ct.prototype.updateIn=function(t,e,r){r||(r=e,e=void 0);var n=Kt(this,ke(t),e,r);return n===yr?void 0:n},ct.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,
this._root=null,this.__hash=void 0,this.__altered=!0,this):zt()},ct.prototype.merge=function(){return xt(this,void 0,arguments)},ct.prototype.mergeWith=function(t){var e=sr.call(arguments,1);return xt(this,t,e)},ct.prototype.mergeIn=function(t){var e=sr.call(arguments,1);return this.updateIn(t,zt(),function(t){return"function"==typeof t.merge?t.merge.apply(t,e):e[e.length-1]})},ct.prototype.mergeDeep=function(){return xt(this,kt,arguments)},ct.prototype.mergeDeepWith=function(t){var e=sr.call(arguments,1);return xt(this,At(t),e)},ct.prototype.mergeDeepIn=function(t){var e=sr.call(arguments,1);return this.updateIn(t,zt(),function(t){return"function"==typeof t.mergeDeep?t.mergeDeep.apply(t,e):e[e.length-1]})},ct.prototype.sort=function(t){return Zt(we(this,t))},ct.prototype.sortBy=function(t,e){return Zt(we(this,e,t))},ct.prototype.withMutations=function(t){var e=this.asMutable();return t(e),e.wasAltered()?e.__ensureOwner(this.__ownerID):this},ct.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new _)},ct.prototype.asImmutable=function(){return this.__ensureOwner()},ct.prototype.wasAltered=function(){return this.__altered},ct.prototype.__iterator=function(t,e){return new mt(this,t,e)},ct.prototype.__iterate=function(t,e){var r=this,n=0;return this._root&&this._root.iterate(function(e){return n++,t(e[1],e[0],r)},e),n},ct.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?St(this.size,this._root,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},ct.isMap=_t;var Br="@@__IMMUTABLE_MAP__@@",Cr=ct.prototype;Cr[Br]=!0,Cr[_r]=Cr.remove,Cr.removeIn=Cr.deleteIn,pt.prototype.get=function(t,e,r,n){for(var i=this.entries,o=0,u=i.length;u>o;o++)if(X(r,i[o][0]))return i[o][1];return n},pt.prototype.update=function(t,e,r,n,i,o,u){for(var s=i===yr,a=this.entries,h=0,f=a.length;f>h&&!X(n,a[h][0]);h++);var _=f>h;if(_?a[h][1]===i:s)return this;if(c(u),(s||!_)&&c(o),!s||1!==a.length){if(!_&&!s&&a.length>=Nr)return Mt(t,a,n,i);var v=t&&t===this.ownerID,l=v?a:p(a);return _?s?h===f-1?l.pop():l[h]=l.pop():l[h]=[n,i]:l.push([n,i]),
v?(this.entries=l,this):new pt(t,l)}},vt.prototype.get=function(t,e,r,n){void 0===e&&(e=ot(r));var i=1<<((0===t?e:e>>>t)&lr),o=this.bitmap;return 0===(o&i)?n:this.nodes[Rt(o&i-1)].get(t+pr,e,r,n)},vt.prototype.update=function(t,e,r,n,i,o,u){void 0===r&&(r=ot(n));var s=(0===e?r:r>>>e)&lr,a=1<<s,h=this.bitmap,f=0!==(h&a);if(!f&&i===yr)return this;var c=Rt(h&a-1),_=this.nodes,p=f?_[c]:void 0,v=bt(p,t,e+pr,r,n,i,o,u);if(v===p)return this;if(!f&&v&&_.length>=Pr)return Ot(t,_,h,s,v);if(f&&!v&&2===_.length&&qt(_[1^c]))return _[1^c];if(f&&v&&1===_.length&&qt(v))return v;var l=t&&t===this.ownerID,y=f?v?h:h^a:h|a,d=f?v?Ut(_,c,v,l):Tt(_,c,l):Lt(_,c,v,l);return l?(this.bitmap=y,this.nodes=d,this):new vt(t,y,d)},lt.prototype.get=function(t,e,r,n){void 0===e&&(e=ot(r));var i=(0===t?e:e>>>t)&lr,o=this.nodes[i];return o?o.get(t+pr,e,r,n):n},lt.prototype.update=function(t,e,r,n,i,o,u){void 0===r&&(r=ot(n));var s=(0===e?r:r>>>e)&lr,a=i===yr,h=this.nodes,f=h[s];if(a&&!f)return this;var c=bt(f,t,e+pr,r,n,i,o,u);if(c===f)return this;var _=this.count;if(f){if(!c&&(_--,Hr>_))return Et(t,h,_,s)}else _++;var p=t&&t===this.ownerID,v=Ut(h,s,c,p);return p?(this.count=_,this.nodes=v,this):new lt(t,_,v)},yt.prototype.get=function(t,e,r,n){for(var i=this.entries,o=0,u=i.length;u>o;o++)if(X(r,i[o][0]))return i[o][1];return n},yt.prototype.update=function(t,e,r,n,i,o,u){void 0===r&&(r=ot(n));var s=i===yr;if(r!==this.keyHash)return s?this:(c(u),c(o),Dt(this,t,e,r,[n,i]));for(var a=this.entries,h=0,f=a.length;f>h&&!X(n,a[h][0]);h++);var _=f>h;if(_?a[h][1]===i:s)return this;if(c(u),(s||!_)&&c(o),s&&2===f)return new dt(t,this.keyHash,a[1^h]);var v=t&&t===this.ownerID,l=v?a:p(a);return _?s?h===f-1?l.pop():l[h]=l.pop():l[h]=[n,i]:l.push([n,i]),v?(this.entries=l,this):new yt(t,this.keyHash,l)},dt.prototype.get=function(t,e,r,n){return X(r,this.entry[0])?this.entry[1]:n},dt.prototype.update=function(t,e,r,n,i,o,u){var s=i===yr,a=X(n,this.entry[0]);return(a?i===this.entry[1]:s)?this:(c(u),s?void c(o):a?t&&t===this.ownerID?(this.entry[1]=i,this):new dt(t,this.keyHash,[n,i]):(c(o),
Dt(this,t,e,ot(n),[n,i])))},pt.prototype.iterate=yt.prototype.iterate=function(t,e){for(var r=this.entries,n=0,i=r.length-1;i>=n;n++)if(t(r[e?i-n:n])===!1)return!1},vt.prototype.iterate=lt.prototype.iterate=function(t,e){for(var r=this.nodes,n=0,i=r.length-1;i>=n;n++){var o=r[e?i-n:n];if(o&&o.iterate(t,e)===!1)return!1}},dt.prototype.iterate=function(t,e){return t(this.entry)},t(mt,S),mt.prototype.next=function(){for(var t=this._type,e=this._stack;e;){var r,n=e.node,i=e.index++;if(n.entry){if(0===i)return gt(t,n.entry)}else if(n.entries){if(r=n.entries.length-1,r>=i)return gt(t,n.entries[this._reverse?r-i:i])}else if(r=n.nodes.length-1,r>=i){var o=n.nodes[this._reverse?r-i:i];if(o){if(o.entry)return gt(t,o.entry);e=this._stack=wt(o,e)}continue}e=this._stack=this._stack.__prev}return I()};var Jr,Nr=vr/4,Pr=vr/2,Hr=vr/4;t(Wt,rt),Wt.of=function(){return this(arguments)},Wt.prototype.toString=function(){return this.__toString("List [","]")},Wt.prototype.get=function(t,e){if(t=l(this,t),t>=0&&this.size>t){t+=this._origin;var r=Qt(this,t);return r&&r.array[t&lr]}return e},Wt.prototype.set=function(t,e){return Ht(this,t,e)},Wt.prototype.remove=function(t){return this.has(t)?0===t?this.shift():t===this.size-1?this.pop():this.splice(t,1):this},Wt.prototype.insert=function(t,e){return this.splice(t,0,e)},Wt.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=this._origin=this._capacity=0,this._level=pr,this._root=this._tail=null,this.__hash=void 0,this.__altered=!0,this):Pt()},Wt.prototype.push=function(){var t=arguments,e=this.size;return this.withMutations(function(r){Xt(r,0,e+t.length);for(var n=0;t.length>n;n++)r.set(e+n,t[n])})},Wt.prototype.pop=function(){return Xt(this,0,-1)},Wt.prototype.unshift=function(){var t=arguments;return this.withMutations(function(e){Xt(e,-t.length);for(var r=0;t.length>r;r++)e.set(r,t[r])})},Wt.prototype.shift=function(){return Xt(this,1)},Wt.prototype.merge=function(){return Ft(this,void 0,arguments)},Wt.prototype.mergeWith=function(t){var e=sr.call(arguments,1);
return Ft(this,t,e)},Wt.prototype.mergeDeep=function(){return Ft(this,kt,arguments)},Wt.prototype.mergeDeepWith=function(t){var e=sr.call(arguments,1);return Ft(this,At(t),e)},Wt.prototype.setSize=function(t){return Xt(this,0,t)},Wt.prototype.slice=function(t,e){var r=this.size;return d(t,e,r)?this:Xt(this,m(t,r),g(e,r))},Wt.prototype.__iterator=function(t,e){var r=0,n=Jt(this,e);return new S(function(){var e=n();return e===Xr?I():z(t,r++,e)})},Wt.prototype.__iterate=function(t,e){for(var r,n=0,i=Jt(this,e);(r=i())!==Xr&&t(r,n++,this)!==!1;);return n},Wt.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Nt(this._origin,this._capacity,this._level,this._root,this._tail,t,this.__hash):(this.__ownerID=t,this)},Wt.isList=Bt;var Vr="@@__IMMUTABLE_LIST__@@",Yr=Wt.prototype;Yr[Vr]=!0,Yr[_r]=Yr.remove,Yr.setIn=Cr.setIn,Yr.deleteIn=Yr.removeIn=Cr.removeIn,Yr.update=Cr.update,Yr.updateIn=Cr.updateIn,Yr.mergeIn=Cr.mergeIn,Yr.mergeDeepIn=Cr.mergeDeepIn,Yr.withMutations=Cr.withMutations,Yr.asMutable=Cr.asMutable,Yr.asImmutable=Cr.asImmutable,Yr.wasAltered=Cr.wasAltered,Ct.prototype.removeBefore=function(t,e,r){if(r===e?1<<e:0===this.array.length)return this;var n=r>>>e&lr;if(n>=this.array.length)return new Ct([],t);var i,o=0===n;if(e>0){var u=this.array[n];if(i=u&&u.removeBefore(t,e-pr,r),i===u&&o)return this}if(o&&!i)return this;var s=Yt(this,t);if(!o)for(var a=0;n>a;a++)s.array[a]=void 0;return i&&(s.array[n]=i),s},Ct.prototype.removeAfter=function(t,e,r){if(r===(e?1<<e:0)||0===this.array.length)return this;var n=r-1>>>e&lr;if(n>=this.array.length)return this;var i;if(e>0){var o=this.array[n];if(i=o&&o.removeAfter(t,e-pr,r),i===o&&n===this.array.length-1)return this}var u=Yt(this,t);return u.array.splice(n+1),i&&(u.array[n]=i),u};var Qr,Xr={};t(Zt,ct),Zt.of=function(){return this(arguments)},Zt.prototype.toString=function(){return this.__toString("OrderedMap {","}")},Zt.prototype.get=function(t,e){var r=this._map.get(t);return void 0!==r?this._list.get(r)[1]:e},Zt.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,
this._map.clear(),this._list.clear(),this):ee()},Zt.prototype.set=function(t,e){return re(this,t,e)},Zt.prototype.remove=function(t){return re(this,t,yr)},Zt.prototype.wasAltered=function(){return this._map.wasAltered()||this._list.wasAltered()},Zt.prototype.__iterate=function(t,e){var r=this;return this._list.__iterate(function(e){return e&&t(e[1],e[0],r)},e)},Zt.prototype.__iterator=function(t,e){return this._list.fromEntrySeq().__iterator(t,e)},Zt.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map.__ensureOwner(t),r=this._list.__ensureOwner(t);return t?te(e,r,t,this.__hash):(this.__ownerID=t,this._map=e,this._list=r,this)},Zt.isOrderedMap=$t,Zt.prototype[cr]=!0,Zt.prototype[_r]=Zt.prototype.remove;var Fr;t(ne,x),ne.prototype.get=function(t,e){return this._iter.get(t,e)},ne.prototype.has=function(t){return this._iter.has(t)},ne.prototype.valueSeq=function(){return this._iter.valueSeq()},ne.prototype.reverse=function(){var t=this,e=he(this,!0);return this._useKeys||(e.valueSeq=function(){return t._iter.toSeq().reverse()}),e},ne.prototype.map=function(t,e){var r=this,n=ae(this,t,e);return this._useKeys||(n.valueSeq=function(){return r._iter.toSeq().map(t,e)}),n},ne.prototype.__iterate=function(t,e){var r,n=this;return this._iter.__iterate(this._useKeys?function(e,r){return t(e,r,n)}:(r=e?De(this):0,function(i){return t(i,e?--r:r++,n)}),e)},ne.prototype.__iterator=function(t,e){if(this._useKeys)return this._iter.__iterator(t,e);var r=this._iter.__iterator(wr,e),n=e?De(this):0;return new S(function(){var i=r.next();return i.done?i:z(t,e?--n:n++,i.value,i)})},ne.prototype[cr]=!0,t(ie,k),ie.prototype.includes=function(t){return this._iter.includes(t)},ie.prototype.__iterate=function(t,e){var r=this,n=0;return this._iter.__iterate(function(e){return t(e,n++,r)},e)},ie.prototype.__iterator=function(t,e){var r=this._iter.__iterator(wr,e),n=0;return new S(function(){var e=r.next();return e.done?e:z(t,n++,e.value,e)})},t(oe,A),oe.prototype.has=function(t){return this._iter.includes(t)},oe.prototype.__iterate=function(t,e){
var r=this;return this._iter.__iterate(function(e){return t(e,e,r)},e)},oe.prototype.__iterator=function(t,e){var r=this._iter.__iterator(wr,e);return new S(function(){var e=r.next();return e.done?e:z(t,e.value,e.value,e)})},t(ue,x),ue.prototype.entrySeq=function(){return this._iter.toSeq()},ue.prototype.__iterate=function(t,e){var r=this;return this._iter.__iterate(function(e){if(e){qe(e);var n=o(e);return t(n?e.get(1):e[1],n?e.get(0):e[0],r)}},e)},ue.prototype.__iterator=function(t,e){var r=this._iter.__iterator(wr,e);return new S(function(){for(;;){var e=r.next();if(e.done)return e;var n=e.value;if(n){qe(n);var i=o(n);return z(t,i?n.get(0):n[0],i?n.get(1):n[1],e)}}})},ie.prototype.cacheResult=ne.prototype.cacheResult=oe.prototype.cacheResult=ue.prototype.cacheResult=Oe,t(Ae,et),Ae.prototype.toString=function(){return this.__toString(Ke(this)+" {","}")},Ae.prototype.has=function(t){return this._defaultValues.hasOwnProperty(t)},Ae.prototype.get=function(t,e){if(!this.has(t))return e;var r=this._defaultValues[t];return this._map?this._map.get(t,r):r},Ae.prototype.clear=function(){if(this.__ownerID)return this._map&&this._map.clear(),this;var t=this.constructor;return t._empty||(t._empty=je(this,zt()))},Ae.prototype.set=function(t,e){if(!this.has(t))throw Error('Cannot set unknown key "'+t+'" on '+Ke(this));var r=this._map&&this._map.set(t,e);return this.__ownerID||r===this._map?this:je(this,r)},Ae.prototype.remove=function(t){if(!this.has(t))return this;var e=this._map&&this._map.remove(t);return this.__ownerID||e===this._map?this:je(this,e)},Ae.prototype.wasAltered=function(){return this._map.wasAltered()},Ae.prototype.__iterator=function(t,e){var n=this;return r(this._defaultValues).map(function(t,e){return n.get(e)}).__iterator(t,e)},Ae.prototype.__iterate=function(t,e){var n=this;return r(this._defaultValues).map(function(t,e){return n.get(e)}).__iterate(t,e)},Ae.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map&&this._map.__ensureOwner(t);return t?je(this,e,t):(this.__ownerID=t,
this._map=e,this)};var Gr=Ae.prototype;Gr[_r]=Gr.remove,Gr.deleteIn=Gr.removeIn=Cr.removeIn,Gr.merge=Cr.merge,Gr.mergeWith=Cr.mergeWith,Gr.mergeIn=Cr.mergeIn,Gr.mergeDeep=Cr.mergeDeep,Gr.mergeDeepWith=Cr.mergeDeepWith,Gr.mergeDeepIn=Cr.mergeDeepIn,Gr.setIn=Cr.setIn,Gr.update=Cr.update,Gr.updateIn=Cr.updateIn,Gr.withMutations=Cr.withMutations,Gr.asMutable=Cr.asMutable,Gr.asImmutable=Cr.asImmutable,t(Le,nt),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(r(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return We(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return We(this,this._map.remove(t))},Le.prototype.clear=function(){return We(this,this._map.clear())},Le.prototype.union=function(){var t=sr.call(arguments,0);return t=t.filter(function(t){return 0!==t.size}),0===t.length?this:0!==this.size||this.__ownerID||1!==t.length?this.withMutations(function(e){for(var r=0;t.length>r;r++)i(t[r]).forEach(function(t){return e.add(t)})}):this.constructor(t[0])},Le.prototype.intersect=function(){var t=sr.call(arguments,0);if(0===t.length)return this;t=t.map(function(t){return i(t)});var e=this;return this.withMutations(function(r){e.forEach(function(e){t.every(function(t){return t.includes(e)})||r.remove(e)})})},Le.prototype.subtract=function(){var t=sr.call(arguments,0);if(0===t.length)return this;t=t.map(function(t){return i(t)});var e=this;return this.withMutations(function(r){e.forEach(function(e){t.some(function(t){return t.includes(e)})&&r.remove(e)})})},Le.prototype.merge=function(){return this.union.apply(this,arguments)},Le.prototype.mergeWith=function(t){var e=sr.call(arguments,1);return this.union.apply(this,e)},Le.prototype.sort=function(t){return Je(we(this,t))},Le.prototype.sortBy=function(t,e){return Je(we(this,e,t))},Le.prototype.wasAltered=function(){return this._map.wasAltered()},Le.prototype.__iterate=function(t,e){var r=this;return this._map.__iterate(function(e,n){
return t(n,n,r)},e)},Le.prototype.__iterator=function(t,e){return this._map.map(function(t,e){return e}).__iterator(t,e)},Le.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map.__ensureOwner(t);return t?this.__make(e,t):(this.__ownerID=t,this._map=e,this)},Le.isSet=Te;var Zr="@@__IMMUTABLE_SET__@@",$r=Le.prototype;$r[Zr]=!0,$r[_r]=$r.remove,$r.mergeDeep=$r.merge,$r.mergeDeepWith=$r.mergeWith,$r.withMutations=Cr.withMutations,$r.asMutable=Cr.asMutable,$r.asImmutable=Cr.asImmutable,$r.__empty=Ce,$r.__make=Be;var tn;t(Je,Le),Je.of=function(){return this(arguments)},Je.fromKeys=function(t){return this(r(t).keySeq())},Je.prototype.toString=function(){return this.__toString("OrderedSet {","}")},Je.isOrderedSet=Ne;var en=Je.prototype;en[cr]=!0,en.__empty=He,en.__make=Pe;var rn;t(Ve,rt),Ve.of=function(){return this(arguments)},Ve.prototype.toString=function(){return this.__toString("Stack [","]")},Ve.prototype.get=function(t,e){var r=this._head;for(t=l(this,t);r&&t--;)r=r.next;return r?r.value:e},Ve.prototype.peek=function(){return this._head&&this._head.value},Ve.prototype.push=function(){if(0===arguments.length)return this;for(var t=this.size+arguments.length,e=this._head,r=arguments.length-1;r>=0;r--)e={value:arguments[r],next:e};return this.__ownerID?(this.size=t,this._head=e,this.__hash=void 0,this.__altered=!0,this):Qe(t,e)},Ve.prototype.pushAll=function(t){if(t=n(t),0===t.size)return this;ft(t.size);var e=this.size,r=this._head;return t.reverse().forEach(function(t){e++,r={value:t,next:r}}),this.__ownerID?(this.size=e,this._head=r,this.__hash=void 0,this.__altered=!0,this):Qe(e,r)},Ve.prototype.pop=function(){return this.slice(1)},Ve.prototype.unshift=function(){return this.push.apply(this,arguments)},Ve.prototype.unshiftAll=function(t){return this.pushAll(t)},Ve.prototype.shift=function(){return this.pop.apply(this,arguments)},Ve.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):Xe()},Ve.prototype.slice=function(t,e){
if(d(t,e,this.size))return this;var r=m(t,this.size),n=g(e,this.size);if(n!==this.size)return rt.prototype.slice.call(this,t,e);for(var i=this.size-r,o=this._head;r--;)o=o.next;return this.__ownerID?(this.size=i,this._head=o,this.__hash=void 0,this.__altered=!0,this):Qe(i,o)},Ve.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Qe(this.size,this._head,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},Ve.prototype.__iterate=function(t,e){if(e)return this.reverse().__iterate(t);for(var r=0,n=this._head;n&&t(n.value,r++,this)!==!1;)n=n.next;return r},Ve.prototype.__iterator=function(t,e){if(e)return this.reverse().__iterator(t);var r=0,n=this._head;return new S(function(){if(n){var e=n.value;return n=n.next,z(t,r++,e)}return I()})},Ve.isStack=Ye;var nn="@@__IMMUTABLE_STACK__@@",on=Ve.prototype;on[nn]=!0,on.withMutations=Cr.withMutations,on.asMutable=Cr.asMutable,on.asImmutable=Cr.asImmutable,on.wasAltered=Cr.wasAltered;var un;e.Iterator=S,Fe(e,{toArray:function(){ft(this.size);var t=Array(this.size||0);return this.valueSeq().__iterate(function(e,r){t[r]=e}),t},toIndexedSeq:function(){return new ie(this)},toJS:function(){return this.toSeq().map(function(t){return t&&"function"==typeof t.toJS?t.toJS():t}).__toJS()},toJSON:function(){return this.toSeq().map(function(t){return t&&"function"==typeof t.toJSON?t.toJSON():t}).__toJS()},toKeyedSeq:function(){return new ne(this,!0)},toMap:function(){return ct(this.toKeyedSeq())},toObject:function(){ft(this.size);var t={};return this.__iterate(function(e,r){t[r]=e}),t},toOrderedMap:function(){return Zt(this.toKeyedSeq())},toOrderedSet:function(){return Je(u(this)?this.valueSeq():this)},toSet:function(){return Le(u(this)?this.valueSeq():this)},toSetSeq:function(){return new oe(this)},toSeq:function(){return s(this)?this.toIndexedSeq():u(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return Ve(u(this)?this.valueSeq():this)},toList:function(){return Wt(u(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(t,e){
return 0===this.size?t+e:t+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+e},concat:function(){var t=sr.call(arguments,0);return be(this,ye(this,t))},includes:function(t){return this.some(function(e){return X(e,t)})},entries:function(){return this.__iterator(Sr)},every:function(t,e){ft(this.size);var r=!0;return this.__iterate(function(n,i,o){return t.call(e,n,i,o)?void 0:(r=!1,!1)}),r},filter:function(t,e){return be(this,fe(this,t,e,!0))},find:function(t,e,r){var n=this.findEntry(t,e);return n?n[1]:r},findEntry:function(t,e){var r;return this.__iterate(function(n,i,o){return t.call(e,n,i,o)?(r=[i,n],!1):void 0}),r},findLastEntry:function(t,e){return this.toSeq().reverse().findEntry(t,e)},forEach:function(t,e){return ft(this.size),this.__iterate(e?t.bind(e):t)},join:function(t){ft(this.size),t=void 0!==t?""+t:",";var e="",r=!0;return this.__iterate(function(n){r?r=!1:e+=t,e+=null!==n&&void 0!==n?""+n:""}),e},keys:function(){return this.__iterator(gr)},map:function(t,e){return be(this,ae(this,t,e))},reduce:function(t,e,r){ft(this.size);var n,i;return arguments.length<2?i=!0:n=e,this.__iterate(function(e,o,u){i?(i=!1,n=e):n=t.call(r,n,e,o,u)}),n},reduceRight:function(t,e,r){var n=this.toKeyedSeq().reverse();return n.reduce.apply(n,arguments)},reverse:function(){return be(this,he(this,!0))},slice:function(t,e){return be(this,pe(this,t,e,!0))},some:function(t,e){return!this.every($e(t),e)},sort:function(t){return be(this,we(this,t))},values:function(){return this.__iterator(wr)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some(function(){return!0})},count:function(t,e){return v(t?this.toSeq().filter(t,e):this)},countBy:function(t,e){return ce(this,t,e)},equals:function(t){return F(this,t)},entrySeq:function(){var t=this;if(t._cache)return new j(t._cache);var e=t.toSeq().map(Ze).toIndexedSeq();return e.fromEntrySeq=function(){return t.toSeq()},e},filterNot:function(t,e){return this.filter($e(t),e)},findLast:function(t,e,r){return this.toKeyedSeq().reverse().find(t,e,r);
},first:function(){return this.find(y)},flatMap:function(t,e){return be(this,me(this,t,e))},flatten:function(t){return be(this,de(this,t,!0))},fromEntrySeq:function(){return new ue(this)},get:function(t,e){return this.find(function(e,r){return X(r,t)},void 0,e)},getIn:function(t,e){for(var r,n=this,i=ke(t);!(r=i.next()).done;){var o=r.value;if(n=n&&n.get?n.get(o,yr):yr,n===yr)return e}return n},groupBy:function(t,e){return _e(this,t,e)},has:function(t){return this.get(t,yr)!==yr},hasIn:function(t){return this.getIn(t,yr)!==yr},isSubset:function(t){return t="function"==typeof t.includes?t:e(t),this.every(function(e){return t.includes(e)})},isSuperset:function(t){return t="function"==typeof t.isSubset?t:e(t),t.isSubset(this)},keySeq:function(){return this.toSeq().map(Ge).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},max:function(t){return Se(this,t)},maxBy:function(t,e){return Se(this,e,t)},min:function(t){return Se(this,t?tr(t):nr)},minBy:function(t,e){return Se(this,e?tr(e):nr,t)},rest:function(){return this.slice(1)},skip:function(t){return this.slice(Math.max(0,t))},skipLast:function(t){return be(this,this.toSeq().reverse().skip(t).reverse())},skipWhile:function(t,e){return be(this,le(this,t,e,!0))},skipUntil:function(t,e){return this.skipWhile($e(t),e)},sortBy:function(t,e){return be(this,we(this,e,t))},take:function(t){return this.slice(0,Math.max(0,t))},takeLast:function(t){return be(this,this.toSeq().reverse().take(t).reverse())},takeWhile:function(t,e){return be(this,ve(this,t,e))},takeUntil:function(t,e){return this.takeWhile($e(t),e)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=ir(this))}});var sn=e.prototype;sn[ar]=!0,sn[br]=sn.values,sn.__toJS=sn.toArray,sn.__toStringMapper=er,sn.inspect=sn.toSource=function(){return""+this},sn.chain=sn.flatMap,sn.contains=sn.includes,function(){try{Object.defineProperty(sn,"length",{get:function(){if(!e.noLengthWarning){var t;try{throw Error()}catch(r){t=r.stack}if(-1===t.indexOf("_wrapObject"))return console&&console.warn&&console.warn("iterable.length has been deprecated, use iterable.size or iterable.count(). This warning will become a silent error in a future version. "+t),
this.size}}})}catch(t){}}(),Fe(r,{flip:function(){return be(this,se(this))},findKey:function(t,e){var r=this.findEntry(t,e);return r&&r[0]},findLastKey:function(t,e){return this.toSeq().reverse().findKey(t,e)},keyOf:function(t){return this.findKey(function(e){return X(e,t)})},lastKeyOf:function(t){return this.findLastKey(function(e){return X(e,t)})},mapEntries:function(t,e){var r=this,n=0;return be(this,this.toSeq().map(function(i,o){return t.call(e,[o,i],n++,r)}).fromEntrySeq())},mapKeys:function(t,e){var r=this;return be(this,this.toSeq().flip().map(function(n,i){return t.call(e,n,i,r)}).flip())}});var an=r.prototype;an[hr]=!0,an[br]=sn.entries,an.__toJS=sn.toObject,an.__toStringMapper=function(t,e){return JSON.stringify(e)+": "+er(t)},Fe(n,{toKeyedSeq:function(){return new ne(this,!1)},filter:function(t,e){return be(this,fe(this,t,e,!1))},findIndex:function(t,e){var r=this.findEntry(t,e);return r?r[0]:-1},indexOf:function(t){var e=this.toKeyedSeq().keyOf(t);return void 0===e?-1:e},lastIndexOf:function(t){var e=this.toKeyedSeq().reverse().keyOf(t);return void 0===e?-1:e},reverse:function(){return be(this,he(this,!1))},slice:function(t,e){return be(this,pe(this,t,e,!1))},splice:function(t,e){var r=arguments.length;if(e=Math.max(0|e,0),0===r||2===r&&!e)return this;t=m(t,0>t?this.count():this.size);var n=this.slice(0,t);return be(this,1===r?n:n.concat(p(arguments,2),this.slice(t+e)))},findLastIndex:function(t,e){var r=this.toKeyedSeq().findLastKey(t,e);return void 0===r?-1:r},first:function(){return this.get(0)},flatten:function(t){return be(this,de(this,t,!1))},get:function(t,e){return t=l(this,t),0>t||this.size===1/0||void 0!==this.size&&t>this.size?e:this.find(function(e,r){return r===t},void 0,e)},has:function(t){return t=l(this,t),t>=0&&(void 0!==this.size?this.size===1/0||this.size>t:-1!==this.indexOf(t))},interpose:function(t){return be(this,ge(this,t))},interleave:function(){var t=[this].concat(p(arguments)),e=Ie(this.toSeq(),k.of,t),r=e.flatten(!0);return e.size&&(r.size=e.size*t.length),be(this,r)},last:function(){
return this.get(-1)},skipWhile:function(t,e){return be(this,le(this,t,e,!1))},zip:function(){var t=[this].concat(p(arguments));return be(this,Ie(this,rr,t))},zipWith:function(t){var e=p(arguments);return e[0]=this,be(this,Ie(this,t,e))}}),n.prototype[fr]=!0,n.prototype[cr]=!0,Fe(i,{get:function(t,e){return this.has(t)?t:e},includes:function(t){return this.has(t)},keySeq:function(){return this.valueSeq()}}),i.prototype.has=sn.includes,Fe(x,r.prototype),Fe(k,n.prototype),Fe(A,i.prototype),Fe(et,r.prototype),Fe(rt,n.prototype),Fe(nt,i.prototype);var hn={Iterable:e,Seq:O,Collection:tt,Map:ct,OrderedMap:Zt,List:Wt,Stack:Ve,Set:Le,OrderedSet:Je,Record:Ae,Range:$,Repeat:G,is:X,fromJS:H};return hn});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,16 @@
import _ from 'lodash';
export default function (initialState: any) {
const { user } = initialState;
const roles = _.isEmpty(user) ? [] : user.roles;
return {
// roles.indexOf('ROLE_USER') >= 0
canUsePortal: true,
// _.some(
// roles,
// (role: string) => _.isString(role) && role.indexOf('ADMIN') >= 0,
// ),
canUseManage: true
};
}

@ -0,0 +1,25 @@
import { request, Option } from '../utils/request';
export default class BasicService {
private readonly baseURL: string;
constructor(baseURL: string = '') {
this.baseURL = baseURL;
}
get(url: string, options?: Option) {
return request._request('get', url, null, options);
}
post(url: string, data?: any, options?: Option) {
return request._request('post', url, data, options);
}
put(url: string, data?: any, options?: Option) {
return request._request('put', url, data, options);
}
delete(url: string, options?: Option) {
return request._request('delete', url, null, options);
}
}

@ -0,0 +1,65 @@
import * as React from 'react';
import { DataNode } from 'rc-tree/lib/interface';
export type IApp = {
id: string;
name: string;
title: string;
entry: string;
}
export type ICompany = {
id: string;
name: string;
logo?: string;
isDefault?: boolean;
}
export type IOrganization = {
id: string;
name: string;
logo?: string;
isDefault?: boolean;
}
export type IWindow = {
id: string;
name?: string;
icon?: string;
path?: string;
component?:React.ReactNode;
closable?: boolean;
}
export type IMenuData = {
id?: string;
pid?: string;
appId?: string;
title?: string;
name?:string;
path: string;
icon?: string;
type?: string;
target?: string;
description?: string;
};
export type IAction = {
key: string;
size?: 'large' | 'middle' | 'small';
type?: 'primary' | 'ghost' | 'dashed' | 'link' | 'text' | 'default';
label?: string;
icon?: string | React.ReactNode;
render?: () => React.FC;
handle?: (e: Event) => void;
};
export interface IDataNode extends DataNode {
id?: string | number;
pid?: string | number;
value?: any;
type?: string;
parent?: IDataNode;
}

@ -0,0 +1,110 @@
import BasicService from './BasicService';
/**
* @desc
*/
class AccountService extends BasicService {
constructor() {
super();
}
pk = async () => {
return await this.get('/gateway/idm/api/pk');
};
fakeAccountLogin = async (data: any) => {
return await this.post('/gateway/idm/api/token/login', data);
};
fakeAccountChangePassword = async (data: any) => {
return await this.post('/gateway/idm/api/account/change-password', data);
};
fakeLogout = async () => {
return this.get('/gateway/idm/api/logout');
};
getAccountInfo = async () => {
return this.get(`/gateway/idm/api/account/current/info`);
};
// =============== 人员相关 ==================================
/**
*
*/
getUserAddressClassTree = async (data: any) => {
return this.post(
`/gateway/idm/api/idmComponent/getUserAddressClassTree`,
data,
);
};
/**
*
* @param
* @returns
*/
searchUserInAddressClassTreeAndParentNo = async (data: any) => {
return this.post(
`/gateway/idm/api/idmComponent/searchUserInAddressClassTreeAndParentNo`,
data,
);
};
/**
*
*/
searchUserInAddressClassTree = async (data: any) => {
return this.post(
`/gateway/idm/api/idmComponent/searchUserInAddressClassTree`,
data,
);
};
/**
*
*/
tenants = async () => {
return this.get(`/gateway/idm/api/account/tenants`);
};
/**
*
*/
organizations = async (tenantId: string) => {
return this.get(
`/gateway/idm/api/account/console/organizations/${tenantId}?roleNos=`,
);
};
/**
*
*/
tenantAndBaseOrgIdChange = async (data: any) => {
const { tenantId, baseOrgId } = data;
return this.get(
`/gateway/idm/api/token/tenant-and-baseOrgId-change/${tenantId}?baseOrgId=${baseOrgId}&needCheck=F`,
);
};
/**
*
*/
updateUserInfo = async (dto: any) => {
return this.post(`/gateway/idm/api/idm-users/updateUserInfo`, dto);
};
/**
*
*/
getCommonUserInfoByUserNo = async (userNo: string) => {
return this.get(
`/gateway/idm/api/idm-users/getCommonUserInfoByUserNo/${userNo}`,
);
};
}
const accountService = new AccountService();
export default accountService;

@ -0,0 +1,149 @@
import BasicService from './BasicService';
/**
* @desc
*/
class DictionaryService extends BasicService {
constructor() {
super();
}
/**
* :
* @param data
* @returns
*/
queryDictionaryPage = async (data: any) => {
const { page, size, sort, ...dto } = data;
return await this.post(
`/gateway/idm/api/idm-dictionarys/queryDictionaryPage?page=${page}&size=${size}&sort=${sort}`,
dto,
);
};
/**
* :
* @param data
* @returns
*/
saveDictionary = async (data: any) => {
return await this.post(
`/gateway/idm/api/idm-dictionarys/saveDictionary`,
data,
);
};
/**
* :
* @param data
* @returns
*/
deleteDictionaryById = async (ids: string) => {
return await this.post(
`/gateway/idm/api/idm-dictionarys/deleteDictionaryById/${ids}`,
);
};
/**
* :
* @param data
* @returns
*/
deleteDictionaryValueByIds = async (ids: string) => {
return await this.post(
`/gateway/idm/api/idm-dictionarys/deleteDictionaryValueByIds/${ids}`,
);
};
/**
* :,T/F
* @param data
* @returns
*/
changeDictionaryStatus = async (id: string, flag: string) => {
return await this.post(
`/gateway/idm/api/idm-dictionarys/changeDictionaryStatus/${id}/${flag}`,
);
};
/**
* :ID
* @param data
* @returns
*/
getIdmDictionaryById = async (id: string) => {
return await this.get(
`/gateway/idm/api/idm-dictionarys/getIdmDictionaryById/${id}`,
);
};
/**
*
* @param data
* @returns
*/
saveDictionaryValueBatch = async (data: any) => {
return await this.post(
`/gateway/idm/api/idm-dictionarys/saveDictionaryValueBatch`,
data,
);
};
/**
* ()
* @param data
* @returns
*/
saveDictionaryValue = async (data: any) => {
return await this.post(
`/gateway/idm/api/idm-dictionarys/saveDictionaryValue`,
data,
);
};
/**
*
* @param data
* @returns
*/
queryDictionaryValuePage = async (data: any) => {
const { page, size, sort, ...dto } = data;
return await this.post(
`/gateway/idm/api/idm-dictionarys/queryDictionaryValuePage?page=${page}&size=${size}&sort=${sort}`,
dto,
);
};
/**
*
* @param data
* @returns
*/
countryType = async () => {
return await this.get(
`/gateway/idm/api/idm-dictionarys/getTopDictionaryModelByCode/countryType`,
);
};
/**
*
*/
getChildDictionaryModelByParentId = async (code: string) => {
return await this.get(
`/gateway/idm/api/idm-dictionarys/getChildDictionaryModelByParentId/${code}`,
);
};
/**
*
*/
getDictionaryByCode = async (code: string) => {
return await this.get(
`/gateway/idm/api/idm-dictionarys/getDictionaryByCode/${code}`,
);
};
}
const dictionaryService = new DictionaryService();
export default dictionaryService;

@ -0,0 +1,40 @@
import BasicService from './BasicService';
/**
* @desc
*/
class GlobalService extends BasicService {
constructor() {
super();
}
changeTenantAndBaseOrg = async (data: any) => {
return await this.post('/api/changeTenantAndBaseOrg', data);
};
getCurrentUser = async () => {
return await this.get('/api/current-user');
};
getRoles = async () => {
return await this.get('/api/roles');
};
// 获取公司
getCompanies = async () => {
return [];
// return await this.get(`/api/companies`);
};
// 获取组织
getOrganizations = async () => {
return [];
// return await this.get(`/api/organizations`);
};
// =============== 应用相关 ==================================
}
const globalService = new GlobalService();
export default globalService;

@ -0,0 +1,21 @@
import AccountService from './account.service';
import GlobalService from './global.service';
import MenuService from './menu.service';
import SettingService from './setting.service';
import DictionaryService from './dictionary.service';
export {
AccountService,
GlobalService,
MenuService,
SettingService,
DictionaryService,
};
export default {
AccountService,
GlobalService,
MenuService,
SettingService,
DictionaryService,
};

@ -0,0 +1,46 @@
import BasicService from './BasicService';
import config from '@/config';
/**
* @desc
*/
class MenuService extends BasicService {
constructor() {
super();
}
getAccountMenu = async () => {
return this.get(
`/gateway/idm/api/account/menus/${config.get('/app/code')}`,
);
};
/**
*
*/
query = async (searchKey?: string) => {
return this.get(`/gateway/idm/api/menus?searchKey=${searchKey}`);
};
queryByAppId = async (appId: string) => {
return this.get(`/gateway/idm/api/menus/${appId}/menu`);
};
/**
*
*/
getById = async (id: string) => {
return this.get(`/gateway/idm/api/menus/${id}`);
};
/**
*
*/
getChild = async (id: string) => {
return this.get(`/gateway/idm/api/menus/${id}/children`);
};
}
const menuService = new MenuService();
export default menuService;

@ -0,0 +1,148 @@
import { Storage } from "../utils";
import BasicService from "./BasicService";
import config from "@/config";
import _ from "lodash";
//TODO 参数获取接口idm替换为对应的微服务
/**
* @desc
*/
class SettingService extends BasicService {
SYSTEM_PARAMETER_KEY = `${config.get("/app/code")}_SYSTEM_PARAMETER__`;
constructor() {
super();
}
/**
* Code
* @param code
*/
getSystemParam = (code: string) => {
if (_.isEmpty(code)) {
return null;
}
const systemParameters = this.getSystemParamCache();
if (_.isEmpty(systemParameters)) {
return null;
}
if (_.has(systemParameters, code)) {
return _.get(systemParameters, code, null);
}
const systemParameter = _.find(
systemParameters,
(param: any) => param.code === code
);
if (_.isEmpty(systemParameter)) {
return null;
}
return _.get(systemParameter, "content", null);
};
/**
*
*/
getSystemParamCache = () => {
let systemParameters = Storage.local.get(this.SYSTEM_PARAMETER_KEY);
if (_.isEmpty(systemParameters)) {
this.reloadSystemParam();
}
systemParameters = Storage.local.get(this.SYSTEM_PARAMETER_KEY);
return systemParameters;
};
/**
*
*/
initSystemParam = () => {
this.reloadSystemParam();
};
/**
*
*/
reloadSystemParam = () => {
this.getPublicSystemParams().then(({ success, data }) => {
if (success && !_.isEmpty(data)) {
const config = _.reduce(
data,
(ret: any, config: any) => {
_.set(ret, config.code, config.content);
return ret;
},
{}
);
Storage.local.set(this.SYSTEM_PARAMETER_KEY, config);
}
});
};
/**
*
*/
refreshSystemParams = async () => {
return await this.post(`/gateway/idm/api/system-parameter/refresh`);
};
/**
*
* ENV configdefine
*/
getPublicSystemParams = async () => {
return await this.get(
//@ts-ignore
`/gateway/idm/api/system-parameter/public?env=${ENV}`
);
};
/**
* - 使
*/
querySystemParams = async () => {
return await this.get(`/gateway/idm/api/system-parameter/all`);
};
/**
* - 使
*/
createSystemParam = async (data: any) => {
return await this.post(`/gateway/idm/api/system-parameter`, data);
};
/**
* - 使
*/
updateSystemParam = async (data: any) => {
return await this.put(`/gateway/idm/api/system-parameter`, data);
};
/**
* - 使
*/
batchCreateSystemParam = async (data: any) => {
return await this.post(`/gateway/idm/api/system-parameter/batch`, data);
};
/**
* - 使
*/
batchUpdateSystemParam = async (data: any) => {
return await this.put(`/gateway/idm/api/system-parameter/batch`, data);
};
/**
* - 使
*/
deleteSystemParam = async (id: any) => {
return await this.delete(`/gateway/idm/api/system-parameter/${id}`, {});
};
}
const settingService = new SettingService();
export default settingService;

@ -0,0 +1,23 @@
import { configure } from 'mobx';
import API from './api';
import { Session } from './utils';
configure({ enforceActions: 'observed' });
export interface API {
user?: any;
}
export async function getInitialState(): Promise<API> {
const user = Session.get();
return { user };
}
export const qiankun = {
// 应用加载之前
async bootstrap(props: any) {},
// 应用 render 之前触发
async mount(props: any) {},
// 应用卸载之后触发
async unmount(props: any) {},
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

@ -0,0 +1 @@
<?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 t="1605174369977" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="927" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M743.2704 264.32l91.8784 53.0176v130.56l-156.5184 90.368-0.384-126.848-97.28-56.32zM404.9664 826.3936v-173.9008l103.7568 59.5456 102.912-59.3152-0.7936 173.0048-103.7056 59.5968-102.0928-58.88z m42.3168-472.704l-108.1088 61.9008v121.7024L179.2 444.0832v-126.6176l102.5792-59.264 165.6576 95.5136z m66.8928 38.7072l98.4576 56.8064-0.6144 127.4112-103.3728 59.6992-103.808-60.5952v-122.2656l109.3888-61.056z" fill="#0188FB" p-id="928"></path><path d="M673.5872 224.128l-160.4096 91.8272L347.52 220.16 507.1616 128zM338.7136 788.1472L179.2 695.9872v-172.9536l159.744 91.8272v173.44z m496.4352-264.576v172.4928l-155.8272 89.856-0.4608-172.2368 156.16-90.2144z" fill="#0188FB" opacity=".5" p-id="929"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

@ -0,0 +1,32 @@
import IconTypes from './icons';
const routeTitle: {} = {
['/mine/personInfo']: '我的信息',
['/mine/changeTenement']: '主企业',
['/mine/setting']: '设置',
['/mine/more']: '更多',
['/address/otherTeams']: '其他团队',
['/address/othersInformation']: '详细资料',
};
/**
*
*/
enum HttpCode {
SUCCESS = 0, // 成功
FAIL = 1, // 失败
WARN = 2, // 警告
NO_LOGIN = 1000, // 需要登录
}
/**
*
*/
enum AuthorityStatus {
USER = 1,
ADMIN = 2,
CLOSE = 3,
GUEST = 0,
}
export { IconTypes, HttpCode, AuthorityStatus, routeTitle };

@ -0,0 +1,20 @@
/**
* API(axios)
*/
export interface IAPIResult {
/**
* (true:,false:)
*/
success: boolean;
/**
*
*/
data: any;
/**
*
*/
message?: string;
}

@ -0,0 +1,28 @@
/**
*
*/
export interface IFile {
// 文件名称
name: string;
// 原始文件名
originalName: string;
// 路径
path?: string;
// 所属文件id
ownerId?: string;
// 模块
module: string;
// 类型
type?: number;
// 备注
remark?: string;
// 文件id
fileId: string;
}

@ -0,0 +1,40 @@
import { FunctionComponent } from 'react';
import {
RouteComponentProps as BasicRouteProps,
RouteProps,
match,
} from 'react-router-dom';
export interface MyRouteProps extends RouteProps {
isMenu?: boolean;
}
export type PFC<P = {}> = FunctionComponent<P> & {
title?: string;
authority?: string | string[];
};
type IncludeRoute = 'component' | 'exact' | 'path';
type RouteType = Pick<RouteProps, IncludeRoute>;
export interface RouterTypes<T extends Record<string, any> = {}, P = {}>
extends BasicRouteProps {
computedMatch?: match<P>;
route?: RouteType & T;
}
export interface ReportOptions {
dsn: string;
release: string;
environment: string;
debug: boolean;
}
export interface ServerApiErrorInfo {
error: Error;
type: 'request';
requestUrl: string;
requestOptions: string;
response?: string;
}

@ -0,0 +1,5 @@
export * from './global';
export * from './apiResult';
export * from './file';
export * from './page';

@ -0,0 +1,34 @@
/**
*
*/
interface IPage {
/**
* (0)
*/
page: number;
/**
*
*/
size: number;
/**
* (header)
*/
total?: number;
/**
* (,,:createdDate)
*/
sort?: string;
}
let defaultPage: IPage = {
page: 0,
size: 100,
sort: 'createdDate',
};
export { IPage, defaultPage };

@ -0,0 +1,4 @@
// export const IP = `http://192.168.31.89`;
export const IP = `http://192.168.1.3`;
// export const IP = `http://mobile.h5ds.com`;
// export const IP = `http://127.0.0.1`;

@ -0,0 +1,4 @@
export default {
domains: {},
app: {},
};

@ -0,0 +1,19 @@
export default {
$meta: 'This file configures the plot device.',
projectName: 'Casic-portal',
domains: {},
app: {
code: 'slave',
name: 'Demo',
},
company: {},
picSuffix:
'.tiff,.pjp,.jfif,.bmp,.gif,.svg,.png,.xbm,.dib,.jxl,.jpeg,.svgz,.jpg,.ico,.tif,.pjpeg,.avif,.webp',
size: 100,
file: {
uploadReturnDetail: '/gateway/fileservice/api/file/upload/detail', //上传附件返回对象详情
uploadReturnId: '/gateway/fileservice/api/file/upload', //上传附件仅返回文件id
download: '/gateway/fileservice/api/file/download', //下载附件
viewImg: '/gateway/fileservice/api/file/view', //img标签src属性
},
};

@ -0,0 +1,4 @@
export default {
domains: {},
app: {},
};

@ -0,0 +1,36 @@
import app from './application';
import dev from './application.dev';
import prod from './application.prod';
const env = process.env.NODE_ENV;
let config = {};
switch (env) {
case 'dev':
config = _.merge({}, app, dev);
break;
case 'prod':
config = _.merge({}, app, prod);
break;
default:
config = _.merge({}, app);
break;
}
const Config = {
get: (key) => {
if (key !== '/') {
let newkey = key.replace(/\/+/g, '/');
newkey = newkey.replace(/^\//i, '');
newkey = newkey.replace(/\/$/, '');
let keys = newkey.split('/');
let value = keys.reduce(function (json, k) {
return json[k];
}, config);
return value;
}
return '';
},
};
export default Config;

@ -0,0 +1,2 @@
export const HTML_ID_LAYOUT_CONTENT = '__base-layout-main-area'
export const HTML_ID_GHOST = '__GHOST_HTML__'

@ -0,0 +1,14 @@
import * as React from 'react';
import { useAccess, Access, Redirect } from 'umi';
export default (props: any) => {
const access = useAccess();
return (
<Access
accessible={access.canUseManage}
fallback={<Redirect to="/exception/403" />}
>
{props.children}
</Access>
);
};

@ -0,0 +1,28 @@
import * as React from 'react';
import { useAccess, Access, Redirect } from 'umi';
// @ts-ignore
import { stringify } from 'qs';
export default (props:any) => {
const access = useAccess();
const { location = {} } = props;
const { pathname, query } = location;
let redirect = '/passport/sign-in';
if (pathname) {
redirect += `?back_url=${pathname}`;
}
if (query) {
redirect += `&${stringify(query)}`;
}
return (
<Access
accessible={access.canUsePortal}
// @ts-ignore
fallback={<Redirect to={redirect} />}
>
{props.children}
</Access>
);
};

@ -0,0 +1,146 @@
@import './lib/style/vars.less';
html {
height: 100vh;
min-height: 100vh;
overflow-x: hidden;
background: #f0f2f5;
font-family: 'pingfang SC', 'helvetica neue', arial, 'hiragino sans gb',
'microsoft yahei ui', 'microsoft yahei', simsun, sans-serif;
font-size: 10px;
}
html,
body {
width: 100vw;
height: 100vh;
}
#root,
#root-master {
width: 100%;
height: 100%;
}
canvas {
display: block;
}
body {
background: #f5f5f5;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.globalSpin {
width: 100%;
margin: 40px 0 !important;
}
ul,
ol {
list-style: none;
}
@media (max-width: 480px) {
.ant-table {
width: 100%;
overflow-x: auto;
&-thead>tr,
&-tbody>tr {
>th,
>td {
white-space: pre;
>span {
display: block;
}
}
}
}
}
body,
section,
ul,
div,
iframe,
aside,
main {
scrollbar-color: #999 transparent;
/* 第一个方块颜色,第二个轨道颜色(用于更改火狐浏览器样式) */
scrollbar-width: thin;
/* 火狐滚动条无法自定义宽度,只能通过此属性使滚动条宽度变细 */
&::-webkit-scrollbar-track {
-webkit-box-shadow: 0 0 0;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 4px;
}
&::-webkit-scrollbar {
width: 6px;
height: 6px;
background-color: transparent;
}
&::-webkit-scrollbar-thumb {
border-radius: 4px;
-webkit-box-shadow: inset 0 0 6px #999;
background-color: #999;
}
}
input {
&::-webkit-input-placeholder {
color: #ccc;
text-align: left;
}
&:-moz-placeholder {
color: #ccc;
text-align: left;
}
&::-moz-placeholder {
color: #ccc;
text-align: left;
}
&:-ms-input-placeholder {
color: #ccc;
text-align: left;
}
}
:global {
.art-table-cell {
word-break: break-all
}
}
.clearfix:after {
/*伪元素是行内元素 正常浏览器清除浮动方法*/
display: block;
clear: both;
height: 0;
visibility: hidden;
content: '';
}
.clearfix {
*zoom: 1;
/*ie6清除浮动的方式 *号只有IE6-IE7执行其他浏览器不执行*/
}
input:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px white inset !important;
}
.ant-dropdown-menu {
max-height: calc(100vh - 300px);
overflow-y: auto;
}

@ -0,0 +1,10 @@
import * as React from 'react';
import { MobXProviderContext } from 'mobx-react';
import useMobStore from './useMobStore';
import { useSetState } from './useSetState';
export default (name: string) => {
return React.useContext(MobXProviderContext)[name];
};
export { useMobStore, useSetState };

@ -0,0 +1,44 @@
/*
* Author: yuanzhirong
* Date: 2020-11-24 15:19:27
* @LastEditors: yuanzhirong
* @LastEditTime: 2021-01-28 16:55:04
* Description:
*/
/**
* hooks
* @example
*
* const getDiagnosesList = React.useCallback<OptionalQueryParamsMethod<State>>(
* async query => {
* const finalQuery = { ...state.query, ...query } // 合并搜索条件
* const result = await fetch(finalQuery)
* },
* [state, store, setState]
* )
*/
declare type OptionalParamsMethod<S extends AnyObject, R = Promise<void>> = <
K extends keyof S,
>(
state?: Pick<S, K>,
) => R;
/**
* webpack
*/
declare namespace NodeJS {
interface ProcessEnv {
NODE_ENV: 'development' | 'production';
}
}
/** 任意 key-value 形式的对象 */
declare interface AnyObject<T = any> {
[k: string]: T;
}
/** 定义类似 React.setState 函数声明 */
declare type SetStateLikeMethod<S extends AnyObject> = <K extends keyof S>(
state: Pick<S, K> | ((state: Readonly<S>) => Pick<S, K> | S | null),
) => void;

@ -0,0 +1,6 @@
import * as React from 'react';
import { MobXProviderContext } from 'mobx-react';
export default (name: string) => {
return React.useContext(MobXProviderContext)[name];
};

@ -0,0 +1,26 @@
/*
* Author : YangHao
* Date : 2021-03-03 10:55:50
* @LastEditTime: 2021-05-14 11:22:03
* @LastEditors: yuanzhirong
* Description : class componentsetState
*/
import React from 'react';
/**
* React.useState,使 this.setState state
* @param initialState
* @returns [state, setState]
* - setState
* - setState null
*/
export function useSetState<S extends AnyObject>(initialState: S | (() => S)) {
const [state, updateState] = React.useState(initialState);
const setState = React.useCallback<SetStateLikeMethod<S>>((inputState) => {
updateState((s) => {
const newState = inputState instanceof Function ? inputState(s) : inputState;
return newState ? { ...s, ...newState } : s;
});
}, []);
return [state, setState] as const;
}

@ -0,0 +1,173 @@
@import '~antd/lib/style/themes/variable.less';
.actions {
font-size: 20px;
font-weight: 700;
cursor: pointer;
}
.menu {
width: 300px;
min-height: 200px;
.item {
border-bottom: 1px solid #eee;
padding: 10px 5px;
display: flex;
.title {
flex: 0 0 40px;
font-size: 14px;
}
.action {
flex: 1 1 auto;
padding: 0 10px;
}
}
}
.theme-picker {
display: flex;
flex-wrap: wrap;
> div {
flex: 0 0 auto;
display: flex;
align-items: center;
justify-content: center;
height: 24px;
width: 24px;
margin: 0 5px 5px 5px;
border-radius: 4px;
border: 1px solid white;
cursor: pointer;
color: white;
}
}
.layout-picker {
display: flex;
padding: 0 10px;
:global {
.picker {
display: flex;
&-item {
position: relative;
width: 44px;
height: 36px;
margin-right: 16px;
overflow: hidden;
background-color: #f0f2f5;
border-radius: 4px;
box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.18);
cursor: pointer;
&::before {
position: absolute;
top: 0;
left: 0;
width: 33%;
height: 100%;
background-color: #fff;
content: '';
}
&::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 25%;
background-color: #fff;
content: '';
}
&-realDark {
background-color: fade(@menu-dark-bg, 85%);
&::before {
background-color: fade(@menu-dark-bg, 65%);
content: '';
}
&::after {
background-color: fade(@menu-dark-bg, 85%);
}
}
// 亮色主题
&-light {
&::before {
background-color: @white;
content: '';
}
&::after {
background-color: @white;
}
}
// 暗色主题
&-dark,
// 侧边菜单布局
&-side {
&::before {
z-index: 1;
background-color: @menu-dark-bg;
content: '';
}
&::after {
background-color: @white;
}
}
// 顶部菜单布局
&-top {
&::before {
background-color: transparent;
content: '';
}
&::after {
background-color: @menu-dark-bg;
}
}
// 顶部菜单布局
&-mix {
&::before {
background-color: @white;
content: '';
}
&::after {
background-color: @menu-dark-bg;
}
}
}
&-selectIcon {
position: absolute;
right: 6px;
bottom: 4px;
color: @primary-color;
font-weight: bold;
font-size: 14px;
pointer-events: none;
.action {
color: @primary-color;
}
}
}
}
}
.base{
display: flex;
flex-wrap: wrap;
padding: 0 10px;
}

@ -0,0 +1,184 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Popover, Tooltip, Checkbox } from 'antd';
import { Icon } from '@/lib';
import classNames from 'classnames';
import { CheckOutlined } from '@ant-design/icons';
import _ from 'lodash';
import styles from './index.less';
import { observer } from 'mobx-react';
import { useMobStore } from '@/hooks';
declare type ActionProps = {};
const Actions: React.FC<ActionProps> = observer(() => {
return (
<div className={styles.actions}>
<Popover
title={'系统设置'}
content={() => <Menu />}
placement="bottomLeft"
trigger="click"
overlayClassName={styles.overlay}
overlayInnerStyle={{ borderRadius: 8 }}
>
<Icon type="icon-setting" />
</Popover>
</div>
);
});
const Menu = observer(() => {
const store = useMobStore('baseLayoutStore')
return (
<div className={styles.menu}>
<div className={styles.item}>
<div className={styles.title}></div>
<div className={styles.action}>
<LayoutPick />
</div>
</div>
{
store.layout === 'mix' && (
<div className={styles.item}>
<div className={styles.title}></div>
<div className={styles.action}>
<SplitMenuSwitch />
</div>
</div>
)
}
<div className={styles.item}>
<div className={styles.title}></div>
<div className={styles.action}>
<ThemePicker />
</div>
</div>
</div>
);
});
const baseClassName = 'picker';
const LayoutPick = observer(() => {
const store = useMobStore('baseLayoutStore');
const onChange = useCallback((layout: string) => {
store.setLayout(layout);
}, []);
return (
<div className={styles.layoutPicker}>
<Tooltip title={'顶部模式'} key={'top'}>
<div
className={classNames(
`${baseClassName}-item`,
`${baseClassName}-item-top`,
`${baseClassName}-layout-item`,
)}
onClick={(e) => {
e.stopPropagation()
onChange('top')
}}
>
<CheckOutlined
className={`${baseClassName}-selectIcon`}
style={{
display: store.layout === 'top' ? 'block' : 'none',
}}
/>
</div>
</Tooltip>
<Tooltip title={'边栏模式'} key={'side'}>
<div
className={classNames(
`${baseClassName}-item`,
`${baseClassName}-item-side`,
`${baseClassName}-layout-item`,
)}
onClick={(e) => {
e.stopPropagation()
onChange('side')
}}
>
<CheckOutlined
className={`${baseClassName}-selectIcon`}
style={{
display: store.layout === 'side' ? 'block' : 'none',
}}
/>
</div>
</Tooltip>
<Tooltip title={'混合模式'} key={'mix'}>
<div
className={classNames(
`${baseClassName}-item`,
`${baseClassName}-item-mix`,
`${baseClassName}-layout-item`,
)}
onClick={(e) => {
e.stopPropagation()
onChange('mix')
}}
>
<CheckOutlined
className={`${baseClassName}-selectIcon`}
style={{
display: store.layout === 'mix' ? 'block' : 'none',
}}
/>
</div>
</Tooltip>
</div>
);
});
const themeConfig = {
'#1890ff': '拂晓蓝',
'#F5222D': '薄暮',
'#FA541C': '火山',
'#FADB14': '日出',
'#FAAD14': '日暮',
'#13C2C2': '明青',
'#52C41A': '极光绿',
'#2F54EB': '极客蓝',
'#722ED1': '酱紫',
};
const ThemePicker = observer(() => {
const store = useMobStore('baseLayoutStore');
const onClick = useCallback((color: string) => {
store.setPrimaryColor(color);
}, []);
return (
<div className={styles.themePicker}>
{_.map(themeConfig, (v: string, k: string) => (
<Tooltip title={v} key={k}>
<div style={{ background: k }} onClick={() => onClick(k)}>
{store.primaryColor === k ? <CheckOutlined /> : <>&nbsp;</>}
</div>
</Tooltip>
))}
</div>
);
});
const SplitMenuSwitch = observer(() => {
const [checked, setChecked] = useState<boolean>(false);
const store = useMobStore('baseLayoutStore');
useEffect(() => {
setChecked(store.splitMenus);
}, [store.splitMenus])
const onClick = useCallback(({ target }: any) => {
setChecked(target.checked);
store.setSplitMenus(target.checked);
}, []);
return (
<div className={styles.base}>
<Tooltip title='显示顶部菜单'>
<div>
<Checkbox onChange={onClick} checked={checked}></Checkbox>
</div>
</Tooltip>
</div>
);
});
export default Actions;

@ -0,0 +1,48 @@
@import '~themes/default.less';
.menu {
width: 300px;
height: 300px;
overflow-x: hidden;
overflow-y: auto;
display: flex;
flex-direction: column;
&.empty {
flex-direction: row;
align-items: center;
justify-content: center;
}
.title {
color: #666;
font-size: 16px;
font-weight: 700;
margin-bottom: 5px;
}
.menu-item {
flex: 0 0 auto;
padding: 5px 10px;
margin-bottom: 5px;
font-size: 14px;
color: #666;
cursor: pointer;
&:hover {
background: rgba(0, 0, 0, 0.1);
color: #0a60ff;
}
}
}
.overlay {
border-radius: 8px;
}
.search {
width: 100%;
input {
background: transparent;
color: white;
}
}

@ -0,0 +1,151 @@
import * as React from 'react';
import { Input, Popover } from 'antd';
import { Empty } from '@/lib';
import { useEffect, useRef, useState } from 'react';
import { AudioOutlined, SearchOutlined } from '@ant-design/icons';
import { useClickAway, useDebounce } from 'ahooks';
import _ from 'lodash';
import classNames from 'classnames';
import { history } from 'umi';
import { MenuDataItem } from '../../typings';
import styles from './index.less';
import { observer } from 'mobx-react';
import { baseLayoutStore } from '@/layouts/BaseLayout/Store';
declare type ComponentProps = {
originalMenu: MenuDataItem[];
onMenuSelect: Function;
};
const Search = observer(({ originalMenu, onMenuSelect }: ComponentProps) => {
const [visible, setVisible] = useState<boolean>(false);
const [value, setValue] = useState();
const debouncedValue = useDebounce(value, { wait: 1000 });
const logoRef = useRef(null);
useClickAway(
() => {
setVisible(false);
},
() => logoRef.current,
);
const iconColor = baseLayoutStore.layout === 'side' ? '#666' : 'rgba(255,255,255,.2)'
const bgColor = baseLayoutStore.layout === 'side' ? 'rgba(0,0,0,.1)' : 'rgba(255,255,255,.2)'
return (
<Popover
visible={visible}
title={null}
content={
<Menu
searchKey={debouncedValue}
originalMenu={originalMenu}
onMenuSelect={onMenuSelect}
/>
}
placement="bottom"
trigger="click"
overlayClassName={styles.overlay}
overlayInnerStyle={{ borderRadius: 8 }}
>
<div
className={styles.search}
ref={logoRef}
onClick={() => setVisible(!visible)}
>
<Input
size="small"
placeholder="搜索你想要的功能"
style={{
width: '100%',
outline: 'none',
borderRadius: 4,
background: bgColor,
border: 'none',
height: 30,
lineHeight: '30px',
}}
prefix={
<SearchOutlined style={{ color: iconColor }} />
}
suffix={
<AudioOutlined
style={{
fontSize: 16,
color: iconColor,
}}
/>
}
allowClear
onChange={(e: any) => setValue(e.target.value)}
/>
</div>
</Popover>
);
})
declare type MenuProps = {
searchKey: string | undefined;
originalMenu: MenuDataItem[];
onMenuSelect: Function;
};
const Menu: React.FC<MenuProps> = ({
originalMenu,
searchKey,
onMenuSelect,
}) => {
const [data, setData] = useState<any[]>([]);
useEffect(() => {
if (!_.isEmpty(searchKey) && !_.isEmpty(originalMenu)) {
setData(
_.filter(
originalMenu,
(menu: any) =>
menu.name.indexOf(searchKey) >= 0 ||
menu.path.indexOf(searchKey) >= 0,
),
);
}
}, [searchKey, originalMenu]);
if (_.isEmpty(searchKey) || _.isEmpty(data)) {
return (
<div className={classNames(styles.menu, styles.empty)}>
<Empty />
</div>
);
}
return (
<div className={styles.menu}>
<div className={styles.title}></div>
{_.map(data, (menu: any) => {
if (_.isEmpty(menu.name)) {
return null;
}
const index = menu.name.indexOf(searchKey);
const name = (
<span>
{menu.name.substr(0, index)}
<span style={{ color: '#0a60ff' }}>{searchKey}</span>
<span>{menu.name.substr(index + searchKey?.length)}</span>
</span>
);
return (
<div
key={menu.id}
className={styles.menuItem}
onClick={() => {
onMenuSelect({ key: menu.id, keyPath: [menu.pid] });
history.push(menu.path);
}}
>
{name}
</div>
);
})}
</div>
);
};
export default Search;

@ -0,0 +1,33 @@
.baseView {
display: flex;
padding-top: 12px;
.left {
min-width: 440px;
max-width: 448px;
}
.right {
flex: 1;
padding-left: 104px;
.avatar_title {
height: 22px;
margin-bottom: 8px;
color: fade(#000, 85%);
font-size: 14px;
line-height: 22px;
}
.avatar {
width: 144px;
height: 144px;
margin-bottom: 12px;
overflow: hidden;
img {
width: 100%;
}
}
.button_view {
width: 144px;
text-align: center;
}
}
}

@ -0,0 +1,470 @@
/*
* compName :
* Description :
* Author :
* Date : 2021-11-05 11:44:25
* LastEditors: Please set LastEditors
* LastEditTime: 2022-05-18 16:06:59
*/
import React, { useState, useEffect } from 'react';
import {
Button,
Input,
Upload,
Form,
Space,
Radio,
DatePicker,
Select,
message,
Spin,
} from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import API from '@/api';
import moment from 'moment';
import config from '@/config';
import { Session } from '@/utils';
import { Common } from '@/utils';
import styles from './index.less';
const token = Session.getAccessToken();
const headers = {
Authorization: `Bearer ${token}`,
};
const { Option } = Select;
const AvatarView = ({
avatar,
onChange,
}: {
avatar: string;
onChange: Function;
}) => {
const [iconUrl, setIconUrl] = useState(avatar || '');
/**
*
*/
const beforeUpload = (file: any) => {
const { name } = file;
// 1. 上传文件提示
if (_.isNil(name)) {
message.error('请上传文件');
}
// 文件类型校验
const isJPG = file.type === 'image/jpeg';
const isPNG = file.type === 'image/png';
if (!(isJPG || isPNG)) {
message.error('只能上传JPG 、PNG格式的图片~');
}
// 3. 文件大小校验
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('超过2M限制不允许上传~');
}
return (isJPG || isPNG) && isLt2M;
};
const getBase64 = (img: any, callback: (imageUrl: any) => void) => {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
};
/**
*
* @param info
*/
const handleChange = async (info: any) => {
let avatarObj: Record<string, string> = {
avatar: '',
};
if (info.file.status === 'done') {
getBase64(info.file.originFileObj, (imageUrl: any) =>
setIconUrl(imageUrl),
);
const response = info?.file?.response || {};
if (!_.isEmpty(response)) {
const { data } = response;
avatarObj.avatar = data.id;
}
onChange && onChange(avatarObj);
}
};
return (
<>
<div className={styles.avatar_title}></div>
<div className={styles.avatar}>
<img src={avatar || iconUrl} alt="avatar" />
</div>
<Upload
showUploadList={false}
headers={headers}
action={Common.uploadURLReturnDetail()}
beforeUpload={beforeUpload}
onChange={handleChange}
accept={config.get('picSuffix')}
>
<div className={styles.button_view}>
<Button>
<UploadOutlined />
</Button>
</div>
</Upload>
</>
);
};
const Base: React.FC = () => {
const [country, setCountry] = useState<Array<any>>([]);
const [province, setProvince] = useState<Array<any>>([]);
const [city, setCity] = useState<Array<any>>([]);
const [currentUser, setCurrentUser] = useState<Record<string, any>>({});
const [loading, setLoading] = useState<boolean>(false);
const [form] = Form.useForm();
useEffect(() => {
countryType();
getCommonUserInfoByUserNo();
return () => { };
}, []);
const getAvatarURL = () => {
if (currentUser) {
if (currentUser.avatar) {
return Common.viewImg(currentUser.avatar);
}
const url =
'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png';
return url;
}
return '';
};
/**
*
*/
const countryType = () => {
API.DictionaryService.countryType().then(({ success, data }) => {
if (success && !_.isEmpty(data)) {
setCountry(
_.map(data, (it) => {
return {
label: it.name,
value: it.code,
};
}),
);
}
});
};
/**
*
*/
const getCommonUserInfoByUserNo = () => {
const { userNo } = Session.get();
setLoading(true);
API.AccountService.getCommonUserInfoByUserNo(userNo).then(
({ success, data }) => {
setLoading(false);
if (success && !_.isEmpty(data)) {
const { birthday, avatar, country, province, city, ...datas } = data;
setCurrentUser(data);
country && handleCountryChange(country.split('|')[0]);
province && handleProvinceChange(province.split('|')[0]);
form.setFieldsValue({
birthday: birthday ? moment(birthday) : void 0,
country: country
? { label: country.split('|')[1], value: country.split('|')[0] }
: undefined,
province: province
? { label: province.split('|')[1], value: province.split('|')[0] }
: undefined,
city: city
? { label: city.split('|')[1], value: city.split('|')[0] }
: undefined,
...datas,
});
}
},
);
};
const handleFinish = async (values: any) => {
const { id } = Session.get();
let { birthday, country, province, city, ...value } = values;
birthday = moment(birthday).format('YYYY-MM-DD');
const payload = {
...currentUser,
birthday,
country: `${country.value}|${country.label}`,
province: `${province.value}|${province.label}`,
city: `${city.value}|${city.label}`,
...value,
id,
};
API.AccountService.updateUserInfo(payload).then(({ success }) => {
if (success) {
message.success('更新基本信息成功');
getCommonUserInfoByUserNo();
}
});
};
const onReset = () => {
form.resetFields();
setProvince([]);
setCity([]);
};
/**
*
* @param code
*/
const handleCountryChange = (code: string) => {
setProvince([]);
setCity([]);
form.setFieldsValue({
province: undefined,
city: undefined,
});
API.DictionaryService.getChildDictionaryModelByParentId(code).then(
({ success, data }) => {
if (success && !_.isEmpty(data)) {
setProvince(
_.map(data, (it) => {
return {
label: it.name,
value: it.code,
};
}),
);
}
},
);
};
/**
*
* @param rule
* @param value
* @param callback
*/
const validatorPhone = (
rule: any,
value: string,
callback: (message?: string) => void,
) => {
const reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/;
if (!reg.test(value)) {
callback('请输入正确的手机号码!');
}
callback();
};
/**
*
* @param rule
* @param value
* @param callback
*/
const validatorIDCard = (
rule: any,
value: string,
callback: (message?: string) => void,
) => {
const reg = /(^\d{15}$)|(^\d{17}([0-9]|X)$)/;
if (!reg.test(value)) {
callback('请输入正确的身份证号码!');
}
callback();
};
/**
*
* @param code
*/
const handleProvinceChange = (code: string) => {
API.DictionaryService.getChildDictionaryModelByParentId(code).then(
({ success, data }) => {
if (success && !_.isEmpty(data)) {
setCity(
_.map(data, (it) => {
return {
label: it.name,
value: it.code,
};
}),
);
}
},
);
};
const handleAvatarChange = (avatar: any) => {
setCurrentUser({ ...currentUser, ...avatar });
};
return (
<div className={styles.baseView}>
<div className={styles.left}>
<Spin spinning={loading}>
<Form
form={form}
layout="vertical"
onFinish={handleFinish}
autoComplete="off"
>
<Form.Item
name="email"
label="邮箱"
rules={[
{
type: 'email',
message: '请输入正确的邮箱地址!',
},
]}
>
<Input placeholder="请输入" allowClear />
</Form.Item>
<Form.Item name="nickname" label="昵称">
<Input placeholder="请输入" allowClear />
</Form.Item>
<Form.Item
name="idCard"
label="身份证号"
rules={[
{
validator: validatorIDCard,
},
]}
>
<Input placeholder="请输入" allowClear />
</Form.Item>
<Form.Item
name="mobile"
label="移动电话"
rules={[
{
validator: validatorPhone,
},
]}
>
<Input placeholder="请输入" />
</Form.Item>
<Form.Item name="birthday" label="生日">
<DatePicker
style={{ width: '100%' }}
getPopupContainer={(triggerNode: any) =>
triggerNode.parentElement
}
/>
</Form.Item>
<Form.Item name="sex" label="性别">
<Radio.Group buttonStyle="solid">
<Radio.Button value="M"></Radio.Button>
<Radio.Button value="F"></Radio.Button>
</Radio.Group>
</Form.Item>
<Form.Item name="country" label="国家/地区">
<Select
allowClear
style={{ width: '216px' }}
showSearch
getPopupContainer={(triggerNode) => triggerNode.parentElement}
filterOption={(input, option: any) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >=
0
}
labelInValue
onChange={({ value }) => handleCountryChange(value)}
onClear={() => {
setProvince([]);
setCity([]);
}}
>
{country.map((it) => (
<Option key={it.value} value={it.value}>
{it.label}
</Option>
))}
</Select>
</Form.Item>
<Form.Item label="所在省市">
<Form.Item
name="province"
style={{ display: 'inline-block', marginBottom: 0 }}
>
<Select
allowClear
showSearch
style={{ width: '216px', marginRight: 10 }}
disabled={_.isEmpty(province)}
getPopupContainer={(triggerNode) => triggerNode.parentElement}
filterOption={(input, option: any) =>
option.children
.toLowerCase()
.indexOf(input.toLowerCase()) >= 0
}
labelInValue
onChange={({ value }) => handleProvinceChange(value)}
onClear={() => setCity([])}
>
{province.map((it) => (
<Option key={it.value} value={it.value}>
{it.label}
</Option>
))}
</Select>
</Form.Item>
<Form.Item
name="city"
style={{ display: 'inline-block', marginBottom: 0 }}
>
<Select
allowClear
showSearch
disabled={_.isEmpty(city)}
getPopupContainer={(triggerNode) => triggerNode.parentElement}
style={{ width: '216px' }}
filterOption={(input, option: any) =>
option.children
.toLowerCase()
.indexOf(input.toLowerCase()) >= 0
}
labelInValue
>
{city.map((it) => (
<Option key={it.value} value={it.value}>
{it.label}
</Option>
))}
</Select>
</Form.Item>
</Form.Item>
<Form.Item name="area" label="街道地址">
<Input placeholder="请输入" allowClear />
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit">
</Button>
<Button htmlType="button" onClick={onReset}>
</Button>
</Space>
</Form.Item>
</Form>
</Spin>
</div>
<div className={styles.right}>
<AvatarView avatar={getAvatarURL()} onChange={handleAvatarChange} />
</div>
</div>
);
};
export default Base;

@ -0,0 +1,173 @@
@import '~antd/lib/style/themes/variable.less';
.actions {
font-size: 20px;
font-weight: 700;
cursor: pointer;
}
.menu {
width: 300px;
min-height: 200px;
.item {
border-bottom: 1px solid #eee;
padding: 20px;
display: flex;
.title {
flex: 0 0 40px;
font-size: 14px;
}
.action {
flex: 1 1 auto;
padding: 0 10px;
}
}
}
.theme-picker {
display: flex;
flex-wrap: wrap;
> div {
flex: 0 0 auto;
display: flex;
align-items: center;
justify-content: center;
height: 24px;
width: 24px;
margin: 0 5px 5px 5px;
border-radius: 4px;
border: 1px solid white;
cursor: pointer;
color: white;
}
}
.layout-picker {
display: flex;
padding: 0 10px;
:global {
.picker {
display: flex;
&-item {
position: relative;
width: 44px;
height: 36px;
margin-right: 16px;
overflow: hidden;
background-color: #f0f2f5;
border-radius: 4px;
box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.18);
cursor: pointer;
&::before {
position: absolute;
top: 0;
left: 0;
width: 33%;
height: 100%;
background-color: #fff;
content: '';
}
&::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 25%;
background-color: #fff;
content: '';
}
&-realDark {
background-color: fade(@menu-dark-bg, 85%);
&::before {
background-color: fade(@menu-dark-bg, 65%);
content: '';
}
&::after {
background-color: fade(@menu-dark-bg, 85%);
}
}
// 亮色主题
&-light {
&::before {
background-color: @white;
content: '';
}
&::after {
background-color: @white;
}
}
// 暗色主题
&-dark,
// 侧边菜单布局
&-side {
&::before {
z-index: 1;
background-color: @menu-dark-bg;
content: '';
}
&::after {
background-color: @white;
}
}
// 顶部菜单布局
&-top {
&::before {
background-color: transparent;
content: '';
}
&::after {
background-color: @menu-dark-bg;
}
}
// 顶部菜单布局
&-mix {
&::before {
background-color: @white;
content: '';
}
&::after {
background-color: @menu-dark-bg;
}
}
}
&-selectIcon {
position: absolute;
right: 6px;
bottom: 4px;
color: @primary-color;
font-weight: bold;
font-size: 14px;
pointer-events: none;
.action {
color: @primary-color;
}
}
}
}
}
.base {
display: flex;
flex-wrap: wrap;
padding: 0 10px;
}

@ -0,0 +1,162 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Tooltip, Checkbox } from 'antd';
import classNames from 'classnames';
import { CheckOutlined } from '@ant-design/icons';
import _ from 'lodash';
import styles from './index.less';
import { observer } from 'mobx-react';
import { useMobStore } from '@/hooks';
declare type InterfaceProps = {};
const Interface: React.FC<InterfaceProps> = observer(() => {
//@ts-ignore
const store = useMobStore('baseLayoutStore');
return (
<div className={styles.menu}>
<div className={styles.item}>
<div className={styles.title}></div>
<div className={styles.action}>
<LayoutPick />
</div>
</div>
<div className={styles.item}>
<div className={styles.title}></div>
<div className={styles.action}>
<ThemePicker />
</div>
</div>
</div>
);
});
const baseClassName = 'picker';
const LayoutPick = observer(() => {
const store = useMobStore('baseLayoutStore');
const onChange = useCallback((layout: string) => {
store.setLayout(layout);
}, []);
return (
<div className={styles.layoutPicker}>
<Tooltip title={'顶部模式'} key={'top'}>
<div
className={classNames(
`${baseClassName}-item`,
`${baseClassName}-item-top`,
`${baseClassName}-layout-item`,
)}
onClick={(e) => {
e.stopPropagation();
onChange('top');
}}
>
<CheckOutlined
className={`${baseClassName}-selectIcon`}
style={{
display: store.layout === 'top' ? 'block' : 'none',
}}
/>
</div>
</Tooltip>
<Tooltip title={'边栏模式'} key={'side'}>
<div
className={classNames(
`${baseClassName}-item`,
`${baseClassName}-item-side`,
`${baseClassName}-layout-item`,
)}
onClick={(e) => {
e.stopPropagation();
onChange('side');
}}
>
<CheckOutlined
className={`${baseClassName}-selectIcon`}
style={{
display: store.layout === 'side' ? 'block' : 'none',
}}
/>
</div>
</Tooltip>
<Tooltip title={'混合模式'} key={'mix'}>
<div
className={classNames(
`${baseClassName}-item`,
`${baseClassName}-item-mix`,
`${baseClassName}-layout-item`,
)}
onClick={(e) => {
e.stopPropagation();
onChange('mix');
}}
>
<CheckOutlined
className={`${baseClassName}-selectIcon`}
style={{
display: store.layout === 'mix' ? 'block' : 'none',
}}
/>
</div>
</Tooltip>
</div>
);
});
const themeConfig = {
'#001529': '默认',
'#BA000D': '信仰红',
'#21419B': '航天蓝',
'#1890FF': '拂晓蓝',
'#F5222D': '薄暮',
'#FA541C': '火山',
'#FAAD14': '日暮',
'#13C2C2': '明青',
'#52C41A': '极光绿',
'#2F54EB': '极客蓝',
'#722ED1': '酱紫',
};
const ThemePicker = observer(() => {
const store = useMobStore('baseLayoutStore');
const onClick = useCallback((color: string) => {
store.setPrimaryColor(color);
}, []);
return (
<div className={styles.themePicker}>
{_.map(themeConfig, (v: string, k: string) => (
<Tooltip title={v} key={k}>
<div style={{ background: k }} onClick={() => onClick(k)}>
{store.primaryColor === k ? <CheckOutlined /> : <>&nbsp;</>}
</div>
</Tooltip>
))}
</div>
);
});
//@ts-ignore
const SplitMenuSwitch = observer(() => {
const [checked, setChecked] = useState<boolean>(false);
const store = useMobStore('baseLayoutStore');
useEffect(() => {
setChecked(store.splitMenus);
}, [store.splitMenus]);
const onClick = useCallback(({ target }: any) => {
setChecked(target.checked);
store.setSplitMenus(target.checked);
}, []);
return (
<div className={styles.base}>
<Tooltip title="显示顶部菜单">
<div>
<Checkbox onChange={onClick} checked={checked}>
</Checkbox>
</div>
</Tooltip>
</div>
);
});
export default Interface;

@ -0,0 +1,44 @@
/*
* compName :
* Description :
* Author :
* Date : 2021-11-05 11:08:23
* LastEditors :
* LastEditTime : 2021-11-05 14:53:04
*/
import React from 'react';
import { List, Switch } from 'antd';
type Unpacked<T> = T extends (infer U)[] ? U : T;
const Notification: React.FC = () => {
const getData = () => {
const Action = (
<Switch checkedChildren="开" unCheckedChildren="关" defaultChecked />
);
return [
{
title: '待办任务',
description: '待办任务将以站内信的形式通知',
actions: [Action],
},
];
};
const data = getData();
return (
<>
<List<Unpacked<typeof data>>
itemLayout="horizontal"
dataSource={data}
renderItem={(item) => (
<List.Item actions={item.actions}>
<List.Item.Meta title={item.title} description={item.description} />
</List.Item>
)}
/>
</>
);
};
export default Notification;

@ -0,0 +1,176 @@
import React, { useState, useEffect, useRef } from 'react';
import { List, Form, Modal, Input, message } from 'antd';
import { Session } from '@/utils';
import { history } from 'umi';
import JSEncrypt from 'jsencrypt';
import API from '@/api';
type Unpacked<T> = T extends (infer U)[] ? U : T;
const passwordStrength = {
strong: <span className="strong"></span>,
medium: <span className="medium"></span>,
weak: <span className="weak"> Weak</span>,
};
const SecurityView: React.FC = () => {
const [visible, setVisible] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
const [publicKey, setPublicKey] = useState<string>('');
const timer = useRef<any>(null);
useEffect(() => {
API.AccountService.pk().then(({ data }) => setPublicKey(data));
}, []);
const handleSubmit = (formVal: Values) => {
const { password } = formVal;
setLoading(true);
const encrypt = new JSEncrypt();
encrypt.setPublicKey(publicKey);
const payload = {
password: encrypt.encrypt(password),
};
API.AccountService.fakeAccountChangePassword(payload).then(
({ success, errorMsg }) => {
setLoading(false);
if (success) {
setVisible(!visible);
Session.destroy();
successCountDown();
} else {
message.error(errorMsg);
}
},
);
};
const successCountDown = () => {
let secondsToGo = 5;
const modal = Modal.success({
title: '密码修改成功',
content: `系统将于 ${secondsToGo} 秒后重新登录。`,
okText: '立即登录',
onOk: () => {
clearInterval(timer.current);
history.push('/passport/sign-in');
},
});
timer.current = setInterval(() => {
secondsToGo -= 1;
modal.update((prevConfig) => ({
...prevConfig,
content: `系统将于 ${secondsToGo} 秒后重新登录。`,
}));
}, 1000);
setTimeout(() => {
clearInterval(timer.current);
modal.destroy();
history.push('/passport/sign-in');
}, secondsToGo * 1000);
};
const getData = () => [
{
title: '账户密码',
description: (
<>
{passwordStrength.strong}
</>
),
actions: [
<a key="Modify" onClick={() => setVisible(!visible)}>
</a>,
],
},
];
const data = getData();
return (
<>
<List<Unpacked<typeof data>>
itemLayout="horizontal"
dataSource={data}
renderItem={(item) => (
<List.Item actions={item.actions}>
<List.Item.Meta title={item.title} description={item.description} />
</List.Item>
)}
/>
{visible && (
<SetPassportForm
visible={visible}
loading={loading}
onCancel={() => setVisible(!visible)}
onCreate={handleSubmit}
/>
)}
</>
);
};
export default SecurityView;
interface Values {
password: string;
confirm: string;
}
interface CollectionPassportProps {
visible: boolean;
loading?: boolean;
onCreate?: (values: Values) => void;
onCancel?: () => void;
}
const SetPassportForm: React.FC<CollectionPassportProps> = ({
visible,
loading,
onCreate,
onCancel,
}) => {
const [form] = Form.useForm();
return (
<Modal
visible={visible}
title="密码修改"
destroyOnClose
onCancel={onCancel}
confirmLoading={loading}
onOk={() => {
form.validateFields().then((values) => {
onCreate && onCreate(values);
});
}}
>
<Form form={form} layout="vertical">
<Form.Item
name="password"
label="新密码"
rules={[{ required: true }]}
hasFeedback
>
<Input.Password />
</Form.Item>
<Form.Item
name="confirm"
label="确认新密码"
dependencies={['password']}
hasFeedback
rules={[
{ required: true },
({ getFieldValue }) => ({
validator(text, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}
return Promise.reject(new Error('两次输入的密码不一致!'));
},
}),
]}
>
<Input.Password />
</Form.Item>
</Form>
</Modal>
);
};

@ -0,0 +1,40 @@
.main {
display: flex;
width: 100%;
height: 100%;
padding-top: 16px;
padding-bottom: 16px;
background-color: #fff;
.leftMenu {
width: 224px;
border-right: 1px solid hsv(0, 0, 94%);
:global {
.ant-menu-inline {
border: none;
}
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
font-weight: bold;
}
}
}
.right {
flex: 1;
padding: 8px 40px;
.title {
margin-bottom: 12px;
color: fade(#000, 85%);
font-weight: 500;
font-size: 20px;
line-height: 28px;
}
}
:global {
.ant-list-split .ant-list-item:last-child {
border-bottom: 1px solid hsv(0, 0, 94%);
}
.ant-list-item {
padding-top: 14px;
padding-bottom: 14px;
}
}
}

@ -0,0 +1,77 @@
/*
* compName :
* Description :
* Author :
* Date : 2021-11-05 10:04:01
* LastEditors :
* LastEditTime : 2021-11-05 11:10:59
*/
import React, { useState } from 'react';
import { Menu } from 'antd';
import { GridContent } from '@ant-design/pro-layout';
import PageLayout from '@/layouts/PageLayout';
import BaseView from './components/Base';
import InterfaceView from './components/Interface';
import NotificationView from './components/Notification';
import SecurityView from './components/Security';
import styles from './index.less';
const { Item } = Menu;
type SettingsStateKeys = 'base' | 'interface' | 'notification' | 'security';
const Setting: React.FC = () => {
const [initConfig, setInitConfig] = useState<SettingsStateKeys>('base');
const menuMap: Record<string, React.ReactNode> = {
base: '基本设置',
security: '安全设置',
interface: '界面偏好',
notification: '新消息通知',
};
const getMenu = () => {
return Object.keys(menuMap).map((item) => (
<Item key={item}>{menuMap[item]}</Item>
));
};
const renderChildren = () => {
switch (initConfig) {
case 'base':
return <BaseView />;
case 'interface':
return <InterfaceView />;
case 'notification':
return <NotificationView />;
case 'security':
return <SecurityView />;
default:
return null;
}
};
return (
<PageLayout>
<GridContent>
<div className={styles.main}>
<div className={styles.leftMenu}>
<Menu
selectedKeys={[initConfig]}
onClick={({ key }) => {
setInitConfig(key as SettingsStateKeys);
}}
>
{getMenu()}
</Menu>
</div>
<div className={styles.right}>
<div className={styles.title}>{menuMap[initConfig]}</div>
{renderChildren()}
</div>
</div>
</GridContent>
</PageLayout>
);
};
export default Setting;

@ -0,0 +1,70 @@
@import '~themes/default.less';
.menu {
width: 180px;
overflow-x: hidden;
overflow-y: auto;
.username{
padding: 10px;
font-weight: 500;
}
}
.overlay {
border-radius: 8px;
}
.btn {
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.item {
border-radius: 4px;
display: flex;
flex-wrap: nowrap;
padding: 5px;
height: 48px;
align-items: center;
cursor: pointer;
.logo {
border-radius: 4px;
flex: 0 0 auto;
margin-right: 5px;
img {
width: 36px;
height: 36px;
}
}
.content {
flex: 1 1 auto;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-between;
padding: 5px;
.label {
display: flex;
justify-content: space-between;
align-items: center;
.title {
flex: 1 1 auto;
font-size: 12px;
}
}
}
.icon {
display: flex;
align-items: center;
span {
cursor: pointer;
padding: 10px;
}
}
}

@ -0,0 +1,196 @@
import * as React from 'react';
import { history, useModel } from 'umi';
import { Popover, Divider, Modal, message } from 'antd';
import { CaretDownOutlined } from '@ant-design/icons';
import { observer } from 'mobx-react';
import { useCallback, useMemo, useRef, useState } from 'react';
import _ from 'lodash';
import styles from './index.less';
import { useClickAway } from 'ahooks';
import { Avatar, ListItem } from '@/lib';
import { Session, Text } from '@/utils';
import Setting from '../Settings';
import classNames from 'classnames';
import defaultLogo from '@/assets/logo.svg';
import API from '@/api';
import { useMobStore } from '@/hooks';
import { baseLayoutStore } from '@/layouts/BaseLayout/Store';
import moment from 'moment'
const UserInfo: React.FC = observer(() => {
const [visible, setVisible] = useState<boolean>(false);
const logoRef = useRef(null);
const user = Session.get();
useClickAway(
() => {
setVisible(false);
},
() => logoRef.current,
);
const path = useMemo(() => {
if (_.isEmpty(user.avatar)) {
return null;
}
return /http(s):.*/.test(user.avatar)
? user.avatar
: `/gateway/fileservice/api/file/view/${user.avatar
}?access_token=${Session.getAccessToken()}`;
}, [user]);
const avatar = useMemo(() => {
return (
<Avatar
icon={user.icon}
path={path}
name={user.name}
size="normal"
style={{ background: baseLayoutStore.layout === 'side' ? 'rgba(0,0,0,.1)' : 'rgba(255,255,255,.2)' }}
/>
)
}, [path])
return (
<Popover
visible={visible}
title={null}
content={<Menu />}
placement="bottom"
trigger="click"
overlayClassName={styles.overlay}
overlayInnerStyle={{ borderRadius: 8 }}
>
<div
className={styles.btn}
ref={logoRef}
onClick={() => setVisible(!visible)}
>
<Item data={{ icon: avatar, title: user.name, company: user.orgName }} />
</div>
</Popover>
);
});
const ModalStyle = {
padding: 0,
minHeight: '70vh',
maxHeight: '70vh',
overflow: 'hidden auto',
};
const Menu = observer(() => {
const [visible, setVisible] = useState<boolean>(false);
const [isOrgVisible, setIsOrgVisible] = useState<boolean>(false);
const { refresh } = useModel('@@initialState');
const logout = useCallback(() => {
API.AccountService.fakeLogout().then(({ success }) => {
if (success) {
Session.destroy();
refresh && refresh();
history.push('/passport/sign-in');
}
});
}, []);
return (
<div className={styles.menu}>
<div className={styles.username}>Hi {Session.get().name} {moment().format('a')}</div>
<ListItem
ghost
onClick={() => setIsOrgVisible(true)}
style={{ cursor: 'pointer' }}
data={{
id: 'switch',
color: '#666',
icon: 'icon-company',
label: '组织切换',
path: '',
}}
/>
<Divider style={{ margin: '12px 0' }} />
<ListItem
ghost
onClick={() => setVisible(!visible)}
style={{ cursor: 'pointer' }}
data={{
id: 'setting',
color: '#666',
icon: 'icon-setting',
label: '个人设置',
}}
/>
<Divider style={{ margin: '12px 0' }} />
<ListItem
ghost
onClick={logout}
style={{ cursor: 'pointer' }}
data={{
id: 'LOGOUT',
color: '#666',
icon: 'icon-logout',
label: '退出登陆',
path: '',
}}
/>
{visible && (
<Modal
title="个人设置"
centered
bodyStyle={ModalStyle}
visible={visible}
destroyOnClose
onCancel={() => setVisible(false)}
footer={[]}
width={'65vw'}
>
<Setting />
</Modal>
)}
{isOrgVisible && (
<Modal
width={450}
title="租户/组织切换"
visible={isOrgVisible}
footer={null}
maskClosable={false}
onCancel={(e) => {
e.stopPropagation();
setIsOrgVisible(false);
}}
>
</Modal>
)}
</div>
);
});
interface ItemProps {
data: any;
onClick?: Function;
}
const Item = observer(({ data = {}, onClick }: ItemProps) => {
const store = useMobStore('baseLayoutStore')
const classes = classNames({
[styles['item']]: true,
[styles.dark]: store.layout !== 'side'
});
return (
<div className={classes} style={{ color: baseLayoutStore.layout === 'side' ? '#666' : '#eee' }}>
<div className={styles.logo}>
{typeof data.icon === 'string' ? <img src={data.icon || defaultLogo} /> : data.icon}
</div>
<div className={styles.content}>
<div className={styles.label}>
<div className={styles.title} >{Text.toShortText(data.company || '未加入组织', 6)}</div>
</div>
</div>
<div className={styles.icon}>
<CaretDownOutlined />
</div>
</div>
);
});
export default UserInfo;

@ -0,0 +1,20 @@
.header {
display: flex;
align-items: center;
> div {
margin: 0 5px;
}
.search {
flex: 1 1 auto;
}
.actions {
flex: 0 0 auto;
}
.avatar {
flex: 0 0 auto;
}
}

@ -0,0 +1,26 @@
import React from 'react';
import Actions from './Actions';
import UserInfo from './UserInfo';
import Search from './Search';
import styles from './index.less';
import { MenuDataItem } from '../typings';
declare type HeaderProp = {
originalMenu: MenuDataItem[];
onMenuSelect: Function;
};
const Header: React.FC<HeaderProp> = ({ originalMenu, onMenuSelect }) => {
return (
<div className={styles.header}>
<div className={styles.search}>
<Search originalMenu={originalMenu} onMenuSelect={onMenuSelect} />
</div>
<div className={styles.avatar}>
<UserInfo />
</div>
</div>
);
};
export default Header;

@ -0,0 +1,41 @@
.expand-button {
display: flex;
align-items: center;
color: #666;
}
.expand-menu {
display: flex;
flex-wrap: wrap;
.menu-item {
flex: 0 0 180px;
margin-right: 10px;
}
:global {
.ant-menu-inline,
.ant-menu-vertical,
.ant-menu-vertical-left {
border: none !important;
}
.ant-menu-sub.ant-menu-inline {
background: white !important;
}
.ant-menu-submenu-title {
border-bottom: 1px solid #ddd;
font-size: 16px;
font-weight: 700;
}
.ant-menu-item,
.ant-menu-submenu-title {
font-weight: bold;
border-radius: 8px;
a {
color: #171a1d !important;
}
&:hover {
background: rgba(126, 134, 142, 0.16);
}
}
}
}

@ -0,0 +1,101 @@
import React, { forwardRef, useState, useImperativeHandle } from 'react';
import { Drawer } from 'antd';
import { history } from 'umi';
import _ from 'lodash';
import { MenuDataItem } from '../../typings';
import BaseMenu from '@ant-design/pro-layout/lib/components/SiderMenu/BaseMenu';
import MenuCounter from '@ant-design/pro-layout/lib/components/SiderMenu/Counter';
import styles from './index.less';
import { HTML_ID_LAYOUT_CONTENT } from '@/constant/ID';
declare type ExpandMenuProps = {
menuData: MenuDataItem[];
selectMenuKey: string[];
onMenuSelect: Function;
};
export const MenuExpander: React.FC<ExpandMenuProps> = forwardRef(
({ menuData, selectMenuKey, onMenuSelect }, ref) => {
const [visible, setVisible] = useState<boolean>(false);
useImperativeHandle(ref, () => ({
toggle() {
setVisible((visible) => !visible);
},
}));
return (
<Drawer
title="全部导航"
visible={visible}
maskClosable
maskStyle={{ background: 'transparent' }}
onClose={() => setVisible(false)}
width={692}
placement="left"
style={{ position: 'absolute', left: 1, zIndex: 777 }}
//@ts-ignore
getContainer={() => document.getElementById(HTML_ID_LAYOUT_CONTENT)}
>
{visible && (
<Menus
menuData={menuData}
selectMenuKey={selectMenuKey}
onMenuSelect={onMenuSelect}
onClose={() => setVisible(false)}
/>
)}
</Drawer>
);
},
);
declare type MenusProps = {
menuData: MenuDataItem[];
selectMenuKey: string[];
onMenuSelect: Function;
onClose: Function;
};
const Menus: React.FC<MenusProps> = ({
menuData,
selectMenuKey,
onMenuSelect,
onClose,
}) => {
return (
<MenuCounter.Provider>
<div className={styles.expandMenu}>
{_.map(menuData, (menu: MenuDataItem) => {
return (
<div className={styles.menuItem} key={menu.key}>
<BaseMenu
matchMenuKeys={[]}
openKeys={[menu.key || '']}
selectedKeys={selectMenuKey}
menuData={[menu]}
expandIcon={null}
mode="inline"
collapsed={false}
menuItemRender={(item, dom) => (
<a
onClick={() => {
history.push(item.path || '/manage');
onClose();
}}
>
{dom}
</a>
)}
menuProps={{
mode: 'inline',
expandIcon: () => null,
//@ts-ignore
onSelect: onMenuSelect,
}}
/>
</div>
);
})}
</div>
</MenuCounter.Provider>
);
};

@ -0,0 +1,20 @@
.item {
border-radius: 4px;
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
height: 36px;
line-height: 36px;
width: 100%;
color: #eee;
cursor: pointer;
font-size: 12px;
.title {
text-overflow: ellipsis;
}
&:hover {
background: rgba(0, 0, 0, 0.1);
}
}

@ -0,0 +1,46 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import { MouseEventHandler, useRef, useState } from 'react';
import { VerticalAlignTopOutlined } from '@ant-design/icons';
import styles from './index.less';
import classNames from 'classnames';
declare type MenuFooterProps = {
onCollapse: MouseEventHandler;
collapsed: boolean;
};
export const MenuFooter = observer(
({ collapsed, onCollapse }: MenuFooterProps) => {
const [visible, setVisible] = useState<boolean>(false);
const logoRef = useRef(null);
return (
<div
className={styles.btn}
onClick={() => setVisible(!visible)}
ref={logoRef}
>
<Item onClick={onCollapse} collapsed={collapsed} />
</div>
);
},
);
interface ItemProps {
onClick: MouseEventHandler;
collapsed: boolean;
}
const Item = observer(({ collapsed, onClick }: ItemProps) => {
const classes = classNames({
[styles['item']]: true,
});
return (
<div className={classes} onClick={onClick}>
<div className={styles.title}>
<VerticalAlignTopOutlined rotate={collapsed ? 90 : -90} />{' '}
{collapsed ? null : `收起菜单`}
</div>
</div>
);
});

@ -0,0 +1,100 @@
.menu {
overflow-x: hidden;
overflow-y: auto;
}
.overlay {
border-radius: 8px;
}
.btn {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
border-bottom: 1px solid #f4f4f4;
}
.item {
border-radius: 4px;
display: flex;
flex-wrap: nowrap;
align-items: center;
padding: 5px;
height: 56px;
margin-bottom: 5px;
width: 100%;
&:hover,
&.active {
background: #f0f0f0;
}
.logo {
border-radius: 4px;
flex: 0 0 auto;
margin-right: 5px;
img {
width: 36px;
height: 36px;
}
}
.content {
flex: 1 1 auto;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-between;
padding: 5px;
.label {
display: flex;
justify-content: space-between;
align-items: center;
text-overflow: ellipsis;
.title {
flex: 1 1 auto;
font-weight: bold;
font-size: 14px;
color: #111;
}
.time {
flex: 0 0 auto;
font-size: 12px;
color: #666;
}
}
.description {
display: flex;
justify-content: space-between;
align-items: center;
text-overflow: ellipsis;
.message {
flex: 1 1 auto;
color: #666;
font-size: 12px;
}
.dot {
flex: 0 0 auto;
}
}
}
.icon {
display: flex;
align-items: center;
color: #999;
span {
cursor: pointer;
padding: 10px;
}
}
}

@ -0,0 +1,84 @@
import * as React from 'react';
import { Popover, message } from 'antd';
import { observer } from 'mobx-react';
import { forwardRef } from 'react';
import { CaretDownOutlined } from '@ant-design/icons';
import styles from './index.less';
import { Session, Text } from '@/utils';
import classNames from 'classnames';
import defaultLogo from '@/assets/logo.svg';
declare type ComponentProps = {
collapsed: boolean;
};
export const MenuHeader = observer(({ collapsed }: ComponentProps) => {
const user = Session.get();
return (
<Popover
title={'切换组织'}
content={() => <Menu />}
placement="rightBottom"
trigger="click"
overlayClassName={styles.overlay}
overlayInnerStyle={{ borderRadius: 8 }}
>
<div className={styles.btn}>
<Item
data={{ title: user.orgName, company: user.companyName }}
collapsed={collapsed}
/>
</div>
</Popover>
);
});
const Menu = observer(
forwardRef((props, ref) => {
return (
<div className={styles.menu}>
</div>
);
}),
);
interface ItemProps {
collapsed: boolean;
data: any;
}
const Item = observer(({ data = {}, collapsed }: ItemProps) => {
const classes = classNames({
[styles['item']]: true,
});
if (collapsed) {
return (
<div className={classes}>
<div className={styles.logo}>
<img src={data.logo || defaultLogo} />
</div>
</div>
);
}
return (
<div className={classes}>
<div className={styles.logo}>
<img src={data.logo || defaultLogo} />
</div>
<div className={styles.content}>
<div className={styles.label}>
<div className={styles.title}>{Text.toShortText(data.title)}</div>
</div>
<div className={styles.description}>
<div className={styles.message}>{Text.toShortText(data.company)}</div>
</div>
</div>
<div className={styles.icon}>
<CaretDownOutlined />
</div>
</div>
);
});

@ -0,0 +1,3 @@
export * from './MenuHeader';
export * from './MenuFooter';
export * from './MenuExpander';

@ -0,0 +1,85 @@
import React from 'react';
import logo from '@/assets/logo.svg';
import { action, observable, makeObservable } from 'mobx';
import { Storage } from '@/utils';
import config from '@/config';
const PRIMARY_COLOR_LOCAL_KEY = `${config.get('/app/code')}-primary-color`;
const NAV_THEME_LOCAL_KEY = `${config.get('/app/code')}-nav-theme`;
const LAYOUT_LOCAL_KEY = `${config.get('/app/code')}-layout`;
const LAYOUT_MENU_SPLIT_KEY = `${config.get('/app/code')}-menu-split`;
const colorThemeMap = {
'#001529': 'Default',
'#BA000D': 'FlagRed',
'#21419B': 'SpaceBlue',
'#1890FF': 'DaybreakBlue',
'#F5222D': 'DustRed',
'#FA541C': 'Volcano',
'#FAAD14': 'SunsetOrange',
'#13C2C2': 'Cyan',
'#52C41A': 'PolarGreen',
'#2F54EB': 'GeekBlue',
'#722ED1': 'GoldenPurple',
}
export class Store {
constructor() {
makeObservable(this);
}
@observable theme: string = 'default'; //主题
@observable navTheme: string = Storage.local.get(NAV_THEME_LOCAL_KEY) || 'SpaceBlue'; //Nav 主题
@observable primaryColor: string =
Storage.local.get(PRIMARY_COLOR_LOCAL_KEY) || '#21419B'; //主题颜色 拂晓蓝
@observable layout: 'top' | 'mix' | 'side' | undefined =
Storage.local.get(LAYOUT_LOCAL_KEY) || 'top'; //布局类型 top mix side @observable contentWidth: string = 'Fluid';
@observable fixedHeader: boolean = true; //固定头部
@observable fixSiderbar: boolean = true; //移动侧边
@observable colorWeak: boolean = false; //色弱模式
@observable splitMenus: boolean = true; //菜单分割
@observable logo: React.Component | string = logo; //Logo
@action setTheme = (theme: string) => {
this.theme = theme;
};
@action setNavTheme = (navTheme: string) => {
this.navTheme = navTheme;
};
@action setPrimaryColor = (primaryColor: string) => {
this.primaryColor = primaryColor === '#001529' ? '#1890FF' : primaryColor;
this.navTheme = colorThemeMap[primaryColor];
Storage.local.set(NAV_THEME_LOCAL_KEY, this.navTheme);
Storage.local.set(PRIMARY_COLOR_LOCAL_KEY, this.primaryColor);
};
@action setLayout = (layout: 'top' | 'mix' | 'side' | undefined) => {
this.layout = layout;
Storage.local.set(LAYOUT_LOCAL_KEY, layout);
};
@action setFixedHead = (fixedHeader: boolean) => {
this.fixedHeader = fixedHeader;
};
@action setFixSiderbar = (fixSiderbar: boolean) => {
this.fixSiderbar = fixSiderbar;
};
@action setColorWeak = (colorWeak: boolean) => {
this.colorWeak = colorWeak;
};
@action setSplitMenus = (splitMenus: boolean) => {
Storage.local.set(LAYOUT_MENU_SPLIT_KEY, splitMenus);
this.splitMenus = splitMenus;
};
@action setLogo = (logo: React.Component | string) => {
this.logo = logo;
};
}
export const baseLayoutStore = new Store();

@ -0,0 +1,323 @@
@import '~themes/default.less';
.menuStyle{
.ant-menu {
color: #eee;
background: transparent;
.ant-menu-sub {
background: transparent;
}
.ant-menu-item {
font-weight: 500;
font-size: 1.6rem;
.anticon{
font-size: 1.6rem;
}
&-selected, &:hover {
background: rgba(255, 255, 255, .2);
color: #fff;
font-weight: 700;
&::after {
border-bottom: none !important;
border-right: none !important;
}
}
a {
color: inherit;
}
}
.ant-menu-submenu {
padding: 0;
font-weight: 500;
font-size: 1.6rem;
.anticon{
font-size: 1.6rem;
}
&-selected, &:hover {
background: transparent;
color: #fff;
font-weight: 700;
&::after {
border-bottom: none !important;
border-right: none !important;
}
}
.ant-menu-submenu-title{
&:hover{
color: #fff;
background: rgba(255, 255, 255, .2);
}
}
a {
color: inherit;
}
}
.anticon {
color: inherit;
}
}
.ant-pro-sider-links {
.ant-menu-item {
padding: 0 !important;
margin: 0 !important;
}
.ant-menu-submenu-title {
height: auto !important;
}
.anticon {
font-size: 1.6rem !important;
}
}
}
.root {
:global {
.ant-layout-sider-collapsed{
label {
margin-left: 2rem;
}
.anticon{
line-height: 1.6rem !important;
}
}
.ant-pro-layout-watermark-wrapper{
height: 100%;
}
.ant-layout-header{
.ant-menu-submenu-title {
padding: 0 20px!important;
}
color: #eee;
}
.ant-layout-sider{
color: #eee;
}
.ant-pro-top-nav-header-logo{
a, h1{
font-size: 1.8rem;
font-weight: 700;
}
}
.ant-pro-sider-logo {
width: 100%;
white-space: nowrap;
padding: 0 !important;
a, h1{
color: inherit !important;
font-size: 1.8rem;
font-weight: 700;
}
}
.ant-pro-sider-fixed {
transition: all 0.3s ease;
box-shadow: @shadow-1-down;
}
.ant-pro-sider-extra {
margin: 5px 0 !important;
}
.ant-layout-sider-children {
padding: 5px;
}
}
&.Default{ //默认
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #001529;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #001529;
.menuStyle();
}
}
}
&.FlagRed{ //默认
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #BA000D;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #BA000D;
.menuStyle();
}
}
}
&.SpaceBlue{ //航天蓝
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #21419B;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #21419B;
.menuStyle();
}
}
}
&.DaybreakBlue{ //拂晓蓝
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #1890ff;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #1890ff;
.menuStyle();
}
}
}
&.DustRed{ // 薄暮
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #F5222D;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #F5222D;
.menuStyle();
}
}
}
&.Volcano{ // 火山
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #FA541C;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #FA541C;
.menuStyle();
}
}
}
&.SunsetOrange{ //日暮
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #FAAD14;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #FAAD14;
.menuStyle();
}
}
}
&.Cyan{ //明青
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #13C2C2;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #13C2C2;
.menuStyle();
}
}
}
&.PolarGreen{ //极光绿
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #52C41A;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #52C41A;
.menuStyle();
}
}
}
&.GeekBlue{ //极客蓝
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #2F54EB;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #2F54EB;
.menuStyle();
}
}
}
&.GoldenPurple{ //酱紫
:global{
.__layout_main__ > .ant-layout > .ant-layout > .ant-layout-header{
background: #722ED1;
.menuStyle();
}
.__layout_main__ > .ant-layout > .ant-layout-sider{
background: #722ED1;
.menuStyle();
}
}
}
}
.head-content {
display: flex;
align-items: center;
font-size: 1.8rem;
font-weight: 700;
height: 100%;
img {
height: 24px;
width: 24px;
margin-right: 8px;
}
}
.content {
height: 100%;
position: relative;
overflow: hidden;
.breadcrumb {
padding: 10px;
}
.main {
margin: 10px;
height: calc(100% - 20px);
overflow: auto;
background: white;
border-radius: 5px;
box-shadow: @shadow-1-down;
}
}
.expand-button {
display: flex;
padding: 5px 0 0 0;
justify-content: center;
button {
background: rgba(255,255,255,.1) !important;
border-color: transparent!important;;
color: #eee!important;;
font-size: 1rem!important;;
&:hover {
color: #fff;
background: rgba(255,255,255,.2);
}
}
:global{
.ant-input-group{
.ant-input-affix-wrapper, .ant-input-group-addon{
background: rgba(255,255,255,.1);
border-color: transparent;
input{
background: transparent;
color: #eee;
}
}
}
}
}

@ -0,0 +1,306 @@
import * as React from 'react';
import _ from 'lodash';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { history } from 'umi';
import ProLayout, { MenuDataItem, WaterMark } from '@ant-design/pro-layout';
import styles from './index.less';
import { IAction } from '@/api/Types';
import { urlToList } from '@/utils/pathTools';
import { AppStore } from '@/store/AppStore';
import { useMenu } from './useMenu';
import { observer } from 'mobx-react';
import { Text, Util, Storage, Session } from '@/utils';
import { buildIcon, SearchBar } from '@/lib';
import defaultLogo from '@/assets/logo.svg';
import {
UnorderedListOutlined,
CaretDownOutlined,
CaretRightOutlined,
} from '@ant-design/icons';
import {
MenuFooter,
MenuExpander,
} from '@/layouts/BaseLayout/Sider';
import Header from '@/layouts/BaseLayout/Header';
import { getOpenKeysFromSelectedMenu } from '@/layouts/BaseLayout/utils/utils';
import { Breadcrumb, Button, ConfigProvider, Tooltip, Space } from 'antd';
import API from '@/api';
import classNames from 'classnames';
import { baseLayoutStore as store } from './Store';
import { Base64 } from 'js-base64';
import { HTML_ID_LAYOUT_CONTENT } from '@/constant/ID';
const BaseLayout = observer(({ children, location }: any) => {
const { pathname, query } = location;
const [collapsed, setCollapse] = useState(false);
const [selectMenuKey, setSelectMenuKey] = useState([] as Array<string>);
const [openMenuKey, setOpenMenuKey] = useState([] as Array<string>);
const [filterMenuData, setFilterMenuData] = useState<any[]>([])
const session: any = Session.get();
const [
menuData,
breadCrumbMap,
defaultCollapseMenus,
defaultSelectMenus,
originalMenu,
filterMenu,
] = useMenu();
const [breadCrumbs, setBreadCrumbs] = useState<any[]>([]);
const expandMenuRef = useRef<any>();
useEffect(() => {
ConfigProvider.config({
theme: {
primaryColor: store.primaryColor,
},
});
}, [store.primaryColor]);
useEffect(() => {
setCollapse(false)
}, [store.layout])
useEffect(() => {
if (_.isEmpty(menuData) || _.isEmpty(breadCrumbMap)) {
return;
}
setOpenMenuKey(store.layout === 'side' ? defaultCollapseMenus : []);
setSelectMenuKey(defaultSelectMenus);
setFilterMenuData(menuData)
}, [menuData, breadCrumbMap, defaultCollapseMenus, defaultSelectMenus, store.layout]);
useEffect(() => {
if (!collapsed) {
const openKeys = getOpenKeysFromSelectedMenu(originalMenu, selectMenuKey);
if (!_.isEmpty(openKeys)) {
setOpenMenuKey(openKeys);
}
}
}, [collapsed]);
useEffect(() => {
if (_.isEmpty(breadCrumbMap)) {
return;
}
const paths = urlToList(pathname);
let extraBreadcrumbs = _.reduce(
paths,
(ret: any[], path: string) => {
const menu = breadCrumbMap[path];
if (!_.isEmpty(menu)) {
ret.push({ ...menu });
}
return ret;
},
[],
);
const home = breadCrumbMap['/'] || breadCrumbMap['/home'];
const breadcrumbs = _.isEmpty(home)
? extraBreadcrumbs
: [home].concat(
_.filter(extraBreadcrumbs, (data: any) => data.key !== home.key),
);
setBreadCrumbs(breadcrumbs);
}, [pathname, breadCrumbMap]);
const onMenuOpen = useCallback((openKeys: string[]) => {
setOpenMenuKey(openKeys);
Storage.session.set('OPEN_MENU_KEY', openKeys)
}, []);
const onMenuSelect = useCallback((menu: any) => {
if (_.isEmpty(menu)) {
return;
}
if (Array.isArray(menu)) {
setSelectMenuKey(menu);
} else {
setSelectMenuKey([menu.key]);
//@ts-ignore
setOpenMenuKey((openMenuKey) => [].concat(openMenuKey).concat(menu.keyPath),
);
}
}, []);
const breadCrumbComp = useMemo(() => {
return (
<Breadcrumb>
{_.map(breadCrumbs, (item: any) => (
<Breadcrumb.Item
key={item.path}
onClick={() => {
onMenuSelect({
key: item.id,
keyPath: [item.id, item.pid],
});
history.push(item.path);
}}
>
<a>
{buildIcon('', item.icon)} {item.name}
</a>
</Breadcrumb.Item>
))}
</Breadcrumb>
)
}, [breadCrumbs])
const classes = useMemo(() => {
return classNames({
[styles.root]: true,
[styles[store.navTheme]]: true,
})
}, [store.navTheme])
const onMenuSearch = useCallback((key: any) => {
if (_.isEmpty(key)) {
setFilterMenuData(menuData);
} else {
setFilterMenuData(filterMenu(originalMenu, key))
}
}, [menuData])
// 内嵌模式直接渲染子路由
if (query?.embeded && query?.embeded == 'T') {
return <>{children}</>;
}
// const logo = API.SettingService.getSystemParam('logo') || defaultLogo;
// const appName = API.SettingService.getSystemParam('appName') || '管理系统';
// const globalWaterMark = API.SettingService.getSystemParam('globalWaterMark') || 'F';
const logo = defaultLogo;
const appName = '管理系统';
const globalWaterMark = 'F';
let layout = (
<div
className={classes}
style={{
width: '100vw',
height: '100vh',
overflow: 'hidden',
}}
>
<ProLayout
className='__layout_main__'
disableMobile
fixedHeader
fixSiderbar
location={location}
layout={store.layout}
splitMenus={store.layout === 'mix' && store.splitMenus}
navTheme={store.layout === 'top' ? 'dark' : 'light'}
// @ts-ignore
iconfontUrl={`${Util.getPublicPath()}css/iconfont/iconfont.js`}
title={Text.toShortText(appName, store.layout === 'side' ? 7 : 11)}
logo={<span onClick={() => history.push('/')}><img src={logo} /></span>}
collapsed={collapsed}
style={{ transition: 'all 0.5s ease 0s' }}
headerContentRender={() =>
(store.layout === 'side' || (store.layout === 'mix' && !store.splitMenus)) ? (
<div className={styles.headContent}>
{breadCrumbComp}
</div>
) : false
}
menuDataRender={(menus: MenuDataItem[]) => filterMenuData || menus}
menuItemRender={(item) => {
return (
<a
onClick={() => {
const external = /^https?:\/\//.test(item.path || '');
Storage.session.set('ACTIVE_MENU_KEY', item.key)
if (external) {
const embedUrl = Base64.encode(item.path || '', true);
history.push(`/external?_q=${embedUrl}`);
} else {
history.push(item.path || '/');
}
}}
>
{typeof item.icon === 'string'
? buildIcon('FONT', item.icon)
: item.icon}{' '}
<label>{item.name}</label>
</a>
);
}}
menuProps={{
theme: 'light',
selectedKeys: selectMenuKey,
openKeys: openMenuKey,
onOpenChange: onMenuOpen,
onSelect: onMenuSelect,
expandIcon: (props) => {
return props.isOpen ? (
<CaretDownOutlined style={{ color: '#999' }} />
) : (
<CaretRightOutlined style={{ color: '#999' }} />
);
},
}}
menuExtraRender={() =>
store.layout === 'mix' && store.splitMenus ? null : (
<div className={styles.expandButton}>
<Space>
{collapsed ? null : <SearchBar fillOnSearch onSearch={onMenuSearch} size='small' placeholder='搜索功能' />}
<Button size='small' onClick={() => expandMenuRef.current.toggle()}>
<Tooltip title='查看全部'><UnorderedListOutlined /></Tooltip>
</Button>
</Space>
</div>
)}
rightContentRender={() => (
<>
<Header originalMenu={originalMenu} onMenuSelect={onMenuSelect} />
</>
)}
collapsedButtonRender={() => (
<MenuFooter
collapsed={collapsed}
onCollapse={() => setCollapse((collapsed) => !collapsed)}
/>
)}
contentStyle={{ padding: 0, margin: 0, height: 'calc(100vh - 48px)' }}
>
<div className={styles.content} id={HTML_ID_LAYOUT_CONTENT}>
<div className={styles.main}>
{globalWaterMark === 'T' ? <WaterMark content={`${session?.name}${session?.userNo || ''}`}>{children}</WaterMark> : children}
</div>
</div>
</ProLayout>
<MenuExpander
//@ts-ignore
ref={expandMenuRef}
menuData={menuData}
selectMenuKey={selectMenuKey}
onMenuSelect={onMenuSelect}
/>
</div>
);
return layout;
});
export default (props: any) => <BaseLayout {...props} />;
export const resetManageLayoutBreadcrumbs = (
store: AppStore,
breadcrumbs: [],
) => {
if (_.isEmpty(store.breadcrumbs)) {
store.setBreadcrumbs(breadcrumbs);
}
};
export const resetManageLayoutTopActions = (
store: AppStore,
actions: Array<IAction>,
) => {
if (_.isEmpty(store.topActions)) {
store.setTopActions(actions);
}
};

@ -0,0 +1,64 @@
import type * as H from 'history';
import type {
RouteComponentProps as BasicRouteProps,
match,
} from 'react-router-dom';
import type React from 'react';
export type LinkProps = {
to: H.LocationDescriptor;
replace?: boolean;
innerRef?: React.Ref<HTMLAnchorElement>;
} & React.AnchorHTMLAttributes<HTMLAnchorElement>;
export type MenuDataItem = {
/** @name 子菜单 */
children?: MenuDataItem[];
/** @name 在菜单中隐藏子节点 */
hideChildrenInMenu?: boolean;
/** @name 在菜单中隐藏自己和子节点 */
hideInMenu?: boolean;
/** @name 菜单的icon */
icon?: React.ReactNode;
/** @name 自定义菜单的国际化 key */
locale?: string | false;
/** @name 菜单的名字 */
name?: string;
/** @name 用于标定选中的值,默认是 path */
key?: string;
/** @name disable 菜单选项 */
disabled?: boolean;
/** @name 路径,可以设定为网页链接 */
path?: string;
/**
* parentKeys
*
* @name
*/
parentKeys?: string[];
/** @name 隐藏自己,并且将子节点提升到与自己平级 */
flatMenu?: boolean;
/** @name 指定外链打开形式同a标签 */
target?: string;
[key: string]: any;
};
export type Route = {
routes?: Route[];
} & MenuDataItem;
export type WithFalse<T> = T | false;
export type RouterTypes<P> = {
computedMatch?: match<P>;
route?: Route;
location: BasicRouteProps['location'] | { pathname?: string };
} & Omit<BasicRouteProps, 'location'>;
export type MessageDescriptor = {
id: any;
description?: string;
defaultMessage?: string;
};

@ -0,0 +1,253 @@
import React, { useEffect } from 'react';
import memoizeOne from 'memoize-one';
//@ts-ignore
import isEqual from 'lodash/isEqual';
import API from '@/api';
import _ from 'lodash';
import pathToRegexp from 'path-to-regexp';
import { Base64 } from 'js-base64';
import { urlToList } from '@/utils';
import { history } from 'umi';
import { buildIcon } from '@/lib';
import { Storage } from '@/utils';
import { MenuDataItem } from '@/layouts/BaseLayout/typings';
/**
* Recursively flatten the data
* [{path:string},{path:string}] => {path,path2}
* @param menus
*/
const getFlatMenuKeys: (menuData: any) => Array<string> = (menuData) => {
let keys = [] as Array<string>;
menuData.forEach((item: any) => {
keys.push(item.path);
if (item.routes) {
keys = keys.concat(getFlatMenuKeys(item.routes));
}
});
return keys;
};
/**
*
* @param {Object} menuData
*/
const getBreadcrumbNameMap: (menuData: any) => any = (menuData) => {
if (!menuData) {
return {};
}
const routerMap = {};
const flattenMenuData = (data: any) => {
data.forEach((menuItem: any) => {
if (menuItem.routes) {
flattenMenuData(menuItem.routes);
}
// Reduce memory usage
routerMap[menuItem.path] = menuItem;
});
};
flattenMenuData(menuData);
return routerMap;
};
const memoizeOneGetBreadcrumbNameMap = memoizeOne(
getBreadcrumbNameMap,
isEqual,
);
const buildMenuData: (menus: any) => AnyObject[] = (menus) => {
let root = [] as AnyObject[];
const map = _.reduce(
menus,
(ret: any, menu: any) => {
const node = {
...menu,
};
if (!node.pid || node.pid === '0') {
root.push(node);
}
_.set(ret, menu.id, node);
return ret;
},
{},
);
_.forEach(map, (menu: any) => {
if (menu.pid) {
let parent = map[menu.pid];
if (parent) {
if (!parent.routes) {
parent.routes = [];
}
parent.routes.push(menu);
}
}
});
root = _.sortBy(root, 'order');
return root;
};
const getMenuMatches = (flatMenuKeys: string[], path: string) =>
flatMenuKeys.filter((item: string) => {
if (item) {
return pathToRegexp(item.split('?')[0]).test(path.split('?')[0]);
}
return false;
});
/**
*
*/
const getDefaultCollapsedSubMenus = (
flatMenuKeys: string[],
breadcrumbMap: any,
originalMenu: any,
) => {
const {
location: { pathname, query },
} = history;
if (query && query.embed_url) {
const path = Base64.decode(query.embed_url as string);
const menu = _.find(breadcrumbMap, (menu: MenuDataItem, k: string) => {
if (path.indexOf(k) === 0) {
return menu;
}
return null;
});
if (_.isEmpty(menu)) {
return [];
}
return [menu.pid];
}
let currentMenu = breadcrumbMap[pathname];
if (_.isEmpty(currentMenu)) {
return [];
}
const ret = [];
do {
ret.push(currentMenu.pid);
currentMenu = _.find(
originalMenu,
(menu: MenuDataItem) => menu.id === currentMenu.pid,
);
} while (currentMenu && currentMenu.pid);
return ret;
};
/**
*
*/
const getDefaultSelectMenus: (
flatMenuKeys: string[],
breadcrumbNameMap: any,
) => string[] = (flatMenuKeys, breadcrumbNameMap) => {
const {
location: { pathname },
} = history;
const selectMenuPaths = urlToList(pathname)
.map((item: string) => getMenuMatches(flatMenuKeys, item)[0])
.filter((item: string) => item);
return _.reduce(
selectMenuPaths,
(ret: string[], path: string) => {
if (breadcrumbNameMap[path]) {
ret.push(_.get(breadcrumbNameMap[path], 'key'));
}
return ret;
},
[],
);
};
const filterMenu = (originalMenus: any[], key: string) => {
const filtered = _.filter(originalMenus, (menu: any) => menu?.name?.indexOf(key) >= 0);
return buildMenuData(filtered);
}
/**
* hook
* @param
* @returns [menuData, originalMenu, breadCrumbMap]
* - menuData
* - originalMenu
* - breadCrumbMap
*/
export function useMenu<S extends AnyObject>() {
const [menuData, setMenuData] = React.useState<AnyObject[]>([]);
const [originalMenu, setOriginalMenu] = React.useState<AnyObject[]>([]);
const [breadCrumbMap, setBreadCrumbMap] = React.useState({});
const [defaultCollapseMenus, setDefaultCollapseMenus] = React.useState<
Array<string>
>([]);
const [defaultSelectMenus, setDefaultSelectMenus] = React.useState<
Array<string>
>([]);
// iconContent: "icon-changyongtubiao-mianxing-17"
// iconStyle: "{}"
// iconType: "FONT"
useEffect(() => {
API.MenuService.getAccountMenu().then(({ success, data }) => {
if (success) {
let menus = _.map(data || [], (menu: any) => ({
key: menu.id,
id: menu.id,
pid: menu.pid,
name: menu.name,
path: menu.url,
dataPath: menu.path,
icon: _.isEmpty(menu.iconContent)
? 'icon-appstore'
: buildIcon(
menu.iconType,
menu.iconContent,
/\{.*\}/.test(menu.iconStyle) ? JSON.parse(menu.iconStyle) : {},
),
order: menu.order,
}));
setOriginalMenu(menus);
const buildMenus = buildMenuData(menus);
setMenuData(buildMenus);
const flatMenuKeys = getFlatMenuKeys(buildMenus);
const breadCrumbMap = memoizeOneGetBreadcrumbNameMap(buildMenus);
const defaultCollapseMenus = getDefaultCollapsedSubMenus(
flatMenuKeys,
breadCrumbMap,
menus,
);
const defaultSelectMenus = getDefaultSelectMenus(
flatMenuKeys,
breadCrumbMap,
);
if (_.isEmpty(defaultSelectMenus)) {
const sessionStoreKey = Storage.session.get('ACTIVE_MENU_KEY');
defaultSelectMenus.push(sessionStoreKey)
}
if (_.isEmpty(defaultCollapseMenus)) {
const sessionStoreKey = Storage.session.get('OPEN_MENU_KEY');
defaultCollapseMenus.push(...(sessionStoreKey || []))
}
setBreadCrumbMap(breadCrumbMap);
setDefaultCollapseMenus(defaultCollapseMenus);
setDefaultSelectMenus(defaultSelectMenus);
}
});
}, []);
return [
menuData,
breadCrumbMap,
defaultCollapseMenus,
defaultSelectMenus,
originalMenu,
filterMenu,
] as const;
}

@ -0,0 +1,117 @@
import type { MenuDataItem } from '../typings';
import _ from 'lodash';
export const searchMenuData = (
menuData?: MenuDataItem[],
searchKey?: string,
) => {
return (menuData || []).reduce((pre, item) => {
if (item.key) {
pre.push(item.key);
}
if (item.children) {
const newArray: string[] = pre.concat(
getOpenKeysFromMenuData(item.children) || [],
);
return newArray;
}
return pre;
}, [] as string[]);
};
export const getOpenKeysFromSelectedMenu: (
originalMenu: any[],
selectMenuKey: string[],
) => string[] = (originalMenu, selectMenuKey) => {
if (_.isEmpty(selectMenuKey) || _.isEmpty(originalMenu)) {
return [];
}
const openKeys = _.map(selectMenuKey, (key: string) =>
_.get(
_.find(originalMenu, (menu: any) => menu.id === key),
'pid',
null,
),
);
return _.filter(openKeys, (key: string) => !_.isEmpty(key));
};
export const getOpenKeysFromMenuData = (menuData?: MenuDataItem[]) => {
return (menuData || []).reduce((pre, item) => {
if (item.key) {
pre.push(item.key);
}
if (item.children) {
const newArray: string[] = pre.concat(
getOpenKeysFromMenuData(item.children) || [],
);
return newArray;
}
return pre;
}, [] as string[]);
};
const themeConfig = {
daybreak: 'daybreak',
'#1890ff': 'daybreak',
'#F5222D': 'dust',
'#FA541C': 'volcano',
'#FAAD14': 'sunset',
'#13C2C2': 'cyan',
'#52C41A': 'green',
'#2F54EB': 'geekblue',
'#722ED1': 'purple',
};
const invertKeyValues = (obj: Object) =>
Object.keys(obj).reduce((acc, key) => {
acc[obj[key]] = key;
return acc;
}, {});
/**
* #1890ff -> daybreak
*
* @param val
*/
export function genThemeToString(val?: string): string {
return val && themeConfig[val] ? themeConfig[val] : undefined;
}
/**
* Daybreak-> #1890ff
*
* @param val
*/
export function genStringToTheme(val?: string): string {
const stringConfig = invertKeyValues(themeConfig);
return val && stringConfig[val] ? stringConfig[val] : val;
}
export function clearMenuItem(menusData: MenuDataItem[]): MenuDataItem[] {
return menusData
.map((item) => {
const finalItem = { ...item };
if (!finalItem.name || finalItem.hideInMenu) {
return null;
}
if (finalItem && finalItem?.children) {
if (
!finalItem.hideChildrenInMenu &&
finalItem.children.some(
(child) => child && child.name && !child.hideInMenu,
)
) {
return {
...item,
children: clearMenuItem(finalItem.children),
};
}
// children 为空就直接删掉
delete finalItem.children;
}
return finalItem;
})
.filter((item) => item) as MenuDataItem[];
}

@ -0,0 +1,30 @@
.root {
:global {
.ant-pro-sider-logo {
white-space: nowrap;
}
.ant-layout-sider {
transition: all 0.3s ease;
}
}
}
.header {
display: flex;
.left {
flex: 0 0 auto;
}
.center {
flex: 1 1 auto;
}
}
.trigger {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
span {
color: whitesmoke;
}
}

@ -0,0 +1,17 @@
import * as React from 'react';
import styles from './index.less';
export default ({children, style = {}}: any) => {
return (
<div
className={styles.root}
style={{
width: '100%',
height: '100%',
...style
}}
>
{children}
</div>
);
};

@ -0,0 +1,5 @@
.root {
margin: 24px;
position: relative;
background: white;
}

@ -0,0 +1,6 @@
import * as React from 'react';
import styles from './index.less';
export default ({ children }: any) => {
return <div className={styles.root}>{children}</div>;
};

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save