This commit is contained in:
leij1ang 2017-09-17 06:39:34 +00:00 committed by GitHub
commit 888050318b
7 changed files with 387 additions and 353 deletions

View File

@ -1,6 +1,6 @@
<template>
<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:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;"
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:#4AB7BD; color:#fff; position: absolute; top: 0px; border: 0; right: 0;"
aria-hidden="true">
<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"

View File

@ -1,297 +1,291 @@
<template>
<div class="material-input__component" :class="computedClasses">
<input v-if="type === 'email'" type="email" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)"
@blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'url'" type="url" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)"
@blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'number'" type="number" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :max="max" :min="min" :minlength="minlength" :maxlength="maxlength"
:required="required" @focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'password'" type="password" class="material-input" :name="name" :id="id" :placeholder="placeholder"
v-model="valueCopy" :readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :max="max" :min="min" :required="required"
@focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'tel'" type="tel" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)"
@blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'text'" type="text" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :minlength="minlength" :maxlength="maxlength"
:required="required" @focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput">
<div :class="{iconClass:icon}">
<i class="el-input__icon material-input__icon" :class="['el-icon-' + icon]" v-if="icon"></i>
<input v-if="type === 'email'" type="email" class="material-input" :name="name"
:placeholder="fillPlaceHolder" v-model="currentValue"
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :required="required"
@focus="handleMdFocus"
@blur="handleMdBlur" @input="handleModelInput">
<input v-if="type === 'url'" type="url" class="material-input" :name="name"
:placeholder="fillPlaceHolder"
v-model="currentValue"
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :required="required"
@focus="handleMdFocus"
@blur="handleMdBlur" @input="handleModelInput">
<input v-if="type === 'number'" type="number" class="material-input" :name="name"
:placeholder="fillPlaceHolder" v-model="currentValue" :step="step"
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :max="max" :min="min"
:minlength="minlength" :maxlength="maxlength"
:required="required" @focus="handleMdFocus" @blur="handleMdBlur" @input="handleModelInput">
<input v-if="type === 'password'" type="password" class="material-input" :name="name"
:placeholder="fillPlaceHolder"
v-model="currentValue" :readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :max="max"
:min="min" :required="required"
@focus="handleMdFocus" @blur="handleMdBlur" @input="handleModelInput">
<input v-if="type === 'tel'" type="tel" class="material-input" :name="name"
:placeholder="fillPlaceHolder"
v-model="currentValue"
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :required="required"
@focus="handleMdFocus"
@blur="handleMdBlur" @input="handleModelInput">
<input v-if="type === 'text'" type="text" class="material-input" :name="name"
:placeholder="fillPlaceHolder" v-model="currentValue"
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :minlength="minlength"
:maxlength="maxlength"
:required="required" @focus="handleMdFocus" @blur="handleMdBlur" @input="handleModelInput">
<span class="material-input-bar"></span>
<span class="material-input-bar"></span>
<label class="material-label">
<slot></slot>
</label>
<label class="material-label">
<slot></slot>
</label>
<div v-if="errorMessages" class="material-errors">
<div v-for="error in computedErrors" class="material-error" :key='error'>
{{ error }}
</div>
</div>
</div>
</template>
<script>
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
export default {
name: 'material-input',
computed: {
computedErrors() {
return typeof this.errorMessages === 'string'
? [this.errorMessages] : this.errorMessages
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
export default {
name: 'md-input',
computed: {
computedClasses() {
return {
'material--active': this.focus,
'material--disabled': this.disabled,
'material--raised': Boolean(this.focus || this.currentValue) // has value
}
}
},
computedClasses() {
data() {
return {
'material--active': this.focus,
'material--disabled': this.disabled,
'material--has-errors': Boolean(!this.valid || (this.errorMessages && this.errorMessages.length)),
'material--raised': Boolean(this.focus || this.valueCopy || // has value
(this.placeholder && !this.valueCopy)) // has placeholder
currentValue: this.value,
focus: false,
fillPlaceHolder: null
}
},
methods: {
handleModelInput(event) {
const value = event.target.value
this.$emit('input', value)
if (this.$parent.$options.componentName === 'ElFormItem') {
if (this.validateEvent) {
this.$parent.$emit('el.form.change', [value])
}
}
this.$emit('change', value)
// this.handleValidation()
},
handleMdFocus(event) {
this.focus = true
this.$emit('focus', event)
if (this.placeholder && this.placeholder !== '') {
this.fillPlaceHolder = this.placeholder
}
},
handleMdBlur(event) {
this.focus = false
this.$emit('blur', event)
this.fillPlaceHolder = null
if (this.$parent.$options.componentName === 'ElFormItem') {
if (this.validateEvent) {
this.$parent.$emit('el.form.blur', [this.currentValue])
}
}
}
},
props: {
icon: String,
name: String,
type: {
type: String,
default: 'text'
},
value: [String, Number],
placeholder: String,
readonly: Boolean,
disabled: Boolean,
min: String,
max: String,
step: String,
minlength: Number,
maxlength: Number,
required: {
type: Boolean,
default: true
},
autoComplete: {
type: String,
default: 'off'
},
validateEvent: {
type: Boolean,
default: true
}
}
},
data() {
return {
valueCopy: null,
focus: false,
valid: true
}
},
beforeMount() {
// Here we are following the Vue2 convention on custom v-model:
// https://github.com/vuejs/vue/issues/2873#issuecomment-223759341
this.copyValue(this.value)
},
methods: {
handleModelInput(event) {
this.$emit('input', event.target.value, event)
this.handleValidation()
},
handleFocus(focused) {
this.focus = focused
},
handleValidation() {
this.valid = this.$el ? this.$el.querySelector('.material-input').validity.valid : this.valid
},
copyValue(value) {
this.valueCopy = value
this.handleValidation()
}
},
watch: {
value(newValue) {
this.copyValue(newValue)
}
},
props: {
id: {
type: String,
default: null
},
name: {
type: String,
default: null
},
type: {
type: String,
default: 'text'
},
value: {
default: null
},
placeholder: {
type: String,
default: null
},
readonly: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
min: {
type: String,
default: null
},
max: {
type: String,
default: null
},
minlength: {
type: Number,
default: null
},
maxlength: {
type: Number,
default: null
},
required: {
type: Boolean,
default: true
},
autocomplete: {
type: String,
default: 'off'
},
errorMessages: {
type: [Array, String],
default: null
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
// Fonts:
$font-size-base: 16px;
$font-size-small: 18px;
$font-size-smallest: 12px;
$font-weight-normal: normal;
// Utils
$spacer: 12px;
$transition: 0.2s ease all;
// Base clases:
%base-bar-pseudo {
content: '';
height: 1px;
width: 0;
bottom: 0;
// Fonts:
$font-size-base: 16px;
$font-size-small: 18px;
$font-size-smallest: 12px;
$font-weight-normal: normal;
$font-weight-bold: bold;
$apixel: 1px;
// Utils
$spacer: 12px;
$transition: 0.2s ease all;
$index: 0px;
$index-has-icon: 30px;
// Theme:
$color-white: white;
$color-grey: #9E9E9E;
$color-grey-light: #E0E0E0;
$color-blue: #2196F3;
$color-red: #F44336;
$color-black: black;
// Base clases:
%base-bar-pseudo {
content: '';
height: 1px;
width: 0;
bottom: 0;
position: absolute;
transition: $transition;
}
// Mixins:
@mixin slided-top() {
top: - ($font-size-base + $spacer);
left: 0;
font-size: $font-size-base;
font-weight: $font-weight-bold;
}
// Component:
.material-input__component {
margin-top: 36px;
position: relative;
* {
box-sizing: border-box;
}
.iconClass {
.material-input__icon {
position: absolute;
transition: $transition;
left: 0;
color: $color-blue;
top: $spacer;
width: $index-has-icon;
height: $font-size-base;
font-size: $font-size-base;
font-weight: $font-weight-normal;
pointer-events: none;
}
.material-label {
left: $index-has-icon;
}
.material-input {
text-indent: $index-has-icon;
}
}
.material-input {
font-size: $font-size-base;
padding: $spacer $spacer $spacer - $apixel * 10 $spacer / 2;
display: block;
width: 100%;
border: none;
line-height: 1;
border-radius: 0;
&:focus {
outline: none;
border: none;
border-bottom: 1px solid transparent; // fixes the height issue
}
}
.material-label {
font-weight: $font-weight-normal;
position: absolute;
pointer-events: none;
left: $index;
top: 0;
transition: $transition;
font-size: $font-size-small;
}
.material-input-bar {
position: relative;
display: block;
width: 100%;
&:before {
@extend %base-bar-pseudo;
left: 50%;
}
&:after {
@extend %base-bar-pseudo;
right: 50%;
}
}
// Disabled state:
&.material--disabled {
.material-input {
border-bottom-style: dashed;
}
}
// Raised state:
&.material--raised {
.material-label {
@include slided-top();
}
}
// Active state:
&.material--active {
.material-input-bar {
&:before,
&:after {
width: 50%;
}
}
}
}
// Mixins:
@mixin slided-top() {
top: -2 * $spacer;
font-size: $font-size-small;
.material-input__component {
background: $color-white;
.material-input {
background: none;
color: $color-black;
text-indent: $index;
border-bottom: 1px solid $color-grey-light;
}
// Component:
.material-input__component {
/*margin-top: 30px;*/
position: relative;
* {
box-sizing: border-box;
}
.material-input {
font-size: $font-size-base;
padding: $spacer $spacer $spacer $spacer / 2;
display: block;
width: 100%;
border: none;
border-radius: 0;
&:focus {
outline: none;
border: none;
border-bottom: 1px solid transparent; // fixes the height issue
}
}
.material-label {
font-size: $font-size-base;
font-weight: $font-weight-normal;
position: absolute;
pointer-events: none;
left: 0;
top: $spacer;
transition: $transition;
}
.material-input-bar {
position: relative;
display: block;
width: 100%;
&:before {
@extend %base-bar-pseudo;
left: 50%;
}
&:after {
@extend %base-bar-pseudo;
right: 50%;
}
}
// Disabled state:
&.material--disabled {
.material-input {
border-bottom-style: dashed;
}
}
// Raised state:
&.material--raised {
.material-label {
@include slided-top();
}
}
// Active state:
&.material--active {
.material-input-bar {
&:before,
&:after {
width: 50%;
}
}
}
// Errors:
.material-errors {
position: relative;
overflow: hidden;
.material-error {
font-size: $font-size-smallest;
line-height: $font-size-smallest + 2px;
overflow: hidden;
margin-top: 0;
padding-top: $spacer / 2;
padding-right: $spacer / 2;
padding-left: 0;
}
}
.material-label {
color: $color-grey;
}
// Theme:
$color-white: white;
$color-grey: #9E9E9E;
$color-grey-light: #E0E0E0;
$color-blue: #2196F3;
$color-red: #F44336;
$color-black: black;
.material-input__component {
background: $color-white;
.material-input {
background: none;
color: $color-black;
text-indent: 30px;
border-bottom: 1px solid $color-grey-light;
}
.material-label {
color: $color-grey;
}
.material-input-bar {
&:before,
&:after {
background: $color-blue;
}
}
// Active state:
&.material--active {
.material-label {
color: $color-blue;
}
}
// Errors:
&.material--has-errors {
&.material--active .material-label {
color: $color-red;
}
.material-input-bar {
&:before,
&:after {
background: $color-red;
}
}
.material-errors {
color: $color-red;
}
}
.material-input-bar {
&:before,
&:after {
background: $color-blue;
}
}
// Active state:
&.material--active {
.material-label {
color: $color-blue;
}
}
// Errors:
&.material--has-errors {
&.material--active .material-label {
color: $color-red;
}
.material-input-bar {
&:before,
&:after {
background: transparent;
}
}
}
}
</style>

View File

@ -1,9 +1,11 @@
<template>
<div class="components-container">
<div class='component-item'>
<md-input name="name" v-model="title" required :maxlength="100">
标题
</md-input>
<el-form :model="demo" :rules="demoRules">
<el-form-item prop="title">
<md-input icon="search" name="title" placeholder="输入标题" v-model="demo.title">标题</md-input>
</el-form-item>
</el-form>
<code class='code-part'>Material Design 的input</code>
</div>
@ -22,18 +24,33 @@
</template>
<script>
import MdInput from '@/components/MDinput'
import PanThumb from '@/components/PanThumb'
import MdInput from '@/components/MDinput'
import waves from '@/directive/waves.js' //
export default {
components: { MdInput, PanThumb },
components: {
PanThumb,
MdInput
},
directives: {
waves
},
data() {
const validate = (rule, value, callback) => {
if (value.length !== 6) {
callback(new Error('请输入六个字符'))
} else {
callback()
}
}
return {
title: ''
demo: {
title: ''
},
demoRules: {
title: [{ required: true, trigger: 'change', validator: validate }]
}
}
}
}

View File

@ -98,7 +98,6 @@ export default {
<style rel="stylesheet/scss" lang="scss" scoped>
.dashboard-editor-container {
margin: 30px;
.btn-group {
margin-bottom: 60px;
}

View File

@ -1,5 +1,5 @@
<template>
<div class="dashboard-container">
<div class="dashboard-container" style="padding:20px;">
<component :is="currentRole"></component>
</div>
</template>

View File

@ -1,5 +1,5 @@
<template>
<section class="app-main" style="min-height: 100%">
<section class="app-main" style="min-height: 100%;margin-top:50px;">
<transition name="fade" mode="out-in">
<router-view :key="key"></router-view>
</transition>

View File

@ -1,30 +1,32 @@
<template>
<el-menu class="navbar" mode="horizontal">
<hamburger class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger>
<levelbar></levelbar>
<tabs-view></tabs-view>
<error-log v-if="log.length>0" class="errLog-container" :logsList="log"></error-log>
<screenfull class='screenfull'></screenfull>
<el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper">
<img class="user-avatar" :src="avatar+'?imageView2/1/w/80/h/80'">
<i class="el-icon-caret-bottom"></i>
</div>
<el-dropdown-menu class="user-dropdown" slot="dropdown">
<router-link class='inlineBlock' to="/">
<el-dropdown-item>
首页
</el-dropdown-item>
</router-link>
<a target='_blank' href="https://github.com/PanJiaChen/vue-element-admin/">
<el-dropdown-item>
项目地址
</el-dropdown-item>
</a>
<el-dropdown-item divided><span @click="logout" style="display:block;">退出登录</span></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-menu>
<div class="nav-container">
<el-menu class="navbar" mode="horizontal">
<hamburger class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger>
<levelbar></levelbar>
<tabs-view></tabs-view>
<error-log v-if="log.length>0" class="errLog-container" :logsList="log"></error-log>
<screenfull class='screenfull'></screenfull>
<el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper">
<img class="user-avatar" :src="avatar+'?imageView2/1/w/80/h/80'">
<i class="el-icon-caret-bottom"></i>
</div>
<el-dropdown-menu class="user-dropdown" slot="dropdown">
<router-link class='inlineBlock' to="/">
<el-dropdown-item>
首页
</el-dropdown-item>
</router-link>
<a target='_blank' href="https://github.com/PanJiaChen/vue-element-admin/">
<el-dropdown-item>
项目地址
</el-dropdown-item>
</a>
<el-dropdown-item divided><span @click="logout" style="display:block;">退出登录</span></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-menu>
</div>
</template>
<script>
@ -70,50 +72,72 @@ export default {
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.navbar {
height: 50px;
line-height: 50px;
border-radius: 0px !important;
.hamburger-container {
line-height: 58px;
height: 50px;
float: left;
padding: 0 10px;
}
.errLog-container {
display: inline-block;
position: absolute;
right: 150px;
}
.screenfull {
position: absolute;
right: 90px;
top: 16px;
color: red;
}
.avatar-container {
height: 50px;
display: inline-block;
position: absolute;
right: 35px;
.avatar-wrapper {
cursor: pointer;
margin-top: 5px;
position: relative;
.user-avatar {
width: 40px;
height: 40px;
border-radius: 10px;
}
.el-icon-caret-bottom {
position: absolute;
right: -20px;
top: 25px;
font-size: 12px;
}
}
}
}
.nav-container {
position:fixed;
top:0;
z-index:102;
width:100%;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
&::before{
content:'';
display: block;
width:100%;
z-index:-1;
filter:blur(10px);
background: rgba(238,241,246,0.8);
height:50px;
position:fixed;
left:0;
right:0;
top:0;
bottom:0;
}
.navbar {
height: 50px;
line-height: 50px;
border-radius: 0px !important;
background-color: rgba(238,241,246,0.8);
.hamburger-container {
line-height: 58px;
height: 50px;
float: left;
padding: 0 10px;
}
.errLog-container {
display: inline-block;
position: fixed;
right: 150px;
}
.screenfull {
position: fixed;
right: 90px;
top: 16px;
color: red;
}
.avatar-container {
height: 50px;
display: inline-block;
position: fixed;
right: 35px;
.avatar-wrapper {
cursor: pointer;
margin-top: 5px;
position: relative;
.user-avatar {
width: 40px;
height: 40px;
border-radius: 10px;
}
.el-icon-caret-bottom {
position: absolute;
right: -20px;
top: 25px;
font-size: 12px;
}
}
}
}
}
</style>