Merge pull request #1 from iview/2.0

merge from iview/iview
This commit is contained in:
Lawrence Lee 2017-06-01 17:55:56 +08:00 committed by GitHub
commit b087f93efa
61 changed files with 1759 additions and 365 deletions

View file

@ -4,7 +4,7 @@
</a> </a>
</p> </p>
# iView [![](https://img.shields.io/travis/iview/iview.svg?style=flat-square)](https://travis-ci.org/iview/iview) [![iView](https://img.shields.io/npm/v/iview.svg?style=flat-square)](https://www.npmjs.org/package/iview) [![NPM downloads](http://img.shields.io/npm/dm/iview.svg?style=flat-square)](https://npmjs.org/package/iview) [![Join the chat at https://gitter.im/iview/iview](https://badges.gitter.im/iview/iview.svg)](https://gitter.im/iview/iview?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) # iView [![](https://img.shields.io/travis/iview/iview.svg?style=flat-square)](https://travis-ci.org/iview/iview) [![iView](https://img.shields.io/npm/v/iview.svg?style=flat-square)](https://www.npmjs.org/package/iview) [![NPM downloads](http://img.shields.io/npm/dm/iview.svg?style=flat-square)](https://npmjs.org/package/iview) [![Join the chat at https://gitter.im/iview/iview](https://img.shields.io/badge/chat-on_gitter-30b392.svg?style=flat-square)](https://gitter.im/iview/iview?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
### A high quality UI Toolkit built on Vue.js. ### A high quality UI Toolkit built on Vue.js.

View file

@ -27,7 +27,8 @@ module.exports = merge(webpackBaseConfig, {
resolve: { resolve: {
alias: { alias: {
iview: '../../src/index', iview: '../../src/index',
vue: 'vue/dist/vue.js' // vue: 'vue/dist/vue.js'
vue: 'vue/dist/vue.runtime.js'
} }
}, },
plugins: [ plugins: [

View file

@ -0,0 +1,101 @@
<template>
<Table width="550" border :columns="columns2" :data="data3"></Table>
</template>
<script>
export default {
name: 'etable',
data () {
return {
columns2: [
{
title: '姓名',
key: 'name',
width: 100,
fixed: 'left'
},
{
title: '年龄',
key: 'age',
width: 100
},
{
title: '省份',
key: 'province',
width: 100
},
{
title: '市区',
key: 'city',
width: 100
},
{
title: '地址',
key: 'address',
width: 200
},
{
title: '邮编',
key: 'zip',
width: 100
},
{
title: '操作',
key: 'action',
fixed: 'right',
width: 120,
render: (h, params) => {
return h('div', [
h('Button', {
props: {
type: 'text',
size: 'small'
}
}, '查看'),
h('Button', {
props: {
type: 'text',
size: 'small'
}
}, '编辑')
]);
}
}
],
data3: [
{
name: '王小明',
age: 18,
address: '北京市朝阳区芍药居',
province: '北京市',
city: '朝阳区',
zip: 100000
},
{
name: '张小刚',
age: 25,
address: '北京市海淀区西二旗',
province: '北京市',
city: '海淀区',
zip: 100000
},
{
name: '李小红',
age: 30,
address: '上海市浦东新区世纪大道',
province: '上海市',
city: '浦东新区',
zip: 100000
},
{
name: '周小伟',
age: 26,
address: '深圳市南山区深南大道',
province: '广东',
city: '南山区',
zip: 100000
}
]
}
}
}
</script>

View file

@ -1,39 +1,273 @@
<!--<template>-->
<!--<Row>-->
<!--<i-col span="4">-->
<!--<Button @click="handleLoad">load</Button>-->
<!--{{ v1 }}-->
<!--</i-col>-->
<!--<i-col span="4">-->
<!--<Cascader :data="data2" filterable v-model="v1" style="width: 200px;"></Cascader>-->
<!--&lt;!&ndash;<Cascader :data="data2" filterable v-model="v1" :loadData="loadData"></Cascader>&ndash;&gt;-->
<!--</i-col>-->
<!--</Row>-->
<!--</template>-->
<!--<script>-->
<!--export default {-->
<!--data () {-->
<!--return {-->
<!--v1: [],-->
<!--data2: [-->
<!--{-->
<!--value: 'zhejiang',-->
<!--label: '浙江',-->
<!--children: [],-->
<!--loading: false-->
<!--},-->
<!--{-->
<!--value: 'jiangsu',-->
<!--label: '江苏',-->
<!--children: [{-->
<!--value: 'nanjing',-->
<!--label: '南京',-->
<!--children: [-->
<!--{-->
<!--value: 'zhonghuamen',-->
<!--label: '中华门'-->
<!--},-->
<!--{-->
<!--value: 'v1',-->
<!--label: 'v111'-->
<!--},-->
<!--{-->
<!--value: 'v2',-->
<!--label: 'v2222'-->
<!--},-->
<!--{-->
<!--value: 'v3',-->
<!--label: 'v333'-->
<!--},-->
<!--{-->
<!--value: 'v4',-->
<!--label: 'v4444'-->
<!--},-->
<!--{-->
<!--value: 'v5',-->
<!--label: 'v555'-->
<!--},-->
<!--{-->
<!--value: 'v6',-->
<!--label: 'v666'-->
<!--},-->
<!--{-->
<!--value: 'v7',-->
<!--label: 'v777'-->
<!--}-->
<!--]-->
<!--}]-->
<!--}-->
<!--],-->
<!--data3: [{-->
<!--value: 'beijing',-->
<!--label: '北京',-->
<!--children: [-->
<!--{-->
<!--value: 'gugong',-->
<!--label: '故宫'-->
<!--},-->
<!--{-->
<!--value: 'tiantan',-->
<!--label: '天坛'-->
<!--},-->
<!--{-->
<!--value: 'wangfujing',-->
<!--label: '王府井'-->
<!--}-->
<!--]-->
<!--}, {-->
<!--value: 'jiangsu',-->
<!--label: '江苏',-->
<!--children: [-->
<!--{-->
<!--value: 'nanjing',-->
<!--label: '南京',-->
<!--children: [-->
<!--{-->
<!--value: 'fuzimiao',-->
<!--label: '夫子庙',-->
<!--}-->
<!--]-->
<!--},-->
<!--{-->
<!--value: 'suzhou',-->
<!--label: '苏州',-->
<!--children: [-->
<!--{-->
<!--disabled: true,-->
<!--value: 'zhuozhengyuan',-->
<!--label: '拙政园',-->
<!--},-->
<!--{-->
<!--value: 'shizilin',-->
<!--label: '狮子林',-->
<!--}-->
<!--]-->
<!--}-->
<!--],-->
<!--}]-->
<!--}-->
<!--},-->
<!--methods: {-->
<!--handleLoad () {-->
<!--this.data2[0].loading = !this.data2[0].loading;-->
<!--},-->
<!--loadData (item, cb) {-->
<!--item.loading = true;-->
<!--setTimeout(() => {-->
<!--if (item.value === 'zhejiang') {-->
<!--item.children = [-->
<!--{-->
<!--value: 'hangzhou',-->
<!--label: '杭州',-->
<!--loading: false,-->
<!--children: []-->
<!--}-->
<!--];-->
<!--} else if (item.value === 'hangzhou') {-->
<!--item.children = [-->
<!--{-->
<!--value: 'ali',-->
<!--label: '阿里巴巴'-->
<!--}-->
<!--];-->
<!--}-->
<!--item.loading = false;-->
<!--cb();-->
<!--}, 1000);-->
<!--}-->
<!--}-->
<!--}-->
<!--</script>-->
<!--<template>-->
<!--<Cascader :data="data4" :load-data="loadData"></Cascader>-->
<!--</template>-->
<!--<script>-->
<!--export default {-->
<!--data () {-->
<!--return {-->
<!--data4: [-->
<!--{-->
<!--value: 'beijing',-->
<!--label: '北京',-->
<!--children: [],-->
<!--loading: false-->
<!--},-->
<!--{-->
<!--value: 'hangzhou',-->
<!--label: '杭州',-->
<!--children: [],-->
<!--loading:false-->
<!--}-->
<!--]-->
<!--}-->
<!--},-->
<!--methods: {-->
<!--loadData (item, callback) {-->
<!--item.loading = true;-->
<!--setTimeout(() => {-->
<!--if (item.value === 'beijing') {-->
<!--item.children = [-->
<!--{-->
<!--value: 'talkingdata',-->
<!--label: 'TalkingData'-->
<!--},-->
<!--{-->
<!--value: 'baidu',-->
<!--label: '百度'-->
<!--},-->
<!--{-->
<!--value: 'sina',-->
<!--label: '新浪'-->
<!--}-->
<!--];-->
<!--} else if (item.value === 'hangzhou') {-->
<!--item.children = [-->
<!--{-->
<!--value: 'ali',-->
<!--label: '阿里巴巴'-->
<!--},-->
<!--{-->
<!--value: '163',-->
<!--label: '网易'-->
<!--}-->
<!--];-->
<!--}-->
<!--item.loading = false;-->
<!--callback();-->
<!--}, 1000);-->
<!--}-->
<!--}-->
<!--}-->
<!--</script>-->
<template> <template>
<!--<Cascader :data="data4" :load-data="loadData" style="width: 200px;"></Cascader>-->
<div> <div>
<Cascader :data="data2" v-model="v1" disabled clearable></Cascader> <Cascader :data="data" v-model="model" :load-data="loadData"></Cascader>
<Cascader :data="data2" clearable></Cascader> <ul>
<li v-for="(log, idx) in logs" :key="idx">{{log}}</li>
</ul>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
v1: ['zhejiang', 'hangzhou', 'xihu'], data4: [
data2: [{ {
value: 'zhejiang', value: 'beijing',
label: '浙江', label: '北京',
children: [{ children: [],
loading: false
},
{
value: 'hangzhou', value: 'hangzhou',
label: '杭州', label: '杭州',
children: [{ children: [],
value: 'xihu', loading:false
label: '西湖' }
}] ],
}] data: [],
}, { model: [340000, 340100, 340104],
value: 'jiangsu', count: 1,
label: '江苏', logs: []
disabled: true,
children: [{
value: 'nanjing',
label: '南京',
children: [{
value: 'zhonghuamen',
label: '中华门'
}]
}]
}]
} }
},
methods: {
loadData (item, callback) {
this.logs.push(`${this.count}次请求: ${item.value}`)
this.count++
item.loading = true;
setTimeout(() => {
if (item.value === 340000) {
item.children = [
{value: 340100, label: "合肥市", children: [], loading: false}
];
} else if (item.value === 340100) {
item.children = [
{value: 340104, label: "蜀山区"},
{value: 340111, label: "包河区"}
];
}
item.loading = false;
callback();
}, 1000);
}
},
mounted() {
this.data = [{value: 340000, label: "安徽省", children: [], loading: false}];
} }
} }
</script> </script>

View file

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<Checkbox-group v-model="fruit"> <Checkbox-group v-model="fruit">
<Checkbox v-for="item in tags" :label="item.label"></Checkbox> <Checkbox v-for="item in tags" :label="item.label" :key="item"></Checkbox>
</Checkbox-group> </Checkbox-group>
<div>{{ fruit }}</div> <div>{{ fruit }}</div>
</div> </div>

View file

