diff --git a/README-zh.md b/README-zh.md index d248632..5b6f7bd 100644 --- a/README-zh.md +++ b/README-zh.md @@ -79,6 +79,10 @@ npm run lint -- --fix 更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/) +## 购买贴纸 + +你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,我们将获得 2 元的捐赠。 + ## Demo ![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif) diff --git a/mock/index.js b/mock/index.js index 90e2ffe..aca99f4 100644 --- a/mock/index.js +++ b/mock/index.js @@ -50,18 +50,4 @@ export function mockXHR() { } } -// for mock server -const responseFake = (url, type, respond) => { - return { - url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`), - type: type || 'get', - response(req, res) { - console.log('request invoke:' + req.path) - res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) - } - } -} - -export default mocks.map(route => { - return responseFake(route.url, route.type, route.response) -}) +export default mocks diff --git a/mock/mock-server.js b/mock/mock-server.js index 4c4cb2a..806fdac 100644 --- a/mock/mock-server.js +++ b/mock/mock-server.js @@ -2,17 +2,21 @@ const chokidar = require('chokidar') const bodyParser = require('body-parser') const chalk = require('chalk') const path = require('path') +const Mock = require('mockjs') const mockDir = path.join(process.cwd(), 'mock') function registerRoutes(app) { let mockLastIndex const { default: mocks } = require('./index.js') - for (const mock of mocks) { + const mocksForServer = mocks.map(route => { + return responseFake(route.url, route.type, route.response) + }) + for (const mock of mocksForServer) { app[mock.type](mock.url, mock.response) mockLastIndex = app._router.stack.length } - const mockRoutesLength = Object.keys(mocks).length + const mockRoutesLength = Object.keys(mocksForServer).length return { mockRoutesLength: mockRoutesLength, mockStartIndex: mockLastIndex - mockRoutesLength @@ -27,6 +31,18 @@ function unregisterRoutes() { }) } +// for mock server +const responseFake = (url, type, respond) => { + return { + url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`), + type: type || 'get', + response(req, res) { + console.log('request invoke:' + req.path) + res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) + } + } +} + module.exports = app => { // es6 polyfill require('@babel/register') diff --git a/package.json b/package.json index ba2e9e2..5a98844 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-admin-template", - "version": "4.2.1", + "version": "4.3.0", "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint", "author": "Pan ", "license": "MIT", @@ -45,11 +45,10 @@ "eslint-plugin-vue": "5.2.2", "html-webpack-plugin": "3.2.0", "mockjs": "1.0.1-beta3", - "node-sass": "^4.9.0", "runjs": "^4.3.2", + "sass": "^1.26.8", "sass-loader": "^7.1.0", "script-ext-html-webpack-plugin": "2.1.3", - "script-loader": "0.7.2", "serve-static": "^1.13.2", "svg-sprite-loader": "4.1.3", "svgo": "1.2.2", diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue index 9a3318e..b07ded2 100644 --- a/src/components/SvgIcon/index.vue +++ b/src/components/SvgIcon/index.vue @@ -1,7 +1,7 @@ diff --git a/src/layout/components/Sidebar/Link.vue b/src/layout/components/Sidebar/Link.vue index eb4dd10..530b3d5 100644 --- a/src/layout/components/Sidebar/Link.vue +++ b/src/layout/components/Sidebar/Link.vue @@ -1,7 +1,5 @@ - @@ -16,19 +14,28 @@ export default { required: true } }, + computed: { + isExternal() { + return isExternal(this.to) + }, + type() { + if (this.isExternal) { + return 'a' + } + return 'router-link' + } + }, methods: { - linkProps(url) { - if (isExternal(url)) { + linkProps(to) { + if (this.isExternal) { return { - is: 'a', - href: url, + href: to, target: '_blank', rel: 'noopener' } } return { - is: 'router-link', - to: url + to: to } } } diff --git a/src/utils/index.js b/src/utils/index.js index 7e3fc1a..37ae434 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -9,7 +9,7 @@ * @returns {string | null} */ export function parseTime(time, cFormat) { - if (arguments.length === 0) { + if (arguments.length === 0 || !time) { return null } const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' @@ -17,9 +17,17 @@ export function parseTime(time, cFormat) { if (typeof time === 'object') { date = time } else { - if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { - time = parseInt(time) + if ((typeof time === 'string')) { + if ((/^[0-9]+$/.test(time))) { + // support "1548221490638" + time = parseInt(time) + } else { + // support safari + // https://stackoverflow.com/questions/4310953/invalid-date-in-safari + time = time.replace(new RegExp(/-/gm), '/') + } } + if ((typeof time === 'number') && (time.toString().length === 10)) { time = time * 1000 } diff --git a/tests/unit/utils/parseTime.spec.js b/tests/unit/utils/parseTime.spec.js index 41d1b02..56045af 100644 --- a/tests/unit/utils/parseTime.spec.js +++ b/tests/unit/utils/parseTime.spec.js @@ -5,6 +5,9 @@ describe('Utils:parseTime', () => { it('timestamp', () => { expect(parseTime(d)).toBe('2018-07-13 17:54:01') }) + it('timestamp string', () => { + expect(parseTime((d + ''))).toBe('2018-07-13 17:54:01') + }) it('ten digits timestamp', () => { expect(parseTime((d / 1000).toFixed(0))).toBe('2018-07-13 17:54:01') }) @@ -25,4 +28,8 @@ describe('Utils:parseTime', () => { it('empty argument', () => { expect(parseTime()).toBeNull() }) + + it('null', () => { + expect(parseTime(null)).toBeNull() + }) }) diff --git a/vue.config.js b/vue.config.js index bbc361f..aa4d75a 100644 --- a/vue.config.js +++ b/vue.config.js @@ -80,12 +80,6 @@ module.exports = { }) .end() - config - // https://webpack.js.org/configuration/devtool/#development - .when(process.env.NODE_ENV === 'development', - config => config.devtool('cheap-source-map') - ) - config .when(process.env.NODE_ENV !== 'development', config => {