Commit c571d9ec2bb39957e811dff3d014c44a821728e0

Authored by 梁灏
1 parent eaaea36a

add a dialog to fixed $Modal can not use temporarily

add a dialog to fixed $Modal can not use temporarily
src/components/dialog/confirm.js 0 → 100644
  1 +import Vue from 'vue';
  2 +import Modal from './dialog.vue';
  3 +import Icon from '../icon/icon.vue';
  4 +import iButton from '../button/button.vue';
  5 +import { camelcaseToHyphen } from '../../utils/assist';
  6 +
  7 +const prefixCls = 'ivu-modal-confirm';
  8 +
  9 +Modal.newInstance = properties => {
  10 + const _props = properties || {};
  11 +
  12 + let props = '';
  13 + Object.keys(_props).forEach(prop => {
  14 + props += ' :' + camelcaseToHyphen(prop) + '=' + prop;
  15 + });
  16 +
  17 + const div = document.createElement('div');
  18 + div.innerHTML = `
  19 + <Modal${props} :visible.sync="visible" :width="width">
  20 + <div class="${prefixCls}">
  21 + <div class="${prefixCls}-head">
  22 + <div :class="iconTypeCls"><i :class="iconNameCls"></i></div>
  23 + <div class="${prefixCls}-head-title">{{{ title }}}</div>
  24 + </div>
  25 + <div class="${prefixCls}-body">
  26 + {{{ body }}}
  27 + </div>
  28 + <div class="${prefixCls}-footer">
  29 + <i-button type="ghost" size="large" v-if="showCancel" @click="cancel">{{ cancelText }}</i-button>
  30 + <i-button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</i-button>
  31 + </div>
  32 + </div>
  33 + </Modal>
  34 + `;
  35 + document.body.appendChild(div);
  36 +
  37 + const modal = new Vue({
  38 + el: div,
  39 + components: { Modal, iButton, Icon },
  40 + data: Object.assign(_props, {
  41 + visible: false,
  42 + width: 416,
  43 + title: '',
  44 + body: '',
  45 + iconType: '',
  46 + iconName: '',
  47 + okText: '确定',
  48 + cancelText: '取消',
  49 + showCancel: false,
  50 + loading: false,
  51 + buttonLoading: false
  52 + }),
  53 + computed: {
  54 + iconTypeCls () {
  55 + return [
  56 + `${prefixCls}-head-icon`,
  57 + `${prefixCls}-head-icon-${this.iconType}`
  58 + ]
  59 + },
  60 + iconNameCls () {
  61 + return [
  62 + 'ivu-icon',
  63 + `ivu-icon-${this.iconName}`
  64 + ]
  65 + }
  66 + },
  67 + methods: {
  68 + cancel () {
  69 + this.visible = false;
  70 + this.buttonLoading = false;
  71 + this.onCancel();
  72 + this.remove();
  73 + },
  74 + ok () {
  75 + if (this.loading) {
  76 + this.buttonLoading = true;
  77 + } else {
  78 + this.visible = false;
  79 + this.remove();
  80 + }
  81 + this.onOk();
  82 + },
  83 + remove () {
  84 + setTimeout(() => {
  85 + this.destroy();
  86 + }, 300);
  87 + },
  88 + destroy () {
  89 + this.$destroy();
  90 + document.body.removeChild(div);
  91 + this.onRemove();
  92 + },
  93 + onOk () {},
  94 + onCancel () {},
  95 + onRemove () {}
  96 + }
  97 + }).$children[0];
  98 +
  99 + return {
  100 + show (props) {
  101 + modal.$parent.showCancel = props.showCancel;
  102 + modal.$parent.iconType = props.icon;
  103 +
  104 + switch (props.icon) {
  105 + case 'info':
  106 + modal.$parent.iconName = 'information-circled';
  107 + break;
  108 + case 'success':
  109 + modal.$parent.iconName = 'checkmark-circled';
  110 + break;
  111 + case 'warning':
  112 + modal.$parent.iconName = 'android-alert';
  113 + break;
  114 + case 'error':
  115 + modal.$parent.iconName = 'close-circled';
  116 + break;
  117 + case 'confirm':
  118 + modal.$parent.iconName = 'help-circled';
  119 + break;
  120 + }
  121 +
  122 + if ('width' in props) {
  123 + modal.$parent.width = props.width;
  124 + }
  125 +
  126 + if ('title' in props) {
  127 + modal.$parent.title = props.title;
  128 + }
  129 +
  130 + if ('content' in props) {
  131 + modal.$parent.body = props.content;
  132 + }
  133 +
  134 + if ('okText' in props) {
  135 + modal.$parent.okText = props.okText;
  136 + }
  137 +
  138 + if ('cancelText' in props) {
  139 + modal.$parent.cancelText = props.cancelText;
  140 + }
  141 +
  142 + if ('onCancel' in props) {
  143 + modal.$parent.onCancel = props.onCancel;
  144 + }
  145 +
  146 + if ('onOk' in props) {
  147 + modal.$parent.onOk = props.onOk;
  148 + }
  149 +
  150 + // async for ok
  151 + if ('loading' in props) {
  152 + modal.$parent.loading = props.loading;
  153 + }
  154 +
  155 + // notice when component destroy
  156 + modal.$parent.onRemove = props.onRemove;
  157 +
  158 + modal.visible = true;
  159 + },
  160 + remove () {
  161 + modal.visible = false;
  162 + modal.$parent.buttonLoading = false;
  163 + modal.$parent.remove();
  164 + },
  165 + component: modal
  166 + }
  167 +};
  168 +
  169 +export default Modal;
