Merge pull request #1 from PanJiaChen/master

release
This commit is contained in:
Hustwhw 2018-07-20 13:59:19 -04:00 committed by GitHub
commit cfc6aca923
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 563 additions and 376 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@ dist/
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
**/*.log
test/unit/coverage test/unit/coverage
test/e2e/reports test/e2e/reports

View File

@ -152,7 +152,7 @@ npm run dev
# 构建测试环境 # 构建测试环境
npm run build:sit npm run build:sit
# 构建生环境 # 构建生环境
npm run build:prod npm run build:prod
``` ```

View File

@ -8,9 +8,10 @@ const chalk = require('chalk')
const webpack = require('webpack') const webpack = require('webpack')
const config = require('../config') const config = require('../config')
const webpackConfig = require('./webpack.prod.conf') const webpackConfig = require('./webpack.prod.conf')
const server = require('pushstate-server') var connect = require('connect');
var serveStatic = require('serve-static')
var spinner = ora('building for '+ process.env.env_config+ ' environment...' ) const spinner = ora('building for ' + process.env.env_config + ' environment...')
spinner.start() spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
@ -36,13 +37,20 @@ rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
' Tip: built files are meant to be served over an HTTP server.\n' + ' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n' ' Opening index.html over file:// won\'t work.\n'
)) ))
if (process.env.npm_config_preview) { if (process.env.npm_config_preview) {
server.start({ const port = 9526
port: 9526, const host = "http://localhost:" + port
directory: './dist', const basePath = config.build.assetsPublicPath
file: '/index.html' const app = connect()
app.use(basePath, serveStatic('./dist', {
'index': ['index.html', '/']
}))
app.listen(port, function () {
console.log(chalk.green(`> Listening at http://localhost:${port}${basePath}`))
}); });
console.log('> Listening at ' + 'http://localhost:9526' + '\n')
} }
}) })
}) })

View File

@ -1,6 +1,6 @@
{ {
"name": "vue-element-admin", "name": "vue-element-admin",
"version": "3.7.1", "version": "3.7.2",
"description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features", "description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
"author": "Pan <panfree23@gmail.com>", "author": "Pan <panfree23@gmail.com>",
"license": "MIT", "license": "MIT",
@ -9,7 +9,14 @@
"build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js", "build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
"build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js", "build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js",
"lint": "eslint --ext .js,.vue src", "lint": "eslint --ext .js,.vue src",
"test": "npm run lint" "test": "npm run lint",
"precommit": "lint-staged"
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
}, },
"keywords": [ "keywords": [
"vue", "vue",
@ -29,6 +36,7 @@
"axios": "0.17.1", "axios": "0.17.1",
"clipboard": "1.7.1", "clipboard": "1.7.1",
"codemirror": "5.32.0", "codemirror": "5.32.0",
"connect": "3.6.6",
"driver.js": "0.5.2", "driver.js": "0.5.2",
"dropzone": "5.2.0", "dropzone": "5.2.0",
"echarts": "3.8.5", "echarts": "3.8.5",
@ -42,6 +50,7 @@
"normalize.css": "7.0.0", "normalize.css": "7.0.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"screenfull": "3.3.2", "screenfull": "3.3.2",
"serve-static": "1.13.2",
"showdown": "1.8.5", "showdown": "1.8.5",
"simplemde": "1.11.2", "simplemde": "1.11.2",
"sortablejs": "1.7.0", "sortablejs": "1.7.0",
@ -79,6 +88,8 @@
"file-loader": "1.1.5", "file-loader": "1.1.5",
"friendly-errors-webpack-plugin": "1.6.1", "friendly-errors-webpack-plugin": "1.6.1",
"html-webpack-plugin": "2.30.1", "html-webpack-plugin": "2.30.1",
"husky": "0.14.3",
"lint-staged": "7.2.0",
"node-notifier": "5.1.2", "node-notifier": "5.1.2",
"node-sass": "^4.7.2", "node-sass": "^4.7.2",
"optimize-css-assets-webpack-plugin": "3.2.0", "optimize-css-assets-webpack-plugin": "3.2.0",
@ -87,7 +98,6 @@
"postcss-import": "11.0.0", "postcss-import": "11.0.0",
"postcss-loader": "2.0.9", "postcss-loader": "2.0.9",
"postcss-url": "7.3.0", "postcss-url": "7.3.0",
"pushstate-server": "3.0.1",
"rimraf": "2.6.2", "rimraf": "2.6.2",
"sass-loader": "6.0.6", "sass-loader": "6.0.6",
"script-loader": "0.7.2", "script-loader": "0.7.2",

View File

@ -1,6 +1,6 @@
<template> <template>
<a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github"> <a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:#40c9c6; color:#fff; position: absolute; top: 84px; border: 0; right: 0;" <svg width="80" height="80" viewBox="0 0 250 250" style="fill:#40c9c6; color:#fff;"
aria-hidden="true"> aria-hidden="true">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path> <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"

View File

@ -84,6 +84,7 @@ export default {
imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'], imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
default_link_target: '_blank', default_link_target: '_blank',
link_title: false, link_title: false,
nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
init_instance_callback: editor => { init_instance_callback: editor => {
if (_this.value) { if (_this.value) {
editor.setContent(_this.value) editor.setContent(_this.value)

View File

@ -41,6 +41,11 @@ export default {
return return
} }
const rawFile = files[0] // only use files[0] const rawFile = files[0] // only use files[0]
if (!this.isExcel(rawFile)) {
this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
return false
}
this.upload(rawFile) this.upload(rawFile)
e.stopPropagation() e.stopPropagation()
e.preventDefault() e.preventDefault()
@ -110,6 +115,9 @@ export default {
headers.push(hdr) headers.push(hdr)
} }
return headers return headers
},
isExcel(file) {
return /\.(xlsx|xls|csv)$/.test(file.name)
} }
} }
} }

View File

@ -29,9 +29,13 @@ export default {
mixChart: 'Mix Chart', mixChart: 'Mix Chart',
example: 'Example', example: 'Example',
nested: 'Nested Routes', nested: 'Nested Routes',
bar: 'Bar', menu1: 'Menu 1',
barProfile: 'Profile', 'menu1-1': 'Menu 1-1',
barPosts: 'Posts', 'menu1-2': 'Menu 1-2',
'menu1-2-1': 'Menu 1-2-1',
'menu1-2-2': 'Menu 1-2-2',
'menu1-3': 'Menu 1-3',
menu2: 'Menu 2',
Table: 'Table', Table: 'Table',
dynamicTable: 'Dynamic Table', dynamicTable: 'Dynamic Table',
dragTable: 'Drag Table', dragTable: 'Drag Table',

View File

@ -20,8 +20,11 @@ const messages = {
} }
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: Cookies.get('language') || 'en', // set locale // set locale
messages // set locale messages // options: en or zh
locale: Cookies.get('language') || 'en',
// set locale messages
messages
}) })
export default i18n export default i18n

View File

@ -29,9 +29,13 @@ export default {
mixChart: '混合图表', mixChart: '混合图表',
example: '综合实例', example: '综合实例',
nested: '路由嵌套', nested: '路由嵌套',
bar: 'Bar', menu1: '菜单1',
barProfile: 'Profile', 'menu1-1': '菜单1-1',
barPosts: 'Posts', 'menu1-2': '菜单1-2',
'menu1-2-1': '菜单1-2-1',
'menu1-2-2': '菜单1-2-2',
'menu1-3': '菜单1-3',
menu2: '菜单2',
Table: 'Table', Table: 'Table',
dynamicTable: '动态Table', dynamicTable: '动态Table',
dragTable: '拖拽Table', dragTable: '拖拽Table',

View File

@ -202,7 +202,7 @@ export const asyncRouterMap = [
{ {
path: '/nested', path: '/nested',
component: Layout, component: Layout,
redirect: '/nested/bar/profile', redirect: '/nested/menu1/menu1-1',
name: 'nested', name: 'nested',
meta: { meta: {
title: 'nested', title: 'nested',
@ -210,24 +210,52 @@ export const asyncRouterMap = [
}, },
children: [ children: [
{ {
path: '/nested/bar', // Must write the full path path: 'menu1',
component: () => import('@/views/nested/bar/index'), // Parent router-view component: () => import('@/views/nested/menu1/index'), // Parent router-view
name: 'bar', name: 'menu1',
meta: { title: 'bar' }, meta: { title: 'menu1' },
redirect: '/nested/menu1/menu1-1',
children: [ children: [
{ {
path: 'profile', path: 'menu1-1',
component: () => import('@/views/nested/bar/profile'), component: () => import('@/views/nested/menu1/menu1-1'),
name: 'bar-profile', name: 'menu1-1',
meta: { title: 'barProfile' } meta: { title: 'menu1-1' }
}, },
{ {
path: 'posts', path: 'menu1-2',
component: () => import('@/views/nested/bar/posts'), component: () => import('@/views/nested/menu1/menu1-2'),
name: 'bar-posts', name: 'menu1-2',
meta: { title: 'barPosts' } redirect: '/nested/menu1/menu1-2/menu1-2-1',
meta: { title: 'menu1-2' },
children: [
{
path: 'menu1-2-1',
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),
name: 'menu1-2-1',
meta: { title: 'menu1-2-1' }
},
{
path: 'menu1-2-2',
component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),
name: 'menu1-2-2',
meta: { title: 'menu1-2-2' }
} }
] ]
},
{
path: 'menu1-3',
component: () => import('@/views/nested/menu1/menu1-3'),
name: 'menu1-3',
meta: { title: 'menu1-3' }
}
]
},
{
path: 'menu2',
name: 'menu2',
component: () => import('@/views/nested/menu2/index'),
meta: { title: 'menu2' }
} }
] ]
}, },

View File

@ -4,6 +4,7 @@
min-height: 100%; min-height: 100%;
transition: margin-left .28s; transition: margin-left .28s;
margin-left: 180px; margin-left: 180px;
position: relative;
} }
// 侧边栏 // 侧边栏
.sidebar-container { .sidebar-container {

69
src/vendor/Blob.js vendored
View File

@ -33,37 +33,37 @@
var var
get_class = function (object) { get_class = function (object) {
return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
} },
, FakeBlobBuilder = function BlobBuilder() { FakeBlobBuilder = function BlobBuilder() {
this.data = []; this.data = [];
} },
, FakeBlob = function Blob(data, type, encoding) { FakeBlob = function Blob(data, type, encoding) {
this.data = data; this.data = data;
this.size = data.length; this.size = data.length;
this.type = type; this.type = type;
this.encoding = encoding; this.encoding = encoding;
} },
, FBB_proto = FakeBlobBuilder.prototype FBB_proto = FakeBlobBuilder.prototype,
, FB_proto = FakeBlob.prototype FB_proto = FakeBlob.prototype,
, FileReaderSync = view.FileReaderSync FileReaderSync = view.FileReaderSync,
, FileException = function(type) { FileException = function (type) {
this.code = this[this.name = type]; this.code = this[this.name = type];
} },
, file_ex_codes = ( file_ex_codes = (
"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " +
+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
).split(" ") ).split(" "),
, file_ex_code = file_ex_codes.length file_ex_code = file_ex_codes.length,
, real_URL = view.URL || view.webkitURL || view real_URL = view.URL || view.webkitURL || view,
, real_create_object_URL = real_URL.createObjectURL real_create_object_URL = real_URL.createObjectURL,
, real_revoke_object_URL = real_URL.revokeObjectURL real_revoke_object_URL = real_URL.revokeObjectURL,
, URL = real_URL URL = real_URL,
, btoa = view.btoa btoa = view.btoa,
, atob = view.atob atob = view.atob
, ArrayBuffer = view.ArrayBuffer ,
, Uint8Array = view.Uint8Array ArrayBuffer = view.ArrayBuffer,
; Uint8Array = view.Uint8Array;
FakeBlob.fake = FB_proto.fake = true; FakeBlob.fake = FB_proto.fake = true;
while (file_ex_code--) { while (file_ex_code--) {
FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
@ -73,9 +73,8 @@
} }
URL.createObjectURL = function (blob) { URL.createObjectURL = function (blob) {
var var
type = blob.type type = blob.type,
, data_URI_header data_URI_header;
;
if (type === null) { if (type === null) {
type = "application/octet-stream"; type = "application/octet-stream";
} }
@ -85,7 +84,8 @@
return data_URI_header + ";base64," + blob.data; return data_URI_header + ";base64," + blob.data;
} else if (blob.encoding === "URI") { } else if (blob.encoding === "URI") {
return data_URI_header + "," + decodeURIComponent(blob.data); return data_URI_header + "," + decodeURIComponent(blob.data);
} if (btoa) { }
if (btoa) {
return data_URI_header + ";base64," + btoa(blob.data); return data_URI_header + ";base64," + btoa(blob.data);
} else { } else {
return data_URI_header + "," + encodeURIComponent(blob.data); return data_URI_header + "," + encodeURIComponent(blob.data);
@ -104,11 +104,10 @@
// decode data to a binary string // decode data to a binary string
if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
var var
str = "" str = "",
, buf = new Uint8Array(data) buf = new Uint8Array(data),
, i = 0 i = 0,
, buf_len = buf.length buf_len = buf.length;
;
for (; i < buf_len; i++) { for (; i < buf_len; i++) {
str += String.fromCharCode(buf[i]); str += String.fromCharCode(buf[i]);
} }
@ -152,9 +151,7 @@
type = null; type = null;
} }
return new FakeBlob( return new FakeBlob(
this.data.slice(start, args > 1 ? end : this.data.length) this.data.slice(start, args > 1 ? end : this.data.length), type, this.encoding
, type
, this.encoding
); );
}; };
FB_proto.toString = function () { FB_proto.toString = function () {

View File

@ -29,15 +29,24 @@ function generateArray(table) {
if (rowspan || colspan) { if (rowspan || colspan) {
rowspan = rowspan || 1; rowspan = rowspan || 1;
colspan = colspan || 1; colspan = colspan || 1;
ranges.push({s: {r: R, c: outRow.length}, e: {r: R + rowspan - 1, c: outRow.length + colspan - 1}}); ranges.push({
s: {
r: R,
c: outRow.length
},
e: {
r: R + rowspan - 1,
c: outRow.length + colspan - 1
} }
; });
};
//Handle Value //Handle Value
outRow.push(cellValue !== "" ? cellValue : null); outRow.push(cellValue !== "" ? cellValue : null);
//Handle Colspan //Handle Colspan
if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null); if (colspan)
for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
} }
out.push(outRow); out.push(outRow);
} }
@ -52,16 +61,30 @@ function datenum(v, date1904) {
function sheet_from_array_of_arrays(data, opts) { function sheet_from_array_of_arrays(data, opts) {
var ws = {}; var ws = {};
var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}}; var range = {
s: {
c: 10000000,
r: 10000000
},
e: {
c: 0,
r: 0
}
};
for (var R = 0; R != data.length; ++R) { for (var R = 0; R != data.length; ++R) {
for (var C = 0; C != data[R].length; ++C) { for (var C = 0; C != data[R].length; ++C) {
if (range.s.r > R) range.s.r = R; if (range.s.r > R) range.s.r = R;
if (range.s.c > C) range.s.c = C; if (range.s.c > C) range.s.c = C;
if (range.e.r < R) range.e.r = R; if (range.e.r < R) range.e.r = R;
if (range.e.c < C) range.e.c = C; if (range.e.c < C) range.e.c = C;
var cell = {v: data[R][C]}; var cell = {
v: data[R][C]
};
if (cell.v == null) continue; if (cell.v == null) continue;
var cell_ref = XLSX.utils.encode_cell({c: C, r: R}); var cell_ref = XLSX.utils.encode_cell({
c: C,
r: R
});
if (typeof cell.v === 'number') cell.t = 'n'; if (typeof cell.v === 'number') cell.t = 'n';
else if (typeof cell.v === 'boolean') cell.t = 'b'; else if (typeof cell.v === 'boolean') cell.t = 'b';
@ -69,8 +92,7 @@ function sheet_from_array_of_arrays(data, opts) {
cell.t = 'n'; cell.t = 'n';
cell.z = XLSX.SSF._table[14]; cell.z = XLSX.SSF._table[14];
cell.v = datenum(cell.v); cell.v = datenum(cell.v);
} } else cell.t = 's';
else cell.t = 's';
ws[cell_ref] = cell; ws[cell_ref] = cell;
} }
@ -101,7 +123,8 @@ export function export_table_to_excel(id) {
var data = oo[0]; var data = oo[0];
var ws_name = "SheetJS"; var ws_name = "SheetJS";
var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); var wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
/* add ranges to worksheet */ /* add ranges to worksheet */
// ws['!cols'] = ['apple', 'banan']; // ws['!cols'] = ['apple', 'banan'];
@ -111,30 +134,49 @@ export function export_table_to_excel(id) {
wb.SheetNames.push(ws_name); wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws; wb.Sheets[ws_name] = ws;
var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); var wbout = XLSX.write(wb, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx") saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), "test.xlsx")
} }
export function export_json_to_excel({header, data, filename='excel-list', autoWidth=true}={}) { export function export_json_to_excel({
header,
data,
filename,
autoWidth = true
} = {}) {
/* original data */ /* original data */
filename = filename || 'excel-list'
data = [...data] data = [...data]
data.unshift(header); data.unshift(header);
var ws_name = "SheetJS"; var ws_name = "SheetJS";
var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); var wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
if (autoWidth) { if (autoWidth) {
/*设置worksheet每列的最大宽度*/ /*设置worksheet每列的最大宽度*/
const colWidth = data.map(row => row.map(val => { const colWidth = data.map(row => row.map(val => {
/*先判断是否为null/undefined*/ /*先判断是否为null/undefined*/
if (val == null) { if (val == null) {
return {'wch': 10}; return {
'wch': 10
};
} }
/*再判断是否为中文*/ /*再判断是否为中文*/
else if (val.toString().charCodeAt(0) > 255) { else if (val.toString().charCodeAt(0) > 255) {
return {'wch': val.toString().length * 2}; return {
'wch': val.toString().length * 2
};
} else { } else {
return {'wch': val.toString().length}; return {
'wch': val.toString().length
};
} }
})) }))
/*以第一行为初始值*/ /*以第一行为初始值*/
@ -153,6 +195,12 @@ export function export_json_to_excel({header, data, filename='excel-list', autoW
wb.SheetNames.push(ws_name); wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws; wb.Sheets[ws_name] = ws;
var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); var wbout = XLSX.write(wb, {
saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), filename + ".xlsx"); bookType: 'xlsx',
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), filename + ".xlsx");
} }