@ -1,34 +1,14 @@
<template> <template>
<div> <Date-picker type="daterange" placeholder="选择日期" style="width: 200px"></Date-picker>
{{ val1 }}
<Date-picker type="datetime" placeholder="选择日期和时间" style="width: 200px"></Date-picker>
<Date-picker v-model="val1" type="date" placeholder="选择日期" style="width: 200px"></Date-picker>
<Date-picker type="daterange" placement="bottom-end" placeholder="选择日期" style="width: 200px"></Date-picker>
<div @click="val1 = '2017-03-02'">change</div>
</div>
</template> </template>
<script> <script>
export default { export default {
data () {
return {
val1: ''
}
},
computed: {
ddd () {
const date = new Date(this.val1);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}-${month}-${day}`;
}
}
} }
</script> </script>
<!--<template>--> <!--<template>-->
<!--<row>--> <!--<row>-->
<!--<i-col span="12">--> <!--<i-col span="12">-->

View file

@ -1,25 +1,63 @@
<!--<template>-->
<!--<Row>-->
<!--<i-col span="8">-->
<!--<Card>-->
<!--<Dropdown @on-click="handleClick">-->
<!--<a href="javascript:void(0)">-->
<!--下拉菜单-->
<!--<Icon type="arrow-down-b"></Icon>-->
<!--</a>-->
<!--<Dropdown-menu slot="list">-->
<!--<Dropdown-item name="1">驴打滚</Dropdown-item>-->
<!--<Dropdown-item name="2">炸酱面</Dropdown-item>-->
<!--<Dropdown-item name="3" disabled>豆汁儿</Dropdown-item>-->
<!--<Dropdown-item name="4">冰糖葫芦</Dropdown-item>-->
<!--<Dropdown-item name="5" divided>北京烤鸭</Dropdown-item>-->
<!--</Dropdown-menu>-->
<!--</Dropdown>-->
<!--</Card>-->
<!--</i-col>-->
<!--</Row>-->
<!--</template>-->
<!--<script>-->
<!--export default {-->
<!--methods: {-->
<!--handleClick (val) {-->
<!--console.log(val)-->
<!--}-->
<!--}-->
<!--}-->
<!--</script>-->
<template> <template>
<div> <Table border :context="self" :columns="columns7" :data="data6"></Table>
<Dropdown @on-click="handleClick">
<a href="javascript:void(0)">
下拉菜单
<Icon type="arrow-down-b"></Icon>
</a>
<Dropdown-menu slot="list">
<Dropdown-item name="1">驴打滚</Dropdown-item>
<Dropdown-item name="2">炸酱面</Dropdown-item>
<Dropdown-item name="3" disabled>豆汁儿</Dropdown-item>
<Dropdown-item name="4">冰糖葫芦</Dropdown-item>
<Dropdown-item name="5" divided>北京烤鸭</Dropdown-item>
</Dropdown-menu>
</Dropdown>
</div>
</template> </template>
<script> <script>
export default { export default {
data () {
return {
self: this,
columns7: [
{
title: '姓名',
key: 'name',
render (row, column, index) {
return `<Dropdown @on-click="change"><a href="javascript:void(0)">下拉菜单<Icon type="arrow-down-b"></Icon></a><Dropdown-menu slot="list"><Dropdown-item name="1">驴打滚</Dropdown-item><Dropdown-item name="2">炸酱面</Dropdown-item><Dropdown-item disabled name="3">豆汁儿</Dropdown-item><Dropdown-item>冰糖葫芦</Dropdown-item><Dropdown-item divided>北京烤鸭</Dropdown-item></Dropdown-menu></Dropdown>`;
}
}
],
data6: [
{
name: '王小明',
age: 18,
address: '北京市朝阳区芍药居'
}
]
}
},
methods: { methods: {
handleClick (val) { change (s) {
console.log(val) console.log(s)
} }
} }
} }

View file

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<Input-number :max="10" :min="-1" v-model="v1"></Input-number> <Input-number :max="10" name="he" :min="-1" v-model="v1" :autofocus="autofocus"></Input-number>
{{ v1 }} {{ v1 }}
<div @click="c">change v1</div> <div @click="c">change v1</div>
<Input-number disabled :max="10" :min="1" :step="1.2" v-model="v2"></Input-number> <Input-number disabled :max="10" :min="1" :step="1.2" v-model="v2"></Input-number>
@ -12,7 +12,8 @@
data () { data () {
return { return {
v1: 1, v1: 1,
v2: 1 v2: 1,
autofocus: true
}; };
}, },
computed: {}, computed: {},

View file

@ -1,6 +1,6 @@
<template> <template>
<div style="width: 300px;"> <div style="width: 300px;">
<i-input v-model="value11" icon="ios-clock-outline"> <i-input v-model="value11" icon="ios-clock-outline" :autofocus="autofocus">
<span slot="prepend">.com</span> <span slot="prepend">.com</span>
</i-input> </i-input>
<i-input v-model="value11" icon="ios-clock-outline"> <i-input v-model="value11" icon="ios-clock-outline">
@ -17,7 +17,8 @@
value13: '', value13: '',
select1: 'http', select1: 'http',
select2: 'com', select2: 'com',
select3: 'day' select3: 'day',
autofocus: true
} }
} }
} }

View file

@ -1,5 +1,6 @@
<template> <template>
<div> <div>
<i-button @click.native="info">显示普通提示</i-button>
<i-button @click.native="success">显示成功提示</i-button> <i-button @click.native="success">显示成功提示</i-button>
<i-button @click.native="warning">显示警告提示</i-button> <i-button @click.native="warning">显示警告提示</i-button>
<i-button @click.native="error">显示错误提示</i-button> <i-button @click.native="error">显示错误提示</i-button>
@ -9,6 +10,17 @@
<script> <script>
export default { export default {
methods: { methods: {
info () {
// this.$Message.info('');
this.$Message.success({
content: '这是一条普通提示2',
duration: 500,
onClose () {
console.log(123)
},
closable: true
})
},
success () { success () {
this.$Message.success('这是一条成功的提示'); this.$Message.success('这是一条成功的提示');
}, },

View file

@ -1,33 +1,45 @@
<template> <template>
<div> <div>
<Button type="primary" @click="modal1 = true">显示对话框</Button> <Button @click="confirm">标准</Button>
<Button @click="custom">自定义按钮文字</Button>
<Modal <Button @click="async">异步关闭</Button>
v-model="modal1"
:title="title"
@on-ok="ok"
:mask-closable="false"
@on-cancel="cancel">
<p><Button type="ghost" @click="title = '这是标题'">设置标题</Button> {{title}}</p>
<p>对话框内容</p>
<p>对话框内容</p>
</Modal>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data () {
return {
modal1: true,
title:''
}
},
methods: { methods: {
ok () { confirm () {
this.$Message.info('点击了确定'); this.$Modal.confirm({
title: '确认对话框标题',
content: '<p>一些对话框内容</p><p>一些对话框内容</p>',
onOk: () => {
this.$Message.info('点击了确定');
},
onCancel: () => {
this.$Message.info('点击了取消');
}
});
}, },
cancel () { custom () {
this.$Message.info('点击了取消'); this.$Modal.confirm({
title: '确认对话框标题',
content: '<p>一些对话框内容</p><p>一些对话框内容</p>',
okText: 'OK',
cancelText: 'Cancel'
});
},
async () {
this.$Modal.confirm({
title: '确认对话框标题',
content: '<p>对话框将在 2秒 后关闭</p>',
loading: true,
onOk: () => {
setTimeout(() => {
this.$Modal.remove();
this.$Message.info('异步关闭了对话框');
}, 2000);
}
});
} }
} }
} }

View file

@ -1,21 +1,44 @@
<template> <template>
<i-button type="primary" @click.native="time">打开提醒</i-button> <div>
<p>带描述信息</p>
<Button @click="info(false)">消息</Button>
<Button @click="success(false)">成功</Button>
<Button @click="warning(false)">警告</Button>
<Button @click="error(false)">错误</Button>
<p>仅标题</p>
<Button @click="info(true)">消息</Button>
<Button @click="success(true)">成功</Button>
<Button @click="warning(true)">警告</Button>
<Button @click="error(true)">错误</Button>
</div>
</template> </template>
<script> <script>
export default { export default {
methods: { methods: {
time () { info (nodesc) {
this.$Notice.open({ this.$Notice.info({
title: '这是通知标题', title: '这是通知标题',
desc: '这条通知不会自动关闭,需要点击关闭按钮才可以关闭。' desc: nodesc ? '' : '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描述这里是通知描述'
});
},
success (nodesc) {
this.$Notice.success({
title: '这是通知标题',
desc: nodesc ? '' : '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描述这里是通知描述'
});
},
warning (nodesc) {
this.$Notice.warning({
title: '这是通知标题',
desc: nodesc ? '' : '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描述这里是通知描述'
});
},
error (nodesc) {
this.$Notice.error({
title: '这是通知标题',
desc: nodesc ? '' : '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描述这里是通知描述'
}); });
} }
},
mounted () {
this.$Notice.config({
top: 150,
duration: 3
});
} }
} }
</script> </script>

View file

@ -1,16 +1,10 @@
<template> <template>
<div> <div style="margin: 100px;">
<Page :total="100" :current="current"></Page> <Page :total="100" show-sizer placement="top"></Page>
{{ current }}
<Button @click="current = 1">set current</Button>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data () {
return {
current: 2
}
}
} }
</script> </script>

View file

@ -1,8 +1,10 @@
<template> <template>
<div> <div>
<Radio-group v-model="date.sex"> <Radio-group v-model="date.sex">
<Radio label="male form"></Radio> <div v-if="show">
<Radio label="female"></Radio> <Radio label="male"></Radio>
<Radio label="female"></Radio>
</div>
</Radio-group> </Radio-group>
<Button @click="handleChange">change</Button> <Button @click="handleChange">change</Button>
</div> </div>
@ -12,13 +14,15 @@
data () { data () {
return { return {
date: { date: {
sex: '' sex: 'male'
} },
show: false
} }
}, },
methods: { methods: {
handleChange () { handleChange () {
this.date.sex = 'male form'; // this.date.sex = 'male form';
this.show = true;
} }
} }
} }

View file

@ -1,18 +1,166 @@
<template> <template>
<Select v-model="fields.pid" filterable> <Row>
<Option :value="0" label="一级菜单"></Option> <i-col span="4">{{model}}</i-col>
<Option :value="1" label="二级菜单"></Option> <i-col span="8">
</Select> <i-select v-model="model" multiple @input="handleInput" filterable remote :remote-method="remoteMethod" :loading="loading" clearable>
<i-option v-for="option in options" :value="option.value" :key="new Date()">{{option.label}}</i-option>
</i-select>
</i-col>
</Row>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
fields: { // model: 'Alabama',
pid: 0 model: ['Alabama', 'Hawaii'],
} options: [
],
list: [],
loading: false,
states: ["Al", "Alabama", "Alaska", "Arizona",
"Arkansas", "California", "Colorado",
"Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois",
"Indiana", "Iowa", "Kansas", "Kentucky",
"Louisiana", "Maine", "Maryland",
"Massachusetts", "Michigan", "Minnesota",
"Mississippi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire",
"New Jersey", "New Mexico", "New York",
"North Carolina", "North Dakota", "Ohio",
"Oklahoma", "Oregon", "Pennsylvania",
"Rhode Island", "South Carolina",
"South Dakota", "Tennessee", "Texas",
"Utah", "Vermont", "Virginia",
"Washington", "West Virginia", "Wisconsin",
"Wyoming"]
} }
},
mounted () {
this.options = [
// {
// label: '',
// value: 0
// },{
// label: '',
// value: 1
// },{
// label: '',
// value: 2
// },{
// label: '西',
// value: 3
// }
];
},
methods: {
handleAdd () {
this.options = [
{
label: '全部',
value: 0
},{
label: '苹果',
value: 1
},{
label: '香蕉',
value: 2
},{
label: '西瓜',
value: 3
}
]
},
remoteMethod (query) {
console.log(13)
if (query !== '') {
this.loading = true;
setTimeout(() => {
this.loading = false;
this.options = this.list.filter(item => {
return item.label.toLowerCase()
.indexOf(query.toLowerCase()) > -1;
});
}, 500);
} else {
this.options = [];
}
},
handleInput () {
// console.log(1)
}
},
mounted () {
this.list = this.states.map(item => {
return {
value: item,
label: 'L ' + item
};
});
} }
} }
</script> </script>
<!--<template>-->
<!--<div>-->
<!--<Row style="width: 400px;">-->
<!--<i-col span="12" style="padding-right:10px">-->
<!--<Select v-model="model11" filterable>-->
<!--<Option v-for="item in cityList" :value="item.value" :key="item">{{ item.label }}</Option>-->
<!--</Select>-->
<!--</i-col>-->
<!--<i-col span="12">-->
<!--<Select v-model="model12" filterable multiple>-->
<!--<Option v-for="item in cityList" :value="item.value" :key="item">{{ item.label }}</Option>-->
<!--</Select>-->
<!--</i-col>-->
<!--</Row>-->
<!--<Button @click="handleSet">set</Button>-->
<!--</div>-->
<!--</template>-->
<!--<script>-->
<!--export default {-->
<!--data () {-->
<!--return {-->
<!--cityList: [-->
<!--{-->
<!--value: 'beijing',-->
<!--label: '北京市'-->
<!--},-->
<!--{-->
<!--value: 'shanghai',-->
<!--label: '上海市'-->
<!--},-->
<!--{-->
<!--value: 'shenzhen',-->
<!--label: '深圳市'-->
<!--},-->
<!--{-->
<!--value: 'hangzhou',-->
<!--label: '杭州市'-->
<!--},-->
<!--{-->
<!--value: 'nanjing',-->
<!--label: '南京市'-->
<!--},-->
<!--{-->
<!--value: 'chongqing',-->
<!--label: '重庆市'-->
<!--}-->
<!--],-->
<!--model11: '',-->
<!--model12: []-->
<!--}-->
<!--},-->
<!--methods: {-->
<!--handleSet () {-->
<!--this.model11 = 'shanghai';-->
<!--// this.model12 = ['beijing'];-->
<!--}-->
<!--}-->
<!--}-->
<!--</script>-->

View file

@ -1,27 +1,39 @@
<template> <template>
<div> <Table border :columns="columns7" :data="data6" @on-expand="expand"></Table>
<Table border :context="self" :columns="columns7" :data="data6"></Table>
<abc></abc>
</div>
</template> </template>
<script> <script>
import abc from '../components/test.vue'; import etable from '../components/table.vue';
export default { export default {
components: { abc }, components: { etable },
data () { data () {
return { return {
self: this,
columns7: [ columns7: [
{
type: 'expand',
width: 50,
render: (h, params) => {
// return h(etable);
return h('div', params.row.name)
}
},
{ {
title: '姓名', title: '姓名',
key: 'name', key: 'name',
render (row, column, index) { render: (h, params) => {
return `<abc></abc>`; return h('div', [
h('Icon', {
props: {
type: 'person'
}
}),
h('strong', params.row.name)
]);
} }
}, },
{ {
title: '年龄', title: '年龄',
key: 'age' key: 'age',
sortable: true
}, },
{ {
title: '地址', title: '地址',
@ -32,8 +44,34 @@
key: 'action', key: 'action',
width: 150, width: 150,
align: 'center', align: 'center',
render (row, column, index) { render: (h, params) => {
return `<i-button type="primary" size="small" @click="show(${index})">查看</i-button> <i-button type="error" size="small" @click="remove(${index})">删除</i-button>`; return h('div', [
h('Button', {
props: {
type: 'primary',
size: 'small'
},
style: {
marginRight: '5px'
},
on: {
click: () => {
this.show(params.index)
}
}
}, '查看'),
h('Button', {
props: {
type: 'error',
size: 'small'
},
on: {
click: () => {
this.remove(params.index)
}
}
}, '删除')
]);
} }
} }
], ],
@ -51,7 +89,8 @@
{ {
name: '李小红', name: '李小红',
age: 30, age: 30,
address: '上海市浦东新区世纪大道' address: '上海市浦东新区世纪大道',
_expanded: true
}, },
{ {
name: '周小伟', name: '周小伟',
@ -70,6 +109,10 @@
}, },
remove (index) { remove (index) {
this.data6.splice(index, 1); this.data6.splice(index, 1);
},
expand (row, s) {
// console.log(row);
// console.log(s);
} }
} }
} }

View file

@ -178,7 +178,7 @@
setTimeout(function() { setTimeout(function() {
console.log('--1'); console.log('--1');
// _this.data1 = null; // _this.data1 = null;
_this.data1 = _this.getMockData1(); // _this.data1 = _this.getMockData1();
console.log('-fetch-', _this.data1); console.log('-fetch-', _this.data1);
}, 1500); }, 1500);

View file

@ -1,6 +1,6 @@
{ {
"name": "iview", "name": "iview",
"version": "2.0.0-rc.11", "version": "2.0.0-rc.15",
"title": "iView", "title": "iView",
"description": "A high quality UI components Library with Vue.js", "description": "A high quality UI components Library with Vue.js",
"homepage": "http://www.iviewui.com", "homepage": "http://www.iviewui.com",

View file

@ -67,7 +67,8 @@
this.backTop = window.pageYOffset >= this.height; this.backTop = window.pageYOffset >= this.height;
}, },
back () { back () {
scrollTop(window, document.body.scrollTop, 0, this.duration); const sTop = document.documentElement.scrollTop || document.body.scrollTop;
scrollTop(window, sTop, 0, this.duration);
this.$emit('on-click'); this.$emit('on-click');
} }
} }

View file

@ -1,24 +1,21 @@
import Notification from './notification.vue'; import Notification from './notification.vue';
import Vue from 'vue'; import Vue from 'vue';
import { camelcaseToHyphen } from '../../../utils/assist';
Notification.newInstance = properties => { Notification.newInstance = properties => {
const _props = properties || {}; const _props = properties || {};
let props = ''; const Instance = new Vue({
Object.keys(_props).forEach(prop => { data: _props,
props += ' :' + camelcaseToHyphen(prop) + '=' + prop; render (h) {
return h(Notification, {
props: _props
});
}
}); });
const div = document.createElement('div'); const component = Instance.$mount();
div.innerHTML = `<notification${props}></notification>`; document.body.appendChild(component.$el);
document.body.appendChild(div); const notification = Instance.$children[0];
const notification = new Vue({
el: div,
data: _props,
components: { Notification }
}).$children[0];
return { return {
notice (noticeProps) { notice (noticeProps) {

View file

@ -1,10 +1,20 @@
<template> <template>
<transition :name="transitionName"> <transition :name="transitionName">
<div :class="classes" :style="styles"> <div :class="classes" :style="styles">
<div :class="[baseClass + '-content']" ref="content" v-html="content"></div> <template v-if="type === 'notice'">
<a :class="[baseClass + '-close']" @click="close" v-if="closable"> <div :class="[baseClass + '-content']" ref="content" v-html="content"></div>
<i class="ivu-icon ivu-icon-ios-close-empty"></i> <a :class="[baseClass + '-close']" @click="close" v-if="closable">
</a> <i class="ivu-icon ivu-icon-ios-close-empty"></i>
</a>
</template>
<template v-if="type === 'message'">
<div :class="[baseClass + '-content']" ref="content">
<div :class="[baseClass + '-content-text']" v-html="content"></div>
<a :class="[baseClass + '-close']" @click="close" v-if="closable">
<i class="ivu-icon ivu-icon-ios-close-empty"></i>
</a>
</div>
</template>
</div> </div>
</transition> </transition>
</template> </template>
@ -19,6 +29,9 @@
type: Number, type: Number,
default: 1.5 default: 1.5
}, },
type: {
type: String
},
content: { content: {
type: String, type: String,
default: '' default: ''

View file

@ -5,6 +5,7 @@
:key="notice.name" :key="notice.name"
:prefix-cls="prefixCls" :prefix-cls="prefixCls"
:styles="notice.styles" :styles="notice.styles"
:type="notice.type"
:content="notice.content" :content="notice.content"
:duration="notice.duration" :duration="notice.duration"
:closable="notice.closable" :closable="notice.closable"

View file

@ -3,11 +3,17 @@
<div :class="[prefixCls + '-rel']" @click="toggleOpen"> <div :class="[prefixCls + '-rel']" @click="toggleOpen">
<slot> <slot>
<i-input <i-input
readonly ref="input"
:readonly="!filterable"
:disabled="disabled" :disabled="disabled"
v-model="displayRender" :value="displayInputRender"
@on-change="handleInput"
:size="size" :size="size"
:placeholder="placeholder"></i-input> :placeholder="inputPlaceholder"></i-input>
<div
:class="[prefixCls + '-label']"
v-show="filterable && query === ''"
@click="handleFocus">{{ displayRender }}</div>
<Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSelect"></Icon> <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSelect"></Icon>
<Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon> <Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon>
</slot> </slot>
@ -16,12 +22,24 @@
<Drop v-show="visible"> <Drop v-show="visible">
<div> <div>
<Caspanel <Caspanel
v-show="!filterable || (filterable && query === '')"
ref="caspanel" ref="caspanel"
:prefix-cls="prefixCls" :prefix-cls="prefixCls"
:data="data" :data="data"
:disabled="disabled" :disabled="disabled"
:change-on-select="changeOnSelect" :change-on-select="changeOnSelect"
:trigger="trigger"></Caspanel> :trigger="trigger"></Caspanel>
<div :class="[prefixCls + '-dropdown']" v-show="filterable && query !== '' && querySelections.length">
<ul :class="[selectPrefixCls + '-dropdown-list']">
<li
:class="[selectPrefixCls + '-item', {
[selectPrefixCls + '-item-disabled']: item.disabled
}]"
v-for="(item, index) in querySelections"
@click="handleSelectItem(index)" v-html="item.display"></li>
</ul>
</div>
<ul v-show="filterable && query !== '' && !querySelections.length" :class="[prefixCls + '-not-found-tip']"><li>{{ localeNotFoundText }}</li></ul>
</div> </div>
</Drop> </Drop>
</transition> </transition>
@ -35,12 +53,14 @@
import clickoutside from '../../directives/clickoutside'; import clickoutside from '../../directives/clickoutside';
import { oneOf } from '../../utils/assist'; import { oneOf } from '../../utils/assist';
import Emitter from '../../mixins/emitter'; import Emitter from '../../mixins/emitter';
import Locale from '../../mixins/locale';
const prefixCls = 'ivu-cascader'; const prefixCls = 'ivu-cascader';
const selectPrefixCls = 'ivu-select';
export default { export default {
name: 'Cascader', name: 'Cascader',
mixins: [ Emitter ], mixins: [ Emitter, Locale ],
components: { iInput, Drop, Icon, Caspanel }, components: { iInput, Drop, Icon, Caspanel },
directives: { clickoutside }, directives: { clickoutside },
props: { props: {
@ -65,8 +85,7 @@
default: true default: true
}, },
placeholder: { placeholder: {
type: String, type: String
default: '请选择'
}, },
size: { size: {
validator (value) { validator (value) {
@ -88,16 +107,30 @@
default (label) { default (label) {
return label.join(' / '); return label.join(' / ');
} }
},
loadData: {
type: Function
},
filterable: {
type: Boolean,
default: false
},
notFoundText: {
type: String
} }
}, },
data () { data () {
return { return {
prefixCls: prefixCls, prefixCls: prefixCls,
selectPrefixCls: selectPrefixCls,
visible: false, visible: false,
selected: [], selected: [],
tmpSelected: [], tmpSelected: [],
updatingValue: false, // to fix set value in changeOnSelect type updatingValue: false, // to fix set value in changeOnSelect type
currentValue: this.value currentValue: this.value,
query: '',
validDataStr: '',
isLoadedChildren: false // #950
}; };
}, },
computed: { computed: {
@ -106,8 +139,10 @@
`${prefixCls}`, `${prefixCls}`,
{ {
[`${prefixCls}-show-clear`]: this.showCloseIcon, [`${prefixCls}-show-clear`]: this.showCloseIcon,
[`${prefixCls}-size-${this.size}`]: !!this.size,
[`${prefixCls}-visible`]: this.visible, [`${prefixCls}-visible`]: this.visible,
[`${prefixCls}-disabled`]: this.disabled [`${prefixCls}-disabled`]: this.disabled,
[`${prefixCls}-not-found`]: this.filterable && this.query !== '' && !this.querySelections.length
} }
]; ];
}, },
@ -121,6 +156,56 @@
} }
return this.renderFormat(label, this.selected); return this.renderFormat(label, this.selected);
},
displayInputRender () {
return this.filterable ? '' : this.displayRender;
},
localePlaceholder () {
if (this.placeholder === undefined) {
return this.t('i.select.placeholder');
} else {
return this.placeholder;
}
},
inputPlaceholder () {
return this.filterable && this.currentValue.length ? null : this.localePlaceholder;
},
localeNotFoundText () {
if (this.notFoundText === undefined) {
return this.t('i.select.noMatch');
} else {
return this.notFoundText;
}
},
querySelections () {
let selections = [];
function getSelections (arr, label, value) {
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
item.__label = label ? label + ' / ' + item.label : item.label;
item.__value = value ? value + ',' + item.value : item.value;
if (item.children && item.children.length) {
getSelections(item.children, item.__label, item.__value);
delete item.__label;
delete item.__value;
} else {
selections.push({
label: item.__label,
value: item.__value,
display: item.__label,
item: item,
disabled: !!item.disabled
});
}
}
}
getSelections(this.data);
selections = selections.filter(item => item.label.indexOf(this.query) > -1).map(item => {
item.display = item.display.replace(new RegExp(this.query, 'g'), `<span>${this.query}</span>`);
return item;
});
return selections;
} }
}, },
methods: { methods: {
@ -139,7 +224,7 @@
toggleOpen () { toggleOpen () {
if (this.disabled) return false; if (this.disabled) return false;
if (this.visible) { if (this.visible) {
this.handleClose(); if (!this.filterable) this.handleClose();
} else { } else {
this.onFocus(); this.onFocus();
} }
@ -170,10 +255,48 @@
}); });
}); });
} }
},
handleInput (event) {
this.query = event.target.value;
},
handleSelectItem (index) {
const item = this.querySelections[index];
if (item.item.disabled) return false;
this.query = '';
this.$refs.input.currentValue = '';
const oldVal = JSON.stringify(this.currentValue);
this.currentValue = item.value.split(',');
this.emitValue(this.currentValue, oldVal);
this.handleClose();
},
handleFocus () {
this.$refs.input.focus();
},
// loading data updateSelect
getValidData (data) {
function deleteData (item) {
const new_item = Object.assign({}, item);
if ('loading' in new_item) {
delete new_item.loading;
}
if ('__value' in new_item) {
delete new_item.__value;
}
if ('__label' in new_item) {
delete new_item.__label;
}
if ('children' in new_item && new_item.children.length) {
new_item.children = new_item.children.map(i => deleteData(i));
}
return new_item;
}
return data.map(item => deleteData(item));
} }
}, },
mounted () { created () {
this.updateSelected(true); this.validDataStr = JSON.stringify(this.getValidData(this.data));
this.$on('on-result-change', (params) => { this.$on('on-result-change', (params) => {
// lastValue: is click the final val // lastValue: is click the final val
// fromInit: is this emit from update value // fromInit: is this emit from update value
@ -201,12 +324,20 @@
} }
}); });
}, },
mounted () {
this.updateSelected(true);
},
watch: { watch: {
visible (val) { visible (val) {
if (val) { if (val) {
if (this.currentValue.length) { if (this.currentValue.length) {
this.updateSelected(); this.updateSelected();
} }
} else {
if (this.filterable) {
this.query = '';
this.$refs.input.currentValue = '';
}
} }
this.$emit('on-visible-change', val); this.$emit('on-visible-change', val);
}, },
@ -222,8 +353,18 @@
} }
this.updateSelected(true); this.updateSelected(true);
}, },
data () { data: {
this.$nextTick(() => this.updateSelected()); deep: true,
handler () {
const validDataStr = JSON.stringify(this.getValidData(this.data));
if (validDataStr !== this.validDataStr) {
this.validDataStr = validDataStr;
if (!this.isLoadedChildren) {
this.$nextTick(() => this.updateSelected());
}
this.isLoadedChildren = false;
}
}
} }
} }
}; };

View file

@ -1,5 +1,9 @@
<template> <template>
<li :class="classes">{{ data.label }}<i v-if="data.children && data.children.length" class="ivu-icon ivu-icon-ios-arrow-right"></i></li> <li :class="classes">
{{ data.label }}
<i v-if="showArrow" class="ivu-icon ivu-icon-ios-arrow-right"></i>
<i v-if="showLoading" class="ivu-icon ivu-icon-load-c ivu-load-loop"></i>
</li>
</template> </template>
<script> <script>
export default { export default {
@ -18,6 +22,12 @@
[`${this.prefixCls}-menu-item-disabled`]: this.data.disabled [`${this.prefixCls}-menu-item-disabled`]: this.data.disabled
} }
]; ];
},
showArrow () {
return (this.data.children && this.data.children.length) || ('loading' in this.data && !this.data.loading);
},
showLoading () {
return 'loading' in this.data && this.data.loading;
} }
} }
}; };

View file

@ -15,6 +15,7 @@
<script> <script>
import Casitem from './casitem.vue'; import Casitem from './casitem.vue';
import Emitter from '../../mixins/emitter'; import Emitter from '../../mixins/emitter';
import { findComponentUpward } from '../../utils/assist';
export default { export default {
name: 'Caspanel', name: 'Caspanel',
@ -47,23 +48,35 @@
methods: { methods: {
handleClickItem (item) { handleClickItem (item) {
if (this.trigger !== 'click' && item.children) return; if (this.trigger !== 'click' && item.children) return;
this.handleTriggerItem(item); this.handleTriggerItem(item, false, true);
}, },
handleHoverItem (item) { handleHoverItem (item) {
if (this.trigger !== 'hover' || !item.children) return; if (this.trigger !== 'hover' || !item.children) return;
this.handleTriggerItem(item); this.handleTriggerItem(item, false, true);
}, },
handleTriggerItem (item, fromInit = false) { handleTriggerItem (item, fromInit = false, fromUser = false) {
if (item.disabled) return; if (item.disabled) return;
if (item.loading !== undefined && !item.children.length) {
const cascader = findComponentUpward(this, 'Cascader');
if (cascader && cascader.loadData) {
cascader.loadData(item, () => {
// todo
if (fromUser) {
cascader.isLoadedChildren = true;
}
this.handleTriggerItem(item);
});
return;
}
}
// return value back recursion // // return value back recursion //
const backItem = this.getBaseItem(item); const backItem = this.getBaseItem(item);
this.tmpItem = backItem; this.tmpItem = backItem;
this.emitUpdate([backItem]); this.emitUpdate([backItem]);
if (item.children && item.children.length){ if (item.children && item.children.length){
this.sublist = item.children; this.sublist = item.children;
// this.$dispatch('on-result-change', false, this.changeOnSelect, fromInit);
this.dispatch('Cascader', 'on-result-change', { this.dispatch('Cascader', 'on-result-change', {
lastValue: false, lastValue: false,
changeOnSelect: this.changeOnSelect, changeOnSelect: this.changeOnSelect,
@ -71,7 +84,6 @@
}); });
} else { } else {
this.sublist = []; this.sublist = [];
// this.$dispatch('on-result-change', true, this.changeOnSelect, fromInit);
this.dispatch('Cascader', 'on-result-change', { this.dispatch('Cascader', 'on-result-change', {
lastValue: true, lastValue: true,
changeOnSelect: this.changeOnSelect, changeOnSelect: this.changeOnSelect,

View file

@ -324,7 +324,7 @@
if (this[`${direction}CurrentView`] === 'year') { if (this[`${direction}CurrentView`] === 'year') {
this.$refs[`${direction}YearTable`].nextTenYear(); this.$refs[`${direction}YearTable`].nextTenYear();
} else if (this[`${direction}CurrentView`] === 'month') { } else if (this[`${direction}CurrentView`] === 'month') {
this[`${direction}TableYear`]--; this[`${direction}TableYear`]++;
} else { } else {
const date = this.date; const date = this.date;
date.setFullYear(date.getFullYear() + 1); date.setFullYear(date.getFullYear() + 1);

View file

@ -13,7 +13,7 @@
<script> <script>
import Drop from '../select/dropdown.vue'; import Drop from '../select/dropdown.vue';
import clickoutside from '../../directives/clickoutside'; import clickoutside from '../../directives/clickoutside';
import { oneOf } from '../../utils/assist'; import { oneOf, findComponentUpward } from '../../utils/assist';
const prefixCls = 'ivu-dropdown'; const prefixCls = 'ivu-dropdown';
@ -99,8 +99,9 @@
this.currentVisible = false; this.currentVisible = false;
}, },
hasParent () { hasParent () {
const $parent = this.$parent.$parent.$parent; // const $parent = this.$parent.$parent.$parent;
if ($parent && $parent.$options.name === 'Dropdown') { const $parent = findComponentUpward(this, 'Dropdown');
if ($parent) {
return $parent; return $parent;
} else { } else {
return false; return false;

View file

@ -1,5 +1,5 @@
<template> <template>
<form :class="classes"><slot></slot></form> <form :class="classes" @submit="formSubmit"><slot></slot></form>
</template> </template>
<script> <script>
// https://github.com/ElemeFE/element/blob/dev/packages/form/src/form.vue // https://github.com/ElemeFE/element/blob/dev/packages/form/src/form.vue
@ -75,6 +75,9 @@
if (!field) { throw new Error('[iView warn]: must call validateField with valid prop string!'); } if (!field) { throw new Error('[iView warn]: must call validateField with valid prop string!'); }
field.validate('', cb); field.validate('', cb);
},
formSubmit (event) {
event.preventDefault();
} }
}, },
watch: { watch: {

View file

@ -19,10 +19,12 @@
:class="inputClasses" :class="inputClasses"
:disabled="disabled" :disabled="disabled"
autocomplete="off" autocomplete="off"
:autofocus="autofocus"
@focus="focus" @focus="focus"
@blur="blur" @blur="blur"
@keydown.stop="keyDown" @keydown.stop="keyDown"
@change="change" @change="change"
:name="name"
:value="value"> :value="value">
</div> </div>
</div> </div>
@ -89,6 +91,13 @@
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false
},
autofocus: {
type: Boolean,
default: false
},
name: {
type: String
} }
}, },
data () { data () {

View file

@ -7,6 +7,7 @@
<i class="ivu-icon ivu-icon-load-c ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']" v-if="!icon"></i> <i class="ivu-icon ivu-icon-load-c ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']" v-if="!icon"></i>
</transition> </transition>
<input <input
ref="input"
:type="type" :type="type"
:class="inputClasses" :class="inputClasses"
:placeholder="placeholder" :placeholder="placeholder"
@ -16,6 +17,7 @@
:name="name" :name="name"
:value="currentValue" :value="currentValue"
:number="number" :number="number"
:autofocus="autofocus"
@keyup.enter="handleEnter" @keyup.enter="handleEnter"
@focus="handleFocus" @focus="handleFocus"
@blur="handleBlur" @blur="handleBlur"
@ -35,6 +37,7 @@
:readonly="readonly" :readonly="readonly"
:name="name" :name="name"
:value="value" :value="value"
:autofocus="autofocus"
@keyup.enter="handleEnter" @keyup.enter="handleEnter"
@focus="handleFocus" @focus="handleFocus"
@blur="handleBlur" @blur="handleBlur"
@ -98,6 +101,10 @@
number: { number: {
type: Boolean, type: Boolean,
default: false default: false
},
autofocus: {
type: Boolean,
default: false
} }
}, },
data () { data () {
@ -189,6 +196,13 @@
const maxRows = autosize.maxRows; const maxRows = autosize.maxRows;
this.textareaStyles = calcTextareaHeight(this.$refs.textarea, minRows, maxRows); this.textareaStyles = calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
},
focus() {
if (this.type === 'textarea') {
this.$refs.textarea.focus();
} else {
this.$refs.input.focus();
}
} }
}, },
watch: { watch: {

View file

@ -1,24 +1,21 @@
import LoadingBar from './loading-bar.vue'; import LoadingBar from './loading-bar.vue';
import Vue from 'vue'; import Vue from 'vue';
import { camelcaseToHyphen } from '../../utils/assist';
LoadingBar.newInstance = properties => { LoadingBar.newInstance = properties => {
const _props = properties || {}; const _props = properties || {};
let props = ''; const Instance = new Vue({
Object.keys(_props).forEach(prop => { data: _props,
props += ' :' + camelcaseToHyphen(prop) + '=' + prop; render (h) {
return h(LoadingBar, {
props: _props
});
}
}); });
const div = document.createElement('div'); const component = Instance.$mount();
div.innerHTML = `<loading-bar${props}></loading-bar>`; document.body.appendChild(component.$el);
document.body.appendChild(div); const loading_bar = Instance.$children[0];
const loading_bar = new Vue({
el: div,
data: _props,
components: { LoadingBar }
}).$children[0];
return { return {
update (options) { update (options) {
@ -34,7 +31,9 @@ LoadingBar.newInstance = properties => {
}, },
component: loading_bar, component: loading_bar,
destroy () { destroy () {
document.body.removeChild(div); setTimeout(function() {
document.body.removeChild(document.getElementsByClassName('ivu-loading-bar')[0].parentElement);
}, 500);
} }
}; };
}; };

View file

@ -28,12 +28,7 @@ function getMessageInstance () {
return messageInstance; return messageInstance;
} }
function notice (content, duration = defaultDuration, type, onClose) { function notice (content = '', duration = defaultDuration, type, onClose = function () {}, closable = false) {
if (!onClose) {
onClose = function () {
};
}
const iconType = iconTypes[type]; const iconType = iconTypes[type];
// if loading // if loading
@ -52,7 +47,9 @@ function notice (content, duration = defaultDuration, type, onClose) {
<span>${content}</span> <span>${content}</span>
</div> </div>
`, `,
onClose: onClose onClose: onClose,
closable: closable,
type: 'message'
}); });
// 用于手动消除 // 用于手动消除
@ -66,20 +63,50 @@ function notice (content, duration = defaultDuration, type, onClose) {
} }
export default { export default {
info (content, duration, onClose) { info (options) {
return notice(content, duration, 'info', onClose); const type = typeof options;
if (type === 'string') {
options = {
content: options
};
}
return notice(options.content, options.duration, 'info', options.onClose, options.closable);
}, },
success (content, duration, onClose) { success (options) {
return notice(content, duration, 'success', onClose); const type = typeof options;
if (type === 'string') {
options = {
content: options
};
}
return notice(options.content, options.duration, 'success', options.onClose, options.closable);
}, },
warning (content, duration, onClose) { warning (options) {
return notice(content, duration, 'warning', onClose); const type = typeof options;
if (type === 'string') {
options = {
content: options
};
}
return notice(options.content, options.duration, 'warning', options.onClose, options.closable);
}, },
error (content, duration, onClose) { error (options) {
return notice(content, duration, 'error', onClose); const type = typeof options;
if (type === 'string') {
options = {
content: options
};
}
return notice(options.content, options.duration, 'error', options.onClose, options.closable);
}, },
loading (content, duration, onClose) { loading (options) {
return notice(content, duration, 'loading', onClose); const type = typeof options;
if (type === 'string') {
options = {
content: options
};
}
return notice(options.content, options.duration, 'loading', options.onClose, options.closable);
}, },
config (options) { config (options) {
if (options.top) { if (options.top) {

View file

@ -1,8 +1,6 @@
import Vue from 'vue'; import Vue from 'vue';
import Modal from './modal.vue'; import Modal from './modal.vue';
import Icon from '../icon/icon.vue'; import Button from '../button/button.vue';
import iButton from '../button/button.vue';
import { camelcaseToHyphen } from '../../utils/assist';
import Locale from '../../mixins/locale'; import Locale from '../../mixins/locale';
const prefixCls = 'ivu-modal-confirm'; const prefixCls = 'ivu-modal-confirm';
@ -10,36 +8,34 @@ const prefixCls = 'ivu-modal-confirm';
Modal.newInstance = properties => { Modal.newInstance = properties => {
const _props = properties || {}; const _props = properties || {};
let props = ''; // let props = '';
Object.keys(_props).forEach(prop => { // Object.keys(_props).forEach(prop => {
props += ' :' + camelcaseToHyphen(prop) + '=' + prop; // props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
}); // });
//
// const div = document.createElement('div');
// div.innerHTML = `
// <Modal${props} v-model="visible" :width="width" :scrollable="scrollable">
// <div class="${prefixCls}">
// <div class="${prefixCls}-head">
// <div class="${prefixCls}-head-title" v-html="title"></div>
// </div>
// <div class="${prefixCls}-body">
// <div :class="iconTypeCls"><i :class="iconNameCls"></i></div>
// <div v-html="body"></div>
// </div>
// <div class="${prefixCls}-footer">
// <i-button type="text" size="large" v-if="showCancel" @click.native="cancel">{{ localeCancelText }}</i-button>
// <i-button type="primary" size="large" :loading="buttonLoading" @click.native="ok">{{ localeOkText }}</i-button>
// </div>
// </div>
// </Modal>
// `;
// document.body.appendChild(div);
const div = document.createElement('div'); const Instance = new Vue({
div.innerHTML = `
<Modal${props} v-model="visible" :width="width" :scrollable="scrollable">
<div class="${prefixCls}">
<div class="${prefixCls}-head">
<div class="${prefixCls}-head-title" v-html="title"></div>
</div>
<div class="${prefixCls}-body">
<div :class="iconTypeCls"><i :class="iconNameCls"></i></div>
<div v-html="body"></div>
</div>
<div class="${prefixCls}-footer">
<i-button type="text" size="large" v-if="showCancel" @click.native="cancel">{{ localeCancelText }}</i-button>
<i-button type="primary" size="large" :loading="buttonLoading" @click.native="ok">{{ localeOkText }}</i-button>
</div>
</div>
</Modal>
`;
document.body.appendChild(div);
const modal = new Vue({
el: div,
mixins: [ Locale ], mixins: [ Locale ],
components: { Modal, iButton, Icon }, data: Object.assign({}, _props, {
data: Object.assign(_props, {
visible: false, visible: false,
width: 416, width: 416,
title: '', title: '',
@ -53,6 +49,89 @@ Modal.newInstance = properties => {
buttonLoading: false, buttonLoading: false,
scrollable: false scrollable: false
}), }),
render (h) {
let footerVNodes = [];
if (this.showCancel) {
footerVNodes.push(h(Button, {
props: {
type: 'text',
size: 'large'
},
on: {
click: this.cancel
}
}, this.localeCancelText));
}
footerVNodes.push(h(Button, {
props: {
type: 'primary',
size: 'large',
loading: this.buttonLoading
},
on: {
click: this.ok
}
}, this.localeOkText));
return h(Modal, {
props: Object.assign({}, _props, {
width: this.width,
scrollable: this.scrollable
}),
domProps: {
value: this.visible
},
on: {
input: (status) => {
this.visible = status;
}
}
}, [
h('div', {
attrs: {
class: prefixCls
}
}, [
h('div', {
attrs: {
class: `${prefixCls}-head`
}
}, [
h('div', {
attrs: {
class: `${prefixCls}-head-title`
},
domProps: {
innerHTML: this.title
}
})
]),
h('div', {
attrs: {
class: `${prefixCls}-body`
}
}, [
h('div', {
class: this.iconTypeCls
}, [
h('i', {
class: this.iconNameCls
})
]),
h('div', {
domProps: {
innerHTML: this.body
}
})
]),
h('div', {
attrs: {
class: `${prefixCls}-footer`
}
}, footerVNodes)
])
]);
},
computed: { computed: {
iconTypeCls () { iconTypeCls () {
return [ return [
@ -111,7 +190,11 @@ Modal.newInstance = properties => {
onCancel () {}, onCancel () {},
onRemove () {} onRemove () {}
} }
}).$children[0]; });
const component = Instance.$mount();
document.body.appendChild(component.$el);
const modal = Instance.$children[0];
return { return {
show (props) { show (props) {

View file

@ -1,5 +1,5 @@
<template> <template>
<div v-transfer-dom> <div>
<transition :name="transitionNames[1]"> <transition :name="transitionNames[1]">
<div :class="maskClasses" v-show="visible" @click="mask"></div> <div :class="maskClasses" v-show="visible" @click="mask"></div>
</transition> </transition>

View file

@ -71,7 +71,8 @@ function notice (type, options) {
transitionName: 'move-notice', transitionName: 'move-notice',
content: content, content: content,
onClose: onClose, onClose: onClose,
closable: true closable: true,
type: 'notice'
}); });
} }

View file

@ -1,7 +1,7 @@
<template> <template>
<div v-if="showSizer || showElevator" :class="optsClasses"> <div v-if="showSizer || showElevator" :class="optsClasses">
<div v-if="showSizer" :class="sizerClasses"> <div v-if="showSizer" :class="sizerClasses">
<i-select v-model="currentPageSize" :size="size" @on-change="changeSize"> <i-select v-model="currentPageSize" :size="size" :placement="placement" @on-change="changeSize">
<i-option v-for="item in pageSizeOpts" :key="item" :value="item" style="text-align:center;">{{ item }} {{ t('i.page.page') }}</i-option> <i-option v-for="item in pageSizeOpts" :key="item" :value="item" style="text-align:center;">{{ item }} {{ t('i.page.page') }}</i-option>
</i-select> </i-select>
</div> </div>
@ -35,7 +35,8 @@
_current: Number, _current: Number,
pageSize: Number, pageSize: Number,
allPages: Number, allPages: Number,
isSmall: Boolean isSmall: Boolean,
placement: String
}, },
data () { data () {
return { return {

View file

@ -52,6 +52,7 @@
:show-sizer="showSizer" :show-sizer="showSizer"
:page-size="currentPageSize" :page-size="currentPageSize"
:page-size-opts="pageSizeOpts" :page-size-opts="pageSizeOpts"
:placement="placement"
:show-elevator="showElevator" :show-elevator="showElevator"
:_current.once="currentPage" :_current.once="currentPage"
:current="currentPage" :current="currentPage"
@ -92,6 +93,12 @@
return [10, 20, 30, 40]; return [10, 20, 30, 40];
} }
}, },
placement: {
validator (value) {
return oneOf(value, ['top', 'bottom']);
},
default: 'bottom'
},
size: { size: {
validator (value) { validator (value) {
return oneOf(value, ['small']); return oneOf(value, ['small']);
@ -236,8 +243,8 @@
}, },
onSize (pageSize) { onSize (pageSize) {
this.currentPageSize = pageSize; this.currentPageSize = pageSize;
this.changePage(1);
this.$emit('on-page-size-change', pageSize); this.$emit('on-page-size-change', pageSize);
this.changePage(1);
}, },
onPage (page) { onPage (page) {
this.changePage(page); this.changePage(page);

View file

@ -71,6 +71,8 @@
if (this.parent) this.group = true; if (this.parent) this.group = true;
if (!this.group) { if (!this.group) {
this.updateValue(); this.updateValue();
} else {
this.parent.updateValue();
} }
}, },
methods: { methods: {

View file

@ -22,12 +22,13 @@
@keydown.delete="handleInputDelete" @keydown.delete="handleInputDelete"
ref="input"> ref="input">
<Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSingleSelect"></Icon> <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSingleSelect"></Icon>
<Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon> <Icon type="arrow-down-b" :class="[prefixCls + '-arrow']" v-if="!remote"></Icon>
</div> </div>
<transition name="slide-up"> <transition :name="transitionName">
<Drop v-show="visible" ref="dropdown"> <Drop v-show="dropVisible" :placement="placement" ref="dropdown">
<ul v-show="notFound" :class="[prefixCls + '-not-found']"><li>{{ localeNotFoundText }}</li></ul> <ul v-show="notFountShow" :class="[prefixCls + '-not-found']"><li>{{ localeNotFoundText }}</li></ul>
<ul v-show="!notFound" :class="[prefixCls + '-dropdown-list']" ref="options"><slot></slot></ul> <ul v-show="(!notFound && !remote) || (remote && !loading && !notFound)" :class="[prefixCls + '-dropdown-list']"><slot></slot></ul>
<ul v-show="loading" :class="[prefixCls + '-loading']">{{ localeLoadingText }}</ul>
</Drop> </Drop>
</transition> </transition>
</div> </div>
@ -52,6 +53,10 @@
type: [String, Number, Array], type: [String, Number, Array],
default: '' default: ''
}, },
label: {
type: [String, Number, Array],
default: ''
},
multiple: { multiple: {
type: Boolean, type: Boolean,
default: false default: false
@ -74,6 +79,20 @@
filterMethod: { filterMethod: {
type: Function type: Function
}, },
remote: {
type: Boolean,
default: false
},
remoteMethod: {
type: Function
},
loading: {
type: Boolean,
default: false
},
loadingText: {
type: String
},
size: { size: {
validator (value) { validator (value) {
return oneOf(value, ['small', 'large', 'default']); return oneOf(value, ['small', 'large', 'default']);
@ -85,6 +104,12 @@
}, },
notFoundText: { notFoundText: {
type: String type: String
},
placement: {
validator (value) {
return oneOf(value, ['top', 'bottom']);
},
default: 'bottom'
} }
}, },
data () { data () {
@ -97,10 +122,13 @@
selectedMultiple: [], selectedMultiple: [],
focusIndex: 0, focusIndex: 0,
query: '', query: '',
lastQuery: '',
selectToChangeQuery: false, // when select an option, set this first and set query, because query is watching, it will emit event
inputLength: 20, inputLength: 20,
notFound: false, notFound: false,
slotChangeDuration: false, // if slot change duration and in multiple, set true and after slot change, set false slotChangeDuration: false, // if slot change duration and in multiple, set true and after slot change, set false
model: this.value model: this.value,
currentLabel: this.label
}; };
}, },
computed: { computed: {
@ -128,6 +156,8 @@
if (!this.model.length) { if (!this.model.length) {
status = true; status = true;
} }
} else if( this.model === null){
status = true;
} }
return status; return status;
@ -161,6 +191,26 @@
} else { } else {
return this.notFoundText; return this.notFoundText;
} }
},
localeLoadingText () {
if (this.loadingText === undefined) {
return this.t('i.select.loading');
} else {
return this.loadingText;
}
},
transitionName () {
return this.placement === 'bottom' ? 'slide-up' : 'slide-down';
},
dropVisible () {
let status = true;
const options = this.$slots.default || [];
if (!this.loading && this.remote && this.query === '' && !options.length) status = false;
return this.visible && status;
},
notFountShow () {
const options = this.$slots.default || [];
return (this.notFound && !this.remote) || (this.remote && !this.loading && !options.length);
} }
}, },
methods: { methods: {
@ -168,7 +218,6 @@
if (this.disabled) { if (this.disabled) {
return false; return false;
} }
this.visible = !this.visible; this.visible = !this.visible;
}, },
hideMenu () { hideMenu () {
@ -219,8 +268,10 @@
this.options = options; this.options = options;
if (init) { if (init) {
this.updateSingleSelected(true, slot); if (!this.remote) {
this.updateMultipleSelected(true, slot); this.updateSingleSelected(true, slot);
this.updateMultipleSelected(true, slot);
}
} }
}, },
updateSingleSelected (init = false, slot = false) { updateSingleSelected (init = false, slot = false) {
@ -259,7 +310,7 @@
}, },
updateMultipleSelected (init = false, slot = false) { updateMultipleSelected (init = false, slot = false) {
if (this.multiple && Array.isArray(this.model)) { if (this.multiple && Array.isArray(this.model)) {
let selected = []; let selected = this.remote ? this.selectedMultiple : [];
for (let i = 0; i < this.model.length; i++) { for (let i = 0; i < this.model.length; i++) {
const model = this.model[i]; const model = this.model[i];
@ -276,7 +327,16 @@
} }
} }
this.selectedMultiple = selected; const selectedArray = [];
const selectedObject = {};
selected.forEach(item => {
if (!selectedObject[item.value]) {
selectedArray.push(item);
selectedObject[item.value] = 1;
}
});
this.selectedMultiple = this.remote ? selectedArray : selected;
if (slot) { if (slot) {
let selectedModel = []; let selectedModel = [];
@ -299,6 +359,12 @@
if (this.disabled) { if (this.disabled) {
return false; return false;
} }
if (this.remote) {
const tag = this.model[index];
this.selectedMultiple = this.selectedMultiple.filter(item => item.value !== tag);
}
this.model.splice(index, 1); this.model.splice(index, 1);
if (this.filterable && this.visible) { if (this.filterable && this.visible) {
@ -469,6 +535,12 @@
this.query = child.label === undefined ? child.searchLabel : child.label; this.query = child.label === undefined ? child.searchLabel : child.label;
} }
}); });
// remoteMethod
if (this.remote && this.query !== this.lastQuery) {
this.$nextTick(() => {
this.query = this.lastQuery;
});
}
} else { } else {
this.query = ''; this.query = '';
} }
@ -518,6 +590,23 @@
}, },
mounted () { mounted () {
this.modelToQuery(); this.modelToQuery();
// remote
if (this.remote) {
if (!this.multiple && this.model !== '') {
this.selectToChangeQuery = true;
if (this.currentLabel === '') this.currentLabel = this.model;
this.lastQuery = this.currentLabel;
this.query = this.currentLabel;
} else if (this.multiple && this.model.length) {
if (this.currentLabel.length !== this.model.length) this.currentLabel = this.model;
this.selectedMultiple = this.model.map((item, index) => {
return {
value: item,
label: this.currentLabel[index]
};
});
}
}
this.$nextTick(() => { this.$nextTick(() => {
this.broadcastQuery(''); this.broadcastQuery('');
}); });
@ -526,12 +615,30 @@
document.addEventListener('keydown', this.handleKeydown); document.addEventListener('keydown', this.handleKeydown);
this.$on('append', () => { this.$on('append', () => {
this.modelToQuery(); if (!this.remote) {
this.modelToQuery();
this.$nextTick(() => {
this.broadcastQuery('');
});
} else {
this.findChild(child => {
child.selected = this.multiple ? this.model.indexOf(child.value) > -1 : this.model === child.value;
});
}
this.slotChange(); this.slotChange();
this.updateOptions(true, true); this.updateOptions(true, true);
}); });
this.$on('remove', () => { this.$on('remove', () => {
this.modelToQuery(); if (!this.remote) {
this.modelToQuery();
this.$nextTick(() => {
this.broadcastQuery('');
});
} else {
this.findChild(child => {
child.selected = this.multiple ? this.model.indexOf(child.value) > -1 : this.model === child.value;
});
}
this.slotChange(); this.slotChange();
this.updateOptions(true, true); this.updateOptions(true, true);
}); });
@ -550,6 +657,8 @@
} }
if (this.filterable) { if (this.filterable) {
// remote&filterable&multipletruefalse
if (this.query !== '') this.selectToChangeQuery = true;
this.query = ''; this.query = '';
this.$refs.input.focus(); this.$refs.input.focus();
} }
@ -559,7 +668,8 @@
if (this.filterable) { if (this.filterable) {
this.findChild((child) => { this.findChild((child) => {
if (child.value === value) { if (child.value === value) {
this.query = child.label === undefined ? child.searchLabel : child.label; if (this.query !== '') this.selectToChangeQuery = true;
this.lastQuery = this.query = child.label === undefined ? child.searchLabel : child.label;
} }
}); });
} }
@ -587,6 +697,12 @@
} else { } else {
this.updateSingleSelected(); this.updateSingleSelected();
} }
// #957
if (!this.visible && this.filterable) {
this.$nextTick(() => {
this.broadcastQuery('');
});
}
}, },
visible (val) { visible (val) {
if (val) { if (val) {
@ -596,6 +712,16 @@
} else { } else {
this.$refs.input.select(); this.$refs.input.select();
} }
if (this.remote) {
this.findChild(child => {
child.selected = this.multiple ? this.model.indexOf(child.value) > -1 : this.model === child.value;
});
// remote
const options = this.$slots.default || [];
if (this.query !== '' && !options.length) {
this.remoteMethod(this.query);
}
}
} }
this.broadcast('Drop', 'on-update-popper'); this.broadcast('Drop', 'on-update-popper');
} else { } else {
@ -610,20 +736,33 @@
} }
}, },
query (val) { query (val) {
this.$emit('on-query-change', val); if (this.remote && this.remoteMethod) {
if (!this.selectToChangeQuery) {
this.broadcastQuery(val); this.$emit('on-query-change', val);
this.remoteMethod(val);
let is_hidden = true; }
this.focusIndex = 0;
this.$nextTick(() => { this.findChild(child => {
this.findChild((child) => { child.isFocus = false;
if (!child.hidden) {
is_hidden = false;
}
}); });
this.notFound = is_hidden; } else {
}); if (!this.selectToChangeQuery) {
this.$emit('on-query-change', val);
}
this.broadcastQuery(val);
let is_hidden = true;
this.$nextTick(() => {
this.findChild((child) => {
if (!child.hidden) {
is_hidden = false;
}
});
this.notFound = is_hidden;
});
}
this.selectToChangeQuery = false;
this.broadcast('Drop', 'on-update-popper'); this.broadcast('Drop', 'on-update-popper');
} }
} }

