afa2f1ef by 406803045

初始化项目

1 parent 35204b5c
1 # http://editorconfig.org
2 root = true
3
4 [*]
5 charset = utf-8
6 indent_style = space
7 indent_size = 2
8 end_of_line = lf
9 insert_final_newline = true
10 trim_trailing_whitespace = true
11
12 [*.md]
13 insert_final_newline = false
14 trim_trailing_whitespace = false
1 NODE_ENV
2 # just a flag
3 ENV = 'development'
4 #base url
5 BASE_URL = https://www.xxx.com/
6 # base api
7 VUE_APP_BASE_API = '/dev-api'
8 VUE_CLI_BABEL_TRANSPILE_MODULES = true
1 # just a flag
2 ENV = 'production'
3 #base url
4 BASE_URL = https://www.top1buyer.com/
5 # base api
6 VUE_APP_BASE_API = '/prod-api'
7
1 NODE_ENV = production
2
3 # just a flag
4 ENV = 'staging'
5 #base url
6 BASE_URL = https://www.top1buyer.com/
7 # base api
8 VUE_APP_BASE_API = '/stage-api'
9
1 build/*.js
2 src/assets
3 public
4 dist
1 module.exports = {
2 root: true,
3 parserOptions: {
4 parser: 'babel-eslint',
5 sourceType: 'module'
6 },
7 env: {
8 browser: true,
9 node: true,
10 es6: true
11 },
12 extends: ['plugin:vue/recommended', 'eslint:recommended'],
13
14 // add your custom rules here
15 //it is base on https://github.com/vuejs/eslint-config-vue
16 rules: {
17 'vue/max-attributes-per-line': [
18 2,
19 {
20 singleline: 10,
21 multiline: {
22 max: 1,
23 allowFirstLine: false
24 }
25 }
26 ],
27 'vue/singleline-html-element-content-newline': 'off',
28 'vue/multiline-html-element-content-newline': 'off',
29 'vue/name-property-casing': ['error', 'PascalCase'],
30 'vue/no-v-html': 'off',
31 'accessor-pairs': 2,
32 'arrow-spacing': [
33 2,
34 {
35 before: true,
36 after: true
37 }
38 ],
39 'block-spacing': [2, 'always'],
40 'brace-style': [
41 2,
42 '1tbs',
43 {
44 allowSingleLine: true
45 }
46 ],
47 camelcase: [
48 0,
49 {
50 properties: 'always'
51 }
52 ],
53 'comma-dangle': [2, 'never'],
54 'comma-spacing': [
55 2,
56 {
57 before: false,
58 after: true
59 }
60 ],
61 'comma-style': [2, 'last'],
62 'constructor-super': 2,
63 curly: [2, 'multi-line'],
64 'dot-location': [2, 'property'],
65 'eol-last': 2,
66 eqeqeq: ['error', 'always', { null: 'ignore' }],
67 'generator-star-spacing': [
68 2,
69 {
70 before: true,
71 after: true
72 }
73 ],
74 'handle-callback-err': [2, '^(err|error)$'],
75 'indent': ['off', 2],
76 'jsx-quotes': [2, 'prefer-single'],
77 'key-spacing': [
78 2,
79 {
80 beforeColon: false,
81 afterColon: true
82 }
83 ],
84 'keyword-spacing': [
85 2,
86 {
87 before: true,
88 after: true
89 }
90 ],
91 'new-cap': [
92 2,
93 {
94 newIsCap: true,
95 capIsNew: false
96 }
97 ],
98 'new-parens': 2,
99 'no-array-constructor': 2,
100 'no-caller': 2,
101 'no-console': 'off',
102 'no-class-assign': 2,
103 'no-cond-assign': 2,
104 'no-const-assign': 2,
105 'no-control-regex': 0,
106 'no-delete-var': 2,
107 'no-dupe-args': 2,
108 'no-dupe-class-members': 2,
109 'no-dupe-keys': 2,
110 'no-duplicate-case': 2,
111 'no-empty-character-class': 2,
112 'no-empty-pattern': 2,
113 'no-eval': 2,
114 'no-ex-assign': 2,
115 'no-extend-native': 2,
116 'no-extra-bind': 2,
117 'no-extra-boolean-cast': 2,
118 'no-extra-parens': [2, 'functions'],
119 'no-fallthrough': 2,
120 'no-floating-decimal': 2,
121 'no-func-assign': 2,
122 'no-implied-eval': 2,
123 'no-inner-declarations': [2, 'functions'],
124 'no-invalid-regexp': 2,
125 'no-irregular-whitespace': 2,
126 'no-iterator': 2,
127 'no-label-var': 2,
128 'no-labels': [
129 2,
130 {
131 allowLoop: false,
132 allowSwitch: false
133 }
134 ],
135 'no-lone-blocks': 2,
136 'no-mixed-spaces-and-tabs': 2,
137 'no-multi-spaces': 2,
138 'no-multi-str': 2,
139 'no-multiple-empty-lines': [
140 2,
141 {
142 max: 1
143 }
144 ],
145 'no-native-reassign': 2,
146 'no-negated-in-lhs': 2,
147 'no-new-object': 2,
148 'no-new-require': 2,
149 'no-new-symbol': 2,
150 'no-new-wrappers': 2,
151 'no-obj-calls': 2,
152 'no-octal': 2,
153 'no-octal-escape': 2,
154 'no-path-concat': 2,
155 'no-proto': 2,
156 'no-redeclare': 2,
157 'no-regex-spaces': 2,
158 'no-return-assign': [2, 'except-parens'],
159 'no-self-assign': 2,
160 'no-self-compare': 2,
161 'no-sequences': 2,
162 'no-shadow-restricted-names': 2,
163 'no-spaced-func': 2,
164 'no-sparse-arrays': 2,
165 'no-this-before-super': 2,
166 'no-throw-literal': 2,
167 'no-trailing-spaces': 2,
168 'no-undef': 2,
169 'no-undef-init': 2,
170 'no-unexpected-multiline': 2,
171 'no-unmodified-loop-condition': 2,
172 'no-unneeded-ternary': [
173 2,
174 {
175 defaultAssignment: false
176 }
177 ],
178 'no-unreachable': 2,
179 'no-unsafe-finally': 2,
180 'no-unused-vars': [
181 2,
182 {
183 vars: 'all',
184 args: 'none'
185 }
186 ],
187 'no-useless-call': 2,
188 'no-useless-computed-key': 2,
189 'no-useless-constructor': 2,
190 'no-useless-escape': 0,
191 'no-whitespace-before-property': 2,
192 'no-with': 2,
193 'one-var': [
194 2,
195 {
196 initialized: 'never'
197 }
198 ],
199 'operator-linebreak': [
200 2,
201 'after',
202 {
203 overrides: {
204 '?': 'before',
205 ':': 'before'
206 }
207 }
208 ],
209 'padded-blocks': [2, 'never'],
210 quotes: [
211 2,
212 'single',
213 {
214 avoidEscape: true,
215 allowTemplateLiterals: true
216 }
217 ],
218 semi: [2, 'never'],
219 'semi-spacing': [
220 2,
221 {
222 before: false,
223 after: true
224 }
225 ],
226 'space-before-blocks': [2, 'always'],
227 'space-before-function-paren': [2, 'never'],
228 'space-in-parens': [2, 'never'],
229 'space-infix-ops': 2,
230 'space-unary-ops': [
231 2,
232 {
233 words: true,
234 nonwords: false
235 }
236 ],
237 'spaced-comment': [
238 2,
239 'always',
240 {
241 markers: [
242 'global',
243 'globals',
244 'eslint',
245 'eslint-disable',
246 '*package',
247 '!',
248 ','
249 ]
250 }
251 ],
252 'template-curly-spacing': [2, 'never'],
253 'use-isnan': 2,
254 'valid-typeof': 2,
255 'wrap-iife': [2, 'any'],
256 'yield-star-spacing': [2, 'both'],
257 yoda: [2, 'never'],
258 'prefer-const': 2,
259 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
260 'object-curly-spacing': [
261 2,
262 'always',
263 {
264 objectsInObjects: false
265 }
266 ],
267 'array-bracket-spacing': [2, 'never'],
268 'vue/html-self-closing': ["error",{
269 "html": {
270 "void": "never",
271 "normal": "any",
272 "component": "any"
273 },
274 "svg": "always",
275 "math": "always"
276 }]
277 }
278 }
1 .DS_Store
2 node_modules/
3 dist/
4 npm-debug.log*
5 yarn-debug.log*
6 yarn-error.log*
7 package-lock.json
8 tests/**/coverage/
9
10 # Editor directories and files
11 .idea
12 .vscode
13 *.suo
14 *.ntvs*
15 *.njsproj
16 *.sln
1 // https://github.com/michael-ciniawsky/postcss-load-config
2 module.exports = {
3 plugins: {
4 autoprefixer: {
5 browsers: ['Android >= 4.0', 'iOS >= 7']
6 },
7 'postcss-pxtorem': {
8 rootValue: 37.5,
9 propList: ['*']
10 }
11 }
12 }
1 language: node_js
2 node_js: 10
3 script: npm run test
4 notifications:
5 email: false
1 MIT License
2
3 Copyright (c) 2017-present PanJiaChen
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 SOFTWARE.
1 module.exports = {
2 presets: ['@vue/app'],
3 plugins: [
4 [
5 'import',
6 {
7 libraryName: 'vant',
8 libraryDirectory: 'es',
9 style: true
10 },
11 'vant'
12 ]
13 ]
14 }
1 const { run } = require('runjs')
2 const chalk = require('chalk')
3 // const config = require('../vue.config.js')
4 const rawArgv = process.argv.slice(2)
5 const args = rawArgv.join(' ')
6
7 if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
8 const report = rawArgv.includes('--report')
9
10 run(`vue-cli-service build ${args}`)
11
12 const port = 9018
13 const publicPath = '/'
14
15 var connect = require('connect')
16 var serveStatic = require('serve-static')
17 const app = connect()
18
19 app.use(
20 publicPath,
21 serveStatic('./dist', {
22 index: ['index.html', '/']
23 })
24 )
25
26 app.listen(port, function () {
27 console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
28 if (report) {
29 console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
30 }
31
32 })
33 } else {
34 run(`vue-cli-service build ${args}`)
35 }
1 module.exports = {
2 moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
3 transform: {
4 '^.+\\.vue$': 'vue-jest',
5 '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
6 'jest-transform-stub',
7 '^.+\\.jsx?$': 'babel-jest'
8 },
9 moduleNameMapper: {
10 '^@/(.*)$': '<rootDir>/src/$1'
11 },
12 snapshotSerializers: ['jest-serializer-vue'],
13 testMatch: [
14 '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
15 ],
16 collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
17 coverageDirectory: '<rootDir>/tests/unit/coverage',
18 // 'collectCoverage': true,
19 'coverageReporters': [
20 'lcov',
21 'text-summary'
22 ],
23 testURL: 'http://localhost/'
24 }
1 {
2 "name": "vue-admin-template",
3 "version": "4.1.0",
4 "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
5 "author": "Pan <panfree23@gmail.com>",
6 "license": "MIT",
7 "scripts": {
8 "dev": "vue-cli-service serve",
9 "build:prod": "vue-cli-service build",
10 "build:stage": "vue-cli-service build --mode staging",
11 "preview": "node build/index.js --preview",
12 "lint": "eslint --ext .js,.vue src",
13 "test:unit": "jest --clearCache && vue-cli-service test:unit",
14 "test:ci": "npm run lint && npm run test:unit",
15 "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
16 },
17 "dependencies": {
18 "axios": "0.18.0",
19 "lib-flexible": "^0.3.2",
20 "normalize.css": "7.0.0",
21 "vant": "^1.6.19",
22 "vue": "2.6.10",
23 "vue-router": "3.0.6",
24 "vuex": "3.1.0"
25 },
26 "devDependencies": {
27 "@babel/core": "7.0.0",
28 "@babel/register": "7.0.0",
29 "@vue/cli-plugin-babel": "3.6.0",
30 "@vue/cli-plugin-eslint": "3.6.0",
31 "@vue/cli-plugin-unit-jest": "3.6.3",
32 "@vue/cli-service": "3.6.0",
33 "@vue/test-utils": "1.0.0-beta.29",
34 "babel-core": "7.0.0-bridge.0",
35 "babel-eslint": "10.0.1",
36 "babel-jest": "23.6.0",
37 "babel-plugin-import": "^1.11.2",
38 "chalk": "2.4.2",
39 "connect": "3.6.6",
40 "eslint": "5.15.3",
41 "eslint-plugin-vue": "5.2.2",
42 "html-webpack-plugin": "3.2.0",
43 "node-sass": "^4.9.0",
44 "postcss-pxtorem": "^4.0.1",
45 "runjs": "^4.3.2",
46 "sass-loader": "^7.1.0",
47 "script-ext-html-webpack-plugin": "2.1.3",
48 "script-loader": "0.7.2",
49 "serve-static": "^1.13.2",
50 "svgo": "1.2.2",
51 "vue-template-compiler": "2.6.10"
52 },
53 "engines": {
54 "node": ">=8.9",
55 "npm": ">= 3.0.0"
56 },
57 "browserslist": [
58 "> 1%",
59 "last 2 versions",
60 "not ie <= 8"
61 ]
62 }
No preview for this file type
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
7
8 <link rel="icon" href="<%= BASE_URL %>favicon.ico">
9 <title><%= webpackConfig.name %></title>
10 </head>
11 <body>
12 <noscript>
13 <strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
14 </noscript>
15 <div id="app"></div>
16 <!-- built files will be auto injected -->
17 </body>
18 </html>
1 <template>
2 <div id="app">
3 <keep-alive>
4 <router-view v-if="$route.meta.keepAlive"></router-view>
5 </keep-alive>
6 <router-view v-if="!$route.meta.keepAlive"></router-view>
7 </div>
8 </template>
9 <script>
10 export default {
11 name: 'App'
12 }
13
14 </script>
1 import qs from 'qs'
2 import request from '@/utils/request'
3 import { api } from '@/config'
4 // api
5 const { common_api } = api
6 // 登录
7 export function login(params) {
8 return request({
9 url: common_api + '/ruleCommon/queryrule',
10 method: 'post',
11 data: qs.stringify(params)
12 })
13 }
1 // cover some element-ui styles
2
3 .el-breadcrumb__inner,
4 .el-breadcrumb__inner a {
5 font-weight: 400 !important;
6 }
7
8 .el-upload {
9 input[type="file"] {
10 display: none !important;
11 }
12 }
13
14 .el-upload__input {
15 display: none;
16 }
17
18
19 // to fixed https://github.com/ElemeFE/element/issues/2461
20 .el-dialog {
21 transform: none;
22 left: 0;
23 position: relative;
24 margin: 0 auto;
25 }
26
27 // refine element ui upload
28 .upload-container {
29 .el-upload {
30 width: 100%;
31
32 .el-upload-dragger {
33 width: 100%;
34 height: 200px;
35 }
36 }
37 }
38
39 // dropdown
40 .el-dropdown-menu {
41 a {
42 display: block
43 }
44 }
1 @import './variables.scss';
2 @import './mixin.scss';
3 @import './transition.scss';
4 @import './element-ui.scss';
5 @import './sidebar.scss';
6
7 body {
8 height: 100%;
9 -moz-osx-font-smoothing: grayscale;
10 -webkit-font-smoothing: antialiased;
11 text-rendering: optimizeLegibility;
12 font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
13 }
14
15 label {
16 font-weight: 700;
17 }
18
19 html {
20 height: 100%;
21 box-sizing: border-box;
22 }
23
24 #app {
25 height: 100%;
26 }
27
28 *,
29 *:before,
30 *:after {
31 box-sizing: inherit;
32 }
33
34 a:focus,
35 a:active {
36 outline: none;
37 }
38
39 a,
40 a:focus,
41 a:hover {
42 cursor: pointer;
43 color: inherit;
44 text-decoration: none;
45 }
46
47 div:focus {
48 outline: none;
49 }
50
51 .clearfix {
52 &:after {
53 visibility: hidden;
54 display: block;
55 font-size: 0;
56 content: " ";
57 clear: both;
58 height: 0;
59 }
60 }
61
62 // main-container global css
63 .app-container {
64 padding: 20px;
65 }
1 @mixin clearfix {
2 &:after {
3 content: "";
4 display: table;
5 clear: both;
6 }
7 }
8
9 @mixin scrollBar {
10 &::-webkit-scrollbar-track-piece {
11 background: #d3dce6;
12 }
13
14 &::-webkit-scrollbar {
15 width: 6px;
16 }
17
18 &::-webkit-scrollbar-thumb {
19 background: #99a9bf;
20 border-radius: 20px;
21 }
22 }
23
24 @mixin relative {
25 position: relative;
26 width: 100%;
27 height: 100%;
28 }
1 #app {
2
3 .main-container {
4 min-height: 100%;
5 transition: margin-left .28s;
6 margin-left: $sideBarWidth;
7 position: relative;
8 }
9
10 .sidebar-container {
11 transition: width 0.28s;
12 width: $sideBarWidth !important;
13 background-color: $menuBg;
14 height: 100%;
15 position: fixed;
16 font-size: 0px;
17 top: 0;
18 bottom: 0;
19 left: 0;
20 z-index: 1001;
21 overflow: hidden;
22
23 // reset element-ui css
24 .horizontal-collapse-transition {
25 transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
26 }
27
28 .scrollbar-wrapper {
29 overflow-x: hidden !important;
30 }
31
32 .el-scrollbar__bar.is-vertical {
33 right: 0px;
34 }
35
36 .el-scrollbar {
37 height: 100%;
38 }
39
40 &.has-logo {
41 .el-scrollbar {
42 height: calc(100% - 50px);
43 }
44 }
45
46 .is-horizontal {
47 display: none;
48 }
49
50 a {
51 display: inline-block;
52 width: 100%;
53 overflow: hidden;
54 }
55
56 .svg-icon {
57 margin-right: 16px;
58 }
59
60 .el-menu {
61 border: none;
62 height: 100%;
63 width: 100% !important;
64 }
65
66 // menu hover
67 .submenu-title-noDropdown,
68 .el-submenu__title {
69 &:hover {
70 background-color: $menuHover !important;
71 }
72 }
73
74 .is-active>.el-submenu__title {
75 color: $subMenuActiveText !important;
76 }
77
78 & .nest-menu .el-submenu>.el-submenu__title,
79 & .el-submenu .el-menu-item {
80 min-width: $sideBarWidth !important;
81 background-color: $subMenuBg !important;
82
83 &:hover {
84 background-color: $subMenuHover !important;
85 }
86 }
87 }
88
89 .hideSidebar {
90 .sidebar-container {
91 width: 54px !important;
92 }
93
94 .main-container {
95 margin-left: 54px;
96 }
97
98 .submenu-title-noDropdown {
99 padding: 0 !important;
100 position: relative;
101
102 .el-tooltip {
103 padding: 0 !important;
104
105 .svg-icon {
106 margin-left: 20px;
107 }
108 }
109 }
110
111 .el-submenu {
112 overflow: hidden;
113
114 &>.el-submenu__title {
115 padding: 0 !important;
116
117 .svg-icon {
118 margin-left: 20px;
119 }
120
121 .el-submenu__icon-arrow {
122 display: none;
123 }
124 }
125 }
126
127 .el-menu--collapse {
128 .el-submenu {
129 &>.el-submenu__title {
130 &>span {
131 height: 0;
132 width: 0;
133 overflow: hidden;
134 visibility: hidden;
135 display: inline-block;
136 }
137 }
138 }
139 }
140 }
141
142 .el-menu--collapse .el-menu .el-submenu {
143 min-width: $sideBarWidth !important;
144 }
145
146 // mobile responsive
147 .mobile {
148 .main-container {
149 margin-left: 0px;
150 }
151
152 .sidebar-container {
153 transition: transform .28s;
154 width: $sideBarWidth !important;
155 }
156
157 &.hideSidebar {
158 .sidebar-container {
159 pointer-events: none;
160 transition-duration: 0.3s;
161 transform: translate3d(-$sideBarWidth, 0, 0);
162 }
163 }
164 }
165
166 .withoutAnimation {
167
168 .main-container,
169 .sidebar-container {
170 transition: none;
171 }
172 }
173 }
174
175 // when menu collapsed
176 .el-menu--vertical {
177 &>.el-menu {
178 .svg-icon {
179 margin-right: 16px;
180 }
181 }
182
183 .nest-menu .el-submenu>.el-submenu__title,
184 .el-menu-item {
185 &:hover {
186 // you can use $subMenuHover
187 background-color: $menuHover !important;
188 }
189 }
190
191 // the scroll bar appears when the subMenu is too long
192 >.el-menu--popup {
193 max-height: 100vh;
194 overflow-y: auto;
195
196 &::-webkit-scrollbar-track-piece {
197 background: #d3dce6;
198 }
199
200 &::-webkit-scrollbar {
201 width: 6px;
202 }
203
204 &::-webkit-scrollbar-thumb {
205 background: #99a9bf;
206 border-radius: 20px;
207 }
208 }
209 }
1 // global transition css
2
3 /* fade */
4 .fade-enter-active,
5 .fade-leave-active {
6 transition: opacity 0.28s;
7 }
8
9 .fade-enter,
10 .fade-leave-active {
11 opacity: 0;
12 }
13
14 /* fade-transform */
15 .fade-transform-leave-active,
16 .fade-transform-enter-active {
17 transition: all .5s;
18 }
19
20 .fade-transform-enter {
21 opacity: 0;
22 transform: translateX(-30px);
23 }
24
25 .fade-transform-leave-to {
26 opacity: 0;
27 transform: translateX(30px);
28 }
29
30 /* breadcrumb transition */
31 .breadcrumb-enter-active,
32 .breadcrumb-leave-active {
33 transition: all .5s;
34 }
35
36 .breadcrumb-enter,
37 .breadcrumb-leave-active {
38 opacity: 0;
39 transform: translateX(20px);
40 }
41
42 .breadcrumb-move {
43 transition: all .5s;
44 }
45
46 .breadcrumb-leave-active {
47 position: absolute;
48 }
1 // sidebar
2 $menuText:#bfcbd9;
3 $menuActiveText:#409EFF;
4 $subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
5
6 $menuBg:#304156;
7 $menuHover:#263445;
8
9 $subMenuBg:#1f2d3d;
10 $subMenuHover:#001528;
11
12 $sideBarWidth: 210px;
13
14 // the :export directive is the magic sauce for webpack
15 // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
16 :export {
17 menuText: $menuText;
18 menuActiveText: $menuActiveText;
19 subMenuActiveText: $subMenuActiveText;
20 menuBg: $menuBg;
21 menuHover: $menuHover;
22 subMenuBg: $subMenuBg;
23 subMenuHover: $subMenuHover;
24 sideBarWidth: $sideBarWidth;
25 }
1 // 本地
2 module.exports = {
3 title: '蚁小宝',
4 api: {
5 base_api: 'https://t1.top1buyer.com/admin',
6 common_api: 'https://t.top1buyer.com/common'
7 }
8 }
1 // 正式
2 module.exports = {
3 title: '蚁小宝',
4 api: {
5 base_api: 'https://t1.top1buyer.com/admin',
6 common_api: 'https://t.top1buyer.com/common'
7 }
8 }
1 module.exports = {
2 title: '蚁小宝',
3 api: {
4 base_api: 'https://t1.top1buyer.com/admin',
5 common_api: 'https://t.top1buyer.com/common'
6 }
7 }
1 // 根据环境引入不同配置 process.env.NODE_ENV
2 const config = require('./env.' + process.env.ENV)
3 console.log( process.env.ENV)
4 module.exports = config
1 import Vue from 'vue'
2
3 import 'normalize.css/normalize.css' // A modern alternative to CSS resets
4 import '@/assets/css/index.scss' // global css
5 //移动端适配
6 import "lib-flexible/flexible.js"
7 import App from './App'
8 import store from './store'
9 import router from './router'
10 Vue.config.productionTip = false
11
12 new Vue({
13 el: '#app',
14 router,
15 store,
16 render: h => h(App)
17 })
1 import Vue from 'vue'
2 import Router from 'vue-router'
3
4 Vue.use(Router)
5 export const constantRoutes = [
6 {
7 path: '/',
8 component: () => import('@/views/home/index'),
9 meta: {
10 keepAlive: false
11 }
12 }
13 ]
14
15 const createRouter = () =>
16 new Router({
17 // mode: 'history', // require service support
18 scrollBehavior: () => ({ y: 0 }),
19 routes: constantRoutes
20 })
21
22 export default createRouter()
1 const getters = {
2 }
3 export default getters
1 import Vue from 'vue'
2 import Vuex from 'vuex'
3 import getters from './getters'
4 import app from './modules/app'
5
6 Vue.use(Vuex)
7
8 const store = new Vuex.Store({
9 modules: {
10 app
11 },
12 getters
13 })
14
15 export default store
1 const state = {
2
3 }
4
5 const mutations = {
6
7 }
8
9 const actions = {
10
11 }
12
13 export default {
14 namespaced: true,
15 state,
16 mutations,
17 actions
18 }
1 /**
2 * Created by PanJiaChen on 16/11/18.
3 */
4
5 /**
6 * Parse the time to string
7 * @param {(Object|string|number)} time
8 * @param {string} cFormat
9 * @returns {string}
10 */
11 export function parseTime(time, cFormat) {
12 if (arguments.length === 0) {
13 return null
14 }
15 const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
16 let date
17 if (typeof time === 'object') {
18 date = time
19 } else {
20 if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
21 time = parseInt(time)
22 }
23 if ((typeof time === 'number') && (time.toString().length === 10)) {
24 time = time * 1000
25 }
26 date = new Date(time)
27 }
28 const formatObj = {
29 y: date.getFullYear(),
30 m: date.getMonth() + 1,
31 d: date.getDate(),
32 h: date.getHours(),
33 i: date.getMinutes(),
34 s: date.getSeconds(),
35 a: date.getDay()
36 }
37 const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
38 let value = formatObj[key]
39 // Note: getDay() returns 0 on Sunday
40 if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
41 if (result.length > 0 && value < 10) {
42 value = '0' + value
43 }
44 return value || 0
45 })
46 return time_str
47 }
48
49 /**
50 * @param {number} time
51 * @param {string} option
52 * @returns {string}
53 */
54 export function formatTime(time, option) {
55 if (('' + time).length === 10) {
56 time = parseInt(time) * 1000
57 } else {
58 time = +time
59 }
60 const d = new Date(time)
61 const now = Date.now()
62
63 const diff = (now - d) / 1000
64
65 if (diff < 30) {
66 return '刚刚'
67 } else if (diff < 3600) {
68 // less 1 hour
69 return Math.ceil(diff / 60) + '分钟前'
70 } else if (diff < 3600 * 24) {
71 return Math.ceil(diff / 3600) + '小时前'
72 } else if (diff < 3600 * 24 * 2) {
73 return '1天前'
74 }
75 if (option) {
76 return parseTime(time, option)
77 } else {
78 return (
79 d.getMonth() +
80 1 +
81 '月' +
82 d.getDate() +
83 '日' +
84 d.getHours() +
85 '时' +
86 d.getMinutes() +
87 '分'
88 )
89 }
90 }
91
92 /**
93 * @param {string} url
94 * @returns {Object}
95 */
96 export function param2Obj(url) {
97 const search = url.split('?')[1]
98 if (!search) {
99 return {}
100 }
101 return JSON.parse(
102 '{"' +
103 decodeURIComponent(search)
104 .replace(/"/g, '\\"')
105 .replace(/&/g, '","')
106 .replace(/=/g, '":"')
107 .replace(/\+/g, ' ') +
108 '"}'
109 )
110 }
1 import axios from 'axios'
2 import store from '@/store'
3
4 // create an axios instance
5 const service = axios.create({
6 baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
7 withCredentials: true, // send cookies when cross-domain requests
8 timeout: 5000 // request timeout
9 })
10
11 // request interceptor
12 service.interceptors.request.use(
13 config => {
14 // do something before request is sent
15 if (store.getters.token) {
16 // let each request carry token
17 // ['X-Token'] is a custom headers key
18 // please modify it according to the actual situation
19 config.headers['X-Token'] = ''
20 }
21 return config
22 },
23 error => {
24 // do something with request error
25 console.log(error) // for debug
26 return Promise.reject(error)
27 }
28 )
29
30 // response interceptor
31 service.interceptors.response.use(
32 response => {
33 const res = response.data
34
35 // if the custom code is not 20000, it is judged as an error.
36 if (res.code !== 20000) {
37 Message({
38 message: res.message || 'error',
39 type: 'error',
40 duration: 5 * 1000
41 })
42
43 // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
44 if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
45 // to re-login
46 MessageBox.confirm(
47 'You have been logged out, you can cancel to stay on this page, or log in again',
48 'Confirm logout',
49 {
50 confirmButtonText: 'Re-Login',
51 cancelButtonText: 'Cancel',
52 type: 'warning'
53 }
54 ).then(() => {
55 store.dispatch('user/resetToken').then(() => {
56 location.reload()
57 })
58 })
59 }
60 return Promise.reject(res.message || 'error')
61 } else {
62 return res
63 }
64 },
65 error => {
66 console.log('err' + error) // for debug
67 Message({
68 message: error.message,
69 type: 'error',
70 duration: 5 * 1000
71 })
72 return Promise.reject(error)
73 }
74 )
75
76 export default service
1 import axios from 'axios'
2 import store from '@/store'
3 import { Toast } from 'vant'
4 // create an axios instance
5 const service = axios.create({
6 baseURL: process.env.BASE_URL, // url = base url + request url
7 withCredentials: true, // send cookies when cross-domain requests
8 timeout: 5000 // request timeout
9 })
10
11 // request拦截器 request interceptor
12 service.interceptors.request.use(
13 config => {
14 // 不传递默认开启loading
15 if (!config.hideloading) {
16 // loading
17 Toast.loading({
18 forbidClick: true
19 })
20 }
21 if (store.getters.token) {
22 config.headers['X-Token'] = ''
23 }
24 return config
25 },
26 error => {
27 // do something with request error
28 console.log(error) // for debug
29 return Promise.reject(error)
30 }
31 )
32 // respone拦截器
33 service.interceptors.response.use(
34 response => {
35 Toast.clear()
36 // 如果是数据流
37 if (response.config.responseType === 'arraybuffer') {
38 return response.data
39 } else {
40 const res = response.data
41 if (res.status !== 200) {
42 // 登录超时,重新登录
43 if (res.status === 401) {
44 store.dispatch('FedLogOut').then(() => {
45 location.reload()
46 })
47 }
48 return Promise.reject(res || 'error')
49 } else {
50 return Promise.resolve(res)
51 }
52 }
53 },
54 error => {
55 Toast.clear()
56 console.log('err' + error) // for debug
57 return Promise.reject(error)
58 }
59 )
60
61 export default service
File mode changed
1 /**
2 * Created by PanJiaChen on 16/11/18.
3 */
4
5 /**
6 * @param {string} path
7 * @returns {Boolean}
8 */
9 export function isExternal(path) {
10 return /^(https?:|mailto:|tel:)/.test(path)
11 }
12
13 /**
14 * @param {string} str
15 * @returns {Boolean}
16 */
17 export function validUsername(str) {
18 const valid_map = ['admin', 'editor']
19 return valid_map.indexOf(str.trim()) >= 0
20 }
1 <!-- home -->
2 <template>
3 <div>
4 <h1>home</h1>
5 <van-button type="primary">主要按钮</van-button>
6 </div>
7 </template>
8
9 <script>
10 import {
11 Button
12 } from 'vant'
13 export default {
14 data() {
15 return {};
16 },
17
18 components: {
19 'van-button': Button
20 },
21
22 computed: {},
23
24 mounted() {},
25
26 methods: {}
27 }
28
29 </script>
30 <style lang='scss' scoped>
31 h1 {
32 background: red;
33 width: 375px;
34 }
35
36 </style>
1 'use strict'
2 const path = require('path')
3 const defaultSettings = require('./src/config/index.js')
4 function resolve(dir) {
5 return path.join(__dirname, dir)
6 }
7
8 const name = defaultSettings.title || 'vue mobile template' // page title
9 const port = 9018 // dev port
10 module.exports = {
11 publicPath: '/',
12 outputDir: 'dist',
13 assetsDir: 'static',
14 lintOnSave: process.env.NODE_ENV === 'development',
15 productionSourceMap: false,
16 devServer: {
17 port: port,
18 open: true,
19 overlay: {
20 warnings: false,
21 errors: true
22 }
23 },
24 // css: {
25 // loaderOptions: {
26 // postcss: {
27 // plugins: [
28 // require('postcss-plugin-px2rem')({
29 // rootValue: 75, // 换算基数, 默认100 ,这样的话把根标签的字体规定为1rem为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。
30 // // unitPrecision: 5, //允许REM单位增长到的十进制数字。
31 // // propWhiteList: [], //默认值是一个空数组,这意味着禁用白名单并启用所有属性。
32 // // propBlackList: [], //黑名单
33 // exclude: /(node_module)/, // 默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)\/如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
34 // // selectorBlackList: [], //要忽略并保留为px的选择器
35 // // ignoreIdentifier: false, //(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。
36 // // replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。
37 // mediaQuery: false, // (布尔值)允许在媒体查询中转换px。
38 // minPixelValue: 3 // 设置要替换的最小像素值(3px会被转rem)。 默认 0
39 // })
40 // ]
41 // }
42 // }
43 // },
44 configureWebpack: {
45 name: name,
46 resolve: {
47 alias: {
48 '@': resolve('src')
49 }
50 }
51 },
52 chainWebpack(config) {
53 config.plugins.delete('preload') // TODO: need test
54 config.plugins.delete('prefetch') // TODO: need test
55 // set preserveWhitespace
56 config.module
57 .rule('vue')
58 .use('vue-loader')
59 .loader('vue-loader')
60 .tap(options => {
61 options.compilerOptions.preserveWhitespace = true
62 return options
63 })
64 .end()
65
66 config
67 // https://webpack.js.org/configuration/devtool/#development
68 .when(process.env.NODE_ENV === 'development', config =>
69 config.devtool('cheap-source-map')
70 )
71
72 config.when(process.env.NODE_ENV !== 'development', config => {
73 console.log(config)
74 config
75 .plugin('ScriptExtHtmlWebpackPlugin')
76 .after('html')
77 .use('script-ext-html-webpack-plugin', [
78 {
79 // `runtime` must same as runtimeChunk name. default is `runtime`
80 inline: /runtime\..*\.js$/
81 }
82 ])
83 .end()
84 config.optimization.splitChunks({
85 chunks: 'all',
86 cacheGroups: {
87 libs: {
88 name: 'chunk-libs',
89 test: /[\\/]node_modules[\\/]/,
90 priority: 10,
91 chunks: 'initial' // only package third parties that are initially dependent
92 },
93 // elementUI: {
94 // name: 'chunk-elementUI', // split elementUI into a single package
95 // priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
96 // test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
97 // },
98 commons: {
99 name: 'chunk-commons',
100 test: resolve('src/components'), // can customize your rules
101 minChunks: 3, // minimum common number
102 priority: 5,
103 reuseExistingChunk: true
104 }
105 }
106 })
107 config.optimization.runtimeChunk('single')
108 })
109 }
110 }
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!