0 170 \ No newline at end of file
... ...
src/components/dialog/dialog.vue 0 → 100644
  1 +<template>
  2 + <div :class="wrapClasses">
  3 + <div :class="maskClasses" v-show="visible" @click="mask" transition="fade"></div>
  4 + <div :class="classes" :style="styles" v-show="visible" transition="ease">
  5 + <div :class="[prefixCls + '-content']">
  6 + <a :class="[prefixCls + '-close']" v-if="closable" @click="close">
  7 + <slot name="close">
  8 + <Icon type="ios-close-empty"></Icon>
  9 + </slot>
  10 + </a>
  11 + <div :class="[prefixCls + '-header']" v-if="showHead" v-el:head><slot name="header"><div :class="[prefixCls + '-header-inner']">{{ title }}</div></slot></div>
  12 + <div :class="[prefixCls + '-body']"><slot></slot></div>
  13 + <div :class="[prefixCls + '-footer']" v-if="!footerHide">
  14 + <slot name="footer">
  15 + <i-button type="ghost" size="large" @click="cancel">{{ cancelText }}</i-button>
  16 + <i-button type="primary" size="large" :loading="buttonLoading" @click="ok">{{ okText }}</i-button>
  17 + </slot>
  18 + </div>
  19 + </div>
  20 + </div>
  21 + </div>
  22 +</template>
  23 +<script>
  24 + import Icon from '../icon';
  25 + import iButton from '../button/button.vue';
  26 + import { getScrollBarSize } from '../../utils/assist';
  27 +
  28 + const prefixCls = 'ivu-modal';
  29 +
  30 + export default {
  31 + components: { Icon, iButton },
  32 + props: {
  33 + visible: {
  34 + type: Boolean,
  35 + default: false
  36 + },
  37 + closable: {
  38 + type: Boolean,
  39 + default: true
  40 + },
  41 + maskClosable: {
  42 + type: Boolean,
  43 + default: true
  44 + },
  45 + title: {
  46 + type: String
  47 + },
  48 + width: {
  49 + type: [Number, String],
  50 + default: 520
  51 + },
  52 + okText: {
  53 + type: String,
  54 + default: '确定'
  55 + },
  56 + cancelText: {
  57 + type: String,
  58 + default: '取消'
  59 + },
  60 + loading: {
  61 + type: Boolean,
  62 + default: false
  63 + },
  64 + style: {
  65 + type: Object
  66 + },
  67 + className: {
  68 + type: String
  69 + },
  70 + // for instance
  71 + footerHide: {
  72 + type: Boolean,
  73 + default: false
  74 + }
  75 + },
  76 + data () {
  77 + return {
  78 + prefixCls: prefixCls,
  79 + wrapShow: false,
  80 + showHead: true,
  81 + buttonLoading: false
  82 + }
  83 + },
  84 + computed: {
  85 + wrapClasses () {
  86 + return [
  87 + `${prefixCls}-wrap`,
  88 + {
  89 + [`${prefixCls}-hidden`]: !this.wrapShow,
  90 + [`${this.className}`]: !!this.className
  91 + }
  92 + ]
  93 + },
  94 + maskClasses () {
  95 + return `${prefixCls}-mask`;
  96 + },
  97 + classes () {
  98 + return `${prefixCls}`;
  99 + },
  100 + styles () {
  101 + let style = {};
  102 +
  103 + const styleWidth = {
  104 + width: `${this.width}px`
  105 + };
  106 +
  107 + const customStyle = !!this.style ? this.style : {};
  108 +
  109 + Object.assign(style, styleWidth, customStyle);
  110 +
  111 + return style;
  112 + }
  113 + },
  114 + methods: {
  115 + close () {
  116 + this.visible = false;
  117 + this.$emit('on-cancel');
  118 + },
  119 + mask () {
  120 + if (this.maskClosable) {
  121 + this.close();
  122 + }
  123 + },
  124 + cancel () {
  125 + this.close();
  126 + },
  127 + ok () {
  128 + if (this.loading) {
  129 + this.buttonLoading = true;
  130 + } else {
  131 + this.visible = false;
  132 + }
  133 + this.$emit('on-ok');
  134 + },
  135 + EscClose (e) {
  136 + if (this.visible && this.closable) {
  137 + if (e.keyCode === 27) {
  138 + this.close()
  139 + }
  140 + }
  141 + },
  142 + checkScrollBar () {
  143 + let fullWindowWidth = window.innerWidth;
  144 + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
  145 + const documentElementRect = document.documentElement.getBoundingClientRect();
  146 + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
  147 + }
  148 + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
  149 + if (this.bodyIsOverflowing) {
  150 + this.scrollBarWidth = getScrollBarSize();
  151 + }
  152 + },
  153 + setScrollBar () {
  154 + if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
  155 + document.body.style.paddingRight = `${this.scrollBarWidth}px`;
  156 + }
  157 + },
  158 + resetScrollBar () {
  159 + document.body.style.paddingRight = '';
  160 + },
  161 + addScrollEffect () {
  162 + this.checkScrollBar();
  163 + this.setScrollBar();
  164 + document.body.style.overflow = 'hidden';
  165 + },
  166 + removeScrollEffect() {
  167 + document.body.style.overflow = '';
  168 + this.resetScrollBar();
  169 + }
  170 + },
  171 + ready () {
  172 + if (this.visible) {
  173 + this.wrapShow = true;
  174 + }
  175 +
  176 + let showHead = true;
  177 +
  178 + if (this.$els.head.innerHTML == `<div class="${prefixCls}-header-inner"></div>` && !this.title) {
  179 + showHead = false;
  180 + }
  181 +
  182 + this.showHead = showHead;
  183 +
  184 + // ESC close
  185 + document.addEventListener('keydown', this.EscClose);
  186 + },
  187 + beforeDestroy () {
  188 + document.removeEventListener('keydown', this.EscClose);
  189 + },
  190 + watch: {
  191 + visible (val) {
  192 + if (val === false) {
  193 + this.buttonLoading = false;
  194 + setTimeout(() => {
  195 + this.wrapShow = false;
  196 + }, 300);
  197 + this.removeScrollEffect();
  198 + } else {
  199 + this.wrapShow = true;
  200 + this.addScrollEffect();
  201 + }
  202 + },
  203 + loading (val) {
  204 + if (!val) {
  205 + this.buttonLoading = false;
  206 + }
  207 + }
  208 + }
  209 + }
  210 +</script>