View file

@ -5,15 +5,22 @@
<Checkbox :value="checked" @on-change="toggleSelect" :disabled="disabled"></Checkbox> <Checkbox :value="checked" @on-change="toggleSelect" :disabled="disabled"></Checkbox>
</template> </template>
<template v-if="renderType === 'normal'"><span v-html="row[column.key]"></span></template> <template v-if="renderType === 'normal'"><span v-html="row[column.key]"></span></template>
<template v-if="renderType === 'expand'">
<div :class="expandCls" @click="toggleExpand">
<Icon type="ios-arrow-right"></Icon>
</div>
</template>
</div> </div>
</template> </template>
<script> <script>
import Vue from 'vue'; import Vue from 'vue';
import Icon from '../icon/icon.vue';
import Checkbox from '../checkbox/checkbox.vue'; import Checkbox from '../checkbox/checkbox.vue';
import { findComponentUpward } from '../../utils/assist';
export default { export default {
name: 'TableCell', name: 'TableCell',
components: { Checkbox }, components: { Icon, Checkbox },
props: { props: {
prefixCls: String, prefixCls: String,
row: Object, row: Object,
@ -22,6 +29,7 @@
index: Number, // _index of data index: Number, // _index of data
checked: Boolean, checked: Boolean,
disabled: Boolean, disabled: Boolean,
expanded: Boolean,
fixed: { fixed: {
type: [Boolean, String], type: [Boolean, String],
default: false default: false
@ -40,50 +48,81 @@
`${this.prefixCls}-cell`, `${this.prefixCls}-cell`,
{ {
[`${this.prefixCls}-hidden`]: !this.fixed && this.column.fixed && (this.column.fixed === 'left' || this.column.fixed === 'right'), [`${this.prefixCls}-hidden`]: !this.fixed && this.column.fixed && (this.column.fixed === 'left' || this.column.fixed === 'right'),
[`${this.prefixCls}-cell-ellipsis`]: this.column.ellipsis || false [`${this.prefixCls}-cell-ellipsis`]: this.column.ellipsis || false,
[`${this.prefixCls}-cell-with-expand`]: this.renderType === 'expand'
}
];
},
expandCls () {
return [
`${this.prefixCls}-cell-expand`,
{
[`${this.prefixCls}-cell-expand-expanded`]: this.expanded
} }
]; ];
} }
}, },
methods: { methods: {
compile () { compile () {
if (this.column.render) { if (this.column.render && this.renderType === 'render') {
const $parent = this.context; // Render
const template = this.column.render(this.row, this.column, this.index); let isRealRender = true;
const cell = document.createElement('div'); const Table = findComponentUpward(this, 'Table');
cell.innerHTML = template; if (Table.context) isRealRender = false;
this.$el.innerHTML = ''; if (isRealRender) {
let methods = {}; this.$el.innerHTML = '';
Object.keys($parent).forEach(key => { const component = new Vue({
const func = $parent[key]; functional: true,
if (typeof(func) === 'function' && (func.name === 'boundFn' || func.name === 'n')) { render: (h) => {
methods[key] = func; return this.column.render(h, {
row: this.row,
column: this.column,
index: this.index
});
}
});
const Cell = component.$mount();
this.$refs.cell.appendChild(Cell.$el);
} else {
const $parent = this.context;
const template = this.column.render(this.row, this.column, this.index);
const cell = document.createElement('div');
cell.innerHTML = template;
this.$el.innerHTML = '';
let methods = {};
Object.keys($parent).forEach(key => {
const func = $parent[key];
if (typeof(func) === 'function' && (func.name === 'boundFn' || func.name === 'n')) {
methods[key] = func;
}
});
const res = Vue.compile(cell.outerHTML);
// 使 component
const components = {};
Object.getOwnPropertyNames($parent.$options.components).forEach(item => {
components[item] = $parent.$options.components[item];
});
const component = new Vue({
render: res.render,
staticRenderFns: res.staticRenderFns,
methods: methods,
data () {
return $parent._data;
},
components: components
});
if ($parent.$store != undefined) {
component.$store = $parent.$store;
} }
}); component.row = this.row;
const res = Vue.compile(cell.outerHTML); component.column = this.column;
// todo
// 使 component const Cell = component.$mount();
const components = {}; this.$refs.cell.appendChild(Cell.$el);
Object.getOwnPropertyNames($parent.$options.components).forEach(item => { }
components[item] = $parent.$options.components[item];
});
const component = new Vue({
render: res.render,
staticRenderFns: res.staticRenderFns,
methods: methods,
data () {
return $parent._data;
},
components: components
});
component.row = this.row;
component.column = this.column;
const Cell = component.$mount();
this.$refs.cell.appendChild(Cell.$el);
} }
}, },
destroy () { destroy () {
@ -91,6 +130,9 @@
}, },
toggleSelect () { toggleSelect () {
this.$parent.$parent.toggleSelect(this.index); this.$parent.$parent.toggleSelect(this.index);
},
toggleExpand () {
this.$parent.$parent.toggleExpand(this.index);
} }
}, },
created () { created () {
@ -98,6 +140,8 @@
this.renderType = 'index'; this.renderType = 'index';
} else if (this.column.type === 'selection') { } else if (this.column.type === 'selection') {
this.renderType = 'selection'; this.renderType = 'selection';
} else if (this.column.type === 'expand') {
this.renderType = 'expand';
} else if (this.column.render) { } else if (this.column.render) {
this.renderType = 'render'; this.renderType = 'render';
} else { } else {

View file

@ -0,0 +1,37 @@
<template>
<div ref="cell"></div>
</template>
<script>
import Vue from 'vue';
export default {
name: 'TableExpand',
props: {
row: Object,
render: Function,
index: Number,
},
methods: {
compile () {
if (this.render) {
this.$el.innerHTML = '';
const component = new Vue({
functional: true,
render: (h) => {
return this.render(h, {
row: this.row,
index: this.index
});
}
});
const Cell = component.$mount();
this.$refs.cell.appendChild(Cell.$el);
}
}
},
mounted () {
this.$nextTick(() => {
this.compile();
});
}
};
</script>

View file

@ -4,39 +4,47 @@
<col v-for="(column, index) in columns" :width="setCellWidth(column, index, false)"> <col v-for="(column, index) in columns" :width="setCellWidth(column, index, false)">
</colgroup> </colgroup>
<tbody :class="[prefixCls + '-tbody']"> <tbody :class="[prefixCls + '-tbody']">
<tr <template v-for="(row, index) in data">
v-for="(row, index) in data" <tr
:key="row" :key="row"
:class="rowClasses(row._index)" :class="rowClasses(row._index)"
@mouseenter.stop="handleMouseIn(row._index)" @mouseenter.stop="handleMouseIn(row._index)"
@mouseleave.stop="handleMouseOut(row._index)" @mouseleave.stop="handleMouseOut(row._index)"
@click.stop="clickCurrentRow(row._index)" @click.stop="clickCurrentRow(row._index)"
@dblclick.stop="dblclickCurrentRow(row._index)"> @dblclick.stop="dblclickCurrentRow(row._index)">
<td v-for="column in columns" :class="alignCls(column, row)"> <td v-for="column in columns" :class="alignCls(column, row)">
<Cell <Cell
:fixed="fixed" :fixed="fixed"
:prefix-cls="prefixCls" :prefix-cls="prefixCls"
:row="row" :row="row"
:column="column" :column="column"
:natural-index="index" :natural-index="index"
:index="row._index" :index="row._index"
:checked="rowChecked(row._index)" :checked="rowChecked(row._index)"
:disabled="rowDisabled(row._index)" :disabled="rowDisabled(row._index)"
:expanded="rowExpanded(row._index)"
></Cell> ></Cell>
</td> </td>
</tr> </tr>
<tr v-if="rowExpanded(row._index)">
<td :colspan="columns.length" :class="prefixCls + '-expanded-cell'">
<Expand :row="row" :render="expandRender" :index="row._index"></Expand>
</td>
</tr>
</template>
</tbody> </tbody>
</table> </table>
</template> </template>
<script> <script>
// todo :key="row" // todo :key="row"
import Cell from './cell.vue'; import Cell from './cell.vue';
import Expand from './expand.vue';
import Mixin from './mixin'; import Mixin from './mixin';
export default { export default {
name: 'TableBody', name: 'TableBody',
mixins: [ Mixin ], mixins: [ Mixin ],
components: { Cell }, components: { Cell, Expand },
props: { props: {
prefixCls: String, prefixCls: String,
styleObject: Object, styleObject: Object,
@ -49,6 +57,20 @@
default: false default: false
} }
}, },
computed: {
expandRender () {
let render = function () {
return '';
};
for (let i = 0; i < this.columns.length; i++) {
const column = this.columns[i];
if (column.type && column.type === 'expand') {
if (column.render) render = column.render;
}
}
return render;
}
},
methods: { methods: {
rowClasses (_index) { rowClasses (_index) {
return [ return [
@ -66,6 +88,9 @@
rowDisabled(_index){ rowDisabled(_index){
return this.objData[_index] && this.objData[_index]._isDisabled; return this.objData[_index] && this.objData[_index]._isDisabled;
}, },
rowExpanded(_index){
return this.objData[_index] && this.objData[_index]._isExpanded;
},
rowClsName (_index) { rowClsName (_index) {
return this.$parent.rowClassName(this.objData[_index], _index); return this.$parent.rowClassName(this.objData[_index], _index);
}, },

View file

@ -7,7 +7,8 @@
<tr> <tr>
<th v-for="(column, index) in columns" :class="alignCls(column)"> <th v-for="(column, index) in columns" :class="alignCls(column)">
<div :class="cellClasses(column)"> <div :class="cellClasses(column)">
<template v-if="column.type === 'selection'"><Checkbox :value="isSelectAll" @on-change="selectAll"></Checkbox></template> <template v-if="column.type === 'expand'"></template>
<template v-else-if="column.type === 'selection'"><Checkbox :value="isSelectAll" @on-change="selectAll"></Checkbox></template>
<template v-else> <template v-else>
<span v-html="renderHeader(column, index)"></span> <span v-html="renderHeader(column, index)"></span>
<span :class="[prefixCls + '-sort']" v-if="column.sortable"> <span :class="[prefixCls + '-sort']" v-if="column.sortable">

View file

@ -404,6 +404,18 @@
} }
this.$emit('on-selection-change', selection); this.$emit('on-selection-change', selection);
}, },
toggleExpand (_index) {
let data = {};
for (let i in this.objData) {
if (parseInt(i) === _index) {
data = this.objData[i];
}
}
const status = !data._isExpanded;
this.objData[_index]._isExpanded = status;
this.$emit('on-expand', JSON.parse(JSON.stringify(this.cloneData[_index])), status);
},
selectAll (status) { selectAll (status) {
// this.rebuildData.forEach((data) => { // this.rebuildData.forEach((data) => {
// if(this.objData[data._index]._isDisabled){ // if(this.objData[data._index]._isDisabled){
@ -581,9 +593,9 @@
this.data.forEach((row, index) => { this.data.forEach((row, index) => {
const newRow = deepCopy(row);// todo const newRow = deepCopy(row);// todo
newRow._isHover = false; newRow._isHover = false;
if(newRow._disabled){ if (newRow._disabled) {
newRow._isDisabled = newRow._disabled; newRow._isDisabled = newRow._disabled;
}else{ } else {
newRow._isDisabled = false; newRow._isDisabled = false;
} }
if (newRow._checked) { if (newRow._checked) {
@ -591,6 +603,11 @@
} else { } else {
newRow._isChecked = false; newRow._isChecked = false;
} }
if (newRow._expanded) {
newRow._isExpanded = newRow._expanded;
} else {
newRow._isExpanded = false;
}
if (newRow._highlight) { if (newRow._highlight) {
newRow._isHighlight = newRow._highlight; newRow._isHighlight = newRow._highlight;
} else { } else {

View file

@ -1,8 +1,8 @@
<template> <template>
<div :class="classes" :style="style"> <div :class="classes" :style="listStyle">
<div :class="prefixCls + '-header'"> <div :class="prefixCls + '-header'">
<Checkbox :value="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox> <Checkbox :value="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox>
<span>{{ title }}</span> <span :class="prefixCls + '-header-title'" @click="toggleSelectAll(!checkedAll)">{{ title }}</span>
<span :class="prefixCls + '-header-count'">{{ count }}</span> <span :class="prefixCls + '-header-count'">{{ count }}</span>
</div> </div>
<div :class="bodyClasses"> <div :class="bodyClasses">
@ -40,7 +40,7 @@
data: Array, data: Array,
renderFormat: Function, renderFormat: Function,
checkedKeys: Array, checkedKeys: Array,
style: Object, listStyle: Object,
title: [String, Number], title: [String, Number],
filterable: Boolean, filterable: Boolean,
filterPlaceholder: String, filterPlaceholder: String,

View file

@ -39,7 +39,7 @@
renderFormat: this.renderFormat, renderFormat: this.renderFormat,
checkedKeys: this.leftCheckedKeys, checkedKeys: this.leftCheckedKeys,
validKeysCount: this.leftValidKeysCount, validKeysCount: this.leftValidKeysCount,
style: this.listStyle, listStyle: this.listStyle,
title: this.localeTitles[0], title: this.localeTitles[0],
filterable: this.filterable, filterable: this.filterable,
filterPlaceholder: this.localeFilterPlaceholder, filterPlaceholder: this.localeFilterPlaceholder,
@ -68,7 +68,7 @@
renderFormat: this.renderFormat, renderFormat: this.renderFormat,
checkedKeys: this.rightCheckedKeys, checkedKeys: this.rightCheckedKeys,
validKeysCount: this.rightValidKeysCount, validKeysCount: this.rightValidKeysCount,
style: this.listStyle, listStyle: this.listStyle,
title: this.localeTitles[1], title: this.localeTitles[1],
filterable: this.filterable, filterable: this.filterable,
filterPlaceholder: this.localeFilterPlaceholder, filterPlaceholder: this.localeFilterPlaceholder,

View file

@ -2,7 +2,8 @@ export default {
i: { i: {
select: { select: {
placeholder: 'Select', placeholder: 'Select',
noMatch: 'No matching data' noMatch: 'No matching data',
loading: 'Loading'
}, },
table: { table: {
noDataText: 'No Data', noDataText: 'No Data',

View file

@ -2,7 +2,8 @@ export default {
i: { i: {
select: { select: {
placeholder: 'Seleccionar', placeholder: 'Seleccionar',
noMatch: 'Sin coincidencias' noMatch: 'Sin coincidencias',
loading: 'Cargando'
}, },
table: { table: {
noDataText: 'Sin Datos', noDataText: 'Sin Datos',

View file

@ -2,7 +2,8 @@ export default {
i: { i: {
select: { select: {
placeholder: '選んでください', placeholder: '選んでください',
noMatch: 'マッチするデータなし' noMatch: 'マッチするデータなし',
loading: 'ロード中'
}, },
table: { table: {
noDataText: 'データなし', noDataText: 'データなし',

96
src/locale/lang/ru-RU.js Normal file
View file

@ -0,0 +1,96 @@
export default {
i: {
select: {
placeholder: 'Выбрать',
noMatch: 'Нет соответствующих данных',
loading: 'Загрузка'
},
table: {
noDataText: 'Нет данных',
noFilteredDataText: 'Нет данных по фильтру',
confirmFilter: 'Подтвердить',
resetFilter: 'Сброс',
clearFilter: 'Все'
},
datepicker: {
selectDate: 'Выбрать дату',
selectTime: 'Выбрать время',
startTime: 'Начальное время',
endTime: 'Конечное время',
clear: 'Очистить',
ok: 'OK',
month: '',
month1: 'Январь',
month2: 'Февраль',
month3: 'Март',
month4: 'Апрель',
month5: 'Май',
month6: 'Июнь',
month7: 'Июль',
month8: 'Август',
month9: 'Сентябрь',
month10: 'Октябрь',
month11: 'Ноябрь',
month12: 'Декабрь',
year: '',
weeks: {
sun: 'Вс',
mon: 'Пн',
tue: 'Вт',
wed: 'Ср',
thu: 'Чт',
fri: 'Пт',
sat: 'Сб'
},
months: {
m1: 'Янв',
m2: 'Фев',
m3: 'Мар',
m4: 'Апр',
m5: 'Май',
m6: 'Июн',
m7: 'Июл',
m8: 'Авг',
m9: 'Сен',
m10: 'Окт',
m11: 'Ноя',
m12: 'Дек'
}
},
transfer: {
titles: {
source: 'Источник',
target: 'Цель'
},
filterPlaceholder: 'Искать здесь',
notFoundText: 'Не Найдено'
},
modal: {
okText: 'OK',
cancelText: 'Отменить'
},
poptip: {
okText: 'OK',
cancelText: 'Отменить'
},
page: {
prev: 'Пред. страница',
next: 'След. страница',
total: 'Всего',
item: 'пункт',
items: 'пункты',
prev5: 'Пред. 5 страниц',
next5: 'След. 5 страниц',
page: '/page',
goto: 'Идти к',
p: ''
},
rate: {
star: 'Звезда',
stars: 'Звезды'
},
tree: {
emptyText: 'Нет данных'
}
}
};

View file

@ -2,7 +2,8 @@ export default {
i: { i: {
select: { select: {
placeholder: 'Seç', placeholder: 'Seç',
noMatch: 'Eşleşen veri yok' noMatch: 'Eşleşen veri yok',
loading: 'yükleme'
}, },
table: { table: {
noDataText: 'Veri Yok', noDataText: 'Veri Yok',

View file

@ -2,7 +2,8 @@ export default {
i: { i: {
select: { select: {
placeholder: '请选择', placeholder: '请选择',
noMatch: '无匹配数据' noMatch: '无匹配数据',
loading: '加载中'
}, },
table: { table: {
noDataText: '暂无数据', noDataText: '暂无数据',

View file

@ -2,7 +2,8 @@ export default {
i: { i: {
select: { select: {
placeholder: '請選擇', placeholder: '請選擇',
noMatch: '無匹配數據' noMatch: '無匹配數據',
loading: '加載中'
}, },
table: { table: {
noDataText: '暫無數據', noDataText: '暫無數據',

View file

@ -19,6 +19,29 @@
cursor: @cursor-disabled; cursor: @cursor-disabled;
} }
&-label{
width: 100%;
height: 100%;
line-height: 32px;
padding: 0 7px;
box-sizing: border-box;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
cursor: pointer;
font-size: @font-size-small;
position: absolute;
left: 0;
top: 0;
}
&-size-large &-label{
line-height: 36px;
font-size: @font-size-base;
}
&-size-small &-label{
line-height: 26px;
}
.@{cascader-prefix-cls}-arrow:nth-of-type(1) { .@{cascader-prefix-cls}-arrow:nth-of-type(1) {
display: none; display: none;
cursor: pointer; cursor: pointer;
@ -48,6 +71,30 @@
} }
.select-item(@cascader-prefix-cls, @cascader-item-prefix-cls); .select-item(@cascader-prefix-cls, @cascader-item-prefix-cls);
.ivu-select-item span{
color: @error-color;
}
&-dropdown{
padding: 5px 0;
.@{select-dropdown-prefix-cls}-list{
max-height: 190px;
box-sizing: border-box;
overflow: auto;
}
}
&-not-found-tip{
padding: 5px 0;
text-align: center;
color: @btn-disable-color;
li:not([class^=ivu-]){
margin-bottom: 0;
}
}
&-not-found .@{select-dropdown-prefix-cls} {
width: inherit;
}
&-menu{ &-menu{
display: inline-block; display: inline-block;

View file

@ -14,6 +14,18 @@
vertical-align: middle; vertical-align: middle;
position: absolute; position: absolute;
left: 50%; left: 50%;
&-close {
position: absolute;
right: 4px;
top: 9px;
color: #999;
outline: none;
i.@{icon-prefix-cls}{
.close-base(-3px);
}
}
} }
&-notice-content { &-notice-content {
@ -25,6 +37,15 @@
box-shadow: @shadow-base; box-shadow: @shadow-base;
background: #fff; background: #fff;
display: block; display: block;
&-text{
display: inline-block;
}
}
&-notice-closable{
.@{message-prefix-cls}-notice-content-text{
padding-right: 32px;
}
} }
&-success .@{icon-prefix-cls} { &-success .@{icon-prefix-cls} {

View file

@ -50,6 +50,7 @@
white-space: nowrap; white-space: nowrap;
} }
&-with-desc &-title{ &-with-desc &-title{
font-weight: bold;
margin-bottom: 8px; margin-bottom: 8px;
} }
&-with-desc&-with-icon &-title{ &-with-desc&-with-icon &-title{
@ -58,7 +59,8 @@
&-desc { &-desc {
font-size: 12px; font-size: 12px;
color: @legend-color; //color: @legend-color;
color: @text-color;
text-align: justify; text-align: justify;
line-height: 1.5; line-height: 1.5;
} }

View file

@ -173,6 +173,13 @@
&-not-found{ &-not-found{
text-align: center; text-align: center;
color: @btn-disable-color; color: @btn-disable-color;
li:not([class^=ivu-]){
margin-bottom: 0;
}
}
&-loading{
text-align: center;
color: @btn-disable-color;
} }
&-multiple .@{css-prefix}tag{ &-multiple .@{css-prefix}tag{

View file

@ -145,6 +145,24 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
&-with-expand{
height: 47px;
line-height: 47px;
padding: 0;
text-align: center;
}
&-expand{
cursor: pointer;
transition: transform @transition-time @ease-in-out;
i{
font-size: @font-size-base;
}
&-expanded{
transform: rotate(90deg);
}
}
} }
&-hidden{ &-hidden{
visibility: hidden; visibility: hidden;
@ -156,6 +174,11 @@
vertical-align: middle; vertical-align: middle;
} }
td&-expanded-cell{
padding: 20px 50px;
background: @table-thead-bg;
}
&-stripe &-body, &-stripe &-body,
&-stripe &-fixed-body &-stripe &-fixed-body
{ {
@ -184,6 +207,13 @@
height: 60px; height: 60px;
line-height: 60px; line-height: 60px;
} }
.@{table-prefix-cls}-cell-with-expand{
height: 59px;
line-height: 59px;
i{
font-size: @font-size-base+2;
}
}
} }
&-small{ &-small{
@ -197,6 +227,10 @@
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
} }
.@{table-prefix-cls}-cell-with-expand{
height: 39px;
line-height: 39px;
}
} }
&-row-highlight, &-row-highlight,

View file

@ -31,6 +31,10 @@
left: 0; left: 0;
width: 100%; width: 100%;
&-title{
cursor: pointer;
}
& > span{ & > span{
padding-left: 4px; padding-left: 4px;
} }

View file

@ -3,25 +3,25 @@
@css-prefix-iconfont : ivu-icon; @css-prefix-iconfont : ivu-icon;
// Color // Color
@primary-color : #3399ff; @primary-color : #2d8cf0;
@info-color : #2db7f5; @info-color : #2db7f5;
@success-color : #00cc66; @success-color : #19be6b;
@warning-color : #ff9900; @warning-color : #ff9900;
@error-color : #ff3300; @error-color : #ed3f14;
@link-color : #3399ff; @link-color : #2D8cF0;
@link-hover-color : tint(@link-color, 20%); @link-hover-color : tint(@link-color, 20%);
@link-active-color : shade(@link-color, 5%); @link-active-color : shade(@link-color, 5%);
@selected-color : fade(@primary-color, 90%); @selected-color : fade(@primary-color, 90%);
@tooltip-color : #fff; @tooltip-color : #fff;
@subsidiary-color : #9ea7b4; @subsidiary-color : #80848f;
@rate-star-color : #f5a623; @rate-star-color : #f5a623;
// Base // Base
@body-background : #fff; @body-background : #fff;
@font-family : "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif; @font-family : "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
@code-family : Consolas,Menlo,Courier,monospace; @code-family : Consolas,Menlo,Courier,monospace;
@title-color : #464c5b; @title-color : #1c2438;
@text-color : #657180; @text-color : #495060;
@font-size-base : 14px; @font-size-base : 14px;
@font-size-small : 12px; @font-size-small : 12px;
@line-height-base : 1.5; @line-height-base : 1.5;
@ -31,16 +31,16 @@
@cursor-disabled : not-allowed; @cursor-disabled : not-allowed;
// Border color // Border color
@border-color-base : #d7dde4; // outside @border-color-base : #dddee1; // outside
@border-color-split : #e3e8ee; // inside @border-color-split : #e9eaec; // inside
// Background color // Background color
@background-color-base : #f7f7f7; // base @background-color-base : #f7f7f7; // base
@background-color-select-hover: @input-disabled-bg; @background-color-select-hover: @input-disabled-bg;
@tooltip-bg : rgba(70, 76, 91, .9); @tooltip-bg : rgba(70, 76, 91, .9);
@head-bg : #f9fafc; @head-bg : #f9fafc;
@table-thead-bg : #f5f7f9; @table-thead-bg : #f8f8f9;
@table-td-stripe-bg : #f5f7f9; @table-td-stripe-bg : #f8f8f9;
@table-td-hover-bg : #ebf7ff; @table-td-hover-bg : #ebf7ff;
@table-td-highlight-bg : #ebf7ff; @table-td-highlight-bg : #ebf7ff;
@menu-dark-active-bg : #313540; @menu-dark-active-bg : #313540;
@ -66,7 +66,7 @@
@btn-border-radius-small: 3px; @btn-border-radius-small: 3px;
@btn-group-border : shade(@primary-color, 5%); @btn-group-border : shade(@primary-color, 5%);
@btn-disable-color : #c3cbd6; @btn-disable-color : #bbbec4;
@btn-disable-bg : @background-color-base; @btn-disable-bg : @background-color-base;
@btn-disable-border : @border-color-base; @btn-disable-border : @border-color-base;

View file

@ -133,7 +133,7 @@
line-height: @line-height-base; line-height: @line-height-base;
user-select: none; user-select: none;
.button-size(@btn-padding-base; @btn-font-size; @btn-border-radius); .button-size(@btn-padding-base; @btn-font-size; @btn-border-radius);
transform: translate3d(0, 0, 0); //transform: translate3d(0, 0, 0);
//transition: all @transition-time linear; //transition: all @transition-time linear;
transition: color @transition-time linear, background-color @transition-time linear, border @transition-time linear; transition: color @transition-time linear, background-color @transition-time linear, border @transition-time linear;