├── .babelrc
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── 1.png
├── 2.png
├── 3.png
├── README.md
├── app.js
├── bin
├── build.js
├── dev.js
└── server.js
├── package-lock.json
├── package.json
├── readfiles.js
├── src
├── assets
│ ├── css
│ │ └── common.scss
│ └── image
│ │ ├── empty_ysd.png
│ │ └── timg.jpg
├── common
│ ├── App.vue
│ └── index.js
├── components
│ ├── alert.vue
│ ├── titlerefresher.vue
│ └── toast.js
├── features
│ ├── login
│ │ ├── home.vue
│ │ ├── main.js
│ │ └── router.js
│ ├── test
│ │ ├── container
│ │ │ ├── test.vue
│ │ │ └── test1.vue
│ │ ├── home.vue
│ │ ├── main.js
│ │ ├── module
│ │ │ └── test1.js
│ │ ├── router.js
│ │ └── store
│ │ │ └── index.js
│ └── test1
│ │ ├── container
│ │ └── test.vue
│ │ ├── home.vue
│ │ ├── main.js
│ │ ├── router.js
│ │ └── store
│ │ └── index.js
└── pluges
│ ├── filter.js
│ ├── service.js
│ ├── store.js
│ └── vuexMap.js
├── view
├── login.html
├── test.html
└── test1.html
├── webpack.dev.conf.js
├── webpack.prod.conf.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-0"],
3 | "plugins": [
4 | "transform-runtime",
5 | "transform-vue-jsx",
6 | "transform-decorators-legacy"
7 | ],
8 | "comments": false
9 | }
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | dist/
3 | node_modules/
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parserOptions: {
4 | sourceType: 'module'
5 | },
6 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
7 | extends: 'standard',
8 | parser: "babel-eslint",
9 | // required to lint *.vue files
10 | plugins: [
11 | 'html'
12 | ],
13 | // add your custom rules here
14 | 'rules': {
15 | "no-eval": 0,
16 | // allow paren-less arrow functions
17 | 'arrow-parens': 0,
18 | // allow debugger during development
19 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
20 | "eqeqeq": 0,//必须使用全等
21 | "no-multi-spaces":0,
22 | "indent":0,
23 | "comma-dangle": [2, "only-multiline"], //定义数组或对象最后多余的逗号
24 | "no-unused-expressions": [2, { "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true }]
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
--------------------------------------------------------------------------------
/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shuobeige11/vue-genection/007004427e04b3e493149e5828cb074fd245f2d5/1.png
--------------------------------------------------------------------------------
/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shuobeige11/vue-genection/007004427e04b3e493149e5828cb074fd245f2d5/2.png
--------------------------------------------------------------------------------
/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shuobeige11/vue-genection/007004427e04b3e493149e5828cb074fd245f2d5/3.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 基于VUE2.0, VUE-Route实现的多页脚手架
3 |
4 | 适用于混合式app下的多页面入口及分模块发布
5 |
6 | 多页下单路由配置基与 children 实现
7 |
8 | 
9 |
10 |
11 | 
12 |
13 |
14 |
15 |
16 | ### 服务端配置
17 |
18 | nginx:
19 |
20 | 
21 |
22 | node: (参考bin文件夹下dev.js配置: 基于express路由配置)
23 |
24 | ### 开发目录
25 | ```
26 | .
27 | ├── README.md
28 | ├── bin
29 | │ ├── dev.js
30 | │ └── build.js
31 | │ └── server.js
32 | ├── redfiles.js(遍历目录)
33 | ├── app.js
34 | ├── dist(打包目录)
35 | ├── webpack.dev.conf.js
36 | ├── webpack.prod.conf.js
37 | ├── package-lock.json
38 | ├── package.json
39 | ├── src
40 | │ ├── features
41 | │ ├── test
42 | | | └── container
43 | | | └── store
44 | | | └── App.vue
45 | | | └── home.vue
46 | | | └── router.js
47 | | | └── main.js
48 | │ ├── test2
49 | | | └── container
50 | | | └── store
51 | | | └── App.vue
52 | | | └── home.vue
53 | | | └── router.js
54 | | | └── main.js
55 | │ ├── components(公共组件)
56 | │ └── common(公共方法)
57 | │ └── pluges(中间件)
58 | ├── view
59 | │ ├── test.html
60 | │ ├── test2.html
61 | ```
62 |
63 |
64 |
65 |
66 |
67 | ----
68 |
69 | 启动程序
70 | ``` bash
71 |
72 | # serve with hot reload at localhost:8083
73 | npm run dev
74 |
75 | # build for production with minification
76 | npm run build
77 |
78 | ```
79 |
80 | ----
81 |
82 |
83 | ### 结语
84 | + 拓展方向(结合nuxt做服务端渲染)
85 | + 单页面下可以引入vuex
86 |
87 | ...
88 |
89 | 👍👍👍
90 |
91 |
92 | ----
93 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 |
2 | const express = require('express');
3 | const path = require('path');
4 | const bodyParser = require('body-parser');
5 | const ejs = require('ejs');
6 |
7 | const app = express();
8 |
9 |
10 | app.engine('html', ejs.__express);
11 | app.set('views', path.join(__dirname, 'view'));
12 | app.set('view engine', 'html');
13 |
14 | app.use(bodyParser.json());
15 | app.use(bodyParser.urlencoded({ extended: false }));
16 |
17 | app.use(express.static(path.join(__dirname, 'static')));
18 |
19 |
20 | //安全设置,
21 | //禁用x-powered-by 头
22 | //禁止任何frame,iframe,xss protections
23 |
24 |
25 | module.exports = app;
--------------------------------------------------------------------------------
/bin/build.js:
--------------------------------------------------------------------------------
1 | var webpack = require("webpack");
2 | var config = require("../webpack.prod.conf");
3 |
4 | var compiler = webpack(config, function(err, stats) {
5 | if (err) throw err;
6 | process.stdout.write(
7 | stats.toString({
8 | colors: true,
9 | modules: false,
10 | children: false,
11 | chunks: false,
12 | chunkModules: false
13 | })
14 | );
15 | });
16 |
--------------------------------------------------------------------------------
/bin/dev.js:
--------------------------------------------------------------------------------
1 | require("babel-register");
2 | require("babel-polyfill");
3 | require("./server");
4 |
5 | var webpack = require("webpack");
6 | var webpackDevMiddleware = require("webpack-dev-middleware");
7 | var webpackHotMiddleware = require("webpack-hot-middleware");
8 | var config = require("../webpack.dev.conf");
9 | var fileReder = require("../readfiles");
10 | var files = fileReder("./src/features");
11 | var proxyMiddleware = require("http-proxy-middleware");
12 | var proxyTable = require("./config/dev").default;
13 | proxyTable = proxyTable.proxyTable;
14 |
15 | var app = require("../app");
16 |
17 | var compiler = webpack(config);
18 |
19 | const serverOption = {
20 | publicPath: config.output.publicPath,
21 | stats: {
22 | colors: true,
23 | chunks: false
24 | }
25 | };
26 |
27 | Object.keys(proxyTable).forEach(context => {
28 | let options = proxyTable[context];
29 | if (typeof options === "string") {
30 | options = { target: options };
31 | }
32 | app.use(proxyMiddleware(options.filter || context, options));
33 | });
34 |
35 | app.use(webpackDevMiddleware(compiler, serverOption));
36 | app.use(webpackHotMiddleware(compiler));
37 | app.use((req, res, next) => {
38 | if (req.headers.accept.match("text/html")) {
39 | res.header("Content-Type", "text/html; charset=utf-8");
40 | return next();
41 | }
42 | return next();
43 | });
44 |
45 | files.forEach(data => {
46 | app.get("/" + data, (req, res) => {
47 | res.render(data);
48 | });
49 | app.get("/" + data + "/:siteId", (req, res) => {
50 | res.render(data);
51 | });
52 | app.get("/" + data + "/:siteId/:pageId", (req, res) => {
53 | res.render(data);
54 | });
55 | app.get("/" + data + "/:siteId/:pageId/:nameId", (req, res) => {
56 | res.render(data);
57 | });
58 | app.get("/" + data + "/:siteId/:pageId/nameId/nameId1", (req, res) => {
59 | res.render(data);
60 | });
61 | });
62 |
--------------------------------------------------------------------------------
/bin/server.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | var app = require('../app');
4 | var debug = require('debug');
5 | var http = require('http');
6 |
7 | var port = normalizePort(process.env.PORT || '8083');
8 | app.set('port', port);
9 |
10 | /**
11 | * Create HTTP server.
12 | */
13 |
14 | var server = http.createServer(app);
15 |
16 | /**
17 | * Listen on provided port, on all network interfaces.
18 | */
19 |
20 | server.listen(port);
21 | server.on('error', onError);
22 | server.on('listening', onListening);
23 |
24 | /**
25 | * Normalize a port into a number, string, or false.
26 | */
27 |
28 | function normalizePort(val) {
29 | var port = parseInt(val, 10);
30 |
31 | if (isNaN(port)) {
32 | // named pipe
33 | return val;
34 | }
35 |
36 | if (port >= 0) {
37 | // port number
38 | return port;
39 | }
40 |
41 | return false;
42 | }
43 |
44 | /**
45 | * Event listener for HTTP server "error" event.
46 | */
47 |
48 | function onError(error) {
49 | if (error.syscall !== 'listen') {
50 | throw error;
51 | }
52 |
53 | var bind = typeof port === 'string'
54 | ? 'Pipe ' + port
55 | : 'Port ' + port;
56 |
57 | // handle specific listen errors with friendly messages
58 | switch (error.code) {
59 | case 'EACCES':
60 | console.error(bind + ' requires elevated privileges');
61 | process.exit(1);
62 | break;
63 | case 'EADDRINUSE':
64 | console.error(bind + ' is already in use');
65 | process.exit(1);
66 | break;
67 | default:
68 | throw error;
69 | }
70 | }
71 |
72 | /**
73 | * Event listener for HTTP server "listening" event.
74 | */
75 |
76 | function onListening() {
77 | var addr = server.address();
78 | var bind = typeof addr === 'string'
79 | ? 'pipe ' + addr
80 | : 'port ' + addr.port;
81 | debug('test:server')('Listening on ' + bind);
82 | console.log('serve start on: %s', bind);
83 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vues",
3 | "version": "1.0.0",
4 | "description": "vues 2.0",
5 | "author": "weichangbin",
6 | "private": true,
7 | "scripts": {
8 | "dev": "cross-env CODE_ENV=dev node bin/dev.js",
9 | "build": "rimraf ./dist && node bin/build.js",
10 | "deploy_dev": "cross-env CODE_ENV=dev npm run build && ymm_upload -r ./dist -n ymm-boss-component -t dev -z 0",
11 | "deploy_beta": "cross-env CODE_ENV=beta npm run build:entry-all && ymm_upload -r ./dist -n ymm-boss-component -t beta -z 0",
12 | "deploy_prod": "cross-env CODE_ENV=production npm run build:entry-all && ymm_upload -r ./dist -n ymm-boss-component -t release -z 1",
13 | "test": "jest",
14 | "lint": "eslint --ext .js,.vue src test/e2e/specs"
15 | },
16 | "dependencies": {
17 | "axios": "^0.17.1",
18 | "babel": "^6.23.0",
19 | "babel-loader": "^7.1.5",
20 | "babel-plugin-component": "^1.1.0",
21 | "babel-plugin-transform-react-jsx": "^6.24.1",
22 | "element-ui": "^2.2.2",
23 | "eslint": "^5.4.0",
24 | "eslint-config-standard": "^12.0.0-alpha.0",
25 | "eslint-plugin-html": "^4.0.5",
26 | "eslint-plugin-import": "^2.14.0",
27 | "eslint-plugin-node": "^7.0.1",
28 | "eslint-plugin-promise": "^4.0.0",
29 | "eslint-plugin-standard": "^3.1.0",
30 | "file-loader": "^1.1.11",
31 | "html-webpack-plugin": "^2.30.1",
32 | "jest": "^22.0.5",
33 | "mint-ui": "^2.2.13",
34 | "transform-runtime": "0.0.0",
35 | "uglifyjs-webpack-plugin": "^1.2.2",
36 | "url-loader": "^0.6.2",
37 | "vue": "^2.5.17",
38 | "vue-loader": "^13.7.2",
39 | "vue-property-decorator": "^7.0.0",
40 | "vue-router": "^3.0.1",
41 | "vue-template-compiler": "^2.5.17",
42 | "vuex": "^3.0.1",
43 | "vuex-router-sync": "^5.0.0",
44 | "webpack": "^3.12.0"
45 | },
46 | "devDependencies": {
47 | "autoprefixer": "^6.7.7",
48 | "babel-core": "^6.26.0",
49 | "babel-eslint": "^7.2.3",
50 | "babel-helper-vue-jsx-merge-props": "^2.0.1",
51 | "babel-plugin-syntax-jsx": "^6.18.0",
52 | "babel-plugin-transform-decorators-legacy": "^1.3.5",
53 | "babel-plugin-transform-runtime": "^6.23.0",
54 | "babel-plugin-transform-vue-jsx": "^3.7.0",
55 | "babel-polyfill": "^6.26.0",
56 | "babel-preset-es2015": "^6.24.1",
57 | "babel-preset-stage-0": "^6.24.1",
58 | "babel-preset-stage-2": "^6.0.0",
59 | "babel-register": "^6.26.0",
60 | "bluebird": "^3.5.1",
61 | "body-parser": "^1.17.1",
62 | "cross-env": "^5.2.0",
63 | "css-loader": "^0.25.0",
64 | "ejs": "^2.6.1",
65 | "eslint-friendly-formatter": "^4.0.1",
66 | "eslint-loader": "^2.1.0",
67 | "express": "^4.16.3",
68 | "extract-text-webpack-plugin": "^1.0.1",
69 | "http-proxy-middleware": "^0.18.0",
70 | "json-loader": "^0.5.4",
71 | "node-sass": "^4.9.3",
72 | "sass-loader": "^6.0.7",
73 | "scss-loader": "0.0.1",
74 | "style-loader": "^0.16.1",
75 | "vue-style-loader": "^1.0.0",
76 | "webpack-dev-middleware": "^1.12.2",
77 | "webpack-hot-middleware": "^2.22.3"
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/readfiles.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const fs = require('fs')
3 |
4 | function readfiles(path) {
5 | return fs.readdirSync(path);
6 | }
7 |
8 | module.exports = paths => {
9 | let entry = []
10 | paths = path.resolve(__dirname, paths)
11 | if (fs.statSync(paths).isDirectory()) {
12 | let files = readfiles(paths)
13 | let states = fs.statSync(paths)
14 | files.forEach(function(file){
15 | if (states.isDirectory() && paths) {
16 | entry.push(file)
17 | }
18 | });
19 | entry = entry.filter(data => data != '.DS_Store')
20 | return entry
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/src/assets/css/common.scss:
--------------------------------------------------------------------------------
1 | html, body, div, span, header, section, div, p, ul, li, dl, dd, a, input, i, textarea {
2 | margin:0;
3 | padding:0;
4 | list-style:none;
5 | border:0;
6 | font-style:normal;
7 | -webkit-appearance: none;
8 | -webkit-tap-highlight-color: rgba(255,255,255,0);
9 | }
10 | em, dfn {
11 | font-style:normal
12 | }
13 | html {
14 | height: 100%;
15 | }
16 |
17 | body {
18 | font-family:Microsoft Yahei, sans-serif;
19 | line-height: 1.5;
20 | font-size: 12px;
21 | color: #444;
22 | user-select: none;
23 | text-size-adjust: 100%;
24 | width: 100%;
25 | overflow-x: hidden;
26 | background:#f3f3f3;
27 | height:100%;
28 |
29 |
30 | }
31 |
32 | a {
33 | color:#444;
34 | text-decoration:none
35 | }
--------------------------------------------------------------------------------
/src/assets/image/empty_ysd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shuobeige11/vue-genection/007004427e04b3e493149e5828cb074fd245f2d5/src/assets/image/empty_ysd.png
--------------------------------------------------------------------------------
/src/assets/image/timg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shuobeige11/vue-genection/007004427e04b3e493149e5828cb074fd245f2d5/src/assets/image/timg.jpg
--------------------------------------------------------------------------------
/src/common/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
25 |
26 |
--------------------------------------------------------------------------------
/src/common/index.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | codeMsg: ''
3 | }
4 |
5 | const getters = {
6 | codeMsg: state => state.codeMsg
7 | }
8 |
9 | const mutations = {
10 | API_FALID (state, { data }) {
11 | state.codeMsg = data
12 | },
13 | API_MSG_CLEAR (state) {
14 | state.codeMsg = ''
15 | }
16 | }
17 |
18 | const actions = {
19 | msgClear ({ commit, state }) {
20 | commit('API_MSG_CLEAR')
21 | },
22 | alertshow ({ commit, state }, data) {
23 | commit('API_FALID', { data })
24 | }
25 | }
26 |
27 | export default {
28 | state,
29 | getters,
30 | mutations,
31 | actions
32 | }
33 |
--------------------------------------------------------------------------------
/src/components/alert.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/components/titlerefresher.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
23 |
--------------------------------------------------------------------------------
/src/components/toast.js:
--------------------------------------------------------------------------------
1 | function show () {
2 | const loader = document.querySelector('.uiLoadingBlock')
3 | if (loader) {
4 | loader.setAttribute('class', 'uiLoadingBlock show')
5 | return
6 | }
7 | const htmlStr = `
8 |
9 |
`
10 | const div = document.createElement('div')
11 | div.setAttribute('class', 'uiLoadingBlock show')
12 | div.innerHTML = htmlStr
13 | document.body.appendChild(div)
14 | }
15 |
16 | function hide () {
17 | const loader = document.querySelector('.uiLoadingBlock')
18 | if (!loader) return
19 | loader.setAttribute('class', 'uiLoadingBlock')
20 | }
21 |
22 | function css () {
23 | return `.loading{
24 | display: flex;
25 | box-pack: center;
26 | box-align: center;
27 | text-align: center;
28 | height: 40px;
29 | }
30 | .uiLoading{
31 | width: 20px;
32 | height: 20px;
33 | display: block;
34 | background: url("../assets/img/loading_sprite.png");
35 | background-size: auto 20px;
36 | animation: am-rotate 1s steps(12) infinite;
37 | }
38 | .uiLoadingBright{
39 | width: 37px;
40 | height: 37px;
41 | display: block;
42 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA3gAAABKBAMAAAAbGutGAAAAGFBMVEUAAAD///////////////////////////8jfp1fAAAACHRSTlMAQPxyHw2o1YJriTUAABB5SURBVHja7JrLk5NAEMZNCXoFQ/SqqJtr4uziFdxEr6hBr7qsw9Un/Pv2QzaZnhmHKvdk0VqxLH81xfY3Xz+Id+aYY4455phjjjnmmGOOOeaYY4455rj1iL7/vC3o6noC1E2BivPbgtQEKF6uJkDpFKjaT0j5oZ4ANVOgd3kexj7m6zB0P1/fCcaHoQ9D97QOQ3d1OwFS6pagRZqGoSjNJkC7XRiKmyYgLn48yPNkMlT+M/RmGMog9LrTEyDNUO2BYvy4VCoMvVeqFpAdb9N0ApQFobB4hyni3c2/jClHeAL0Ik/c0HACPVh7IH0Bn4+GIcE/1m5hFgCxLgj1HkidQA+1D1qxeAS1pccpyQjhHz6oPIp3uXULE+9qgir8o0o9UFOzeCy0G7qX/zqKd3DpzE45O6a8aeogFOX5Y5sgRX6cQl9tgrLcsvPCEDsvGoZPTuhSbRFqCdLaC7EuDG2cUJWmDNWQLqU2Hs9lLF7pgTjL+xvnxWmaeGshi0dQaRPkkLOjeLudx8RXeV5yyol1Uy9OoHt5/swJvRyGMFSQIo8I9UNgJzYV+nlwj0lLpY6Q7r/4oJp0IUh/8Yl3Ay2UunBDVVWPzvNCB1KEnbdIPcNNw+Ltd+TnKvHJwoKQn3eosFuXT5Z4fog+n/vEC0MPdbch5zH0ywMVG3YeoV99uiDEOrt1IUUS+iSo8DqPIZbQB2UlO09AQryanYeo33k1Ow/RLPFl/OuJSWvvnPlkTHnjE+/jCfQ9zzduaBi+BaEPff957HlXXkjra0h2j7p0w+CG3hfqfCybRd9vfCPkOYtHfk58U8hqhFShHBB7ZDU6b6l80H63H52Xgs5B8aoKIJ8shI5XwjOL5OsT8YLQIndvFVTg+iC00Lon8Qhae6EWnQKjymIYBg+klGLnIa/dUKTUlnRBqG09EOSZnYe88kFZxs7jQ+3gArdn5wG/hE9v3WTxYjjUn3ESjw49+MZkNAml3F81yUkJQ/fz/KkTIZOEId3rhHre36CiBYicdw/t7A7IM0Aaoa777Nu8QTcSD1seQ3ak23SEPLqwSWp23oLs7K2b7LxFChNOQDy2szPiHGUZxdu7Ie48Ujw/xMXYGSjJpyD0UPefkAxAekPO4zPdcVmoDZVNxL0QKMy6cCP1Nj123lK1TojbU0nO4zP94rHzuJF66yYNLEiW/ow/R5LP9EBsgFcwTo5Vs3GuHSOU/9kIXdAw/CCIjAqMShxQpz/zku6HyCXkPHIzGsiGyCXsPN33+O8OiFzC4hVaE2Rni1zCS7riZc+V0gggFO+vUAxNj5w3tryqdIvHzqt4I9zVblkM8Q4CiuFkaj2Arm9mWGHSuGboDCGmedG0IWh6IPPZCD3Kn9pQpDsNMvd0pB8qWlCwpSMFREEQJBEhoHkvHL45oS3KfAO5ameMTW8BIB6JdnVD1Q5lpiN5hXQ3PWyPQC9T1E6dWxnnRMcAwpEZr5AeWWIG96idXDxenCF2BUmMX17wig6seG/zsr+Bigs8k6egRmxmCHVDT1BE0HswqVkM25LQ9m/QUt1ACiDY8ghamxC94YAk0uvkSPfXNC8NohjWiAIEnkTxENK9NqEMIZpYUoDQpzT/mMVwz+dl5KSYIdBZdLKbNX0HEE6wNvRinYxNr6kBylY8LwlozDhCd2jLi7K0MqsFTwyvIIkUDaEQBoS1ENYtgujMT0BCyPEQIb77DC2+i5Ez4onhtb4eoY2E2CmnUDf4offjtS6gQ0YdiifLnIQ0+F54ju/+ahyCQMFCF1raCaHsD7RESEG4du9xn8aWFy8Jkhk/1q0qRZkhfLLwfQCZKzCpHEfzn5iKcqwzSIJLxQIwXJ9Ad1vWrjGgrtMGBJZ4AaefCYU1JDK2ILkAIDQ2lIUPWhkQvSIYerkAEFSPjQ0F7PvWhKpqj/KMUEbTkm6FeLvT1hRltOq1SjQykoTyQioSpLYy498QvmmRNC1tU58sfDJAGYR0nliTseHBgwrnyTU5Ru1qub1pE3qDh/8yIZ4ZJPTFXMwKpcKQktDrAcKE0qVYk3F+1frCdF4moUvdtgISSUFIFfIVmUgKWlWppVpJXfKNCeFjrgKyHNLKWvmvgDJf7LPx5PY29KX9mPKVZa9LsaeIKQMbmW4N6LsNKQwL+iFfjUErq0+hbrAWwhSjNndMayGs8E4bJxWayrvIipjilPSUXY64aJ47Mp7Ip8xCslTQ8YQsfBGeiDtGkLTeT/mYEtKg3rW4PutSQqCehM4khHf6PACR9S7EQ/YSEneaBt22llCVCahlSFqvlPUBIK/1GFIwWIUyjg8ZhirHm5jXspv8qe5WRfohW7OMS0zM6ZOT9UW8b/UESKl2a0JrC3qrtsqA4BkTCxLdJNJUtm31MhNqBcRvqPanfx/LttVNBESKyx5wJrYUC3ptQ1XteHltUDTZON+c9KZ4tfPrgtb0/k8XVAjoWiLc5oPQpShbLwcHVIk5rtAXzu+9dwGI24n5jATZ6pnQypnxtVk2J0Du19fRldlz4sYFdaKd1C6oMDvFYuuA4kkQ6BKGluo8DFE7sSHZ9kwoc0EHU7zIhvhWB6Hou5nxaDdFlr3nq4DNhP92oydByQRI3RYUpeUtQfFuCgS6hKMJIzLjfmiO/zYqMaU6dzheD0XUEGLOcX9tEYKiFCIRU7kNia7e7A9NGMIIQXHMlpKLe1UG/+ceRClHficUyjhCdQg6wM9cy712+GILmmb1EdIYF7IBYJxMDy6ooTCmSIiN/DIRoxRQYkJXubl3vE0xAtAhFULxNmiuFNEOo5Z9GaM073Pjgtoj9CrH+GXvrKcrxRuCRMaXU6BULq0diffDunXGvSu6Tvddaw3O8Ks+Qhrjs7Cw+JkVxdbeaE6/1ltOgVKKzAV9MitGJqCB4ggdYAOA3yakO/yZN+IWNqLBUxwhvoVPTUhRhCBxX68YErLI+/qbnfPpbRoIojgoNueYbuBKBUqutZyaqy2acF3UljPBqn0mkdyvj2eeU2ffrnGFKv5IXbhAfnGcHc/u7O57wTdpiTJJaU6oupXlNwfvRv4UA1TnXaumgld1LaNDK23vTqCztPtLZ4kEJenZGe0H+pB+j9K4EL7y8Bhc6RjCwWtl+/obB4+gXNoA4eNXLpQJk10QtKTgyReegpIk7dp8OvNMMmSebuU29YGCR6NNXlHmSfv7mZeUT5h59u9mXorMm5jzJPUm5zzZRfu9Oe/yz8158k0m5rzb/3bOG682fYiajV/c/uFqk6GnqDax32DD0NNXmwxNV5sMPbfn9tz+gXZdz92NeBuCMjr0C0FfANF2HEOpC92GoBv3Jj4vi+C45UDbliHcxDTEN7GtQtBX9xTuUxi6d6EsBF23DnSd2keExYdQNTm78UGlaJS7UJlcBSAqRjArTUCYXhmijfagNjcu3Ypl70NwaExCfBMNCnDqJ/LEoLZmaO9C+TQEFZUP0Qmqr/JF0dTu6HRpEYBqFzLJJiRNTln34UN0F0FzBM3XLyHpoFYaE4b4IIcgPIV8D3SsC4hq2fd0rLuehupHQKjACeoEOQeCFiH5cuPGBboPFnVQ8EqTWIboCFXXvwGIg8cFIQQ5zumoL+mAqGMTgnhFMwnFfP4NzQ7LlzkubeMdorz1oLz2IT4kh2aHwkKajhjSEBpZ5R7ufN0HQbyGExma8bQ2VXbh9xxDKW6UynneTEgAkaSDN4KKIMTlNUPLYkJM9dFXVHzFGo40O9U4xJodhniZRz3O629fs4Pkbyvr6T4MDZp5zpARgwQ/Gqn1uq4gKCXI1zLFibRxSQcg2vliCE2kC5spKLDzdY/nnjJ2aT3Nzs6B9gSRZoegcc0OFKgHgjwt06xRy050zIbSkO5DIewkRND4d4DRQcsYuniVdVBSDBLjeNONnHwHaQG1JfrN130g8YpBSBnbfs/B053Y4YD0zQHQKpR4cnmFdiEIn/+ymQ/QVlLP2zedD6fNnwTqolcztDqFxFoGzY4P5aeQ9B0/Pe1pWNbQ7GT0WxlNfQn5fp8ZBdb3tAUrEJT5MFFDiuZA3ecvBFofIeh3veAtBmU+nNYxB08HzUHCrK+K6tZS6hdwVfSFyAVD+io+wOKfDkQz3mudrABh4LS0fX53AonWSTd9X4Sgc0A63b2B9pohKMsBYeDk7XOE5ViteBAyb6fjYqVqfjitYw4eSiZ5r6r5IUNm3YcmNXwBZZeBxiww7RFkMK1CzY9R1c88g2ISan64SPduvkQm2eD6AsHbzpBc/xbXVyfGLAzBnyH/G+cPUONl3vkAqUsetSRBPxRaAlIlZJS7mTcDpJ6O7FLG1TuNDmeehKVuK3Vi9GGRvnWns8piZBYfjVCpPtaLAJQpkMIVIdDGgbIUUCq9L9CVdp9le4i8UwHz4BmkxUJ/+VKAzTG2M1oHlKa3EEjvS7+tGMLYjdRSe9Osh/YuJJfXC4i9SaClQO5iId7LNDV7gDCqzmoX+t5DS/VAzRDbl/U6AN0rUGnX40dJHKg5WE2aAyDEFj9KQnYq8dnv1MF2FCPGHgSlnTrYSGfI0FodbLExY5C8bmA/xHmuB+nEWpoFHGx9Yt6EjYwIHuSfA8SppZ5Bgngl8P5XUGQdqF9LxGHoXN2HUYO1hAdBSvlDjYVRXQEKhqXdAcoqJyy8BL+A/fDMXS/SakQhdXwufuEzhv2wdNTZlFnpHPbDG7caJXl3geBRNUrVpI6rOpN9CCJ4P9y6BJE0/9sktH+APtL+B0Hw/eYyboahRo4Utw0svWOQmD9gHaWdDSpIKovgYdwcM+8fIapGCULwIpOYEUjWkci8Ua81Rk0JHhU0bELF61oHrIIM3o4uJ4hqwOLxkFQU7fjPABRw3L9yqlGuJi3iIp0/Fpam7qBKIFSjobaVvS/EhUTcrE9G5mHcDEPpT3bOYKVhIIqiFTKuXUh/wW0DfkAKzT4u3AvFfIDg/+vLGRmFHF6FUoQ6C6XlDIW53Nu06buP9CV8QvL7K1IT523ictDKu0bEc+thXMSraSepiXgKEYg51NpMyE2FcF58iF6FSE2c181WL7KNi0kUdlk2kZqIF38lN2knAdLcpJ0knBfQ/Tq03FbFeZqbkboDHUEcv8/uI56n3XMTz6FIzRR6axC56RAVQVvLTZplaJnZHqX9Z44fYiCev511tJOgi3RU0E6C87iYF6in+Icp3FXxCu0kOM9yk1FtnOfiMYuGeNoKQuhy5AZRGlOh2xyiOUGgh6k6z6pDaJahZUYgvjydA4rYjNzs18VjN+IVES+ebxDiGYTzijiPzThPbhuxufXiqXiHJl7n4k1VPIUYjgfiQQ5F8ClE10Wc/7oubMZ5RcRDFpzH8IbE5o++wjtJxApRRegQzlv+DRKbQPtJ7+oyFIN4PiXAZsSLtHtPxHOIMfsc2n1B4a1Xh3Be5OaLdLQFFM5boJ3IAjQPy8muQoxqI57NtfB8g8rBIZwX0CjQ4XudqF5IgvJCk0CxGfEi8IWaWoGrQjf9b6GuVwjnZRDOC4iDMOhYoY2vqkuyqJlJFuLl0D6HuvEcRb7tyC8FEZvJwnk5NA9nKlh+umwLczmxhfnaG7T/ZP95ObH//Nq76//XR3twSAAAAAAg6P9rZ1gAAAAAeAQneKLgE3JcPgAAAABJRU5ErkJggg==");
43 | background-size: auto 37px;
44 | animation: am-rotate2 1s steps(12) infinite;
45 |
46 | }
47 | .loading .uiLoading{margin: 10px;}
48 | .uiLoadingBlock{
49 | position: fixed;
50 | top: 0;
51 | width: 100%;
52 | height: 100%;
53 | z-index: 100000;
54 | display:flex;
55 | align-items: center;
56 | justify-content: center;
57 | box-orient: horizontal;
58 | box-pack: center;
59 | box-align: center;
60 | background: rgba(0,0,0,.4);
61 | background: rgba(0,0,0,0);
62 | display:none;
63 |
64 | }
65 |
66 | .uiLoadingBlock .uiLoadingCnt{
67 | width: 86px;
68 | height: 86px;
69 | display: flex;
70 | text-align: center;
71 | align-items: center;
72 | background: rgba(0,0,0,.65);
73 | border-radius: 6px;
74 | color: #fff;
75 |
76 | }
77 | .uiLoadingBlock .uiLoadingBright{
78 | margin:0 auto
79 | }
80 |
81 | .uiLoadingBlock.show{
82 | display: flex;
83 | }
84 |
85 | @-webkit-keyframes am-rotate {
86 | from {
87 | background-position: 0 0;
88 | }
89 |
90 | to {
91 | background-position: -240px 0;
92 | }
93 | }
94 | @-webkit-keyframes am-rotate2 {
95 | from {
96 | background-position: 0 0;
97 | }
98 |
99 | to {
100 | background-position: -444px 0;
101 | }
102 | }`
103 | }
104 |
105 | export default {
106 | show,
107 | hide
108 | }
109 |
--------------------------------------------------------------------------------
/src/features/login/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
15 |
22 |
--------------------------------------------------------------------------------
/src/features/login/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import MintUI from 'mint-ui'
4 | import axios from 'axios'
5 | import Router from './router'
6 | import Home from './Home'
7 |
8 | Vue.use(VueRouter)
9 | Vue.use(plugin)
10 | Vue.use(MintUI)
11 |
12 | const router = new VueRouter({
13 | routes: Router()
14 | })
15 |
16 | router.beforeEach((to, from, next) => {
17 | // 更改iframe src fix bug
18 | if (document.getElementById('title_refresher')) {
19 | let titleRefresher = document.getElementById('title_refresher')
20 | titleRefresher.src = ''
21 | }
22 | next()
23 | })
24 |
25 | new Vue({
26 | router,
27 | render: h => h(Home)
28 | }).$mount('#app')
29 |
30 | function plugin (Vue) {
31 | if (plugin.installed) {
32 | return
33 | }
34 | plugin.installed = true
35 | Object.defineProperties(Vue.prototype, {
36 | axios: {
37 | get () {
38 | return axios
39 | }
40 | }
41 | })
42 | }
43 | if (typeof window !== 'undefined' && window.Vue) {
44 | window.Vue.use(plugin)
45 | }
46 |
--------------------------------------------------------------------------------
/src/features/login/router.js:
--------------------------------------------------------------------------------
1 | const login = resolve => {
2 | require.ensure(['./home'], () => {
3 | resolve(require('./home'))
4 | })
5 | }
6 | const routes = [
7 | {
8 | path: '/login',
9 | component: login
10 | }
11 | ]
12 |
13 | export default () => routes
14 |
--------------------------------------------------------------------------------
/src/features/test/container/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/features/test/container/test1.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/features/test/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/features/test/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 | import MintUI from 'mint-ui'
4 | import axios from 'axios'
5 | import services from '../../pluges/service'
6 | import { store } from './store'
7 | import Router from './router'
8 | import App from '../../common/App'
9 |
10 | services(store)
11 | Vue.use(VueRouter)
12 | Vue.use(plugin)
13 | Vue.use(MintUI)
14 |
15 | const router = new VueRouter({
16 | routes: Router()
17 | })
18 | router.beforeEach((to, from, next) => {
19 | if (document.getElementById('title_refresher')) {
20 | let titleRefresher = document.getElementById('title_refresher')
21 | titleRefresher.src = ''
22 | }
23 | next()
24 | })
25 |
26 | new Vue({
27 | router,
28 | store,
29 | render: h => h(App)
30 | }).$mount('#app')
31 |
32 | function plugin (Vue) {
33 | if (plugin.installed) {
34 | return
35 | }
36 | plugin.installed = true
37 | Object.defineProperties(Vue.prototype, {
38 | axios: {
39 | get () {
40 | return axios
41 | }
42 | }
43 | })
44 | }
45 | if (typeof window !== 'undefined' && window.Vue) {
46 | window.Vue.use(plugin)
47 | }
48 |
--------------------------------------------------------------------------------
/src/features/test/module/test1.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | const state = {
4 | list: []
5 | }
6 |
7 | const getters = {
8 | list: state => state.list
9 | }
10 |
11 | const actions = {
12 | async getMessage () {
13 | let r = await axios.get('/')
14 | console.log(r)
15 | }
16 | }
17 |
18 | const mutations = {
19 | GET_API_TEST (state, data) {
20 | state.list = data
21 | }
22 | }
23 |
24 | export default {
25 | state,
26 | getters,
27 | actions,
28 | mutations
29 | }
30 |
--------------------------------------------------------------------------------
/src/features/test/router.js:
--------------------------------------------------------------------------------
1 | const testRoute = resolve => {
2 | require.ensure(['./home'], () => {
3 | resolve(require('./home'))
4 | })
5 | }
6 | const route2 = resolve => {
7 | require.ensure(['./container/test'], () => {
8 | resolve(require('./container/test'))
9 | })
10 | }
11 |
12 | const route1 = resolve => {
13 | require.ensure(['./container/test1'], () => {
14 | resolve(require('./container/test1'))
15 | })
16 | }
17 |
18 | const routes = [
19 | {
20 | path: '/test',
21 | component: testRoute,
22 | children: [{
23 | path: 'test1',
24 | component: route1
25 | }, {
26 | path: 'test2',
27 | component: route2
28 | }]
29 | }
30 | ]
31 |
32 | export default () => routes
33 |
--------------------------------------------------------------------------------
/src/features/test/store/index.js:
--------------------------------------------------------------------------------
1 | import stores from '../../../pluges/store'
2 | import test1 from '../module/test1'
3 | export const store = stores({
4 | test1
5 | })
6 |
--------------------------------------------------------------------------------
/src/features/test1/container/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
14 |
--------------------------------------------------------------------------------
/src/features/test1/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/features/test1/main.js:
--------------------------------------------------------------------------------
1 |
2 | import Vue from 'vue'
3 | import VueRouter from 'vue-router'
4 | import Mint from 'mint-ui'
5 | import services from '../../pluges/service'
6 | import { store } from './store'
7 | import Router from './router'
8 | import App from '../../common/App'
9 | Vue.use(VueRouter)
10 | Vue.use(services)
11 | Vue.use(Mint)
12 |
13 | const router = new VueRouter({
14 | routes: Router(),
15 | mode: 'history'
16 | })
17 |
18 | router.beforeEach((to, from, next) => {
19 | // 更改iframe src fix bug
20 | if (document.getElementById('title_refresher')) {
21 | let titleRefresher = document.getElementById('title_refresher')
22 | titleRefresher.src = ''
23 | }
24 | next()
25 | })
26 |
27 | new Vue({
28 | router,
29 | store,
30 | render: h => h(App)
31 | }).$mount('#app')
32 |
--------------------------------------------------------------------------------
/src/features/test1/router.js:
--------------------------------------------------------------------------------
1 | const testRoute = resolve => {
2 | require.ensure(['./home'], () => {
3 | resolve(require('./home'))
4 | })
5 | }
6 | const route2 = resolve => {
7 | require.ensure(['./container/test'], () => {
8 | resolve(require('./container/test'))
9 | })
10 | }
11 | const routes = [
12 | {
13 | path: '/test1',
14 | component: testRoute,
15 | children: [{
16 | path: 'test1',
17 | component: route2
18 | }]
19 | }
20 | ]
21 |
22 | export default () => routes
23 |
--------------------------------------------------------------------------------
/src/features/test1/store/index.js:
--------------------------------------------------------------------------------
1 | import stores from '../../../pluges/store'
2 | export const store = stores({})
3 |
--------------------------------------------------------------------------------
/src/pluges/filter.js:
--------------------------------------------------------------------------------
1 | const REGEXP_TELEPHONE = /^\d{3}-\d{8}$|^\d{4}-\d{7,8}$/
2 | const REGEXP_MOBILE = /^1[34578]\d{9}$/
3 | const REGEXP_USC = /^[^_IOZSVa-z\W]{2}\d{6}[^_IOZSVa-z\W]{10}$/
4 | import moment from 'moment'
5 |
6 | /**
7 | *
8 | * @param item
9 | * @param val
10 | * @param hide
11 | * @return {Array}
12 | * @example
13 | * basic useage
14 | * let item = {key: contract, validator: {required: [true], rules: {phone: 'mobile'}, ignore: this.isCheck}};
15 | * let val = '13770707613'
16 | * let invalidVal = '13770707'
17 | * validator(item, val) // => [] //ok
18 | * validator(item, invalidVal) // => ['phone'] //invalid
19 | *
20 | *
21 | * let hideItem = {required: true, rules: {phone: 'mobile'}};
22 | * let invalidVal = '13770707'
23 | * validator(hideItem, invalidVal, true) // => [] //ok
24 | */
25 | export const validator = (item, val, hide) => {
26 | if (Array.isArray(item)) {
27 | let ret = {}
28 | for (let i = 0, il = item.length; i < il; i++) {
29 | Object.assign(ret, handle(item[i], item[i].val, item[i].hide))
30 | }
31 | return ret
32 | } else {
33 | return handle(item, val, hide)
34 | }
35 | }
36 |
37 | const handle = (item, val, hide) => {
38 | if (!item) return {}
39 | if (item.isRange && item.items.length) {
40 | let ret = {}
41 | for (let i = 0, il = item.items.length; i < il; i++) {
42 | Object.assign(ret, vali(item.items[i], item.items[i].val, item.items[i].hide))
43 | }
44 | return ret
45 | } else {
46 | return vali(item, val, hide)
47 | }
48 | }
49 |
50 | const vali = (item, val, hide) => {
51 | let validatorRet = []
52 | let ret = {}
53 | if (!item.validator || hide || item.validator.ignore) return ret
54 | // console.log(item.key, val)
55 | if (item.validator.rules && !Object.keys(item.validator.rules).length) {
56 | console.error('validator need params', item)
57 | return ret
58 | }
59 | if (item.validator.required && item.validator.required[0]) {
60 | if (val === '' || val === null || val === undefined || (typeof val === 'object' && Object.keys(val).length < 1)) {
61 | validatorRet.push(item.validator.required[1] || '必填')
62 | ret[item.key] = validatorRet
63 | return ret
64 | }
65 | }
66 | for (const rule in item.validator.rules) {
67 | let params = item.validator.rules[rule]
68 | /**
69 | * array_len_range:[min[, max, tips]]
70 | */
71 | if (rule === 'array_len_range') {
72 | if (!Array.isArray(val)) throw new Error('validator array_len_range need a array')
73 | if (!params.length || params[0] < 0 || params[1] < 0) throw new Error('validator array_len_range need params')
74 | let min = Math.max(0, params[0])
75 | if (val.length < min || (params[1] && val.length > params[1])) {
76 | validatorRet.push(params[2] || (params[1] ? `请填写${min} ~ ${params[1]}` : `请至少选择${min}个`))
77 | }
78 | }
79 | /**
80 | * str_len_range:[min, max[, tips]]
81 | * {
82 | title: '公司名称',
83 | type: 'input',
84 | key: 'companyName',
85 | val: '',
86 | validator: {required: [true], rules: {str_len_range: [2, 30]}, ignore: this.isCheck}
87 | },
88 | */
89 | if (rule === 'str_len_range') {
90 | if (!params.length || params[0] < 0 || !params[1]) throw new Error('validator str_len_range need params')
91 | let min = Math.max(0, params[0])
92 | if (typeof val !== 'string' || val.length < min || val.length > params[1]) {
93 | validatorRet.push(params[2] || `请填写${min} ~ ${params[1]}`)
94 | }
95 | }
96 | /**
97 | * num_range:[min, max[, tips]]
98 | */
99 | if (rule === 'num_range') {
100 | if (!params.length) throw new Error('validator num_range need params')
101 | if (typeof val !== 'number' || val.length < params[0] || val.length > params[1]) {
102 | validatorRet.push(params[2] || `请填写${params[0]} ~ ${params[1]}`)
103 | }
104 | }
105 | /**
106 | * phone:[type[, tips]] //type: mobile, tel . Default is both.
107 | */
108 | if (rule === 'phone') {
109 | if (!params.length) throw new Error('validator phone need params')
110 | switch (params[0]) {
111 | case 'mobile':
112 | if (!REGEXP_MOBILE.test(val)) {
113 | validatorRet.push(params[1] || `请填写正确的手机号`)
114 | }
115 | break
116 | case 'tel':
117 | if (!REGEXP_TELEPHONE.test(val)) {
118 | validatorRet.push(params[1] || `请填写正确的电话号码,如025-88886699`)
119 | }
120 | break
121 | default :
122 | if (!REGEXP_TELEPHONE.test(val) && !REGEXP_MOBILE.test(val)) {
123 | validatorRet.push(params[1] || '请填写正确的手机号或电话号码,如025-88886699')
124 | }
125 | break
126 | }
127 | }
128 | /**
129 | * url:[[tips]]
130 | */
131 | if (rule === 'url') {
132 | if (!/^((https?|ftp|file):\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/.test(val)) {
133 | validatorRet.push(params[0] || `请填写正确的网址。`)
134 | }
135 | }
136 | /**
137 | * date:[{startDate:'',endDate:'',tips:''}]
138 | * date:{startDate:'',endDate:'',tips:''}
139 | * {
140 | title: '活动时间',
141 | type: 'startEndDate',
142 | isRange: true,
143 | items: [
144 | {
145 | type: 'start',
146 | val: '',
147 | validator: {required: [true], ignore: this.isCheck},
148 | key: 'actSttime'
149 | },
150 | {
151 | type: 'end',
152 | val: '',
153 | validator: {required: [true], rules: {date: {startDate: this.mainData['actSttime']}}, ignore: this.isCheck},
154 | key: 'actEdtime'
155 | }
156 | ]
157 | },
158 | * {
159 | title: '执行时间',
160 | type: 'startEndDate',
161 | isRange: true,
162 | items: [
163 | {
164 | type: 'start',
165 | val: '',
166 | validator: {required: [true], rules: {date: {startDate: this.mainData['actSttime'], endDate: this.mainData['actEdtime']}}, ignore: this.isCheck},
167 | key: 'exeSttime'
168 | },
169 | {
170 | type: 'end',
171 | val: '',
172 | validator: {required: [true], rules: {date: [{startDate: this.mainData['actSttime'], endDate: this.mainData['actEdtime']}, {startDate: this.mainData['exeSttime']}]}, ignore: this.isCheck},
173 | key: 'exeEdtime'
174 | }
175 | ]
176 | }
177 | */
178 | if (rule === 'date') {
179 | if (Array.isArray(params)) {
180 | for (let i = 0, il = params.length; i < il; i++) {
181 | let r = checkDate(params[i], val)
182 | if (r) validatorRet.push(r)
183 | }
184 | } else {
185 | let r = checkDate(params, val)
186 | if (r) validatorRet.push(r)
187 | }
188 | }
189 | /**
190 | * GB_32100-2015_法人和其他组织统一社会信用代码编码规则
191 | * {
192 | title: '统一社会信用代码',
193 | type: 'unifiedSocialCreditCode',
194 | validator: {required: [true], rules: {unifiedSocialCreditCode: ['请填写18位统一社会信用代码']}, ignore: this.isCheck},
195 | key: 'creditCode',
196 | hide: !this.isCoop
197 | },
198 | */
199 | if (rule === 'unifiedSocialCreditCode') {
200 | // data = "91350100M000100Y43,91430382092581024J,914103057167119596,9A350100M000100Y47,91340828578527976Q,91350128M00000019A,52100000523000026F,91350200M000000510,91520421MA6DJ09246,91440300359143307G,91340881MA2MQ0T315"
201 | if (!REGEXP_USC.test(val)) {
202 | validatorRet.push(params[0] || '请填写正确的统一社会信用代码')
203 | }
204 | }
205 |
206 | /**
207 | * 自定义正则校验
208 | * validator: {required: [true], rules: {customRegexp: [/^\d$/, '请填写数字']}},
209 | */
210 | if (rule === 'customRegexp') {
211 | if (!params[0] || !params[1]) throw new Error('validator customRegexp need params')
212 | if (!new RegExp(params[0]).test(val)) {
213 | validatorRet.push(params[1])
214 | }
215 | }
216 | }
217 |
218 | if (validatorRet.length) ret[item.key] = validatorRet
219 | return ret
220 | }
221 |
222 | const checkDate = (params, val) => {
223 | if (!params || (!params.startDate && !params.endDate)) throw new Error('validator date need params')
224 | let date = moment(val)
225 | if (params.startDate && params.endDate) {
226 | let startDate = moment(params.startDate)
227 | let endDate = moment(params.endDate)
228 | if (!date.isBetween(startDate, endDate, null, '[]')) {
229 | return (params.tips || `请选择${params.startDate} ~ ${params.endDate}之间日期。`)
230 | }
231 | } else if (params.endDate) {
232 | let endDate = moment(params.endDate)
233 | if (date.isAfter(endDate)) return (params.tips || `不能晚于 ${params.endDate}。`)
234 | } else if (params.startDate) {
235 | let startDate = moment(params.startDate)
236 | if (date.isBefore(startDate)) return (params.tips || `不能早于 ${params.startDate}。`)
237 | }
238 | }
239 |
240 |
241 | export const formatDate = (value,type) => {
242 | let format = ''
243 | switch (type) {
244 | case 'day': format = 'YYYY-MM-DD'
245 | break
246 | case 'second': format = 'YYYY-MM-DD HH:MM:SS'
247 | break
248 | default : format = type
249 | break
250 | }
251 | return moment(value).format(format)
252 |
253 | }
254 | export const fromNow = (value) => {
255 | return moment(value).fromNow();
256 | }
257 |
258 | export const getQueryString = (name) => {
259 | var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i'),
260 | r = window.location.search.substr(1).match(reg),
261 | context = '';
262 | if (r != null) {
263 | context = r[2];
264 | }
265 | reg = null;
266 | r = null;
267 | return context === null || context === '' || context === 'undefined' ? '' : context;
268 | }
269 |
270 | //手机号136****1221
271 | export const getFiterPhone = phone => {
272 | return phone.replace(/(\d{3})(?=\d{4})(?:\d{4})/, '$1****')
273 | }
274 |
275 | export const formatToParams = obj => {
276 | const arr = []
277 | for (let key in obj) {
278 | if (!obj.hasOwnProperty(key)) {
279 | continue
280 | }
281 | arr.push(`${key}=${obj[key]}`)
282 | }
283 | return arr.join('&')
284 | }
285 |
286 | export const tofixed = value => {
287 | value = value.toString()
288 | return parseFloat(value.replace(/(\d+)\./,'$1')) / ( Math.pow(10, value.length + 1) / Math.pow(10, value.length - 1))
289 | }
290 |
291 | export const cutNumber = value => {
292 | return value.toString().replace(/\B(?=(\d{3})+(?!(\d)))/g, ',')
293 | }
--------------------------------------------------------------------------------
/src/pluges/service.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by root on 2017/7/12.
3 | */
4 | import axios from 'axios'
5 | import Toast from '@/toast'
6 | let defaultConfig = {
7 | needLoading: true
8 | }
9 | axios.interceptors.request.use(
10 | config => {
11 | Object.assign(defaultConfig, config)
12 | let reg = new RegExp('.(a)')
13 | reg.test(defaultConfig.url)
14 | ? (defaultConfig.withCredentials = false)
15 | : (defaultConfig.withCredentials = true)
16 | defaultConfig.needLoading ? Toast.show() : Toast.hide()
17 | return defaultConfig
18 | },
19 | error => {
20 | Toast.hide()
21 | return Promise.reject(error)
22 | }
23 | )
24 | export default store => {
25 | axios.interceptors.response.use(
26 | response => {
27 | Toast.hide()
28 | if (
29 | response.data.code == 0 ||
30 | response.data.start == 0 ||
31 | response.data.errorCode == 0
32 | ) {
33 | if (response.data.content) {
34 | return Promise.resolve(response.data.content)
35 | } else if (response.data.data) {
36 | return Promise.resolve(response.data.data)
37 | }
38 | } else if (response.data.result == 1001) {
39 | return Promise.resolve(response.data.data)
40 | } else if (response.data.result == -200) {
41 | // token expired
42 | // window.location.href = "?cmd=login";
43 | return false
44 | } else {
45 | store.commit('API_FALID', { data: response.data.errorMsg })
46 | return false
47 | }
48 | },
49 | error => {
50 | Toast.hide()
51 | console.error('response error', error, error && error.response)
52 | store.commit('API_FALID', { data: '网络错误' })
53 | return Promise.reject(error)
54 | }
55 | )
56 | }
57 |
--------------------------------------------------------------------------------
/src/pluges/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import createLogger from 'vuex/dist/logger'
4 | import common from '../common'
5 |
6 | Vue.use(Vuex)
7 | export default (data = {}) => {
8 | console.log(data)
9 | return new Vuex.Store(
10 | Object.assign({}, {
11 | strict: process.env.NODE_ENV !== 'production',
12 | ...common,
13 | modules: data
14 | }, process.env.NODE_ENV === 'production' ? {} : {
15 | plugins: [createLogger()]
16 | }
17 | )
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/src/pluges/vuexMap.js:
--------------------------------------------------------------------------------
1 | import { mapGetters, mapState, mapActions } from 'vuex'
2 | import { createDecorator } from 'vue-class-component'
3 |
4 | export const MapGetters = options => {
5 | if (options === void 0) { options = {} }
6 | return createDecorator((componentOptions) => {
7 | if (typeof componentOptions.computed !== 'object') {
8 | componentOptions.computed = Object.create(null)
9 | }
10 | componentOptions.computed = { ...mapGetters(options) }
11 | })
12 | }
13 |
14 | export const MapStates = options => {
15 | if (options === void 0) { options = {} }
16 | return createDecorator((componentOptions) => {
17 | if (typeof componentOptions.computed !== 'object') {
18 | componentOptions.computed = Object.create(null)
19 | }
20 | componentOptions.computed = { ...mapState(options) }
21 | })
22 | }
23 |
24 | export const MapActions = options => {
25 | if (options === void 0) { options = {} }
26 | return createDecorator((componentOptions) => {
27 | if (typeof componentOptions.methods !== 'object') {
28 | componentOptions.methods = Object.create(null)
29 | }
30 | componentOptions.methods = { ...mapActions(options) }
31 | })
32 | }
33 |
--------------------------------------------------------------------------------
/view/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/view/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/view/test1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | var path = require("path");
2 | var webpack = require("webpack");
3 | var fileReder = require("./readfiles");
4 | var files = fileReder("./src/features");
5 | var imgUrl = require("./bin/config/dev").default;
6 | var jsFile = {};
7 | function resolve(dir) {
8 | return path.join(__dirname, "..", dir);
9 | }
10 | files.forEach(data => {
11 | jsFile[data] = [
12 | "webpack-hot-middleware/client",
13 | "./src/features/" + data + "/main.js"
14 | ];
15 | });
16 |
17 | module.exports = {
18 | entry: jsFile,
19 | output: {
20 | path: path.resolve(__dirname, "./static"),
21 | publicPath: "/",
22 | filename: "[name].min.js"
23 | },
24 | resolve: {
25 | modules: [path.join(__dirname, "./node_modules")],
26 | extensions: [".js", ".vue", ".json"],
27 | alias: {
28 | vue: "vue/dist//vue.esm.js",
29 | "@": path.join(__dirname, "src/components")
30 | }
31 | },
32 | plugins: [
33 | new webpack.optimize.OccurrenceOrderPlugin(),
34 | new webpack.HotModuleReplacementPlugin(),
35 | new webpack.NoEmitOnErrorsPlugin()
36 | ],
37 | module: {
38 | rules: [
39 | {
40 | test: /\.vue$/,
41 | loader: "vue-loader",
42 | options: {
43 | loaders: {
44 | scss: "style-loader!css-loader!sass-loader"
45 | },
46 | postcss: [
47 | require("autoprefixer")({
48 | browsers: ["last 7 versions"]
49 | })
50 | ]
51 | }
52 | },
53 | {
54 | test: /\.css$/,
55 | loader: "style-loader!css-loader"
56 | },
57 | {
58 | test: /\.scss$/,
59 | loader: "style-loader!css-loader!sass-loader"
60 | },
61 | {
62 | test: /\.(js|vue)$/,
63 | loader: "eslint-loader",
64 | enforce: "pre",
65 | include: [path.resolve(__dirname, "src")],
66 | options: {
67 | // 这里的配置项参数将会被传递到 eslint 的 CLIEngine
68 | formatter: require("eslint-friendly-formatter") // 指定错误报告的格式规范
69 | }
70 | },
71 | {
72 | test: /\.js$/,
73 | loader: "babel-loader",
74 | exclude: /node_modules/
75 | },
76 | {
77 | test: /\.json$/,
78 | loader: "json"
79 | },
80 | {
81 | test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
82 | loader: "file-loader"
83 | },
84 | {
85 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
86 | loader: "url-loader",
87 | options: {
88 | limit: 10000,
89 | name: path.posix.join(imgUrl.imageHost, "img/[name].[hash:7].[ext]")
90 | }
91 | }
92 | ]
93 | }
94 | };
95 |
--------------------------------------------------------------------------------
/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | var path = require("path");
2 | var fs = require("fs");
3 | var webpack = require("webpack");
4 | var HtmlWebpackPlugin = require("html-webpack-plugin");
5 | var fileReder = require("./readfiles");
6 | var files = fileReder("./src/features");
7 | var jsFile = {};
8 | jsFile["vender"] = ["vue", "vue-router", "vuex", "axios"];
9 |
10 | files.forEach(data => {
11 | jsFile[data] = "./src/features/" + data + "/main.js";
12 | });
13 | var pluginsArray1 = connect();
14 |
15 | var pluginsArray2 = [
16 | new HtmlWebpackPluginDist(),
17 | new webpack.optimize.OccurrenceOrderPlugin(),
18 | new webpack.optimize.UglifyJsPlugin({
19 | output: {
20 | comments: false
21 | },
22 | compress: {
23 | warnings: false
24 | }
25 | }),
26 | //new webpack.optimize.CommonsChunkPlugin('common', 'dist/js/vendor.js'),
27 | new webpack.optimize.CommonsChunkPlugin({
28 | name: ["vender"],
29 | minChunks: 1
30 | }),
31 | new webpack.NoErrorsPlugin()
32 | ];
33 | pluginsArray1 = pluginsArray1.concat(pluginsArray2);
34 |
35 | module.exports = {
36 | entry: jsFile,
37 | output: {
38 | path: path.resolve(__dirname, "./dist"),
39 | publicPath: "/",
40 | filename: "[name].[chunkhash].js"
41 | },
42 | resolve: {
43 | modules: [path.join(__dirname, "./node_modules")],
44 | extensions: [".js", ".vue", ".json"],
45 | alias: {
46 | vue: "vue/dist//vue.esm.js",
47 | "@": path.join(__dirname, "src/components")
48 | }
49 | },
50 | plugins: pluginsArray1,
51 | module: {
52 | rules: [
53 | {
54 | test: /\.vue$/,
55 | loader: "vue-loader",
56 | options: {
57 | loaders: {
58 | scss: "style-loader!css-loader!sass-loader"
59 | },
60 | postcss: [
61 | require("autoprefixer")({
62 | browsers: ["last 7 versions"]
63 | })
64 | ]
65 | }
66 | },
67 | {
68 | test: /\.css$/,
69 | loader: "style-loader!css-loader"
70 | },
71 | {
72 | test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
73 | loader: "file-loader"
74 | },
75 | {
76 | test: /\.scss$/,
77 | loader: "style-loader!css-loader!sass-loader"
78 | },
79 | {
80 | test: /\.js$/,
81 | loader: "babel-loader",
82 | exclude: /node_modules/
83 | },
84 | {
85 | test: /\.json$/,
86 | loader: "json"
87 | },
88 | {
89 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
90 | loader: "url-loader",
91 | options: {
92 | limit: 10000,
93 | name: path.posix.join("/", "/img/[name].[hash:7].[ext]")
94 | }
95 | }
96 | ]
97 | }
98 | };
99 |
100 | function connect() {
101 | var arr = [];
102 | files.forEach(function(data) {
103 | var cache = null;
104 | cache = new HtmlWebpackPlugin({
105 | filename: path.resolve(__dirname, "./dist/" + data + ".html"),
106 | template: "./view/" + data + ".html",
107 | chunks: ["vender", data]
108 | });
109 | arr.push(cache);
110 | });
111 | return arr;
112 | }
113 |
114 | function HtmlWebpackPluginDist() {}
115 | HtmlWebpackPluginDist.prototype.apply = function(compiler) {
116 | var self = this;
117 | // Hook into the html-webpack-plugin processing
118 | compiler.plugin("compilation", function(compilation) {
119 | compilation.plugin("html-webpack-plugin-before-html-processing", function(
120 | data,
121 | cb
122 | ) {
123 | console.log(data.html);
124 | var filename = data.assets.js;
125 | filename = filename.map(function(data) {
126 | return data.replace(/\/js\//, "");
127 | });
128 | filename = filename.map(function(data) {
129 | var name = data.split(".");
130 | return name[0];
131 | });
132 | data.html = data.html.replace(
133 | '',
136 | ""
137 | );
138 | cb(null, data);
139 | });
140 | });
141 | };
142 |
--------------------------------------------------------------------------------