... ...
src/components/dialog/index.js 0 → 100644
  1 +import Modal from './confirm';
  2 +
  3 +let modalInstance;
  4 +
  5 +function getModalInstance () {
  6 + modalInstance = modalInstance || Modal.newInstance({
  7 + closable: false,
  8 + maskClosable: false,
  9 + footerHide: true
  10 + });
  11 +
  12 + return modalInstance;
  13 +}
  14 +
  15 +function confirm (options) {
  16 + let instance = getModalInstance();
  17 +
  18 + options.onRemove = function () {
  19 + modalInstance = null;
  20 + };
  21 +
  22 + instance.show(options);
  23 +}
  24 +
  25 +export default {
  26 + info (props = {}) {
  27 + props.icon = 'info';
  28 + props.showCancel = false;
  29 + return confirm(props);
  30 + },
  31 + success (props = {}) {
  32 + props.icon = 'success';
  33 + props.showCancel = false;
  34 + return confirm(props);
  35 + },
  36 + warning (props = {}) {
  37 + props.icon = 'warning';
  38 + props.showCancel = false;
  39 + return confirm(props);
  40 + },
  41 + error (props = {}) {
  42 + props.icon = 'error';
  43 + props.showCancel = false;
  44 + return confirm(props);
  45 + },
  46 + confirm (props = {}) {
  47 + props.icon = 'confirm';
  48 + props.showCancel = true;
  49 + return confirm(props);
  50 + },
  51 + remove () {
  52 + if (!modalInstance) { // at loading status, remove after Cancel
  53 + return false;
  54 + }
  55 +
  56 + const instance = getModalInstance();
  57 +
  58 + instance.remove();
  59 + }
  60 +}
0 61 \ No newline at end of file
... ...
src/index.js
... ... @@ -8,6 +8,7 @@ import Card from &#39;./components/card&#39;;
8 8 import Checkbox from './components/checkbox';
9 9 import Circle from './components/circle';
10 10 import Collapse from './components/collapse';
  11 +import Dialog from './components/dialog';
11 12 import Icon from './components/icon';
12 13 import Input from './components/input';
13 14 import InputNumber from './components/input-number';
... ... @@ -79,7 +80,7 @@ const install = function (Vue) {
79 80  
80 81 Vue.prototype.$Loading = LoadingBar;
81 82 Vue.prototype.$Message = Message;
82   - Vue.prototype.$Modal = Modal;
  83 + Vue.prototype.$Modal = Dialog;
83 84 Vue.prototype.$Notice = Notice;
84 85 };
85 86  
... ...
src/styles/components/select.less
... ... @@ -46,7 +46,7 @@
46 46 right: 8px;
47 47 line-height: 1;
48 48 margin-top: -6px;
49   - color: @border-color-base;
  49 + color: @subsidiary-color;
50 50 .transition(all @transition-time @ease-in-out);
51 51 }
52 52  
... ...
test/main.js
... ... @@ -4,8 +4,10 @@
4 4 import Vue from 'vue';
5 5 import VueRouter from 'vue-router';
6 6 import App from './app.vue';
  7 +import iView from '../src/index';
7 8  
8 9 Vue.use(VueRouter);
  10 +Vue.use(iView);
9 11  
10 12 // 开启debug模式
11 13 Vue.config.debug = true;
... ...
test/routers/message.vue
1 1 <template>
2   - <i-button @click="mInfo">m信息</i-button>
3   - <i-button @click="open">打开</i-button>
4   - <i-button @click="info2">消息2</i-button>
5   - <i-button @click="info">消息</i-button>
6   - <i-button @click="success">成功</i-button>
7   - <i-button @click="warning">警告</i-button>
8   - <i-button @click="error">错误</i-button>
9   - <i-button @click="modal1 = true"></i-button>
10   - <Modal
11   - :visible.sync="modal1"
12   - title="普通的Modal对话框标题">
13   - <p>对话框内容</p>
14   - <p>对话框内容</p>
15   - <p>对话框内容</p>
16   - </Modal>
  2 + <i-button @click="instance('info')">消息</i-button>
  3 + <i-button @click="instance('success')">成功</i-button>
  4 + <i-button @click="instance('warning')">警告</i-button>
  5 + <i-button @click="instance('error')">错误</i-button>
17 6 </template>
18 7 <script>
19   - import { Message, Button, Alert, Card, Notice, iButton, Modal } from 'iview';
20   -
21 8 export default {
22   - components: {
23   - Message,
24   - iButton,
25   - Alert,
26   - Card,
27   - Notice,
28   - iButton,
29   - Modal
30   - },
31   - props: {
32   -
33   - },
34   - data () {
35   - return {
36   - modal1: false
37   - }
38   - },
39   - computed: {
40   -
41   - },
42 9 methods: {
43   - open () {
44   - Notice.open({
45   - duration: 1000,
46   - title: '这是通知标题',
47   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描述这里是通知描述'
48   - })
49   - },
50   - info () {
51   - Notice.info({
52   - duration: 1000,
53   - title: '这是通知标题',
54   -// desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描述这里是通知描述'
55   - });
56   - },
57   - info2 () {
58   - Notice.open({
59   - duration: 1000,
60   - title: '这是通知标题这是通知标题这是通知标题这是通知标题这是通知标题这是通知标题'
61   - });
62   - Notice.info({
63   - duration: 1000,
64   - title: '这是通知标题这是通知标题这是通知标题这是通知标题这是通知标题这是通知标题'
65   - });
66   - Notice.open({
67   - duration: 1000,
68   - title: '这是通知标题这是通知标题这是通知标题这是通知标题这是通知标题这是通知标题',
69   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描'
70   - });
71   - Notice.info({
72   - duration: 1000,
73   - title: '这是通知标题这是通知标题这是通知标题这是通知标题这是通知标题这是通知标题',
74   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描'
75   - });
76   - Notice.success({
77   - duration: 1000,
78   - title: '这是通知标题',
79   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描'
80   - });
81   - Notice.warning({
82   - duration: 1000,
83   - title: '这是通知标题',
84   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描'
85   - });
86   - Notice.error({
87   - duration: 1000,
88   - title: '这是通知标题',
89   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描'
90   - });
91   - },
92   - success () {
93   - Notice.success({
94   - duration: 1000,
95   - title: '这是通知标题',
96   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描'
97   - });
98   - },
99   - warning () {
100   - Notice.warning({
101   - duration: 1000,
102   - title: '这是通知标题',
103   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描'
104   - });
105   - },
106   - error () {
107   - Notice.error({
108   - duration: 1000,
109   - title: '这是通知标题',
110   - desc: '这里是通知描述这里,是通知描述这里是通知描述这里,是通知描述这里,是通知描述这里是通知描'
111   - });
112   - },
113   - mInfo () {
114   - Message.info('飞机飞士大夫', 1000);
  10 + instance (type) {
  11 + const title = '对话框的标题';
  12 + const content = '<p>一些对话框内容</p><p>一些对话框内容</p>';
  13 + switch (type) {
  14 + case 'info':
  15 + this.$Modal.info({
  16 + title: title,
  17 + content: content
  18 + });
  19 + break;
  20 + case 'success':
  21 + this.$Modal.success({
  22 + title: title,
  23 + content: content
  24 + });
  25 + break;
  26 + case 'warning':
  27 + this.$Modal.warning({
  28 + title: title,
  29 + content: content
  30 + });
  31 + break;
  32 + case 'error':
  33 + this.$Modal.error({
  34 + title: title,
  35 + content: content
  36 + });
  37 + break;
  38 + }
115 39 }
116   - },
117   - ready () {
118   -// Message.config({
119   -// top: 50,
120   -// duration: 8
121   -// });
122 40 }
123 41 }
124 42 </script>
... ...
test/routers/slider.vue
1 1 <template>
2   - <div style="width: 400px;margin:100px;">
3   - {{ value }}
4   - <Slider @on-change="change" :step="15"></Slider>
5   - <Slider :value="40" :tip-format="format"></Slider>
6   - <Slider :value.sync="value" show-input show-stops range @on-change="change" :step="13"></Slider>
  2 + <div style="width: 140px;margin:100px;">
  3 + <!--{{ value }}-->
  4 + <!--<Slider @on-change="change" :step="15"></Slider>-->
  5 + <!--<Slider :value="40" :tip-format="format"></Slider>-->
  6 + <!--<Slider :value.sync="value" show-input show-stops range @on-change="change" :step="13"></Slider>-->
7 7 <!--<Slider :max="10"></Slider>-->
8 8 <!--<Slider :step="13"></Slider>-->
9 9 <!--<Slider :step="13" :max="60"></Slider>-->
10   - <Icon type="checkmark-circled" size="40" color="#f60"></Icon>
11   - <p>附近的首付款是东方红看就是</p>
12   - <div class="ivu-article">
13   - <a href="http://www.iviewui.com" target="_blank">iView</a>
14   - </div>
  10 + <!--<Icon type="checkmark-circled" size="40" color="#f60"></Icon>-->
  11 + <!--<p>附近的首付款是东方红看就是</p>-->
  12 + <!--<div class="ivu-article">-->
  13 + <!--<a href="http://www.iviewui.com" target="_blank">iView</a>-->
  14 + <!--</div>-->
  15 + <Slider :value="75"></Slider>
  16 + <!--<Slider :value="[20, 50]" range></Slider>-->
15 17 </div>
16 18 </template>
17 19 <script>
... ...