View File

@ -14,7 +14,9 @@ export function export_txt_to_zip(th, jsonData, txtName, zipName) {
txtData += `${tempStr}\r\n` txtData += `${tempStr}\r\n`
}) })
zip.file(`${txt_name}.txt`, txtData) zip.file(`${txt_name}.txt`, txtData)
zip.generateAsync({type:"blob"}).then((blob) => { zip.generateAsync({
type: "blob"
}).then((blob) => {
saveAs(blob, `${zip_name}.zip`) saveAs(blob, `${zip_name}.zip`)
}, (err) => { }, (err) => {
alert('导出失败') alert('导出失败')

View File

@ -34,7 +34,7 @@ export default {
}, },
clipboardSuccess() { clipboardSuccess() {
this.$message({ this.$message({
message: '复制成功', message: 'Copy successfully',
type: 'success', type: 'success',
duration: 1500 duration: 1500
}) })

View File

@ -72,7 +72,7 @@ export default {
} }
}, },
methods: { methods: {
setLocalStorgae() { setLocalStorage() {
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(this.todos)) window.localStorage.setItem(STORAGE_KEY, JSON.stringify(this.todos))
}, },
addTodo(e) { addTodo(e) {
@ -82,30 +82,30 @@ export default {
text, text,
done: false done: false
}) })
this.setLocalStorgae() this.setLocalStorage()
} }
e.target.value = '' e.target.value = ''
}, },
toggleTodo(val) { toggleTodo(val) {
val.done = !val.done val.done = !val.done
this.setLocalStorgae() this.setLocalStorage()
}, },
deleteTodo(todo) { deleteTodo(todo) {
this.todos.splice(this.todos.indexOf(todo), 1) this.todos.splice(this.todos.indexOf(todo), 1)
this.setLocalStorgae() this.setLocalStorage()
}, },
editTodo({ todo, value }) { editTodo({ todo, value }) {
todo.text = value todo.text = value
this.setLocalStorgae() this.setLocalStorage()
}, },
clearCompleted() { clearCompleted() {
this.todos = this.todos.filter(todo => !todo.done) this.todos = this.todos.filter(todo => !todo.done)
this.setLocalStorgae() this.setLocalStorage()
}, },
toggleAll({ done }) { toggleAll({ done }) {
this.todos.forEach(todo => { this.todos.forEach(todo => {
todo.done = done todo.done = done
this.setLocalStorgae() this.setLocalStorage()
}) })
} }
}, },

