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