empty master
This commit is contained in:
parent
92c1162255
commit
67d534df27
276 changed files with 0 additions and 28368 deletions
5
.babelrc
5
.babelrc
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"presets": ["es2015"],
|
||||
"plugins": ["transform-runtime"],
|
||||
"comments": false
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
root = true
|
||||
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"root": true,
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"plugins": [ "html" ],
|
||||
"rules": {
|
||||
"indent": ["error", 4, { "SwitchCase": 1 }],
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["error", "always"],
|
||||
"no-console": ["error"]
|
||||
}
|
||||
}
|
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -1 +0,0 @@
|
|||
src/styles/**/* linguist-vendored=false
|
25
.github/ISSUE_TEMPLATE.md
vendored
25
.github/ISSUE_TEMPLATE.md
vendored
|
@ -1,25 +0,0 @@
|
|||
<!--
|
||||
issue 仅用于提交 bug 或 feature 及 文档错误,其余疑问恕不作答。提问前请先阅读 https://github.com/iview/iview/issues/79 和相关文档后,考虑是否开启issue。
|
||||
-->
|
||||
<!--
|
||||
我们十分感谢有价值的 issue 贡献者,所以请填写以下内容。如果提问不符要求、在文档中已有解答、已有相同 issue,我们将直接 close,感谢理解。
|
||||
-->
|
||||
|
||||
### iView 版本号
|
||||
<!-- 0.9.10 -->
|
||||
|
||||
### 操作系统/浏览器 版本号
|
||||
<!-- macOS/Chrome 54 -->
|
||||
|
||||
### Vue 版本号
|
||||
<!-- 1.0.26 -->
|
||||
|
||||
### 能够复现问题的在线示例
|
||||
<!-- 使用下面的在线链接快速创建示例 -->
|
||||
<!-- https://codepen.io/anon/pen/NbEbja -->
|
||||
|
||||
### 复现步骤
|
||||
|
||||
### 问题现象,以及你期望的结果是怎样的?
|
||||
|
||||
### 你估计可能的原因是什么(选填)?
|
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -1,20 +0,0 @@
|
|||
*.iml
|
||||
.idea
|
||||
.ipr
|
||||
.iws
|
||||
*.diff
|
||||
*.patch
|
||||
*.bak
|
||||
.DS_Store
|
||||
node_modules/
|
||||
node_modules2/
|
||||
.project
|
||||
.settings
|
||||
npm-debug.log
|
||||
.*proj
|
||||
.svn/
|
||||
*.swp
|
||||
*.swo
|
||||
*.log
|
||||
test/dist/
|
||||
dist/
|
|
@ -1,7 +0,0 @@
|
|||
.*
|
||||
*.md
|
||||
*.yml
|
||||
build/
|
||||
node_modules/
|
||||
test/
|
||||
gulpfile.js
|
|
@ -1,5 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "4"
|
||||
script:
|
||||
- npm run test
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 iview
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
83
README.md
83
README.md
|
@ -1,83 +0,0 @@
|
|||
<p align="center">
|
||||
<a href="https://www.iviewui.com">
|
||||
<img width="200" src="https://raw.githubusercontent.com/iview/iview/master/assets/logo.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
# iView [](https://travis-ci.org/iview/iview) [](https://www.npmjs.org/package/iview) [](https://npmjs.org/package/iview) [](https://gitter.im/iview/iview?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
### A high quality UI Components Library with Vue.js
|
||||
|
||||
> iView works only with Vue 1.0 currently. We have been in developing. English document is coming soon. Please pay attention to the iView.
|
||||
|
||||
## Docs
|
||||
|
||||
### [中文文档](https://www.iviewui.com)
|
||||
### English (Coming soon)
|
||||
|
||||
## Overview
|
||||
|
||||
### [组件概览(Component Overview)](https://www.iviewui.com/overview)
|
||||
|
||||
## Features
|
||||
|
||||
- High quality and rich functions
|
||||
- Friendly APIs,free and flexible
|
||||
- Great Documentation
|
||||
- It is quite beautiful
|
||||
- Using .vue file development mode
|
||||
- Based on npm + webpack + babel, using ES2015
|
||||
|
||||
## Programming
|
||||
|
||||