View File

@ -2,7 +2,7 @@
<el-table :data="list" style="width: 100%;padding-top: 15px;"> <el-table :data="list" style="width: 100%;padding-top: 15px;">
<el-table-column label="Order_No" min-width="200"> <el-table-column label="Order_No" min-width="200">
<template slot-scope="scope"> <template slot-scope="scope">
{{scope.row.order_no}} {{scope.row.order_no | orderNoFilter}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="Price" width="195" align="center"> <el-table-column label="Price" width="195" align="center">
@ -34,6 +34,9 @@ export default {
pending: 'danger' pending: 'danger'
} }
return statusMap[status] return statusMap[status]
},
orderNoFilter(str) {
return str.substring(0, 30)
} }
}, },
created() { created() {

View File

@ -1,6 +1,7 @@
<template> <template>
<div class="dashboard-editor-container"> <div class="dashboard-editor-container">
<github-corner></github-corner>
<github-corner style="position: absolute; top: 0px; border: 0; right: 0;"></github-corner>
<panel-group @handleSetLineChartData="handleSetLineChartData"></panel-group> <panel-group @handleSetLineChartData="handleSetLineChartData"></panel-group>
@ -30,10 +31,10 @@
<el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;"> <el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;">
<transaction-table></transaction-table> <transaction-table></transaction-table>
</el-col> </el-col>
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 5}" style="margin-bottom:30px;"> <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
<todo-list></todo-list> <todo-list></todo-list>
</el-col> </el-col>
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 5}" style="margin-bottom:30px;" > <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
<box-card></box-card> <box-card></box-card>
</el-col> </el-col>
</el-row> </el-row>
@ -41,6 +42,7 @@
</div> </div>
</template> </template>
<script> <script>
import GithubCorner from '@/components/GithubCorner' import GithubCorner from '@/components/GithubCorner'
import PanelGroup from './components/PanelGroup' import PanelGroup from './components/PanelGroup'

