init
init
This commit is contained in:
parent
5762337416
commit
7fa943eb39
128 changed files with 51042 additions and 1 deletions
126
components/affix/affix.vue
Normal file
126
components/affix/affix.vue
Normal file
|
@ -0,0 +1,126 @@
|
|||
<template>
|
||||
<div>
|
||||
<div :class="classes" :style="styles">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const prefixCls = 'ivu-affix';
|
||||
|
||||
function getScroll(target, top) {
|
||||
const prop = top ? 'pageYOffset' : 'pageXOffset';
|
||||
const method = top ? 'scrollTop' : 'scrollLeft';
|
||||
|
||||
let ret = target[prop];
|
||||
|
||||
if (typeof ret !== 'number') {
|
||||
ret = window.document.documentElement[method];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getOffset(element) {
|
||||
const rect = element.getBoundingClientRect();
|
||||
|
||||
const scrollTop = getScroll(window, true);
|
||||
const scrollLeft = getScroll(window);
|
||||
|
||||
const docEl = window.document.body;
|
||||
const clientTop = docEl.clientTop || 0;
|
||||
const clientLeft = docEl.clientLeft || 0;
|
||||
|
||||
return {
|
||||
top: rect.top + scrollTop - clientTop,
|
||||
left: rect.left + scrollLeft - clientLeft
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
props: {
|
||||
offsetTop: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
offsetBottom: {
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
affix: false,
|
||||
styles: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
offsetType () {
|
||||
let type = 'top';
|
||||
if (this.offsetBottom >= 0) {
|
||||
type = 'bottom';
|
||||
}
|
||||
|
||||
return type;
|
||||
},
|
||||
classes () {
|
||||
return [
|
||||
{
|
||||
[`${prefixCls}`]: this.affix
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
window.addEventListener('scroll', this.handleScroll, false);
|
||||
window.addEventListener('resize', this.handleScroll, false);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('scroll', this.handleScroll, false);
|
||||
window.removeEventListener('resize', this.handleScroll, false);
|
||||
},
|
||||
methods: {
|
||||
handleScroll () {
|
||||
const affix = this.affix;
|
||||
const scrollTop = getScroll(window, true);
|
||||
const elOffset = getOffset(this.$el);
|
||||
const windowHeight = window.innerHeight;
|
||||
const elHeight = this.$el.getElementsByTagName('div')[0].offsetHeight;
|
||||
|
||||
// Fixed Top
|
||||
if ((elOffset.top - this.offsetTop) < scrollTop && this.offsetType == 'top' && !affix) {
|
||||
this.affix = true;
|
||||
this.styles = {
|
||||
top: `${this.offsetTop}px`,
|
||||
left: `${elOffset.left}px`,
|
||||
width: `${this.$el.offsetWidth}px`
|
||||
};
|
||||
|
||||
this.$emit('on-change', true);
|
||||
} else if ((elOffset.top - this.offsetTop) > scrollTop && this.offsetType == 'top' && affix) {
|
||||
this.affix = false;
|
||||
this.styles = null;
|
||||
|
||||
this.$emit('on-change', false);
|
||||
}
|
||||
|
||||
// Fixed Bottom
|
||||
if ((elOffset.top + this.offsetBottom + elHeight) > (scrollTop + windowHeight) && this.offsetType == 'bottom' && !affix) {
|
||||
this.affix = true;
|
||||
this.styles = {
|
||||
bottom: `${this.offsetBottom}px`,
|
||||
left: `${elOffset.left}px`,
|
||||
width: `${this.$el.offsetWidth}px`
|
||||
};
|
||||
|
||||
this.$emit('on-change', true);
|
||||
} else if ((elOffset.top + this.offsetBottom + elHeight) < (scrollTop + windowHeight) && this.offsetType == 'bottom' && affix) {
|
||||
this.affix = false;
|
||||
this.styles = null;
|
||||
|
||||
this.$emit('on-change', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/affix/index.js
Normal file
2
components/affix/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Affix from './affix.vue';
|
||||
export default Affix;
|
90
components/back-top/back-top.vue
Normal file
90
components/back-top/back-top.vue
Normal file
|
@ -0,0 +1,90 @@
|
|||
<template>
|
||||
<div :class="classes" :style="styles" @click="back">
|
||||
<slot>
|
||||
<div :class="innerClasses">
|
||||
<i class="ivu-icon ivu-icon-chevron-up"></i>
|
||||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-back-top';
|
||||
|
||||
function getScroll(target, top) {
|
||||
const prop = top ? 'pageYOffset' : 'pageXOffset';
|
||||
const method = top ? 'scrollTop' : 'scrollLeft';
|
||||
|
||||
let ret = target[prop];
|
||||
|
||||
if (typeof ret !== 'number') {
|
||||
ret = window.document.documentElement[method];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
export default {
|
||||
props: {
|
||||
height: {
|
||||
type: Number,
|
||||
default: 400
|
||||
},
|
||||
bottom: {
|
||||
type: Number,
|
||||
default: 30
|
||||
},
|
||||
right: {
|
||||
type: Number,
|
||||
default: 30
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
backTop: false
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
window.addEventListener('scroll', this.handleScroll, false);
|
||||
window.addEventListener('resize', this.handleScroll, false);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('scroll', this.handleScroll, false);
|
||||
window.removeEventListener('resize', this.handleScroll, false);
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-show`]: this.backTop
|
||||
}
|
||||
]
|
||||
},
|
||||
styles () {
|
||||
return {
|
||||
bottom: `${this.bottom}px`,
|
||||
right: `${this.right}px`
|
||||
}
|
||||
},
|
||||
innerClasses () {
|
||||
return `${prefixCls}-inner`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleScroll () {
|
||||
const backTop = this.backTop;
|
||||
const scrollTop = getScroll(window, true);
|
||||
|
||||
if (this.height <= scrollTop && !backTop) {
|
||||
this.backTop = true;
|
||||
} else if (this.height > scrollTop && backTop) {
|
||||
this.backTop = false;
|
||||
}
|
||||
},
|
||||
back () {
|
||||
window.scrollTo(0, 0);
|
||||
this.$emit('on-click');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/back-top/index.js
Normal file
2
components/back-top/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import BackTop from './back-top.vue';
|
||||
export default BackTop;
|
77
components/badge/badge.vue
Normal file
77
components/badge/badge.vue
Normal file
|
@ -0,0 +1,77 @@
|
|||
<template>
|
||||
<span v-if="dot" :class="classes" v-el:badge>
|
||||
<slot></slot>
|
||||
<sup :class="dotClasses" v-show="badge"></sup>
|
||||
</span>
|
||||
<span v-else :class="classes" v-el:badge>
|
||||
<slot></slot>
|
||||
<sup v-if="count" :class="countClasses" v-show="badge">{{ finalCount }}</sup>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-badge';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
count: [Number, String],
|
||||
dot: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
overflowCount: {
|
||||
type: [Number, String],
|
||||
default: 99
|
||||
},
|
||||
class: String
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return `${prefixCls}`;
|
||||
},
|
||||
dotClasses () {
|
||||
return `${prefixCls}-dot`;
|
||||
},
|
||||
countClasses () {
|
||||
return [
|
||||
`${prefixCls}-count`,
|
||||
{
|
||||
[`${this.class}`]: !!this.class,
|
||||
[`${prefixCls}-count-alone`]: this.alone
|
||||
}
|
||||
]
|
||||
},
|
||||
finalCount () {
|
||||
return parseInt(this.count) >= parseInt(this.overflowCount) ? `${this.overflowCount}+` : this.count;
|
||||
},
|
||||
badge () {
|
||||
let status = false;
|
||||
|
||||
if (this.count) {
|
||||
status = !(parseInt(this.count) === 0);
|
||||
}
|
||||
|
||||
if (this.dot) {
|
||||
status = true;
|
||||
if (this.count) {
|
||||
if (parseInt(this.count) === 0) {
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
alone: false
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
const child_length = this.$els.badge.children.length;
|
||||
if (child_length === 1) {
|
||||
this.alone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/badge/index.js
Normal file
2
components/badge/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Badge from './badge.vue';
|
||||
export default Badge;
|
36
components/breadcrumb/breadcrumb-item.vue
Normal file
36
components/breadcrumb/breadcrumb-item.vue
Normal file
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<span>
|
||||
<a v-if="href" :href="href" :class="linkClasses">
|
||||
<slot></slot>
|
||||
</a>
|
||||
<span v-else :class="linkClasses">
|
||||
<slot></slot>
|
||||
</span>
|
||||
<span :class="separatorClasses">
|
||||
<slot name="separator">{{{ separator }}}</slot>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-breadcrumb-item';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
href: {
|
||||
type: String
|
||||
},
|
||||
separator: {
|
||||
type: String,
|
||||
default: '/'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
linkClasses () {
|
||||
return `${prefixCls}-link`;
|
||||
},
|
||||
separatorClasses () {
|
||||
return `${prefixCls}-separator`;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
37
components/breadcrumb/breadcrumb.vue
Normal file
37
components/breadcrumb/breadcrumb.vue
Normal file
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-breadcrumb';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
separator: {
|
||||
type: String,
|
||||
default: '/'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return `${prefixCls}`;
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.updateChildren();
|
||||
},
|
||||
methods: {
|
||||
updateChildren () {
|
||||
this.$children.forEach((child) => {
|
||||
child.separator = this.separator;
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
separator () {
|
||||
this.updateChildren();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
5
components/breadcrumb/index.js
Normal file
5
components/breadcrumb/index.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import Breadcrumb from './breadcrumb.vue';
|
||||
import BreadcrumbItem from './breadcrumb-item.vue';
|
||||
|
||||
Breadcrumb.Item = BreadcrumbItem;
|
||||
export default Breadcrumb;
|
30
components/button/button-group.vue
Normal file
30
components/button/button-group.vue
Normal file
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-btn-group';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
56
components/button/button.vue
Normal file
56
components/button/button.vue
Normal file
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<button :type="htmlType" :class="classes" :disabled="disabled">
|
||||
<Icon type="loading" v-if="loading"></Icon>
|
||||
<Icon :type="icon" v-if="icon && !loading"></Icon>
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-btn';
|
||||
|
||||
export default {
|
||||
components: { Icon },
|
||||
props: {
|
||||
type: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['primary', 'ghost']);
|
||||
}
|
||||
},
|
||||
shape: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['circle', 'circle-outline']);
|
||||
}
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
},
|
||||
loading: Boolean,
|
||||
disabled: Boolean,
|
||||
htmlType: {
|
||||
default: 'button',
|
||||
validator (value) {
|
||||
return oneOf(value, ['button', 'submit', 'reset']);
|
||||
}
|
||||
},
|
||||
icon: String
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.type}`]: !!this.type,
|
||||
[`${prefixCls}-${this.shape}`]: !!this.shape,
|
||||
[`${prefixCls}-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-loading`]: this.loading != null && this.loading
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
5
components/button/index.js
Normal file
5
components/button/index.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import Button from './button.vue';
|
||||
import ButtonGroup from './button-group.vue';
|
||||
|
||||
Button.Group = ButtonGroup;
|
||||
export default Button;
|
51
components/checkbox/checkbox-group.vue
Normal file
51
components/checkbox/checkbox-group.vue
Normal file
|
@ -0,0 +1,51 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-checkbox-group';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
model: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return `${prefixCls}`;
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.updateModel(true);
|
||||
},
|
||||
methods: {
|
||||
updateModel (update) {
|
||||
const model = this.model;
|
||||
|
||||
this.$children.forEach((child) => {
|
||||
child.model = model;
|
||||
|
||||
if (update) {
|
||||
child.selected = model.indexOf(child.value) >= 0;
|
||||
child.group = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
change (data) {
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
model (val, oldVal) {
|
||||
if (val == oldVal) {
|
||||
this.updateModel();
|
||||
} else {
|
||||
this.updateModel(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
104
components/checkbox/checkbox.vue
Normal file
104
components/checkbox/checkbox.vue
Normal file
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<label :class="wrapClasses">
|
||||
<span :class="checkboxClasses">
|
||||
<span :class="innerClasses"></span>
|
||||
<input
|
||||
v-if="group"
|
||||
type="checkbox"
|
||||
:class="inputClasses"
|
||||
:disabled="disabled"
|
||||
:value="value"
|
||||
v-model="model"
|
||||
@change="change">
|
||||
<input
|
||||
v-if="!group"
|
||||
type="checkbox"
|
||||
:class="inputClasses"
|
||||
:disabled="disabled"
|
||||
v-model="checked"
|
||||
@change="change">
|
||||
</span>
|
||||
<slot>{{ value }}</slot>
|
||||
</label>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-checkbox';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Boolean]
|
||||
},
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
model: [],
|
||||
selected: false,
|
||||
group: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}-wrapper`,
|
||||
{
|
||||
[`${prefixCls}-group-item`]: this.group,
|
||||
[`${prefixCls}-wrapper-checked`]: this.selected,
|
||||
[`${prefixCls}-wrapper-disabled`]: this.disabled
|
||||
}
|
||||
]
|
||||
},
|
||||
checkboxClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-checked`]: this.selected,
|
||||
[`${prefixCls}-disabled`]: this.disabled
|
||||
}
|
||||
]
|
||||
},
|
||||
innerClasses () {
|
||||
return `${prefixCls}-inner`;
|
||||
},
|
||||
inputClasses () {
|
||||
return `${prefixCls}-input`;
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
if (!this.group) {
|
||||
this.updateModel();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
change (event) {
|
||||
if (this.disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.selected = event.target.checked;
|
||||
|
||||
if (this.group) {
|
||||
this.$parent.change(this.model);
|
||||
} else {
|
||||
this.$emit('on-change', this.checked);
|
||||
}
|
||||
},
|
||||
updateModel () {
|
||||
this.selected = this.checked;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
checked () {
|
||||
this.updateModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
5
components/checkbox/index.js
Normal file
5
components/checkbox/index.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import Checkbox from './checkbox.vue';
|
||||
import CheckboxGroup from './checkbox-group.vue';
|
||||
|
||||
Checkbox.Group = CheckboxGroup;
|
||||
export default Checkbox;
|
83
components/circle/circle.vue
Normal file
83
components/circle/circle.vue
Normal file
|
@ -0,0 +1,83 @@
|
|||
<template>
|
||||
<div :style="circleSize" :class="wrapClasses">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<path :d="pathString" :stroke="trailColor" :stroke-width="trailWidth" :fill-opacity="0"/>
|
||||
<path :d="pathString" :stroke-linecap="strokeLinecap" :stroke="strokeColor" :stroke-width="strokeWidth" fill-opacity="0" :style="pathStyle"/>
|
||||
</svg>
|
||||
<div :class="innerClasses">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-chart-circle';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
percent: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 120
|
||||
},
|
||||
strokeWidth: {
|
||||
type: Number,
|
||||
default: 6
|
||||
},
|
||||
strokeColor: {
|
||||
type: String,
|
||||
default: '#2db7f5'
|
||||
},
|
||||
strokeLinecap: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['square', 'round']);
|
||||
},
|
||||
default: 'round'
|
||||
},
|
||||
trailWidth: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
trailColor: {
|
||||
type: String,
|
||||
default: '#eaeef2'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
circleSize () {
|
||||
return {
|
||||
width: `${this.size}px`,
|
||||
height: `${this.size}px`
|
||||
};
|
||||
},
|
||||
radius () {
|
||||
return 50 - this.strokeWidth / 2;
|
||||
},
|
||||
pathString () {
|
||||
return `M 50,50 m 0,-${this.radius}
|
||||
a ${this.radius},${this.radius} 0 1 1 0,${2 * this.radius}
|
||||
a ${this.radius},${this.radius} 0 1 1 0,-${2 * this.radius}`;
|
||||
},
|
||||
len () {
|
||||
return Math.PI * 2 * this.radius;
|
||||
},
|
||||
pathStyle () {
|
||||
return {
|
||||
'stroke-dasharray': `${this.len}px ${this.len}px`,
|
||||
'stroke-dashoffset': `${((100 - this.percent) / 100 * this.len)}px`,
|
||||
'transition': 'stroke-dashoffset 0.6s ease 0s, stroke 0.6s ease'
|
||||
}
|
||||
},
|
||||
wrapClasses () {
|
||||
return `${prefixCls}`;
|
||||
},
|
||||
innerClasses () {
|
||||
return `${prefixCls}-inner`;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/circle/index.js
Normal file
2
components/circle/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Circle from './circle.vue';
|
||||
export default Circle;
|
27
components/icon/icon.vue
Normal file
27
components/icon/icon.vue
Normal file
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<i :class="classes" :style="styles"></i>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-icon';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
type: String,
|
||||
size: [Number, String]
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return `${prefixCls} ${prefixCls}-${this.type}`
|
||||
},
|
||||
styles () {
|
||||
if (!!this.size) {
|
||||
return {
|
||||
'font-size': `${this.size}px`
|
||||
}
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/icon/index.js
Normal file
2
components/icon/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Icon from './icon.vue';
|
||||
export default Icon;
|
2
components/input-number/index.js
Normal file
2
components/input-number/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import InputNumber from './input-number.vue';
|
||||
export default InputNumber;
|
236
components/input-number/input-number.vue
Normal file
236
components/input-number/input-number.vue
Normal file
|
@ -0,0 +1,236 @@
|
|||
<template>
|
||||
<div :class="wrapClasses">
|
||||
<div :class="handlerClasses">
|
||||
<a
|
||||
@click="up"
|
||||
@mouse.down="preventDefault"
|
||||
:class="upClasses">
|
||||
<span
|
||||
:class="innerUpClasses"
|
||||
@click="preventDefault">+</span>
|
||||
</a>
|
||||
<a
|
||||
@click="down"
|
||||
@mouse.down="preventDefault"
|
||||
:class="downClasses">
|
||||
<span
|
||||
:class="innerDownClasses"
|
||||
@click="preventDefault">-</span>
|
||||
</a>
|
||||
</div>
|
||||
<div :class="inputWrapClasses">
|
||||
<input
|
||||
:class="inputClasses"
|
||||
:disabled="disabled"
|
||||
autoComplete="off"
|
||||
@focus="focus"
|
||||
@blur="blur"
|
||||
@keydown.stop="keyDown"
|
||||
@change="change"
|
||||
:value="value">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-input-number';
|
||||
|
||||
function isValueNumber (value) {
|
||||
return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)/).test(value + '');
|
||||
}
|
||||
function addNum (num1, num2) {
|
||||
var sq1, sq2, m;
|
||||
try {
|
||||
sq1 = num1.toString().split(".")[1].length;
|
||||
}
|
||||
catch (e) {
|
||||
sq1 = 0;
|
||||
}
|
||||
try {
|
||||
sq2 = num2.toString().split(".")[1].length;
|
||||
}
|
||||
catch (e) {
|
||||
sq2 = 0;
|
||||
}
|
||||
// if (sq1 === 0 || sq2 === 0) {
|
||||
// return num1 + num2;
|
||||
// } else {
|
||||
// m = Math.pow(10, Math.max(sq1, sq2));
|
||||
// return (num1 * m + num2 * m) / m;
|
||||
// }
|
||||
m = Math.pow(10, Math.max(sq1, sq2));
|
||||
return (num1 * m + num2 * m) / m;
|
||||
}
|
||||
|
||||
export default {
|
||||
props: {
|
||||
max: {
|
||||
type: Number,
|
||||
default: Infinity
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
default: -Infinity
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
focused: false,
|
||||
upDisabled: false,
|
||||
downDisabled: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-disabled`]: this.disabled,
|
||||
[`${prefixCls}-focused`]: this.focused
|
||||
}
|
||||
]
|
||||
},
|
||||
handlerClasses () {
|
||||
return `${prefixCls}-handler-wrap`;
|
||||
},
|
||||
upClasses () {
|
||||
return [
|
||||
`${prefixCls}-handler`,
|
||||
`${prefixCls}-handler-up`,
|
||||
{
|
||||
[`${prefixCls}-handler-up-disabled`]: this.upDisabled
|
||||
}
|
||||
]
|
||||
},
|
||||
innerUpClasses () {
|
||||
return `${prefixCls}-handler-up-inner`;
|
||||
},
|
||||
downClasses () {
|
||||
return [
|
||||
`${prefixCls}-handler`,
|
||||
`${prefixCls}-handler-down`,
|
||||
{
|
||||
[`${prefixCls}-handler-down-disabled`]: this.downDisabled
|
||||
}
|
||||
]
|
||||
},
|
||||
innerDownClasses () {
|
||||
return `${prefixCls}-handler-down-inner`;
|
||||
},
|
||||
inputWrapClasses () {
|
||||
return `${prefixCls}-input-wrap`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
preventDefault (e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
up () {
|
||||
if (this.upDisabled) {
|
||||
return false;
|
||||
}
|
||||
this.changeStep('up');
|
||||
},
|
||||
down () {
|
||||
if (this.downDisabled) {
|
||||
return false;
|
||||
}
|
||||
this.changeStep('down');
|
||||
},
|
||||
changeStep (type) {
|
||||
if (this.disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let val = Number(this.value);
|
||||
const step = Number(this.step);
|
||||
if (isNaN(val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == 'up') {
|
||||
val = addNum(val, step);
|
||||
} else if (type == 'down') {
|
||||
val = addNum(val, -step);
|
||||
}
|
||||
this.setValue(val);
|
||||
},
|
||||
setValue (val) {
|
||||
this.value = val;
|
||||
this.$emit('on-change', val);
|
||||
},
|
||||
focus () {
|
||||
this.focused = true;
|
||||
},
|
||||
blur () {
|
||||
this.focused = false;
|
||||
},
|
||||
keyDown (e) {
|
||||
if (e.keyCode === 38) {
|
||||
e.preventDefault();
|
||||
this.up()
|
||||
} else if (e.keyCode === 40) {
|
||||
e.preventDefault();
|
||||
this.down()
|
||||
}
|
||||
},
|
||||
change (event) {
|
||||
let val = event.target.value.trim();
|
||||
|
||||
const max = this.max;
|
||||
const min = this.min;
|
||||
|
||||
if (isValueNumber(val)) {
|
||||
val = Number(val);
|
||||
if (val > max) {
|
||||
this.setValue(max);
|
||||
} else if (val < min) {
|
||||
this.setValue(min);
|
||||
} else {
|
||||
this.setValue(val);
|
||||
}
|
||||
} else {
|
||||
event.target.value = this.value;
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
if (isValueNumber(val) || val === 0) {
|
||||
val = Number(val);
|
||||
const step = this.step;
|
||||
if (val + step > this.max) {
|
||||
this.upDisabled = true;
|
||||
} else if (val - step < this.min) {
|
||||
this.downDisabled = true;
|
||||
} else {
|
||||
this.upDisabled = false;
|
||||
this.downDisabled = false;
|
||||
}
|
||||
} else {
|
||||
this.upDisabled = true;
|
||||
this.downDisabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/input/index.js
Normal file
2
components/input/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Input from './input.vue';
|
||||
export default Input;
|
49
components/input/input.vue
Normal file
49
components/input/input.vue
Normal file
|
@ -0,0 +1,49 @@
|
|||
<template>
|
||||
<input
|
||||
:class="classes"
|
||||
:type="type"
|
||||
:placeholder="placeholder"
|
||||
:name="name"
|
||||
v-model="value">
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-input';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
twoWay: true
|
||||
},
|
||||
placeholder: String,
|
||||
name: String,
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
36
components/layout/col.vue
Normal file
36
components/layout/col.vue
Normal file
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-col';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
span: [Number, String],
|
||||
order: [Number, String],
|
||||
offset: [Number, String],
|
||||
push: [Number, String],
|
||||
pull: [Number, String],
|
||||
className: String
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-span-${this.span}`]: this.span,
|
||||
[`${prefixCls}-order-${this.order}`]: this.order,
|
||||
[`${prefixCls}-offset-${this.offset}`]: this.offset,
|
||||
[`${prefixCls}-push-${this.push}`]: this.push,
|
||||
[`${prefixCls}-pull-${this.pull}`]: this.pull,
|
||||
[`${this.className}`]: !!this.className
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
4
components/layout/index.js
Normal file
4
components/layout/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
import Row from './row.vue';
|
||||
import Col from './col.vue';
|
||||
|
||||
export { Row, Col };
|
44
components/layout/row.vue
Normal file
44
components/layout/row.vue
Normal file
|
@ -0,0 +1,44 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-row';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
type: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['flex']);
|
||||
}
|
||||
},
|
||||
align: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['top', 'middle', 'bottom']);
|
||||
}
|
||||
},
|
||||
justify: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['start', 'end', 'center', 'space-around', 'space-between']);
|
||||
}
|
||||
},
|
||||
className: String
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.type}`]: !!this.type,
|
||||
[`${prefixCls}-${this.type}-${this.align}`]: !!this.align,
|
||||
[`${prefixCls}-${this.type}-${this.justify}`]: !!this.justify,
|
||||
[`${this.className}`]: !!this.className
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/page/index.js
Normal file
2
components/page/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Page from './page.vue';
|
||||
export default Page;
|
79
components/page/options.vue
Normal file
79
components/page/options.vue
Normal file
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<div v-if="showSizer || showElevator" :class="optsClasses">
|
||||
<div v-if="showSizer" :class="sizerClasses">
|
||||
<select v-model="pageSize" @change="changeSize">
|
||||
<option :value="item" v-for="item in pageSizeOpts">{{ item }} 条/页</option>
|
||||
</select>
|
||||
</div>
|
||||
<div v-if="showElevator" :class="ElevatorClasses">
|
||||
跳至
|
||||
<input type="text" :value="_current" @keyup.enter="changePage">
|
||||
页
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-page';
|
||||
|
||||
function isValueNumber (value) {
|
||||
return (/^[1-9][0-9]*$/).test(value + '');
|
||||
}
|
||||
|
||||
export default {
|
||||
props: {
|
||||
pageSizeOpts: Array,
|
||||
showSizer: Boolean,
|
||||
showElevator: Boolean,
|
||||
current: Number,
|
||||
_current: Number,
|
||||
pageSize: Number,
|
||||
allPages: Number
|
||||
},
|
||||
computed: {
|
||||
optsClasses () {
|
||||
return [
|
||||
`${prefixCls}-options`
|
||||
]
|
||||
},
|
||||
sizerClasses () {
|
||||
return [
|
||||
`${prefixCls}-options-sizer`
|
||||
]
|
||||
},
|
||||
ElevatorClasses () {
|
||||
return [
|
||||
`${prefixCls}-options-elevator`
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeSize () {
|
||||
this.$emit('on-size', this.pageSize);
|
||||
},
|
||||
changePage (event) {
|
||||
let val = event.target.value.trim();
|
||||
let page = 0;
|
||||
|
||||
if (isValueNumber(val)) {
|
||||
val = Number(val);
|
||||
if (val != this.current) {
|
||||
const allPages = this.allPages;
|
||||
|
||||
if (val > allPages) {
|
||||
page = allPages;
|
||||
} else {
|
||||
page = val;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
page = 1;
|
||||
}
|
||||
|
||||
if (page) {
|
||||
this.$emit('on-page', page);
|
||||
event.target.value = page;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
230
components/page/page.vue
Normal file
230
components/page/page.vue
Normal file
|
@ -0,0 +1,230 @@
|
|||
<template>
|
||||
<ul :class="simpleWrapClasses" v-if="simple">
|
||||
<li
|
||||
title="上一页"
|
||||
:class="prevClasses"
|
||||
@click="prev">
|
||||
<a>←</a>
|
||||
</li>
|
||||
<div :title="current + '/' + allPages">
|
||||
<input
|
||||
type="text"
|
||||
:value="current"
|
||||
@keydown="keyDown"
|
||||
@keyup="keyUp"
|
||||
@change="keyUp">
|
||||
<span>/</span>
|
||||
{{ allPages }}
|
||||
</div>
|
||||
<li
|
||||
title="下一页"
|
||||
:class="nextClasses"
|
||||
@click="next">
|
||||
<a>→</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul :class="wrapClasses" v-else>
|
||||
<span :class="[`${prefixCls}-total`]" v-if="showTotal">
|
||||
<slot>共 {{ total }} 条</slot>
|
||||
</span>
|
||||
<li
|
||||
title="上一页"
|
||||
:class="prevClasses"
|
||||
@click="prev">
|
||||
<a>←</a>
|
||||
</li>
|
||||
<li title="第一页" :class="[`${prefixCls}-item`,{[`${prefixCls}-item-active`]: current == 1}]" @click="changePage(1)"><a>1</a></li>
|
||||
<li title="向前 5 页" v-if="current - 3 > 1" :class="[`${prefixCls}-item-jump-prev`]" @click="fastPrev"><a>…</a></li>
|
||||
<li :title="current - 2" v-if="current - 2 > 1" :class="[`${prefixCls}-item`]" @click="changePage(current - 2)"><a>{{ current - 2 }}</a></li>
|
||||
<li :title="current - 1" v-if="current - 1 > 1" :class="[`${prefixCls}-item`]" @click="changePage(current - 1)"><a>{{ current - 1 }}</a></li>
|
||||
<li :title="current" v-if="current != 1 && current != allPages" :class="[`${prefixCls}-item`,`${prefixCls}-item-active`]"><a>{{ current }}</a></li>
|
||||
<li :title="current + 1" v-if="current + 1 < allPages" :class="[`${prefixCls}-item`]" @click="changePage(current + 1)"><a>{{ current + 1 }}</a></li>
|
||||
<li :title="current + 2" v-if="current + 2 < allPages" :class="[`${prefixCls}-item`]" @click="changePage(current + 2)"><a>{{ current + 2 }}</a></li>
|
||||
<li title="向后 5 页" v-if="current + 3 < allPages" :class="[`${prefixCls}-item-jump-next`]" @click="fastNext"><a>…</a></li>
|
||||
<li :title="'最后一页:' + allPages" :class="[`${prefixCls}-item`, {[`${prefixCls}-item-active`]: current == allPages}]" @click="changePage(allPages)"><a>{{ allPages }}</a></li>
|
||||
<li
|
||||
title="下一页"
|
||||
:class="nextClasses"
|
||||
@click="next">
|
||||
<a>→</a>
|
||||
</li>
|
||||
<Options
|
||||
:show-sizer="showSizer"
|
||||
:page-size="pageSize"
|
||||
:page-size-opts="pageSizeOpts"
|
||||
:show-elevator="showElevator"
|
||||
:_current.once="current"
|
||||
:current.sync="current"
|
||||
:all-pages="allPages"
|
||||
@on-size="onSize"
|
||||
@on-page="onPage">
|
||||
</Options>
|
||||
</ul>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
import Options from './options.vue';
|
||||
|
||||
const prefixCls = 'ivu-page';
|
||||
|
||||
export default {
|
||||
components: { Options },
|
||||
props: {
|
||||
current: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
total: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
pageSizeOpts: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [10, 20, 30, 40]
|
||||
}
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small']);
|
||||
}
|
||||
},
|
||||
simple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showTotal: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showElevator: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showSizer: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
allPages () {
|
||||
return Math.ceil(this.total / this.pageSize);
|
||||
},
|
||||
simpleWrapClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-simple`
|
||||
]
|
||||
},
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
'mini': !!this.size
|
||||
}
|
||||
]
|
||||
},
|
||||
prevClasses () {
|
||||
return [
|
||||
`${prefixCls}-prev`,
|
||||
{
|
||||
[`${prefixCls}-disabled`]: this.current == 1
|
||||
}
|
||||
]
|
||||
},
|
||||
nextClasses () {
|
||||
return [
|
||||
`${prefixCls}-next`,
|
||||
{
|
||||
[`${prefixCls}-disabled`]: this.current == this.allPages
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changePage (page) {
|
||||
if (this.current != page) {
|
||||
this.current = page;
|
||||
this.$emit('on-change', page);
|
||||
}
|
||||
},
|
||||
prev () {
|
||||
const current = this.current;
|
||||
if (current <= 1) {
|
||||
return false;
|
||||
}
|
||||
this.changePage(current - 1);
|
||||
},
|
||||
next () {
|
||||
const current = this.current;
|
||||
if (current >= this.allPages) {
|
||||
return false;
|
||||
}
|
||||
this.changePage(current + 1);
|
||||
},
|
||||
fastPrev () {
|
||||
const page = this.current - 5;
|
||||
if (page > 0) {
|
||||
this.changePage(page);
|
||||
} else {
|
||||
this.changePage(1);
|
||||
}
|
||||
},
|
||||
fastNext () {
|
||||
const page = this.current + 5;
|
||||
if (page > this.allPages) {
|
||||
this.changePage(this.allPages);
|
||||
} else {
|
||||
this.changePage(page);
|
||||
}
|
||||
},
|
||||
onSize (pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
this.changePage(1);
|
||||
},
|
||||
onPage (page) {
|
||||
this.changePage(page);
|
||||
},
|
||||
keyDown (e) {
|
||||
const key = e.keyCode;
|
||||
const condition = (key >= 48 && key <= 57) || key == 8 || key == 37 || key == 39;
|
||||
|
||||
if (!condition) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
keyUp (e) {
|
||||
const key = e.keyCode;
|
||||
const val = parseInt(e.target.value);
|
||||
|
||||
if (key === 38) {
|
||||
this.prev()
|
||||
} else if (key === 40) {
|
||||
this.next()
|
||||
} else if (key == 13) {
|
||||
let page = 1;
|
||||
|
||||
if (val > this.allPages) {
|
||||
page = this.allPages;
|
||||
} else if (val <= 0) {
|
||||
page = 1;
|
||||
} else {
|
||||
page = val;
|
||||
}
|
||||
|
||||
e.target.value = page;
|
||||
this.changePage(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/progress/index.js
Normal file
2
components/progress/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Progress from './progress.vue';
|
||||
export default Progress;
|
121
components/progress/progress.vue
Normal file
121
components/progress/progress.vue
Normal file
|
@ -0,0 +1,121 @@
|
|||
<template>
|
||||
<div :class="wrapClasses">
|
||||
<span v-if="!hideInfo" :class="textClasses">
|
||||
<slot>
|
||||
<span v-if="isStatus" :class="textInnerClasses">
|
||||
<Icon :type="statusIcon"></Icon>
|
||||
</span>
|
||||
<span v-else :class="textInnerClasses">
|
||||
{{ percent }}%
|
||||
</span>
|
||||
</slot>
|
||||
</span>
|
||||
<div :class="outerClasses">
|
||||
<div :class="innerClasses">
|
||||
<div :class="bgClasses" :style="bgStyle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-progress';
|
||||
|
||||
export default {
|
||||
components: { Icon },
|
||||
props: {
|
||||
percent: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
status: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['normal', 'active', 'wrong', 'success']);
|
||||
},
|
||||
default: 'normal'
|
||||
},
|
||||
hideInfo: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
strokeWidth: {
|
||||
type: Number,
|
||||
default: 10
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isStatus () {
|
||||
return this.status == 'wrong' || this.status == 'success';
|
||||
},
|
||||
statusIcon () {
|
||||
let type = '';
|
||||
switch (this.status) {
|
||||
case 'wrong':
|
||||
type = 'ios-close-empty';
|
||||
break;
|
||||
case 'success':
|
||||
type = 'ios-checkmark-empty';
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
},
|
||||
bgStyle () {
|
||||
return {
|
||||
width: `${this.percent}%`,
|
||||
height: `${this.strokeWidth}px`
|
||||
}
|
||||
},
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-${this.status}`,
|
||||
{
|
||||
[`${prefixCls}-show-info`]: !this.hideInfo,
|
||||
|
||||
}
|
||||
]
|
||||
},
|
||||
textClasses () {
|
||||
return `${prefixCls}-text`;
|
||||
},
|
||||
textInnerClasses () {
|
||||
return `${prefixCls}-text-inner`;
|
||||
},
|
||||
outerClasses () {
|
||||
return `${prefixCls}-outer`;
|
||||
},
|
||||
innerClasses () {
|
||||
return `${prefixCls}-inner`;
|
||||
},
|
||||
bgClasses () {
|
||||
return `${prefixCls}-bg`;
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.handleStatus();
|
||||
},
|
||||
methods: {
|
||||
handleStatus (isDown) {
|
||||
if (isDown) {
|
||||
this.status = 'normal';
|
||||
} else {
|
||||
if (parseInt(this.percent, 10) == 100) {
|
||||
this.status = 'success';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
percent (val, oldVal) {
|
||||
if (val < oldVal) {
|
||||
this.handleStatus(true);
|
||||
} else {
|
||||
this.handleStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
5
components/radio/index.js
Normal file
5
components/radio/index.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import Radio from './radio.vue';
|
||||
import RadioGroup from './radio-group.vue';
|
||||
|
||||
Radio.Group = RadioGroup;
|
||||
export default Radio;
|
62
components/radio/radio-group.vue
Normal file
62
components/radio/radio-group.vue
Normal file
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-radio-group';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
model: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
},
|
||||
type: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['button']);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-${this.type}`]: !!this.type
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.updateModel();
|
||||
},
|
||||
methods: {
|
||||
updateModel () {
|
||||
const model = this.model;
|
||||
this.$children.forEach((child) => {
|
||||
child.selected = model == child.value;
|
||||
child.group = true;
|
||||
});
|
||||
},
|
||||
change (data) {
|
||||
this.model = data.value;
|
||||
this.updateModel();
|
||||
this.$emit('on-change', data.value);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
model () {
|
||||
this.updateModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
96
components/radio/radio.vue
Normal file
96
components/radio/radio.vue
Normal file
|
@ -0,0 +1,96 @@
|
|||
<template>
|
||||
<label :class="wrapClasses">
|
||||
<span :class="radioClasses">
|
||||
<span :class="innerClasses"></span>
|
||||
<input
|
||||
type="radio"
|
||||
:class="inputClasses"
|
||||
:disabled="disabled"
|
||||
:checked="selected"
|
||||
@change="change">
|
||||
</span>
|
||||
<slot>{{ value }}</slot>
|
||||
</label>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-radio';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
value: {
|
||||
type: [String, Number]
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
selected: false,
|
||||
group: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}-wrapper`,
|
||||
{
|
||||
[`${prefixCls}-group-item`]: this.group,
|
||||
[`${prefixCls}-wrapper-checked`]: this.selected,
|
||||
[`${prefixCls}-wrapper-disabled`]: this.disabled
|
||||
}
|
||||
]
|
||||
},
|
||||
radioClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-checked`]: this.selected,
|
||||
[`${prefixCls}-disabled`]: this.disabled
|
||||
}
|
||||
]
|
||||
},
|
||||
innerClasses () {
|
||||
return `${prefixCls}-inner`;
|
||||
},
|
||||
inputClasses () {
|
||||
return `${prefixCls}-input`;
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
if (!this.group) {
|
||||
this.updateModel();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
change (event) {
|
||||
if (this.disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.selected = event.target.checked;
|
||||
this.checked = this.selected;
|
||||
|
||||
if (this.group && this.checked) {
|
||||
this.$parent.change({
|
||||
value: this.value,
|
||||
checked: this.checked
|
||||
});
|
||||
}
|
||||
},
|
||||
updateModel () {
|
||||
this.selected = this.checked;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
checked () {
|
||||
this.updateModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/spin/index.js
Normal file
2
components/spin/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Spin from './spin.vue';
|
||||
export default Spin;
|
60
components/spin/spin.vue
Normal file
60
components/spin/spin.vue
Normal file
|
@ -0,0 +1,60 @@
|
|||
<template>
|
||||
<div :class="classes" transition="fade">
|
||||
<div :class="mainClasses">
|
||||
<span :class="dotClasses"></span>
|
||||
<div :class="textClasses" v-el:text><slot></slot></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-spin';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
},
|
||||
fix: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showText: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-fix`]: this.fix,
|
||||
[`${prefixCls}-show-text`]: this.showText,
|
||||
}
|
||||
]
|
||||
},
|
||||
mainClasses () {
|
||||
return `${prefixCls}-main`;
|
||||
},
|
||||
dotClasses () {
|
||||
return `${prefixCls}-dot`;
|
||||
},
|
||||
textClasses () {
|
||||
return `${prefixCls}-text`;
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
const text = this.$els.text.innerHTML;
|
||||
|
||||
if (text != '') {
|
||||
this.showText = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
5
components/steps/index.js
Normal file
5
components/steps/index.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import Steps from './steps.vue';
|
||||
import Step from './step.vue';
|
||||
|
||||
Steps.Step = Step;
|
||||
export default Steps;
|
88
components/steps/step.vue
Normal file
88
components/steps/step.vue
Normal file
|
@ -0,0 +1,88 @@
|
|||
<template>
|
||||
<div :class="wrapClasses">
|
||||
<div :class="[`${prefixCls}-tail`]"></div>
|
||||
<div :class="[`${prefixCls}-head`]">
|
||||
<div :class="[`${prefixCls}-head-inner`]">
|
||||
<span v-if="!icon && status != 'finish' && status != 'error'">{{ stepNumber }}</span>
|
||||
<span v-else :class="iconClasses"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="[`${prefixCls}-main`]">
|
||||
<div :class="[`${prefixCls}-title`]">{{ title }}</div>
|
||||
<div v-if="content" :class="[`${prefixCls}-content`]">{{ content }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-steps';
|
||||
const iconPrefixCls = 'ivu-icon';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
status: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['wait', 'process', 'finish', 'error']);
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String
|
||||
},
|
||||
icon: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
stepNumber: '',
|
||||
nextError: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}-item`,
|
||||
`${prefixCls}-status-${this.status}`,
|
||||
{
|
||||
[`${prefixCls}-custom`]: !!this.icon,
|
||||
[`${prefixCls}-next-error`]: this.nextError
|
||||
}
|
||||
]
|
||||
},
|
||||
iconClasses () {
|
||||
let icon = '';
|
||||
|
||||
if (!!this.icon) {
|
||||
icon = this.icon;
|
||||
} else {
|
||||
if (this.status == 'finish') {
|
||||
icon = 'ios-checkmark-empty';
|
||||
} else if (this.status == 'error') {
|
||||
icon = 'ios-close-empty';
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
`${prefixCls}-icon`,
|
||||
`${iconPrefixCls}`,
|
||||
{
|
||||
[`${iconPrefixCls}-${icon}`]: icon != ''
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
status () {
|
||||
if (this.status == 'error') {
|
||||
this.$parent.setNextError();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
102
components/steps/steps.vue
Normal file
102
components/steps/steps.vue
Normal file
|
@ -0,0 +1,102 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-steps';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
current: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
status: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['wait', 'process', 'finish', 'error']);
|
||||
},
|
||||
default: 'process'
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small']);
|
||||
}
|
||||
},
|
||||
direction: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['horizontal', 'vertical']);
|
||||
},
|
||||
default: 'horizontal'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-${this.direction}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
this.updateChildProps(true);
|
||||
this.setNextError();
|
||||
this.updateCurrent(true);
|
||||
},
|
||||
methods: {
|
||||
updateChildProps (isInit) {
|
||||
this.$children.forEach((child, index) => {
|
||||
child.stepNumber = index + 1;
|
||||
|
||||
// 如果已存在status,且在初始化时,则略过
|
||||
// todo 如果当前是error,在current改变时需要处理
|
||||
if (!(isInit && child.status)) {
|
||||
if (index == this.current) {
|
||||
if (this.status != 'error') {
|
||||
child.status = 'process';
|
||||
}
|
||||
} else if (index < this.current) {
|
||||
child.status = 'finish';
|
||||
} else {
|
||||
child.status = 'wait';
|
||||
}
|
||||
}
|
||||
|
||||
if (child.status != 'error' && index != 0) {
|
||||
this.$children[index - 1].nextError = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
setNextError () {
|
||||
this.$children.forEach((child, index) => {
|
||||
if (child.status == 'error' && index != 0) {
|
||||
this.$children[index - 1].nextError = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
updateCurrent (isInit) {
|
||||
if (isInit) {
|
||||
const current_status = this.$children[this.current].status;
|
||||
if (!current_status) {
|
||||
this.$children[this.current].status = this.status;
|
||||
}
|
||||
} else {
|
||||
this.$children[this.current].status = this.status;
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
current () {
|
||||
this.updateChildProps();
|
||||
},
|
||||
status () {
|
||||
this.updateCurrent();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/switch/index.js
Normal file
2
components/switch/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Switch from './switch.vue';
|
||||
export default Switch;
|
56
components/switch/switch.vue
Normal file
56
components/switch/switch.vue
Normal file
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<span :class="wrapClasses" @click="toggle">
|
||||
<span :class="innerClasses">
|
||||
<slot name="open" v-if="checked"></slot>
|
||||
<slot name="close" v-if="!checked"></slot>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-switch';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small']);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-checked`]: this.checked,
|
||||
[`${prefixCls}-disabled`]: this.disabled,
|
||||
[`${prefixCls}-${this.size}`]: !!this.size
|
||||
}
|
||||
]
|
||||
},
|
||||
innerClasses () {
|
||||
return `${prefixCls}-inner`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle () {
|
||||
if (this.disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.checked = !this.checked;
|
||||
this.$emit('on-change', this.checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
2
components/tag/index.js
Normal file
2
components/tag/index.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import Tag from './tag.vue';
|
||||
export default Tag;
|
51
components/tag/tag.vue
Normal file
51
components/tag/tag.vue
Normal file
|
@ -0,0 +1,51 @@
|
|||
<template>
|
||||
<div v-if="!closed" :class="classes" transition="fade">
|
||||
<span :class="textClasses"><slot></slot></span>
|
||||
<Icon v-if="closable" type="ios-close-empty" @click="close"></Icon>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-tag';
|
||||
|
||||
export default {
|
||||
components: { Icon },
|
||||
props: {
|
||||
closable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
color: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['blue', 'green', 'red', 'yellow']);
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
closed: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.color}`]: !!this.color
|
||||
}
|
||||
]
|
||||
},
|
||||
textClasses () {
|
||||
return `${prefixCls}-text`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close (e) {
|
||||
this.closed = true;
|
||||
this.$emit('on-close', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
5
components/timeline/index.js
Normal file
5
components/timeline/index.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import Timeline from './timeline.vue';
|
||||
import TimelineItem from './timeline-item.vue';
|
||||
|
||||
Timeline.Item = TimelineItem;
|
||||
export default Timeline;
|
67
components/timeline/timeline-item.vue
Normal file
67
components/timeline/timeline-item.vue
Normal file
|
@ -0,0 +1,67 @@
|
|||
<template>
|
||||
<li :class="itemClasses">
|
||||
<div :class="tailClasses"></div>
|
||||
<div :class="headClasses" :style="customColor">
|
||||
<slot name="dot"></slot>
|
||||
</div>
|
||||
<div :class="contentClasses">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-timeline';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: 'blue'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
dot: false
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
this.dot = this.$children.length ? true : false;
|
||||
},
|
||||
computed: {
|
||||
itemClasses () {
|
||||
return `${prefixCls}-item`;
|
||||
},
|
||||
tailClasses () {
|
||||
return `${prefixCls}-item-tail`;
|
||||
},
|
||||
headClasses () {
|
||||
return [
|
||||
`${prefixCls}-item-head`,
|
||||
{
|
||||
[`${prefixCls}-item-head-custom`]: this.dot,
|
||||
[`${prefixCls}-item-head-${this.color}`]: this.headColorShow
|
||||
}
|
||||
]
|
||||
},
|
||||
headColorShow () {
|
||||
return this.color == 'blue' || this.color == 'red' || this.color == 'green';
|
||||
},
|
||||
customColor () {
|
||||
let style = {};
|
||||
if (this.color) {
|
||||
if (!this.headColorShow) {
|
||||
style = {
|
||||
'color': this.color,
|
||||
'border-color': this.color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
contentClasses () {
|
||||
return `${prefixCls}-item-content`;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
27
components/timeline/timeline.vue
Normal file
27
components/timeline/timeline.vue
Normal file
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<ul :class="classes">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-timeline';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
pending: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-pending`]: this.pending
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue