Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| const BasicGenerator = require('../../BasicGenerator.js'); | ||
| class Generator extends BasicGenerator { | ||
| prompting() { | ||
| const prompts = [ | ||
| { | ||
| type: 'input', | ||
| name: 'title', | ||
| message: 'Package Name', | ||
| default: 'React Template', | ||
| }, | ||
| ]; | ||
| return this.prompt(prompts).then(props => { | ||
| this.prompts = props; | ||
| }); | ||
| } | ||
| writing() { | ||
| this.writeFiles({ | ||
| context: { | ||
| name: this.name, | ||
| ...this.prompts, | ||
| }, | ||
| filterFiles: f => { | ||
| return true; | ||
| }, | ||
| }); | ||
| } | ||
| } | ||
| module.exports = Generator; |
| # http://editorconfig.org | ||
| root = true | ||
| [*] | ||
| indent_style = space | ||
| indent_size = 4 | ||
| end_of_line = lf | ||
| charset = utf-8 | ||
| trim_trailing_whitespace = true | ||
| insert_final_newline = true | ||
| [*.md] | ||
| trim_trailing_whitespace = false | ||
| [Makefile] | ||
| indent_style = tab |
Sorry, the diff of this file is not supported yet
| module.exports = { | ||
| extends: ['@vtx/vortex', 'plugin:react/recommended'], | ||
| settings: { | ||
| react: { | ||
| version: 'detect', | ||
| }, | ||
| }, | ||
| globals: { | ||
| OPERATE_INFO: true, | ||
| }, | ||
| rules: { | ||
| 'react/prop-types': 'off', | ||
| }, | ||
| }; |
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
| # dependencies | ||
| /node_modules | ||
| # production | ||
| /dist | ||
| # misc | ||
| .DS_Store | ||
| npm-debug.log* | ||
| *.lock |
Sorry, the diff of this file is not supported yet
| module.exports = { | ||
| // 一行最多 100 字符 | ||
| printWidth: 100, | ||
| // 使用 4 个空格缩进 | ||
| tabWidth: 4, | ||
| // 使用单引号 | ||
| singleQuote: true, | ||
| // 句尾添加分号 | ||
| semi: true, | ||
| // 末尾需要逗号 | ||
| trailingComma: 'all', | ||
| // 换行符使用 lf | ||
| endOfLine: 'lf', | ||
| }; |
| export default {}; |
| { | ||
| "editor.formatOnSave": true, | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode", | ||
| "css.validate": false, | ||
| "less.validate": false, | ||
| "scss.validate": false | ||
| } |
| var path = require('path'); | ||
| export default { | ||
| entry: 'src/index.js', | ||
| html: { | ||
| template: './public/index.ejs', | ||
| }, | ||
| proxy: { | ||
| '/api': { | ||
| target: 'http://jsonplaceholder.typicode.com/', | ||
| changeOrigin: true, | ||
| pathRewrite: { '^/api': '' }, | ||
| }, | ||
| }, | ||
| extraBabelPlugins: [ | ||
| ['import', { libraryName: 'antd', libraryDirectory: 'lib', style: 'css' }, 'antd'], | ||
| ['import', { libraryName: 'vtx-ui', camel2DashComponentName: false }, 'vtx-ui'], | ||
| [ | ||
| 'import', | ||
| { libraryName: 'lodash', libraryDirectory: '', camel2DashComponentName: false }, | ||
| 'lodash', | ||
| ], | ||
| ], | ||
| hash: true, | ||
| ignoreMomentLocale: true, | ||
| commons: [ | ||
| { | ||
| async: 'common', | ||
| children: true, | ||
| minChunks: 5, | ||
| }, | ||
| { | ||
| async: 'echarts', | ||
| children: true, | ||
| minChunks: function(module) { | ||
| return /echarts/.test(module.context); | ||
| }, | ||
| }, | ||
| { | ||
| async: 'lodash', | ||
| children: true, | ||
| minChunks: function(module) { | ||
| return /lodash/.test(module.context); | ||
| }, | ||
| }, | ||
| { | ||
| async: 'moment', | ||
| children: true, | ||
| minChunks: function(module) { | ||
| return /moment/.test(module.context); | ||
| }, | ||
| }, | ||
| { | ||
| name: 'manifest', | ||
| minChunks: 'Infinity', | ||
| }, | ||
| ], | ||
| alias: { | ||
| history: path.dirname(require.resolve('history/package.json')), | ||
| moment: path.dirname(require.resolve('moment/package.json')), | ||
| '@': path.resolve(__dirname, 'src'), | ||
| }, | ||
| env: { | ||
| development: { | ||
| extraBabelPlugins: ['dva-hmr'], | ||
| }, | ||
| production: { | ||
| extraBabelPlugins: ['transform-remove-console'], | ||
| }, | ||
| }, | ||
| }; |
| module.exports = { | ||
| extends: ['@commitlint/config-conventional'], | ||
| /** | ||
| * rule 由 name 和配置数组组成,如:'name: [0, 'always', 72]' | ||
| * 数组中第一位为 level, 可选0, 1, 2; 0为disable, 1为warning, 2为error | ||
| * 第二位为应用与否, 可选 always | never | ||
| * 第三位为 rule 的值 | ||
| */ | ||
| rules: { | ||
| 'type-enum': [ | ||
| 2, | ||
| 'always', | ||
| ['feature', 'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'release'], | ||
| ], | ||
| }, | ||
| }; |
| { | ||
| "compilerOptions": { | ||
| "baseUrl": ".", | ||
| "paths": { | ||
| "@src/*": ["src/*"] | ||
| } | ||
| }, | ||
| "include": ["src/**/*"], | ||
| "exclude": ["node_modules", "dist", ".cache"] | ||
| } |
Sorry, the diff of this file is not supported yet
| { | ||
| "private": true, | ||
| "scripts": { | ||
| "start": "cross-env BROWSER=none ESLINT=none roadhog dev", | ||
| "build": "cross-env ESLINT=none roadhog build", | ||
| "buildD": "cross-env NO_COMPRESS=none ESLINT=none roadhog build", | ||
| "lint": "npm run lint:script", | ||
| "lint:script": "eslint --ext .js --ext jsx src", | ||
| "prettier": "prettier --write \"src/**/*+(js|less|css|jsx)\"", | ||
| "prettier:check": "prettier --check \"src/**/*+(js|less|css|jsx)\"", | ||
| "pretty-quick": "pretty-quick" | ||
| }, | ||
| "husky": { | ||
| "hooks": { | ||
| "pre-commit": "lint-staged", | ||
| "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" | ||
| } | ||
| }, | ||
| "lint-staged": { | ||
| "src/**/*+(js|jsx|less|css)": "npm run prettier:check", | ||
| "src/**/*+(js|jsx)": "npm run lint" | ||
| }, | ||
| "engines": { | ||
| "install-node": "6.9.2" | ||
| }, | ||
| "dependencies": { | ||
| "antd": "^2.13.11", | ||
| "dva": "^2.1.0", | ||
| "dva-loading": "^2.0.5", | ||
| "immutable": "^3.8.2", | ||
| "lodash": "^4.17.10", | ||
| "moment": "^2.20.1", | ||
| "react": "^15.4.0", | ||
| "react-dom": "^15.4.0", | ||
| "updeep": "^1.0.0", | ||
| "vtx-ui": "latest" | ||
| }, | ||
| "devDependencies": { | ||
| "@commitlint/cli": "^11.0.0", | ||
| "@commitlint/config-conventional": "^11.0.0", | ||
| "@vtx/eslint-config-vortex": "^1.1.0", | ||
| "babel-plugin-dva-hmr": "^0.4.0", | ||
| "babel-plugin-import": "^1.6.3", | ||
| "babel-plugin-transform-remove-console": "^6.8.5", | ||
| "babel-plugin-transform-runtime": "^6.9.0", | ||
| "cross-env": "^5.1.3", | ||
| "css-split-webpack-plugin": "^0.2.5", | ||
| "eslint": "^7.11.0", | ||
| "eslint-config-umi": "^0.1.1", | ||
| "eslint-plugin-flowtype": "^2.34.1", | ||
| "eslint-plugin-import": "^2.6.0", | ||
| "eslint-plugin-jsx-a11y": "^5.1.1", | ||
| "eslint-plugin-react": "^7.1.0", | ||
| "history": "4.7.2", | ||
| "husky": "^4.3.0", | ||
| "lint-staged": "^10.4.2", | ||
| "prettier": "^1.19.1", | ||
| "pretty-quick": "^3.1.0", | ||
| "redbox-react": "^1.3.2", | ||
| "roadhog": "2.5.0-beta.4", | ||
| "webpack-parallel-uglify-plugin": "^1.1.0" | ||
| } | ||
| } |
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
| <title><%= title%></title> | ||
| </head> | ||
| <body> | ||
| <div id="root"></div> | ||
| <script src="./resources/js/gtmd-ie.min.js"></script> | ||
| <script src="./resources/js/jquery.min.js"></script> | ||
| <script src="./resources/js/polyfill.min.js"></script> | ||
| </body> | ||
| </html> |
| Object.setPrototypeOf||{__proto__:[]}instanceof Array?Object.setPrototypeOf=function setProtoOf(obj,proto){return obj.__proto__=proto,obj}:Object.setPrototypeOf=function mixinProperties(obj,proto){for(var prop in Object.defineProperty(obj,"__proto__",{value:proto}),proto)obj.hasOwnProperty(prop)||(obj[prop]=proto[prop]);return obj}; | ||
| window.console=window.console||function(){var c={};return c.log=c.warn=c.debug=c.info=c.error=c.time=c.dir=c.profile=c.clear=c.exception=c.trace=c.assert=function(){},c}(); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
| import React from 'react'; | ||
| export default class MyComponent extends React.Component { | ||
| constructor(props) { | ||
| super(props); | ||
| } | ||
| render() { | ||
| return <div></div>; | ||
| } | ||
| } |
| import dva from 'dva'; | ||
| import './index.less'; | ||
| import createLoading from 'dva-loading'; | ||
| // 1. Initialize | ||
| const app = dva(createLoading()); | ||
| // 2. Plugins | ||
| // app.use({}); | ||
| // 3. Model | ||
| // app.model(require('./models/example')); | ||
| // 4. Router | ||
| app.router(require('./router').default); | ||
| // 5. Start | ||
| app.start('#root'); |
| html, | ||
| body, | ||
| :global(#root) { | ||
| height: 100%; | ||
| } |
| import u from 'updeep'; | ||
| const STATE = {}; | ||
| export default { | ||
| namespace: 'example', | ||
| state: u(STATE, null), | ||
| subscriptions: { | ||
| setup({ dispatch, history }) { | ||
| // todo | ||
| }, | ||
| }, | ||
| effects: { | ||
| // 普通请求 | ||
| *fetch({ payload }, { call, put, select, take }) { | ||
| yield put({ type: 'takeLatest' }); | ||
| yield take('takeLatest/@@end'); //等takeLatest函数执行完毕后,才会执行此语句后面的代码 | ||
| }, | ||
| // 节流函数:短时间连续触发多次,此函数只执行一次 | ||
| throttle: [ | ||
| function*({ payload }, { call, put, select }) { | ||
| // todo | ||
| }, | ||
| { type: 'throttle', ms: 500 }, | ||
| ], | ||
| // 连续多次请求只返回最后一次结果 | ||
| takeLatest: [ | ||
| function*({ payload }, { call, put, select }) { | ||
| // todo | ||
| }, | ||
| { type: 'takeLatest' }, | ||
| ], | ||
| }, | ||
| reducers: { | ||
| updateState(state, action) { | ||
| return u(action.payload, state); | ||
| }, | ||
| resetState(state, action) { | ||
| return u(STATE, null); | ||
| }, | ||
| }, | ||
| }; |
| import React from 'react'; | ||
| import { Router, Route, Switch } from 'dva/router'; | ||
| import dynamic from 'dva/dynamic'; | ||
| const routes = [ | ||
| { | ||
| path: '/', | ||
| models: () => [import('./models/example')], | ||
| component: () => import('./routes/IndexPage'), | ||
| }, | ||
| ]; | ||
| function RouterConfig({ history, app }) { | ||
| return ( | ||
| <Router history={history}> | ||
| <Switch> | ||
| {routes.map(({ path, ...dynamics }, key) => ( | ||
| <Route | ||
| key={key} | ||
| exact | ||
| path={path} | ||
| component={dynamic({ | ||
| app, | ||
| ...dynamics, | ||
| })} | ||
| /> | ||
| ))} | ||
| </Switch> | ||
| </Router> | ||
| ); | ||
| } | ||
| export default RouterConfig; |
| import React from 'react'; | ||
| import { connect } from 'dva'; | ||
| import styles from './IndexPage.less'; | ||
| function IndexPage() { | ||
| return ( | ||
| <div className={styles.normal}> | ||
| <h1 className={styles.title}>Yay! Welcome to dva!</h1> | ||
| <div className={styles.welcome} /> | ||
| <ul className={styles.list}> | ||
| <li> | ||
| To get started, edit <code>src/index.js</code> and save to reload. | ||
| </li> | ||
| <li> | ||
| <a href="https://github.com/dvajs/dva-docs/blob/master/v1/en-us/getting-started.md"> | ||
| Getting Started | ||
| </a> | ||
| </li> | ||
| </ul> | ||
| </div> | ||
| ); | ||
| } | ||
| export default connect(({ example, loading }) => ({ | ||
| example, | ||
| loading, | ||
| }))(IndexPage); |
| .normal { | ||
| font-family: Georgia, sans-serif; | ||
| margin-top: 3em; | ||
| text-align: center; | ||
| } | ||
| .title { | ||
| font-size: 2.5rem; | ||
| font-weight: normal; | ||
| letter-spacing: -1px; | ||
| } | ||
| .welcome { | ||
| height: 328px; | ||
| background: url('@/assets/yay.jpg') no-repeat center 0; | ||
| background-size: 388px 328px; | ||
| } | ||
| .list { | ||
| font-size: 1.2em; | ||
| margin-top: 1.8em; | ||
| list-style: none; | ||
| line-height: 1.5em; | ||
| } | ||
| .list code { | ||
| background: #f7f7f7; | ||
| } |
| import request from '../utils/request'; | ||
| export function query() { | ||
| return request('/api/users'); | ||
| } |
| import isObject from 'lodash/isObject'; | ||
| import pickBy from 'lodash/pickBy'; | ||
| import { VtxUtil } from './util'; | ||
| import { message } from 'antd'; | ||
| /** | ||
| * 请求封装 | ||
| * 支持 Get 和 Post 请求 | ||
| */ | ||
| class Http { | ||
| constructor(config) { | ||
| this.defaults = config; | ||
| } | ||
| /** | ||
| * Get 请求 | ||
| * @param {string} url | ||
| * @param {object} [options] | ||
| * @return {object} | ||
| */ | ||
| get(url, options) { | ||
| const { body = {}, extraHeader } = options; | ||
| const { headers, extraQs = {} } = this.defaults; | ||
| const postData = isObject(body) | ||
| ? pickBy(body, function(value) { | ||
| return value !== '' && value !== undefined && value !== null; | ||
| }) | ||
| : {}; | ||
| const config = { | ||
| url, | ||
| type: 'get', | ||
| data: { ...extraQs, ...postData }, | ||
| dataType: 'json', | ||
| cache: false, | ||
| headers: { | ||
| ...headers, | ||
| ...this._mergePeration(extraHeader), | ||
| }, | ||
| }; | ||
| return this._request(config); | ||
| } | ||
| /** | ||
| * Post 请求 | ||
| * @param {string} url | ||
| * @param {object} options | ||
| */ | ||
| post(url, options) { | ||
| const { body, extraHeader } = options; | ||
| const config = { | ||
| url, | ||
| data: body, | ||
| type: 'post', | ||
| dataType: 'json', | ||
| contentType: `${ | ||
| isObject(body) ? 'application/x-www-form-urlencoded;' : 'application/json;' | ||
| }charset=UTF-8`, | ||
| cache: false, | ||
| headers: { | ||
| ...this._mergePeration(extraHeader), | ||
| }, | ||
| }; | ||
| return this._request(config); | ||
| } | ||
| /** | ||
| * 合并操作信息 | ||
| * @param {object} extraHeader 操作明细信息 | ||
| */ | ||
| _mergePeration(extraHeader) { | ||
| const { OPERATE_INFO } = this.defaults; | ||
| if (OPERATE_INFO && extraHeader) { | ||
| return { | ||
| operation: encodeURIComponent( | ||
| JSON.stringify({ | ||
| ...JSON.parse(OPERATE_INFO), | ||
| operation: extraHeader.msg, | ||
| }), | ||
| ), | ||
| }; | ||
| } | ||
| return {}; | ||
| } | ||
| _request(options) { | ||
| const t = this; | ||
| return new Promise((resolve, reject) => { | ||
| $.ajax({ | ||
| ...options, | ||
| success: function(response) { | ||
| resolve(response); | ||
| }, | ||
| error: function(XMLHttpRequest, textStatus, errorThrown) { | ||
| reject(XMLHttpRequest, textStatus, errorThrown); | ||
| }, | ||
| }); | ||
| }) | ||
| .then(response => { | ||
| return t._responseHandler(response); | ||
| }) | ||
| .catch(err => { | ||
| t._errorHandler(err); | ||
| return { data: null }; | ||
| }); | ||
| } | ||
| /** | ||
| * 响应处理 | ||
| * @param {*} res | ||
| */ | ||
| _responseHandler(res) { | ||
| if (res) { | ||
| if (res.result === 0) { | ||
| return res; | ||
| } else { | ||
| message.error(res.msg || '请求信息错误'); | ||
| } | ||
| } else { | ||
| message.error('请求数据失败,请刷新重试!'); | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * 请求错误处理 | ||
| * @param {*} err | ||
| */ | ||
| _errorHandler(err) { | ||
| if (err) { | ||
| let msg; | ||
| switch (err.status) { | ||
| case 404: | ||
| msg = '接口请求不存在!错误码【404】。'; | ||
| break; | ||
| case 500: | ||
| msg = '服务端应用接口异常!错误码【500】。'; | ||
| break; | ||
| default: | ||
| msg = '请求错误,请检查或刷新重试!'; | ||
| break; | ||
| } | ||
| message.error(msg); | ||
| } | ||
| } | ||
| } | ||
| const token = VtxUtil.getUrlParam('token'); | ||
| const tenantId = VtxUtil.getUrlParam('tenantId'); | ||
| const http = new Http({ | ||
| // 全局变量,记录操作信息,在 public/index.ejs 定义 | ||
| OPERATE_INFO: 'OPERATE_INFO' in window ? OPERATE_INFO : '', | ||
| extraQs: { tenantId }, | ||
| headers: { | ||
| tenantId, | ||
| Authorization: token ? `Bearer ${token}` : '', | ||
| }, | ||
| }); | ||
| export default http; |
| import React from 'react'; | ||
| export default class RouterComponent extends React.Component { | ||
| constructor(props) { | ||
| super(props); | ||
| this.namespace = ''; | ||
| this.updateState = this.updateState.bind(this); | ||
| this.act = this.act.bind(this); | ||
| } | ||
| // 更新state | ||
| updateState(obj, namespace) { | ||
| this.props.dispatch({ | ||
| type: `${namespace || this.namespace}/updateState`, | ||
| payload: obj, | ||
| }); | ||
| } | ||
| // 调用指定namespace内部函数 | ||
| act(functionName, obj = {}, namespace) { | ||
| return this.props.dispatch({ | ||
| type: `${namespace || this.namespace}/${functionName}`, | ||
| payload: obj, | ||
| }); | ||
| } | ||
| } |
| import moment from 'moment'; | ||
| import 'moment/locale/zh-cn'; | ||
| moment.locale('zh-cn'); | ||
| /* | ||
| 时间util类 | ||
| */ | ||
| export const VtxTime = { | ||
| /* | ||
| 获取时间 | ||
| time: 指定时间, 可以是任何类型的时间 | ||
| 默认:当前时间 | ||
| format: YYYY/MM/DD/HH/mm/ss | ||
| 类型: String | ||
| 默认: YYYY-MM-DD | ||
| return: 返回匹配的时间字符串 | ||
| */ | ||
| getFormatTime: ({ time = new Date(), format = 'YYYY-MM-DD' } = {}) => { | ||
| return moment(time).format(format); | ||
| }, | ||
| /* | ||
| 时间加减 | ||
| time: 指定时间, 可以是任何类型的时间 | ||
| 默认:当前时间 | ||
| format: YYYY/MM/DD/HH/mm/ss | ||
| 默认: YYYY-MM-DD | ||
| 类型: String | ||
| type: 加/减 | ||
| 默认: add | ||
| 类型: String | ||
| 参数: add/subtract | ||
| num: 正整数 | ||
| 默认: 0 | ||
| 类型: Number | ||
| dateType: 加减的类型,如y代表加减几年, 参数: y/M/w/d/h/m/s/ms 默认d (String) | ||
| return: 返回匹配的时间字符串 | ||
| */ | ||
| operationTime: ({ | ||
| time = new Date(), | ||
| format = 'YYYY-MM-DD', | ||
| type = 'add', | ||
| num = 0, | ||
| dateType = 'd', | ||
| } = {}) => { | ||
| const parseNum = VtxNum.replaceInt(num); | ||
| return moment(time, format) | ||
| [type](parseNum, dateType) | ||
| .format(format); | ||
| }, | ||
| /* | ||
| 获取毫秒时间 | ||
| time: 需要转换的时间 | ||
| 默认: 0 | ||
| return: 返回对应类型的时间 | ||
| */ | ||
| getMsTime: time => { | ||
| if (time) { | ||
| return new Date(time).getTime(); | ||
| } else { | ||
| return new Date().getTime(); | ||
| } | ||
| }, | ||
| }; | ||
| /* | ||
| 正则匹配 | ||
| */ | ||
| export const VtxRegex = { | ||
| /* | ||
| 验证是几位浮点数 数字 | ||
| num 需要验证的数字 | ||
| n 是数字几位 例如2 | ||
| */ | ||
| checkFloatNumber(num, n) { | ||
| let regex = new RegExp(`^-?(0|[1-9][0-9]*)(\.([0-9]?){${n}})?$`); | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是数字 | ||
| */ | ||
| checkNumber(num) { | ||
| let regex = /^-?(0|[1-9][0-9]*)(\.[0-9]*)?$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是正数 | ||
| */ | ||
| checkPositiveNumber(num) { | ||
| let regex = /^(0|[1-9][0-9]*)(\.[0-9]*)?$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是正整数 | ||
| */ | ||
| checkPositiveInteger(num) { | ||
| let regex = /^(0|[1-9][0-9]*)$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是正几位小数 | ||
| */ | ||
| checkIntegerFloatNumber(num, n) { | ||
| let regex = new RegExp(`^(0|[1-9][0-9]*)(\.([0-9]?){${n}})?$`); | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是负数 | ||
| */ | ||
| checkNegativeNumber(num) { | ||
| let regex = /^-(0|[1-9][0-9]*)(\.[0-9]*)?$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是负整数 | ||
| */ | ||
| checkNegativeInteger(num) { | ||
| let regex = /^-(0|[1-9][0-9]*)$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是负几位小数 | ||
| */ | ||
| checkNegativeIntegerFloatNumber(num, n) { | ||
| let regex = new RegExp(`^-(0|[1-9][0-9]*)(\.([0-9]?){${n}})?$`); | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证手机号码 | ||
| phone 需要验证的手机号码 | ||
| */ | ||
| checkCellphone(phone) { | ||
| let regex = /^1\d{10}$/; | ||
| return regex.test(phone); | ||
| }, | ||
| /* | ||
| 验证号码 | ||
| tel 需要验证的号码 | ||
| */ | ||
| checkTelphone(tel) { | ||
| let regex = /(^(\d{3,4}-)?\d*)$/; | ||
| return regex.test(tel); | ||
| }, | ||
| /* | ||
| 验证数组 | ||
| phone 需要验证的手机号码 | ||
| */ | ||
| checkArray(ary) { | ||
| return ary instanceof Array; | ||
| }, | ||
| }; | ||
| export const VtxNum = { | ||
| /* | ||
| 字符串转成 float类型的字符串 | ||
| str: 需要处理的字符串 (String) | ||
| return: 返回一个float类型的字符串 | ||
| */ | ||
| replaceFloat: str => { | ||
| let b = str.toString().split('.'); | ||
| if (!b[1]) { | ||
| if (str.indexOf('.') > -1) { | ||
| return `${b[0].replace(/[^0-9]/g, '') || 0}.`; | ||
| } else { | ||
| return b[0].replace(/[^0-9]/g, '') || 0; | ||
| } | ||
| } else { | ||
| if (!parseInt(b[1].replace(/[^0-9]/g, ''))) { | ||
| if (parseInt(b[1].replace(/[^0-9]/g, '')) == 0) { | ||
| return `${b[0].replace(/[^0-9]/g, '') || 0}.${b[1].replace(/[^0-9]/g, '')}`; | ||
| } else { | ||
| return b[0].replace(/[^0-9]/g, '') || 0; | ||
| } | ||
| } else { | ||
| if (b[0].length > 1) { | ||
| return `${b[0].replace(/[^0-9]/g, '').replace(/^0*/g, '') || 0}.${b[1].replace( | ||
| /[^0-9]/g, | ||
| '', | ||
| )}`; | ||
| } else { | ||
| return `${b[0].replace(/[^0-9]/g, '') || 0}.${b[1].replace(/[^0-9]/g, '')}`; | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| /* | ||
| 字符串转成 Int类型的字符串 | ||
| str: 需要处理的字符串 支持number类型 | ||
| return: 返回一个Int类型的字符串 | ||
| */ | ||
| replaceInt: str => { | ||
| return ( | ||
| str | ||
| .toString() | ||
| .split('.')[0] | ||
| .replace(/[^0-9]/g, '') | ||
| .replace(/^0*/g, '') || '0' | ||
| ); | ||
| }, | ||
| /* | ||
| 取小数后几位 | ||
| num: 需要处理的 数字 支持String类型 | ||
| count: 需要保留的位数 Number | ||
| return: 返回对应的float类型字符串 | ||
| */ | ||
| decimals: (num, count) => { | ||
| let nary = VtxNum.replaceFloat(num) | ||
| .toString() | ||
| .split('.'), | ||
| n = ''; | ||
| const decimal = parseInt(count); | ||
| if (decimal > 0) { | ||
| if (nary[1]) { | ||
| n = `${nary[0]}.${nary[1].substr(0, decimal)}`; | ||
| for (let i = 0; i < decimal - nary[1].length; i++) { | ||
| n = `${n}0`; | ||
| } | ||
| } else { | ||
| n = nary[0]; | ||
| for (let j = 0; j < decimal; j++) { | ||
| if (j == 0) n = `${n}.0`; | ||
| else n = `${n}0`; | ||
| } | ||
| } | ||
| } else { | ||
| n = nary[0]; | ||
| } | ||
| return n; | ||
| }, | ||
| }; | ||
| /* | ||
| 其他公共方法 | ||
| */ | ||
| export const VtxUtil = { | ||
| /* | ||
| 获取url中 参数的值 | ||
| key: 参数前面的key | ||
| return: 对应key的value | ||
| */ | ||
| getUrlParam(key) { | ||
| let paramObj = {}; | ||
| let matchList = window.location.href.match(/([^\?&]+)=([^&]+)/g) || []; | ||
| for (let i = 0, len = matchList.length; i < len; i++) { | ||
| let r = matchList[i].match(/([^\?&]+)=([^&]+)/); | ||
| paramObj[r[1]] = r[2]; | ||
| } | ||
| if (key) { | ||
| return paramObj[key]; | ||
| } else { | ||
| return paramObj; | ||
| } | ||
| }, | ||
| /* | ||
| 获取hash字符串 | ||
| */ | ||
| getHash() { | ||
| let h = location.hash, | ||
| xI = h.indexOf('/'), | ||
| wI = h.indexOf('?'); | ||
| return h.substring(xI + 1, wI); | ||
| }, | ||
| /* | ||
| 延迟时间 | ||
| time是延迟的时间 单位ms | ||
| */ | ||
| delay: time => { | ||
| return new Promise((resolve, reject) => { | ||
| setTimeout(() => { | ||
| resolve(); | ||
| }, time); | ||
| }); | ||
| }, | ||
| /* | ||
| 设置抬头 | ||
| title 设置的title名 | ||
| */ | ||
| setTitle: title => { | ||
| document.title = title; | ||
| }, | ||
| /* | ||
| 处理提交参数的前后空格 | ||
| */ | ||
| submitTrim(obj) { | ||
| if (typeof obj == 'object') { | ||
| let postData = {}; | ||
| for (let k in obj) { | ||
| postData[k] = typeof obj[k] == 'string' ? obj[k].trim() : obj[k]; | ||
| } | ||
| return postData; | ||
| } else { | ||
| return obj; | ||
| } | ||
| }, | ||
| /* | ||
| 数组去除重复 | ||
| 只限 数组中值是字符串或number的 | ||
| */ | ||
| ArraywipeOffRepetition(ary = []) { | ||
| let na = []; | ||
| for (let i = 0; i < ary.length; i++) { | ||
| if (na.indexOf(ary[i]) > -1) { | ||
| continue; | ||
| } else { | ||
| na.push(ary[i]); | ||
| } | ||
| } | ||
| return na; | ||
| }, | ||
| }; | ||
| /* | ||
| 前后端数据转换处理工具 | ||
| -----demo----- | ||
| const yourMapping = {a:'b'}; // 映射关系:原始key为a,转换后key替换为b | ||
| const rawData = {a:100,ss:500}; //原始数据(后端返回的数据) | ||
| const carDataConverter = new DataConverter(yourMapping); | ||
| const new_data = carDataConverter.getMappingData(rawData); // 结果: {b:100} | ||
| */ | ||
| export class DataConverter { | ||
| constructor(mapping) { | ||
| this.mapping = mapping; | ||
| this.reverseMap = this.getReverseMap(mapping); | ||
| } | ||
| getReverseMap(mapping) { | ||
| let new_map = {}; | ||
| for (let k in mapping) { | ||
| new_map[mapping[k]] = k; | ||
| } | ||
| return new_map; | ||
| } | ||
| /* 获取转换完成后的数据 | ||
| data: 【Object】需要转换的数据 | ||
| reverse: 【Bool】按照映射关系反向转换数据(默认正向转换) | ||
| filter:【Bool】是否只获取在映射关系表内的数据(true:只获取在映射关系表内的数据,false:除了转换数据保留原数据的其他属性) | ||
| */ | ||
| getMappingData(data, reverse = false, filter = true) { | ||
| let new_date = {}; | ||
| let mapping = reverse ? this.reverseMap : this.mapping; | ||
| for (let k in data) { | ||
| if (k in mapping) { | ||
| new_date[mapping[k]] = data[k]; | ||
| } else if (!filter) { | ||
| new_date[k] = data[k]; | ||
| } | ||
| } | ||
| return new_date; | ||
| } | ||
| } |
| var webpack = require('webpack'); | ||
| var CSSSplitWebpackPlugin = require('css-split-webpack-plugin/dist/index').default; | ||
| var ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin'); | ||
| // var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; | ||
| module.exports = function(webpackConfig) { | ||
| // adding plugins to your configuration | ||
| // css文件分割(For IE) | ||
| webpackConfig.plugins.push( | ||
| new CSSSplitWebpackPlugin({ | ||
| size: 3000, | ||
| }), | ||
| ); | ||
| if (process.env.NODE_ENV == 'production') { | ||
| // 代码压缩 | ||
| webpackConfig.plugins = webpackConfig.plugins.filter(function(plugin) { | ||
| return !(plugin instanceof webpack.optimize.UglifyJsPlugin); | ||
| }); | ||
| webpackConfig.plugins.push( | ||
| new ParallelUglifyPlugin({ | ||
| uglifyJS: { | ||
| output: { | ||
| comments: false, | ||
| ascii_only: true, | ||
| }, | ||
| warnings: false, | ||
| }, | ||
| cacheDir: './.cache', | ||
| }), | ||
| ); | ||
| // 打包分析工具 | ||
| // webpackConfig.plugins.push(new BundleAnalyzerPlugin()); | ||
| } | ||
| return webpackConfig; | ||
| }; |
Sorry, the diff of this file is not supported yet
| const BasicGenerator = require('../../BasicGenerator.js'); | ||
| class Generator extends BasicGenerator { | ||
| prompting() { | ||
| const prompts = [ | ||
| { | ||
| type: 'input', | ||
| name: 'title', | ||
| message: 'Package Name', | ||
| default: 'React Template', | ||
| }, | ||
| { | ||
| type: 'checkbox', | ||
| name: 'plugins', | ||
| message: '插件', | ||
| choices: [ | ||
| 'echarts' | ||
| ] | ||
| } | ||
| ]; | ||
| return this.prompt(prompts).then(props => { | ||
| this.prompts = props; | ||
| }); | ||
| } | ||
| writing() { | ||
| this.writeFiles({ | ||
| context: { | ||
| name: this.name, | ||
| ...this.prompts, | ||
| }, | ||
| filterFiles: f => { | ||
| return true; | ||
| }, | ||
| }); | ||
| } | ||
| } | ||
| module.exports = Generator; |
| # http://editorconfig.org | ||
| root = true | ||
| [*] | ||
| indent_style = space | ||
| indent_size = 4 | ||
| end_of_line = lf | ||
| charset = utf-8 | ||
| trim_trailing_whitespace = true | ||
| insert_final_newline = true | ||
| [*.md] | ||
| trim_trailing_whitespace = false | ||
| [Makefile] | ||
| indent_style = tab |
| PORT=8000 |
Sorry, the diff of this file is not supported yet
| module.exports = { | ||
| parser: 'babel-eslint', | ||
| parserOptions: { | ||
| ecmaFeatures: { | ||
| legacyDecorators: true, | ||
| }, | ||
| }, | ||
| extends: ['@vtx/vortex', 'plugin:react/recommended'], | ||
| settings: { | ||
| react: { | ||
| version: 'detect', | ||
| }, | ||
| }, | ||
| globals: { | ||
| OPERATE_INFO: true, | ||
| }, | ||
| rules: { | ||
| 'react/prop-types': 'off', | ||
| }, | ||
| }; |
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
| # dependencies | ||
| /node_modules | ||
| /npm-debug.log* | ||
| /yarn-error.log | ||
| /yarn.lock | ||
| /package-lock.json | ||
| # production | ||
| /dist | ||
| # misc | ||
| .DS_Store | ||
| # umi | ||
| /src/.umi | ||
| /src/.umi-production | ||
| /src/.umi-test | ||
| /.env.local |
Sorry, the diff of this file is not supported yet
| module.exports = { | ||
| // 一行最多 100 字符 | ||
| printWidth: 100, | ||
| // 使用 4 个空格缩进 | ||
| tabWidth: 4, | ||
| // 使用单引号 | ||
| singleQuote: true, | ||
| // 句尾添加分号 | ||
| semi: true, | ||
| // 末尾需要逗号 | ||
| trailingComma: 'all', | ||
| // 换行符使用 lf | ||
| endOfLine: 'lf', | ||
| }; |
| { | ||
| "editor.formatOnSave": true, | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode", | ||
| "css.validate": false, | ||
| "less.validate": false, | ||
| "scss.validate": false | ||
| } |
| module.exports = { | ||
| extends: ['@commitlint/config-conventional'], | ||
| /** | ||
| * rule 由 name 和配置数组组成,如:'name: [0, 'always', 72]' | ||
| * 数组中第一位为 level, 可选0, 1, 2; 0为disable, 1为warning, 2为error | ||
| * 第二位为应用与否, 可选 always | never | ||
| * 第三位为 rule 的值 | ||
| */ | ||
| rules: { | ||
| 'type-enum': [ | ||
| 2, | ||
| 'always', | ||
| ['feature', 'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'release'], | ||
| ], | ||
| }, | ||
| }; |
| import { defineConfig } from 'umi'; | ||
| import routes from './routes'; | ||
| import proxy from './proxy'; | ||
| export default defineConfig({ | ||
| // 配置路由 | ||
| routes, | ||
| // 配置代理能力。 | ||
| proxy, | ||
| // 配置 favicon 地址(href 属性) | ||
| favicon: '/favicon.ico', | ||
| // 使用内置dva | ||
| // https://umijs.org/zh-CN/plugins/plugin-dva | ||
| dva: { | ||
| hmr: true, // 启动热更新 | ||
| }, | ||
| // 配置是否让生成的文件包含 hash 后缀,通常用于增量发布和避免浏览器加载缓存。 | ||
| hash: true, | ||
| // https://umijs.org/zh-CN/config#history | ||
| history: { type: 'hash' }, | ||
| manifest: { | ||
| basePath: './', | ||
| }, | ||
| publicPath: './', | ||
| // 国际化插件 | ||
| // https://umijs.org/zh-CN/plugins/plugin-locale | ||
| // 若开启,需创建src/locales/zh-CN.js文件来消除控制台的报警信息 | ||
| locale: { | ||
| default: 'zh-CN', | ||
| antd: true, | ||
| baseNavigator: false, | ||
| }, | ||
| // 配置需要兼容的浏览器最低版本,会自动引入 polyfill 和做语法转换。 | ||
| // https://umijs.org/zh-CN/config#targets | ||
| targets: { | ||
| ie: 9, | ||
| }, | ||
| // 是否启用按需加载,即是否把构建产物进行拆分 | ||
| dynamicImport: { | ||
| // 禁用掉每次刷新路由时出现的 loading... 状态 | ||
| // 官方文档提供的方案目前有误 | ||
| // https://github.com/umijs/umi/issues/5688 | ||
| loading: '@/components/PageLoading.js', | ||
| }, | ||
| // https://umijs.org/zh-CN/config#cssloader | ||
| cssLoader: { | ||
| localsConvention: 'camelCase', | ||
| }, | ||
| // https://umijs.org/zh-CN/config#terseroptions | ||
| // 生产环境移除console和debugger | ||
| terserOptions: { | ||
| compress: { | ||
| drop_console: true, | ||
| drop_debugger: true, | ||
| }, | ||
| }, | ||
| // 设置 node_modules 目录下依赖文件的编译方式。 | ||
| // https://umijs.org/zh-CN/config#nodemodulestransform-31 | ||
| nodeModulesTransform: { | ||
| type: 'none', | ||
| }, | ||
| // 配置额外的 babel 插件。 | ||
| // https://umijs.org/zh-CN/config#extrababelplugins | ||
| // 按需加载antd和lodash | ||
| extraBabelPlugins: [ | ||
| ['import', { libraryName: 'antd', style: 'css' }, 'antd'], | ||
| // https://git.cloudhw.cn:3443/front-end/react-components | ||
| ['import', { libraryName: '@vtx/components', style: 'css' }, 'vtx-components'], | ||
| [ | ||
| 'import', | ||
| { libraryName: 'lodash', libraryDirectory: '', camel2DashComponentName: false }, | ||
| 'lodash', | ||
| ], | ||
| // https://git.cloudhw.cn:3443/front-end/vhooks | ||
| ['import', { libraryName: '@vtx/hooks', camel2DashComponentName: false }, '@vtx/hooks'], | ||
| // https://ahooks.js.org/zh-CN | ||
| ['import', { libraryName: 'ahooks', camel2DashComponentName: false }, 'ahooks'], | ||
| ], | ||
| }); |
| import { defineConfig } from 'umi'; | ||
| /** | ||
| * 此为生产环境的配置文件 | ||
| * 调整 splitChunks 策略,减少整体尺寸 | ||
| * 参考:https://umijs.org/guide/boost-compile-speed#%E8%B0%83%E6%95%B4-splitchunks-%E7%AD%96%E7%95%A5%EF%BC%8C%E5%87%8F%E5%B0%91%E6%95%B4%E4%BD%93%E5%B0%BA%E5%AF%B8 | ||
| */ | ||
| export default defineConfig({ | ||
| // 默认是 ['umi'],可修改,比如做了 vendors 依赖提取之后,会需要在 umi.js 之前加载 vendors.js。 | ||
| // https://umijs.org/zh-CN/config#chunks | ||
| // 结合splitChunks.cacheGroups 使用 | ||
| // 注意:cacheGroups拆分了几个包,chunks也得同步配置,且必须得存在拆分的文件,不然打包会报错 | ||
| chunks: ['vendors', 'antd', 'umi'], | ||
| // 通过 webpack-chain 的 API 修改 webpack 配置。 | ||
| chainWebpack(config) { | ||
| config.merge({ | ||
| optimization: { | ||
| splitChunks: { | ||
| chunks: 'all', | ||
| // byte, == 30 kb, | ||
| // 越大那么单个文件越大,chunk 数就会变少(针对于提取公共 chunk 的时候,不管再大也不会把动态加载的模块合并到初始化模块中) | ||
| // 当这个值很大的时候就不会做公共部分的抽取了 | ||
| minSize: 30000, | ||
| // 文件的最大尺寸,优先级:maxInitialRequest/maxAsyncRequests < maxSize < minSize, | ||
| // 需要注意的是这个如果配置了,umi.js 就可能被拆开,最后构建出来的 chunkMap 中可能就找不到 umi.js 了。 | ||
| maxSize: 0, | ||
| // 被提取的一个模块至少需要在几个 chunk 中被引用,这个值越大,抽取出来的文件就越小 | ||
| minChunks: 1, | ||
| // 在做一次按需加载的时候最多有多少个异步请求,为 1 的时候就不会抽取公共 chunk 了 | ||
| maxAsyncRequests: 10, | ||
| // 针对一个 entry 做初始化模块分隔的时候的最大文件数,优先级高于 cacheGroup,所以为 1 的时候就不会抽取 initial common 了。 | ||
| maxInitialRequests: 3, | ||
| // 缓存组 | ||
| // 注意:工程内至少在一个chunk中被引用才会拆出配置的文件 | ||
| cacheGroups: { | ||
| vendors: { | ||
| name: 'vendors', | ||
| chunks: 'all', | ||
| // 表示要过滤 modules,默认为所有的 modules,可匹配模块路径或 chunk 名字, | ||
| // 当匹配到某个 chunk 的名字时,这个 chunk 里面引入的所有 module 都会选中; | ||
| test: /[\\/]node_modules[\\/](react|react-dom|react-router|lodash|dva|moment|rc-select|rc-pagination)[\\/]/, | ||
| // 权重,数字越大表示优先级越高 | ||
| priority: -10, | ||
| }, | ||
| // 提取出antd文件 | ||
| antd: { | ||
| name: 'antd', | ||
| chunks: 'all', | ||
| test: /[\\/]node_modules[\\/](@ant-design|antd)[\\/]/, | ||
| priority: -11, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| }); | ||
| config | ||
| .plugin('replace') | ||
| .use(require('webpack').ContextReplacementPlugin) | ||
| .tap(() => { | ||
| return [/moment[/\\]locale$/, /zh-cn/]; | ||
| }); | ||
| }, | ||
| }); |
| /** | ||
| * 代理配置 | ||
| * https://umijs.org/zh-CN/config#proxy | ||
| */ | ||
| export default { | ||
| '/api': { | ||
| target: 'http://jsonplaceholder.typicode.com/', | ||
| changeOrigin: true, | ||
| pathRewrite: { '^/api': '' }, | ||
| }, | ||
| }; |
| /** | ||
| * 路由 | ||
| * https://umijs.org/zh-CN/config#routes | ||
| * https://umijs.org/zh-CN/docs/routing | ||
| */ | ||
| export default [{ path: '/demo', component: '@/pages/demo', title: '示例' }]; |
| { | ||
| "compilerOptions": { | ||
| "experimentalDecorators": true, | ||
| "baseUrl": ".", | ||
| "paths": { | ||
| "@/*": ["src/*"] | ||
| } | ||
| }, | ||
| "include": ["src/**/*"], | ||
| "exclude": ["node_modules", "dist", ".cache"] | ||
| } |
Sorry, the diff of this file is not supported yet
| { | ||
| "name": "react-template", | ||
| "version": "0.1.0", | ||
| "private": true, | ||
| "scripts": { | ||
| "start": "umi dev", | ||
| "build": "cross-env UMI_ENV=prod umi build", | ||
| "build:noCompress": "cross-env UMI_ENV=prod COMPRESS=none umi build", | ||
| "build:analyze": "cross-env UMI_ENV=prod ANALYZE=1 umi build", | ||
| "postinstall": "umi generate tmp", | ||
| "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'", | ||
| "lint": "npm run lint:script", | ||
| "lint:script": "eslint --ext .js --ext jsx src" | ||
| }, | ||
| "gitHooks": { | ||
| "pre-commit": "lint-staged", | ||
| "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" | ||
| }, | ||
| "lint-staged": { | ||
| "*.{js,jsx,less,md,json}": [ | ||
| "prettier --write" | ||
| ], | ||
| "src/**/*+(js|jsx)": "npm run lint" | ||
| }, | ||
| "dependencies": { | ||
| "@vtx/components": "latest", | ||
| "@vtx/hooks": "latest", | ||
| "ahooks": "^2.9.4", | ||
| "antd": "3.26.19", | ||
| "axios": "^0.21.0", | ||
| "classnames": "^2.2.6", | ||
| <%_ if(plugins.indexOf('echarts') > -1) { _%> | ||
| "echarts": "^4.6.0", | ||
| "echarts-for-react": "^2.0.15-beta.1", | ||
| <%_ } _%> | ||
| "lodash": "^4.17.20", | ||
| "react": "^16.12.0", | ||
| "react-dom": "^16.12.0", | ||
| "umi": "^3.3.7", | ||
| "updeep": "^1.2.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@commitlint/cli": "^11.0.0", | ||
| "@commitlint/config-conventional": "^11.0.0", | ||
| "@umijs/preset-react": "1.x", | ||
| "@umijs/test": "^3.2.28", | ||
| "@vtx/eslint-config-vortex": "^1.1.0", | ||
| "babel-eslint": "^10.1.0", | ||
| "cross-env": "^7.0.2", | ||
| "eslint": "^7.18.0", | ||
| "eslint-plugin-react": "^7.22.0", | ||
| "lint-staged": "^10.0.7", | ||
| "prettier": "^1.19.1", | ||
| "yorkie": "^2.0.0" | ||
| } | ||
| } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
| Object.setPrototypeOf||{__proto__:[]}instanceof Array?Object.setPrototypeOf=function setProtoOf(obj,proto){return obj.__proto__=proto,obj}:Object.setPrototypeOf=function mixinProperties(obj,proto){for(var prop in Object.defineProperty(obj,"__proto__",{value:proto}),proto)obj.hasOwnProperty(prop)||(obj[prop]=proto[prop]);return obj}; | ||
| window.console=window.console||function(){var c={};return c.log=c.warn=c.debug=c.info=c.error=c.time=c.dir=c.profile=c.clear=c.exception=c.trace=c.assert=function(){},c}(); |
Sorry, the diff of this file is too big to display
| # umi project | ||
| ## Getting Started | ||
| Install dependencies, | ||
| ```bash | ||
| $ yarn | ||
| ``` | ||
| Start the dev server, | ||
| ```bash | ||
| $ yarn start | ||
| ``` |
| import * as React from 'react'; | ||
| /** | ||
| * 此文件不可随意删除 | ||
| * 此处文件用于禁用掉每次刷新路由时出现的 loading... 状态 | ||
| * https://github.com/umijs/umi/issues/5688 | ||
| */ | ||
| const Loading = () => <></>; | ||
| export default Loading; |
| html, | ||
| body, | ||
| :global(#root) { | ||
| height: 100%; | ||
| margin: 0; | ||
| } |
| export default {}; |
| import React from 'react'; | ||
| import { connect } from 'umi'; | ||
| import styles from './index.less'; | ||
| import { Spin, Pagination } from 'antd'; | ||
| import moment from 'moment'; | ||
| import { VtxDatePicker } from '@vtx/components'; | ||
| const Demo = props => { | ||
| const { loading } = props; | ||
| return ( | ||
| <div> | ||
| {moment().format('YYYY')} | ||
| <Spin spinning={loading} /> | ||
| <Pagination showSizeChanger /> | ||
| <h1 className={styles.title}>Page index</h1> | ||
| <VtxDatePicker /> | ||
| </div> | ||
| ); | ||
| }; | ||
| export default connect(({ demo, loading }) => ({ | ||
| demo, | ||
| loading: loading.effects['demo/query'], | ||
| }))(Demo); |
| .normal { | ||
| } | ||
| .title { | ||
| background: rgb(121, 242, 157); | ||
| } |
| import u from 'updeep'; | ||
| import { demoService } from '@/service/demoService'; | ||
| export default { | ||
| namespace: 'demo', | ||
| state: { | ||
| page: 1, | ||
| }, | ||
| effects: { | ||
| *query({ payload = {} }, { call }) { | ||
| yield call(demoService.page); | ||
| }, | ||
| }, | ||
| reducers: { | ||
| updateState(state, action) { | ||
| return u(action.payload, state); | ||
| }, | ||
| }, | ||
| subscriptions: { | ||
| setup({ dispatch, history }) { | ||
| return history.listen(({ pathname }) => { | ||
| if (pathname === '/demo') { | ||
| // TODO | ||
| } | ||
| }); | ||
| }, | ||
| }, | ||
| }; |
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <meta charSet="utf-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
| <title><%= title%></title> | ||
| </head> | ||
| <body> | ||
| <div id="root"></div> | ||
| <script src="./resources/lib/jquery.min.js"></script> | ||
| <script src="./resources/lib/polyfill-ie.min.js"></script> | ||
| <script src="./resources/lib/polyfill.min.js"></script> | ||
| </body> | ||
| </html> |
| import http from '@/utils/request'; | ||
| export const demoService = (() => { | ||
| return { | ||
| page: params => { | ||
| return http.get('/demo', { body: params }); | ||
| }, | ||
| }; | ||
| })(); |
| import axios from 'axios'; | ||
| // 安装axios的同时会同步安装qs包 https://www.npmjs.com/package/qs | ||
| import qs from 'qs'; | ||
| import isObject from 'lodash/isObject'; | ||
| import pickBy from 'lodash/pickBy'; | ||
| import { message } from 'antd'; | ||
| import { getUrlParam } from './util'; | ||
| // 默认30秒超时 | ||
| const SECOND = 30; | ||
| const MILL_SECOND = 1000; | ||
| const { token } = getUrlParam(); | ||
| /** | ||
| * 基于 axios 封装的请求封装 | ||
| * axios文档 http://www.axios-js.com/zh-cn/docs/ | ||
| * 支持 Get 和 Post 请求 | ||
| */ | ||
| class Http { | ||
| constructor(options) { | ||
| // 创建axios实例 | ||
| this.instance = this._createAxios(options); | ||
| } | ||
| // 初始化 | ||
| _createAxios(options) { | ||
| // 创建实例 | ||
| let instance = axios.create({ | ||
| // `timeout` 指定请求超时的毫秒数(0 表示无超时时间) | ||
| // 如果请求话费了超过 `timeout` 的时间,请求将被中断 | ||
| timeout: MILL_SECOND * SECOND, | ||
| headers: { | ||
| Authorization: token ? `Bearer ${token}` : '', | ||
| 'Cache-Control': 'no-cache', | ||
| }, | ||
| ...options, | ||
| }); | ||
| instance.interceptors.response.use(this._responseHandler, this._errorHandler); | ||
| return instance; | ||
| } | ||
| /** | ||
| * get 请求 | ||
| * @param {*} url | ||
| * @param {*} options {body} | ||
| */ | ||
| get(url, options = {}) { | ||
| const { body = {} } = options; | ||
| // 过滤掉值为 '' || undefined || null 的对象属性 | ||
| const postData = isObject(body) | ||
| ? pickBy(body, function(value) { | ||
| return value !== '' && value !== undefined && value !== null; | ||
| }) | ||
| : {}; | ||
| return this.instance.get(url, { | ||
| params: { | ||
| ...postData, | ||
| }, | ||
| }); | ||
| } | ||
| /** | ||
| * post 请求 | ||
| * @param {*} url | ||
| * @param {*} options | ||
| */ | ||
| post(url, options = {}) { | ||
| const { body = {}, extraHeader = {} } = options; | ||
| const data = isObject(body) ? qs.stringify(body) : JSON.parse(body); | ||
| return this.instance.post(url, data, { | ||
| headers: extraHeader ? { operation: extraHeader.msg } : {}, | ||
| }); | ||
| } | ||
| /** | ||
| * 响应数据的处理 | ||
| * @param {*} response | ||
| */ | ||
| _responseHandler(response) { | ||
| const { status, data, statusText } = response; | ||
| if (status >= 200 && status < 300) { | ||
| if (data.result === 0) { | ||
| return data; | ||
| } else { | ||
| message.error(data.msg || '请求信息错误'); | ||
| } | ||
| } | ||
| const error = new Error(statusText); | ||
| error.response = response; | ||
| throw error; | ||
| } | ||
| /** | ||
| * 请求错误处理 | ||
| * @param {*} error | ||
| */ | ||
| _errorHandler(error) { | ||
| if (error.response) { | ||
| let msg; | ||
| switch (error.response.status) { | ||
| case 404: | ||
| msg = '接口请求不存在!错误码【404】。'; | ||
| break; | ||
| case 500: | ||
| msg = '服务端应用接口异常!错误码【500】。'; | ||
| break; | ||
| default: | ||
| msg = '请求错误,请检查或刷新重试!'; | ||
| break; | ||
| } | ||
| message.error(msg); | ||
| } else { | ||
| message.error('服务不可用'); | ||
| } | ||
| } | ||
| // 获取实例 | ||
| getInstance() { | ||
| return this.instance; | ||
| } | ||
| } | ||
| const http = new Http(); | ||
| export default http; |
| import qs from 'qs'; | ||
| export const getUrlParam = key => { | ||
| const params = qs.parse(location.href.split('?')[1]); | ||
| return key ? params[key] : params; | ||
| }; |
+7
-1
@@ -8,2 +8,7 @@ const fs = require('fs'); | ||
| const tips = { | ||
| umi: '推荐使用', | ||
| roadhog: '已废弃' | ||
| } | ||
| const generators = fs | ||
@@ -17,3 +22,3 @@ .readdirSync(`${__dirname}/generators`) | ||
| return { | ||
| name: `${f.padEnd(15)}`, | ||
| name: `${f}(${tips[f]})`, | ||
| value: f, | ||
@@ -63,2 +68,3 @@ short: f, | ||
| choices: generators, | ||
| default: 'umi' | ||
| }, | ||
@@ -65,0 +71,0 @@ ]) |
+1
-1
| { | ||
| "name": "@vtx/cli", | ||
| "version": "1.2.2", | ||
| "version": "2.0.0", | ||
| "description": "基于dva-cli封装的脚手架工具", | ||
@@ -5,0 +5,0 @@ "bin": { |
Sorry, the diff of this file is not supported yet
| const BasicGenerator = require('../../BasicGenerator.js'); | ||
| class Generator extends BasicGenerator { | ||
| prompting() { | ||
| const prompts = [ | ||
| { | ||
| type: 'input', | ||
| name: 'title', | ||
| message: 'Package Name', | ||
| default: 'React Template', | ||
| }, | ||
| ]; | ||
| return this.prompt(prompts).then(props => { | ||
| this.prompts = props; | ||
| }); | ||
| } | ||
| writing() { | ||
| this.writeFiles({ | ||
| context: { | ||
| name: this.name, | ||
| ...this.prompts, | ||
| }, | ||
| filterFiles: f => { | ||
| return true; | ||
| }, | ||
| }); | ||
| } | ||
| } | ||
| module.exports = Generator; |
| # http://editorconfig.org | ||
| root = true | ||
| [*] | ||
| indent_style = space | ||
| indent_size = 4 | ||
| end_of_line = lf | ||
| charset = utf-8 | ||
| trim_trailing_whitespace = true | ||
| insert_final_newline = true | ||
| [*.md] | ||
| trim_trailing_whitespace = false | ||
| [Makefile] | ||
| indent_style = tab |
Sorry, the diff of this file is not supported yet
| module.exports = { | ||
| extends: ['@vtx/vortex', 'plugin:react/recommended'], | ||
| settings: { | ||
| react: { | ||
| version: 'detect', | ||
| }, | ||
| }, | ||
| globals: { | ||
| OPERATE_INFO: true, | ||
| }, | ||
| rules: { | ||
| 'react/prop-types': 'off', | ||
| }, | ||
| }; |
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
| # dependencies | ||
| /node_modules | ||
| # production | ||
| /dist | ||
| # misc | ||
| .DS_Store | ||
| npm-debug.log* | ||
| *.lock |
Sorry, the diff of this file is not supported yet
| module.exports = { | ||
| // 一行最多 100 字符 | ||
| printWidth: 100, | ||
| // 使用 4 个空格缩进 | ||
| tabWidth: 4, | ||
| // 使用单引号 | ||
| singleQuote: true, | ||
| // 句尾添加分号 | ||
| semi: true, | ||
| // 末尾需要逗号 | ||
| trailingComma: 'all', | ||
| // 换行符使用 lf | ||
| endOfLine: 'lf', | ||
| }; |
| export default {}; |
| { | ||
| "editor.formatOnSave": true, | ||
| "editor.defaultFormatter": "esbenp.prettier-vscode", | ||
| "css.validate": false, | ||
| "less.validate": false, | ||
| "scss.validate": false | ||
| } |
| var path = require('path'); | ||
| export default { | ||
| entry: 'src/index.js', | ||
| html: { | ||
| template: './public/index.ejs', | ||
| }, | ||
| proxy: { | ||
| '/api': { | ||
| target: 'http://jsonplaceholder.typicode.com/', | ||
| changeOrigin: true, | ||
| pathRewrite: { '^/api': '' }, | ||
| }, | ||
| }, | ||
| extraBabelPlugins: [ | ||
| ['import', { libraryName: 'antd', libraryDirectory: 'lib', style: 'css' }, 'antd'], | ||
| ['import', { libraryName: 'vtx-ui', camel2DashComponentName: false }, 'vtx-ui'], | ||
| [ | ||
| 'import', | ||
| { libraryName: 'lodash', libraryDirectory: '', camel2DashComponentName: false }, | ||
| 'lodash', | ||
| ], | ||
| ], | ||
| hash: true, | ||
| ignoreMomentLocale: true, | ||
| commons: [ | ||
| { | ||
| async: 'common', | ||
| children: true, | ||
| minChunks: 5, | ||
| }, | ||
| { | ||
| async: 'echarts', | ||
| children: true, | ||
| minChunks: function(module) { | ||
| return /echarts/.test(module.context); | ||
| }, | ||
| }, | ||
| { | ||
| async: 'lodash', | ||
| children: true, | ||
| minChunks: function(module) { | ||
| return /lodash/.test(module.context); | ||
| }, | ||
| }, | ||
| { | ||
| async: 'moment', | ||
| children: true, | ||
| minChunks: function(module) { | ||
| return /moment/.test(module.context); | ||
| }, | ||
| }, | ||
| { | ||
| name: 'manifest', | ||
| minChunks: 'Infinity', | ||
| }, | ||
| ], | ||
| alias: { | ||
| history: path.dirname(require.resolve('history/package.json')), | ||
| moment: path.dirname(require.resolve('moment/package.json')), | ||
| '@': path.resolve(__dirname, 'src'), | ||
| }, | ||
| env: { | ||
| development: { | ||
| extraBabelPlugins: ['dva-hmr'], | ||
| }, | ||
| production: { | ||
| extraBabelPlugins: ['transform-remove-console'], | ||
| }, | ||
| }, | ||
| }; |
| module.exports = { | ||
| extends: ['@commitlint/config-conventional'], | ||
| /** | ||
| * rule 由 name 和配置数组组成,如:'name: [0, 'always', 72]' | ||
| * 数组中第一位为 level, 可选0, 1, 2; 0为disable, 1为warning, 2为error | ||
| * 第二位为应用与否, 可选 always | never | ||
| * 第三位为 rule 的值 | ||
| */ | ||
| rules: { | ||
| 'type-enum': [ | ||
| 2, | ||
| 'always', | ||
| ['feature', 'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'release'], | ||
| ], | ||
| }, | ||
| }; |
| { | ||
| "compilerOptions": { | ||
| "baseUrl": ".", | ||
| "paths": { | ||
| "@src/*": ["src/*"] | ||
| } | ||
| }, | ||
| "include": ["src/**/*"], | ||
| "exclude": ["node_modules", "dist", ".cache"] | ||
| } |
Sorry, the diff of this file is not supported yet
| { | ||
| "private": true, | ||
| "scripts": { | ||
| "start": "cross-env BROWSER=none ESLINT=none roadhog dev", | ||
| "build": "cross-env ESLINT=none roadhog build", | ||
| "buildD": "cross-env NO_COMPRESS=none ESLINT=none roadhog build", | ||
| "lint": "npm run lint:script", | ||
| "lint:script": "eslint --ext .js --ext jsx src", | ||
| "prettier": "prettier --write \"src/**/*+(js|less|css|jsx)\"", | ||
| "prettier:check": "prettier --check \"src/**/*+(js|less|css|jsx)\"", | ||
| "pretty-quick": "pretty-quick" | ||
| }, | ||
| "husky": { | ||
| "hooks": { | ||
| "pre-commit": "lint-staged", | ||
| "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" | ||
| } | ||
| }, | ||
| "lint-staged": { | ||
| "src/**/*+(js|jsx|less|css)": "npm run prettier:check", | ||
| "src/**/*+(js|jsx)": "npm run lint" | ||
| }, | ||
| "engines": { | ||
| "install-node": "6.9.2" | ||
| }, | ||
| "dependencies": { | ||
| "antd": "^2.13.11", | ||
| "dva": "^2.1.0", | ||
| "dva-loading": "^2.0.5", | ||
| "immutable": "^3.8.2", | ||
| "lodash": "^4.17.10", | ||
| "moment": "^2.20.1", | ||
| "react": "^15.4.0", | ||
| "react-dom": "^15.4.0", | ||
| "updeep": "^1.0.0", | ||
| "vtx-ui": "latest" | ||
| }, | ||
| "devDependencies": { | ||
| "@commitlint/cli": "^11.0.0", | ||
| "@commitlint/config-conventional": "^11.0.0", | ||
| "@vtx/eslint-config-vortex": "^1.1.0", | ||
| "babel-plugin-dva-hmr": "^0.4.0", | ||
| "babel-plugin-import": "^1.6.3", | ||
| "babel-plugin-transform-remove-console": "^6.8.5", | ||
| "babel-plugin-transform-runtime": "^6.9.0", | ||
| "cross-env": "^5.1.3", | ||
| "css-split-webpack-plugin": "^0.2.5", | ||
| "eslint": "^7.11.0", | ||
| "eslint-config-umi": "^0.1.1", | ||
| "eslint-plugin-flowtype": "^2.34.1", | ||
| "eslint-plugin-import": "^2.6.0", | ||
| "eslint-plugin-jsx-a11y": "^5.1.1", | ||
| "eslint-plugin-react": "^7.1.0", | ||
| "history": "4.7.2", | ||
| "husky": "^4.3.0", | ||
| "lint-staged": "^10.4.2", | ||
| "prettier": "^1.19.1", | ||
| "pretty-quick": "^3.1.0", | ||
| "redbox-react": "^1.3.2", | ||
| "roadhog": "2.5.0-beta.4", | ||
| "webpack-parallel-uglify-plugin": "^1.1.0" | ||
| } | ||
| } |
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
| <title><%= title%></title> | ||
| </head> | ||
| <body> | ||
| <div id="root"></div> | ||
| <script src="./resources/js/gtmd-ie.min.js"></script> | ||
| <script src="./resources/js/jquery.min.js"></script> | ||
| <script src="./resources/js/polyfill.min.js"></script> | ||
| </body> | ||
| </html> |
| Object.setPrototypeOf||{__proto__:[]}instanceof Array?Object.setPrototypeOf=function setProtoOf(obj,proto){return obj.__proto__=proto,obj}:Object.setPrototypeOf=function mixinProperties(obj,proto){for(var prop in Object.defineProperty(obj,"__proto__",{value:proto}),proto)obj.hasOwnProperty(prop)||(obj[prop]=proto[prop]);return obj}; | ||
| window.console=window.console||function(){var c={};return c.log=c.warn=c.debug=c.info=c.error=c.time=c.dir=c.profile=c.clear=c.exception=c.trace=c.assert=function(){},c}(); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
| import React from 'react'; | ||
| export default class MyComponent extends React.Component { | ||
| constructor(props) { | ||
| super(props); | ||
| } | ||
| render() { | ||
| return <div></div>; | ||
| } | ||
| } |
| import dva from 'dva'; | ||
| import './index.less'; | ||
| import createLoading from 'dva-loading'; | ||
| // 1. Initialize | ||
| const app = dva(createLoading()); | ||
| // 2. Plugins | ||
| // app.use({}); | ||
| // 3. Model | ||
| // app.model(require('./models/example')); | ||
| // 4. Router | ||
| app.router(require('./router').default); | ||
| // 5. Start | ||
| app.start('#root'); |
| html, | ||
| body, | ||
| :global(#root) { | ||
| height: 100%; | ||
| } |
| import u from 'updeep'; | ||
| const STATE = {}; | ||
| export default { | ||
| namespace: 'example', | ||
| state: u(STATE, null), | ||
| subscriptions: { | ||
| setup({ dispatch, history }) { | ||
| // todo | ||
| }, | ||
| }, | ||
| effects: { | ||
| // 普通请求 | ||
| *fetch({ payload }, { call, put, select, take }) { | ||
| yield put({ type: 'takeLatest' }); | ||
| yield take('takeLatest/@@end'); //等takeLatest函数执行完毕后,才会执行此语句后面的代码 | ||
| }, | ||
| // 节流函数:短时间连续触发多次,此函数只执行一次 | ||
| throttle: [ | ||
| function*({ payload }, { call, put, select }) { | ||
| // todo | ||
| }, | ||
| { type: 'throttle', ms: 500 }, | ||
| ], | ||
| // 连续多次请求只返回最后一次结果 | ||
| takeLatest: [ | ||
| function*({ payload }, { call, put, select }) { | ||
| // todo | ||
| }, | ||
| { type: 'takeLatest' }, | ||
| ], | ||
| }, | ||
| reducers: { | ||
| updateState(state, action) { | ||
| return u(action.payload, state); | ||
| }, | ||
| resetState(state, action) { | ||
| return u(STATE, null); | ||
| }, | ||
| }, | ||
| }; |
| import React from 'react'; | ||
| import { Router, Route, Switch } from 'dva/router'; | ||
| import dynamic from 'dva/dynamic'; | ||
| const routes = [ | ||
| { | ||
| path: '/', | ||
| models: () => [import('./models/example')], | ||
| component: () => import('./routes/IndexPage'), | ||
| }, | ||
| ]; | ||
| function RouterConfig({ history, app }) { | ||
| return ( | ||
| <Router history={history}> | ||
| <Switch> | ||
| {routes.map(({ path, ...dynamics }, key) => ( | ||
| <Route | ||
| key={key} | ||
| exact | ||
| path={path} | ||
| component={dynamic({ | ||
| app, | ||
| ...dynamics, | ||
| })} | ||
| /> | ||
| ))} | ||
| </Switch> | ||
| </Router> | ||
| ); | ||
| } | ||
| export default RouterConfig; |
| import React from 'react'; | ||
| import { connect } from 'dva'; | ||
| import styles from './IndexPage.less'; | ||
| function IndexPage() { | ||
| return ( | ||
| <div className={styles.normal}> | ||
| <h1 className={styles.title}>Yay! Welcome to dva!</h1> | ||
| <div className={styles.welcome} /> | ||
| <ul className={styles.list}> | ||
| <li> | ||
| To get started, edit <code>src/index.js</code> and save to reload. | ||
| </li> | ||
| <li> | ||
| <a href="https://github.com/dvajs/dva-docs/blob/master/v1/en-us/getting-started.md"> | ||
| Getting Started | ||
| </a> | ||
| </li> | ||
| </ul> | ||
| </div> | ||
| ); | ||
| } | ||
| export default connect(({ example, loading }) => ({ | ||
| example, | ||
| loading, | ||
| }))(IndexPage); |
| .normal { | ||
| font-family: Georgia, sans-serif; | ||
| margin-top: 3em; | ||
| text-align: center; | ||
| } | ||
| .title { | ||
| font-size: 2.5rem; | ||
| font-weight: normal; | ||
| letter-spacing: -1px; | ||
| } | ||
| .welcome { | ||
| height: 328px; | ||
| background: url('@/assets/yay.jpg') no-repeat center 0; | ||
| background-size: 388px 328px; | ||
| } | ||
| .list { | ||
| font-size: 1.2em; | ||
| margin-top: 1.8em; | ||
| list-style: none; | ||
| line-height: 1.5em; | ||
| } | ||
| .list code { | ||
| background: #f7f7f7; | ||
| } |
| import request from '../utils/request'; | ||
| export function query() { | ||
| return request('/api/users'); | ||
| } |
| import isObject from 'lodash/isObject'; | ||
| import pickBy from 'lodash/pickBy'; | ||
| import { VtxUtil } from './util'; | ||
| import { message } from 'antd'; | ||
| /** | ||
| * 请求封装 | ||
| * 支持 Get 和 Post 请求 | ||
| */ | ||
| class Http { | ||
| constructor(config) { | ||
| this.defaults = config; | ||
| } | ||
| /** | ||
| * Get 请求 | ||
| * @param {string} url | ||
| * @param {object} [options] | ||
| * @return {object} | ||
| */ | ||
| get(url, options) { | ||
| const { body = {}, extraHeader } = options; | ||
| const { headers, extraQs = {} } = this.defaults; | ||
| const postData = isObject(body) | ||
| ? pickBy(body, function(value) { | ||
| return value !== '' && value !== undefined && value !== null; | ||
| }) | ||
| : {}; | ||
| const config = { | ||
| url, | ||
| type: 'get', | ||
| data: { ...extraQs, ...postData }, | ||
| dataType: 'json', | ||
| cache: false, | ||
| headers: { | ||
| ...headers, | ||
| ...this._mergePeration(extraHeader), | ||
| }, | ||
| }; | ||
| return this._request(config); | ||
| } | ||
| /** | ||
| * Post 请求 | ||
| * @param {string} url | ||
| * @param {object} options | ||
| */ | ||
| post(url, options) { | ||
| const { body, extraHeader } = options; | ||
| const config = { | ||
| url, | ||
| data: body, | ||
| type: 'post', | ||
| dataType: 'json', | ||
| contentType: `${ | ||
| isObject(body) ? 'application/x-www-form-urlencoded;' : 'application/json;' | ||
| }charset=UTF-8`, | ||
| cache: false, | ||
| headers: { | ||
| ...this._mergePeration(extraHeader), | ||
| }, | ||
| }; | ||
| return this._request(config); | ||
| } | ||
| /** | ||
| * 合并操作信息 | ||
| * @param {object} extraHeader 操作明细信息 | ||
| */ | ||
| _mergePeration(extraHeader) { | ||
| const { OPERATE_INFO } = this.defaults; | ||
| if (OPERATE_INFO && extraHeader) { | ||
| return { | ||
| operation: encodeURIComponent( | ||
| JSON.stringify({ | ||
| ...JSON.parse(OPERATE_INFO), | ||
| operation: extraHeader.msg, | ||
| }), | ||
| ), | ||
| }; | ||
| } | ||
| return {}; | ||
| } | ||
| _request(options) { | ||
| const t = this; | ||
| return new Promise((resolve, reject) => { | ||
| $.ajax({ | ||
| ...options, | ||
| success: function(response) { | ||
| resolve(response); | ||
| }, | ||
| error: function(XMLHttpRequest, textStatus, errorThrown) { | ||
| reject(XMLHttpRequest, textStatus, errorThrown); | ||
| }, | ||
| }); | ||
| }) | ||
| .then(response => { | ||
| return t._responseHandler(response); | ||
| }) | ||
| .catch(err => { | ||
| t._errorHandler(err); | ||
| return { data: null }; | ||
| }); | ||
| } | ||
| /** | ||
| * 响应处理 | ||
| * @param {*} res | ||
| */ | ||
| _responseHandler(res) { | ||
| if (res) { | ||
| if (res.result === 0) { | ||
| return res; | ||
| } else { | ||
| message.error(res.msg || '请求信息错误'); | ||
| } | ||
| } else { | ||
| message.error('请求数据失败,请刷新重试!'); | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * 请求错误处理 | ||
| * @param {*} err | ||
| */ | ||
| _errorHandler(err) { | ||
| if (err) { | ||
| let msg; | ||
| switch (err.status) { | ||
| case 404: | ||
| msg = '接口请求不存在!错误码【404】。'; | ||
| break; | ||
| case 500: | ||
| msg = '服务端应用接口异常!错误码【500】。'; | ||
| break; | ||
| default: | ||
| msg = '请求错误,请检查或刷新重试!'; | ||
| break; | ||
| } | ||
| message.error(msg); | ||
| } | ||
| } | ||
| } | ||
| const token = VtxUtil.getUrlParam('token'); | ||
| const tenantId = VtxUtil.getUrlParam('tenantId'); | ||
| const http = new Http({ | ||
| // 全局变量,记录操作信息,在 public/index.ejs 定义 | ||
| OPERATE_INFO: 'OPERATE_INFO' in window ? OPERATE_INFO : '', | ||
| extraQs: { tenantId }, | ||
| headers: { | ||
| tenantId, | ||
| Authorization: token ? `Bearer ${token}` : '', | ||
| }, | ||
| }); | ||
| export default http; |
| import React from 'react'; | ||
| export default class RouterComponent extends React.Component { | ||
| constructor(props) { | ||
| super(props); | ||
| this.namespace = ''; | ||
| this.updateState = this.updateState.bind(this); | ||
| this.act = this.act.bind(this); | ||
| } | ||
| // 更新state | ||
| updateState(obj, namespace) { | ||
| this.props.dispatch({ | ||
| type: `${namespace || this.namespace}/updateState`, | ||
| payload: obj, | ||
| }); | ||
| } | ||
| // 调用指定namespace内部函数 | ||
| act(functionName, obj = {}, namespace) { | ||
| return this.props.dispatch({ | ||
| type: `${namespace || this.namespace}/${functionName}`, | ||
| payload: obj, | ||
| }); | ||
| } | ||
| } |
| import moment from 'moment'; | ||
| import 'moment/locale/zh-cn'; | ||
| moment.locale('zh-cn'); | ||
| /* | ||
| 时间util类 | ||
| */ | ||
| export const VtxTime = { | ||
| /* | ||
| 获取时间 | ||
| time: 指定时间, 可以是任何类型的时间 | ||
| 默认:当前时间 | ||
| format: YYYY/MM/DD/HH/mm/ss | ||
| 类型: String | ||
| 默认: YYYY-MM-DD | ||
| return: 返回匹配的时间字符串 | ||
| */ | ||
| getFormatTime: ({ time = new Date(), format = 'YYYY-MM-DD' } = {}) => { | ||
| return moment(time).format(format); | ||
| }, | ||
| /* | ||
| 时间加减 | ||
| time: 指定时间, 可以是任何类型的时间 | ||
| 默认:当前时间 | ||
| format: YYYY/MM/DD/HH/mm/ss | ||
| 默认: YYYY-MM-DD | ||
| 类型: String | ||
| type: 加/减 | ||
| 默认: add | ||
| 类型: String | ||
| 参数: add/subtract | ||
| num: 正整数 | ||
| 默认: 0 | ||
| 类型: Number | ||
| dateType: 加减的类型,如y代表加减几年, 参数: y/M/w/d/h/m/s/ms 默认d (String) | ||
| return: 返回匹配的时间字符串 | ||
| */ | ||
| operationTime: ({ | ||
| time = new Date(), | ||
| format = 'YYYY-MM-DD', | ||
| type = 'add', | ||
| num = 0, | ||
| dateType = 'd', | ||
| } = {}) => { | ||
| const parseNum = VtxNum.replaceInt(num); | ||
| return moment(time, format) | ||
| [type](parseNum, dateType) | ||
| .format(format); | ||
| }, | ||
| /* | ||
| 获取毫秒时间 | ||
| time: 需要转换的时间 | ||
| 默认: 0 | ||
| return: 返回对应类型的时间 | ||
| */ | ||
| getMsTime: time => { | ||
| if (time) { | ||
| return new Date(time).getTime(); | ||
| } else { | ||
| return new Date().getTime(); | ||
| } | ||
| }, | ||
| }; | ||
| /* | ||
| 正则匹配 | ||
| */ | ||
| export const VtxRegex = { | ||
| /* | ||
| 验证是几位浮点数 数字 | ||
| num 需要验证的数字 | ||
| n 是数字几位 例如2 | ||
| */ | ||
| checkFloatNumber(num, n) { | ||
| let regex = new RegExp(`^-?(0|[1-9][0-9]*)(\.([0-9]?){${n}})?$`); | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是数字 | ||
| */ | ||
| checkNumber(num) { | ||
| let regex = /^-?(0|[1-9][0-9]*)(\.[0-9]*)?$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是正数 | ||
| */ | ||
| checkPositiveNumber(num) { | ||
| let regex = /^(0|[1-9][0-9]*)(\.[0-9]*)?$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是正整数 | ||
| */ | ||
| checkPositiveInteger(num) { | ||
| let regex = /^(0|[1-9][0-9]*)$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是正几位小数 | ||
| */ | ||
| checkIntegerFloatNumber(num, n) { | ||
| let regex = new RegExp(`^(0|[1-9][0-9]*)(\.([0-9]?){${n}})?$`); | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是负数 | ||
| */ | ||
| checkNegativeNumber(num) { | ||
| let regex = /^-(0|[1-9][0-9]*)(\.[0-9]*)?$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是负整数 | ||
| */ | ||
| checkNegativeInteger(num) { | ||
| let regex = /^-(0|[1-9][0-9]*)$/; | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证是否是负几位小数 | ||
| */ | ||
| checkNegativeIntegerFloatNumber(num, n) { | ||
| let regex = new RegExp(`^-(0|[1-9][0-9]*)(\.([0-9]?){${n}})?$`); | ||
| return regex.test(num); | ||
| }, | ||
| /* | ||
| 验证手机号码 | ||
| phone 需要验证的手机号码 | ||
| */ | ||
| checkCellphone(phone) { | ||
| let regex = /^1\d{10}$/; | ||
| return regex.test(phone); | ||
| }, | ||
| /* | ||
| 验证号码 | ||
| tel 需要验证的号码 | ||
| */ | ||
| checkTelphone(tel) { | ||
| let regex = /(^(\d{3,4}-)?\d*)$/; | ||
| return regex.test(tel); | ||
| }, | ||
| /* | ||
| 验证数组 | ||
| phone 需要验证的手机号码 | ||
| */ | ||
| checkArray(ary) { | ||
| return ary instanceof Array; | ||
| }, | ||
| }; | ||
| export const VtxNum = { | ||
| /* | ||
| 字符串转成 float类型的字符串 | ||
| str: 需要处理的字符串 (String) | ||
| return: 返回一个float类型的字符串 | ||
| */ | ||
| replaceFloat: str => { | ||
| let b = str.toString().split('.'); | ||
| if (!b[1]) { | ||
| if (str.indexOf('.') > -1) { | ||
| return `${b[0].replace(/[^0-9]/g, '') || 0}.`; | ||
| } else { | ||
| return b[0].replace(/[^0-9]/g, '') || 0; | ||
| } | ||
| } else { | ||
| if (!parseInt(b[1].replace(/[^0-9]/g, ''))) { | ||
| if (parseInt(b[1].replace(/[^0-9]/g, '')) == 0) { | ||
| return `${b[0].replace(/[^0-9]/g, '') || 0}.${b[1].replace(/[^0-9]/g, '')}`; | ||
| } else { | ||
| return b[0].replace(/[^0-9]/g, '') || 0; | ||
| } | ||
| } else { | ||
| if (b[0].length > 1) { | ||
| return `${b[0].replace(/[^0-9]/g, '').replace(/^0*/g, '') || 0}.${b[1].replace( | ||
| /[^0-9]/g, | ||
| '', | ||
| )}`; | ||
| } else { | ||
| return `${b[0].replace(/[^0-9]/g, '') || 0}.${b[1].replace(/[^0-9]/g, '')}`; | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| /* | ||
| 字符串转成 Int类型的字符串 | ||
| str: 需要处理的字符串 支持number类型 | ||
| return: 返回一个Int类型的字符串 | ||
| */ | ||
| replaceInt: str => { | ||
| return ( | ||
| str | ||
| .toString() | ||
| .split('.')[0] | ||
| .replace(/[^0-9]/g, '') | ||
| .replace(/^0*/g, '') || '0' | ||
| ); | ||
| }, | ||
| /* | ||
| 取小数后几位 | ||
| num: 需要处理的 数字 支持String类型 | ||
| count: 需要保留的位数 Number | ||
| return: 返回对应的float类型字符串 | ||
| */ | ||
| decimals: (num, count) => { | ||
| let nary = VtxNum.replaceFloat(num) | ||
| .toString() | ||
| .split('.'), | ||
| n = ''; | ||
| const decimal = parseInt(count); | ||
| if (decimal > 0) { | ||
| if (nary[1]) { | ||
| n = `${nary[0]}.${nary[1].substr(0, decimal)}`; | ||
| for (let i = 0; i < decimal - nary[1].length; i++) { | ||
| n = `${n}0`; | ||
| } | ||
| } else { | ||
| n = nary[0]; | ||
| for (let j = 0; j < decimal; j++) { | ||
| if (j == 0) n = `${n}.0`; | ||
| else n = `${n}0`; | ||
| } | ||
| } | ||
| } else { | ||
| n = nary[0]; | ||
| } | ||
| return n; | ||
| }, | ||
| }; | ||
| /* | ||
| 其他公共方法 | ||
| */ | ||
| export const VtxUtil = { | ||
| /* | ||
| 获取url中 参数的值 | ||
| key: 参数前面的key | ||
| return: 对应key的value | ||
| */ | ||
| getUrlParam(key) { | ||
| let paramObj = {}; | ||
| let matchList = window.location.href.match(/([^\?&]+)=([^&]+)/g) || []; | ||
| for (let i = 0, len = matchList.length; i < len; i++) { | ||
| let r = matchList[i].match(/([^\?&]+)=([^&]+)/); | ||
| paramObj[r[1]] = r[2]; | ||
| } | ||
| if (key) { | ||
| return paramObj[key]; | ||
| } else { | ||
| return paramObj; | ||
| } | ||
| }, | ||
| /* | ||
| 获取hash字符串 | ||
| */ | ||
| getHash() { | ||
| let h = location.hash, | ||
| xI = h.indexOf('/'), | ||
| wI = h.indexOf('?'); | ||
| return h.substring(xI + 1, wI); | ||
| }, | ||
| /* | ||
| 延迟时间 | ||
| time是延迟的时间 单位ms | ||
| */ | ||
| delay: time => { | ||
| return new Promise((resolve, reject) => { | ||
| setTimeout(() => { | ||
| resolve(); | ||
| }, time); | ||
| }); | ||
| }, | ||
| /* | ||
| 设置抬头 | ||
| title 设置的title名 | ||
| */ | ||
| setTitle: title => { | ||
| document.title = title; | ||
| }, | ||
| /* | ||
| 处理提交参数的前后空格 | ||
| */ | ||
| submitTrim(obj) { | ||
| if (typeof obj == 'object') { | ||
| let postData = {}; | ||
| for (let k in obj) { | ||
| postData[k] = typeof obj[k] == 'string' ? obj[k].trim() : obj[k]; | ||
| } | ||
| return postData; | ||
| } else { | ||
| return obj; | ||
| } | ||
| }, | ||
| /* | ||
| 数组去除重复 | ||
| 只限 数组中值是字符串或number的 | ||
| */ | ||
| ArraywipeOffRepetition(ary = []) { | ||
| let na = []; | ||
| for (let i = 0; i < ary.length; i++) { | ||
| if (na.indexOf(ary[i]) > -1) { | ||
| continue; | ||
| } else { | ||
| na.push(ary[i]); | ||
| } | ||
| } | ||
| return na; | ||
| }, | ||
| }; | ||
| /* | ||
| 前后端数据转换处理工具 | ||
| -----demo----- | ||
| const yourMapping = {a:'b'}; // 映射关系:原始key为a,转换后key替换为b | ||
| const rawData = {a:100,ss:500}; //原始数据(后端返回的数据) | ||
| const carDataConverter = new DataConverter(yourMapping); | ||
| const new_data = carDataConverter.getMappingData(rawData); // 结果: {b:100} | ||
| */ | ||
| export class DataConverter { | ||
| constructor(mapping) { | ||
| this.mapping = mapping; | ||
| this.reverseMap = this.getReverseMap(mapping); | ||
| } | ||
| getReverseMap(mapping) { | ||
| let new_map = {}; | ||
| for (let k in mapping) { | ||
| new_map[mapping[k]] = k; | ||
| } | ||
| return new_map; | ||
| } | ||
| /* 获取转换完成后的数据 | ||
| data: 【Object】需要转换的数据 | ||
| reverse: 【Bool】按照映射关系反向转换数据(默认正向转换) | ||
| filter:【Bool】是否只获取在映射关系表内的数据(true:只获取在映射关系表内的数据,false:除了转换数据保留原数据的其他属性) | ||
| */ | ||
| getMappingData(data, reverse = false, filter = true) { | ||
| let new_date = {}; | ||
| let mapping = reverse ? this.reverseMap : this.mapping; | ||
| for (let k in data) { | ||
| if (k in mapping) { | ||
| new_date[mapping[k]] = data[k]; | ||
| } else if (!filter) { | ||
| new_date[k] = data[k]; | ||
| } | ||
| } | ||
| return new_date; | ||
| } | ||
| } |
| var webpack = require('webpack'); | ||
| var CSSSplitWebpackPlugin = require('css-split-webpack-plugin/dist/index').default; | ||
| var ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin'); | ||
| // var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; | ||
| module.exports = function(webpackConfig) { | ||
| // adding plugins to your configuration | ||
| // css文件分割(For IE) | ||
| webpackConfig.plugins.push( | ||
| new CSSSplitWebpackPlugin({ | ||
| size: 3000, | ||
| }), | ||
| ); | ||
| if (process.env.NODE_ENV == 'production') { | ||
| // 代码压缩 | ||
| webpackConfig.plugins = webpackConfig.plugins.filter(function(plugin) { | ||
| return !(plugin instanceof webpack.optimize.UglifyJsPlugin); | ||
| }); | ||
| webpackConfig.plugins.push( | ||
| new ParallelUglifyPlugin({ | ||
| uglifyJS: { | ||
| output: { | ||
| comments: false, | ||
| ascii_only: true, | ||
| }, | ||
| warnings: false, | ||
| }, | ||
| cacheDir: './.cache', | ||
| }), | ||
| ); | ||
| // 打包分析工具 | ||
| // webpackConfig.plugins.push(new BundleAnalyzerPlugin()); | ||
| } | ||
| return webpackConfig; | ||
| }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
651406
54.2%74
89.74%2932
69.48%8
60%7
16.67%11
83.33%