View File

@ -4,10 +4,10 @@
<pan-thumb style="float: left" :image="avatar"> Your roles: <pan-thumb style="float: left" :image="avatar"> Your roles:
<span class="pan-info-roles" :key='item' v-for="item in roles">{{item}}</span> <span class="pan-info-roles" :key='item' v-for="item in roles">{{item}}</span>
</pan-thumb> </pan-thumb>
<github-corner></github-corner> <github-corner style="position: absolute; top: 0px; border: 0; right: 0;"></github-corner>
<div class="info-container"> <div class="info-container">
<span class="display_name">{{name}}</span> <span class="display_name">{{name}}</span>
<span style="font-size:20px;padding-top:20px;display:inline-block;">editor : dashboard</span> <span style="font-size:20px;padding-top:20px;display:inline-block;">Editor's Dashboard</span>
</div> </div>
</div> </div>
<div> <div>

View File

@ -57,6 +57,7 @@ export default {
.pan-back-btn { .pan-back-btn {
background: #008489; background: #008489;
color: #fff; color: #fff;
border: none!important;
} }
.pan-gif { .pan-gif {
margin: 0 auto; margin: 0 auto;

View File

@ -1,5 +1,5 @@
<template> <template>
<div style="background:#f0f2f5;margin-top: -20px;height:100%;"> <div class="wscn-http404-container">
<div class="wscn-http404"> <div class="wscn-http404">
<div class="pic-404"> <div class="pic-404">
<img class="pic-404__parent" :src="img_404" alt="404"> <img class="pic-404__parent" :src="img_404" alt="404">
@ -34,24 +34,28 @@ export default {
}, },
computed: { computed: {
message() { message() {
return '特朗普说这个页面你不能进......' return '网管说这个页面你不能进......'
} }
} }
} }
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.wscn-http404-container{
transform: translate(-50%,-50%);
position: absolute;
top: 40%;
left: 50%;
}
.wscn-http404 { .wscn-http404 {
position: relative; position: relative;
width: 1200px; width: 1200px;
margin: 20px auto 60px; padding: 0 50px;
padding: 0 100px;
overflow: hidden; overflow: hidden;
.pic-404 { .pic-404 {
position: relative; position: relative;
float: left; float: left;
width: 600px; width: 600px;
padding: 150px 0;
overflow: hidden; overflow: hidden;
&__parent { &__parent {
width: 100%; width: 100%;
@ -163,7 +167,7 @@ export default {
position: relative; position: relative;
float: left; float: left;
width: 300px; width: 300px;
padding: 150px 0; padding: 30px 0;
overflow: hidden; overflow: hidden;
&__oops { &__oops {
font-size: 32px; font-size: 32px;
@ -179,7 +183,8 @@ export default {
&__headline { &__headline {
font-size: 20px; font-size: 20px;
line-height: 24px; line-height: 24px;
color: #1482f0; color: #222;
font-weight: bold;
opacity: 0; opacity: 0;
margin-bottom: 10px; margin-bottom: 10px;
animation-name: slideUp; animation-name: slideUp;

View File

@ -16,7 +16,7 @@
<Warning /> <Warning />
<el-col :span="21"> <el-col :span="24">
<el-form-item style="margin-bottom: 40px;" prop="title"> <el-form-item style="margin-bottom: 40px;" prop="title">
<MDinput name="name" v-model="postForm.title" required :maxlength="100"> <MDinput name="name" v-model="postForm.title" required :maxlength="100">
标题 标题
@ -34,14 +34,14 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="10">
<el-form-item label-width="80px" label="发布时间:" class="postInfo-container-item"> <el-form-item label-width="80px" label="发布时间:" class="postInfo-container-item">
<el-date-picker v-model="postForm.display_time" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期时间"> <el-date-picker v-model="postForm.display_time" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期时间">
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="6">
<el-form-item label-width="60px" label="重要性:" class="postInfo-container-item"> <el-form-item label-width="60px" label="重要性:" class="postInfo-container-item">
<el-rate style="margin-top:8px;" v-model="postForm.importance" :max='3' :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :low-threshold="1" <el-rate style="margin-top:8px;" v-model="postForm.importance" :max='3' :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :low-threshold="1"
:high-threshold="3"> :high-threshold="3">

View File

@ -33,6 +33,7 @@ export default {
classObj() { classObj() {
return { return {
hideSidebar: !this.sidebar.opened, hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation, withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === 'mobile' mobile: this.device === 'mobile'
} }
@ -53,6 +54,10 @@ export default {
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; width: 100%;
&.mobile.openSidebar{
position: fixed;
top: 0;
}
} }
.drawer-bg { .drawer-bg {
background: #000; background: #000;

View File

@ -1,5 +1,5 @@
<template> <template>
<section class="app-main" style="min-height: 100%"> <section class="app-main">
<transition name="fade-transform" mode="out-in"> <transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews"> <keep-alive :include="cachedViews">
<router-view :key="key"></router-view> <router-view :key="key"></router-view>
@ -21,3 +21,13 @@ export default {
} }
} }
</script> </script>
<style scoped>
.app-main {
/*84 = navbar + tags-view = 50 +34 */
min-height: calc(100vh - 84px);
position: relative;
overflow: hidden;
}
</style>

View File

@ -1,26 +1,24 @@
<template> <template>
<div class="menu-wrapper"> <div v-if="!item.hidden&&item.children" class="menu-wrapper">
<template v-for="item in routes" v-if="!item.hidden&&item.children">
<router-link v-if="hasOneShowingChildren(item.children) && !item.children[0].children&&!item.alwaysShow" :to="item.path+'/'+item.children[0].path" <router-link v-if="hasOneShowingChild(item.children) && !onlyOneChild.children&&!item.alwaysShow" :to="resolvePath(onlyOneChild.path)">
:key="item.children[0].name"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<el-menu-item :index="item.path+'/'+item.children[0].path" :class="{'submenu-title-noDropdown':!isNest}"> <svg-icon v-if="onlyOneChild.meta&&onlyOneChild.meta.icon" :icon-class="onlyOneChild.meta.icon"></svg-icon>
<svg-icon v-if="item.children[0].meta&&item.children[0].meta.icon" :icon-class="item.children[0].meta.icon"></svg-icon> <span v-if="onlyOneChild.meta&&onlyOneChild.meta.title" slot="title">{{generateTitle(onlyOneChild.meta.title)}}</span>
<span v-if="item.children[0].meta&&item.children[0].meta.title" slot="title">{{generateTitle(item.children[0].meta.title)}}</span>
</el-menu-item> </el-menu-item>
</router-link> </router-link>
<el-submenu v-else :index="item.name||item.path" :key="item.name"> <el-submenu v-else :index="item.name||item.path">
<template slot="title"> <template slot="title">
<svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon> <svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon>
<span v-if="item.meta&&item.meta.title" slot="title">{{generateTitle(item.meta.title)}}</span> <span v-if="item.meta&&item.meta.title" slot="title">{{generateTitle(item.meta.title)}}</span>
</template> </template>
<template v-for="child in item.children" v-if="!child.hidden"> <template v-for="child in item.children" v-if="!child.hidden">
<sidebar-item :is-nest="true" class="nest-menu" v-if="child.children&&child.children.length>0" :routes="[child]" :key="child.path"></sidebar-item> <sidebar-item :is-nest="true" class="nest-menu" v-if="child.children&&child.children.length>0" :item="child" :key="child.path" :base-path="resolvePath(child.path)"></sidebar-item>
<router-link v-else :to="item.path+'/'+child.path" :key="child.name"> <router-link v-else :to="resolvePath(child.path)" :key="child.name">
<el-menu-item :index="item.path+'/'+child.path"> <el-menu-item :index="resolvePath(child.path)">
<svg-icon v-if="child.meta&&child.meta.icon" :icon-class="child.meta.icon"></svg-icon> <svg-icon v-if="child.meta&&child.meta.icon" :icon-class="child.meta.icon"></svg-icon>
<span v-if="child.meta&&child.meta.title" slot="title">{{generateTitle(child.meta.title)}}</span> <span v-if="child.meta&&child.meta.title" slot="title">{{generateTitle(child.meta.title)}}</span>
</el-menu-item> </el-menu-item>
@ -28,34 +26,54 @@
</template> </template>
</el-submenu> </el-submenu>
</template>
</div> </div>
</template> </template>
<script> <script>
import path from 'path'
import { generateTitle } from '@/utils/i18n' import { generateTitle } from '@/utils/i18n'
export default { export default {
name: 'SidebarItem', name: 'SidebarItem',
props: { props: {
routes: { // route object
type: Array item: {
type: Object,
required: true
}, },
isNest: { isNest: {
type: Boolean, type: Boolean,
default: false default: false
},
basePath: {
type: String,
default: ''
}
},
data() {
return {
onlyOneChild: null
} }
}, },
methods: { methods: {
hasOneShowingChildren(children) { hasOneShowingChild(children) {
const showingChildren = children.filter(item => { const showingChildren = children.filter(item => {
return !item.hidden if (item.hidden) {
return false
} else {
// temp set(will be used if only has one showing child )
this.onlyOneChild = item
return true
}
}) })
if (showingChildren.length === 1) { if (showingChildren.length === 1) {
return true return true
} }
return false return false
}, },
resolvePath(...paths) {
return path.resolve(this.basePath, ...paths)
},
generateTitle generateTitle
} }
} }

View File

@ -9,7 +9,7 @@
text-color="#bfcbd9" text-color="#bfcbd9"
active-text-color="#409EFF" active-text-color="#409EFF"
> >
<sidebar-item :routes="permission_routers"></sidebar-item> <sidebar-item v-for="route in permission_routers" :key="route.name" :item="route" :base-path="route.path"></sidebar-item>
</el-menu> </el-menu>
</el-scrollbar> </el-scrollbar>
</template> </template>

View File

@ -104,7 +104,8 @@ export default {
openMenu(tag, e) { openMenu(tag, e) {
this.visible = true this.visible = true
this.selectedTag = tag this.selectedTag = tag
this.left = e.clientX const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
this.left = e.clientX - offsetLeft + 15 // 15: margin right
this.top = e.clientY this.top = e.clientY
}, },
closeMenu() { closeMenu() {

View File

@ -1,22 +1,27 @@
<template> <template>
<div class="login-container"> <div class="login-container">
<el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left"> <el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left">
<div class="title-container"> <div class="title-container">
<h3 class="title">{{$t('login.title')}}</h3> <h3 class="title">{{$t('login.title')}}</h3>
<lang-select class="set-language"></lang-select> <lang-select class="set-language"></lang-select>
</div> </div>
<el-form-item prop="username"> <el-form-item prop="username">
<span class="svg-container svg-container_login"> <span class="svg-container svg-container_login">
<svg-icon icon-class="user" /> <svg-icon icon-class="user" />
</span> </span>
<el-input name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="username" /> <el-input name="username" type="text" v-model="loginForm.username" autoComplete="on" :placeholder="$t('login.username')"
/>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<span class="svg-container"> <span class="svg-container">
<svg-icon icon-class="password" /> <svg-icon icon-class="password" />
</span> </span>
<el-input name="password" :type="passwordType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="on" placeholder="password" /> <el-input name="password" :type="passwordType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="on"
:placeholder="$t('login.password')" />
<span class="show-pwd" @click="showPwd"> <span class="show-pwd" @click="showPwd">
<svg-icon icon-class="eye" /> <svg-icon icon-class="eye" />
</span> </span>

View File

@ -1,7 +0,0 @@
<template>
<div class="app-container">
<code>Parent View: Bar</code>
<img src="https://wpimg.wallstcn.com/be29a7d2-5ccf-4a2b-888d-8a6c2bbb7aac.png">
<router-view></router-view>
</div>
</template>

View File

@ -1,6 +0,0 @@
<template>
<div style="margin-top:30px;">
<el-alert title="Children: Posts" type="warning" :closable="false">
</el-alert>
</div>
</template>

View File

@ -1,6 +0,0 @@
<template>
<div style="margin-top:30px;">
<el-alert title="Children: Profile" type="success" :closable="false">
</el-alert>
</div>
</template>

View File

@ -0,0 +1,7 @@
<template >
<div style="padding:30px;">
<el-alert title="menu 1" :closable="false">
<router-view />
</el-alert>
</div>
</template>

View File

@ -0,0 +1,7 @@
<template >
<div style="padding:30px;">
<el-alert title="menu 1-1" type="success" :closable="false">
<router-view />
</el-alert>
</div>
</template>

View File

@ -0,0 +1,7 @@
<template>
<div style="padding:30px;">
<el-alert title="menu 1-2" type="success" :closable="false">
<router-view />
</el-alert>
</div>
</template>

View File

@ -0,0 +1,5 @@
<template functional>
<div style="padding:30px;">
<el-alert title="menu 1-2-1" type="warning" :closable="false" />
</div>
</template>

View File

@ -0,0 +1,5 @@
<template functional>
<div style="padding:30px;">
<el-alert title="menu 1-2-2" type="warning" :closable="false" />
</div>
</template>

View File

@ -0,0 +1,5 @@
<template functional>
<div style="padding:30px;">
<el-alert title="menu 1-3" type="success" :closable="false" />
</div>
</template>

View File

@ -0,0 +1,5 @@
<template>
<div style="padding:30px;">
<el-alert title="menu 2" :closable="false" />
</div>
</template>