|
||||
|
||||
## Install
|
||||
|
||||
### Install vue-webpack project in the first place
|
||||
|
||||
Use [iview-project](https://github.com/iview/iview-project)(Recommended) Or [vue-cli](https://github.com/vuejs/vue-cli)
|
||||
|
||||
### Install iView
|
||||
|
||||
using npm
|
||||
```
|
||||
npm install iview --save
|
||||
```
|
||||
Or using script tag for global use
|
||||
```
|
||||
<script type="text/javascript" src="iview.min.js"></script>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```html
|
||||
<template>
|
||||
<Slider :value.sync="value" range></Slider>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
value: [20, 50]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
Use css
|
||||
```js
|
||||
import 'iview/dist/styles/iview.css';
|
||||
```
|
||||
|
||||
## Browser Support
|
||||
|
||||
Normal browsers and Internet Explorer 9+.
|
||||
|
||||
## Links
|
||||
|
||||
- [TalkingData](https://github.com/TalkingData)
|
||||
- [Vue](https://github.com/vuejs/vue)
|
||||
- [Webpack](https://github.com/webpack/webpack)
|
||||
- [ionicons](https://github.com/driftyco/ionicons)
|
||||
- [Ant Design](https://github.com/ant-design/ant-design)
|
BIN
assets/iview.png
BIN
assets/iview.png
Binary file not shown.
Before Width: | Height: | Size: 160 KiB |
BIN
assets/logo.png
BIN
assets/logo.png
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
BIN
assets/pay.png
BIN
assets/pay.png
Binary file not shown.
Before Width: | Height: | Size: 158 KiB |
|
@ -1,25 +0,0 @@
|
|||
var gulp = require('gulp');
|
||||
var cleanCSS = require('gulp-clean-css');
|
||||
var less = require('gulp-less');
|
||||
var rename = require('gulp-rename');
|
||||
var autoprefixer = require('gulp-autoprefixer');
|
||||
|
||||
// 编译less
|
||||
gulp.task('css', function () {
|
||||
gulp.src('../src/styles/index.less')
|
||||
.pipe(less())
|
||||
.pipe(autoprefixer({
|
||||
browsers: ['last 2 versions', 'ie > 8']
|
||||
}))
|
||||
.pipe(cleanCSS())
|
||||
.pipe(rename('iview.css'))
|
||||
.pipe(gulp.dest('../dist/styles'));
|
||||
});
|
||||
|
||||
// 拷贝字体文件
|
||||
gulp.task('fonts', function () {
|
||||
gulp.src('../src/styles/common/iconfont/fonts/*.*')
|
||||
.pipe(gulp.dest('../dist/styles/fonts'));
|
||||
});
|
||||
|
||||
gulp.task('default', ['css', 'fonts']);
|
|
@ -1,61 +0,0 @@
|
|||
/**
|
||||
* 本地预览
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
var webpack = require('webpack');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
// 入口
|
||||
entry: {
|
||||
main: './test/main',
|
||||
vendors: ['vue', 'vue-router']
|
||||
},
|
||||
// 输出
|
||||
output: {
|
||||
path: path.join(__dirname, '../test/dist'),
|
||||
publicPath: '/test/dist/',
|
||||
filename: '[name].js',
|
||||
chunkFilename: '[name].chunk.js'
|
||||
},
|
||||
// 加载器
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.vue$/, loader: 'vue' },
|
||||
{ test: /\.js$/, loader: 'babel', exclude: /node_modules/ },
|
||||
{ test: /\.css$/, loader: 'style!css!autoprefixer'},
|
||||
{ test: /\.less$/, loader: 'style!css!less' },
|
||||
{ test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
|
||||
{ test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, loader: 'url-loader?limit=8192'},
|
||||
{ test: /\.(html|tpl)$/, loader: 'html-loader' }
|
||||
]
|
||||
},
|
||||
vue: {
|
||||
loaders: {
|
||||
css: ExtractTextPlugin.extract(
|
||||
"style-loader",
|
||||
"css-loader?sourceMap",
|
||||
{
|
||||
publicPath: "/test/dist/"
|
||||
}
|
||||
),
|
||||
less: ExtractTextPlugin.extract(
|
||||
'vue-style-loader',
|
||||
'css-loader!less-loader'
|
||||
),
|
||||
js: 'babel'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
// require时省略的扩展名,如:require('module') 不需要module.js
|
||||
extensions: ['', '.js', '.vue'],
|
||||
alias: {
|
||||
iview: '../../src/index'
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new ExtractTextPlugin("[name].css",{ allChunks : true,resolve : ['modules'] }), // 提取CSS
|
||||
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'), // 提取第三方库
|
||||
]
|
||||
};
|
|
@ -1,56 +0,0 @@
|
|||
var path = require('path');
|
||||
var webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
main: './src/index.js'
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../dist'),
|
||||
publicPath: '/dist/',
|
||||
filename: 'iview.js',
|
||||
library: 'iview',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true
|
||||
},
|
||||
externals: {
|
||||
vue: {
|
||||
root: 'Vue',
|
||||
commonjs: 'vue',
|
||||
commonjs2: 'vue',
|
||||
amd: 'vue'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.vue']
|
||||
},
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue'
|
||||
}, {
|
||||
test: /\.js$/,
|
||||
loader: 'babel',
|
||||
exclude: /node_modules/
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
loader: 'style!css!autoprefixer'
|
||||
}, {
|
||||
test: /\.less$/,
|
||||
loader: 'style!css!less'
|
||||
}, {
|
||||
test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
|
||||
loader: 'url?limit=8192'
|
||||
}, {
|
||||
test: /\.(html|tpl)$/,
|
||||
loader: 'vue-html'
|
||||
}]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"development"'
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
var path = require('path');
|
||||
var webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
main: './src/index.js'
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../dist'),
|
||||
publicPath: '/dist/',
|
||||
filename: 'iview.min.js',
|
||||
library: 'iview',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true
|
||||
},
|
||||
externals: {
|
||||
vue: {
|
||||
root: 'Vue',
|
||||
commonjs: 'vue',
|
||||
commonjs2: 'vue',
|
||||
amd: 'vue'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.vue']
|
||||
},
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue'
|
||||
}, {
|
||||
test: /\.js$/,
|
||||
loader: 'babel',
|
||||
exclude: /node_modules/
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
loader: 'style!css!autoprefixer'
|
||||
}, {
|
||||
test: /\.less$/,
|
||||
loader: 'style!css!less'
|
||||
}, {
|
||||
test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
|
||||
loader: 'url?limit=8192'
|
||||
}, {
|
||||
test: /\.(html|tpl)$/,
|
||||
loader: 'vue-html'
|
||||
}]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
}),
|
||||
new webpack.optimize.OccurenceOrderPlugin()
|
||||
]
|
||||
}
|
81
package.json
81
package.json
|
@ -1,81 +0,0 @@
|
|||
{
|
||||
"name": "iview",
|
||||
"version": "1.0.2",
|
||||
"title": "iView",
|
||||
"description": "A high quality UI components Library with Vue.js",
|
||||
"homepage": "http://www.iviewui.com",
|
||||
"keywords": [
|
||||
"iview",
|
||||
"vue",
|
||||
"vue.js",
|
||||
"component",
|
||||
"components",
|
||||
"ui",
|
||||
"framework"
|
||||
],
|
||||
"main": "dist/iview.js",
|
||||
"files": [
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server --content-base test/ --open --inline --hot --compress --history-api-fallback --port 8081 --config build/webpack.dev.config.js",
|
||||
"dist:style": "gulp --gulpfile build/build-style.js",
|
||||
"dist:dev": "webpack --config build/webpack.dist.dev.config.js",
|
||||
"dist:prod": "webpack --config build/webpack.dist.prod.config.js",
|
||||
"dist": "npm run dist:style && npm run dist:dev && npm run dist:prod",
|
||||
"lint": "eslint --fix --ext .js,.vue src",
|
||||
"test": "npm run dist && npm run lint",
|
||||
"prepublish": "npm run dist"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/iview/iview"
|
||||
},
|
||||
"author": "Aresn",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/iview/iview/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-validator": "^1.6.7",
|
||||
"core-js": "^2.4.1",
|
||||
"deepmerge": "^1.3.1",
|
||||
"popper.js": "^0.6.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^1.0.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer-loader": "^2.0.0",
|
||||
"babel": "^6.3.13",
|
||||
"babel-core": "^6.11.4",
|
||||
"babel-loader": "^6.2.4",
|
||||
"babel-plugin-transform-runtime": "^6.12.0",
|
||||
"babel-preset-es2015": "^6.9.0",
|
||||
"babel-runtime": "^6.11.6",
|
||||
"css-loader": "^0.23.1",
|
||||
"eslint": "^3.12.2",
|
||||
"eslint-plugin-html": "^1.7.0",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.5",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-autoprefixer": "^3.1.1",
|
||||
"gulp-clean-css": "^2.0.13",
|
||||
"gulp-less": "^3.1.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"html-loader": "^0.3.0",
|
||||
"less": "^2.7.1",
|
||||
"less-loader": "^2.2.3",
|
||||
"style-loader": "^0.13.1",
|
||||
"url-loader": "^0.5.7",
|
||||
"vue": "^1.0.26",
|
||||
"vue-hot-reload-api": "^1.3.3",
|
||||
"vue-html-loader": "^1.2.3",
|
||||
"vue-loader": "^8.5.3",
|
||||
"vue-router": "^0.7.13",
|
||||
"vue-style-loader": "^1.0.0",
|
||||
"webpack": "^1.13.1",
|
||||
"webpack-dev-server": "^1.16.1"
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
<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>
|
|
@ -1,2 +0,0 @@
|
|||
import Affix from './affix.vue';
|
||||
export default Affix;
|
|
@ -1,106 +0,0 @@
|
|||
<template>
|
||||
<div v-if="!closed" :class="wrapClasses" transition="fade">
|
||||
<span :class="iconClasses" v-if="showIcon">
|
||||
<slot name="icon">
|
||||
<Icon :type="iconType"></Icon>
|
||||
</slot>
|
||||
</span>
|
||||
<span :class="messageClasses"><slot></slot></span>
|
||||
<span :class="descClasses" v-el:desc><slot name="desc"></slot></span>
|
||||
<a :class="closeClasses" v-if="closable" @click="close">
|
||||
<slot name="close">
|
||||
<Icon type="ios-close-empty"></Icon>
|
||||
</slot>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-alert';
|
||||
|
||||
export default {
|
||||
components: { Icon },
|
||||
props: {
|
||||
type: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['success', 'info', 'warning', 'error']);
|
||||
},
|
||||
default: 'info'
|
||||
},
|
||||
closable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
banner: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
closed: false,
|
||||
desc: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-${this.type}`,
|
||||
{
|
||||
[`${prefixCls}-with-icon`]: this.showIcon,
|
||||
[`${prefixCls}-with-desc`]: this.desc,
|
||||
[`${prefixCls}-with-banner`]: this.banner
|
||||
}
|
||||
];
|
||||
},
|
||||
messageClasses () {
|
||||
return `${prefixCls}-message`;
|
||||
},
|
||||
descClasses () {
|
||||
return `${prefixCls}-desc`;
|
||||
},
|
||||
closeClasses () {
|
||||
return `${prefixCls}-close`;
|
||||
},
|
||||
iconClasses () {
|
||||
return `${prefixCls}-icon`;
|
||||
},
|
||||
iconType () {
|
||||
let type = '';
|
||||
|
||||
switch (this.type) {
|
||||
case 'success':
|
||||
type = 'checkmark-circled';
|
||||
break;
|
||||
case 'info':
|
||||
type = 'information-circled';
|
||||
break;
|
||||
case 'warning':
|
||||
type = 'android-alert';
|
||||
break;
|
||||
case 'error':
|
||||
type = 'close-circled';
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close (e) {
|
||||
this.closed = true;
|
||||
this.$emit('on-close', e);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.desc = this.$els.desc.innerHTML != '';
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,2 +0,0 @@
|
|||
import Alert from './alert.vue';
|
||||
export default Alert;
|
|
@ -1,75 +0,0 @@
|
|||
<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>
|
||||
import { scrollTop } from '../../utils/assist';
|
||||
const prefixCls = 'ivu-back-top';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
height: {
|
||||
type: Number,
|
||||
default: 400
|
||||
},
|
||||
bottom: {
|
||||
type: Number,
|
||||
default: 30
|
||||
},
|
||||
right: {
|
||||
type: Number,
|
||||
default: 30
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 1000
|
||||
}
|
||||
},
|
||||
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 () {
|
||||
this.backTop = window.pageYOffset >= this.height;
|
||||
},
|
||||
back () {
|
||||
scrollTop(window, document.body.scrollTop, 0, this.duration);
|
||||
this.$emit('on-click');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,2 +0,0 @@
|
|||
import BackTop from './back-top.vue';
|
||||
export default BackTop;
|
|
@ -1,77 +0,0 @@
|
|||
<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>
|
|
@ -1,2 +0,0 @@
|
|||
import Badge from './badge.vue';
|
||||
export default Badge;
|
|
@ -1,37 +0,0 @@
|
|||
import Notification from './notification.vue';
|
||||
import Vue from 'vue';
|
||||
import { camelcaseToHyphen } from '../../../utils/assist';
|
||||
|
||||
Notification.newInstance = properties => {
|
||||
const _props = properties || {};
|
||||
|
||||
let props = '';
|
||||
Object.keys(_props).forEach(prop => {
|
||||
props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
|
||||
});
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `<notification${props}></notification>`;
|
||||
document.body.appendChild(div);
|
||||
|
||||
const notification = new Vue({
|
||||
el: div,
|
||||
data: _props,
|
||||
components: { Notification }
|
||||
}).$children[0];
|
||||
|
||||
return {
|
||||
notice (noticeProps) {
|
||||
notification.add(noticeProps);
|
||||
},
|
||||
remove (key) {
|
||||
notification.close(key);
|
||||
},
|
||||
component: notification,
|
||||
destroy () {
|
||||
document.body.removeChild(div);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default Notification;
|
|
@ -1,104 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" :style="style" :transition="transitionName">
|
||||
<div :class="[baseClass + '-content']" v-el:content>{{{ content }}}</div>
|
||||
<a :class="[baseClass + '-close']" @click="close" v-if="closable">
|
||||
<i class="ivu-icon ivu-icon-ios-close-empty"></i>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
prefixCls: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 1.5
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
style: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {
|
||||
right: '50%'
|
||||
};
|
||||
}
|
||||
},
|
||||
closable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
className: {
|
||||
type: String
|
||||
},
|
||||
key: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
onClose: {
|
||||
type: Function
|
||||
},
|
||||
transitionName: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
withDesc: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
baseClass () {
|
||||
return `${this.prefixCls}-notice`;
|
||||
},
|
||||
classes () {
|
||||
return [
|
||||
this.baseClass,
|
||||
{
|
||||
[`${this.className}`]: !!this.className,
|
||||
[`${this.baseClass}-closable`]: this.closable,
|
||||
[`${this.baseClass}-with-desc`]: this.withDesc
|
||||
}
|
||||
];
|
||||
},
|
||||
contentClasses () {
|
||||
return `${this.baseClass}-content`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clearCloseTimer () {
|
||||
if (this.closeTimer) {
|
||||
clearTimeout(this.closeTimer);
|
||||
this.closeTimer = null;
|
||||
}
|
||||
},
|
||||
close () {
|
||||
this.clearCloseTimer();
|
||||
this.onClose();
|
||||
this.$parent.close(this.key);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.clearCloseTimer();
|
||||
|
||||
if (this.duration !== 0) {
|
||||
this.closeTimer = setTimeout(() => {
|
||||
this.close();
|
||||
}, this.duration * 1000);
|
||||
}
|
||||
|
||||
// check if with desc in Notice component
|
||||
if (this.prefixCls === 'ivu-notice') {
|
||||
this.withDesc = this.$els.content.querySelectorAll(`.${this.prefixCls}-desc`)[0].innerHTML !== '';
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.clearCloseTimer();
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,92 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" :style="style">
|
||||
<Notice v-for="notice in notices"
|
||||
:prefix-cls="prefixCls"
|
||||
:style="notice.style"
|
||||
:content="notice.content"
|
||||
:duration="notice.duration"
|
||||
:closable="notice.closable"
|
||||
:key="notice.key"
|
||||
:transition-name="notice.transitionName"
|
||||
:on-close="notice.onClose">
|
||||
</Notice>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Notice from './notice.vue';
|
||||
|
||||
const prefixCls = 'ivu-notification';
|
||||
let seed = 0;
|
||||
const now = Date.now();
|
||||
|
||||
function getUuid () {
|
||||
return 'ivuNotification_' + now + '_' + (seed++);
|
||||
}
|
||||
|
||||
export default {
|
||||
components: { Notice },
|
||||
props: {
|
||||
prefixCls: {
|
||||
type: String,
|
||||
default: prefixCls
|
||||
},
|
||||
style: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {
|
||||
top: '65px',
|
||||
left: '50%'
|
||||
};
|
||||
}
|
||||
},
|
||||
content: {
|
||||
type: String
|
||||
},
|
||||
className: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
notices: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${this.prefixCls}`,
|
||||
{
|
||||
[`${this.className}`]: !!this.className
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
add (notice) {
|
||||
const key = notice.key || getUuid();
|
||||
|
||||
let _notice = Object.assign({
|
||||
style: {
|
||||
right: '50%'
|
||||
},
|
||||
content: '',
|
||||
duration: 1.5,
|
||||
closable: false,
|
||||
key: key
|
||||
}, notice);
|
||||
|
||||
this.notices.push(_notice);
|
||||
},
|
||||
close (key) {
|
||||
const notices = this.notices;
|
||||
|
||||
for (let i = 0; i < notices.length; i++) {
|
||||
if (notices[i].key === key) {
|
||||
this.notices.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,106 +0,0 @@
|
|||
/**
|
||||
* https://github.com/freeze-component/vue-popper
|
||||
* */
|
||||
import Popper from 'popper.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
placement: {
|
||||
type: String,
|
||||
default: 'bottom'
|
||||
},
|
||||
boundariesPadding: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
reference: Object,
|
||||
popper: Object,
|
||||
offset: {
|
||||
default: 0
|
||||
},
|
||||
value: Boolean,
|
||||
transition: String,
|
||||
options: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
gpuAcceleration: false,
|
||||
boundariesElement: 'body'
|
||||
};
|
||||
}
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.visible = val;
|
||||
this.$emit('input', val);
|
||||
}
|
||||
},
|
||||
visible(val) {
|
||||
if (val) {
|
||||
this.updatePopper();
|
||||
} else {
|
||||
this.destroyPopper();
|
||||
this.$emit('on-popper-hide');
|
||||
}
|
||||
this.$emit('input', val);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
createPopper() {
|
||||
if (!/^(top|bottom|left|right)(-start|-end)?$/g.test(this.placement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const options = this.options;
|
||||
const popper = this.popper || this.$els.popper;
|
||||
const reference = this.reference || this.$els.reference;
|
||||
|
||||
if (!popper || !reference) return;
|
||||
|
||||
if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) {
|
||||
this.popperJS.destroy();
|
||||
}
|
||||
|
||||
options.placement = this.placement;
|
||||
options.offset = this.offset;
|
||||
|
||||
this.popperJS = new Popper(reference, popper, options);
|
||||
this.popperJS.onCreate(popper => {
|
||||
this.resetTransformOrigin(popper);
|
||||
this.$nextTick(this.updatePopper);
|
||||
this.$emit('created', this);
|
||||
});
|
||||
},
|
||||
updatePopper() {
|
||||
this.popperJS ? this.popperJS.update() : this.createPopper();
|
||||
},
|
||||
doDestroy() {
|
||||
if (this.visible) return;
|
||||
this.popperJS.destroy();
|
||||
this.popperJS = null;
|
||||
},
|
||||
destroyPopper() {
|
||||
if (this.popperJS) {
|
||||
this.resetTransformOrigin(this.popperJS);
|
||||
}
|
||||
},
|
||||
resetTransformOrigin(popper) {
|
||||
let placementMap = {top: 'bottom', bottom: 'top', left: 'right', right: 'left'};
|
||||
let placement = popper._popper.getAttribute('x-placement').split('-')[0];
|
||||
let origin = placementMap[placement];
|
||||
popper._popper.style.transformOrigin = ['top', 'bottom'].indexOf(placement) > -1 ? `center ${ origin }` : `${ origin } center`;
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.popperJS) {
|
||||
this.popperJS.destroy();
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,36 +0,0 @@
|
|||
<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>
|
|
@ -1,37 +0,0 @@
|
|||
<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>
|
|
@ -1,5 +0,0 @@
|
|||
import Breadcrumb from './breadcrumb.vue';
|
||||
import BreadcrumbItem from './breadcrumb-item.vue';
|
||||
|
||||
Breadcrumb.Item = BreadcrumbItem;
|
||||
export default Breadcrumb;
|
|
@ -1,41 +0,0 @@
|
|||
<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']);
|
||||
}
|
||||
},
|
||||
shape: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['circle', 'circle-outline']);
|
||||
}
|
||||
},
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-${this.shape}`]: !!this.shape,
|
||||
[`${prefixCls}-vertical`]: this.vertical
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,70 +0,0 @@
|
|||
<template>
|
||||
<button :type="htmlType" :class="classes" :disabled="disabled">
|
||||
<Icon class="ivu-load-loop" type="load-c" v-if="loading"></Icon>
|
||||
<Icon :type="icon" v-if="icon && !loading"></Icon>
|
||||
<span v-if="showSlot" v-el:slot><slot></slot></span>
|
||||
</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', 'dashed', 'text', 'info', 'success', 'warning', 'error']);
|
||||
}
|
||||
},
|
||||
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,
|
||||
long: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showSlot: true
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.type}`]: !!this.type,
|
||||
[`${prefixCls}-long`]: this.long,
|
||||
[`${prefixCls}-${this.shape}`]: !!this.shape,
|
||||
[`${prefixCls}-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-loading`]: this.loading != null && this.loading,
|
||||
[`${prefixCls}-icon-only`]: !this.showSlot && (!!this.icon || this.loading)
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.showSlot = this.$els.slot.innerHTML.replace(/\n/g, '').replace(/<!--[\w\W\r\n]*?-->/gmi, '') !== '';
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,5 +0,0 @@
|
|||
import Button from './button.vue';
|
||||
import ButtonGroup from './button-group.vue';
|
||||
|
||||
Button.Group = ButtonGroup;
|
||||
export default Button;
|
|
@ -1,58 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<div :class="headClasses" v-if="showHead" v-el:head><slot name="title"></slot></div>
|
||||
<div :class="extraClasses" v-if="showExtra" v-el:extra><slot name="extra"></slot></div>
|
||||
<div :class="bodyClasses"><slot></slot></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-card';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
bordered: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disHover: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
shadow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showHead: true,
|
||||
showExtra: true
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-bordered`]: this.bordered && !this.shadow,
|
||||
[`${prefixCls}-dis-hover`]: this.disHover || this.shadow,
|
||||
[`${prefixCls}-shadow`]: this.shadow
|
||||
}
|
||||
];
|
||||
},
|
||||
headClasses () {
|
||||
return `${prefixCls}-head`;
|
||||
},
|
||||
extraClasses () {
|
||||
return `${prefixCls}-extra`;
|
||||
},
|
||||
bodyClasses () {
|
||||
return `${prefixCls}-body`;
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.showHead = this.$els.head.innerHTML != '';
|
||||
this.showExtra = this.$els.extra.innerHTML != '';
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,2 +0,0 @@
|
|||
import Card from './card.vue';
|
||||
export default Card;
|
|
@ -1,34 +0,0 @@
|
|||
<template>
|
||||
<div :class="prefixCls" v-bind:style="styles"><slot></slot></div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-carousel-item';
|
||||
|
||||
export default {
|
||||
componentName: 'carousel-item',
|
||||
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
width: 0,
|
||||
height: 'auto',
|
||||
left: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
styles () {
|
||||
return {
|
||||
width: `${this.width}px`,
|
||||
height: `${this.height}`,
|
||||
left: `${this.left}px`
|
||||
};
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.$parent.slotChange();
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$parent.slotChange();
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,245 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<button :class="arrowClasses" class="left" @click="arrowEvent(-1)">
|
||||
<Icon type="chevron-left"></Icon>
|
||||
</button>
|
||||
<div :class="[prefixCls + '-list']">
|
||||
<div :class="[prefixCls + '-track']" :style="trackStyles" v-el:slides>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<button :class="arrowClasses" class="right" @click="arrowEvent(1)">
|
||||
<Icon type="chevron-right"></Icon>
|
||||
</button>
|
||||
<ul :class="dotsClasses">
|
||||
<template v-for="n in slides.length">
|
||||
<li :class="[n === currentIndex ? prefixCls + '-active' : '']"
|
||||
@click="dotsEvent('click', n)"
|
||||
@mouseover="dotsEvent('hover', n)">
|
||||
<button></button>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon/icon.vue';
|
||||
import { getStyle, oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-carousel';
|
||||
|
||||
export default {
|
||||
name: 'Carousel',
|
||||
components: { Icon },
|
||||
props: {
|
||||
arrow: {
|
||||
type: String,
|
||||
default: 'hover',
|
||||
validator (value) {
|
||||
return oneOf(value, ['hover', 'always', 'never']);
|
||||
}
|
||||
},
|
||||
autoplay: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
autoplaySpeed: {
|
||||
type: Number,
|
||||
default: 2000
|
||||
},
|
||||
easing: {
|
||||
type: String,
|
||||
default: 'ease'
|
||||
},
|
||||
dots: {
|
||||
type: String,
|
||||
default: 'inside',
|
||||
validator (value) {
|
||||
return oneOf(value, ['inside', 'outside', 'none']);
|
||||
}
|
||||
},
|
||||
trigger: {
|
||||
type: String,
|
||||
default: 'click',
|
||||
validator (value) {
|
||||
return oneOf(value, ['click', 'hover']);
|
||||
}
|
||||
},
|
||||
currentIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: 'auto',
|
||||
validator (value) {
|
||||
return value === 'auto' || Object.prototype.toString.call(value) === '[object Number]';
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
listWidth: 0,
|
||||
trackWidth: 0,
|
||||
trackOffset: 0,
|
||||
slides: [],
|
||||
slideInstances: [],
|
||||
timer: null,
|
||||
ready: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`
|
||||
];
|
||||
},
|
||||
trackStyles () {
|
||||
return {
|
||||
width: `${this.trackWidth}px`,
|
||||
transform: `translate3d(-${this.trackOffset}px, 0px, 0px)`,
|
||||
transition: `transform 500ms ${this.easing}`
|
||||
};
|
||||
},
|
||||
arrowClasses () {
|
||||
return [
|
||||
`${prefixCls}-arrow`,
|
||||
`${prefixCls}-arrow-${this.arrow}`
|
||||
];
|
||||
},
|
||||
dotsClasses () {
|
||||
return [
|
||||
`${prefixCls}-dots`,
|
||||
`${prefixCls}-dots-${this.dots}`
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// find option component
|
||||
findChild (cb) {
|
||||
const find = function (child) {
|
||||
const name = child.$options.componentName;
|
||||
|
||||
if (name) {
|
||||
cb(child);
|
||||
} else if (child.$children.length) {
|
||||
child.$children.forEach((innerChild) => {
|
||||
find(innerChild, cb);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (this.slideInstances.length || !this.$children) {
|
||||
this.slideInstances.forEach((child) => {
|
||||
find(child);
|
||||
});
|
||||
} else {
|
||||
this.$children.forEach((child) => {
|
||||
find(child);
|
||||
});
|
||||
}
|
||||
},
|
||||
updateSlides (init ) {
|
||||
let slides = [];
|
||||
let index = 1;
|
||||
|
||||
this.findChild((child) => {
|
||||
slides.push({
|
||||
$el: child.$el
|
||||
});
|
||||
child.index = index++;
|
||||
|
||||
if (init) {
|
||||
this.slideInstances.push(child);
|
||||
}
|
||||
});
|
||||
|
||||
this.slides = slides;
|
||||
|
||||
this.updatePos();
|
||||
},
|
||||
updatePos () {
|
||||
this.findChild((child) => {
|
||||
child.width = this.listWidth;
|
||||
child.height = typeof this.height === 'number' ? `${this.height}px` : this.height;
|
||||
});
|
||||
|
||||
this.trackWidth = (this.slides.length || 0) * this.listWidth;
|
||||
},
|
||||
// use when slot changed
|
||||
slotChange () {
|
||||
this.$nextTick(() => {
|
||||
this.slides = [];
|
||||
this.slideInstances = [];
|
||||
|
||||
this.updateSlides(true, true);
|
||||
this.updatePos();
|
||||
this.updateOffset();
|
||||
});
|
||||
},
|
||||
handleResize () {
|
||||
this.listWidth = parseInt(getStyle(this.$el, 'width'));
|
||||
this.updatePos();
|
||||
this.updateOffset();
|
||||
},
|
||||
add (offset) {
|
||||
let index = this.currentIndex;
|
||||
index += offset;
|
||||
while (index < 0) index += this.slides.length;
|
||||
index = index % this.slides.length;
|
||||
this.currentIndex = index;
|
||||
},
|
||||
arrowEvent (offset) {
|
||||
this.setAutoplay();
|
||||
this.add(offset);
|
||||
},
|
||||
dotsEvent (event, n) {
|
||||
if (event === this.trigger && this.currentIndex !== n) {
|
||||
this.currentIndex = n;
|
||||
// Reset autoplay timer when trigger be activated
|
||||
this.setAutoplay();
|
||||
}
|
||||
},
|
||||
setAutoplay () {
|
||||
window.clearInterval(this.timer);
|
||||
if (this.autoplay) {
|
||||
this.timer = window.setInterval(() => {
|
||||
this.add(1);
|
||||
}, this.autoplaySpeed);
|
||||
}
|
||||
},
|
||||
updateOffset () {
|
||||
this.$nextTick(() => {
|
||||
this.trackOffset = this.currentIndex * this.listWidth;
|
||||
});
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.updateSlides(true);
|
||||
},
|
||||
watch: {
|
||||
autoplay () {
|
||||
this.setAutoplay();
|
||||
},
|
||||
autoplaySpeed () {
|
||||
this.setAutoplay();
|
||||
},
|
||||
currentIndex (val, oldVal) {
|
||||
this.$emit('on-change', oldVal, val);
|
||||
this.updateOffset();
|
||||
},
|
||||
height () {
|
||||
this.updatePos();
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
this.handleResize();
|
||||
this.setAutoplay();
|
||||
window.addEventListener('resize', this.handleResize, false);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('resize', this.handleResize, false);
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,5 +0,0 @@
|
|||
import Carousel from './carousel.vue';
|
||||
import CarouselItem from './carousel-item.vue';
|
||||
|
||||
Carousel.Item = CarouselItem;
|
||||
export default Carousel;
|
|
@ -1,210 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" v-clickoutside="handleClose">
|
||||
<div :class="[prefixCls + '-rel']" @click="toggleOpen">
|
||||
<slot>
|
||||
<i-input
|
||||
readonly
|
||||
:disabled="disabled"
|
||||
:value.sync="displayRender"
|
||||
:size="size"
|
||||
:placeholder="placeholder"></i-input>
|
||||
<Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.stop="clearSelect"></Icon>
|
||||
<Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon>
|
||||
</slot>
|
||||
</div>
|
||||
<Dropdown v-show="visible" transition="slide-up">
|
||||
<div>
|
||||
<Caspanel
|
||||
v-ref:caspanel
|
||||
:prefix-cls="prefixCls"
|
||||
:data.sync="data"
|
||||
:disabled="disabled"
|
||||
:change-on-select="changeOnSelect"
|
||||
:trigger="trigger"></Caspanel>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import iInput from '../input/input.vue';
|
||||
import Dropdown from '../select/dropdown.vue';
|
||||
import Icon from '../icon/icon.vue';
|
||||
import Caspanel from './caspanel.vue';
|
||||
import clickoutside from '../../directives/clickoutside';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-cascader';
|
||||
|
||||
export default {
|
||||
components: { iInput, Dropdown, Icon, Caspanel },
|
||||
directives: { clickoutside },
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
},
|
||||
trigger: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['click', 'hover']);
|
||||
},
|
||||
default: 'click'
|
||||
},
|
||||
changeOnSelect: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
renderFormat: {
|
||||
type: Function,
|
||||
default (label) {
|
||||
return label.join(' / ');
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
visible: false,
|
||||
selected: [],
|
||||
tmpSelected: [],
|
||||
updatingValue: false // to fix set value in changeOnSelect type
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-show-clear`]: this.showCloseIcon,
|
||||
[`${prefixCls}-visible`]: this.visible,
|
||||
[`${prefixCls}-disabled`]: this.disabled
|
||||
}
|
||||
];
|
||||
},
|
||||
showCloseIcon () {
|
||||
return this.value && this.value.length && this.clearable;
|
||||
},
|
||||
displayRender () {
|
||||
let label = [];
|
||||
for (let i = 0; i < this.selected.length; i++) {
|
||||
label.push(this.selected[i].label);
|
||||
}
|
||||
|
||||
return this.renderFormat(label, this.selected);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clearSelect () {
|
||||
const oldVal = JSON.stringify(this.value);
|
||||
this.value = this.selected = this.tmpSelected = [];
|
||||
this.handleClose();
|
||||
this.emitValue(this.value, oldVal);
|
||||
this.$broadcast('on-clear');
|
||||
},
|
||||
handleClose () {
|
||||
this.visible = false;
|
||||
},
|
||||
toggleOpen () {
|
||||
if (this.disabled) return false;
|
||||
if (this.visible) {
|
||||
this.handleClose();
|
||||
} else {
|
||||
this.onFocus();
|
||||
}
|
||||
},
|
||||
onFocus () {
|
||||
this.visible = true;
|
||||
if (!this.value.length) {
|
||||
this.$broadcast('on-clear');
|
||||
}
|
||||
},
|
||||
updateResult (result) {
|
||||
this.tmpSelected = result;
|
||||
},
|
||||
updateSelected (init = false) {
|
||||
if (!this.changeOnSelect || init) {
|
||||
this.$broadcast('on-find-selected', this.value);
|
||||
}
|
||||
},
|
||||
emitValue (val, oldVal) {
|
||||
if (JSON.stringify(val) !== oldVal) {
|
||||
this.$emit('on-change', this.value, JSON.parse(JSON.stringify(this.selected)));
|
||||
this.$dispatch('on-form-change', this.value, JSON.parse(JSON.stringify(this.selected)));
|
||||
}
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
this.updateSelected(true);
|
||||
},
|
||||
events: {
|
||||
// lastValue: is click the final val
|
||||
// fromInit: is this emit from update value
|
||||
'on-result-change' (lastValue, changeOnSelect, fromInit) {
|
||||
if (lastValue || changeOnSelect) {
|
||||
const oldVal = JSON.stringify(this.value);
|
||||
this.selected = this.tmpSelected;
|
||||
|
||||
let newVal = [];
|
||||
this.selected.forEach((item) => {
|
||||
newVal.push(item.value);
|
||||
});
|
||||
|
||||
if (!fromInit) {
|
||||
this.updatingValue = true;
|
||||
this.value = newVal;
|
||||
this.emitValue(this.value, oldVal);
|
||||
}
|
||||
}
|
||||
if (lastValue && !fromInit) {
|
||||
this.handleClose();
|
||||
}
|
||||
},
|
||||
'on-form-blur' () {
|
||||
return false;
|
||||
},
|
||||
'on-form-change' () {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible (val) {
|
||||
if (val) {
|
||||
if (this.value.length) {
|
||||
this.updateSelected();
|
||||
}
|
||||
}
|
||||
},
|
||||
value () {
|
||||
if (this.updatingValue) {
|
||||
this.updatingValue = false;
|
||||
return;
|
||||
}
|
||||
this.updateSelected(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,23 +0,0 @@
|
|||
<template>
|
||||
<li :class="classes">{{ data.label }}<i v-if="data.children && data.children.length" class="ivu-icon ivu-icon-ios-arrow-right"></i></li>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
data: Object,
|
||||
prefixCls: String,
|
||||
tmpItem: Object
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${this.prefixCls}-menu-item`,
|
||||
{
|
||||
[`${this.prefixCls}-menu-item-active`]: this.tmpItem.value === this.data.value,
|
||||
[`${this.prefixCls}-menu-item-disabled`]: this.data.disabled
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,114 +0,0 @@
|
|||
<template>
|
||||
<ul v-if="data && data.length" :class="[prefixCls + '-menu']">
|
||||
<Casitem
|
||||
v-for="item in data"
|
||||
:prefix-cls="prefixCls"
|
||||
:data.sync="item"
|
||||
:tmp-item="tmpItem"
|
||||
@click.stop="handleClickItem(item)"
|
||||
@mouseenter.stop="handleHoverItem(item)"></Casitem>
|
||||
</ul><Caspanel v-if="sublist && sublist.length" :prefix-cls="prefixCls" :data.sync="sublist" :disabled="disabled" :trigger="trigger" :change-on-select="changeOnSelect"></Caspanel>
|
||||
</template>
|
||||
<script>
|
||||
import Casitem from './casitem.vue';
|
||||
|
||||
export default {
|
||||
name: 'Caspanel',
|
||||
components: { Casitem },
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
sublist: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
disabled: Boolean,
|
||||
changeOnSelect: Boolean,
|
||||
trigger: String,
|
||||
prefixCls: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tmpItem: {},
|
||||
result: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClickItem (item) {
|
||||
if (this.trigger !== 'click' && item.children) return;
|
||||
this.handleTriggerItem(item);
|
||||
},
|
||||
handleHoverItem (item) {
|
||||
if (this.trigger !== 'hover' || !item.children) return;
|
||||
this.handleTriggerItem(item);
|
||||
},
|
||||
handleTriggerItem (item, fromInit = false) {
|
||||
if (item.disabled) return;
|
||||
|
||||
// return value back recursion
|
||||
const backItem = this.getBaseItem(item);
|
||||
this.tmpItem = backItem;
|
||||
this.emitUpdate([backItem]);
|
||||
|
||||
if (item.children && item.children.length){
|
||||
this.sublist = item.children;
|
||||
this.$dispatch('on-result-change', false, this.changeOnSelect, fromInit);
|
||||
} else {
|
||||
this.sublist = [];
|
||||
this.$dispatch('on-result-change', true, this.changeOnSelect, fromInit);
|
||||
}
|
||||
},
|
||||
updateResult (item) {
|
||||
this.result = [this.tmpItem].concat(item);
|
||||
this.emitUpdate(this.result);
|
||||
},
|
||||
getBaseItem (item) {
|
||||
let backItem = Object.assign({}, item);
|
||||
if (backItem.children) {
|
||||
delete backItem.children;
|
||||
}
|
||||
|
||||
return backItem;
|
||||
},
|
||||
emitUpdate (result) {
|
||||
if (this.$parent.$options.name === 'Caspanel') {
|
||||
this.$parent.updateResult(result);
|
||||
} else {
|
||||
this.$parent.$parent.updateResult(result);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
data () {
|
||||
this.sublist = [];
|
||||
}
|
||||
},
|
||||
events: {
|
||||
'on-find-selected' (val) {
|
||||
let value = [...val];
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
for (let j = 0; j < this.data.length; j++) {
|
||||
if (value[i] === this.data[j].value) {
|
||||
this.handleTriggerItem(this.data[j], true);
|
||||
value.splice(0, 1);
|
||||
this.$nextTick(() => {
|
||||
this.$broadcast('on-find-selected', value);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'on-clear' () {
|
||||
this.sublist = [];
|
||||
this.tmpItem = {};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,2 +0,0 @@
|
|||
import Cascader from './cascader.vue';
|
||||
export default Cascader;
|
|
@ -1,52 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-checkbox-group';
|
||||
|
||||
export default {
|
||||
name: 'checkboxGroup',
|
||||
props: {
|
||||
model: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
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.model = data;
|
||||
this.$emit('on-change', data);
|
||||
this.$dispatch('on-form-change', data);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
model () {
|
||||
this.updateModel(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,115 +0,0 @@
|
|||
<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 v-if="showSlot"><span v-el:slot>{{ value }}</span></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
|
||||
},
|
||||
indeterminate: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
model: [],
|
||||
selected: false,
|
||||
group: false,
|
||||
showSlot: true
|
||||
};
|
||||
},
|
||||
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,
|
||||
[`${prefixCls}-indeterminate`]: this.indeterminate
|
||||
}
|
||||
];
|
||||
},
|
||||
innerClasses () {
|
||||
return `${prefixCls}-inner`;
|
||||
},
|
||||
inputClasses () {
|
||||
return `${prefixCls}-input`;
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
if (this.$parent && this.$parent.$options.name === 'checkboxGroup') this.group = true;
|
||||
if (!this.group) {
|
||||
this.updateModel();
|
||||
if (this.$els.slot && this.$els.slot.innerHTML === '') {
|
||||
this.showSlot = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
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);
|
||||
this.$dispatch('on-form-change', this.checked);
|
||||
}
|
||||
},
|
||||
updateModel () {
|
||||
this.selected = this.checked;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
checked () {
|
||||
this.updateModel();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,5 +0,0 @@
|
|||
import Checkbox from './checkbox.vue';
|
||||
import CheckboxGroup from './checkbox-group.vue';
|
||||
|
||||
Checkbox.Group = CheckboxGroup;
|
||||
export default Checkbox;
|
|
@ -1,83 +0,0 @@
|
|||
<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>
|
|
@ -1,2 +0,0 @@
|
|||
import Circle from './circle.vue';
|
||||
export default Circle;
|
|
@ -1,98 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-collapse';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
accordion: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
activeKey: {
|
||||
type: [Array, String]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return `${prefixCls}`;
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.setActive();
|
||||
},
|
||||
methods: {
|
||||
setActive () {
|
||||
const activeKey = this.getActiveKey();
|
||||
|
||||
this.$children.forEach((child, index) => {
|
||||
const key = child.key || index.toString();
|
||||
let isActive = false;
|
||||
|
||||
if (self.accordion) {
|
||||
isActive = activeKey === key;
|
||||
} else {
|
||||
isActive = activeKey.indexOf(key) > -1;
|
||||
}
|
||||
|
||||
child.isActive = isActive;
|
||||
child.index = index;
|
||||
});
|
||||
},
|
||||
getActiveKey () {
|
||||
let activeKey = this.activeKey || [];
|
||||
const accordion = this.accordion;
|
||||
|
||||
if (!Array.isArray(activeKey)) {
|
||||
activeKey = [activeKey];
|
||||
}
|
||||
|
||||
if (accordion && activeKey.length > 1) {
|
||||
activeKey = [activeKey[0]];
|
||||
}
|
||||
|
||||
for (let i = 0; i < activeKey.length; i++) {
|
||||
activeKey[i] = activeKey[i].toString();
|
||||
}
|
||||
|
||||
return activeKey;
|
||||
},
|
||||
toggle (data) {
|
||||
const key = data.key.toString();
|
||||
let newActiveKey = [];
|
||||
|
||||
if (this.accordion) {
|
||||
if (!data.isActive) {
|
||||
newActiveKey.push(key);
|
||||
}
|
||||
} else {
|
||||
let activeKey = this.getActiveKey();
|
||||
const keyIndex = activeKey.indexOf(key);
|
||||
|
||||
if (data.isActive) {
|
||||
if (keyIndex > -1) {
|
||||
activeKey.splice(keyIndex, 1);
|
||||
}
|
||||
} else {
|
||||
if (keyIndex < 0) {
|
||||
activeKey.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
newActiveKey = activeKey;
|
||||
}
|
||||
|
||||
this.activeKey = newActiveKey;
|
||||
this.$emit('on-change', newActiveKey);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeKey () {
|
||||
this.setActive();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,5 +0,0 @@
|
|||
import Collapse from './collapse.vue';
|
||||
import Panel from './panel.vue';
|
||||
|
||||
Collapse.Panel = Panel;
|
||||
export default Collapse;
|
|
@ -1,57 +0,0 @@
|
|||
<template>
|
||||
<div :class="itemClasses">
|
||||
<div :class="headerClasses" @click="toggle">
|
||||
<Icon type="arrow-right-b"></Icon>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div :class="concentClasses" v-show="isActive">
|
||||
<div :class="boxClasses"><slot name="content"></slot></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon/icon.vue';
|
||||
const prefixCls = 'ivu-collapse';
|
||||
|
||||
export default {
|
||||
components: { Icon },
|
||||
props: {
|
||||
key: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
index: 0, // use index for default when key is null
|
||||
isActive: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
itemClasses () {
|
||||
return [
|
||||
`${prefixCls}-item`,
|
||||
{
|
||||
[`${prefixCls}-item-active`]: this.isActive
|
||||
}
|
||||
];
|
||||
},
|
||||
headerClasses () {
|
||||
return `${prefixCls}-header`;
|
||||
},
|
||||
concentClasses () {
|
||||
return `${prefixCls}-content`;
|
||||
},
|
||||
boxClasses () {
|
||||
return `${prefixCls}-content-box`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle () {
|
||||
this.$parent.toggle({
|
||||
key: this.key || this.index,
|
||||
isActive: this.isActive
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,50 +0,0 @@
|
|||
<template>
|
||||
<div :class="[prefixCls + '-confirm']">
|
||||
<span :class="timeClasses" v-if="showTime" @click="handleToggleTime">
|
||||
<template v-if="isTime">{{ t('i.datepicker.selectDate') }}</template>
|
||||
<template v-else>{{ t('i.datepicker.selectTime') }}</template>
|
||||
</span>
|
||||
<i-button size="small" type="text" @click="handleClear">{{ t('i.datepicker.clear') }}</i-button>
|
||||
<i-button size="small" type="primary" @click="handleSuccess">{{ t('i.datepicker.ok') }}</i-button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import iButton from '../../button/button.vue';
|
||||
import Locale from '../../../mixins/locale';
|
||||
|
||||
const prefixCls = 'ivu-picker';
|
||||
|
||||
export default {
|
||||
mixins: [ Locale ],
|
||||
components: { iButton },
|
||||
props: {
|
||||
showTime: false,
|
||||
isTime: false,
|
||||
timeDisabled: false
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
timeClasses () {
|
||||
return {
|
||||
[`${prefixCls}-confirm-time-disabled`]: this.timeDisabled
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClear () {
|
||||
this.$emit('on-pick-clear');
|
||||
},
|
||||
handleSuccess () {
|
||||
this.$emit('on-pick-success');
|
||||
},
|
||||
handleToggleTime () {
|
||||
if (this.timeDisabled) return;
|
||||
this.$emit('on-pick-toggle-time');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,284 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
:class="classes"
|
||||
@click="handleClick"
|
||||
@mousemove="handleMouseMove">
|
||||
<div :class="[prefixCls + '-header']">
|
||||
<span>{{ t('i.datepicker.weeks.sun') }}</span><span>{{ t('i.datepicker.weeks.mon') }}</span><span>{{ t('i.datepicker.weeks.tue') }}</span><span>{{ t('i.datepicker.weeks.wed') }}</span><span>{{ t('i.datepicker.weeks.thu') }}</span><span>{{ t('i.datepicker.weeks.fri') }}</span><span>{{ t('i.datepicker.weeks.sat') }}</span>
|
||||
</div>
|
||||
<span :class="getCellCls(cell)" v-for="cell in readCells"><em :index="$index">{{ cell.text }}</em></span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getFirstDayOfMonth, getDayCountOfMonth } from '../util';
|
||||
import { deepCopy } from '../../../utils/assist';
|
||||
import Locale from '../../../mixins/locale';
|
||||
|
||||
const prefixCls = 'ivu-date-picker-cells';
|
||||
|
||||
const clearHours = function (time) {
|
||||
const cloneDate = new Date(time);
|
||||
cloneDate.setHours(0, 0, 0, 0);
|
||||
return cloneDate.getTime();
|
||||
};
|
||||
|
||||
export default {
|
||||
mixins: [ Locale ],
|
||||
props: {
|
||||
date: {},
|
||||
year: {},
|
||||
month: {},
|
||||
selectionMode: {
|
||||
default: 'day'
|
||||
},
|
||||
disabledDate: {},
|
||||
minDate: {},
|
||||
maxDate: {},
|
||||
rangeState: {
|
||||
default () {
|
||||
return {
|
||||
endDate: null,
|
||||
selecting: false
|
||||
};
|
||||
}
|
||||
},
|
||||
value: ''
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
readCells: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
'rangeState.endDate' (newVal) {
|
||||
this.markRange(newVal);
|
||||
},
|
||||
minDate(newVal, oldVal) {
|
||||
if (newVal && !oldVal) {
|
||||
this.rangeState.selecting = true;
|
||||
this.markRange(newVal);
|
||||
} else if (!newVal) {
|
||||
this.rangeState.selecting = false;
|
||||
this.markRange(newVal);
|
||||
} else {
|
||||
this.markRange();
|
||||
}
|
||||
},
|
||||
maxDate(newVal, oldVal) {
|
||||
if (newVal && !oldVal) {
|
||||
this.rangeState.selecting = false;
|
||||
this.markRange(newVal);
|
||||
// this.$emit('on-pick', {
|
||||
// minDate: this.minDate,
|
||||
// maxDate: this.maxDate
|
||||
// });
|
||||
}
|
||||
},
|
||||
cells: {
|
||||
handler (cells) {
|
||||
this.readCells = cells;
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`
|
||||
];
|
||||
},
|
||||
cells () {
|
||||
const date = new Date(this.year, this.month, 1);
|
||||
let day = getFirstDayOfMonth(date); // day of first day
|
||||
day = (day === 0 ? 7 : day);
|
||||
const today = clearHours(new Date()); // timestamp of today
|
||||
const selectDay = clearHours(new Date(this.value)); // timestamp of selected day
|
||||
const minDay = clearHours(new Date(this.minDate));
|
||||
const maxDay = clearHours(new Date(this.maxDate));
|
||||
|
||||
const dateCountOfMonth = getDayCountOfMonth(date.getFullYear(), date.getMonth());
|
||||
const dateCountOfLastMonth = getDayCountOfMonth(date.getFullYear(), (date.getMonth() === 0 ? 11 : date.getMonth() - 1));
|
||||
|
||||
const disabledDate = this.disabledDate;
|
||||
|
||||
let cells = [];
|
||||
const cell_tmpl = {
|
||||
text: '',
|
||||
type: '',
|
||||
selected: false,
|
||||
disabled: false,
|
||||
range: false,
|
||||
start: false,
|
||||
end: false
|
||||
};
|
||||
if (day !== 7) {
|
||||
for (let i = 0; i < day; i++) {
|
||||
const cell = deepCopy(cell_tmpl);
|
||||
cell.type = 'prev-month';
|
||||
cell.text = dateCountOfLastMonth - (day - 1) + i;
|
||||
|
||||
let prevMonth = this.month - 1;
|
||||
let prevYear = this.year;
|
||||
if (this.month === 0) {
|
||||
prevMonth = 11;
|
||||
prevYear -= 1;
|
||||
}
|
||||
const time = clearHours(new Date(prevYear, prevMonth, cell.text));
|
||||
cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
|
||||
cells.push(cell);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 1; i <= dateCountOfMonth; i++) {
|
||||
const cell = deepCopy(cell_tmpl);
|
||||
const time = clearHours(new Date(this.year, this.month, i));
|
||||
cell.type = time === today ? 'today' : 'normal';
|
||||
cell.text = i;
|
||||
cell.selected = time === selectDay;
|
||||
cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
|
||||
cell.range = time >= minDay && time <= maxDay;
|
||||
cell.start = this.minDate && time === minDay;
|
||||
cell.end = this.maxDate && time === maxDay;
|
||||
|
||||
cells.push(cell);
|
||||
}
|
||||
|
||||
const nextMonthCount = 42 - cells.length;
|
||||
for (let i = 1; i <= nextMonthCount; i++) {
|
||||
const cell = deepCopy(cell_tmpl);
|
||||
cell.type = 'next-month';
|
||||
cell.text = i;
|
||||
|
||||
let nextMonth = this.month + 1;
|
||||
let nextYear = this.year;
|
||||
if (this.month === 11) {
|
||||
nextMonth = 0;
|
||||
nextYear += 1;
|
||||
}
|
||||
const time = clearHours(new Date(nextYear, nextMonth, cell.text));
|
||||
cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
|
||||
cells.push(cell);
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDateOfCell (cell) {
|
||||
let year = this.year;
|
||||
let month = this.month;
|
||||
let day = cell.text;
|
||||
|
||||
const date = this.date;
|
||||
const hours = date.getHours();
|
||||
const minutes = date.getMinutes();
|
||||
const seconds = date.getSeconds();
|
||||
|
||||
if (cell.type === 'prev-month') {
|
||||
if (month === 0) {
|
||||
month = 11;
|
||||
year--;
|
||||
} else {
|
||||
month--;
|
||||
}
|
||||
} else if (cell.type === 'next-month') {
|
||||
if (month === 11) {
|
||||
month = 0;
|
||||
year++;
|
||||
} else {
|
||||
month++;
|
||||
}
|
||||
}
|
||||
|
||||
return new Date(year, month, day, hours, minutes, seconds);
|
||||
},
|
||||
handleClick (event) {
|
||||
const target = event.target;
|
||||
if (target.tagName === 'EM') {
|
||||
const cell = this.cells[parseInt(event.target.getAttribute('index'))];
|
||||
if (cell.disabled) return;
|
||||
|
||||
const newDate = this.getDateOfCell(cell);
|
||||
|
||||
if (this.selectionMode === 'range') {
|
||||
if (this.minDate && this.maxDate) {
|
||||
const minDate = new Date(newDate.getTime());
|
||||
const maxDate = null;
|
||||
this.rangeState.selecting = true;
|
||||
this.markRange(this.minDate);
|
||||
|
||||
this.$emit('on-pick', {minDate, maxDate}, false);
|
||||
} else if (this.minDate && !this.maxDate) {
|
||||
if (newDate >= this.minDate) {
|
||||
const maxDate = new Date(newDate.getTime());
|
||||
this.rangeState.selecting = false;
|
||||
|
||||
this.$emit('on-pick', {minDate: this.minDate, maxDate});
|
||||
} else {
|
||||
const minDate = new Date(newDate.getTime());
|
||||
|
||||
this.$emit('on-pick', {minDate, maxDate: this.maxDate}, false);
|
||||
}
|
||||
} else if (!this.minDate) {
|
||||
const minDate = new Date(newDate.getTime());
|
||||
this.rangeState.selecting = true;
|
||||
this.markRange(this.minDate);
|
||||
|
||||
this.$emit('on-pick', {minDate, maxDate: this.maxDate}, false);
|
||||
}
|
||||
} else {
|
||||
this.$emit('on-pick', newDate);
|
||||
}
|
||||
}
|
||||
this.$emit('on-pick-click');
|
||||
},
|
||||
handleMouseMove (event) {
|
||||
if (!this.rangeState.selecting) return;
|
||||
|
||||
this.$emit('on-changerange', {
|
||||
minDate: this.minDate,
|
||||
maxDate: this.maxDate,
|
||||
rangeState: this.rangeState
|
||||
});
|
||||
|
||||
const target = event.target;
|
||||
if (target.tagName === 'EM') {
|
||||
const cell = this.cells[parseInt(event.target.getAttribute('index'))];
|
||||
// if (cell.disabled) return; // todo 待确定
|
||||
this.rangeState.endDate = this.getDateOfCell(cell);
|
||||
}
|
||||
},
|
||||
markRange (maxDate) {
|
||||
const minDate = this.minDate;
|
||||
if (!maxDate) maxDate = this.maxDate;
|
||||
|
||||
const minDay = clearHours(new Date(minDate));
|
||||
const maxDay = clearHours(new Date(maxDate));
|
||||
|
||||
this.cells.forEach(cell => {
|
||||
if (cell.type === 'today' || cell.type === 'normal') {
|
||||
const time = clearHours(new Date(this.year, this.month, cell.text));
|
||||
cell.range = time >= minDay && time <= maxDay;
|
||||
cell.start = minDate && time === minDay;
|
||||
cell.end = maxDate && time === maxDay;
|
||||
}
|
||||
});
|
||||
},
|
||||
getCellCls (cell) {
|
||||
return [
|
||||
`${prefixCls}-cell`,
|
||||
{
|
||||
[`${prefixCls}-cell-selected`]: cell.selected || cell.start || cell.end,
|
||||
[`${prefixCls}-cell-disabled`]: cell.disabled,
|
||||
[`${prefixCls}-cell-today`]: cell.type === 'today',
|
||||
[`${prefixCls}-cell-prev-month`]: cell.type === 'prev-month',
|
||||
[`${prefixCls}-cell-next-month`]: cell.type === 'next-month',
|
||||
[`${prefixCls}-cell-range`]: cell.range && !cell.start && !cell.end
|
||||
}
|
||||
];
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,79 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" @click="handleClick">
|
||||
<span :class="getCellCls(cell)" v-for="cell in cells"><em :index="$index">{{ tCell(cell.text) }}</em></span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { deepCopy } from '../../../utils/assist';
|
||||
import Locale from '../../../mixins/locale';
|
||||
const prefixCls = 'ivu-date-picker-cells';
|
||||
|
||||
export default {
|
||||
mixins: [ Locale ],
|
||||
props: {
|
||||
date: {},
|
||||
month: {
|
||||
type: Number
|
||||
},
|
||||
disabledDate: {},
|
||||
selectionMode: {
|
||||
default: 'month'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-month`
|
||||
];
|
||||
},
|
||||
cells () {
|
||||
let cells = [];
|
||||
const cell_tmpl = {
|
||||
text: '',
|
||||
selected: false,
|
||||
disabled: false
|
||||
};
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
const cell = deepCopy(cell_tmpl);
|
||||
cell.text = i + 1;
|
||||
|
||||
const date = new Date(this.date);
|
||||
date.setMonth(i);
|
||||
cell.disabled = typeof this.disabledDate === 'function' && this.disabledDate(date) && this.selectionMode === 'month';
|
||||
|
||||
cell.selected = Number(this.month) === i;
|
||||
cells.push(cell);
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCellCls (cell) {
|
||||
return [
|
||||
`${prefixCls}-cell`,
|
||||
{
|
||||
[`${prefixCls}-cell-selected`]: cell.selected,
|
||||
[`${prefixCls}-cell-disabled`]: cell.disabled
|
||||
}
|
||||
];
|
||||
},
|
||||
handleClick (event) {
|
||||
const target = event.target;
|
||||
if (target.tagName === 'EM') {
|
||||
const index = parseInt(event.target.getAttribute('index'));
|
||||
const cell = this.cells[index];
|
||||
if (cell.disabled) return;
|
||||
|
||||
this.$emit('on-pick', index);
|
||||
}
|
||||
this.$emit('on-pick-click');
|
||||
},
|
||||
tCell (cell) {
|
||||
return this.t(`i.datepicker.months.m${cell}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,207 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<div :class="[prefixCls+ '-list']" v-el:hours>
|
||||
<ul :class="[prefixCls + '-ul']" @click="handleClickHours">
|
||||
<li :class="getCellCls(item)" v-for="item in hoursList" v-show="!item.hide" :index="$index">{{ formatTime(item.text) }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div :class="[prefixCls+ '-list']" v-el:minutes>
|
||||
<ul :class="[prefixCls + '-ul']" @click="handleClickMinutes">
|
||||
<li :class="getCellCls(item)" v-for="item in minutesList" v-show="!item.hide" :index="$index">{{ formatTime(item.text) }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div :class="[prefixCls+ '-list']" v-show="showSeconds" v-el:seconds>
|
||||
<ul :class="[prefixCls + '-ul']" @click="handleClickSeconds">
|
||||
<li :class="getCellCls(item)" v-for="item in secondsList" v-show="!item.hide" :index="$index">{{ formatTime(item.text) }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Options from '../time-mixins';
|
||||
import { deepCopy, scrollTop, firstUpperCase } from '../../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-time-picker-cells';
|
||||
|
||||
export default {
|
||||
mixins: [Options],
|
||||
props: {
|
||||
hours: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
minutes: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
seconds: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
showSeconds: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
compiled: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-with-seconds`]: this.showSeconds
|
||||
}
|
||||
];
|
||||
},
|
||||
hoursList () {
|
||||
let hours = [];
|
||||
const hour_tmpl = {
|
||||
text: 0,
|
||||
selected: false,
|
||||
disabled: false,
|
||||
hide: false
|
||||
};
|
||||
|
||||
for (let i = 0; i < 24; i++) {
|
||||
const hour = deepCopy(hour_tmpl);
|
||||
hour.text = i;
|
||||
|
||||
if (this.disabledHours.length && this.disabledHours.indexOf(i) > -1) {
|
||||
hour.disabled = true;
|
||||
if (this.hideDisabledOptions) hour.hide = true;
|
||||
}
|
||||
if (this.hours === i) hour.selected = true;
|
||||
hours.push(hour);
|
||||
}
|
||||
|
||||
return hours;
|
||||
},
|
||||
minutesList () {
|
||||
let minutes = [];
|
||||
const minute_tmpl = {
|
||||
text: 0,
|
||||
selected: false,
|
||||
disabled: false,
|
||||
hide: false
|
||||
};
|
||||
|
||||
for (let i = 0; i < 60; i++) {
|
||||
const minute = deepCopy(minute_tmpl);
|
||||
minute.text = i;
|
||||
|
||||
if (this.disabledMinutes.length && this.disabledMinutes.indexOf(i) > -1) {
|
||||
minute.disabled = true;
|
||||
if (this.hideDisabledOptions) minute.hide = true;
|
||||
}
|
||||
if (this.minutes === i) minute.selected = true;
|
||||
minutes.push(minute);
|
||||
}
|
||||
|
||||
return minutes;
|
||||
},
|
||||
secondsList () {
|
||||
let seconds = [];
|
||||
const second_tmpl = {
|
||||
text: 0,
|
||||
selected: false,
|
||||
disabled: false,
|
||||
hide: false
|
||||
};
|
||||
|
||||
for (let i = 0; i < 60; i++) {
|
||||
const second = deepCopy(second_tmpl);
|
||||
second.text = i;
|
||||
|
||||
if (this.disabledSeconds.length && this.disabledSeconds.indexOf(i) > -1) {
|
||||
second.disabled = true;
|
||||
if (this.hideDisabledOptions) second.hide = true;
|
||||
}
|
||||
if (this.seconds === i) second.selected = true;
|
||||
seconds.push(second);
|
||||
}
|
||||
|
||||
return seconds;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCellCls (cell) {
|
||||
return [
|
||||
`${prefixCls}-cell`,
|
||||
{
|
||||
[`${prefixCls}-cell-selected`]: cell.selected,
|
||||
[`${prefixCls}-cell-disabled`]: cell.disabled
|
||||
}
|
||||
];
|
||||
},
|
||||
handleClickHours (event) {
|
||||
this.handleClick('hours', event);
|
||||
},
|
||||
handleClickMinutes (event) {
|
||||
this.handleClick('minutes', event);
|
||||
},
|
||||
handleClickSeconds (event) {
|
||||
this.handleClick('seconds', event);
|
||||
},
|
||||
handleClick (type, event) {
|
||||
const target = event.target;
|
||||
if (target.tagName === 'LI') {
|
||||
const cell = this[`${type}List`][parseInt(event.target.getAttribute('index'))];
|
||||
if (cell.disabled) return;
|
||||
const data = {};
|
||||
data[type] = cell.text;
|
||||
this.$emit('on-change', data);
|
||||
}
|
||||
this.$emit('on-pick-click');
|
||||
},
|
||||
scroll (type, index) {
|
||||
const from = this.$els[type].scrollTop;
|
||||
const to = 24 * this.getScrollIndex(type, index);
|
||||
scrollTop(this.$els[type], from, to, 500);
|
||||
},
|
||||
getScrollIndex (type, index) {
|
||||
const Type = firstUpperCase(type);
|
||||
const disabled = this[`disabled${Type}`];
|
||||
if (disabled.length && this.hideDisabledOptions) {
|
||||
let _count = 0;
|
||||
disabled.forEach(item => item <= index ? _count++ : '');
|
||||
index -= _count;
|
||||
}
|
||||
return index;
|
||||
},
|
||||
updateScroll () {
|
||||
const times = ['hours', 'minutes', 'seconds'];
|
||||
this.$nextTick(() => {
|
||||
times.forEach(type => {
|
||||
this.$els[type].scrollTop = 24 * this.getScrollIndex(type, this[type]);
|
||||
});
|
||||
});
|
||||
},
|
||||
formatTime (text) {
|
||||
return text < 10 ? '0' + text : text;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
hours (val) {
|
||||
if (!this.compiled) return;
|
||||
this.scroll('hours', val);
|
||||
},
|
||||
minutes (val) {
|
||||
if (!this.compiled) return;
|
||||
this.scroll('minutes', val);
|
||||
},
|
||||
seconds (val) {
|
||||
if (!this.compiled) return;
|
||||
this.scroll('seconds', val);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.updateScroll();
|
||||
this.$nextTick(() => this.compiled = true);
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,80 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" @click="handleClick">
|
||||
<span :class="getCellCls(cell)" v-for="cell in cells"><em :index="$index">{{ cell.text }}</em></span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { deepCopy } from '../../../utils/assist';
|
||||
const prefixCls = 'ivu-date-picker-cells';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
date: {},
|
||||
year: {},
|
||||
disabledDate: {},
|
||||
selectionMode: {
|
||||
default: 'year'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-year`
|
||||
];
|
||||
},
|
||||
startYear() {
|
||||
return Math.floor(this.year / 10) * 10;
|
||||
},
|
||||
cells () {
|
||||
let cells = [];
|
||||
const cell_tmpl = {
|
||||
text: '',
|
||||
selected: false,
|
||||
disabled: false
|
||||
};
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const cell = deepCopy(cell_tmpl);
|
||||
cell.text = this.startYear + i;
|
||||
|
||||
const date = new Date(this.date);
|
||||
date.setFullYear(cell.text);
|
||||
cell.disabled = typeof this.disabledDate === 'function' && this.disabledDate(date) && this.selectionMode === 'year';
|
||||
|
||||
cell.selected = Number(this.year) === cell.text;
|
||||
cells.push(cell);
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCellCls (cell) {
|
||||
return [
|
||||
`${prefixCls}-cell`,
|
||||
{
|
||||
[`${prefixCls}-cell-selected`]: cell.selected,
|
||||
[`${prefixCls}-cell-disabled`]: cell.disabled
|
||||
}
|
||||
];
|
||||
},
|
||||
nextTenYear() {
|
||||
this.$emit('on-pick', Number(this.year) + 10, false);
|
||||
},
|
||||
prevTenYear() {
|
||||
this.$emit('on-pick', Number(this.year) - 10, false);
|
||||
},
|
||||
handleClick (event) {
|
||||
const target = event.target;
|
||||
if (target.tagName === 'EM') {
|
||||
const cell = this.cells[parseInt(event.target.getAttribute('index'))];
|
||||
if (cell.disabled) return;
|
||||
|
||||
this.$emit('on-pick', cell.text);
|
||||
}
|
||||
this.$emit('on-pick-click');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,3 +0,0 @@
|
|||
import DatePicker from './picker/date-picker';
|
||||
|
||||
export default DatePicker;
|
|
@ -1,421 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<div :class="[prefixCls + '-sidebar']" v-if="shortcuts.length">
|
||||
<div
|
||||
:class="[prefixCls + '-shortcut']"
|
||||
v-for="shortcut in shortcuts"
|
||||
@click="handleShortcutClick(shortcut)">{{ shortcut.text }}</div>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-body']">
|
||||
<div :class="[prefixCls + '-content', prefixCls + '-content-left']" v-show="!isTime">
|
||||
<div :class="[datePrefixCls + '-header']" v-show="leftCurrentView !== 'time'">
|
||||
<span
|
||||
:class="iconBtnCls('prev', '-double')"
|
||||
@click="prevYear('left')"><Icon type="ios-arrow-left"></Icon></span>
|
||||
<span
|
||||
:class="iconBtnCls('prev')"
|
||||
@click="prevMonth"
|
||||
v-show="leftCurrentView === 'date'"><Icon type="ios-arrow-left"></Icon></span>
|
||||
<span
|
||||
:class="[datePrefixCls + '-header-label']"
|
||||
@click="showYearPicker('left')">{{ leftYearLabel }}</span>
|
||||
<span
|
||||
:class="[datePrefixCls + '-header-label']"
|
||||
@click="showMonthPicker('left')"
|
||||
v-show="leftCurrentView === 'date'">{{ leftMonthLabel }}</span>
|
||||
<span
|
||||
:class="iconBtnCls('next', '-double')"
|
||||
@click="nextYear('left')"
|
||||
v-show="leftCurrentView === 'year' || leftCurrentView === 'month'"><Icon type="ios-arrow-right"></Icon></span>
|
||||
</div>
|
||||
<date-table
|
||||
v-show="leftCurrentView === 'date'"
|
||||
:year="leftYear"
|
||||
:month="leftMonth"
|
||||
:date="date"
|
||||
:min-date="minDate"
|
||||
:max-date="maxDate"
|
||||
:range-state="rangeState"
|
||||
selection-mode="range"
|
||||
:disabled-date="disabledDate"
|
||||
@on-changerange="handleChangeRange"
|
||||
@on-pick="handleRangePick"
|
||||
@on-pick-click="handlePickClick"></date-table>
|
||||
<year-table
|
||||
v-ref:left-year-table
|
||||
v-show="leftCurrentView === 'year'"
|
||||
:year="leftTableYear"
|
||||
:date="leftTableDate"
|
||||
selection-mode="range"
|
||||
:disabled-date="disabledDate"
|
||||
@on-pick="handleLeftYearPick"
|
||||
@on-pick-click="handlePickClick"></year-table>
|
||||
<month-table
|
||||
v-ref:left-month-table
|
||||
v-show="leftCurrentView === 'month'"
|
||||
:month="leftMonth"
|
||||
:date="leftTableDate"
|
||||
selection-mode="range"
|
||||
:disabled-date="disabledDate"
|
||||
@on-pick="handleLeftMonthPick"
|
||||
@on-pick-click="handlePickClick"></month-table>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-content', prefixCls + '-content-right']" v-show="!isTime">
|
||||
<div :class="[datePrefixCls + '-header']" v-show="rightCurrentView !== 'time'">
|
||||
<span
|
||||
:class="iconBtnCls('prev', '-double')"
|
||||
@click="prevYear('right')"
|
||||
v-show="rightCurrentView === 'year' || rightCurrentView === 'month'"><Icon type="ios-arrow-left"></Icon></span>
|
||||
<span
|
||||
:class="[datePrefixCls + '-header-label']"
|
||||
@click="showYearPicker('right')">{{ rightYearLabel }}</span>
|
||||
<span
|
||||
:class="[datePrefixCls + '-header-label']"
|
||||
@click="showMonthPicker('right')"
|
||||
v-show="rightCurrentView === 'date'">{{ rightMonthLabel }}</span>
|
||||
<span
|
||||
:class="iconBtnCls('next', '-double')"
|
||||
@click="nextYear('right')"><Icon type="ios-arrow-right"></Icon></span>
|
||||
<span
|
||||
:class="iconBtnCls('next')"
|
||||
@click="nextMonth"
|
||||
v-show="rightCurrentView === 'date'"><Icon type="ios-arrow-right"></Icon></span>
|
||||
</div>
|
||||
<date-table
|
||||
v-show="rightCurrentView === 'date'"
|
||||
:year="rightYear"
|
||||
:month="rightMonth"
|
||||
:date="rightDate"
|
||||
:min-date="minDate"
|
||||
:max-date="maxDate"
|
||||
:range-state="rangeState"
|
||||
selection-mode="range"
|
||||
:disabled-date="disabledDate"
|
||||
@on-changerange="handleChangeRange"
|
||||
@on-pick="handleRangePick"
|
||||
@on-pick-click="handlePickClick"></date-table>
|
||||
<year-table
|
||||
v-ref:right-year-table
|
||||
v-show="rightCurrentView === 'year'"
|
||||
:year="rightTableYear"
|
||||
:date="rightTableDate"
|
||||
selection-mode="range"
|
||||
:disabled-date="disabledDate"
|
||||
@on-pick="handleRightYearPick"
|
||||
@on-pick-click="handlePickClick"></year-table>
|
||||
<month-table
|
||||
v-ref:right-month-table
|
||||
v-show="rightCurrentView === 'month'"
|
||||
:month="rightMonth"
|
||||
:date="rightTableDate"
|
||||
selection-mode="range"
|
||||
:disabled-date="disabledDate"
|
||||
@on-pick="handleRightMonthPick"
|
||||
@on-pick-click="handlePickClick"></month-table>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-content']" v-show="isTime">
|
||||
<time-picker
|
||||
v-ref:time-picker
|
||||
v-show="isTime"
|
||||
@on-pick="handleTimePick"
|
||||
@on-pick-click="handlePickClick"></time-picker>
|
||||
</div>
|
||||
<Confirm
|
||||
v-if="confirm"
|
||||
:show-time="showTime"
|
||||
:is-time="isTime"
|
||||
:time-disabled="timeDisabled"
|
||||
@on-pick-toggle-time="handleToggleTime"
|
||||
@on-pick-clear="handlePickClear"
|
||||
@on-pick-success="handlePickSuccess"></Confirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../../icon/icon.vue';
|
||||
import DateTable from '../base/date-table.vue';
|
||||
import YearTable from '../base/year-table.vue';
|
||||
import MonthTable from '../base/month-table.vue';
|
||||
import TimePicker from './time-range.vue';
|
||||
import Confirm from '../base/confirm.vue';
|
||||
import { toDate, prevMonth, nextMonth, initTimeDate } from '../util';
|
||||
|
||||
import Mixin from './mixin';
|
||||
import Locale from '../../../mixins/locale';
|
||||
|
||||
const prefixCls = 'ivu-picker-panel';
|
||||
const datePrefixCls = 'ivu-date-picker';
|
||||
|
||||
export default {
|
||||
name: 'DatePicker',
|
||||
mixins: [ Mixin, Locale ],
|
||||
components: { Icon, DateTable, YearTable, MonthTable, TimePicker, Confirm },
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
datePrefixCls: datePrefixCls,
|
||||
shortcuts: [],
|
||||
date: initTimeDate(),
|
||||
value: '',
|
||||
minDate: '',
|
||||
maxDate: '',
|
||||
confirm: false,
|
||||
rangeState: {
|
||||
endDate: null,
|
||||
selecting: false
|
||||
},
|
||||
showTime: false,
|
||||
disabledDate: '',
|
||||
leftCurrentView: 'date',
|
||||
rightCurrentView: 'date',
|
||||
selectionMode: 'range',
|
||||
leftTableYear: null,
|
||||
rightTableYear: null,
|
||||
isTime: false,
|
||||
format: 'yyyy-MM-dd'
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}-body-wrapper`,
|
||||
`${datePrefixCls}-with-range`,
|
||||
{
|
||||
[`${prefixCls}-with-sidebar`]: this.shortcuts.length
|
||||
}
|
||||
];
|
||||
},
|
||||
leftYear () {
|
||||
return this.date.getFullYear();
|
||||
},
|
||||
leftTableDate () {
|
||||
if (this.leftCurrentView === 'year' || this.leftCurrentView === 'month') {
|
||||
return new Date(this.leftTableYear);
|
||||
} else {
|
||||
return this.date;
|
||||
}
|
||||
},
|
||||
leftYearLabel () {
|
||||
const tYear = this.t('i.datepicker.year');
|
||||
if (this.leftCurrentView === 'year') {
|
||||
const year = this.leftTableYear;
|
||||
if (!year) return '';
|
||||
const startYear = Math.floor(year / 10) * 10;
|
||||
return `${startYear}${tYear} - ${startYear + 9}${tYear}`;
|
||||
} else {
|
||||
const year = this.leftCurrentView === 'month' ? this.leftTableYear : this.leftYear;
|
||||
if (!year) return '';
|
||||
return `${year}${tYear}`;
|
||||
}
|
||||
},
|
||||
leftMonth () {
|
||||
return this.date.getMonth();
|
||||
},
|
||||
leftMonthLabel () {
|
||||
const month = this.leftMonth + 1;
|
||||
return this.t(`i.datepicker.month${month}`);
|
||||
},
|
||||
rightYear () {
|
||||
return this.rightDate.getFullYear();
|
||||
},
|
||||
rightTableDate () {
|
||||
if (this.rightCurrentView === 'year' || this.rightCurrentView === 'month') {
|
||||
return new Date(this.rightTableYear);
|
||||
} else {
|
||||
return this.date;
|
||||
}
|
||||
},
|
||||
rightYearLabel () {
|
||||
const tYear = this.t('i.datepicker.year');
|
||||
if (this.rightCurrentView === 'year') {
|
||||
const year = this.rightTableYear;
|
||||
if (!year) return '';
|
||||
const startYear = Math.floor(year / 10) * 10;
|
||||
return `${startYear}${tYear} - ${startYear + 9}${tYear}`;
|
||||
} else {
|
||||
const year = this.rightCurrentView === 'month' ? this.rightTableYear : this.rightYear;
|
||||
if (!year) return '';
|
||||
return `${year}${tYear}`;
|
||||
}
|
||||
},
|
||||
rightMonth () {
|
||||
return this.rightDate.getMonth();
|
||||
},
|
||||
rightMonthLabel () {
|
||||
const month = this.rightMonth + 1;
|
||||
return this.t(`i.datepicker.month${month}`);
|
||||
},
|
||||
rightDate () {
|
||||
const newDate = new Date(this.date);
|
||||
const month = newDate.getMonth();
|
||||
newDate.setDate(1);
|
||||
|
||||
if (month === 11) {
|
||||
newDate.setFullYear(newDate.getFullYear() + 1);
|
||||
newDate.setMonth(0);
|
||||
} else {
|
||||
newDate.setMonth(month + 1);
|
||||
}
|
||||
return newDate;
|
||||
},
|
||||
timeDisabled () {
|
||||
return !(this.minDate && this.maxDate);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(newVal) {
|
||||
if (!newVal) {
|
||||
this.minDate = null;
|
||||
this.maxDate = null;
|
||||
} else if (Array.isArray(newVal)) {
|
||||
this.minDate = newVal[0] ? toDate(newVal[0]) : null;
|
||||
this.maxDate = newVal[1] ? toDate(newVal[1]) : null;
|
||||
if (this.minDate) this.date = new Date(this.minDate);
|
||||
}
|
||||
if (this.showTime) this.$refs.timePicker.value = newVal;
|
||||
},
|
||||
minDate (val) {
|
||||
if (this.showTime) this.$refs.timePicker.date = val;
|
||||
},
|
||||
maxDate (val) {
|
||||
if (this.showTime) this.$refs.timePicker.dateEnd = val;
|
||||
},
|
||||
format (val) {
|
||||
if (this.showTime) this.$refs.timePicker.format = val;
|
||||
},
|
||||
isTime (val) {
|
||||
if (val) this.$refs.timePicker.updateScroll();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetDate () {
|
||||
this.date = new Date(this.date);
|
||||
this.leftTableYear = this.date.getFullYear();
|
||||
this.rightTableYear = this.rightDate.getFullYear();
|
||||
},
|
||||
handleClear() {
|
||||
this.minDate = null;
|
||||
this.maxDate = null;
|
||||
this.date = new Date();
|
||||
this.handleConfirm();
|
||||
if (this.showTime) this.$refs.timePicker.handleClear();
|
||||
},
|
||||
resetView(reset = false) {
|
||||
this.leftCurrentView = 'date';
|
||||
this.rightCurrentView = 'date';
|
||||
|
||||
this.leftTableYear = this.leftYear;
|
||||
this.rightTableYear = this.rightYear;
|
||||
|
||||
if (reset) this.isTime = false;
|
||||
},
|
||||
prevYear (direction) {
|
||||
if (this[`${direction}CurrentView`] === 'year') {
|
||||
this.$refs[`${direction}YearTable`].prevTenYear();
|
||||
} else if (this[`${direction}CurrentView`] === 'month') {
|
||||
this[`${direction}TableYear`]--;
|
||||
} else {
|
||||
const date = this.date;
|
||||
date.setFullYear(date.getFullYear() - 1);
|
||||
this.resetDate();
|
||||
}
|
||||
},
|
||||
nextYear (direction) {
|
||||
if (this[`${direction}CurrentView`] === 'year') {
|
||||
this.$refs[`${direction}YearTable`].nextTenYear();
|
||||
} else if (this[`${direction}CurrentView`] === 'month') {
|
||||
this[`${direction}TableYear`]--;
|
||||
} else {
|
||||
const date = this.date;
|
||||
date.setFullYear(date.getFullYear() + 1);
|
||||
this.resetDate();
|
||||
}
|
||||
},
|
||||
prevMonth () {
|
||||
this.date = prevMonth(this.date);
|
||||
},
|
||||
nextMonth () {
|
||||
this.date = nextMonth(this.date);
|
||||
},
|
||||
handleLeftYearPick (year, close = true) {
|
||||
this.handleYearPick(year, close, 'left');
|
||||
},
|
||||
handleRightYearPick (year, close = true) {
|
||||
this.handleYearPick(year, close, 'right');
|
||||
},
|
||||
handleYearPick (year, close, direction) {
|
||||
this[`${direction}TableYear`] = year;
|
||||
if (!close) return;
|
||||
|
||||
this[`${direction}CurrentView`] = 'month';
|
||||
},
|
||||
handleLeftMonthPick (month) {
|
||||
this.handleMonthPick(month, 'left');
|
||||
},
|
||||
handleRightMonthPick (month) {
|
||||
this.handleMonthPick(month, 'right');
|
||||
},
|
||||
handleMonthPick (month, direction) {
|
||||
let year = this[`${direction}TableYear`];
|
||||
if (direction === 'right') {
|
||||
if (month === 0) {
|
||||
month = 11;
|
||||
year--;
|
||||
} else {
|
||||
month--;
|
||||
}
|
||||
}
|
||||
|
||||
this.date.setYear(year);
|
||||
this.date.setMonth(month);
|
||||
this[`${direction}CurrentView`] = 'date';
|
||||
this.resetDate();
|
||||
},
|
||||
showYearPicker (direction) {
|
||||
this[`${direction}CurrentView`] = 'year';
|
||||
this[`${direction}TableYear`] = this[`${direction}Year`];
|
||||
},
|
||||
showMonthPicker (direction) {
|
||||
this[`${direction}CurrentView`] = 'month';
|
||||
},
|
||||
handleConfirm(visible) {
|
||||
this.$emit('on-pick', [this.minDate, this.maxDate], visible);
|
||||
},
|
||||
handleRangePick (val, close = true) {
|
||||
if (this.maxDate === val.maxDate && this.minDate === val.minDate) return;
|
||||
|
||||
this.minDate = val.minDate;
|
||||
this.maxDate = val.maxDate;
|
||||
|
||||
if (!close) return;
|
||||
// if (!this.showTime) {
|
||||
// this.handleConfirm(false);
|
||||
// }
|
||||
this.handleConfirm(false);
|
||||
},
|
||||
handleChangeRange (val) {
|
||||
this.minDate = val.minDate;
|
||||
this.maxDate = val.maxDate;
|
||||
this.rangeState = val.rangeState;
|
||||
},
|
||||
handleToggleTime () {
|
||||
this.isTime = !this.isTime;
|
||||
},
|
||||
handleTimePick (date) {
|
||||
this.minDate = date[0];
|
||||
this.maxDate = date[1];
|
||||
this.handleConfirm(false);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
if (this.showTime) {
|
||||
// todo 这里也到不了
|
||||
this.$refs.timePicker.date = this.minDate;
|
||||
this.$refs.timePicker.dateEnd = this.maxDate;
|
||||
this.$refs.timePicker.value = this.value;
|
||||
this.$refs.timePicker.format = this.format;
|
||||
this.$refs.timePicker.showDate = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,293 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<div :class="[prefixCls + '-sidebar']" v-if="shortcuts.length">
|
||||
<div
|
||||
:class="[prefixCls + '-shortcut']"
|
||||
v-for="shortcut in shortcuts"
|
||||
@click="handleShortcutClick(shortcut)">{{ shortcut.text }}</div>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-body']">
|
||||
<div :class="[datePrefixCls + '-header']" v-show="currentView !== 'time'">
|
||||
<span
|
||||
:class="iconBtnCls('prev', '-double')"
|
||||
@click="prevYear"><Icon type="ios-arrow-left"></Icon></span>
|
||||
<span
|
||||
:class="iconBtnCls('prev')"
|
||||
@click="prevMonth"
|
||||
v-show="currentView === 'date'"><Icon type="ios-arrow-left"></Icon></span>
|
||||
<span
|
||||
:class="[datePrefixCls + '-header-label']"
|
||||
@click="showYearPicker">{{ yearLabel }}</span>
|
||||
<span
|
||||
:class="[datePrefixCls + '-header-label']"
|
||||
@click="showMonthPicker"
|
||||
v-show="currentView === 'date'">{{ monthLabel }}</span>
|
||||
<span
|
||||
:class="iconBtnCls('next', '-double')"
|
||||
@click="nextYear"><Icon type="ios-arrow-right"></Icon></span>
|
||||
<span
|
||||
:class="iconBtnCls('next')"
|
||||
@click="nextMonth"
|
||||
v-show="currentView === 'date'"><Icon type="ios-arrow-right"></Icon></span>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-content']">
|
||||
<date-table
|
||||
v-show="currentView === 'date'"
|
||||
:year="year"
|
||||
:month="month"
|
||||
:date="date"
|
||||
:value="value"
|
||||
:selection-mode="selectionMode"
|
||||
:disabled-date="disabledDate"
|
||||
@on-pick="handleDatePick"
|
||||
@on-pick-click="handlePickClick"></date-table>
|
||||
<year-table
|
||||
v-ref:year-table
|
||||
v-show="currentView === 'year'"
|
||||
:year="year"
|
||||
:date="date"
|
||||
:selection-mode="selectionMode"
|
||||
:disabled-date="disabledDate"
|
||||
@on-pick="handleYearPick"
|
||||
@on-pick-click="handlePickClick"></year-table>
|
||||
<month-table
|
||||
v-ref:month-table
|
||||
v-show="currentView === 'month'"
|
||||
:month="month"
|
||||
:date="date"
|
||||
:selection-mode="selectionMode"
|
||||
:disabled-date="disabledDate"
|
||||
@on-pick="handleMonthPick"
|
||||
@on-pick-click="handlePickClick"></month-table>
|
||||
<time-picker
|
||||
v-ref:time-picker
|
||||
show-date
|
||||
v-show="currentView === 'time'"
|
||||
@on-pick="handleTimePick"
|
||||
@on-pick-click="handlePickClick"></time-picker>
|
||||
</div>
|
||||
<Confirm
|
||||
v-if="confirm"
|
||||
:show-time="showTime"
|
||||
:is-time="isTime"
|
||||
@on-pick-toggle-time="handleToggleTime"
|
||||
@on-pick-clear="handlePickClear"
|
||||
@on-pick-success="handlePickSuccess"></Confirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../../icon/icon.vue';
|
||||
import DateTable from '../base/date-table.vue';
|
||||
import YearTable from '../base/year-table.vue';
|
||||
import MonthTable from '../base/month-table.vue';
|
||||
import TimePicker from './time.vue';
|
||||
import Confirm from '../base/confirm.vue';
|
||||
|
||||
import Mixin from './mixin';
|
||||
import Locale from '../../../mixins/locale';
|
||||
|
||||
import { initTimeDate } from '../util';
|
||||
|
||||
const prefixCls = 'ivu-picker-panel';
|
||||
const datePrefixCls = 'ivu-date-picker';
|
||||
|
||||
export default {
|
||||
name: 'DatePicker',
|
||||
mixins: [ Mixin, Locale ],
|
||||
components: { Icon, DateTable, YearTable, MonthTable, TimePicker, Confirm },
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
datePrefixCls: datePrefixCls,
|
||||
shortcuts: [],
|
||||
currentView: 'date',
|
||||
date: initTimeDate(),
|
||||
value: '',
|
||||
showTime: false,
|
||||
selectionMode: 'day',
|
||||
disabledDate: '',
|
||||
year: null,
|
||||
month: null,
|
||||
confirm: false,
|
||||
isTime: false,
|
||||
format: 'yyyy-MM-dd'
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}-body-wrapper`,
|
||||
{
|
||||
[`${prefixCls}-with-sidebar`]: this.shortcuts.length
|
||||
}
|
||||
];
|
||||
},
|
||||
yearLabel () {
|
||||
const tYear = this.t('i.datepicker.year');
|
||||
const year = this.year;
|
||||
if (!year) return '';
|
||||
if (this.currentView === 'year') {
|
||||
const startYear = Math.floor(year / 10) * 10;
|
||||
return `${startYear}${tYear} - ${startYear + 9}${tYear}`;
|
||||
}
|
||||
return `${year}${tYear}`;
|
||||
},
|
||||
monthLabel () {
|
||||
const month = this.month + 1;
|
||||
return this.t(`i.datepicker.month${month}`);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (newVal) {
|
||||
if (!newVal) return;
|
||||
newVal = new Date(newVal);
|
||||
if (!isNaN(newVal)) {
|
||||
this.date = newVal;
|
||||
this.year = newVal.getFullYear();
|
||||
this.month = newVal.getMonth();
|
||||
}
|
||||
if (this.showTime) this.$refs.timePicker.value = newVal;
|
||||
},
|
||||
date (val) {
|
||||
if (this.showTime) this.$refs.timePicker.date = val;
|
||||
},
|
||||
format (val) {
|
||||
if (this.showTime) this.$refs.timePicker.format = val;
|
||||
},
|
||||
currentView (val) {
|
||||
if (val === 'time') this.$refs.timePicker.updateScroll();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetDate () {
|
||||
this.date = new Date(this.date);
|
||||
},
|
||||
handleClear () {
|
||||
this.date = new Date();
|
||||
this.$emit('on-pick', '');
|
||||
if (this.showTime) this.$refs.timePicker.handleClear();
|
||||
},
|
||||
resetView (reset = false) {
|
||||
if (this.currentView !== 'time' || reset) {
|
||||
if (this.selectionMode === 'month') {
|
||||
this.currentView = 'month';
|
||||
} else if (this.selectionMode === 'year') {
|
||||
this.currentView = 'year';
|
||||
} else {
|
||||
this.currentView = 'date';
|
||||
}
|
||||
}
|
||||
|
||||
this.year = this.date.getFullYear();
|
||||
this.month = this.date.getMonth();
|
||||
if (reset) this.isTime = false;
|
||||
},
|
||||
prevYear () {
|
||||
if (this.currentView === 'year') {
|
||||
this.$refs.yearTable.prevTenYear();
|
||||
} else {
|
||||
this.year--;
|
||||
this.date.setFullYear(this.year);
|
||||
this.resetDate();
|
||||
}
|
||||
},
|
||||
nextYear () {
|
||||
if (this.currentView === 'year') {
|
||||
this.$refs.yearTable.nextTenYear();
|
||||
} else {
|
||||
this.year++;
|
||||
this.date.setFullYear(this.year);
|
||||
this.resetDate();
|
||||
}
|
||||
},
|
||||
prevMonth () {
|
||||
this.month--;
|
||||
if (this.month < 0) {
|
||||
this.month = 11;
|
||||
this.year--;
|
||||
}
|
||||
},
|
||||
nextMonth () {
|
||||
this.month++;
|
||||
if (this.month > 11) {
|
||||
this.month = 0;
|
||||
this.year++;
|
||||
}
|
||||
},
|
||||
showYearPicker () {
|
||||
this.currentView = 'year';
|
||||
},
|
||||
showMonthPicker () {
|
||||
this.currentView = 'month';
|
||||
},
|
||||
handleToggleTime () {
|
||||
if (this.currentView === 'date') {
|
||||
this.currentView = 'time';
|
||||
this.isTime = true;
|
||||
} else if (this.currentView === 'time') {
|
||||
this.currentView = 'date';
|
||||
this.isTime = false;
|
||||
}
|
||||
},
|
||||
handleYearPick(year, close = true) {
|
||||
this.year = year;
|
||||
if (!close) return;
|
||||
|
||||
this.date.setFullYear(year);
|
||||
if (this.selectionMode === 'year') {
|
||||
this.$emit('on-pick', new Date(year, 0, 1));
|
||||
} else {
|
||||
this.currentView = 'month';
|
||||
}
|
||||
|
||||
this.resetDate();
|
||||
},
|
||||
handleMonthPick (month) {
|
||||
this.month = month;
|
||||
const selectionMode = this.selectionMode;
|
||||
if (selectionMode !== 'month') {
|
||||
this.date.setMonth(month);
|
||||
this.currentView = 'date';
|
||||
this.resetDate();
|
||||
} else {
|
||||
this.date.setMonth(month);
|
||||
this.year && this.date.setFullYear(this.year);
|
||||
this.resetDate();
|
||||
const value = new Date(this.date.getFullYear(), month, 1);
|
||||
this.$emit('on-pick', value);
|
||||
}
|
||||
},
|
||||
handleDatePick (value) {
|
||||
if (this.selectionMode === 'day') {
|
||||
this.$emit('on-pick', new Date(value.getTime()));
|
||||
this.date.setFullYear(value.getFullYear());
|
||||
this.date.setMonth(value.getMonth());
|
||||
this.date.setDate(value.getDate());
|
||||
}
|
||||
|
||||
this.resetDate();
|
||||
},
|
||||
handleTimePick (date) {
|
||||
this.handleDatePick(date);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
if (this.selectionMode === 'month') {
|
||||
this.currentView = 'month';
|
||||
}
|
||||
|
||||
if (this.date && !this.year) {
|
||||
this.year = this.date.getFullYear();
|
||||
this.month = this.date.getMonth();
|
||||
}
|
||||
if (this.showTime) {
|
||||
// todo 这里可能有问题,并不能进入到这里,但不影响正常使用
|
||||
this.$refs.timePicker.date = this.date;
|
||||
this.$refs.timePicker.value = this.value;
|
||||
this.$refs.timePicker.format = this.format;
|
||||
this.$refs.timePicker.showDate = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,27 +0,0 @@
|
|||
const prefixCls = 'ivu-picker-panel';
|
||||
const datePrefixCls = 'ivu-date-picker';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
iconBtnCls (direction, type = '') {
|
||||
return [
|
||||
`${prefixCls}-icon-btn`,
|
||||
`${datePrefixCls}-${direction}-btn`,
|
||||
`${datePrefixCls}-${direction}-btn-arrow${type}`,
|
||||
];
|
||||
},
|
||||
handleShortcutClick (shortcut) {
|
||||
if (shortcut.value) this.$emit('on-pick', shortcut.value());
|
||||
if (shortcut.onClick) shortcut.onClick(this);
|
||||
},
|
||||
handlePickClear () {
|
||||
this.$emit('on-pick-clear');
|
||||
},
|
||||
handlePickSuccess () {
|
||||
this.$emit('on-pick-success');
|
||||
},
|
||||
handlePickClick () {
|
||||
this.$emit('on-pick-click');
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,207 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<div :class="[prefixCls + '-body']">
|
||||
<div :class="[prefixCls + '-content', prefixCls + '-content-left']">
|
||||
<div :class="[timePrefixCls + '-header']">
|
||||
<template v-if="showDate">{{ visibleDate }}</template>
|
||||
<template v-else>{{ t('i.datepicker.startTime') }}</template>
|
||||
</div>
|
||||
<time-spinner
|
||||
v-ref:time-spinner
|
||||
:show-seconds="showSeconds"
|
||||
:hours="hours"
|
||||
:minutes="minutes"
|
||||
:seconds="seconds"
|
||||
:disabled-hours="disabledHours"
|
||||
:disabled-minutes="disabledMinutes"
|
||||
:disabled-seconds="disabledSeconds"
|
||||
:hide-disabled-options="hideDisabledOptions"
|
||||
@on-change="handleStartChange"
|
||||
@on-pick-click="handlePickClick"></time-spinner>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-content', prefixCls + '-content-right']">
|
||||
<div :class="[timePrefixCls + '-header']">
|
||||
<template v-if="showDate">{{ visibleDateEnd }}</template>
|
||||
<template v-else>{{ t('i.datepicker.endTime') }}</template>
|
||||
</div>
|
||||
<time-spinner
|
||||
v-ref:time-spinner-end
|
||||
:show-seconds="showSeconds"
|
||||
:hours="hoursEnd"
|
||||
:minutes="minutesEnd"
|
||||
:seconds="secondsEnd"
|
||||
:disabled-hours="disabledHours"
|
||||
:disabled-minutes="disabledMinutes"
|
||||
:disabled-seconds="disabledSeconds"
|
||||
:hide-disabled-options="hideDisabledOptions"
|
||||
@on-change="handleEndChange"
|
||||
@on-pick-click="handlePickClick"></time-spinner>
|
||||
</div>
|
||||
<Confirm
|
||||
v-if="confirm"
|
||||
@on-pick-clear="handlePickClear"
|
||||
@on-pick-success="handlePickSuccess"></Confirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import TimeSpinner from '../base/time-spinner.vue';
|
||||
import Confirm from '../base/confirm.vue';
|
||||
|
||||
import Mixin from './mixin';
|
||||
import Locale from '../../../mixins/locale';
|
||||
|
||||
import { initTimeDate, toDate, formatDate } from '../util';
|
||||
|
||||
const prefixCls = 'ivu-picker-panel';
|
||||
const timePrefixCls = 'ivu-time-picker';
|
||||
|
||||
export default {
|
||||
mixins: [ Mixin, Locale ],
|
||||
components: { TimeSpinner, Confirm },
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
timePrefixCls: timePrefixCls,
|
||||
format: 'HH:mm:ss',
|
||||
showDate: false,
|
||||
date: initTimeDate(),
|
||||
dateEnd: initTimeDate(),
|
||||
value: '',
|
||||
hours: '',
|
||||
minutes: '',
|
||||
seconds: '',
|
||||
hoursEnd: '',
|
||||
minutesEnd: '',
|
||||
secondsEnd: '',
|
||||
disabledHours: [],
|
||||
disabledMinutes: [],
|
||||
disabledSeconds: [],
|
||||
hideDisabledOptions: false,
|
||||
confirm: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}-body-wrapper`,
|
||||
`${timePrefixCls}-with-range`,
|
||||
{
|
||||
[`${timePrefixCls}-with-seconds`]: this.showSeconds
|
||||
}
|
||||
];
|
||||
},
|
||||
showSeconds () {
|
||||
return (this.format || '').indexOf('ss') !== -1;
|
||||
},
|
||||
visibleDate () {
|
||||
const date = this.date || initTimeDate();
|
||||
const tYear = this.t('i.datepicker.year');
|
||||
const month = date.getMonth() + 1;
|
||||
const tMonth = this.t(`i.datepicker.month${month}`);
|
||||
return `${date.getFullYear()}${tYear} ${tMonth}`;
|
||||
},
|
||||
visibleDateEnd () {
|
||||
const date = this.dateEnd || initTimeDate();
|
||||
const tYear = this.t('i.datepicker.year');
|
||||
const month = date.getMonth() + 1;
|
||||
const tMonth = this.t(`i.datepicker.month${month}`);
|
||||
return `${date.getFullYear()}${tYear} ${tMonth}`;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (newVal) {
|
||||
if (!newVal) return;
|
||||
if (Array.isArray(newVal)) {
|
||||
const valStart = newVal[0] ? toDate(newVal[0]) : false;
|
||||
const valEnd = newVal[1] ? toDate(newVal[1]) : false;
|
||||
|
||||
if (valStart && valEnd) {
|
||||
this.handleChange(
|
||||
{
|
||||
hours: valStart.getHours(),
|
||||
minutes: valStart.getMinutes(),
|
||||
seconds: valStart.getSeconds()
|
||||
},
|
||||
{
|
||||
hours: valEnd.getHours(),
|
||||
minutes: valEnd.getMinutes(),
|
||||
seconds: valEnd.getSeconds()
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClear() {
|
||||
this.date = initTimeDate();
|
||||
this.dateEnd = initTimeDate();
|
||||
this.hours = '';
|
||||
this.minutes = '';
|
||||
this.seconds = '';
|
||||
this.hoursEnd = '';
|
||||
this.minutesEnd = '';
|
||||
this.secondsEnd = '';
|
||||
},
|
||||
handleChange (date, dateEnd, emit = true) {
|
||||
const oldDateEnd = new Date(this.dateEnd);
|
||||
|
||||
if (date.hours !== undefined) {
|
||||
this.date.setHours(date.hours);
|
||||
this.hours = this.date.getHours();
|
||||
}
|
||||
if (date.minutes !== undefined) {
|
||||
this.date.setMinutes(date.minutes);
|
||||
this.minutes = this.date.getMinutes();
|
||||
}
|
||||
if (date.seconds !== undefined) {
|
||||
this.date.setSeconds(date.seconds);
|
||||
this.seconds = this.date.getSeconds();
|
||||
}
|
||||
if (dateEnd.hours !== undefined) {
|
||||
this.dateEnd.setHours(dateEnd.hours);
|
||||
this.hoursEnd = this.dateEnd.getHours();
|
||||
}
|
||||
if (dateEnd.minutes !== undefined) {
|
||||
this.dateEnd.setMinutes(dateEnd.minutes);
|
||||
this.minutesEnd = this.dateEnd.getMinutes();
|
||||
}
|
||||
if (dateEnd.seconds !== undefined) {
|
||||
this.dateEnd.setSeconds(dateEnd.seconds);
|
||||
this.secondsEnd = this.dateEnd.getSeconds();
|
||||
}
|
||||
// judge endTime > startTime?
|
||||
if (this.dateEnd < this.date) {
|
||||
this.$nextTick(() => {
|
||||
this.dateEnd = new Date(this.date);
|
||||
this.hoursEnd = this.dateEnd.getHours();
|
||||
this.minutesEnd = this.dateEnd.getMinutes();
|
||||
this.secondsEnd = this.dateEnd.getSeconds();
|
||||
|
||||
const format = 'yyyy-MM-dd HH:mm:ss';
|
||||
if (formatDate(oldDateEnd, format) !== formatDate(this.dateEnd, format)) {
|
||||
if (emit) this.$emit('on-pick', [this.date, this.dateEnd], true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (emit) this.$emit('on-pick', [this.date, this.dateEnd], true);
|
||||
}
|
||||
},
|
||||
handleStartChange (date) {
|
||||
this.handleChange(date, {});
|
||||
},
|
||||
handleEndChange (date) {
|
||||
this.handleChange({}, date);
|
||||
},
|
||||
updateScroll () {
|
||||
this.$refs.timeSpinner.updateScroll();
|
||||
this.$refs.timeSpinnerEnd.updateScroll();
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
if (this.$parent && this.$parent.$options.name === 'DatePicker') this.showDate = true;
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,115 +0,0 @@
|
|||
<template>
|
||||
<div :class="[prefixCls + '-body-wrapper']">
|
||||
<div :class="[prefixCls + '-body']">
|
||||
<div :class="[timePrefixCls + '-header']" v-if="showDate">{{ visibleDate }}</div>
|
||||
<div :class="[prefixCls + '-content']">
|
||||
<time-spinner
|
||||
v-ref:time-spinner
|
||||
:show-seconds="showSeconds"
|
||||
:hours="hours"
|
||||
:minutes="minutes"
|
||||
:seconds="seconds"
|
||||
:disabled-hours="disabledHours"
|
||||
:disabled-minutes="disabledMinutes"
|
||||
:disabled-seconds="disabledSeconds"
|
||||
:hide-disabled-options="hideDisabledOptions"
|
||||
@on-change="handleChange"
|
||||
@on-pick-click="handlePickClick"></time-spinner>
|
||||
</div>
|
||||
<Confirm
|
||||
v-if="confirm"
|
||||
@on-pick-clear="handlePickClear"
|
||||
@on-pick-success="handlePickSuccess"></Confirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import TimeSpinner from '../base/time-spinner.vue';
|
||||
import Confirm from '../base/confirm.vue';
|
||||
|
||||
import Mixin from './mixin';
|
||||
import Locale from '../../../mixins/locale';
|
||||
|
||||
import { initTimeDate } from '../util';
|
||||
|
||||
const prefixCls = 'ivu-picker-panel';
|
||||
const timePrefixCls = 'ivu-time-picker';
|
||||
|
||||
export default {
|
||||
mixins: [ Mixin, Locale ],
|
||||
components: { TimeSpinner, Confirm },
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
timePrefixCls: timePrefixCls,
|
||||
date: initTimeDate(),
|
||||
value: '',
|
||||
showDate: false,
|
||||
format: 'HH:mm:ss',
|
||||
hours: '',
|
||||
minutes: '',
|
||||
seconds: '',
|
||||
disabledHours: [],
|
||||
disabledMinutes: [],
|
||||
disabledSeconds: [],
|
||||
hideDisabledOptions: false,
|
||||
confirm: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
showSeconds () {
|
||||
return (this.format || '').indexOf('ss') !== -1;
|
||||
},
|
||||
visibleDate () {
|
||||
const date = this.date;
|
||||
const month = date.getMonth() + 1;
|
||||
const tYear = this.t('i.datepicker.year');
|
||||
const tMonth = this.t(`i.datepicker.month${month}`);
|
||||
return `${date.getFullYear()}${tYear} ${tMonth}`;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (newVal) {
|
||||
if (!newVal) return;
|
||||
newVal = new Date(newVal);
|
||||
if (!isNaN(newVal)) {
|
||||
this.date = newVal;
|
||||
this.handleChange({
|
||||
hours: newVal.getHours(),
|
||||
minutes: newVal.getMinutes(),
|
||||
seconds: newVal.getSeconds()
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClear() {
|
||||
this.date = initTimeDate();
|
||||
this.hours = '';
|
||||
this.minutes = '';
|
||||
this.seconds = '';
|
||||
},
|
||||
handleChange (date, emit = true) {
|
||||
if (date.hours !== undefined) {
|
||||
this.date.setHours(date.hours);
|
||||
this.hours = this.date.getHours();
|
||||
}
|
||||
if (date.minutes !== undefined) {
|
||||
this.date.setMinutes(date.minutes);
|
||||
this.minutes = this.date.getMinutes();
|
||||
}
|
||||
if (date.seconds !== undefined) {
|
||||
this.date.setSeconds(date.seconds);
|
||||
this.seconds = this.date.getSeconds();
|
||||
}
|
||||
if (emit) this.$emit('on-pick', this.date, true);
|
||||
},
|
||||
updateScroll () {
|
||||
this.$refs.timeSpinner.updateScroll();
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
if (this.$parent && this.$parent.$options.name === 'DatePicker') this.showDate = true;
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,496 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
:class="[prefixCls]"
|
||||
v-clickoutside="handleClose">
|
||||
<div v-el:reference :class="[prefixCls + '-rel']">
|
||||
<slot>
|
||||
<i-input
|
||||
:class="[prefixCls + '-editor']"
|
||||
:readonly="!editable || readonly"
|
||||
:disabled="disabled"
|
||||
:size="size"
|
||||
:placeholder="placeholder"
|
||||
:value="visualValue"
|
||||
@on-change="handleInputChange"
|
||||
@on-focus="handleFocus"
|
||||
@on-click="handleIconClick"
|
||||
@mouseenter="handleInputMouseenter"
|
||||
@mouseleave="handleInputMouseleave"
|
||||
:icon="iconType"></i-input>
|
||||
</slot>
|
||||
</div>
|
||||
<Drop v-show="opened" :placement="placement" :transition="transition" v-ref:drop>
|
||||
<div v-el:picker></div>
|
||||
</Drop>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
import iInput from '../../components/input/input.vue';
|
||||
import Drop from '../../components/select/dropdown.vue';
|
||||
import clickoutside from '../../directives/clickoutside';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
import { formatDate, parseDate } from './util';
|
||||
|
||||
const prefixCls = 'ivu-date-picker';
|
||||
|
||||
const DEFAULT_FORMATS = {
|
||||
date: 'yyyy-MM-dd',
|
||||
month: 'yyyy-MM',
|
||||
year: 'yyyy',
|
||||
datetime: 'yyyy-MM-dd HH:mm:ss',
|
||||
time: 'HH:mm:ss',
|
||||
timerange: 'HH:mm:ss',
|
||||
daterange: 'yyyy-MM-dd',
|
||||
datetimerange: 'yyyy-MM-dd HH:mm:ss'
|
||||
};
|
||||
|
||||
const RANGE_SEPARATOR = ' - ';
|
||||
|
||||
const DATE_FORMATTER = function(value, format) {
|
||||
return formatDate(value, format);
|
||||
};
|
||||
const DATE_PARSER = function(text, format) {
|
||||
return parseDate(text, format);
|
||||
};
|
||||
const RANGE_FORMATTER = function(value, format) {
|
||||
if (Array.isArray(value) && value.length === 2) {
|
||||
const start = value[0];
|
||||
const end = value[1];
|
||||
|
||||
if (start && end) {
|
||||
return formatDate(start, format) + RANGE_SEPARATOR + formatDate(end, format);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const RANGE_PARSER = function(text, format) {
|
||||
const array = text.split(RANGE_SEPARATOR);
|
||||
if (array.length === 2) {
|
||||
const range1 = array[0];
|
||||
const range2 = array[1];
|
||||
|
||||
return [parseDate(range1, format), parseDate(range2, format)];
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const TYPE_VALUE_RESOLVER_MAP = {
|
||||
default: {
|
||||
formatter(value) {
|
||||
if (!value) return '';
|
||||
return '' + value;
|
||||
},
|
||||
parser(text) {
|
||||
if (text === undefined || text === '') return null;
|
||||
return text;
|
||||
}
|
||||
},
|
||||
date: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
datetime: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
daterange: {
|
||||
formatter: RANGE_FORMATTER,
|
||||
parser: RANGE_PARSER
|
||||
},
|
||||
datetimerange: {
|
||||
formatter: RANGE_FORMATTER,
|
||||
parser: RANGE_PARSER
|
||||
},
|
||||
timerange: {
|
||||
formatter: RANGE_FORMATTER,
|
||||
parser: RANGE_PARSER
|
||||
},
|
||||
time: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
month: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
year: {
|
||||
formatter: DATE_FORMATTER,
|
||||
parser: DATE_PARSER
|
||||
},
|
||||
number: {
|
||||
formatter(value) {
|
||||
if (!value) return '';
|
||||
return '' + value;
|
||||
},
|
||||
parser(text) {
|
||||
let result = Number(text);
|
||||
|
||||
if (!isNaN(text)) {
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
components: { iInput, Drop },
|
||||
directives: { clickoutside },
|
||||
props: {
|
||||
format: {
|
||||
type: String
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
editable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
confirm: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
placement: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
|
||||
},
|
||||
default: 'bottom-start'
|
||||
},
|
||||
options: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
showClose: false,
|
||||
visible: false,
|
||||
picker: null,
|
||||
internalValue: '',
|
||||
disableClickOutSide: false // fixed when click a date,trigger clickoutside to close picker
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
opened () {
|
||||
return this.open === null ? this.visible : this.open;
|
||||
},
|
||||
iconType () {
|
||||
let icon = 'ios-calendar-outline';
|
||||
if (this.type === 'time' || this.type === 'timerange') icon = 'ios-clock-outline';
|
||||
if (this.showClose) icon = 'ios-close';
|
||||
return icon;
|
||||
},
|
||||
transition () {
|
||||
if (this.placement === 'bottom-start' || this.placement === 'bottom' || this.placement === 'bottom-end') {
|
||||
return 'slide-up';
|
||||
} else {
|
||||
return 'slide-down';
|
||||
}
|
||||
},
|
||||
selectionMode() {
|
||||
if (this.type === 'month') {
|
||||
return 'month';
|
||||
} else if (this.type === 'year') {
|
||||
return 'year';
|
||||
}
|
||||
|
||||
return 'day';
|
||||
},
|
||||
visualValue: {
|
||||
get () {
|
||||
const value = this.internalValue;
|
||||
if (!value) return;
|
||||
const formatter = (
|
||||
TYPE_VALUE_RESOLVER_MAP[this.type] ||
|
||||
TYPE_VALUE_RESOLVER_MAP['default']
|
||||
).formatter;
|
||||
const format = DEFAULT_FORMATS[this.type];
|
||||
|
||||
return formatter(value, this.format || format);
|
||||
},
|
||||
|
||||
set (value) {
|
||||
if (value) {
|
||||
const type = this.type;
|
||||
const parser = (
|
||||
TYPE_VALUE_RESOLVER_MAP[type] ||
|
||||
TYPE_VALUE_RESOLVER_MAP['default']
|
||||
).parser;
|
||||
const parsedValue = parser(value, this.format || DEFAULT_FORMATS[type]);
|
||||
if (parsedValue) {
|
||||
if (this.picker) this.picker.value = parsedValue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this.picker) this.picker.value = value;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose () {
|
||||
if (this.open !== null) return;
|
||||
if (!this.disableClickOutSide) this.visible = false;
|
||||
this.disableClickOutSide = false;
|
||||
},
|
||||
handleFocus () {
|
||||
if (this.readonly) return;
|
||||
this.visible = true;
|
||||
},
|
||||
handleInputChange (event) {
|
||||
const oldValue = this.visualValue;
|
||||
const value = event.target.value;
|
||||
|
||||
let correctValue = '';
|
||||
let correctDate = '';
|
||||
const type = this.type;
|
||||
const format = this.format || DEFAULT_FORMATS[type];
|
||||
|
||||
if (type === 'daterange' || type === 'timerange' || type === 'datetimerange') {
|
||||
const parser = (
|
||||
TYPE_VALUE_RESOLVER_MAP[type] ||
|
||||
TYPE_VALUE_RESOLVER_MAP['default']
|
||||
).parser;
|
||||
|
||||
const formatter = (
|
||||
TYPE_VALUE_RESOLVER_MAP[type] ||
|
||||
TYPE_VALUE_RESOLVER_MAP['default']
|
||||
).formatter;
|
||||
|
||||
const parsedValue = parser(value, format);
|
||||
|
||||
if (parsedValue[0] instanceof Date && parsedValue[1] instanceof Date) {
|
||||
if (parsedValue[0].getTime() > parsedValue[1].getTime()) {
|
||||
correctValue = oldValue;
|
||||
} else {
|
||||
correctValue = formatter(parsedValue, format);
|
||||
}
|
||||
// todo 判断disabledDate
|
||||
} else {
|
||||
correctValue = oldValue;
|
||||
}
|
||||
|
||||
correctDate = parser(correctValue, format);
|
||||
} else if (type === 'time') {
|
||||
const parsedDate = parseDate(value, format);
|
||||
|
||||
if (parsedDate instanceof Date) {
|
||||
if (this.disabledHours.length || this.disabledMinutes.length || this.disabledSeconds.length) {
|
||||
const hours = parsedDate.getHours();
|
||||
const minutes = parsedDate.getMinutes();
|
||||
const seconds = parsedDate.getSeconds();
|
||||
|
||||
if ((this.disabledHours.length && this.disabledHours.indexOf(hours) > -1) ||
|
||||
(this.disabledMinutes.length && this.disabledMinutes.indexOf(minutes) > -1) ||
|
||||
(this.disabledSeconds.length && this.disabledSeconds.indexOf(seconds) > -1)) {
|
||||
correctValue = oldValue;
|
||||
} else {
|
||||
correctValue = formatDate(parsedDate, format);
|
||||
}
|
||||
} else {
|
||||
correctValue = formatDate(parsedDate, format);
|
||||
}
|
||||
} else {
|
||||
correctValue = oldValue;
|
||||
}
|
||||
|
||||
correctDate = parseDate(correctValue, format);
|
||||
} else {
|
||||
const parsedDate = parseDate(value, format);
|
||||
|
||||
if (parsedDate instanceof Date) {
|
||||
const options = this.options || false;
|
||||
if (options && options.disabledDate && typeof options.disabledDate === 'function' && options.disabledDate(new Date(parsedDate))) {
|
||||
correctValue = oldValue;
|
||||
} else {
|
||||
correctValue = formatDate(parsedDate, format);
|
||||
}
|
||||
} else {
|
||||
correctValue = oldValue;
|
||||
}
|
||||
|
||||
correctDate = parseDate(correctValue, format);
|
||||
}
|
||||
|
||||
this.visualValue = correctValue;
|
||||
event.target.value = correctValue;
|
||||
this.internalValue = correctDate;
|
||||
|
||||
if (correctValue !== oldValue) this.emitChange(correctDate);
|
||||
},
|
||||
handleInputMouseenter () {
|
||||
if (this.readonly || this.disabled) return;
|
||||
if (this.visualValue && this.clearable) {
|
||||
this.showClose = true;
|
||||
}
|
||||
},
|
||||
handleInputMouseleave () {
|
||||
this.showClose = false;
|
||||
},
|
||||
handleIconClick () {
|
||||
if (this.showClose) {
|
||||
this.handleClear();
|
||||
} else {
|
||||
this.handleFocus();
|
||||
}
|
||||
},
|
||||
handleClear () {
|
||||
this.visible = false;
|
||||
this.internalValue = '';
|
||||
this.value = '';
|
||||
this.$emit('on-clear');
|
||||
this.$dispatch('on-form-change', '');
|
||||
},
|
||||
showPicker () {
|
||||
if (!this.picker) {
|
||||
const type = this.type;
|
||||
|
||||
this.picker = new Vue(this.panel).$mount(this.$els.picker);
|
||||
if (type === 'datetime' || type === 'datetimerange') {
|
||||
this.confirm = true;
|
||||
this.picker.showTime = true;
|
||||
}
|
||||
this.picker.value = this.internalValue;
|
||||
this.picker.confirm = this.confirm;
|
||||
this.picker.selectionMode = this.selectionMode;
|
||||
if (this.format) this.picker.format = this.format;
|
||||
|
||||
// TimePicker
|
||||
if (this.disabledHours) this.picker.disabledHours = this.disabledHours;
|
||||
if (this.disabledMinutes) this.picker.disabledMinutes = this.disabledMinutes;
|
||||
if (this.disabledSeconds) this.picker.disabledSeconds = this.disabledSeconds;
|
||||
if (this.hideDisabledOptions) this.picker.hideDisabledOptions = this.hideDisabledOptions;
|
||||
|
||||
const options = this.options;
|
||||
for (const option in options) {
|
||||
this.picker[option] = options[option];
|
||||
}
|
||||
|
||||
this.picker.$on('on-pick', (date, visible = false) => {
|
||||
if (!this.confirm) this.visible = visible;
|
||||
this.value = date;
|
||||
this.picker.value = date;
|
||||
this.picker.resetView && this.picker.resetView();
|
||||
this.emitChange(date);
|
||||
});
|
||||
|
||||
this.picker.$on('on-pick-clear', () => {
|
||||
this.handleClear();
|
||||
});
|
||||
this.picker.$on('on-pick-success', () => {
|
||||
this.visible = false;
|
||||
this.$emit('on-ok');
|
||||
});
|
||||
this.picker.$on('on-pick-click', () => this.disableClickOutSide = true);
|
||||
}
|
||||
if (this.internalValue instanceof Date) {
|
||||
this.picker.date = new Date(this.internalValue.getTime());
|
||||
} else {
|
||||
this.picker.value = this.internalValue;
|
||||
}
|
||||
this.picker.resetView && this.picker.resetView();
|
||||
},
|
||||
emitChange (date) {
|
||||
const type = this.type;
|
||||
const format = this.format || DEFAULT_FORMATS[type];
|
||||
const formatter = (
|
||||
TYPE_VALUE_RESOLVER_MAP[type] ||
|
||||
TYPE_VALUE_RESOLVER_MAP['default']
|
||||
).formatter;
|
||||
|
||||
let newDate = formatter(date, format);
|
||||
if (type === 'daterange' || type === 'timerange') {
|
||||
newDate = [newDate.split(RANGE_SEPARATOR)[0], newDate.split(RANGE_SEPARATOR)[1]];
|
||||
}
|
||||
|
||||
this.$emit('on-change', newDate);
|
||||
this.$dispatch('on-form-change', newDate);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible (val) {
|
||||
if (val) {
|
||||
this.showPicker();
|
||||
this.$refs.drop.update();
|
||||
if (this.open === null) this.$emit('on-open-change', true);
|
||||
} else {
|
||||
if (this.picker) this.picker.resetView && this.picker.resetView(true);
|
||||
this.$refs.drop.destroy();
|
||||
if (this.open === null) this.$emit('on-open-change', false);
|
||||
}
|
||||
},
|
||||
internalValue(val) {
|
||||
if (!val && this.picker && typeof this.picker.handleClear === 'function') {
|
||||
this.picker.handleClear();
|
||||
}
|
||||
},
|
||||
value: {
|
||||
immediate: true,
|
||||
handler (val) {
|
||||
const type = this.type;
|
||||
const parser = (
|
||||
TYPE_VALUE_RESOLVER_MAP[type] ||
|
||||
TYPE_VALUE_RESOLVER_MAP['default']
|
||||
).parser;
|
||||
|
||||
if (val && type === 'time' && !(val instanceof Date)) {
|
||||
val = parser(val, this.format || DEFAULT_FORMATS[type]);
|
||||
} else if (val && type === 'timerange' && Array.isArray(val) && val.length === 2 && !(val[0] instanceof Date) && !(val[1] instanceof Date)) {
|
||||
val = val.join(RANGE_SEPARATOR);
|
||||
val = parser(val, this.format || DEFAULT_FORMATS[type]);
|
||||
}
|
||||
|
||||
this.internalValue = val;
|
||||
}
|
||||
},
|
||||
open (val) {
|
||||
if (val === true) {
|
||||
this.visible = val;
|
||||
this.$emit('on-open-change', true);
|
||||
} else if (val === false) {
|
||||
this.$emit('on-open-change', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
if (this.picker) {
|
||||
this.picker.$destroy();
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
if (this.open !== null) this.visible = this.open;
|
||||
},
|
||||
events: {
|
||||
'on-form-blur' () {
|
||||
return false;
|
||||
},
|
||||
'on-form-change' () {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,36 +0,0 @@
|
|||
import Picker from '../picker.vue';
|
||||
import DatePanel from '../panel/date.vue';
|
||||
import DateRangePanel from '../panel/date-range.vue';
|
||||
|
||||
const getPanel = function (type) {
|
||||
if (type === 'daterange' || type === 'datetimerange') {
|
||||
return DateRangePanel;
|
||||
}
|
||||
return DatePanel;
|
||||
};
|
||||
|
||||
import { oneOf } from '../../../utils/assist';
|
||||
|
||||
export default {
|
||||
mixins: [Picker],
|
||||
props: {
|
||||
type: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['year', 'month', 'date', 'daterange', 'datetime', 'datetimerange']);
|
||||
},
|
||||
default: 'date'
|
||||
},
|
||||
value: {}
|
||||
},
|
||||
created () {
|
||||
if (!this.value) {
|
||||
if (this.type === 'daterange' || this.type === 'datetimerange') {
|
||||
this.value = ['',''];
|
||||
} else {
|
||||
this.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
this.panel = getPanel(this.type);
|
||||
}
|
||||
};
|
|
@ -1,36 +0,0 @@
|
|||
import Picker from '../picker.vue';
|
||||
import TimePanel from '../panel/time.vue';
|
||||
import TimeRangePanel from '../panel/time-range.vue';
|
||||
import Options from '../time-mixins';
|
||||
|
||||
const getPanel = function (type) {
|
||||
if (type === 'timerange') {
|
||||
return TimeRangePanel;
|
||||
}
|
||||
return TimePanel;
|
||||
};
|
||||
|
||||
import { oneOf } from '../../../utils/assist';
|
||||
|
||||
export default {
|
||||
mixins: [Picker, Options],
|
||||
props: {
|
||||
type: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['time', 'timerange']);
|
||||
},
|
||||
default: 'time'
|
||||
},
|
||||
value: {}
|
||||
},
|
||||
created () {
|
||||
if (!this.value) {
|
||||
if (this.type === 'timerange') {
|
||||
this.value = ['',''];
|
||||
} else {
|
||||
this.value = '';
|
||||
}
|
||||
}
|
||||
this.panel = getPanel(this.type);
|
||||
}
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
export default {
|
||||
props: {
|
||||
disabledHours: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
disabledMinutes: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
disabledSeconds: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
hideDisabledOptions: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,85 +0,0 @@
|
|||
import dateUtil from '../../utils/date';
|
||||
|
||||
export const toDate = function(date) {
|
||||
date = new Date(date);
|
||||
if (isNaN(date.getTime())) return null;
|
||||
return date;
|
||||
};
|
||||
|
||||
export const formatDate = function(date, format) {
|
||||
date = toDate(date);
|
||||
if (!date) return '';
|
||||
return dateUtil.format(date, format || 'yyyy-MM-dd');
|
||||
};
|
||||
|
||||
export const parseDate = function(string, format) {
|
||||
return dateUtil.parse(string, format || 'yyyy-MM-dd');
|
||||
};
|
||||
|
||||
export const getDayCountOfMonth = function(year, month) {
|
||||
if (month === 3 || month === 5 || month === 8 || month === 10) {
|
||||
return 30;
|
||||
}
|
||||
|
||||
if (month === 1) {
|
||||
if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) {
|
||||
return 29;
|
||||
} else {
|
||||
return 28;
|
||||
}
|
||||
}
|
||||
|
||||
return 31;
|
||||
};
|
||||
|
||||
export const getFirstDayOfMonth = function(date) {
|
||||
const temp = new Date(date.getTime());
|
||||
temp.setDate(1);
|
||||
return temp.getDay();
|
||||
};
|
||||
|
||||
export const prevMonth = function(src) {
|
||||
const year = src.getFullYear();
|
||||
const month = src.getMonth();
|
||||
const date = src.getDate();
|
||||
|
||||
const newYear = month === 0 ? year - 1 : year;
|
||||
const newMonth = month === 0 ? 11 : month - 1;
|
||||
|
||||
const newMonthDayCount = getDayCountOfMonth(newYear, newMonth);
|
||||
if (newMonthDayCount < date) {
|
||||
src.setDate(newMonthDayCount);
|
||||
}
|
||||
|
||||
src.setMonth(newMonth);
|
||||
src.setFullYear(newYear);
|
||||
|
||||
return new Date(src.getTime());
|
||||
};
|
||||
|
||||
export const nextMonth = function(src) {
|
||||
const year = src.getFullYear();
|
||||
const month = src.getMonth();
|
||||
const date = src.getDate();
|
||||
|
||||
const newYear = month === 11 ? year + 1 : year;
|
||||
const newMonth = month === 11 ? 0 : month + 1;
|
||||
|
||||
const newMonthDayCount = getDayCountOfMonth(newYear, newMonth);
|
||||
if (newMonthDayCount < date) {
|
||||
src.setDate(newMonthDayCount);
|
||||
}
|
||||
|
||||
src.setMonth(newMonth);
|
||||
src.setFullYear(newYear);
|
||||
|
||||
return new Date(src.getTime());
|
||||
};
|
||||
|
||||
export const initTimeDate = function () {
|
||||
const date = new Date();
|
||||
date.setHours(0);
|
||||
date.setMinutes(0);
|
||||
date.setSeconds(0);
|
||||
return date;
|
||||
};
|
|
@ -1,57 +0,0 @@
|
|||
<template>
|
||||
<li :class="classes" @click="handleClick"><slot></slot></li>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-dropdown-item';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
key: {
|
||||
type: [String, Number]
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
selected: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
divided: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-disabled`]: this.disabled,
|
||||
[`${prefixCls}-selected`]: this.selected,
|
||||
[`${prefixCls}-divided`]: this.divided
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
const $parent = this.$parent.$parent;
|
||||
const hasChildren = this.$parent && this.$parent.$options.name === 'Dropdown';
|
||||
|
||||
if (this.disabled) {
|
||||
this.$nextTick(() => {
|
||||
$parent.visible = true;
|
||||
});
|
||||
} else if (hasChildren) {
|
||||
this.$parent.$emit('on-haschild-click');
|
||||
} else {
|
||||
if ($parent && $parent.$options.name === 'Dropdown') {
|
||||
$parent.$emit('on-hover-click');
|
||||
}
|
||||
}
|
||||
$parent.$emit('on-click', this.key);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,6 +0,0 @@
|
|||
<template>
|
||||
<ul class="ivu-dropdown-menu"><slot></slot></ul>
|
||||
</template>
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
|
@ -1,134 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
:class="[prefixCls]"
|
||||
v-clickoutside="handleClose"
|
||||
@mouseenter="handleMouseenter"
|
||||
@mouseleave="handleMouseleave">
|
||||
<div :class="[prefixCls-rel]" v-el:reference @click="handleClick"><slot></slot></div>
|
||||
<Drop v-show="visible" :placement="placement" :transition="transition" v-ref:drop><slot name="list"></slot></Drop>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Drop from '../select/dropdown.vue';
|
||||
import clickoutside from '../../directives/clickoutside';
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-dropdown';
|
||||
|
||||
export default {
|
||||
name: 'Dropdown',
|
||||
directives: { clickoutside },
|
||||
components: { Drop },
|
||||
props: {
|
||||
trigger: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['click', 'hover', 'custom']);
|
||||
},
|
||||
default: 'hover'
|
||||
},
|
||||
placement: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
|
||||
},
|
||||
default: 'bottom'
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
transition () {
|
||||
return ['bottom-start', 'bottom', 'bottom-end'].indexOf(this.placement) > -1 ? 'slide-up' : 'fade';
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
if (this.trigger === 'custom') return false;
|
||||
if (this.trigger !== 'click') {
|
||||
return false;
|
||||
}
|
||||
this.visible = !this.visible;
|
||||
},
|
||||
handleMouseenter () {
|
||||
if (this.trigger === 'custom') return false;
|
||||
if (this.trigger !== 'hover') {
|
||||
return false;
|
||||
}
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(() => {
|
||||
this.visible = true;
|
||||
}, 250);
|
||||
},
|
||||
handleMouseleave () {
|
||||
if (this.trigger === 'custom') return false;
|
||||
if (this.trigger !== 'hover') {
|
||||
return false;
|
||||
}
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(() => {
|
||||
this.visible = false;
|
||||
}, 150);
|
||||
},
|
||||
handleClose () {
|
||||
if (this.trigger === 'custom') return false;
|
||||
if (this.trigger !== 'click') {
|
||||
return false;
|
||||
}
|
||||
this.visible = false;
|
||||
},
|
||||
hasParent () {
|
||||
const $parent = this.$parent.$parent;
|
||||
if ($parent && $parent.$options.name === 'Dropdown') {
|
||||
return $parent;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible (val) {
|
||||
if (val) {
|
||||
this.$refs.drop.update();
|
||||
} else {
|
||||
this.$refs.drop.destroy();
|
||||
}
|
||||
this.$emit('on-visible-change', val);
|
||||
}
|
||||
},
|
||||
events: {
|
||||
'on-click' (key) {
|
||||
const $parent = this.hasParent();
|
||||
if ($parent ) $parent.$emit('on-click', key);
|
||||
},
|
||||
'on-hover-click' () {
|
||||
const $parent = this.hasParent();
|
||||
if ($parent) {
|
||||
this.$nextTick(() => {
|
||||
if (this.trigger === 'custom') return false;
|
||||
this.visible = false;
|
||||
});
|
||||
$parent.$emit('on-hover-click');
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
if (this.trigger === 'custom') return false;
|
||||
this.visible = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
'on-haschild-click' () {
|
||||
this.$nextTick(() => {
|
||||
if (this.trigger === 'custom') return false;
|
||||
this.visible = true;
|
||||
});
|
||||
const $parent = this.hasParent();
|
||||
if ($parent) $parent.$emit('on-haschild-click');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,7 +0,0 @@
|
|||
import Dropdown from './dropdown.vue';
|
||||
import DropdownMenu from './dropdown-menu.vue';
|
||||
import DropdownItem from './dropdown-item.vue';
|
||||
|
||||
Dropdown.Menu = DropdownMenu;
|
||||
Dropdown.Item = DropdownItem;
|
||||
export default Dropdown;
|
|
@ -1,235 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<label :class="[prefixCls + '-label']" :style="labelStyles" v-if="label"><slot name="label">{{ label }}</slot></label>
|
||||
<div :class="[prefixCls + '-content']" :style="contentStyles">
|
||||
<slot></slot>
|
||||
<div transition="fade" :class="[prefixCls + '-error-tip']" v-if="validateState === 'error' && showMessage && form.showMessage">{{ validateMessage }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// https://github.com/ElemeFE/element/blob/dev/packages/form/src/form-item.vue
|
||||
|
||||
import AsyncValidator from 'async-validator';
|
||||
|
||||
const prefixCls = 'ivu-form-item';
|
||||
|
||||
function getPropByPath(obj, path) {
|
||||
let tempObj = obj;
|
||||
path = path.replace(/\[(\w+)\]/g, '.$1');
|
||||
path = path.replace(/^\./, '');
|
||||
|
||||
let keyArr = path.split('.');
|
||||
let i = 0;
|
||||
|
||||
for (let len = keyArr.length; i < len - 1; ++i) {
|
||||
let key = keyArr[i];
|
||||
if (key in tempObj) {
|
||||
tempObj = tempObj[key];
|
||||
} else {
|
||||
throw new Error('[iView warn]: please transfer a valid prop path to form item!');
|
||||
}
|
||||
}
|
||||
return {
|
||||
o: tempObj,
|
||||
k: keyArr[i],
|
||||
v: tempObj[keyArr[i]]
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
labelWidth: {
|
||||
type: Number
|
||||
},
|
||||
prop: {
|
||||
type: String
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rules: {
|
||||
type: [Object, Array]
|
||||
},
|
||||
error: {
|
||||
type: String
|
||||
},
|
||||
validateStatus: {
|
||||
type: Boolean
|
||||
},
|
||||
showMessage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
isRequired: false,
|
||||
validateState: '',
|
||||
validateMessage: '',
|
||||
validateDisabled: false,
|
||||
validator: {}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
error (val) {
|
||||
this.validateMessage = val;
|
||||
this.validateState = 'error';
|
||||
},
|
||||
validateStatus (val) {
|
||||
this.validateState = val;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-required`]: this.required || this.isRequired,
|
||||
[`${prefixCls}-error`]: this.validateState === 'error',
|
||||
[`${prefixCls}-validating`]: this.validateState === 'validating'
|
||||
}
|
||||
];
|
||||
},
|
||||
form() {
|
||||
let parent = this.$parent;
|
||||
while (parent.$options.name !== 'iForm') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
fieldValue: {
|
||||
cache: false,
|
||||
get() {
|
||||
const model = this.form.model;
|
||||
if (!model || !this.prop) { return; }
|
||||
|
||||
let path = this.prop;
|
||||
if (path.indexOf(':') !== -1) {
|
||||
path = path.replace(/:/, '.');
|
||||
}
|
||||
|
||||
return getPropByPath(model, path).v;
|
||||
}
|
||||
},
|
||||
labelStyles () {
|
||||
let style = {};
|
||||
const labelWidth = this.labelWidth || this.form.labelWidth;
|
||||
if (labelWidth) {
|
||||
style.width = `${labelWidth}px`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
contentStyles () {
|
||||
let style = {};
|
||||
const labelWidth = this.labelWidth || this.form.labelWidth;
|
||||
if (labelWidth) {
|
||||
style.marginLeft = `${labelWidth}px`;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getRules () {
|
||||
let formRules = this.form.rules;
|
||||
const selfRules = this.rules;
|
||||
|
||||
formRules = formRules ? formRules[this.prop] : [];
|
||||
|
||||
return [].concat(selfRules || formRules || []);
|
||||
},
|
||||
getFilteredRule (trigger) {
|
||||
const rules = this.getRules();
|
||||
|
||||
return rules.filter(rule => !rule.trigger || rule.trigger.indexOf(trigger) !== -1);
|
||||
},
|
||||
validate(trigger, callback = function () {}) {
|
||||
const rules = this.getFilteredRule(trigger);
|
||||
if (!rules || rules.length === 0) {
|
||||
callback();
|
||||
return true;
|
||||
}
|
||||
|
||||
this.validateState = 'validating';
|
||||
|
||||
let descriptor = {};
|
||||
descriptor[this.prop] = rules;
|
||||
|
||||
const validator = new AsyncValidator(descriptor);
|
||||
let model = {};
|
||||
|
||||
model[this.prop] = this.fieldValue;
|
||||
|
||||
validator.validate(model, { firstFields: true }, errors => {
|
||||
this.validateState = !errors ? 'success' : 'error';
|
||||
this.validateMessage = errors ? errors[0].message : '';
|
||||
|
||||
callback(this.validateMessage);
|
||||
});
|
||||
},
|
||||
resetField () {
|
||||
this.validateState = '';
|
||||
this.validateMessage = '';
|
||||
|
||||
let model = this.form.model;
|
||||
let value = this.fieldValue;
|
||||
let path = this.prop;
|
||||
if (path.indexOf(':') !== -1) {
|
||||
path = path.replace(/:/, '.');
|
||||
}
|
||||
|
||||
let prop = getPropByPath(model, path);
|
||||
|
||||
if (Array.isArray(value) && value.length > 0) {
|
||||
this.validateDisabled = true;
|
||||
prop.o[prop.k] = [];
|
||||
} else if (value !== this.initialValue) {
|
||||
this.validateDisabled = true;
|
||||
prop.o[prop.k] = this.initialValue;
|
||||
}
|
||||
},
|
||||
onFieldBlur() {
|
||||
this.validate('blur');
|
||||
},
|
||||
onFieldChange() {
|
||||
if (this.validateDisabled) {
|
||||
this.validateDisabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.validate('change');
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
if (this.prop) {
|
||||
this.$dispatch('on-form-item-add', this);
|
||||
|
||||
Object.defineProperty(this, 'initialValue', {
|
||||
value: this.fieldValue
|
||||
});
|
||||
|
||||
let rules = this.getRules();
|
||||
|
||||
if (rules.length) {
|
||||
rules.every(rule => {
|
||||
if (rule.required) {
|
||||
this.isRequired = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this.$on('on-form-blur', this.onFieldBlur);
|
||||
this.$on('on-form-change', this.onFieldChange);
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$dispatch('on-form-item-remove', this);
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,96 +0,0 @@
|
|||
<template>
|
||||
<form :class="classes"><slot></slot></form>
|
||||
</template>
|
||||
<script>
|
||||
// https://github.com/ElemeFE/element/blob/dev/packages/form/src/form.vue
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-form';
|
||||
|
||||
export default {
|
||||
name: 'iForm',
|
||||
props: {
|
||||
model: {
|
||||
type: Object
|
||||
},
|
||||
rules: {
|
||||
type: Object
|
||||
},
|
||||
labelWidth: {
|
||||
type: Number
|
||||
},
|
||||
labelPosition: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['left', 'right', 'top']);
|
||||
},
|
||||
default: 'right'
|
||||
},
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showMessage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
fields: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-label-${this.labelPosition}`,
|
||||
{
|
||||
[`${prefixCls}-inline`]: this.inline
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetFields() {
|
||||
this.fields.forEach(field => {
|
||||
field.resetField();
|
||||
});
|
||||
},
|
||||
validate(callback) {
|
||||
let valid = true;
|
||||
let count = 0;
|
||||
this.fields.forEach(field => {
|
||||
field.validate('', errors => {
|
||||
if (errors) {
|
||||
valid = false;
|
||||
}
|
||||
if (typeof callback === 'function' && ++count === this.fields.length) {
|
||||
callback(valid);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
validateField(prop, cb) {
|
||||
const field = this.fields.filter(field => field.prop === prop)[0];
|
||||
if (!field) { throw new Error('[iView warn]: must call validateField with valid prop string!'); }
|
||||
|
||||
field.validate('', cb);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
rules() {
|
||||
this.validate();
|
||||
}
|
||||
},
|
||||
events: {
|
||||
'on-form-item-add' (field) {
|
||||
if (field) this.fields.push(field);
|
||||
return false;
|
||||
},
|
||||
'on-form-item-remove' (field) {
|
||||
if (field.prop) this.fields.splice(this.fields.indexOf(field), 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,5 +0,0 @@
|
|||
import Form from './form.vue';
|
||||
import FormItem from './form-item.vue';
|
||||
|
||||
Form.Item = FormItem;
|
||||
export default Form;
|
|
@ -1,32 +0,0 @@
|
|||
<template>
|
||||
<i :class="classes" :style="styles"></i>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-icon';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
type: String,
|
||||
size: [Number, String],
|
||||
color: String
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return `${prefixCls} ${prefixCls}-${this.type}`;
|
||||
},
|
||||
styles () {
|
||||
let style = {};
|
||||
|
||||
if (this.size) {
|
||||
style['font-size'] = `${this.size}px`;
|
||||
}
|
||||
|
||||
if (this.color) {
|
||||
style.color = this.color;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,2 +0,0 @@
|
|||
import Icon from './icon.vue';
|
||||
export default Icon;
|
|
@ -1,2 +0,0 @@
|
|||
import InputNumber from './input-number.vue';
|
||||
export default InputNumber;
|
|
@ -1,262 +0,0 @@
|
|||
<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';
|
||||
const iconPrefixCls = 'ivu-icon';
|
||||
|
||||
function isValueNumber (value) {
|
||||
return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value + '');
|
||||
}
|
||||
function addNum (num1, num2) {
|
||||
let 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 ${iconPrefixCls} ${iconPrefixCls}-ios-arrow-up`;
|
||||
},
|
||||
downClasses () {
|
||||
return [
|
||||
`${prefixCls}-handler`,
|
||||
`${prefixCls}-handler-down`,
|
||||
{
|
||||
[`${prefixCls}-handler-down-disabled`]: this.downDisabled
|
||||
}
|
||||
];
|
||||
},
|
||||
innerDownClasses () {
|
||||
return `${prefixCls}-handler-down-inner ${iconPrefixCls} ${iconPrefixCls}-ios-arrow-down`;
|
||||
},
|
||||
inputWrapClasses () {
|
||||
return `${prefixCls}-input-wrap`;
|
||||
},
|
||||
inputClasses () {
|
||||
return `${prefixCls}-input`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
preventDefault (e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
up (e) {
|
||||
const targetVal = Number(e.target.value);
|
||||
if (this.upDisabled && isNaN(targetVal)) {
|
||||
return false;
|
||||
}
|
||||
this.changeStep('up', e);
|
||||
},
|
||||
down (e) {
|
||||
const targetVal = Number(e.target.value);
|
||||
if (this.downDisabled && isNaN(targetVal)) {
|
||||
return false;
|
||||
}
|
||||
this.changeStep('down', e);
|
||||
},
|
||||
changeStep (type, e) {
|
||||
if (this.disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const targetVal = Number(e.target.value);
|
||||
let val = Number(this.value);
|
||||
const step = Number(this.step);
|
||||
if (isNaN(val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// input a number, and key up or down
|
||||
if (!isNaN(targetVal)) {
|
||||
if (type === 'up') {
|
||||
if (addNum(targetVal, step) <= this.max) {
|
||||
val = targetVal;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (type === 'down') {
|
||||
if (addNum(targetVal, -step) >= this.min) {
|
||||
val = targetVal;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'up') {
|
||||
val = addNum(val, step);
|
||||
} else if (type === 'down') {
|
||||
val = addNum(val, -step);
|
||||
}
|
||||
this.setValue(val);
|
||||
},
|
||||
setValue (val) {
|
||||
this.$nextTick(() => {
|
||||
this.value = val;
|
||||
this.$emit('on-change', val);
|
||||
this.$dispatch('on-form-change', val);
|
||||
});
|
||||
},
|
||||
focus () {
|
||||
this.focused = true;
|
||||
},
|
||||
blur () {
|
||||
this.focused = false;
|
||||
},
|
||||
keyDown (e) {
|
||||
if (e.keyCode === 38) {
|
||||
e.preventDefault();
|
||||
this.up(e);
|
||||
} else if (e.keyCode === 40) {
|
||||
e.preventDefault();
|
||||
this.down(e);
|
||||
}
|
||||
},
|
||||
change (event) {
|
||||
let val = event.target.value.trim();
|
||||
|
||||
const max = this.max;
|
||||
const min = this.min;
|
||||
|
||||
if (isValueNumber(val)) {
|
||||
val = Number(val);
|
||||
this.value = val;
|
||||
|
||||
if (val > max) {
|
||||
this.setValue(max);
|
||||
} else if (val < min) {
|
||||
this.setValue(min);
|
||||
} else {
|
||||
this.setValue(val);
|
||||
}
|
||||
} else {
|
||||
event.target.value = this.value;
|
||||
}
|
||||
},
|
||||
changeVal (val) {
|
||||
if (isValueNumber(val) || val === 0) {
|
||||
val = Number(val);
|
||||
const step = this.step;
|
||||
|
||||
this.upDisabled = val + step > this.max;
|
||||
this.downDisabled = val - step < this.min;
|
||||
} else {
|
||||
this.upDisabled = true;
|
||||
this.downDisabled = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.changeVal(this.value);
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
this.changeVal(val);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,2 +0,0 @@
|
|||
import Input from './input.vue';
|
||||
export default Input;
|
|
@ -1,189 +0,0 @@
|
|||
<template>
|
||||
<div :class="wrapClasses">
|
||||
<template v-if="type !== 'textarea'">
|
||||
<div :class="[prefixCls + '-group-prepend']" v-if="prepend" v-show="slotReady" v-el:prepend><slot name="prepend"></slot></div>
|
||||
<i class="ivu-icon" :class="['ivu-icon-' + icon, prefixCls + '-icon']" v-if="icon" @click="handleIconClick"></i>
|
||||
<i class="ivu-icon ivu-icon-load-c ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']" v-else transition="fade"></i>
|
||||
<input
|
||||
:type="type"
|
||||
:class="inputClasses"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:name="name"
|
||||
v-model="value"
|
||||
:number="number"
|
||||
@keyup.enter="handleEnter"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
@change="handleChange">
|
||||
<div :class="[prefixCls + '-group-append']" v-if="append" v-show="slotReady" v-el:append><slot name="append"></slot></div>
|
||||
</template>
|
||||
<textarea
|
||||
v-else
|
||||
v-el:textarea
|
||||
:class="textareaClasses"
|
||||
:style="textareaStyles"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:rows="rows"
|
||||
:maxlength="maxlength"
|
||||
:readonly="readonly"
|
||||
:name="name"
|
||||
v-model="value"
|
||||
@keyup.enter="handleEnter"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
@change="handleChange">
|
||||
</textarea>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
import calcTextareaHeight from '../../utils/calcTextareaHeight';
|
||||
|
||||
const prefixCls = 'ivu-input';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
type: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['text', 'textarea', 'password']);
|
||||
},
|
||||
default: 'text'
|
||||
},
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
// twoWay: true
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large']);
|
||||
}
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
maxlength: {
|
||||
type: Number
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
icon: String,
|
||||
autosize: {
|
||||
type: [Boolean, Object],
|
||||
default: false
|
||||
},
|
||||
rows: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
name: {
|
||||
type: String
|
||||
},
|
||||
number: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
prepend: true,
|
||||
append: true,
|
||||
slotReady: false,
|
||||
textareaStyles: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}-wrapper`,
|
||||
{
|
||||
[`${prefixCls}-wrapper-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-type`]: this.type,
|
||||
[`${prefixCls}-group`]: this.prepend || this.append,
|
||||
[`${prefixCls}-group-${this.size}`]: (this.prepend || this.append) && !!this.size
|
||||
}
|
||||
];
|
||||
},
|
||||
inputClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-${this.size}`]: !!this.size,
|
||||
[`${prefixCls}-disabled`]: this.disabled
|
||||
}
|
||||
];
|
||||
},
|
||||
textareaClasses () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-disabled`]: this.disabled
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleEnter () {
|
||||
this.$emit('on-enter');
|
||||
},
|
||||
handleIconClick () {
|
||||
this.$emit('on-click');
|
||||
},
|
||||
handleFocus () {
|
||||
this.$emit('on-focus');
|
||||
},
|
||||
handleBlur () {
|
||||
this.$emit('on-blur');
|
||||
this.$dispatch('on-form-blur', this.value);
|
||||
},
|
||||
handleChange (event) {
|
||||
this.$emit('on-change', event);
|
||||
},
|
||||
resizeTextarea () {
|
||||
const autosize = this.autosize;
|
||||
if (!autosize || this.type !== 'textarea') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const minRows = autosize.minRows;
|
||||
const maxRows = autosize.maxRows;
|
||||
|
||||
this.textareaStyles = calcTextareaHeight(this.$els.textarea, minRows, maxRows);
|
||||
},
|
||||
init () {
|
||||
if (this.type !== 'textarea') {
|
||||
this.prepend = this.$els.prepend.innerHTML !== '';
|
||||
this.append = this.$els.append.innerHTML !== '';
|
||||
} else {
|
||||
this.prepend = false;
|
||||
this.append = false;
|
||||
}
|
||||
this.slotReady = true;
|
||||
this.resizeTextarea();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value () {
|
||||
this.$nextTick(() => {
|
||||
this.resizeTextarea();
|
||||
});
|
||||
this.$dispatch('on-form-change', this.value);
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.$nextTick(() => this.init());
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,71 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" :style="styles">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-col';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
span: [Number, String],
|
||||
order: [Number, String],
|
||||
offset: [Number, String],
|
||||
push: [Number, String],
|
||||
pull: [Number, String],
|
||||
className: String,
|
||||
xs: [Number, Object],
|
||||
sm: [Number, Object],
|
||||
md: [Number, Object],
|
||||
lg: [Number, Object]
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
gutter: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
let classList = [
|
||||
`${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
|
||||
}
|
||||
];
|
||||
|
||||
['xs', 'sm', 'md', 'lg'].forEach(size => {
|
||||
if (typeof this[size] === 'number') {
|
||||
classList.push(`${prefixCls}-span-${size}-${this[size]}`);
|
||||
} else if (typeof this[size] === 'object') {
|
||||
let props = this[size];
|
||||
Object.keys(props).forEach(prop => {
|
||||
classList.push(
|
||||
prop !== 'span'
|
||||
? `${prefixCls}-${size}-${prop}-${props[prop]}`
|
||||
: `${prefixCls}-span-${size}-${props[prop]}`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return classList;
|
||||
},
|
||||
styles () {
|
||||
let style = {};
|
||||
if (this.gutter !== 0) {
|
||||
style = {
|
||||
paddingLeft: this.gutter / 2 + 'px',
|
||||
paddingRight: this.gutter / 2 + 'px'
|
||||
};
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,4 +0,0 @@
|
|||
import Row from './row.vue';
|
||||
import Col from './col.vue';
|
||||
|
||||
export { Row, Col };
|
|
@ -1,76 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" :style="styles">
|
||||
<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']);
|
||||
}
|
||||
},
|
||||
gutter: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
className: String
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
{
|
||||
[`${prefixCls}`]: !this.type,
|
||||
[`${prefixCls}-${this.type}`]: !!this.type,
|
||||
[`${prefixCls}-${this.type}-${this.align}`]: !!this.align,
|
||||
[`${prefixCls}-${this.type}-${this.justify}`]: !!this.justify,
|
||||
[`${this.className}`]: !!this.className
|
||||
}
|
||||
];
|
||||
},
|
||||
styles () {
|
||||
let style = {};
|
||||
if (this.gutter !== 0) {
|
||||
style = {
|
||||
marginLeft: this.gutter / -2 + 'px',
|
||||
marginRight: this.gutter / -2 + 'px'
|
||||
};
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateGutter (val) {
|
||||
this.$children.forEach((child) => {
|
||||
if (val !== 0) {
|
||||
child.gutter = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
gutter (val) {
|
||||
this.updateGutter(val);
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
this.updateGutter(this.gutter);
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,112 +0,0 @@
|
|||
import LoadingBar from './loading-bar';
|
||||
|
||||
let loadingBarInstance;
|
||||
let color = 'primary';
|
||||
let failedColor = 'error';
|
||||
let height = 2;
|
||||
let timer;
|
||||
|
||||
function getLoadingBarInstance () {
|
||||
loadingBarInstance = loadingBarInstance || LoadingBar.newInstance({
|
||||
color: color,
|
||||
failedColor: failedColor,
|
||||
height: height
|
||||
});
|
||||
|
||||
return loadingBarInstance;
|
||||
}
|
||||
|
||||
function update(options) {
|
||||
let instance = getLoadingBarInstance();
|
||||
|
||||
instance.update(options);
|
||||
}
|
||||
|
||||
function hide() {
|
||||
setTimeout(() => {
|
||||
update({
|
||||
show: false
|
||||
});
|
||||
setTimeout(() => {
|
||||
update({
|
||||
percent: 0
|
||||
});
|
||||
}, 200);
|
||||
}, 800);
|
||||
}
|
||||
|
||||
function clearTimer() {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
start () {
|
||||
if (timer) return;
|
||||
|
||||
let percent = 0;
|
||||
|
||||
update({
|
||||
percent: percent,
|
||||
status: 'success',
|
||||
show: true
|
||||
});
|
||||
|
||||
timer = setInterval(() => {
|
||||
percent += Math.floor(Math.random () * 3 + 5);
|
||||
if (percent > 95) {
|
||||
clearTimer();
|
||||
}
|
||||
update({
|
||||
percent: percent,
|
||||
status: 'success',
|
||||
show: true
|
||||
});
|
||||
}, 200);
|
||||
},
|
||||
update (percent) {
|
||||
clearTimer();
|
||||
update({
|
||||
percent: percent,
|
||||
status: 'success',
|
||||
show: true
|
||||
});
|
||||
},
|
||||
finish () {
|
||||
clearTimer();
|
||||
update({
|
||||
percent: 100,
|
||||
status: 'success',
|
||||
show: true
|
||||
});
|
||||
hide();
|
||||
},
|
||||
error () {
|
||||
clearTimer();
|
||||
update({
|
||||
percent: 100,
|
||||
status: 'error',
|
||||
show: true
|
||||
});
|
||||
hide();
|
||||
},
|
||||
config (options) {
|
||||
if (options.color) {
|
||||
color = options.color;
|
||||
}
|
||||
if (options.failedColor) {
|
||||
failedColor = options.failedColor;
|
||||
}
|
||||
if (options.height) {
|
||||
height = options.height;
|
||||
}
|
||||
},
|
||||
destroy () {
|
||||
clearTimer();
|
||||
let instance = getLoadingBarInstance();
|
||||
loadingBarInstance = null;
|
||||
instance.destroy();
|
||||
}
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
import LoadingBar from './loading-bar.vue';
|
||||
import Vue from 'vue';
|
||||
import { camelcaseToHyphen } from '../../utils/assist';
|
||||
|
||||
LoadingBar.newInstance = properties => {
|
||||
const _props = properties || {};
|
||||
|
||||
let props = '';
|
||||
Object.keys(_props).forEach(prop => {
|
||||
props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
|
||||
});
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `<loading-bar${props}></loading-bar>`;
|
||||
document.body.appendChild(div);
|
||||
|
||||
const loading_bar = new Vue({
|
||||
el: div,
|
||||
data: _props,
|
||||
components: { LoadingBar }
|
||||
}).$children[0];
|
||||
|
||||
return {
|
||||
update (options) {
|
||||
if ('percent' in options) {
|
||||
loading_bar.percent = options.percent;
|
||||
}
|
||||
if (options.status) {
|
||||
loading_bar.status = options.status;
|
||||
}
|
||||
if ('show' in options) {
|
||||
loading_bar.show = options.show;
|
||||
}
|
||||
},
|
||||
component: loading_bar,
|
||||
destroy () {
|
||||
document.body.removeChild(div);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default LoadingBar;
|
|
@ -1,77 +0,0 @@
|
|||
<template>
|
||||
<div :class="classes" :style="outerStyles" v-show="show" transition="fade">
|
||||
<div :class="innerClasses" :style="styles"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-loading-bar';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
percent: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: 'primary'
|
||||
},
|
||||
failedColor: {
|
||||
type: String,
|
||||
default: 'error'
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
validator (value) {
|
||||
return oneOf(value, ['success', 'error']);
|
||||
},
|
||||
default: 'success'
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return `${prefixCls}`;
|
||||
},
|
||||
innerClasses () {
|
||||
return [
|
||||
`${prefixCls}-inner`,
|
||||
{
|
||||
[`${prefixCls}-inner-color-primary`]: this.color === 'primary' && this.status === 'success',
|
||||
[`${prefixCls}-inner-failed-color-error`]: this.failedColor === 'error' && this.status === 'error'
|
||||
}
|
||||
];
|
||||
},
|
||||
outerStyles () {
|
||||
return {
|
||||
height: `${this.height}px`
|
||||
};
|
||||
},
|
||||
styles () {
|
||||
let style = {
|
||||
width: `${this.percent}%`,
|
||||
height: `${this.height}px`
|
||||
};
|
||||
|
||||
if (this.color !== 'primary' && this.status === 'success') {
|
||||
style.backgroundColor = this.color;
|
||||
}
|
||||
|
||||
if (this.failedColor !== 'error' && this.status === 'error') {
|
||||
style.backgroundColor = this.failedColor;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,10 +0,0 @@
|
|||
import Menu from './menu.vue';
|
||||
import MenuGroup from './menu-group.vue';
|
||||
import MenuItem from './menu-item.vue';
|
||||
import Submenu from './submenu.vue';
|
||||
|
||||
Menu.Group = MenuGroup;
|
||||
Menu.Item = MenuItem;
|
||||
Menu.Sub = Submenu;
|
||||
|
||||
export default Menu;
|
|
@ -1,24 +0,0 @@
|
|||
<template>
|
||||
<li :class="[prefixCls + '-item-group']">
|
||||
<div :class="[prefixCls + '-item-group-title']">{{ title }}</div>
|
||||
<ul><slot></slot></ul>
|
||||
</li>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-menu';
|
||||
|
||||
export default {
|
||||
name: 'MenuGroup',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,43 +0,0 @@
|
|||
<template>
|
||||
<li :class="classes" @click.stop="handleClick"><slot></slot></li>
|
||||
</template>
|
||||
<script>
|
||||
const prefixCls = 'ivu-menu';
|
||||
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
props: {
|
||||
key: {
|
||||
type: [String, Number],
|
||||
required: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
active: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}-item`,
|
||||
{
|
||||
[`${prefixCls}-item-active`]: this.active,
|
||||
[`${prefixCls}-item-selected`]: this.active,
|
||||
[`${prefixCls}-item-disabled`]: this.disabled
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick () {
|
||||
if (this.disabled) return;
|
||||
this.$dispatch('on-menu-item-select', this.key);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,134 +0,0 @@
|
|||
<template>
|
||||
<ul :class="classes" :style="styles"><slot></slot></ul>
|
||||
</template>
|
||||
<script>
|
||||
import { oneOf } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-menu';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
mode: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['horizontal', 'vertical']);
|
||||
},
|
||||
default: 'vertical'
|
||||
},
|
||||
theme: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['light', 'dark', 'primary']);
|
||||
},
|
||||
default: 'light'
|
||||
},
|
||||
activeKey: {
|
||||
type: [String, Number]
|
||||
},
|
||||
openKeys: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
accordion: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '240px'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
let theme = this.theme;
|
||||
if (this.mode === 'vertical' && this.theme === 'primary') theme = 'light';
|
||||
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
`${prefixCls}-${theme}`,
|
||||
{
|
||||
[`${prefixCls}-${this.mode}`]: this.mode
|
||||
}
|
||||
];
|
||||
},
|
||||
styles () {
|
||||
let style = {};
|
||||
|
||||
if (this.mode === 'vertical') style.width = this.width;
|
||||
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateActiveKey () {
|
||||
this.$children.forEach((item, index) => {
|
||||
if (!this.activeKey && index === 0) {
|
||||
this.activeKey = -1;
|
||||
}
|
||||
|
||||
if (item.$options.name === 'Submenu') {
|
||||
item.active = false;
|
||||
item.$children.forEach(subitem => {
|
||||
if (subitem.$options.name === 'MenuGroup') {
|
||||
subitem.$children.forEach(groupItem => {
|
||||
if (groupItem.key === this.activeKey) {
|
||||
groupItem.active = true;
|
||||
groupItem.$parent.$parent.active = true;
|
||||
} else {
|
||||
groupItem.active = false;
|
||||
}
|
||||
});
|
||||
} else if (subitem.$options.name === 'MenuItem') {
|
||||
if (subitem.key === this.activeKey) {
|
||||
subitem.active = true;
|
||||
subitem.$parent.active = true;
|
||||
} else {
|
||||
subitem.active = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (item.$options.name === 'MenuGroup') {
|
||||
item.$children.forEach(groupItem => {
|
||||
groupItem.active = groupItem.key === this.activeKey;
|
||||
});
|
||||
} else if (item.$options.name === 'MenuItem') {
|
||||
item.active = item.key === this.activeKey;
|
||||
}
|
||||
});
|
||||
},
|
||||
updateOpenKeys (key) {
|
||||
const index = this.openKeys.indexOf(key);
|
||||
if (index > -1) {
|
||||
this.openKeys.splice(index, 1);
|
||||
} else {
|
||||
this.openKeys.push(key);
|
||||
}
|
||||
},
|
||||
updateOpened () {
|
||||
this.$children.forEach(item => {
|
||||
if (item.$options.name === 'Submenu') {
|
||||
if (this.openKeys.indexOf(item.key) > -1) item.opened = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
compiled () {
|
||||
this.updateActiveKey();
|
||||
this.updateOpened();
|
||||
},
|
||||
events: {
|
||||
'on-menu-item-select' (key) {
|
||||
this.activeKey = key;
|
||||
this.$emit('on-select', key);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
openKeys () {
|
||||
this.$emit('on-open-change', this.openKeys);
|
||||
},
|
||||
activeKey () {
|
||||
this.updateActiveKey();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,127 +0,0 @@
|
|||
<template>
|
||||
<li :class="classes" @mouseenter="handleMouseenter" @mouseleave="handleMouseleave">
|
||||
<div :class="[prefixCls + '-submenu-title']" v-el:reference @click="handleClick">
|
||||
<slot name="title"></slot>
|
||||
<Icon type="ios-arrow-down" :class="[prefixCls + '-submenu-title-icon']"></Icon>
|
||||
</div>
|
||||
<ul :class="[prefixCls]" v-if="mode === 'vertical'" v-show="opened"><slot></slot></ul>
|
||||
<Drop
|
||||
v-else
|
||||
v-show="opened"
|
||||
placement="bottom"
|
||||
transition="slide-up"
|
||||
v-ref:drop
|
||||
:style="dropStyle"><slot></slot></Drop>
|
||||
</li>
|
||||
</template>
|
||||
<script>
|
||||
import Drop from '../select/dropdown.vue';
|
||||
import Icon from '../icon/icon.vue';
|
||||
import { getStyle } from '../../utils/assist';
|
||||
|
||||
const prefixCls = 'ivu-menu';
|
||||
|
||||
export default {
|
||||
name: 'Submenu',
|
||||
components: { Icon, Drop },
|
||||
props: {
|
||||
key: {
|
||||
type: [String, Number],
|
||||
required: true
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
active: false,
|
||||
opened: false,
|
||||
dropWidth: parseFloat(getStyle(this.$el, 'width'))
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}-submenu`,
|
||||
{
|
||||
[`${prefixCls}-item-active`]: this.active,
|
||||
[`${prefixCls}-opened`]: this.opened,
|
||||
[`${prefixCls}-submenu-disabled`]: this.disabled
|
||||
}
|
||||
];
|
||||
},
|
||||
mode () {
|
||||
return this.$parent.mode;
|
||||
},
|
||||
accordion () {
|
||||
return this.$parent.accordion;
|
||||
},
|
||||
dropStyle () {
|
||||
let style = {};
|
||||
|
||||
if (this.dropWidth) style.minWidth = `${this.dropWidth}px`;
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleMouseenter () {
|
||||
if (this.disabled) return;
|
||||
if (this.mode === 'vertical') return;
|
||||
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(() => {
|
||||
this.$parent.updateOpenKeys(this.key);
|
||||
this.opened = true;
|
||||
}, 250);
|
||||
},
|
||||
handleMouseleave () {
|
||||
if (this.disabled) return;
|
||||
if (this.mode === 'vertical') return;
|
||||
|
||||
clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(() => {
|
||||
this.$parent.updateOpenKeys(this.key);
|
||||
this.opened = false;
|
||||
}, 150);
|
||||
},
|
||||
handleClick () {
|
||||
if (this.disabled) return;
|
||||
if (this.mode === 'horizontal') return;
|
||||
const opened = this.opened;
|
||||
if (this.accordion) {
|
||||
this.$parent.$children.forEach(item => {
|
||||
if (item.$options.name === 'Submenu') item.opened = false;
|
||||
});
|
||||
}
|
||||
this.opened = !opened;
|
||||
this.$parent.updateOpenKeys(this.key);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
mode (val) {
|
||||
if (val === 'horizontal') {
|
||||
this.$refs.drop.update();
|
||||
}
|
||||
},
|
||||
opened (val) {
|
||||
if (this.mode === 'vertical') return;
|
||||
if (val) {
|
||||
// set drop a width to fixed when menu has fixed position
|
||||
this.dropWidth = parseFloat(getStyle(this.$el, 'width'));
|
||||
this.$refs.drop.update();
|
||||
} else {
|
||||
this.$refs.drop.destroy();
|
||||
}
|
||||
}
|
||||
},
|
||||
events: {
|
||||
'on-menu-item-select' () {
|
||||
if (this.mode === 'horizontal') this.opened = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,97 +0,0 @@
|
|||
import Notification from '../base/notification';
|
||||
|
||||
const prefixCls = 'ivu-message';
|
||||
const iconPrefixCls = 'ivu-icon';
|
||||
const prefixKey = 'ivu_message_key_';
|
||||
|
||||
let defaultDuration = 1.5;
|
||||
let top;
|
||||
let messageInstance;
|
||||
let key = 1;
|
||||
|
||||
const iconTypes = {
|
||||
'info': 'information-circled',
|
||||
'success': 'checkmark-circled',
|
||||
'warning': 'android-alert',
|
||||
'error': 'close-circled',
|
||||
'loading': 'load-c'
|
||||
};
|
||||
|
||||
function getMessageInstance () {
|
||||
messageInstance = messageInstance || Notification.newInstance({
|
||||
prefixCls: prefixCls,
|
||||
style: {
|
||||
top: `${top}px`
|
||||
}
|
||||
});
|
||||
|
||||
return messageInstance;
|
||||
}
|
||||
|
||||
function notice (content, duration = defaultDuration, type, onClose) {
|
||||
if (!onClose) {
|
||||
onClose = function () {
|
||||
|
||||
};
|
||||
}
|
||||
const iconType = iconTypes[type];
|
||||
|
||||
// if loading
|
||||
const loadCls = type === 'loading' ? ' ivu-load-loop' : '';
|
||||
|
||||
let instance = getMessageInstance();
|
||||
|
||||
instance.notice({
|
||||
key: `${prefixKey}${key}`,
|
||||
duration: duration,
|
||||
style: {},
|
||||
transitionName: 'move-up',
|
||||
content: `
|
||||
<div class="${prefixCls}-custom-content ${prefixCls}-${type}">
|
||||
<i class="${iconPrefixCls} ${iconPrefixCls}-${iconType}${loadCls}"></i>
|
||||
<span>${content}</span>
|
||||
</div>
|
||||
`,
|
||||
onClose: onClose
|
||||
});
|
||||
|
||||
// 用于手动消除
|
||||
return (function () {
|
||||
let target = key++;
|
||||
|
||||
return function () {
|
||||
instance.remove(`${prefixKey}${target}`);
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
export default {
|
||||
info (content, duration, onClose) {
|
||||
return notice(content, duration, 'info', onClose);
|
||||
},
|
||||
success (content, duration, onClose) {
|
||||
return notice(content, duration, 'success', onClose);
|
||||
},
|
||||
warning (content, duration, onClose) {
|
||||
return notice(content, duration, 'warning', onClose);
|
||||
},
|
||||
error (content, duration, onClose) {
|
||||
return notice(content, duration, 'error', onClose);
|
||||
},
|
||||
loading (content, duration, onClose) {
|
||||
return notice(content, duration, 'loading', onClose);
|
||||
},
|
||||
config (options) {
|
||||
if (options.top) {
|
||||
top = options.top;
|
||||
}
|
||||
if (options.duration) {
|
||||
defaultDuration = options.duration;
|
||||
}
|
||||
},
|
||||
destroy () {
|
||||
let instance = getMessageInstance();
|
||||
messageInstance = null;
|
||||
instance.destroy();
|
||||
}
|
||||
};
|
|
@ -1,175 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
import Modal from './modal.vue';
|
||||
import Icon from '../icon/icon.vue';
|
||||
import iButton from '../button/button.vue';
|
||||
import { camelcaseToHyphen } from '../../utils/assist';
|
||||
import { t } from '../../locale';
|
||||
|
||||
const prefixCls = 'ivu-modal-confirm';
|
||||
|
||||
Modal.newInstance = properties => {
|
||||
const _props = properties || {};
|
||||
|
||||
let props = '';
|
||||
Object.keys(_props).forEach(prop => {
|
||||
props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
|
||||
});
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `
|
||||
<Modal${props} :visible.sync="visible" :width="width" :scrollable.sync="scrollable">
|
||||
<div class="${prefixCls}">
|
||||
<div class="${prefixCls}-head">
|
||||
<div class="${prefixCls}-head-title">{{{ title }}}</div>
|
||||
</div>
|
||||
<div class="${prefixCls}-body">
|
||||
<div :class="iconTypeCls"><i :class="iconNameCls"></i></div>
|
||||
{{{ body }}}
|
||||
</div>
|
||||
<div class="${prefixCls}-footer">
|
||||
<i-button type="text" size="large" v-if="showCancel" @click="cancel">{{ cancelText }}</i-button>
|
||||
<i-button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</i-button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
`;
|
||||
document.body.appendChild(div);
|
||||
|
||||
const modal = new Vue({
|
||||
el: div,
|
||||
components: { Modal, iButton, Icon },
|
||||
data: Object.assign(_props, {
|
||||
visible: false,
|
||||
width: 416,
|
||||
title: '',
|
||||
body: '',
|
||||
iconType: '',
|
||||
iconName: '',
|
||||
okText: t('i.modal.okText'),
|
||||
cancelText: t('i.modal.cancelText'),
|
||||
showCancel: false,
|
||||
loading: false,
|
||||
buttonLoading: false,
|
||||
scrollable: false
|
||||
}),
|
||||
computed: {
|
||||
iconTypeCls () {
|
||||
return [
|
||||
`${prefixCls}-body-icon`,
|
||||
`${prefixCls}-body-icon-${this.iconType}`
|
||||
];
|
||||
},
|
||||
iconNameCls () {
|
||||
return [
|
||||
'ivu-icon',
|
||||
`ivu-icon-${this.iconName}`
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cancel () {
|
||||
this.visible = false;
|
||||
this.buttonLoading = false;
|
||||
this.onCancel();
|
||||
this.remove();
|
||||
},
|
||||
ok () {
|
||||
if (this.loading) {
|
||||
this.buttonLoading = true;
|
||||
} else {
|
||||
this.visible = false;
|
||||
this.remove();
|
||||
}
|
||||
this.onOk();
|
||||
},
|
||||
remove () {
|
||||
setTimeout(() => {
|
||||
this.destroy();
|
||||
}, 300);
|
||||
},
|
||||
destroy () {
|
||||
this.$destroy();
|
||||
document.body.removeChild(div);
|
||||
this.onRemove();
|
||||
},
|
||||
onOk () {},
|
||||
onCancel () {},
|
||||
onRemove () {}
|
||||
}
|
||||
}).$children[0];
|
||||
|
||||
return {
|
||||
show (props) {
|
||||
modal.$parent.showCancel = props.showCancel;
|
||||
modal.$parent.iconType = props.icon;
|
||||
|
||||
switch (props.icon) {
|
||||
case 'info':
|
||||
modal.$parent.iconName = 'information-circled';
|
||||
break;
|
||||
case 'success':
|
||||
modal.$parent.iconName = 'checkmark-circled';
|
||||
break;
|
||||
case 'warning':
|
||||
modal.$parent.iconName = 'android-alert';
|
||||
break;
|
||||
case 'error':
|
||||
modal.$parent.iconName = 'close-circled';
|
||||
break;
|
||||
case 'confirm':
|
||||
modal.$parent.iconName = 'help-circled';
|
||||
break;
|
||||
}
|
||||
|
||||
if ('width' in props) {
|
||||
modal.$parent.width = props.width;
|
||||
}
|
||||
|
||||
if ('title' in props) {
|
||||
modal.$parent.title = props.title;
|
||||
}
|
||||
|
||||
if ('content' in props) {
|
||||
modal.$parent.body = props.content;
|
||||
}
|
||||
|
||||
if ('okText' in props) {
|
||||
modal.$parent.okText = props.okText;
|
||||
}
|
||||
|
||||
if ('cancelText' in props) {
|
||||
modal.$parent.cancelText = props.cancelText;
|
||||
}
|
||||
|
||||
if ('onCancel' in props) {
|
||||
modal.$parent.onCancel = props.onCancel;
|
||||
}
|
||||
|
||||
if ('onOk' in props) {
|
||||
modal.$parent.onOk = props.onOk;
|
||||
}
|
||||
|
||||
// async for ok
|
||||
if ('loading' in props) {
|
||||
modal.$parent.loading = props.loading;
|
||||
}
|
||||
|
||||
if ('scrollable' in props) {
|
||||
modal.$parent.scrollable = props.scrollable;
|
||||
}
|
||||
|
||||
// notice when component destroy
|
||||
modal.$parent.onRemove = props.onRemove;
|
||||
|
||||
modal.visible = true;
|
||||
},
|
||||
remove () {
|
||||
modal.visible = false;
|
||||
modal.$parent.buttonLoading = false;
|
||||
modal.$parent.remove();
|
||||
},
|
||||
component: modal
|
||||
};
|
||||
};
|
||||
|
||||
export default Modal;
|
|
@ -1,65 +0,0 @@
|
|||
import Modal from './confirm';
|
||||
|
||||
let modalInstance;
|
||||
|
||||
function getModalInstance () {
|
||||
modalInstance = modalInstance || Modal.newInstance({
|
||||
closable: false,
|
||||
maskClosable: false,
|
||||
footerHide: true
|
||||
});
|
||||
|
||||
return modalInstance;
|
||||
}
|
||||
|
||||
function confirm (options) {
|
||||
let instance = getModalInstance();
|
||||
|
||||
options.onRemove = function () {
|
||||
modalInstance = null;
|
||||
};
|
||||
|
||||
instance.show(options);
|
||||
}
|
||||
|
||||
Modal.info = function (props = {}) {
|
||||
props.icon = 'info';
|
||||
props.showCancel = false;
|
||||
return confirm(props);
|
||||
};
|
||||
|
||||
Modal.success = function (props = {}) {
|
||||
props.icon = 'success';
|
||||
props.showCancel = false;
|
||||
return confirm(props);
|
||||
};
|
||||
|
||||
Modal.warning = function (props = {}) {
|
||||
props.icon = 'warning';
|
||||
props.showCancel = false;
|
||||
return confirm(props);
|
||||
};
|
||||
|
||||
Modal.error = function (props = {}) {
|
||||
props.icon = 'error';
|
||||
props.showCancel = false;
|
||||
return confirm(props);
|
||||
};
|
||||
|
||||
Modal.confirm = function (props = {}) {
|
||||
props.icon = 'confirm';
|
||||
props.showCancel = true;
|
||||
return confirm(props);
|
||||
};
|
||||
|
||||
Modal.remove = function () {
|
||||
if (!modalInstance) { // at loading status, remove after Cancel
|
||||
return false;
|
||||
}
|
||||
|
||||
const instance = getModalInstance();
|
||||
|
||||
instance.remove();
|
||||
};
|
||||
|
||||
export default Modal;
|
|
@ -1,235 +0,0 @@
|
|||
<template>
|
||||
<div :class="maskClasses" v-show="visible" @click="mask" transition="fade"></div>
|
||||
<div :class="wrapClasses" @click="handleWrapClick">
|
||||
<div :class="classes" :style="styles" v-show="visible" transition="ease">
|
||||
<div :class="[prefixCls + '-content']">
|
||||
<a :class="[prefixCls + '-close']" v-if="closable" @click="close">
|
||||
<slot name="close">
|
||||
<Icon type="ios-close-empty"></Icon>
|
||||
</slot>
|
||||
</a>
|
||||
<div :class="[prefixCls + '-header']" v-if="showHead" v-el:head><slot name="header"><div :class="[prefixCls + '-header-inner']">{{ title }}</div></slot></div>
|
||||
<div :class="[prefixCls + '-body']"><slot></slot></div>
|
||||
<div :class="[prefixCls + '-footer']" v-if="!footerHide">
|
||||
<slot name="footer">
|
||||
<i-button type="text" size="large" @click="cancel">{{ cancelText }}</i-button>
|
||||
<i-button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</i-button>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Icon from '../icon';
|
||||
import iButton from '../button/button.vue';
|
||||
import { getScrollBarSize } from '../../utils/assist';
|
||||
import { t } from '../../locale';
|
||||
|
||||
const prefixCls = 'ivu-modal';
|
||||
|
||||
export default {
|
||||
components: { Icon, iButton },
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
closable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
title: {
|
||||
type: String
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: 520
|
||||
},
|
||||
okText: {
|
||||
type: String,
|
||||
default () {
|
||||
return t('i.modal.okText');
|
||||
}
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default () {
|
||||
return t('i.modal.cancelText');
|
||||
}
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
style: {
|
||||
type: Object
|
||||
},
|
||||
className: {
|
||||
type: String
|
||||
},
|
||||
// for instance
|
||||
footerHide: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
scrollable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
wrapShow: false,
|
||||
showHead: true,
|
||||
buttonLoading: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}-wrap`,
|
||||
{
|
||||
[`${prefixCls}-hidden`]: !this.wrapShow,
|
||||
[`${this.className}`]: !!this.className
|
||||
}
|
||||
];
|
||||
},
|
||||
maskClasses () {
|
||||
return `${prefixCls}-mask`;
|
||||
},
|
||||
classes () {
|
||||
return `${prefixCls}`;
|
||||
},
|
||||
styles () {
|
||||
let style = {};
|
||||
|
||||
const styleWidth = {
|
||||
width: `${this.width}px`
|
||||
};
|
||||
|
||||
const customStyle = this.style ? this.style : {};
|
||||
|
||||
Object.assign(style, styleWidth, customStyle);
|
||||
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.visible = false;
|
||||
this.$emit('on-cancel');
|
||||
},
|
||||
mask () {
|
||||
if (this.maskClosable) {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
handleWrapClick (event) {
|
||||
// use indexOf,do not use === ,because ivu-modal-wrap can have other custom className
|
||||
const className = event.target.getAttribute('class');
|
||||
if (className && className.indexOf(`${prefixCls}-wrap`) > -1) this.mask();
|
||||
},
|
||||
cancel () {
|
||||
this.close();
|
||||
},
|
||||
ok () {
|
||||
if (this.loading) {
|
||||
this.buttonLoading = true;
|
||||
} else {
|
||||
this.visible = false;
|
||||
}
|
||||
this.$emit('on-ok');
|
||||
},
|
||||
EscClose (e) {
|
||||
if (this.visible && this.closable) {
|
||||
if (e.keyCode === 27) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
},
|
||||
checkScrollBar () {
|
||||
let fullWindowWidth = window.innerWidth;
|
||||
if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
|
||||
const documentElementRect = document.documentElement.getBoundingClientRect();
|
||||
fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
|
||||
}
|
||||
this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
|
||||
if (this.bodyIsOverflowing) {
|
||||
this.scrollBarWidth = getScrollBarSize();
|
||||
}
|
||||
},
|
||||
setScrollBar () {
|
||||
if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
|
||||
document.body.style.paddingRight = `${this.scrollBarWidth}px`;
|
||||
}
|
||||
},
|
||||
resetScrollBar () {
|
||||
document.body.style.paddingRight = '';
|
||||
},
|
||||
addScrollEffect () {
|
||||
this.checkScrollBar();
|
||||
this.setScrollBar();
|
||||
document.body.style.overflow = 'hidden';
|
||||
},
|
||||
removeScrollEffect() {
|
||||
document.body.style.overflow = '';
|
||||
this.resetScrollBar();
|
||||
}
|
||||
},
|
||||
ready () {
|
||||
if (this.visible) {
|
||||
this.wrapShow = true;
|
||||
}
|
||||
|
||||
let showHead = true;
|
||||
|
||||
if (this.$els.head.innerHTML == `<div class="${prefixCls}-header-inner"></div>` && !this.title) {
|
||||
showHead = false;
|
||||
}
|
||||
|
||||
this.showHead = showHead;
|
||||
|
||||
// ESC close
|
||||
document.addEventListener('keydown', this.EscClose);
|
||||
},
|
||||
beforeDestroy () {
|
||||
document.removeEventListener('keydown', this.EscClose);
|
||||
this.removeScrollEffect();
|
||||
},
|
||||
watch: {
|
||||
visible (val) {
|
||||
if (val === false) {
|
||||
this.buttonLoading = false;
|
||||
this.timer = setTimeout(() => {
|
||||
this.wrapShow = false;
|
||||
this.removeScrollEffect();
|
||||
}, 300);
|
||||
} else {
|
||||
if (this.timer) clearTimeout(this.timer);
|
||||
this.wrapShow = true;
|
||||
if (!this.scrollable) {
|
||||
this.addScrollEffect();
|
||||
}
|
||||
}
|
||||
},
|
||||
loading (val) {
|
||||
if (!val) {
|
||||
this.buttonLoading = false;
|
||||
}
|
||||
},
|
||||
scrollable (val) {
|
||||
if (!val) {
|
||||
this.addScrollEffect();
|
||||
} else {
|
||||
this.removeScrollEffect();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,117 +0,0 @@
|
|||
import Notification from '../base/notification';
|
||||
|
||||
const prefixCls = 'ivu-notice';
|
||||
const iconPrefixCls = 'ivu-icon';
|
||||
const prefixKey = 'ivu_notice_key_';
|
||||
|
||||
let top = 24;
|
||||
let defaultDuration = 4.5;
|
||||
let noticeInstance;
|
||||
let key = 1;
|
||||
|
||||
const iconTypes = {
|
||||
'info': 'information-circled',
|
||||
'success': 'checkmark-circled',
|
||||
'warning': 'android-alert',
|
||||
'error': 'close-circled'
|
||||
};
|
||||
|
||||
function getNoticeInstance () {
|
||||
noticeInstance = noticeInstance || Notification.newInstance({
|
||||
prefixCls: prefixCls,
|
||||
style: {
|
||||
top: `${top}px`,
|
||||
right: 0
|
||||
}
|
||||
});
|
||||
|
||||
return noticeInstance;
|
||||
}
|
||||
|
||||
function notice (type, options) {
|
||||
const title = options.title || '';
|
||||
const desc = options.desc || '';
|
||||
const noticeKey = options.key || `${prefixKey}${key}`;
|
||||
const onClose = options.onClose || function () {};
|
||||
// todo const btn = options.btn || null;
|
||||
const duration = (options.duration === 0) ? 0 : options.duration || defaultDuration;
|
||||
|
||||
key++;
|
||||
|
||||
let instance = getNoticeInstance();
|
||||
|
||||
let content;
|
||||
|
||||
const with_desc = desc === '' ? '' : ` ${prefixCls}-with-desc`;
|
||||
|
||||
if (type == 'normal') {
|
||||
content = `
|
||||
<div class="${prefixCls}-custom-content ${prefixCls}-with-normal${with_desc}">
|
||||
<div class="${prefixCls}-title">${title}</div>
|
||||
<div class="${prefixCls}-desc">${desc}</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
const iconType = iconTypes[type];
|
||||
content = `
|
||||
<div class="${prefixCls}-custom-content ${prefixCls}-with-icon ${prefixCls}-with-${type}${with_desc}">
|
||||
<span class="${prefixCls}-icon ${prefixCls}-icon-${type}">
|
||||
<i class="${iconPrefixCls} ${iconPrefixCls}-${iconType}"></i>
|
||||
</span>
|
||||
<div class="${prefixCls}-title">${title}</div>
|
||||
<div class="${prefixCls}-desc">${desc}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
instance.notice({
|
||||
key: noticeKey.toString(),
|
||||
duration: duration,
|
||||
style: {},
|
||||
transitionName: 'move-notice',
|
||||
content: content,
|
||||
onClose: onClose,
|
||||
closable: true
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
open (options) {
|
||||
return notice('normal', options);
|
||||
},
|
||||
info (options) {
|
||||
return notice('info', options);
|
||||
},
|
||||
success (options) {
|
||||
return notice('success', options);
|
||||
},
|
||||
warning (options) {
|
||||
return notice('warning', options);
|
||||
},
|
||||
error (options) {
|
||||
return notice('error', options);
|
||||
},
|
||||
config (options) {
|
||||
if (options.top) {
|
||||
top = options.top;
|
||||
}
|
||||
if (options.duration || options.duration === 0) {
|
||||
defaultDuration = options.duration;
|
||||
}
|
||||
},
|
||||
close (key) {
|
||||
if (key) {
|
||||
key = key.toString();
|
||||
if (noticeInstance) {
|
||||
noticeInstance.remove(key);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
destroy () {
|
||||
let instance = getNoticeInstance();
|
||||
noticeInstance = null;
|
||||
instance.destroy();
|
||||
}
|
||||
};
|
|
@ -1,2 +0,0 @@
|
|||
import Page from './page.vue';
|
||||
export default Page;
|
|
@ -1,89 +0,0 @@
|
|||
<template>
|
||||
<div v-if="showSizer || showElevator" :class="optsClasses">
|
||||
<div v-if="showSizer" :class="sizerClasses">
|
||||
<i-select :model.sync="pageSize" :size="size" @on-change="changeSize">
|
||||
<i-option v-for="item in pageSizeOpts" :value="item" style="text-align:center;">{{ item }} {{ t('i.page.page') }}</i-option>
|
||||
</i-select>
|
||||
</div>
|
||||
<div v-if="showElevator" :class="ElevatorClasses">
|
||||
{{ t('i.page.goto') }}
|
||||
<input type="text" :value="_current" @keyup.enter="changePage">
|
||||
{{ t('i.page.p') }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import iSelect from '../../components/select/select.vue';
|
||||
import iOption from '../../components/select/option.vue';
|
||||
import Locale from '../../mixins/locale';
|
||||
|
||||
const prefixCls = 'ivu-page';
|
||||
|
||||
function isValueNumber (value) {
|
||||
return (/^[1-9][0-9]*$/).test(value + '');
|
||||
}
|
||||
|
||||
export default {
|
||||
mixins: [ Locale ],
|
||||
components: { iSelect, iOption },
|
||||
props: {
|
||||
pageSizeOpts: Array,
|
||||
showSizer: Boolean,
|
||||
showElevator: Boolean,
|
||||
current: Number,
|
||||
_current: Number,
|
||||
pageSize: Number,
|
||||
allPages: Number,
|
||||
isSmall: Boolean
|
||||
},
|
||||
computed: {
|
||||
size () {
|
||||
return this.isSmall ? 'small' : 'default';
|
||||
},
|
||||
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>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue