Commit 758b333a by 杨成

创建文件

0 parents
Showing 228 changed files with 4749 additions and 0 deletions
{
"presets": [
["es2015", {"loose": true}],
"react",
"stage-0"
],
"plugins": ["react-hot-loader/babel","transform-runtime","transform-decorators-legacy"]
}
\ No newline at end of file \ No newline at end of file
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
.idea
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}\\--hot"
}
]
}
\ No newline at end of file \ No newline at end of file
# 保险业务核心系统
### 项目开发说明
1.使用 `develop` 分支开发项目,`develop` 分支代码与测试服务器代码保持一致。
2.在需求开发中如遇到交叉需求,需创建新的分支开发,新的分支基于 `develop` 分支创建。
3.当新的需求开发完成的时候,把代码合并到 `release` 分支上,`release` 分支与生产环境保持一致。
'use strict';
const fs = require('fs');
const path = require('path');
const paths = require('./paths');
// Make sure that including paths.js after env.js will read .env variables.
delete require.cache[require.resolve('./paths')];
const NODE_ENV = process.env.NODE_ENV;
if (!NODE_ENV) {
throw new Error(
'The NODE_ENV environment variable is required but was not specified.'
);
}
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
var dotenvFiles = [
`${paths.dotenv}.${NODE_ENV}.local`,
`${paths.dotenv}.${NODE_ENV}`,
// Don't include `.env.local` for `test` environment
// since normally you expect tests to produce the same
// results for everyone
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
paths.dotenv,
].filter(Boolean);
// Load environment variables from .env* files. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set. Variable expansion is supported in .env files.
// https://github.com/motdotla/dotenv
// https://github.com/motdotla/dotenv-expand
dotenvFiles.forEach(dotenvFile => {
if (fs.existsSync(dotenvFile)) {
require('dotenv-expand')(
require('dotenv').config({
path: dotenvFile,
})
);
}
});
// We support resolving modules according to `NODE_PATH`.
// This lets you use absolute paths in imports inside large monorepos:
// https://github.com/facebookincubator/create-react-app/issues/253.
// It works similar to `NODE_PATH` in Node itself:
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
// We also resolve them to make sure all tools using them work consistently.
const appDirectory = fs.realpathSync(process.cwd());
process.env.NODE_PATH = (process.env.NODE_PATH || '')
.split(path.delimiter)
.filter(folder => folder && !path.isAbsolute(folder))
.map(folder => path.resolve(appDirectory, folder))
.join(path.delimiter);
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in Webpack configuration.
const REACT_APP = /^REACT_APP_/i;
function getClientEnvironment(publicUrl) {
const raw = Object.keys(process.env)
.filter(key => REACT_APP.test(key))
.reduce(
(env, key) => {
env[key] = process.env[key];
return env;
},
{
// Useful for determining whether we’re running in production mode.
// Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV || 'development',
// Useful for resolving the correct path to static assets in `public`.
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
// This should only be used as an escape hatch. Normally you would put
// images into the `src` and `import` them in code to get their paths.
PUBLIC_URL: publicUrl,
}
);
// Stringify all values so we can feed into Webpack DefinePlugin
const stringified = {
'process.env': Object.keys(raw).reduce((env, key) => {
env[key] = JSON.stringify(raw[key]);
return env;
}, {}),
};
return { raw, stringified };
}
module.exports = getClientEnvironment;
'use strict';
// This is a custom Jest transformer turning style imports into empty objects.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process() {
return 'module.exports = {};';
},
getCacheKey() {
// The output is always the same.
return 'cssTransform';
},
};
'use strict';
const path = require('path');
// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process(src, filename) {
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
},
};
'use strict';
const path = require('path');
const fs = require('fs');
const url = require('url');
// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebookincubator/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
const envPublicUrl = process.env.PUBLIC_URL;
function ensureSlash(path, needsSlash) {
const hasSlash = path.endsWith('/');
if (hasSlash && !needsSlash) {
return path.substr(path, path.length - 1);
} else if (!hasSlash && needsSlash) {
return `${path}/`;
} else {
return path;
}
}
const getPublicUrl = appPackageJson =>
envPublicUrl || require(appPackageJson).homepage;
// We use `PUBLIC_URL` environment variable or "homepage" field to infer
// "public path" at which the app is served.
// Webpack needs to know it to put the right <script> hrefs into HTML even in
// single-page apps that may serve index.html for nested URLs like /todos/42.
// We can't use a relative path in HTML because we don't want to load something
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
function getServedPath(appPackageJson) {
const publicUrl = getPublicUrl(appPackageJson);
const servedUrl =
envPublicUrl || (publicUrl ? url.parse(publicUrl).pathname : './');
return ensureSlash(servedUrl, true);
}
// config after eject: we're in ./config/
module.exports = {
dotenv: resolveApp('.env'),
appBuild: resolveApp('build'),
appPublic: path.join(__dirname, '../build'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveApp('src/index.js'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveApp('src/setupTests.js'),
appNodeModules: resolveApp('node_modules'),
publicUrl: getPublicUrl(resolveApp('package.json')),
servedPath: getServedPath(resolveApp('package.json')),
};
'use strict';
if (typeof Promise === 'undefined') {
// Rejection tracking prevents a common issue where React gets into an
// inconsistent state due to an error, but it gets swallowed by a Promise,
// and the user has no idea what causes React's erratic future behavior.
require('promise/lib/rejection-tracking').enable();
window.Promise = require('promise/lib/es6-extensions.js');
}
// fetch() polyfill for making API calls.
require('whatwg-fetch');
// Object.assign() is commonly used with React.
// It will use the native implementation if it's present and isn't buggy.
Object.assign = require('object-assign');
// In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet.
// We don't polyfill it in the browser--this is user's responsibility.
if (process.env.NODE_ENV === 'test') {
require('raf').polyfill(global);
}
'use strict';
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const ignoredFiles = require('react-dev-utils/ignoredFiles');
const config = require('./webpack.config.dev');
const paths = require('./paths');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const host = process.env.HOST || '0.0.0.0';
module.exports = function(proxy, allowedHost) {
return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding:
// https://github.com/webpack/webpack-dev-server/issues/887
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
// However, it made several existing use cases such as development in cloud
// environment or subdomains in development significantly more complicated:
// https://github.com/facebookincubator/create-react-app/issues/2271
// https://github.com/facebookincubator/create-react-app/issues/2233
// While we're investigating better solutions, for now we will take a
// compromise. Since our WDS configuration only serves files in the `public`
// folder we won't consider accessing them a vulnerability. However, if you
// use the `proxy` feature, it gets more dangerous because it can expose
// remote code execution vulnerabilities in backends like Django and Rails.
// So we will disable the host check normally, but enable it if you have
// specified the `proxy` setting. Finally, we let you override it if you
// really know what you're doing with a special environment variable.
disableHostCheck:
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
// Enable gzip compression of generated files.
compress: true,
// Silence WebpackDevServer's own logs since they're generally not useful.
// It will still show compile warnings and errors with this setting.
clientLogLevel: 'none',
// By default WebpackDevServer serves physical files from current directory
// in addition to all the virtual build products that it serves from memory.
// This is confusing because those files won’t automatically be available in
// production build folder unless we copy them. However, copying the whole
// project directory is dangerous because we may expose sensitive files.
// Instead, we establish a convention that only files in `public` directory
// get served. Our build script will copy `public` into the `build` folder.
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
// Note that we only recommend to use `public` folder as an escape hatch
// for files like `favicon.ico`, `manifest.json`, and libraries that are
// for some reason broken when imported through Webpack. If you just want to
// use an image, put it in `src` and `import` it from JavaScript instead.
contentBase: paths.appPublic,
// By default files from `contentBase` will not trigger a page reload.
watchContentBase: true,
// Enable hot reloading server. It will provide /sockjs-node/ endpoint
// for the WebpackDevServer client so it can learn when the files were
// updated. The WebpackDevServer client is included as an entry point
// in the Webpack development configuration. Note that only changes
// to CSS are currently hot reloaded. JS changes will refresh the browser.
hot: true,
// It is important to tell WebpackDevServer to use the same "root" path
// as we specified in the config. In development, we always serve from /.
publicPath: config.output.publicPath,
// WebpackDevServer is noisy by default so we emit custom message instead
// by listening to the compiler events with `compiler.plugin` calls above.
quiet: true,
// Reportedly, this avoids CPU overload on some systems.
// https://github.com/facebookincubator/create-react-app/issues/293
// src/node_modules is not ignored to support absolute imports
// https://github.com/facebookincubator/create-react-app/issues/1065
watchOptions: {
ignored: ignoredFiles(paths.appSrc),
},
// Enable HTTPS if the HTTPS environment variable is set to 'true'
https: protocol === 'https',
host: host,
port:8000,
overlay: false,
historyApiFallback: {
// Paths with dots should still use the history fallback.
// See https://github.com/facebookincubator/create-react-app/issues/387.
disableDotRule: true,
},
public: allowedHost,
proxy,
before(app) {
// This lets us open files from the runtime error overlay.
app.use(errorOverlayMiddleware());
// This service worker file is effectively a 'no-op' that will reset any
// previous service worker registered for the same host:port combination.
// We do this in development to avoid hitting the production cache if
// it used the same host and port.
// https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432
app.use(noopServiceWorkerMiddleware());
},
};
};
This diff could not be displayed because it is too large.
{
"name": "insu-core-sys",
"version": "0.1.0",
"private": true,
"dependencies": {
"antd": "^3.8.0",
"autoprefixer": "7.1.6",
"axios": "^0.18.0",
"babel-core": "6.26.0",
"babel-eslint": "7.2.3",
"babel-jest": "20.0.3",
"babel-loader": "7.1.2",
"babel-plugin-import": "^1.8.0",
"babel-polyfill": "^6.26.0",
"babel-preset-react-app": "^3.1.1",
"babel-runtime": "6.26.0",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"chalk": "1.1.3",
"cron-parser": "^2.6.0",
"dotenv": "4.0.0",
"dotenv-expand": "4.2.0",
"draftjs-to-html": "^0.8.4",
"echarts": "^4.1.0",
"echarts-for-react": "^2.0.14",
"eslint": "4.10.0",
"eslint-config-react-app": "^2.1.0",
"eslint-loader": "1.9.0",
"eslint-plugin-flowtype": "2.39.1",
"eslint-plugin-import": "2.8.0",
"eslint-plugin-jsx-a11y": "5.1.1",
"eslint-plugin-react": "7.4.0",
"extract-text-webpack-plugin": "3.0.2",
"file-loader": "1.1.5",
"fs-extra": "3.0.1",
"html-to-draftjs": "^1.4.0",
"html-webpack-plugin": "2.29.0",
"jest": "20.0.4",
"js-md5": "^0.7.3",
"less": "2.7.3",
"less-loader": "^4.1.0",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "2.0.8",
"promise": "8.0.1",
"query-string": "^5.1.1",
"raf": "3.4.0",
"react": "^16.4.2",
"react-dev-utils": "^5.0.1",
"react-dom": "^16.4.2",
"react-draft-wysiwyg": "^1.12.13",
"react-redux": "^5.0.7",
"react-router": "^4.3.1",
"react-router-dom": "^4.3.1",
"react-umeditor": "^1.0.2",
"redux": "3.7.2",
"redux-devtools-extension": "^2.13.5",
"redux-thunk": "^2.3.0",
"resolve": "1.6.0",
"strip-ansi": "^4.0.0",
"style-loader": "0.19.0",
"sw-precache-webpack-plugin": "0.11.4",
"url-loader": "0.6.2",
"webpack": "3.8.1",
"webpack-dev-server": "2.9.4",
"webpack-manifest-plugin": "1.3.2",
"whatwg-fetch": "2.0.3"
},
"scripts": {
"start": "node scripts/start.js --hot",
"build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom"
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,mjs}"
],
"setupFiles": [
"<rootDir>/config/polyfills.js"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}",
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
],
"testEnvironment": "node",
"testURL": "http://localhost",
"transform": {
"^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
],
"moduleNameMapper": {
"^react-native$": "react-native-web"
},
"moduleFileExtensions": [
"web.js",
"js",
"json",
"web.jsx",
"jsx",
"node",
"mjs"
]
},
"babel": {
"presets": [
"react-app"
]
},
"eslintConfig": {
"extends": "react-app",
"rules": {
"eqeqeq": [
"off"
]
}
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-transform-decorators-legacy": "^1.3.5",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"css-loader": "^0.28.11",
"query-string": "^5.1.1",
"react-hot-loader": "^4.3.4"
},
"proxy": {
"/api": {
"target": "http://127.0.0.1:8080",
"changeOrigin": true
},
"/json": {
"target": "http://127.0.0.1:8081"
},
"ins-user": {
"target": "http://192.168.0.254:8000"
}
}
}
<?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="1533801000038" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2940" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M559.795332 978.804414h-95.390684l2.499756 45.195586h90.391173z" fill="#dd3c4d" p-id="2941"></path><path d="M567.2946 843.217655H456.90538l4.999512 90.391172h100.390196z" fill="#dd3c4d" p-id="2942"></path><path d="M512.09999 0.09999L240.926472 255.775022h183.282101l30.197051 542.247046h115.488722L599.991407 255.775022h183.282101z" fill="#dd3c4d" p-id="2943"></path></svg>
\ No newline at end of file \ No newline at end of file
<?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="1533793721853" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1983" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 96C282.2 96 96 282.2 96 512s186.2 416 416 416 416-186.2 416-416S741.8 96 512 96z m0 34.6c210.2 0 381.4 171 381.4 381.4 0 93-33.4 178.2-88.8 244.4-40-16.4-131.8-48.2-185.8-64.2-4.8-1.4-5.4-1.8-5.4-21.4 0-16.2 6.6-32.6 13.2-46.6 7.2-15 15.4-40.4 18.4-63.2 8.4-9.8 20-29 27.2-65.8 6.4-32.4 3.4-44.2-0.8-55.2-0.4-1.2-1-2.4-1.2-3.4-1.6-7.6 0.6-47 6.2-77.6 3.8-21-1-65.6-29.8-102.6-18.2-23.4-53.2-52-117-56h-35c-62.8 4-97.6 32.6-116 56-29 37-33.8 81.6-30 102.6 5.6 30.6 7.8 70 6.2 77.6-0.4 1.4-0.8 2.4-1.2 3.6-4.2 11-7.4 22.8-0.8 55.2 7.4 36.8 18.8 56 27.2 65.8 3 22.8 11.4 48 18.4 63.2 5.2 11 7.6 26 7.6 47.2 0 19.8-0.8 20-5.2 21.4-56.2 16.6-145.2 48.6-180.8 64-55.8-66.4-89.4-151.8-89.4-245 0-210.2 171.2-381.4 381.4-381.4z" fill="#ffffff" p-id="1984"></path></svg>
\ No newline at end of file \ No newline at end of file
<?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="1533794112374" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1983" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M662.016 247.6544a32 32 0 1 1 29.4912-56.832 390.4 390.4 0 1 1-359.0144 0 32 32 0 1 1 29.4912 56.832 326.4 326.4 0 1 0 300.032 0zM544 384a32 32 0 1 1-64 0v-256a32 32 0 1 1 64 0v256z" fill="#ffffff" p-id="1984"></path></svg>
\ No newline at end of file \ No newline at end of file
<?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="1533795273580" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2112" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 864h-112V368a16 16 0 0 0-16-16h-96a16 16 0 0 0-16 16v496h-64V544a16 16 0 0 0-16-16h-96a16 16 0 0 0-16 16v320h-80V656a16 16 0 0 0-16-16h-96a16 16 0 0 0-16 16v208h-96V128a16 16 0 0 0-32 0v736a32 32 0 0 0 32 32h736a16 16 0 0 0 0-32zM688 384h64v480h-64zM496 560h64v304h-64z m-208 112h64v192h-64z" fill="#595c81" p-id="2113"></path><path d="M320 560a64 64 0 0 0 64-64 62.4 62.4 0 0 0-3.2-17.6l104-64a64 64 0 0 0 102.4-68.8l91.2-105.6a64 64 0 0 0 41.6 16 64 64 0 1 0-64-64 64 64 0 0 0 3.2 20.8L569.6 320a64 64 0 0 0-41.6-16 64 64 0 0 0-64 64 64 64 0 0 0 3.2 20.8l-102.4 62.4A64 64 0 1 0 320 560z m400-400a32 32 0 1 1-32 32 32 32 0 0 1 32-32zM528 336a32 32 0 1 1-32 32 32 32 0 0 1 32-32z m-208 128a32 32 0 0 1 27.2 14.4v1.6h1.6a32 32 0 0 1 3.2 14.4 32 32 0 1 1-32-32z" fill="#595c81" p-id="2114"></path></svg>
\ No newline at end of file \ No newline at end of file
<?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="1534297226441" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2447" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M661.426 966.477a31.997 31.997 0 0 1-24.884-11.875 163.118 163.118 0 0 0-11.407-12.681c-62.383-62.384-163.89-62.385-226.273 0a162.692 162.692 0 0 0-11.404 12.679 32 32 0 0 1-35.55 10.043 477.718 477.718 0 0 1-151.83-87.807 32 32 0 0 1-9.072-35.775 162.867 162.867 0 0 0 5.24-16.12 158.955 158.955 0 0 0-15.985-121.413 158.948 158.948 0 0 0-97.153-74.547 162.689 162.689 0 0 0-16.64-3.53 32 32 0 0 1-26.47-25.799 484.234 484.234 0 0 1 0-175.304A32 32 0 0 1 66.47 398.55a162.906 162.906 0 0 0 16.64-3.53 158.953 158.953 0 0 0 97.153-74.548 158.955 158.955 0 0 0 15.984-121.412 162.76 162.76 0 0 0-5.24-16.118 32 32 0 0 1 9.071-35.777A477.694 477.694 0 0 1 351.91 59.357 32 32 0 0 1 387.457 69.4a163.118 163.118 0 0 0 11.407 12.681c62.383 62.382 163.889 62.383 226.273 0a163.224 163.224 0 0 0 11.406-12.68 32.003 32.003 0 0 1 35.548-10.042 477.705 477.705 0 0 1 151.831 87.807 32 32 0 0 1 9.072 35.774 162.79 162.79 0 0 0-5.24 16.122c-22.834 85.218 27.919 173.125 113.137 195.96a163.048 163.048 0 0 0 16.644 3.53A32 32 0 0 1 984 424.35a484.236 484.236 0 0 1 0 175.303 32 32 0 0 1-26.47 25.8 162.681 162.681 0 0 0-16.64 3.53A160 160 0 0 0 827.754 824.94a162.92 162.92 0 0 0 5.24 16.122 32 32 0 0 1-9.071 35.774 477.7 477.7 0 0 1-151.832 87.808 31.965 31.965 0 0 1-10.664 1.833zM511.999 831.059a222.534 222.534 0 0 1 158.392 65.607l0.092 0.093a413.206 413.206 0 0 0 95.457-55.233l-0.006-0.021a224 224 0 0 1 158.392-274.342l0.043-0.012a420.693 420.693 0 0 0 0-110.3l-0.043-0.012a223.999 223.999 0 0 1-158.391-274.342l0.006-0.022a413.248 413.248 0 0 0-95.458-55.232l-0.09 0.09A222.533 222.533 0 0 1 512 192.943a222.53 222.53 0 0 1-158.392-65.609l-0.092-0.092a413.196 413.196 0 0 0-95.456 55.233l0.005 0.02a222.534 222.534 0 0 1-22.377 169.976A222.535 222.535 0 0 1 99.673 456.839l-0.043 0.01a420.693 420.693 0 0 0 0 110.301l0.043 0.011A222.534 222.534 0 0 1 235.687 671.53a222.534 222.534 0 0 1 22.378 169.976l-0.006 0.021a413.268 413.268 0 0 0 95.456 55.233l0.091-0.091a222.533 222.533 0 0 1 158.393-65.61z" p-id="2448" fill="#ffffff"></path><path d="M512 704c-105.87 0-192-86.13-192-192s86.13-192 192-192 192 86.13 192 192-86.13 192-192 192z m0-320a128 128 0 1 0 128 128 128.145 128.145 0 0 0-128-128z" p-id="2449" fill="#ffffff"></path></svg>
\ No newline at end of file \ No newline at end of file
No preview for this file type
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>保险业务核心系统</title>
</head>
<body>
<noscript>
<!-- You need to enable JavaScript to run this app. -->
</noscript>
<div id="root"></div>
<div class="ajax-loading" id="ajaxLoading" style="display: none;">
<div class="overlay"></div>
<div class="loading">
<!-- <img src="./assets/images/loading.gif" alt=""> -->
<span>加载中,请稍后...</span>
</div>
</div>
</body>
</html>
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
'use strict';
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
const path = require('path');
const chalk = require('chalk');
const fs = require('fs-extra');
const webpack = require('webpack');
const config = require('../config/webpack.config.prod');
const paths = require('../config/paths');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
const printBuildError = require('react-dev-utils/printBuildError');
const measureFileSizesBeforeBuild =
FileSizeReporter.measureFileSizesBeforeBuild;
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
const useYarn = fs.existsSync(paths.yarnLockFile);
// These sizes are pretty large. We'll warn for bundles exceeding them.
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
}
// First, read the current file sizes in build directory.
// This lets us display how much they changed later.
measureFileSizesBeforeBuild(paths.appBuild)
.then(previousFileSizes => {
// Remove all content but keep the directory so that
// if you're in it, you don't end up in Trash
fs.emptyDirSync(paths.appBuild);
// Merge with the public folder
copyPublicFolder();
// Start the webpack build
return build(previousFileSizes);
})
.then(
({ stats, previousFileSizes, warnings }) => {
if (warnings.length) {
console.log(chalk.yellow('Compiled with warnings.\n'));
console.log(warnings.join('\n\n'));
console.log(
'\nSearch for the ' +
chalk.underline(chalk.yellow('keywords')) +
' to learn more about each warning.'
);
console.log(
'To ignore, add ' +
chalk.cyan('// eslint-disable-next-line') +
' to the line before.\n'
);
} else {
console.log(chalk.green('Compiled successfully.\n'));
}
console.log('File sizes after gzip:\n');
printFileSizesAfterBuild(
stats,
previousFileSizes,
paths.appBuild,
WARN_AFTER_BUNDLE_GZIP_SIZE,
WARN_AFTER_CHUNK_GZIP_SIZE
);
console.log();
const appPackage = require(paths.appPackageJson);
const publicUrl = paths.publicUrl;
const publicPath = config.output.publicPath;
const buildFolder = path.relative(process.cwd(), paths.appBuild);
printHostingInstructions(
appPackage,
publicUrl,
publicPath,
buildFolder,
useYarn
);
},
err => {
console.log(chalk.red('Failed to compile.\n'));
printBuildError(err);
process.exit(1);
}
);
// Create the production build and print the deployment instructions.
function build(previousFileSizes) {
console.log('Creating an optimized production build...');
let compiler = webpack(config);
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
if (err) {
return reject(err);
}
const messages = formatWebpackMessages(stats.toJson({}, true));
if (messages.errors.length) {
// Only keep the first error. Others are often indicative
// of the same problem, but confuse the reader with noise.
if (messages.errors.length > 1) {
messages.errors.length = 1;
}
return reject(new Error(messages.errors.join('\n\n')));
}
if (
process.env.CI &&
(typeof process.env.CI !== 'string' ||
process.env.CI.toLowerCase() !== 'false') &&
messages.warnings.length
) {
console.log(
chalk.yellow(
'\nTreating warnings as errors because process.env.CI = true.\n' +
'Most CI servers set it automatically.\n'
)
);
return reject(new Error(messages.warnings.join('\n\n')));
}
return resolve({
stats,
previousFileSizes,
warnings: messages.warnings,
});
});
});
}
function copyPublicFolder() {
fs.copySync(paths.appPublic, paths.appBuild, {
dereference: true,
filter: file => file !== paths.appHtml,
});
}
'use strict';
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
const fs = require('fs');
const chalk = require('chalk');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const clearConsole = require('react-dev-utils/clearConsole');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const {
choosePort,
createCompiler,
prepareProxy,
prepareUrls,
} = require('react-dev-utils/WebpackDevServerUtils');
const openBrowser = require('react-dev-utils/openBrowser');
const paths = require('../config/paths');
const config = require('../config/webpack.config.dev');
const createDevServerConfig = require('../config/webpackDevServer.config');
const useYarn = fs.existsSync(paths.yarnLockFile);
const isInteractive = process.stdout.isTTY;
// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
}
// Tools like Cloud9 rely on this.
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const HOST = process.env.HOST || '0.0.0.0';
if (process.env.HOST) {
console.log(
chalk.cyan(
`Attempting to bind to HOST environment variable: ${chalk.yellow(
chalk.bold(process.env.HOST)
)}`
)
);
console.log(
`If this was unintentional, check that you haven't mistakenly set it in your shell.`
);
console.log(`Learn more here: ${chalk.yellow('http://bit.ly/2mwWSwH')}`);
console.log();
}
// We attempt to use the default port but if it is busy, we offer the user to
// run on a different port. `choosePort()` Promise resolves to the next free port.
choosePort(HOST, DEFAULT_PORT)
.then(port => {
if (port == null) {
// We have not found a port.
return;
}
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name;
const urls = prepareUrls(protocol, HOST, port);
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler(webpack, config, appName, urls, useYarn);
// Load proxy config
const proxySetting = require(paths.appPackageJson).proxy;
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
// Serve webpack assets generated by the compiler over a web sever.
const serverConfig = createDevServerConfig(
proxyConfig,
urls.lanUrlForConfig
);
const devServer = new WebpackDevServer(compiler, serverConfig);
// Launch WebpackDevServer.
devServer.listen(port, HOST, err => {
if (err) {
return console.log(err);
}
if (isInteractive) {
clearConsole();
}
console.log(chalk.cyan('Starting the development server...\n'));
openBrowser(urls.localUrlForBrowser);
});
['SIGINT', 'SIGTERM'].forEach(function(sig) {
process.on(sig, function() {
devServer.close();
process.exit();
});
});
})
.catch(err => {
if (err && err.message) {
console.log(err.message);
}
process.exit(1);
});
'use strict';
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
process.env.PUBLIC_URL = '';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
const jest = require('jest');
let argv = process.argv.slice(2);
// Watch unless on CI or in coverage mode
if (!process.env.CI && argv.indexOf('--coverage') < 0) {
argv.push('--watch');
}
jest.run(argv);
export let getApiName = str => {
return str.substr(str.lastIndexOf('/') + 1, str.length)
}
export let createApiObj = ((apiPathArr, PROJECT_ROOT = '') => {
let obj = {};
apiPathArr.forEach(item => {
obj[getApiName(item)] = PROJECT_ROOT + item
})
return obj
})
\ No newline at end of file \ No newline at end of file
import { createApiObj } from './common'
const PROJECT_ROOT = '/ins-dict'
/*字典管理*/
export const API_DICT_MANAGE = createApiObj([
'/dict/addDict', // 添加字典
'/dict/getDict', // 字典列表查询
'/dict/getDictById', // 字典列表修改根据id查找
'/dict/editDict', // 字典修改
'/dict/deleteDictById', // 字典列表删除
'/dict/getDictChild', // 字典子级查询
'/dict/getDictsByCode', // 字典查找(根据代码)
'/dict/getChildsById', // 字典查找(根据代码)
], PROJECT_ROOT)
/*字典管理*/
export { API_DICT_MANAGE } from './dict'
/*用户模块*/
export {
// API_CHANNEL_MANAGE, /*渠道管理*/
API_SYSORORG_MANAGE, /*组织机构管理*/
API_ROLE_MANAGE, /*角色管理*/
API_IMG_CODE, /*图片验证码*/
API_USER_MANAGE, /*用户管理接口*/
API_ORG_MANAGE, /*机构管理*/
API_CLIENT_MANAGE, /*客户端授权*/
API_MENU_MANAGE, /*菜单管理*/
API_SYSPARAM_MANAGE, /*系统参数*/
} from './ins-user'
/* 系统监控模块 */
export {
API_SYS_MONITOR /*系统监控*/
} from './ins-monitor'
export {
API_SYS_MSG /* 消息推送 */
} from './ins-msg'
/* 客户列表 */
export {
API_CUSTOMER_MANAGE /*客户列表*/
} from './ins-customer'
/* 文件上传 */
export {
API_FILEUPLOAD_MANAGE /*文件上传*/
} from './ins-file'
/* 定时任务管理 */
export {
API_TASK_MONITOR, /*任务管理*/
API_HISTORY_MONITOR, /*历史轨迹管理*/
API_STATUS_MONITOR, /*历史状态管理*/
} from './ins-time-job'
/*渠道管理*/
export {
API_CHANNEL_MANAGE,
}from './ins-channel'
/* banner管理 */
export {
API_SYS_CMS
} from './ins-cms';
/* 健康告知管理 */
export {
API_SURVEY_MANAGE,
API_SURVEY_QURADIO,
API_SURVEY_DELETE_BY_ID,
API_SURVEY_QUCHECKBOX,
API_SURVEY_QUFILLBLANK
} from './ins-survey';
import { createApiObj } from './common'
const PROJECT_ROOT = '/ins-channel'
/*渠道管理*/
export const API_CHANNEL_MANAGE = createApiObj([
'/channel/getParamChannel', //渠道查询(多条件)
'/channel/addChannel', //添加渠道
'/channel/deleteChannel', //删除渠道
'/channel/getChannelById', //根据id查询渠道信息
'/channel/updChannel', //修改渠道
'/channel/enableOrDisableById',//根据id启用或者停用渠道
], PROJECT_ROOT)
import { createApiObj } from './common';
const PROJECT_ROOT = '/ins-cms';
/* 系统监控 */
export const API_SYS_CMS = createApiObj([
'/banner/addBanner', // banner添加
'/banner/deleteBannerById', // banner删除
'/banner/editBanner', // banner修改
'/banner/getAppBanner', // banner分页
'/banner/getAppBannerById', // banner查找
],PROJECT_ROOT)
\ No newline at end of file \ No newline at end of file
import { createApiObj } from './common'
const PROJECT_ROOT = '/ins-customer'
/*字典管理*/
export const API_CUSTOMER_MANAGE = createApiObj([
'/customer/getCusParamQuery', // 客户列表查询
'/customer/delCustomerByid', // 客户列表查询
'/customer/addCustomerAndCustomer', // 添加客户
'/customer/getCustomerByid',
'/customer/updCustomerAndCustomer', //修改客户
'/customerExport/exportCustomerList', // 导出
'/customerOther/getAllListInsuranceCompany',
'/customerOther/addCustomerLabel', //添加客户标签
'/customerOther/getAllListCustomerLabel', // 获取客户的全部标签
'/customerOther/delCustomerLabelByid', // 删除客户标签
'/customerOther/getAllListTypesInsurance', //获取险种
'/customerOther/addInsuranceCompany', //获取险种
'/customerOther/updInsuranceCompany', // 修改保险公司
'/customerOther/getInsuranceCompanyByid', // 获取保险公司id信息
'/customerOther/delInsuranceCompanyByid', // 删除保险公司
'/customerOther/delTypesInsuranceByid', // 删除险种
'/customerOther/getTypesInsuranceByid', // 获取险种id信息
'/customerOther/addTypesInsurance', // 新增险种
'/customerOther/updTypesInsurance', // 修改险种
], PROJECT_ROOT)
import { createApiObj } from './common'
const PROJECT_ROOT = '/ins-file'
/*文件上传*/
export const API_FILEUPLOAD_MANAGE = createApiObj([
'/image/upload/base64', // 上传图片
], PROJECT_ROOT)
import { createApiObj } from './common';
const PROJECT_ROOT = '/ins-monitor';
/* 系统监控 */
export const API_SYS_MONITOR = createApiObj([
'/sysLog/getSysLogPageListByCondition', // 日志查询
'/server/getServerInfo', // 获取服务器信息
'/onlineUser/deleteUser', // 踢出在线用户
'/onlineUser/getOnlineUsers', // 获取在线人数
'/redisManage/getAllKey', // 获取redis所有的key
'/redisManage/getMapValueByKey', // 根据map的key获取值
'/redisManage/getValueByKey', // 据key获取数据
'/redisManage/removeByKey', // 根据key删除缓存
'/redisManage/removeAllKey', // 根据key删除缓存
'/websocket', // 根据key删除缓存
],PROJECT_ROOT)
\ No newline at end of file \ No newline at end of file
import { createApiObj } from './common';
const PROJECT_ROOT = '/ins-msg';
/* 系统监控 */
export const API_SYS_MSG = createApiObj([
'/sysMsg/getSysMsgListByCondition', // 消息分页查询
'/sysMsg/deleteSysMsg', // 消息删除
'/sysMsg/updateUsingStatus', // 消息启用和停用
'/sysMsg/pushAgain', // 再次推送
'/sysMsg/getSysMsgById', // 查询消息信息
'/sysMsg/insertSysMsg', // 消息新增或修改
'/sysMsgTemplate/getSysMsgTempListByCondition', // 消息模板查询
'/sysMsgTemplate/deleteSysMsgTemplate', // 消息模板删除
'/sysMsgTemplate/getSysMsgTemplateById', // 根据id查询模板信息
'/sysMsgTemplate/insertSysMsgTemplate', // 模板的新增和修改
'/sysAppMsgSummary/getSysAppMsgDetailList', // app消息详情分页查询
'/sysAppMsgSummary/deleteSysAppMsgSummary', // app消息汇总删除
'/sysAppMsgSummary/getSysAppMsgSummaryList', // app消息汇总分页查询
'/sysMsgTemplate/deleteSysMsgTemplate',
'/sysPcMsgDetail/getSysPcMsgDetail',
'/sysPcMsgDetail/updateReadStatus' ,
'/sysPcMsgDetail/getSysPcMsgDetailListByCondition', // 查询消息列表
'/sysPcMsgDetail/deleteSysPcMsgDetail', // 查询消息列表
'/ws/asset', // 根据key删除缓存
'/sysPcMsgDetail/getUnReadSysPcMsgDetailCount', // 根据key删除缓存
'/sysPcMsgDetail/updateReadStatusByBatchId'
],PROJECT_ROOT)
\ No newline at end of file \ No newline at end of file
import { createApiObj } from './common';
const PROJECT_ROOT = '/ins-survey';
/* 健康告知 */
export const API_SURVEY_MANAGE = createApiObj([
'/survey/buildSurvey', // 设计健康告知
'/survey/copySurvey', // 复制健康告知
'/survey/createSurvey', // 创建健康告知
'/survey/deleteById', // 根据id删除健康告知
'/survey/getQuestionList', // 查询健康告知列表
'/survey/updateStateById', // 根据id变更健康告知发布状态
],PROJECT_ROOT)
export const API_SURVEY_QURADIO = createApiObj([
'/quradio/save', // 保存单选题
'/quradio/deleteById', // 删除单选题
],PROJECT_ROOT)
//单选操作
export const API_SURVEY_DELETE_BY_ID = createApiObj([
'/question/deleteQuestionById', // 删除单选题
],PROJECT_ROOT)
//多选操作
export const API_SURVEY_QUCHECKBOX = createApiObj([
'/qucheckbox/deleteById', // 删除多选题
'/qucheckbox/save', // 保存多选题
],PROJECT_ROOT)
//填空
export const API_SURVEY_QUFILLBLANK = createApiObj([
'/qufillblank/save', // 保存填空
],PROJECT_ROOT)
import { createApiObj } from './common';
const PROJECT_ROOT = '/ins-time-job';
/* 定时任务管理 */
export const API_TASK_MONITOR = createApiObj([
'/timeJob/getParamQuery', // 多条件查询定时任务
'/timeJob/delTimeJobById',// 根据id删除定时任务
'/timeJob/getTimeJobById',// 根据id查询定时任务信息
'/timeJob/immediatelyRun',// 立即运行定时任务
'/timeJob/startOrStopTimeJobById',// 根据id停用定时任务
'/timeJob/updTimeJob',// 修改定时任务
'/timeJob/getTimeJobByName',// 根据任务名称查询定时任务详情
'/timeJob/executiveOutcomes',// 根据任务名称查询定时任务详情
],PROJECT_ROOT)
/* 历史轨迹管理 */
export const API_HISTORY_MONITOR = createApiObj([
'/timeJobExecution/getChannelByJobName',//根据jobName查询历史轨迹信息
'/timeJobExecution/getParamQuery',// 多条件查询历史轨迹
],PROJECT_ROOT)
/* 历史状态管理 */
export const API_STATUS_MONITOR = createApiObj([
' /timeJobStatus/getParamQuery',//多条件查询历史状态
' /timeJobStatus/getStatusTraceByJobName',//根据job_name查询历史状态信息
],PROJECT_ROOT)
\ No newline at end of file \ No newline at end of file
import { createApiObj } from './common'
const PROJECT_ROOT = '/ins-user'
/*渠道管理*/
export const API_CHANNEL_MANAGE = createApiObj([
'/channel/getParamChannel',
], PROJECT_ROOT)
/*组织机构管理*/
export const API_SYSORORG_MANAGE = createApiObj([
'/org/addOrg', //机构增加
'/org/deleteOrg', //机构删除
'/org/getOrgById', // 根据机构id查询
'/org/getOrgByName', // 根据机构名称查询
'/org/getOrgTreeList', // 机构树状图
'/org/updateOrg', // 机构修改
'/org/getChildsOrgByCode', // 根据code 查下级
], PROJECT_ROOT)
/*角色管理*/
export const API_ROLE_MANAGE = createApiObj([
'/role/getRoleAll', //获取所有角色
'/role/getRoleModuleByRoleId', //根据roledId获取角色模块
'/role/getRoleById', //根据id查询角色
'/role/addRole', //添加角色
'/role/deleteRole', //删除角色
'/role/deleteRoleModule', //根据id删除角色模块
'/role/addRoleModule', //添加角色模块
'/role/getRoleJurisdiction', //根据userId获取权限数据
'/role/getRoleParam', //角色模糊查询,状态,名称模糊
'/role/updateRole', //修改角色(名称和状态)
'/role/updateRoleModule', //修改角色相对应所有权限
'/role/getRoleGiveUser', // 多条件查询角色分配用户
'/role/getRoleNoGiveUser', // 多条件查询角色未分配的用户
'/role/deleteByRoleIdBatchUser', // 取消角色分配用户的授权
'/role/updateRoleAndModule', // 修改角色(包含模块数据)
], PROJECT_ROOT)
/*图片验证码*/
export const API_IMG_CODE = createApiObj([
'/imgCode/getImgCode', // 获取图片验证码
'/imgCode/verifyImgCode', // 获取图片验证码
], PROJECT_ROOT)
/*用户管理接口*/
export const API_USER_MANAGE = createApiObj([
'/user/getUserRoleByUserId', //用户角色查询,根据userId
'/user/addOrUpdUserRole', //添加用户角色
'/user/batchAddUserRole', // 批次添加用户角色
'/user/addUser', //添加用户
'/user/deleteUser', //删除用户
'/user/deleteUserRole', //根据用户id删除角色
'/user/getParamQuery', //用户信息多条件查询
'/user/getUserByid', //根据id获取用户信息
'/user/addUserRole', //添加用户角色
'/user/getUserRoleList', //查询所有的用户角色
'/user/login', //登录
'/user/logout', //登出
'/user/resetPassword', //重置密码
'/user/updPassword', //修改密码
'/user/updateUser', //修改密码
'/user/batchAddUserRole', //批量绑定角色
], PROJECT_ROOT)
/*菜单管理*/
export const API_MENU_MANAGE = createApiObj([
'/module/deleteModule', //菜单删除
'/module/getModuleByModuleId', //根据菜单ID查询菜单信息
'/module/getModuleList', // 菜单查询
'/module/getModuleTreeList', // 菜单树形结构查询
'/module/insertModule', // 菜单新增或修改
], PROJECT_ROOT)
// 客户端管理
export const API_CLIENT_MANAGE = createApiObj([
'/user/clientAuthorization', //客户端列表查询
'/user/enaDisAccount', //客户端授权 启用禁用操作
'/user/enaDisableClient', //客户端授权 设置终端
], PROJECT_ROOT)
// 参数设置
export const API_SYSPARAM_MANAGE = createApiObj([
'/sysParam/deleteSysParam', //参数删除
'/sysParam/getSysParamById', //根据参数ID查询参数信息
'/sysParam/getSysParamList', //参数分页查询
'/sysParam/insertSysParam', //参数新增或修改
'/sysParam/getParamKeyValueByKeyName', // 根据keyName查询keyValue
'/sysParam/refreshCacheOfParam', // 刷新缓存
], PROJECT_ROOT)
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}
.App-header {
background-color: #222;
height: 150px;
padding: 20px;
color: #333;
}
.App-title {
font-size: 1.5em;
}
.App-intro {
font-size: large;
}
@keyframes App-logo-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
import './App.css';
import React, { Component } from 'react';
import { HashRouter, Redirect } from 'react-router-dom'
class App extends Component {
constructor(props) {
super(props)
this.state = {
hasError: false
}
}
componentDidCatch(err, info) {
console.log(err, info);
this.setState({
hasError: true
})
}
render() {
return this.state.hasError ? <HashRouter>
<Redirect to="/home" />
</HashRouter> : (
<div >
{this.props.children}
</div>
);
}
}
var DEBUG = false;
if(!DEBUG){
if(!window.console) window.console = {};
var methods = ["log","debug","warn","info"];
for(var i=0;i<methods.length;i++){
console[methods[i]] = function(){};
}
}
export default App;
\ No newline at end of file \ No newline at end of file
import React from 'react'
import { Layout, Icon} from 'antd'
import Header from './components/Header'
import NavLeft from './components/NavLeft'
import './style/common.less'
import NavLink from 'react-router-dom/NavLink';
const {Sider} = Layout;
export default class Admin extends React.Component {
state = {
collapsed: false,
};
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
}
render() {
return (
<div className="container">
<Layout style={{minHeight: '100vh'}}>
<Sider
trigger={null}
collapsible
collapsed={this.state.collapsed}
>
<div className="logo">
<div className='logo_img'>
<NavLink to="/home" replace>
<img style={{display: !this.state.collapsed ? "block" : "none"}}
src={require('./resource/assets/images/logo.png')} alt=""/>
</NavLink>
</div>
<Icon
className="trigger"
type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
onClick={this.toggle}
/>
</div>
<NavLeft collapsed={this.state.collapsed}></NavLeft>
</Sider>
<Layout>
<Header>
</Header>
<div className='contentbg'>
{this.props.children}
</div>
</Layout>
</Layout>
</div>
)
}
}
\ No newline at end of file \ No newline at end of file
import axios from 'axios'
import { message } from 'antd'
import SYS_CONFIG from '@src/config/constant.js'
import Storage from '@src/utils/localStorage'
export default class Axios {
static ajax(options) {
const userInfo = Storage.get('userInfo')
const isLogin = window.location.href.includes('/login')
return new Promise((resolve, reject) => {
if (!isLogin) {
if (!userInfo || !userInfo.token) {
//message.warn('token失效,请重新登录')
window.location.href = '#/login'
return
}
}
axios({
...options,
url: options.url,
method: options.method ? options.method : 'POST',
baseURL: SYS_CONFIG.baseApi,
responseType: 'blob',
headers: options.headers ? options.headers : {
'Content-Type': 'application/json; charset=UTF-8',
'X-Requested-with': 'XMLHttpRequest',
'token': !isLogin ? userInfo.token : '',
},
params: options.params ? options.params : '',
data: JSON.stringify(options.data) === "{}" ? null : JSON.stringify(options.data),
}).then(res => {
if (res.status === 200) {
resolve(res)
} else {
reject(res.data)
}
}).catch(err => {
message.error('请求超时,请重试');
reject(err)
})
})
}
}
\ No newline at end of file \ No newline at end of file
import axios from 'axios'
import { message } from 'antd'
import SYS_CONFIG from '@src/config/constant.js'
import Storage from '@src/utils/localStorage'
export default class Axios {
static ajax(options) {
const userInfo = Storage.get('userInfo')
const isLogin = window.location.href.includes('/login')
return new Promise((resolve, reject) => {
if (!isLogin) {
if (!userInfo || !userInfo.token) {
window.location.href = '#/login'
return
}
}
axios({
...options,
url: options.url,
method: options.method ? options.method : 'POST',
baseURL: SYS_CONFIG.baseApi,
headers: options.headers ? options.headers : {
'Content-Type': 'application/json; charset=UTF-8',
'X-Requested-with': 'XMLHttpRequest',
'token': !isLogin ? userInfo.token : '',
},
params: options.params ? options.params : '',
data: JSON.stringify(options.data) === "{}" ? null : JSON.stringify(options.data),
}).then(res => {
if (res.status === 200) {
let resp = res.data;
if (res.data.code == 0) {
resolve(resp.data)
} else {
if ((res.data.msg && res.data.msg.includes('token')) || (res.data.msg && res.data.msg.includes('在别处登录')) ) {
Storage.clearToken()
window.location.href = '#/login'
return
}
if(res.data.msg && res.data.msg.length < 30){
message.error(res.data.msg)
return
}
// message.error('请求超时,请重试');
}
} else {
reject(res.data)
}
}).catch(err => {
message.error('请求超时,请重试');
reject(err)
})
})
}
static optAjax(options) {
const userInfo = Storage.get('userInfo')
const isLogin = window.location.href.includes('/login')
return new Promise((resolve, reject) => {
if (!isLogin) {
if (!userInfo || !userInfo.token) {
// message.warn('token失效,请重新登录')
window.location.href = '#/login'
return
}
}
axios({
...options,
url: options.url,
method: options.method ? options.method : 'POST',
baseURL: SYS_CONFIG.baseApi,
headers: options.headers ? options.headers : {
'Content-Type': 'application/json; charset=UTF-8',
'X-Requested-with': 'XMLHttpRequest',
'token': !isLogin ? userInfo.token : '',
},
params: options.params ? options.params : '',
data: JSON.stringify(options.data) === "{}" ? null : JSON.stringify(options.data),
}).then(res => {
if (res.status === 200) {
let resp = res.data;
if (res.data.code == 0) {
resolve(resp.data)
}else if(res.data.code === -2){
window.location.href = '#/login'
return
}else {
if ((res.data.msg && res.data.msg.includes('token')) || (res.data.msg && res.data.msg.includes('在别处登录')) ) {
Storage.clearToken()
window.location.href = '#/login'
return
}
if(res.data.msg && res.data.msg.length < 30){
message.error(res.data.msg)
resolve(resp)
return
}
// message.error('请求超时,请重试');
}
} else {
reject(res.data)
}
}).catch(err => {
message.error('请求超时,请重试');
reject(err)
})
})
}
}
\ No newline at end of file \ No newline at end of file
import React from 'react'
import { message } from 'antd'
import Storage from '@src/utils/localStorage'
import { withRouter } from 'react-router-dom'
@withRouter
class AuthRoute extends React.Component {
state = {
}
componentWillMount(){
//获取用户信息
const publicList = ['/login']
const userInfo = Storage.get('userInfo')
const { pathname } = this.props.location
if (publicList.indexOf(pathname) > -1) {
return null
}
//判断是否登录
if(!userInfo || !userInfo.token ){
// message.warn('请重新登录')
window.location.href = '#/login'
return
}
}
render() {
return <div>{this.props.children}</div>
}
}
export default AuthRoute
\ No newline at end of file \ No newline at end of file
import React from 'react'
import { Input, Select, Form, Button, Checkbox, Radio, DatePicker} from 'antd'
import Utils from '../../utils/utils';
const FormItem = Form.Item;
const Option = Select.Option;
class FilterForm extends React.Component{
handleFilterSubmit = ()=>{
let fieldsValue = this.props.form.getFieldsValue();
this.props.filterSubmit(fieldsValue);
}
reset = ()=>{
this.props.form.resetFields();
}
initFormList = ()=>{
const { getFieldDecorator } = this.props.form;
const formList = this.props.formList;
const formItemList = [];
if (formList && formList.length>0){
formList.forEach((item,i)=>{
let label = item.label;
let field = item.field;
let initialValue = item.initialValue || '';
let placeholder = item.placeholder;
let width = item.width;
if (item.type == '时间查询'){
const begin_time = <FormItem label="订单时间" key={field}>
{
getFieldDecorator('begin_time')(
<DatePicker showTime={true} placeholder={placeholder} format="YYYY-MM-DD HH:mm:ss"/>
)
}
</FormItem>;
formItemList.push(begin_time)
const end_time = <FormItem label="~" colon={false} key={field}>
{
getFieldDecorator('end_time')(
<DatePicker showTime={true} placeholder={placeholder} format="YYYY-MM-DD HH:mm:ss" />
)
}
</FormItem>;
formItemList.push(end_time)
}else if(item.type == 'INPUT'){
const INPUT = <FormItem label={label} key={field}>
{
getFieldDecorator([field],{
initialValue: initialValue
})(
<Input type="text" placeholder={placeholder} />
)
}
</FormItem>;
formItemList.push(INPUT)
} else if (item.type == 'SELECT') {
const SELECT = <FormItem label={label} key={field}>
{
getFieldDecorator([field], {
initialValue: initialValue
})(
<Select
style={{ width: width }}
placeholder={placeholder}
>
{Utils.getOptionList(item.list)}
</Select>
)
}
</FormItem>;
formItemList.push(SELECT)
} else if (item.type == 'CHECKBOX') {
const CHECKBOX = <FormItem label={label} key={field}>
{
getFieldDecorator([field], {
valuePropName: 'checked',
initialValue: initialValue //true | false
})(
<Checkbox>
{label}
</Checkbox>
)
}
</FormItem>;
formItemList.push(CHECKBOX)
}
})
}
return formItemList;
}
render(){
return (
<Form layout="inline">
{ this.initFormList() }
<FormItem>
<Button type="primary" style={{ margin: '0 20px' }} onClick={this.handleFilterSubmit}>查询</Button>
<Button onClick={this.reset}>重置</Button>
</FormItem>
</Form>
);
}
}
export default Form.create({})(FilterForm);
\ No newline at end of file \ No newline at end of file
import React from 'react'
import { Row, Col} from 'antd';
import IconConfig from './../../../config/IconConfig'
import './index.less'
class IconOptionsForm extends React.Component {
state = {}
selectedUser= (data)=> {
console.log(data);
if (data) {
this.props.getIconObj(
data
)
}
this.setState({
iconCheckedObj: data
})
}
renderIconLists = (data) => {
const iconCheckedObj = this.props.iconCheckedObj
let _this = this
return data.map(
function (item ,index) {
item.key = index
return <Col key={index} className="iconCol"span={4} style={{backgroundColor:(iconCheckedObj == item.name ) ? "#00a0e9" : "#fff"}} onClick={()=>{_this.selectedUser(item.name)}}>
<div className={ ` iconfont ${item.className}`}></div>
<div>{item.name}</div>
</Col>
}
)
}
render(){
return(
<div className="iconlist">
<div className="iconRow">
<Row type="flex" justify="left" align="middle">
{this.renderIconLists(IconConfig)}
</Row>
</div>
</div>
)
}
}
export default IconOptionsForm
\ No newline at end of file \ No newline at end of file
@font-face {
font-family: 'iconfont'; /* project id 779786 */
src: url('//at.alicdn.com/t/font_779786_qwvd25m8p0d.eot');
src: url('//at.alicdn.com/t/font_779786_qwvd25m8p0d.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_779786_qwvd25m8p0d.woff') format('woff'),
url('//at.alicdn.com/t/font_779786_qwvd25m8p0d.ttf') format('truetype'),
url('//at.alicdn.com/t/font_779786_qwvd25m8p0d.svg#iconfont') format('svg');
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-xuanzefenzu:before { content: "\e6c9"; }
.icon-xiugaimima01:before { content: "\e606"; }
.icon-fangwen:before { content: "\e644"; }
.icon-jiantou:before { content: "\e64a"; }
.icon-jianyi:before { content: "\e607"; }
.icon-weibiaoti25:before { content: "\e62c"; }
.icon-duigou:before { content: "\e60d"; }
.icon-chazhaobiaodanliebiao:before { content: "\e76a"; }
.icon-xuanzhongduigou:before { content: "\e661"; }
.icon-shujutu:before { content: "\e711"; }
.icon-zhanghu:before { content: "\e62b"; }
.icon-mima:before { content: "\e646"; }
.icon-liebiao:before { content: "\e61c"; }
.icon-duigou1:before { content: "\e640"; }
.icon-chaxun:before { content: "\e61b"; }
.icon-chanpin:before { content: "\e67b"; }
.icon-IP:before { content: "\e632"; }
.icon-914caidan_mokuai:before { content: "\e683"; }
.icon-wenhao:before { content: "\e628"; }
.icon-zhuyi:before { content: "\e763"; }
.icon-rili:before { content: "\e60a"; }
.icon-channel:before { content: "\e671"; }
.icon-channel1:before { content: "\e7d5"; }
.icon-error:before { content: "\e7f6"; }
.icon-nav-set-oper:before { content: "\e75f"; }
.icon-fangwen1:before { content: "\e608"; }
.icon-jiantou1:before { content: "\e612"; }
.icon-touxiang:before { content: "\e673"; }
.icon-wode:before { content: "\e62a"; }
.icon-kaifazheID:before { content: "\e60b"; }
.icon-shouye:before { content: "\e611"; }
.icon-baobiao:before { content: "\e65c"; }
.icon-ecurityCode:before { content: "\e60e"; }
.icon-qushi:before { content: "\e609"; }
.icon-icon-:before { content: "\e6e5"; }
.icon-guanjianzhibiao:before { content: "\e7ae"; }
.icon-tuanduijianshe:before { content: "\e7b2"; }
.icon-kujialeqiyezhan_shujutongji:before { content: "\e64d"; }
.icon-yonghu1:before { content: "\e616"; }
.icon-kehu:before { content: "\e645"; }
.icon-shezhi:before { content: "\e6e8"; }
.icon-shuju:before { content: "\e779"; }
.icon-shuju1:before { content: "\e77d"; }
.icon-Group-:before { content: "\e68b"; }
.icon-tuichu:before { content: "\e658"; }
.icon-liulan:before { content: "\e73f"; }
.icon-xitongguanli-:before { content: "\e631"; }
.icon-yonghu:before { content: "\e649"; }
.icon-touxiang-kong:before { content: "\e660"; }
.icon-jiantou-xiangshang:before { content: "\e630"; }
.icon-shuju2:before { content: "\e620"; }
.icon-danxuanxuanzhong_o:before { content: "\eb60"; }
.icon-cuowu:before { content: "\e603"; }
.icon-nav-yunweishezhi:before { content: "\e614"; }
.icon-IP1:before { content: "\e615"; font-size: 40px;padding-left: 44px;}
.icon-liulan1:before { content: "\e617"; font-size: 40px;}
.icon-duliyonghu:before { content: "\e618";font-size: 40px;}
.icon-fangwencishu:before { content: "\e619";font-size: 20px;}
.icon-wodebaodan:before { content: "\e61a"; }
.icon-shousuo-:before { content: "\e61d"; }
.icon-neicun:before {content: "\e626";font-size: 30px;}
.icon-xuniji:before {content: "\e625";font-size: 30px;}
.icon-dui:before {content: "\e624"; font-size: 30px;}
.icon-server:before {content: "\e623";font-size: 30px;}
.icon-argu:before {content: "\e622";font-size: 30px;}
.icon-cpu:before {content: "\e621";font-size: 30px;}
.icon-cipan:before {content: "\e61f" ;font-size: 30px;}
.icon-huancunneirong:before { content: "\e627";font-size: 40px; }
.icon-jianmingliebiao:before { content: "\e629"; font-size: 40px;}
.icon-huancunliebiao:before { content: "\e62e"; font-size: 40px;}
.iconRow{
height: 300px;
overflow-y: auto;
overflow-x: hidden;
}
.iconCol{
text-align:center;
padding:20px 0;
color:#000;
}
.iconCol:hover{
background-color:#00a0e9;
cursor:pointer;
}
.icon-tongzhi:before { content: "\e6d6"; }
.icon-xiaoxi:before { content: "\e63b"; }
.icon-jiantou_yemian_xiangxia_o:before { content: "\eb95"; }
\ No newline at end of file \ No newline at end of file
import React from 'react'
import './index.less'
import { Input, Form, Button, Table, message, Radio} from 'antd'
import { UserManageBar } from '@components/Common'
import axios from '@src/axios/index'
import Utils from '@src/utils/utils'
import {API_SYSORORG_MANAGE } from '@src/Api'
const FormItem = Form.Item;
class LayerOrgSelect extends React.Component {
constructor(props) {
super(props)
this.state = {
orgVisible: this.props.orgVisible,
treeData: [{id: 1 ,childOrgs: [], name: 'a'},{id: 2 ,childOrgs: [], name: 'b'}],
treeLoad: false,
isExpand: false,
orgData: { // 树结构的选中的值
id: null,
name: ''
},
searchForm:{ //树结构的查询条件
orgId: null,
orgName: ''
},
}
}
componentDidMount() {
this.getOrgTreeList()
this.props.onRef(this)
}
//获取机构树状图
getOrgTreeList = (isLocal) => {
this.setState({
treeData:[],
treeLoad: true,
orgData: {name: isLocal === 'reset' || isLocal === 'search' ? '' : this.props.orgData.name }}, ()=> {
// if(isLocal !== 'search') {
// this.props.form.setFieldsValue({layerOrgName: this.state.orgData.name})
// }
var searchData = this.props.form.getFieldsValue()
if(isLocal !== 'search') {
searchData['layerOrgName'] = this.state.orgData.name
// this.props.form.setFieldsValue({layerOrgName: this.state.orgData.name})
}
axios.ajax({
url: API_SYSORORG_MANAGE.getOrgByName,
data:{
name: searchData.layerOrgName || '',
pageNum: 1,
pageSize: 999999
}
}).then(res => {
if (res && res.length > 0) {
this.setState({
treeData: res,
orgData: {id: this.state.searchForm.orgId},
isExpand: false,
treeLoad: false
})
} else {
this.setState({
treeData: [],
isExpand: false,
treeLoad: false
})
}
})
});
}
// 树搜索
searchOrgOpt = (e)=> {
this.setState({treeLoad:true, orgData:{id: this.state.searchForm.orgId}})
this.getOrgTreeList('search')
}
// 机构的重置搜索
orgReset = ()=> {
this.props.form.resetFields('layerOrgName');
this.setState({orgData:{id: this.state.searchForm.orgId}})
this.setState({treeData: []}, ()=> {
this.getOrgTreeList('reset')
})
}
onExpand = (expanded, record)=> {
let _this = this
let arr = [];
this.setState({treeLoad: true})
if (expanded) {
axios.ajax({
url: API_SYSORORG_MANAGE.getChildsOrgByCode,
data: {
code: record.code
}
}).then(res => {
if (res && res.length > 0) {
arr = _this.renderTree(this.state.treeData, record, res)
this.setState({treeData: arr, treeLoad: false})
} else {
this.setState({
treeLoad : false
})
return
}
})
} else {
arr = _this.renderTree(this.state.treeData, record, [])
this.setState({treeData: arr, treeLoad: false})
}
}
renderTree (data, record, res) {
let _this = this
data.forEach((item,index) => {
if(item.id === record.id){
item.childOrgs =res
}else{
if(item.childOrgs && item.childOrgs.length){
_this.renderTree(item.childOrgs, record, res)
}
}
})
return data
}
render () {
const { getFieldDecorator } = this.props.form;
const _this = this
const treeCol =[
{title: '机构名称',key: 'name',dataIndex: 'name',width: '300px',align: 'left',className: 'tdWidth', render(text, records,index) {
const obj = records
return <Radio ref={records.name} data-name={records.name} checked={_this.props.orgData.id == records.id} value={records.id}
onClick= {(e)=> _this.props.selectTree(e, obj)}>
{ Utils.formatTableColumn(records.name) }
</Radio>
}},
{title: '机构级别',key: 'orgGrade',dataIndex: 'orgGrade', width: '80px',align: 'center',className: 'tdWidth', render(orgGrade) {
return Utils.formatTableColumn(orgGrade)
}},
{title: '更新时间',key: 'updateTime',dataIndex: 'updateTime',width: '100px',align: 'center', render(name) {
return Utils.formateDateToYMD(name)
}},
{title: '备注',key: 'remark',dataIndex: 'remark',width: '180px',align: 'center',className: 'tdWidth', render(name) {
return Utils.formatTableColumn(name)
}}
];
return (
<div>
<Form layout="inline" name="orgForm">
<FormItem >
<label >机构名称</label>
{
getFieldDecorator('layerOrgName', {
})(
<Input placeholder="机构名称" />
)
}
</FormItem>
<FormItem style={{ marginTop: 38, }} >
<Button onClick={(item) => { this.searchOrgOpt(item) }} style={{ background: '#00BB29', color: "#fff", marginRight: 4 }} >查询</Button>
<Button onClick={this.orgReset} style={{ background: '#ED1719', color: "#fff" }} type="danger">重置</Button>
</FormItem>
</Form>
<UserManageBar title="详细数据" />
<div className="reTable exTable borderTable orgTable">
<Table
rowKey= 'id'
key={`table-${this.state.treeData && this.state.treeData.length}`}
bordered={false}
columns={treeCol}
defaultExpandAllRows = {this.state.isExpand}
loading={this.state.treeLoad}
dataSource={this.state.treeData}
childrenColumnName= 'childOrgs'
onExpand = {this.onExpand}
pagination={false}
scroll={{ y: 340 }}
/>
</div>
</div>
)
}
}
LayerOrgSelect = Form.create({})(LayerOrgSelect)
export default LayerOrgSelect
.orgTable {
.ant-radio-wrapper{
max-width: 110px;
overflow: hidden;
white-space: nowrap;
word-break: normal;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
}
th{
text-align: center !important;
background: none !important;
}
.ant-table-tbody{
td{
padding: 4px 6px !important;
border-bottom: none !important;
}
}
.ant-table-header{
background: none;
}
.ant-table-row-expand-icon{
height: 23px;
vertical-align: middle;
}
.tdWidth{
max-width: 100px;
overflow: hidden;
white-space: nowrap;
word-break: normal;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
}
}
\ No newline at end of file \ No newline at end of file
import React from 'react'
import UserManageBar from '@components/Common/WhiteBar/index'
import { Form, Button, Input, Tree, message, Radio } from 'antd'
import './index.less'
import Utils from '@src/utils/utils'
const FormItem = Form.Item;
const TreeNode = Tree.TreeNode
//创建所属菜单树
class MenuOptionsForm extends React.Component {
state = {}
componentDidMount () {
this.props.onRef(this);
}
//查询菜单列表
queryList = () => {
let data = this.props.form.getFieldsValue();
if(!data.moduleName || !data.moduleName.replace(/\s+/g,"")){
message.warn('请输入菜单名')
return
}
this.props.getMenuByName(data.moduleName.replace(/\s+/g,""))
this.setState({
checkedKeys: [],
checkedObj:[]
})
}
//重置
reset = () => {
this.props.getMenuTreeList()
this.props.form.resetFields()
this.setState({
checkedKeys: [],
checked:[]
})
}
//递归获取树形机构图
renderTreeNodes = (data) => {
const checkedObj = this.props.checkedObj
const parentCheckedObj = this.props.parentCheckedObj
return data.map(item => {
if (item.modules && item.modules.length > 0) {
return <TreeNode icon={<Radio ref={item.name} disabled={parentCheckedObj== item.name ? true:false} checked={checkedObj.key == item.id} value={item.id} />} title={<span>{Utils.formatTableColumn(item.name)}
<span className="orgGrade" >{item.creator} </span>
<span className="updateTime" >{Utils.formateDateToYMD(item.updateTime)}</span>
<span className="remark" >{Utils.formatTableColumn(item.remark)} </span>
</span>} key={item.id}
name={item.name}
>
{this.renderTreeNodes(item.modules)}
</TreeNode>
} else {
return <TreeNode icon={<Radio ref={item.name} disabled={parentCheckedObj== item.name ? true:false} checked={checkedObj.key == item.id} value={item.id} />} title={<span>{Utils.formatTableColumn(item.name)}
<span className="orgGrade" >{item.creator} </span>
<span className="updateTime" >{Utils.formateDateToYMD(item.updateTime)}</span>
<span className="remark" >{Utils.formatTableColumn(item.remark)}</span>
</span>} key={item.id}
name={item.name}
>
</TreeNode>
}
})
}
//操作选中某一项
onSelect = (checkedKeys, e) => {
//console.log(e.node.props.name)
const parentCheckedObj = this.props.parentCheckedObj
if(parentCheckedObj !== e.node.props.name){
if (checkedKeys && checkedKeys.length > 0) {
console.log(checkedKeys);
this.props.getCheckedObj({
key: checkedKeys[0],
val: e.node.props.name
})
}
}
}
//渲染弹窗页面
render() {
const { getFieldDecorator } = this.props.form;
const menuOptionsArr = this.props.menuOptionsArr
return (
<div>
<Form layout="inline" >
<FormItem >
<label >菜单名称</label>
{
getFieldDecorator('moduleName', {
})(
<Input placeholder="菜单名称" />
)
}
</FormItem>
<FormItem style={{ marginTop: 38, }} >
<Button onClick={(item) => { this.queryList(item) }} style={{ background: '#00BB29', color: "#fff", marginRight: 4 }} >查询</Button>
<Button onClick={this.reset} style={{ background: '#ED1719', color: "#fff" }} type="danger">重置</Button>
</FormItem>
</Form>
<UserManageBar title="菜单树形机构" />
<div className="treeTable" >
<div className="treeHeader">
<div className="flex-item">菜单名称</div>
<div className="flex-item">菜单级别</div>
<div className="flex-item">更新时间</div>
<div className="flex-item">备注</div>
</div>
{menuOptionsArr.length !==0 ?
<Tree
showIcon
defaultExpandAll
className="orgTree"
onSelect={(checkedKeys, e) => { this.onSelect(checkedKeys, e) }}
>
{this.renderTreeNodes(menuOptionsArr)}
</Tree>
: <div className="ant-table-placeholder">No data</div>
}
</div>
</div>
);
}
}
MenuOptionsForm = Form.create({})(MenuOptionsForm)
export default MenuOptionsForm
\ No newline at end of file \ No newline at end of file
.orgTree{
.tRow{
width:700px;
}
.remark{
width: 14%;
display:inline-block;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
}
import React from 'react'
import UserManageBar from '@components/Common/WhiteBar/index'
import { Form, Button, Input, Tree, message, Radio } from 'antd'
import Utils from '@src/utils/utils'
const FormItem = Form.Item;
const TreeNode = Tree.TreeNode
//创建所属机构树
class OrgOptionsForm extends React.Component {
state = {}
componentDidMount () {
this.props.onRef(this);
}
//查询角色列表
queryList = () => {
let data = this.props.form.getFieldsValue();
if(!data.orgName || !data.orgName.replace(/\s+/g,"")){
//
message.warn('请输入机构名')
return
}
this.props.getOrgByName(data.orgName.replace(/\s+/g,""))
this.setState({
checkedKeys: []
})
}
//重置
reset = () => {
this.props.getOrgTreeList()
this.props.form.resetFields()
this.setState({
checkedKeys: []
})
this.props.getCheckedObj({})
}
//递归获取树形机构图
renderTreeNodes = (data) => {
const checkedObj = this.props.checkedObj
const parentCode = this.props.parentCode
return data.map(item => {
if (item.childOrgs && item.childOrgs.length > 0) {
return <TreeNode icon={<Radio ref={item.name} disabled={parentCode== item.code ? true:false} checked={checkedObj.key == item.code} value={item.code} />} title={<span> { Utils.formatTableColumn(item.name) }
<span className="orgGrade" >{item.orgGrade} </span>
<span className="updateTime" >{Utils.formateDateToYMD(item.updateTime)}</span>
<span className="remark" >{ Utils.formatTableColumn(item.remark) } </span>
</span>} key={item.code}
name={item.name}
>
{this.renderTreeNodes(item.childOrgs)}
</TreeNode>
} else {
return <TreeNode icon={<Radio ref={item.name} disabled={parentCode== item.code ? true:false} checked={checkedObj.key == item.code} value={item.code} />} title={<span> { Utils.formatTableColumn(item.name) }
<span className="orgGrade" >{item.orgGrade} </span>
<span className="updateTime" >{Utils.formateDateToYMD(item.updateTime)}</span>
<span className="remark" >{ Utils.formatTableColumn(item.remark) }</span>
</span>} key={item.code}
name={item.name}
>
</TreeNode>
}
})
}
onSelect = (checkedKeys, e) => {
const parentCode = this.props.parentCode
//console.log(e.node.props.name)
//console.log(checkedKeys);
if(parentCode !== checkedKeys[0]){
if (checkedKeys && checkedKeys.length > 0) {
this.props.getCheckedObj(
{
key: checkedKeys[0],
val: e.node.props.name
}
)
}
}
}
render() {
const { getFieldDecorator } = this.props.form;
const orgOptionsArr = this.props.orgOptionsArr
return (
<div>
<Form layout="inline" >
<FormItem >
<label >机构名称</label>
{
getFieldDecorator('orgName', {
})(
<Input placeholder="机构名称" />
)
}
</FormItem>
<FormItem style={{ marginTop: 38, }} >
<Button onClick={(item) => { this.queryList(item) }} style={{ background: '#00BB29', color: "#fff", marginRight: 4 }} >查询</Button>
<Button onClick={this.reset} style={{ background: '#ED1719', color: "#fff" }} type="danger">重置</Button>
</FormItem>
</Form>
<UserManageBar title="详细数据" />
<div className="treeTable" >
<div className="treeHeader">
<div className="flex-item">机构名称</div>
<div className="flex-item">机构级别</div>
<div className="flex-item">更新时间</div>
<div className="flex-item">备注</div>
</div>
{orgOptionsArr.length !==0 ?
<Tree
// checkable
showIcon
// defaultExpandAll
className="orgTree"
onSelect={(checkedKeys, e) => { this.onSelect(checkedKeys, e) }}
>
{this.renderTreeNodes(orgOptionsArr)}
</Tree>
: <div className="ant-table-placeholder">No data</div>
}
</div>
</div>
);
}
}
OrgOptionsForm = Form.create({})(OrgOptionsForm)
export default OrgOptionsForm
\ No newline at end of file \ No newline at end of file
import React from 'react'
import UserManageBar from '@components/Common/WhiteBar/index'
import { Form, Button, Input,Tree, message, Radio} from 'antd'
import Utils from '@src/utils/utils'
const FormItem = Form.Item;
const TreeNode = Tree.TreeNode
//创建所属机构树
class OrgOptionsForm extends React.Component {
state = {}
componentDidMount() {
if (this.props.onRef) {
this.props.onRef(this);
}
this.props.getOrgByName()
this.reset()
}
//查询角色列表
queryList = () => {
let data = this.props.form.getFieldsValue();
if (!data.orgName || !data.orgName.replace(/\s+/g, "")) {
message.warn('请输入机构名')
return
}
this.props.getOrgByName(data.orgName.replace(/\s+/g, ""))
this.setState({
checkedKeys: []
})
}
//重置
reset = () => {
this.props.getOrgTreeList()
this.props.form.resetFields()
this.setState({
checkedKeys: []
})
this.props.getCheckedObj({})
}
//递归获取树形机构图
renderTreeNodes = (data) => {
const checkedObj = this.props.checkedObj
return data.map(item => {
const isLeaf = !(item.childOrgs && item.childOrgs.length > 0)
if (item.childOrgs && item.childOrgs.length > 0) {
return <TreeNode dataRef={item} isLeaf={ isLeaf }
icon={<Radio ref={item.name}
checked={checkedObj? checkedObj.key ==item.id:this.state.checkedKeys == item.id} value={item.id} />}
title={<span className='title' >
{Utils.formatTableColumn(item.name)}
<span className="orgGrade" >{item.orgGrade} </span>
<span className="updateTime" >{Utils.formateDateToYMD(item.updateTime)}</span>
<span className="remark" >{ Utils.formatTableColumn(item.remark) }</span>
</span>} key={item.id}
name={item.name}
>
{this.renderTreeNodes(item.childOrgs)}
</TreeNode>
} else {
return <TreeNode dataRef={item} isLeaf={ isLeaf } icon={<Radio ref={item.name} checked={checkedObj? checkedObj.key ==item.id:this.state.checkedKeys == item.id} value={item.id} />} title={<span > {Utils.formatTableColumn(item.name)}
<span className="orgGrade" >{item.orgGrade} </span>
<span className="updateTime" >{Utils.formateDateToYMD(item.updateTime)}</span>
<span className="remark" >{ Utils.formatTableColumn(item.remark) }</span>
</span>} key={item.id}
name={item.name}
>
</TreeNode>
}
})
}
onCheck = (checkedKeys) => {
// this.props.patchMenuInfo(checkedKeys)
console.log(checkedKeys)
}
onSelect = (checkedKeys, e) => {
console.log(e.node.props.name)
console.log(checkedKeys);
this.setState({
checkedKeys,
checked: {
key: checkedKeys[0],
val: e.node.props.name
}
})
// console.log('子组件',this.state.checked);
if (checkedKeys && checkedKeys.length > 0) {
this.props.getCheckedObj(
{
key: checkedKeys[0],
val: e.node.props.name
}
)
} else {
this.props.getCheckedObj(
{
}
)
}
}
render() {
const { getFieldDecorator } = this.props.form;
const orgOptionsArr = this.props.orgOptionsArr
return (
<div>
<Form layout="inline" >
<FormItem >
<label >机构名称</label>
{
getFieldDecorator('orgName', {
// initialValue: '雨轩',
})(
<Input placeholder="机构名称" />
)
}
</FormItem>
<FormItem style={{ marginTop: 38, }} >
<Button onClick={(item) => { this.queryList(item) }} style={{ background: '#00BB29', color: "#fff", marginRight: 4 }} >查询</Button>
<Button onClick={this.reset} style={{ background: '#ED1719', color: "#fff" }} type="danger">重置</Button>
</FormItem>
</Form>
<UserManageBar title="详细数据" />
<div className="treeTable" >
<div className="treeHeader">
<div className="flex-item">机构名称</div>
<div className="flex-item">机构级别</div>
<div className="flex-item">更新时间</div>
<div className="flex-item">备注</div>
</div>
{orgOptionsArr.length !==0 ?
<Tree
// checkable
showIcon
// defaultExpandAll
// loadData={this.props.onLoadData}
className="orgTree"
onSelect={(checkedKeys, e) => { this.onSelect(checkedKeys, e) }}
>
{this.renderTreeNodes(orgOptionsArr)}
</Tree>
: <div className="ant-table-placeholder">No data</div>
}
</div>
</div>
);
}
}
OrgOptionsForm = Form.create({})(OrgOptionsForm)
export default OrgOptionsForm
\ No newline at end of file \ No newline at end of file
import React from 'react'
export default (title) => (WrappedComponent) => class HOC extends React.Component {
render() {
const newProps = {
test: 'hoc'
}
return <div>
<div className="demo-header">
{title
? title
: '我是标题'}
</div>
<WrappedComponent {...this.props} {...newProps} />
</div>
}
}
\ No newline at end of file \ No newline at end of file
import React from 'react'
import UserManageBar from '@components/Common/WhiteBar/index'
import { Form, Button, Input, Tree, message, } from 'antd'
import Utils from '@src/utils/utils'
const FormItem = Form.Item;
const TreeNode = Tree.TreeNode
//创建所属机构树
class OrgOptionsForm extends React.Component {
state = {
checkedKeys: ['1', '2', '21'],
checked: {
}
}
componentDidMount() {
//获取默认数据
const { checkedKeys } = this.props
this.setState({ checkedKeys })
console.log(checkedKeys)
}
componentWillReceiveProps(nextProps) {
}
//查询角色列表
queryList = () => {
let data = this.props.form.getFieldsValue();
if (!data.name || !data.name.replace(/\s+/g, "")) {
message.warn('请输入角色名')
return
}
this.props.getRoleParam(data.name.replace(/\s+/g, ""))
this.setState({
checkedKeys: []
})
}
//重置
reset = () => {
this.props.getRoleInfo()
this.props.form.resetFields()
this.setState({
checkedKeys: []
})
this.props.getCheckedObj({})
this.props.getRoleObj({})
}
//递归获取树形机构图
renderTreeNodes = (data) => {
return data.map(item => {
if (item.roles && item.roles.length > 0) {
return <TreeNode title={<span> {Utils.formatTableColumn(item.name)}
</span>} key={item.id}
name={item.name}
>
{this.renderTreeNodes(item.roles)}
</TreeNode>
} else {
return <TreeNode title={<span> {Utils.formatTableColumn(item.name)}
</span>} key={item.id}
name={item.name}
>
</TreeNode>
}
})
}
onCheck = (checkedKeys, e) => {
let checkedobj = []
if (e.checkedNodes && e.checkedNodes.length > 0) {
checkedobj = e.checkedNodes.map(item => {
return Object.assign({}, {
key: item.key,
value: item.props.name
})
})
}
this.setState({ checkedKeys, checkedobj });
if (e.checkedNodes && e.checkedNodes.length >= 0) {
this.props.getRoleObj(checkedobj, checkedKeys.checked)
}
}
onSelect = (checkedKeys, e) => {
// this.setState({
// checkedKeys,
// checked: {
// key: checkedKeys[0],
// val: e.node.props.name
// }
// })
// // console.log('子组件',this.state.checked);
// if (checkedKeys && checkedKeys.length > 0) {
// this.props.getCheckedObj(
// {
// key: checkedKeys[0],
// val: e.node.props.name
// }
// )
// } else {
// this.props.getCheckedObj(
// {
// }
// )
// }
}
render() {
const { getFieldDecorator } = this.props.form;
const roleOptionsArr = this.props.roleOptionsArr || []
return (
<div>
<Form layout="inline" >
<FormItem >
<label >角色名称</label>
{
getFieldDecorator('name', {
})(
<Input placeholder="角色名称" />
)
}
</FormItem>
<FormItem style={{ marginTop: 38, }} >
<Button onClick={(item) => { this.queryList(item) }} style={{ background: '#00BB29', color: "#fff", marginRight: 4 }} >查询</Button>
<Button onClick={this.reset} style={{ background: '#ED1719', color: "#fff" }} type="danger">重置</Button>
</FormItem>
</Form>
<UserManageBar title="详细数据" />
<div className="treeTable" >
{roleOptionsArr.length !== 0 ?
<Tree
checkable
checkStrictly
//defaultExpandAll
className="orgTree"
checkedKeys={this.state.checkedKeys}
onCheck={(checkedKeys, e) => {
this.onCheck(checkedKeys, e)
}}
onSelect={(checkedKeys, e) => { this.onSelect(checkedKeys, e) }}
>
{this.renderTreeNodes(roleOptionsArr)}
</Tree>
: <div className="ant-table-placeholder">No data</div>
}
</div>
</div>
);
}
}
OrgOptionsForm = Form.create({})(OrgOptionsForm)
export default OrgOptionsForm
\ No newline at end of file \ No newline at end of file
import React from 'react'
import UserManageBar from '@components/Common/WhiteBar/index'
import { Form, Button, Input, Tree, message, Radio, } from 'antd'
import Utils from '@src/utils/utils'
const FormItem = Form.Item;
const TreeNode = Tree.TreeNode
//创建所属机构树
class OrgOptionsForm extends React.Component {
state = {}
//查询角色列表
queryList = () => {
let data = this.props.form.getFieldsValue();
if (!data.name || !data.name.replace(/\s+/g, "")) {
message.warn('请输入角色名')
return
}
this.props.getRoleParam(data.name.replace(/\s+/g, ""))
this.setState({
checkedKeys: []
})
}
componentWillMount(){
this.reset()
const { setRadioId } = this.props
console.log(setRadioId)
this.setState({
checkedKeys:setRadioId ? [setRadioId.key] : ''
})
}
//重置
reset = () => {
this.props.getRoleInfo()
this.props.form.resetFields()
this.setState({
checkedKeys: []
})
this.props.getRoleObj({})
}
//递归获取树形机构图
renderTreeNodes = (data) => {
const selfObj = this.props.selfObj
const { setRadioId } = this.props
console.log('selfObj',selfObj)
return data.map((item,index ) => {
if (item.roles && item.roles.length > 0) {
return <TreeNode
icon={<Radio ref={item.name} disabled={selfObj ? (selfObj.key== item.id ? true:false) :false}
checked={setRadioId.key == item.id} value={item.id} />}
title={<span> {Utils.formatTableColumn(item.name)}</span>}
key={item.id}
name={item.name}
>
{selfObj? selfObj.key== item.id ? delete item.roles: this.renderTreeNodes(item.roles):this.renderTreeNodes(item.roles)}
</TreeNode>
} else {
return <TreeNode icon={<Radio ref={item.name} disabled={selfObj ? (selfObj.key== item.id ? true:false) :false} checked={setRadioId.key== item.id} value={item.id} />} title={<span> {Utils.formatTableColumn(item.name)}
</span>} key={item.id}
name={item.name}
>
</TreeNode>
}
})
}
onCheck = (checkedKeys) => {
// this.props.patchMenuInfo(checkedKeys)
}
onSelect = (checkedKeys, e) => {
// console.log(e.node.props.name)
// console.log(checkedKeys.includes('top'));
if (checkedKeys.includes('top') || checkedKeys.length === 0) return
this.setState({
checkedKeys,
checked: {
key: checkedKeys[0],
val: e.node.props.name
}
})
// console.log('子组件',this.state.checked);
const selfObj = this.props.selfObj
if(selfObj){
if( selfObj.key !== checkedKeys[0]){
if (checkedKeys && checkedKeys.length > 0) {
this.props.getRoleObj(
{
key: checkedKeys[0],
val: e.node.props.name
}
)
}
}
}else{
if (checkedKeys && checkedKeys.length > 0) {
this.props.getRoleObj(
{
key: checkedKeys[0],
val: e.node.props.name
}
)
}
}
}
render() {
const { getFieldDecorator } = this.props.form;
const roleOptionsArr = this.props.roleOptionsArr || []
return (
<div>
<Form layout="inline" >
<FormItem >
<label >角色名称</label>
{
getFieldDecorator('name', {
// initialValue: '雨轩',
})(
<Input placeholder="角色名称" />
)
}
</FormItem>
<FormItem style={{ marginTop: 38, }} >
<Button onClick={(item) => { this.queryList(item) }} style={{ background: '#00BB29', color: "#fff", marginRight: 4 }} >查询</Button>
<Button onClick={this.reset} style={{ background: '#ED1719', color: "#fff" }} type="danger">重置</Button>
</FormItem>
</Form>
<UserManageBar title="详细数据" />
<div className="treeTable" >
{roleOptionsArr.length !== 0 ?
<Tree
// checkable
showIcon
//defaultExpandAll
className="orgTree"
onSelect={(checkedKeys, e) => { this.onSelect(checkedKeys, e) }}
>
{this.renderTreeNodes(roleOptionsArr)}
</Tree>
: <div className="ant-table-placeholder">No data</div>
}
</div>
</div>
);
}
}
OrgOptionsForm = Form.create({})(OrgOptionsForm)
export default OrgOptionsForm
\ No newline at end of file \ No newline at end of file
import React from 'react'
import {Card} from 'antd'
import './index.less'
const {Meta} = Card
export default class whiteBar extends React.Component {
render() {
return (
<div className="cont">
<Card className="title">
<Meta className="meta"
title={<div style={{width: 5, backgroundColor: '#5668db', marginLeft: 18}}><span
style={{marginLeft: 20}}>{this.props.title}</span></div>}>
</Meta>
</Card>
</div>
)
}
}
\ No newline at end of file \ No newline at end of file
.cont {
margin:10px 0;
overflow: hidden;
.title{
margin-left: -24px;
height: 48px;
}
.meta{
margin-top: -14px;
}
}
\ No newline at end of file \ No newline at end of file
import OrgOptionsForm from './OrgOptions/index'
import MutilOrgOptionsForm from './OrgOptions/codeIndex'
import UserManageBar from './WhiteBar'
import RoleOptionsForm from './RoleOptions/mutilOptions'
import MutilOptions from './RoleOptions'
import WithHeader from './PermBtn'
import MenuOptionsForm from './MenuOptions/index.js'
import IconOptionsForm from './IconOptions/index.js'
import LayerOrgSelect from './LayerOrgSelect/index.js'
export {
OrgOptionsForm,
UserManageBar,
RoleOptionsForm,
MutilOptions,
WithHeader,
MenuOptionsForm,
IconOptionsForm,
LayerOrgSelect,
MutilOrgOptionsForm
}
import React from 'react'
import {Row ,Card, Col ,Tabs ,Table, notification, Modal } from 'antd'
import './index.less'
import ReactEcharts from 'echarts-for-react';
import WhiteBar from '../Common/WhiteBar/index'
import arrow from '@images/arrow.svg'
// import echartTheme from '../../config/echartTheme'
// import echarts from 'echarts'
// 引入饼图和折线图
import 'echarts/lib/chart/line'
// 引入提示框和标题组件
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/legend';
import 'echarts/lib/component/markPoint';
const TabPane = Tabs.TabPane;
const gridStyle = {
textAlign: 'center',
height:115,
minWidth:200,
marginLeft:10
};
function tableChange(key) {
console.log(key);
}
export default class Contnet extends React.Component{
state={
}
componentDidMount(){
const data = [
{
time:'0',
views:66,
users:'78',
visits:'99',
ip:'24',
outRate:'22.2%',
onlineAvgTime:'00:00:22',
},
{
time:'0',
views:66,
users:'78',
visits:'99',
ip:'24',
outRate:'22.2%',
onlineAvgTime:'00:00:22',
},
{
time:'0',
views:66,
users:'78',
visits:'99',
ip:'24',
outRate:'22.2%',
onlineAvgTime:'00:00:22',
},
]
data.map((item,index)=>{
item.key = index;
})
this.setState({
dataSource: data
})
}
getOption = ()=>{
let option = {
title: {
// text: '用户骑行订单'
},
tooltip: {
trigger: 'axis'
},
legend: {
data:['今天','昨天','7天前','30天前']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
data: [
'周一',
'周二',
'周三',
'周四',
'周五',
'周六',
'周日'
]
},
yAxis: {
type: 'value'
},
series: [
{
name: '今天',
type: 'line',
data: [
1000,
2000,
1500,
3000,
2000,
1200,
800
]
},
{
name: '昨天',
type: 'line',
data: [
100,
2500,
1600,
200,
4500,
200,
3500
]
},
{
name: '7天前',
type: 'line',
data: [
1100,
500,
1230,
1250,
2560,
329,
495
]
},
{
name: '30天前',
type: 'line',
data: [
100,
380,
4890,
1985,
952,
2581,
487
]
},
]
}
return option;
}
onRowClick = (record,index)=>{
let selectKey = [index];
// Modal.info({
// title:"信息",
// content:`用户名:${record.userName}, 用户爱好:${record.interest}`
// })
this.setState({
selectedRowKeys:selectKey,
selectedItem:record
})
}
render(){
const columns = [
{
title:'时间',
key:'time',
dataIndex:'time'
},
{
title: '浏览量(PV)',
key: 'views',
dataIndex: 'views'
},
{
title: '独立用户(UV)',
key: 'users',
dataIndex: 'users',
// render(sex){
// return sex ==1 ?'男':'女'
// }
},
{
title: '访问次数(W)',
key: 'visits',
dataIndex: 'visits',
// render(state){
// let config = {
// '1':'咸鱼一条',
// '2':'风华浪子',
// '3':'北大才子',
// '4':'百度FE',
// '5':'创业者'
// }
// return config[state];
// }
},
{
title: '独立IP',
key: 'ip',
dataIndex:'ip'
},
{
title: '跳出率',
key: 'outRate',
dataIndex: 'outRate'
},
{
title: '平均在线时长',
key: 'onlineAvgTime',
dataIndex: 'onlineAvgTime'
},
]
return (
<div className="bg">
<Row>
<div className="realTime">
<img src={require('../../resource/assets/images/realTime.svg')} alt=''/>
<span>实时数据 12:00:00</span>
</div>
<div className="kpi">
<WhiteBar title="关键指标" />
</div>
<div className='panel' style={{padding:'10px 20px'}} >
<Row gutter={15}>
<Col span={6}>
<Card style={gridStyle} bordered={false}>
<div className='pv'>浏览量(PV</div>
<div className='desBox'>
<img className='img' src={require('../../resource/assets/images/liulan.jpg')} alt=""/>
<div className='des'>
<div className="number">253</div>
<div className='number2'>112.61%
<img className='nimg' src={arrow} alt=""/>
</div>
</div>
</div>
</Card>
</Col>
<Col span={6}>
<Card style={gridStyle} bordered={false}>
<div className='pv'>独立用户(UV</div>
<div className='desBox'>
<img className='img' src={require('../../resource/assets/images/user.jpg')} alt=""/>
<div className='des'>
<div className="number">253</div>
<div className='number2'>112.61%
<img className='nimg' src={arrow} alt=""/>
</div>
</div>
</div>
</Card>
</Col>
<Col span={6}>
<Card style={gridStyle} bordered={false}>
<div className='pv'>访问次数(W</div>
<div className='desBox'>
<img className='img' src={require('../../resource/assets/images/times.jpg')} alt=""/>
<div className='des'>
<div className="number">253</div>
<div className='number2'>112.61%
<img className='nimg' src={arrow} alt=""/>
</div>
</div>
</div>
</Card>
</Col>
<Col span={6}>
<Card style={gridStyle} bordered={false}>
<div className='pv'>独立IP</div>
<div className='desBox'>
<img className='img' src={require('../../resource/assets/images/ip.jpg')} alt=""/>
<div className='des'>
<div className="number">253</div>
<div className='number2'>112.61%
<img className='nimg' src={arrow} alt=""/>
</div>
</div>
</div>
</Card>
</Col>
</Row>
</div>
<div className='tabs' >
<Tabs className='tab' defaultActiveKey="1" onChange={tableChange}>
<TabPane tab="小时指标" key="1" >
<WhiteBar title="走势图" />
<div style={{padding:'10px 20px 10px 30px'}}>
<Card style={{padding:-20}} >
<ReactEcharts option = {this.getOption()} />
</Card>
</div>
</TabPane>
{/* <TabPane tab="浏览量" key="2" style={{height:48}}>
<WhiteBar title="详细数据" />
</TabPane>
<TabPane tab="独立用户(UV)" key="3">Content of Tab Pane 3</TabPane>
<TabPane tab="访问次数(W)" key="4">Content of Tab Pane 3</TabPane>
<TabPane tab="独立IP" key="5">Content of Tab Pane 3</TabPane>
<TabPane tab="跳出率" key="6">Content of Tab Pane 3</TabPane>
<TabPane tab="平均在线时长" key="7">Content of Tab Pane 3</TabPane> */}
</Tabs>
</div>
<div className="detailData">
<WhiteBar title="详细数据" />
<div style={{backgroundColor:'#fff',margin:'10px 20px 10px 30px'}}>
<Table
columns={columns}
// rowSelection ={rowCheckSelection}
// onRow = {(record,index)=>{
// return {
// onClick:()=>{
// this.onRowClick(record,index)
// }
// }
// }}
dataSource={this.state.dataSource}
pagination={false}
/>
</div>
</div>
</Row>
</div>
)
}
}
.bg{
background: #e6eaf0;
// height: calc(100vh);
overflow: hidden;
.realTime{
display: flex;
align-items: center;
height: 50px;
font-weight: 600;
}
.realTime img{
width:20px;
height: 20px;
margin-left: 26px;
margin-right: 10px;
}
.kpi {
overflow: hidden;
.title{
margin-left: -24px;
height: 48px;
}
.meta{
margin-top: -14px;
}
}
.panel{
min-width: 200px;
.desBox{
display: flex;
align-items: center;
justify-content: left;
min-width: 200px;
margin-left: 50px;
.number{
text-align: left;
font-weight: 700;
font-size: 18px;
}
.number2{
color:#97a4b6;
margin-top:-2px;
}
}
.pv{
text-align: left;
margin-left: 50px;
margin-top:-10px;
margin-bottom: 15px;
}
.img{
}
.des{
// float: left;
margin-left: 15px;
.nimg{
width:14px;
float: right;
margin-top:2px;
margin-left: 5px;
}
}
}
.tabs{
height: 500px;
.tab{
.ant-tabs-nav{
margin-left: 28px;
}
}
}
.detailData{
height: 400px;
overflow: hidden;
.title{
margin-left: -24px;
height: 48px;
}
.meta{
margin-top: -14px;
}
}
}
.ant-notification{
width: 245px;
}
.msgTip{
background: #5669DA;
color: #fff;
.ant-notification-notice-message{
color:#fff;
width: 100%;
border-bottom:1px dashed #fff;
}
.ant-notification-notice-description{
font-size: 12px;
.msgContent{
}
.msgLink{
text-align: right;
}
a{
color:#5FA8EB;
}
}
.ant-notification-notice-close-x{
color:#fff;
}
.ant-notification-notice-close{
right: 5px;
top: 2px;
}
}
\ No newline at end of file \ No newline at end of file
import React from 'react'
import {Table} from 'antd'
import "./index.less"
export default class ETable extends React.Component {
state = {}
//处理行点击事件
onRowClick = (record, index) => {
let rowSelection = this.props.rowSelection;
if(rowSelection == 'checkbox'){
let selectedRowKeys = this.props.selectedRowKeys;
let selectedIds = this.props.selectedIds;
let selectedItem = this.props.selectedItem || [];
if (selectedIds) {
const i = selectedIds.indexOf(record.id);
if (i == -1) {//避免重复添加
selectedIds.push(record.id)
selectedRowKeys.push(index);
selectedItem.push(record);
}else{
selectedIds.splice(i,1);
selectedRowKeys.splice(i,1);
selectedItem.splice(i,1);
}
} else {
selectedIds = [record.id];
selectedRowKeys = [index]
selectedItem = [record];
}
this.props.updateSelectedItem(selectedRowKeys,selectedItem || {},selectedIds);
}else{
let selectKey = [index];
const selectedRowKeys = this.props.selectedRowKeys;
if (selectedRowKeys && selectedRowKeys[0] == index){
return;
}
this.props.updateSelectedItem(selectKey,record || {});
}
};
// 选择框变更
onSelectChange = (selectedRowKeys, selectedRows) => {
let rowSelection = this.props.rowSelection;
console.log(rowSelection);
const selectedIds = [];
if(rowSelection == 'checkbox'){
selectedRows.map((item)=>{
selectedIds.push(item.id);
});
this.setState({
selectedRowKeys,
selectedIds:selectedIds,
selectedItem: selectedRows[0]
});
}
this.props.updateSelectedItem(selectedRowKeys,selectedRows[0],selectedIds);
};
onSelectAll = (selected, selectedRows, changeRows) => {
let selectedIds = [];
let selectKey = [];
selectedRows.forEach((item,i)=> {
selectedIds.push(item.id);
selectKey.push(i);
});
this.props.updateSelectedItem(selectKey,selectedRows[0] || {},selectedIds);
}
getOptions = () => {
let p = this.props;
const name_list = {
"订单编号":170,
"车辆编号":80,
"手机号码":96,
"用户姓名":70,
"密码":70,
"运维区域":300,
"车型":42,
"故障编号":76,
"代理商编码":97,
"角色ID":64
};
if (p.columns && p.columns.length > 0) {
p.columns.forEach((item)=> {
//开始/结束 时间
if(!item.title){
return
}
if(!item.width){
if(item.title.indexOf("时间") > -1 && item.title.indexOf("持续时间") < 0){
item.width = 132
}else if(item.title.indexOf("图片") > -1){
item.width = 86
}else if(item.title.indexOf("权限") > -1 || item.title.indexOf("负责城市") > -1){
item.width = '40%';
item.className = "text-left";
}else{
if(name_list[item.title]){
item.width = name_list[item.title];
}
}
}
item.bordered = true;
});
}
const { selectedRowKeys } = this.props;
const rowSelection = {
type: 'radio',
selectedRowKeys,
onChange: this.onSelectChange,
onSelect:(record, selected, selectedRows)=>{
console.log('...')
},
onSelectAll:this.onSelectAll
};
let row_selection = this.props.rowSelection;
// 当属性未false或者null时,说明没有单选或者复选列
if(row_selection===false || row_selection === null){
row_selection = false;
}else if(row_selection == 'checkbox'){
//设置类型未复选框
rowSelection.type = 'checkbox';
}else{
//默认未单选
row_selection = 'radio';
}
return <Table
className="card-wrap page-table"
bordered
{...this.props}
rowSelection={row_selection?rowSelection:null}
onRow={(record,index) => ({
onClick: ()=>{
if(!row_selection){
return;
}
this.onRowClick(record,index)
}
})}
/>
};
render = () => {
return (
<div>
{this.getOptions()}
</div>
)
}
}
\ No newline at end of file \ No newline at end of file
@import '../../style/default';
.ant-table{
&-thead > tr > th,
&-tbody > tr > td{
padding:14px 6px;
text-align:center;
}
.ant-table-selection-column{
min-width:42px!important;
width:42px!important;;
}
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
&.ant-table-middle{
&-thead > tr > th,
&-tbody > tr > td{
padding:10px 6px;
}
}
&.ant-table-small{
&-thead > tr > th,
&-tbody > tr > td{
padding:8px 6px;
}
}
}
.ant-table-pagination{
padding:0 20px;
}
\ No newline at end of file \ No newline at end of file
import React from 'react'
export default class Footer extends React.Component{
render(){
return (
<div>这是Footer</div>
)
}
}
\ No newline at end of file \ No newline at end of file
.banner{
overflow: hidden;
// position: relative;
max-height: 150px;
height: 80px;
>img{
width:100vw;
height: 400px;
// transform: translate(-20%,-40%);
position: relative;
top:50%;
margin-top:-200px;
}
.title{
position: absolute;
top:21px;
left:30px;
letter-spacing: 2px;
font-weight: 600;
color:#7687e2;
}
.login{
position: absolute;
top:0;
right:300px ;
width:150px;
height: 80px;
background-color: rgba(73,162,201,0.8);
.userName{
width:60%;
overflow: hidden;
text-align: center;
display: inline-block;
text-overflow: ellipsis;
white-space: nowrap;
word-break: normal;
height: 20px;
}
}
.message{
position: absolute;
top:0;
right:150px ;
width:150px;
height: 80px;
background-color: rgba(0,187,41,0.38);
.msgTipCircle{
width:28px;
height:28px;
display: block;
margin:0 auto;
margin-bottom: 2px;
.circle{
width:5px;
height:5px;
background-color:#ED1719;
border-radius: 50%;
display: inline-block;
position: absolute;
}
}
.userName{
width:60%;
overflow: hidden;
text-align: center;
display: inline-block;
text-overflow: ellipsis;
a{
color:#fff;
}
}
}
.logout{
position: absolute;
top:0;
right:0 ;
width:150px;
height: 80px;
background-color: rgba(102,115,192,0.8);
.userName{
width:60%;
overflow: hidden;
text-align: center;
display: inline-block;
text-overflow: ellipsis;
}
#setting{
position: absolute;
top:0;
bottom: 0;
right: 0;
left: 0;
width: 100%;
height: 100%;
}
}
.login_pic{
width:28px;
height: 28px;
display: inline-block;
background: url(/public/assets/images/login.svg) no-repeat;
}
.login,.logout,.message{
display: flex;
justify-content:center;
align-items:center;
flex-direction:column;
color:#fff;
}
.login img ,.logout img,.message img{
width:28px;
height:28px;
display: block;
margin:0 auto;
margin-bottom: 2px;
}
.logout:hover ,.login:hover,.message:hover{
cursor: pointer;
}
.setting{
display: flex;
align-items: center;
justify-content: center;
height: 70px;
width:152px;
background-color: #fff;
position: absolute;
right: 1px;
bottom: -65px;
border-radius: 3px;
font-size: 14px;
z-index: 1000;
border:1px solid #ddd;
cursor: pointer;
.lock{
border-bottom: 1px solid #ddd;
}
.updPwd i{margin-right: 5px;}
div{
display: block;
padding-left: 20px;
line-height: 35px;
text-align: left;
transition: all .5s;
&:hover{
background-color: #ddd;
}
i{
margin-right: 10px;
font-size: 16px;
}
}
}
}
.errInfo{
color: red;
}
import React from 'react'
import MenuConfig from './../../config/menuConfig'
import './index.less'
import { Menu, Icon, message, notification, Modal } from 'antd';
import { NavLink } from 'react-router-dom'
import axios from '@src/axios/index'
import Storage from '@src/utils/localStorage'
import { API_ROLE_MANAGE, API_MENU_MANAGE, API_SYS_MONITOR , API_SYS_MSG} from '@src/Api'
import storage from '@src/utils/localStorage'
import SYS_CONFIG from '@src/config/constant.js'
import Utils from '@src/utils/utils';
const SubMenu = Menu.SubMenu;
// const MenuItemGroup = Menu.ItemGroup;
export default class NavLeft extends React.Component {
state = {
currentKey: [],
openMenuRouter: ['/home'],
allMenuList: [], //所有菜单
userRoleInfo: {}, //角色信息
userMenuList: [], //根据用户角色信息创建菜单
}
changeRouter = (item) => {
this.setState({
currentKey: item.key
})
}
onOpenChange = (item) => {
this.setState({
openMenuRouter: item
})
}
componentWillMount() {
// const menuTreeNode = this.renderMenu(MenuConfig);
let currentKey = window.location.hash.replace(/#|\?.*$/g, "")
// let onPenkeys = window.location.hash.replace(/(#|\?.*\/)(.*\/*)([^\/]+\/[^\/]+)$/g,'$1$2')
// this.onOpenChange([onPenkeys])
this.setState({
currentKey,
// menuTreeNode
})
}
async componentDidMount() {
//获取所有菜单
await this.getModuleTreeList()
//获取用户菜单
await this.getRoleJurisdiction()
//是否登录
//现在的url地址
// this.props.history.push('/login')
}
//获取所有菜单
getModuleTreeList = () => {
return new Promise((resolve, reject) => {
axios.ajax({
url: API_MENU_MANAGE.getModuleTreeList,
data: {
pageSize: 1,
pageNum: 1000
}
}).then(res => {
//对菜单数据进行处理
const allMenuList = this.formatMenulist(res)
resolve(this.setState({ allMenuList }))
})
})
}
//对菜单数据进行处理,treeNode类型
formatMenulist = (data) => {
if (!data || data.length === 0) {
return []
}
if (data && data.length) {
return data.map(item => {
if (item.modules && item.modules.length > 0) {
return Object.assign({
title: item.name,
sequence: item.sequence,
parentId: item.parentId,
icon: item.menuIcon,
key: item.link,
status: item.status,
id: item.id,
menuType: item.menuType,
code: item.code || '',
children: this.formatMenulist(item.modules)
})
}
return Object.assign({}, {
title: item.name,
sequence: item.sequence,
parentId: item.parentId,
icon: item.menuIcon,
key: item.link,
status: item.status,
id: item.id,
code: item.code || '',
menuType: item.menuType,
children: item.modules
})
});
}
}
//获取登录权限
getRoleJurisdiction = () => {
const userInfo = Storage.get('userInfo')
if (!userInfo || !userInfo.id) {
return
}
axios.ajax({
url: API_ROLE_MANAGE.getRoleJurisdiction,
data: {
userId: userInfo.id
}
}).then(res => {
//将数据处理成标准菜单格式
if (res && res.length) {
const userRoleInfo = res.map(item => {
return {
title: item.name,
status: item.status,
key: item.link,
parentId: item.parentId,
icon: item.menuIcon,
sequence: item.sequence,
menuType: item.menuType,
id: item.id
}
})
this.setState({ userRoleInfo }, () => {
this.createMenu(res)
})
}
})
}
//给要显示的菜单添加isShow
addIsShowFlag = (id, data) => {
const { allMenuList } = this.state
let _this = this
data.forEach((k, i) => {
if (k.id === id) {
k.isShow = true
if (k.parentId !== 0) {
_this.addIsShowFlag(k.parentId, allMenuList)
}
} else {
if (k.children && k.children.length) {
_this.addIsShowFlag(id, k.children)
}
}
})
return data
}
//生成用户菜单
createMenu = (data) => {
let _this = this
//生成用户菜单
const { allMenuList, userRoleInfo } = this.state
let menuTreeNode = [];
//遍历userRoleInfo生成菜单
if (userRoleInfo && userRoleInfo.length) {
userRoleInfo.map(k => {
return _this.addIsShowFlag(k.id, allMenuList)
})
//console.log( this.sortMeunList(allMenuList))
// 先扁平处理 === 再进行树组合
this.flatData(allMenuList)
this.sortMeunList(this.flatList)
let renMenuList = this.treeData(this.flatList, 0);
storage.set('btnAuth', this.buttonAuth)
menuTreeNode = this.renderMenu(renMenuList);
}
this.setState({
menuTreeNode
})
}
flatList = []
buttonAuth = []
// 扁平化数据
flatData(data) {
data.forEach((item, index) => {
if (item.children && item.children.length > 0 ) {
this.flatData(item.children)
}
if(item.menuType === 1) {
this.flatList.push(item)
}else {
if(item.isShow) {
this.buttonAuth.push(item.code)
}
}
})
}
// 删除按钮级别的数据
treeData (data, parentId) {
var itemArr = []
data.map((item, index) => {
if(item.parentId === parentId) {
let newNode={
title: item.title,
sequence: item.sequence,
parentId: item.parentId,
icon: item.icon,
key: item.key,
status: item.status,
id: item.id,
code: item.code || '',
menuType: item.menuType,
isShow: item.isShow,
children: this.treeData(data, item.id)
};
itemArr.push(newNode)
}
})
return itemArr
}
sortMeunList (data) {
data.sort((a,b) => {
return a.sequence - b.sequence
})
return data
}
//菜单渲染
renderMenu = (data) => {
return data.map((item) => {
if (item.isShow) {
if (item.children.length > 0) {
return (
<SubMenu
title={<span >
<i className={item.parentId===0? ` iconfont icon-${item.icon} `:''} ></i>
<span style={{ minWidth: 0 }} className="anticon"> </span>
<span>{item.title}</span>
</span>}
key={item.key}
>
{this.renderMenu(item.children)}
</SubMenu>
)
}
return <Menu.Item style={{ margin: 0, height: 40 }} title={item.title} key={item.key} >
<NavLink to={item.key || '/home'} replace> <span >{item.title}</span></NavLink>
</Menu.Item>
}
})
}
render() {
return (
<div >
<Menu
mode="inline"
theme='dark'
selectedKeys={[this.state.currentKey]}
onClick={this.changeRouter}
// openKeys={this.state.openMenuRouter}
// onOpenChange = {this.onOpenChange}
defaultSelectedKeys={[this.state.currentKey]}
defaultOpenKeys={['/home']}
>
{this.state.menuTreeNode}
</Menu>
</div>
)
}
}
\ No newline at end of file \ No newline at end of file
import React from 'react';
import './index.less';
class Button extends React.PureComponent {
static defaultProps = {
disabled: false,
type: '',
size: '',
}
handleClick = (e) => {
const {
onClick,
} = this.props;
if (onClick) {
onClick();
};
}
render() {
const {
type,
size,
disabled,
children,
onClick,
...otherProps,
} = this.props;
const buttonType = type ? `wowjoy-button__${type}` : '';
const buttonSize = size ? `wowjoy-button__${size}` : '';
return (
<button
className={`wowjoy-button ${buttonType} ${buttonSize}`}
disabled={disabled}
onClick={this.handleClick}>
{children}
</button>
);
}
}
export default Button;
\ No newline at end of file \ No newline at end of file
:global{
.wowjoy-button {
padding: 6px 20px;
border: 1px solid #06aea6;
margin: 0 10px;
outline: none;
cursor: pointer;
font-size: 14px
}
.wowjoy-button__primary {
background: #06aea6;
color: #fff;
}
.wowjoy-button__normal {
background: #fff;
color: #06aea6;
}
.wowjoy-button__mini {
padding: 4px;
font-size: 12px;
}
.wowjoy-button__small {
padding: 7px 9px;
font-size: 12px;
}
.wowjoy-button__large {
padding: 11px 19px;
font-size: 16px;
}
};
\ No newline at end of file \ No newline at end of file
import React from 'react';
import './index.less';
class Checkbox extends React.PureComponent {
static defaultProps = {
value: '',
name: '',
}
handleChange = (e) => {
const {
onChange,
index,
} = this.props;
if (onChange) {
onChange(e, index);
};
}
render() {
const {
defaultChecked,
value,
name,
index,
label,
style,
} = this.props;
return (
<label className="wowjoy-checkbox" style={style}>
<input
type="checkbox"
name={name}
value={value}
data-index={index}
defaultChecked={defaultChecked}
onChange={this.handleChange}
style={{ display: 'none' }}/>
<span className="wowjoy-checkbox__inner"></span>
<span className="wowjoy-checkbox__text">{label}</span>
</label>
);
}
}
export default Checkbox;
\ No newline at end of file \ No newline at end of file
:global {
.wowjoy-checkbox {
cursor: pointer;
display: inline-block;
}
input[type='checkbox']:checked {
&+.wowjoy-checkbox__inner {
border-color: #06aea6;
&:before {
content: '\2713';
color: #06aea6;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
.wowjoy-checkbox__inner {
position: relative;
display: inline-block;
width: 16px;
height: 16px;
background: #fff;
border: 1px solid #DBDBDB;
vertical-align: sub;
margin-right: 5px;
}
.wowjoy-checkbox__text {
display: inline-block;
max-width: 80%;
vertical-align: top;
word-break: break-all;
}
}
\ No newline at end of file \ No newline at end of file
import React from 'react';
import './index.less';
const stripNbsp = str => str.replace(/&nbsp;|\u202F|\u00A0/g, ' ');
export default class ContentEditable extends React.Component {
shouldComponentUpdate(nextProps) {
let {
props,
htmlEl
} = this;
if (JSON.stringify(this.props.style) === JSON.stringify(nextProps.style)) {
return false;
};
// We need not rerender if the change of props simply reflects the user's edits.
// Rerendering in this case would make the cursor/caret jump
// Rerender if there is no element yet... (somehow?)
if (!htmlEl) {
return true;
};
// ...or if html really changed... (programmatically, not by user edit)
if (
stripNbsp(nextProps.html) !== stripNbsp(htmlEl.innerHTML) &&
nextProps.html !== props.html
) {
return true;
};
let optional = ['style', 'className', 'disabled', 'tagName'];
// Handle additional properties
return optional.some(name => props[name] !== nextProps[name]);
}
componentDidUpdate() {
if (this.htmlEl && this.props.html !== this.htmlEl.innerHTML) {
// Perhaps React (whose VDOM gets outdated because we often prevent
// rerendering) did not update the DOM. So we update it manually now.
this.htmlEl.innerHTML = this.props.html;
};
}
emitChange = (evt) => {
if (!this.htmlEl) return;
var name = evt.target.dataset.name;
var html = this.htmlEl.innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
// Clone event with Object.assign to avoid
// "Cannot assign to read only property 'target' of object"
var evt = Object.assign({}, evt, {
target: {
value: html,
name: name,
},
});
this.props.onChange(evt);
}
this.lastHtml = html;
}
render() {
var {
tagName,
name,
html,
style,
onKeyPress,
...otherProps,
} = this.props;
return (
// React.createElement(
// tagName || 'div',
// {
// ...props,
// ref: (e) => this.htmlEl = e,
// onInput: this.emitChange,
// onBlur: this.props.onBlur || this.emitChange,
// contentEditable: !this.props.disabled,
// dangerouslySetInnerHTML: {__html: html}
// },
// this.props.children);
<div {...otherProps}
className="contentEditable"
style={style}
data-name={name}
ref={(e) => this.htmlEl = e}
onInput={this.emitChange}
onKeyPress={onKeyPress}
//onBlur={this.props.onBlur || this.emitChange}
contentEditable={!this.props.disabled}
dangerouslySetInnerHTML={{__html: html}}>
{this.props.children}
</div>
);
}
}
\ No newline at end of file \ No newline at end of file
:global {
.contentEditable {
outline: none;
line-height: 36px;
}
}
\ No newline at end of file \ No newline at end of file
import React from 'react';
import Button from '../Button';
import './index.less'
class Dialog extends React.PureComponent {
state = {
visible: this.props.visible,
}
componentWillReceiveProps(nextProps) {
if (nextProps.visible !== this.props.visible) {
this.setState({
visible: nextProps.visible,
});
};
}
confirm = () => {
const {
onConfirm,
} = this.props;
if (onConfirm) {
onConfirm();
};
}
cancel = () => {
const {
onCancel,
} = this.props;
if (onCancel) {
onCancel();
};
}
render() {
const {
title,
children,
onCancel,
onConfirm,
} = this.props;
const {
visible,
} = this.state;
const fade = visible ? 'wowjoy-dialog__fadeIn' : '';
return (
<div className={`wowjoy-dialog ${fade}`}>
<div className="wowjoy-dialog__inner">
<div className="wowjoy-dialog__header">
{title}
</div>
<div className="wowjoy-dialog__body">
{children}
</div>
<div className="wowjoy-dialog__footer">
<Button type="primary" onClick={this.confirm}>确定</Button>
<Button type="cancel" onClick={this.cancel}>取消</Button>
</div>
</div>
</div>
);
}
}
export default Dialog;
\ No newline at end of file \ No newline at end of file
:global {
.wowjoy-dialog {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.30);
//visibility: hidden;
display: none;
//transition: all .3s;
z-index: 10;
}
.wowjoy-dialog__fadeIn {
display: block;
}
.wowjoy-dialog__inner {
background: #FFFFFF;
box-shadow: 0 0 4px 0 rgba(0,0,0,0.20);
border-radius: 3px;
padding: 10px 20px;
width: 40%;
max-width: 500px;
min-width: 300px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
//opacity: 0;
//transition: all .3s;
}
.wowjoy-dialog__slideDown {
opacity: 1;
transform: translateY(-50%);
}
.wowjoy-dialog__header {
margin-bottom: 15px;
font-family: PingFangSC-Medium;
font-size: 16px;
color: #333333;
}
.wowjoy-dialog__footer {
height: 40px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
};
\ No newline at end of file \ No newline at end of file
import React from 'react';
import DragSort from './index.js';
export default class DragSortExample extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [{
name: 'title'
}, {
name: 'name'
}, {
name: 'code'
}, {
name: 'email'
}],
curMoveItem: null,
index: '',
dragged: false,
}
}
handleDragMove = (data, from, to) => {
this.setState({
curMoveItem: to,
list: data,
index: null,
});
}
handleDragEnd = (index) => {
this.setState({
curMoveItem: null,
dragged: false,
index,
});
}
enter = (index) => {
if (this.state.index !== null) {
this.setState({
index,
});
};
}
leave = () => {
if (this.state.index !== null) {
this.setState({
index: '',
});
};
}
render() {
const {
dragged,
} = this.state;
const el = this.state.list.map((item, index) => {
return (
<div
className={this.state.curMoveItem === index ? 'item active' : 'item'}
onMouseEnter={this.enter.bind(this, index)}
onMouseLeave={this.leave.bind(this, index)}
style={{
background: this.state.index === index ? 'red' : '#eee',
}}
key={item.name}>
<div className="inner">{item.name}</div>
</div>
);
});
return (
<div>
<ul>
<DragSort
onDragEnd={this.handleDragEnd}
onDragMove={this.handleDragMove}
draggable={true}
data={this.state.list}>
{el}
</DragSort>
</ul>
</div>
);
}
}
\ No newline at end of file \ No newline at end of file
import React from 'react';
let curDragIndex = null;
export default function DragSort(props) {
let container = props.children;
let draggable = props.draggable;
function onChange(from, to) {
let curValue = props.data;
let newValue = arrMove(curValue, from, to);
if (typeof props.onDragMove === 'function') {
return props.onDragMove(newValue, from, to);
}
}
return (
<div>
{container.map((item, index)=>{
if(React.isValidElement(item)){
return React.cloneElement(item, {
draggable,
//开始拖动元素时触发此事件
onDragStart(){
curDragIndex = index;
},
/*
* 当被拖动的对象进入其容器范围内时触发此事件
* 在自身拖动时也会触发该事件
*/
onDragEnter() {
onChange(curDragIndex, index);
curDragIndex = index;
},
/*
* 当被拖动的对象在另一对象容器范围内拖动时触发此事件
* 在拖动元素时,每隔350毫秒会触发onDragOver事件
*/
onDragOver(e) {
/*
* 默认情况下,数据/元素不能放置到其他元素中。如果要实现该功能,我们需要
* 防止元素的默认处理方法,我们可以通过调用event.preventDefault()方法来实现onDragOver事件
*/
e.preventDefault();
},
//完成元素拖动后触发
onDragEnd(){
curDragIndex = null;
if(typeof props.onDragEnd === 'function'){
props.onDragEnd(index);
};
},
})
}
return item;
})}
</div>
);
}
function arrMove(arr, fromIndex, toIndex) {
if (fromIndex !== toIndex) {
arr = arr.concat();
let item = arr.splice(fromIndex, 1)[0];
arr.splice(toIndex, 0, item);
};
return arr;
}
\ No newline at end of file \ No newline at end of file
:global {
.item{
height: 35px;
margin:10px;
// background-color: #eee;
// &:hover {
// background-color: red;
// }
}
.item-notdrag {
height: 35px;
margin:10px;
background-color: #eee;
}
.inner {
height: 100%;
}
.item.active{
//height: 35px;
//margin:10px;
opacity: 0;
//background-color: #eee !important;
}
};
\ No newline at end of file \ No newline at end of file
import React from 'react';
import './index.less';
class Select extends React.PureComponent {
handleChange = (e) => {
const {
onChange,
} = this.props;
if (onChange) {
onChange(e);
};
}
render() {
const {
name,
value,
options,
} = this.props;
return (
<div className="wowjoy-select">
<select
name={name}
placeholder="请选择"
className="wowjoy-select__inner"
value={value}
onChange={this.handleChange}>
{options.map((option, index) => {
return <option key={index} value={option}>{option}</option>
})}
</select>
</div>
);
}
}
export default Select;
\ No newline at end of file \ No newline at end of file
:global{
.wowjoy-select {
display: inline-block;
}
};
\ No newline at end of file \ No newline at end of file
import React from 'react'
import './index.less'
class Input extends React.PureComponent {
static defaultProps = {
disabled: false,
type: 'text',
}
handleChange = (e) => {
const {
onChange,
index,
} = this.props;
if (onChange) {
onChange(e, index);
};
}
handleBlur = (e) => {
const {
onBlur,
index,
} = this.props;
if (onBlur) {
onBlur(e, index);
};
}
fixControlledValue = (value) => {
if (typeof value === 'undefined' || value === null) {
return '';
};
return value;
}
render() {
const {
type,
name,
width,
margin,
style,
maxLength,
rows,
disabled,
...otherProps
} = this.props;
/*
* defaultValue只会在第一次渲染有效
* defaultValue和value尽量不共存,如果共存的话value将会覆盖defaultValue
* 在共存的情况下,如果value值为undefined或者null,会被defaultValue覆盖
*/
if ('value' in otherProps) {
otherProps.value = this.fixControlledValue(otherProps.value);
delete otherProps.defaultValue;
};
return (
<div
className="wowjoy-input"
style={{ width, margin }}>
{type === 'textarea' ? (
<textarea {...otherProps}
rows={rows}
name={name}
disabled={disabled}
onChange={this.handleChange}
style={style}
className="wowjoy-textarea__inner"
/>
) : (
<input {...otherProps}
type={type || 'text'}
name={name}
maxLength={maxLength}
disabled={disabled}
onChange={this.handleChange}
onBlur={this.handleBlur}
style={style}
className="wowjoy-input__inner"
/>
)}
</div>
);
}
}
export default Input;
\ No newline at end of file \ No newline at end of file
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!