123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- <template>
- <transition name="msgbox-fade">
- <div
- class="el-message-box__wrapper"
- tabindex="-1"
- v-show="visible"
- @click.self="handleWrapperClick"
- role="dialog"
- aria-modal="true"
- :aria-label="title || 'dialog'">
- <div class="el-message-box" :class="[customClass, center && 'el-message-box--center']">
- <div class="el-message-box__header" v-if="title !== null">
- <div class="el-message-box__title">
- <div
- :class="['el-message-box__status', icon]"
- v-if="icon && center">
- </div>
- <span>{{ title }}</span>
- </div>
- <button
- type="button"
- class="el-message-box__headerbtn"
- aria-label="Close"
- v-if="showClose"
- @click="handleAction(distinguishCancelAndClose ? 'close' : 'cancel')"
- @keydown.enter="handleAction(distinguishCancelAndClose ? 'close' : 'cancel')">
- <i class="el-message-box__close el-icon-close"></i>
- </button>
- </div>
- <div class="el-message-box__content">
- <div class="el-message-box__container">
- <div
- :class="['el-message-box__status', icon]"
- v-if="icon && !center && message !== ''">
- </div>
- <div class="el-message-box__message" v-if="message !== ''">
- <slot>
- <p v-if="!dangerouslyUseHTMLString">{{ message }}</p>
- <p v-else v-html="message"></p>
- </slot>
- </div>
- </div>
- <div class="el-message-box__input" v-show="showInput">
- <el-input
- v-model="inputValue"
- :type="inputType"
- @keydown.enter.native="handleInputEnter"
- :placeholder="inputPlaceholder"
- ref="input"></el-input>
- <div class="el-message-box__errormsg" :style="{ visibility: !!editorErrorMessage ? 'visible' : 'hidden' }">{{ editorErrorMessage }}</div>
- </div>
- </div>
- <div class="el-message-box__btns">
- <el-button
- :loading="cancelButtonLoading"
- :class="[ cancelButtonClasses ]"
- v-if="showCancelButton"
- :round="roundButton"
- size="small"
- @click.native="handleAction('cancel')"
- @keydown.enter="handleAction('cancel')">
- {{ cancelButtonText || t('el.messagebox.cancel') }}
- </el-button>
- <el-button
- :loading="confirmButtonLoading"
- ref="confirm"
- :class="[ confirmButtonClasses ]"
- v-show="showConfirmButton"
- :round="roundButton"
- size="small"
- @click.native="handleAction('confirm')"
- @keydown.enter="handleAction('confirm')">
- {{ confirmButtonText || t('el.messagebox.confirm') }}
- </el-button>
- </div>
- </div>
- </div>
- </transition>
- </template>
- <script type="text/babel">
- import Popup from 'element-ui/src/utils/popup';
- import Locale from 'element-ui/src/mixins/locale';
- import ElInput from 'element-ui/packages/input';
- import ElButton from 'element-ui/packages/button';
- import { addClass, removeClass } from 'element-ui/src/utils/dom';
- import { t } from 'element-ui/src/locale';
- import Dialog from 'element-ui/src/utils/aria-dialog';
- let messageBox;
- let typeMap = {
- success: 'success',
- info: 'info',
- warning: 'warning',
- error: 'error'
- };
- export default {
- mixins: [Popup, Locale],
- props: {
- modal: {
- default: true
- },
- lockScroll: {
- default: true
- },
- showClose: {
- type: Boolean,
- default: true
- },
- closeOnClickModal: {
- default: true
- },
- closeOnPressEscape: {
- default: true
- },
- closeOnHashChange: {
- default: true
- },
- center: {
- default: false,
- type: Boolean
- },
- roundButton: {
- default: false,
- type: Boolean
- }
- },
- components: {
- ElInput,
- ElButton
- },
- computed: {
- icon() {
- const { type, iconClass } = this;
- return iconClass || (type && typeMap[type] ? `el-icon-${ typeMap[type] }` : '');
- },
- confirmButtonClasses() {
- return `el-button--primary ${ this.confirmButtonClass }`;
- },
- cancelButtonClasses() {
- return `${ this.cancelButtonClass }`;
- }
- },
- methods: {
- getSafeClose() {
- const currentId = this.uid;
- return () => {
- this.$nextTick(() => {
- if (currentId === this.uid) this.doClose();
- });
- };
- },
- doClose() {
- if (!this.visible) return;
- this.visible = false;
- this._closing = true;
- this.onClose && this.onClose();
- messageBox.closeDialog(); // 解绑
- if (this.lockScroll) {
- setTimeout(this.restoreBodyStyle, 200);
- }
- this.opened = false;
- this.doAfterClose();
- setTimeout(() => {
- if (this.action) this.callback(this.action, this);
- });
- },
- handleWrapperClick() {
- if (this.closeOnClickModal) {
- this.handleAction(this.distinguishCancelAndClose ? 'close' : 'cancel');
- }
- },
- handleInputEnter() {
- if (this.inputType !== 'textarea') {
- return this.handleAction('confirm');
- }
- },
- handleAction(action) {
- if (this.$type === 'prompt' && action === 'confirm' && !this.validate()) {
- return;
- }
- this.action = action;
- if (typeof this.beforeClose === 'function') {
- this.close = this.getSafeClose();
- this.beforeClose(action, this, this.close);
- } else {
- this.doClose();
- }
- },
- validate() {
- if (this.$type === 'prompt') {
- const inputPattern = this.inputPattern;
- if (inputPattern && !inputPattern.test(this.inputValue || '')) {
- this.editorErrorMessage = this.inputErrorMessage || t('el.messagebox.error');
- addClass(this.getInputElement(), 'invalid');
- return false;
- }
- const inputValidator = this.inputValidator;
- if (typeof inputValidator === 'function') {
- const validateResult = inputValidator(this.inputValue);
- if (validateResult === false) {
- this.editorErrorMessage = this.inputErrorMessage || t('el.messagebox.error');
- addClass(this.getInputElement(), 'invalid');
- return false;
- }
- if (typeof validateResult === 'string') {
- this.editorErrorMessage = validateResult;
- addClass(this.getInputElement(), 'invalid');
- return false;
- }
- }
- }
- this.editorErrorMessage = '';
- removeClass(this.getInputElement(), 'invalid');
- return true;
- },
- getFirstFocus() {
- const btn = this.$el.querySelector('.el-message-box__btns .el-button');
- const title = this.$el.querySelector('.el-message-box__btns .el-message-box__title');
- return btn || title;
- },
- getInputElement() {
- const inputRefs = this.$refs.input.$refs;
- return inputRefs.input || inputRefs.textarea;
- },
- handleClose() {
- this.handleAction('close');
- }
- },
- watch: {
- inputValue: {
- immediate: true,
- handler(val) {
- this.$nextTick(_ => {
- if (this.$type === 'prompt' && val !== null) {
- this.validate();
- }
- });
- }
- },
- visible(val) {
- if (val) {
- this.uid++;
- if (this.$type === 'alert' || this.$type === 'confirm') {
- this.$nextTick(() => {
- this.$refs.confirm.$el.focus();
- });
- }
- this.focusAfterClosed = document.activeElement;
- messageBox = new Dialog(this.$el, this.focusAfterClosed, this.getFirstFocus());
- }
- // prompt
- if (this.$type !== 'prompt') return;
- if (val) {
- setTimeout(() => {
- if (this.$refs.input && this.$refs.input.$el) {
- this.getInputElement().focus();
- }
- }, 500);
- } else {
- this.editorErrorMessage = '';
- removeClass(this.getInputElement(), 'invalid');
- }
- }
- },
- mounted() {
- this.$nextTick(() => {
- if (this.closeOnHashChange) {
- window.addEventListener('hashchange', this.close);
- }
- });
- },
- beforeDestroy() {
- if (this.closeOnHashChange) {
- window.removeEventListener('hashchange', this.close);
- }
- setTimeout(() => {
- messageBox.closeDialog();
- });
- },
- data() {
- return {
- uid: 1,
- title: undefined,
- message: '',
- type: '',
- iconClass: '',
- customClass: '',
- showInput: false,
- inputValue: null,
- inputPlaceholder: '',
- inputType: 'text',
- inputPattern: null,
- inputValidator: null,
- inputErrorMessage: '',
- showConfirmButton: true,
- showCancelButton: false,
- action: '',
- confirmButtonText: '',
- cancelButtonText: '',
- confirmButtonLoading: false,
- cancelButtonLoading: false,
- confirmButtonClass: '',
- confirmButtonDisabled: false,
- cancelButtonClass: '',
- editorErrorMessage: null,
- callback: null,
- dangerouslyUseHTMLString: false,
- focusAfterClosed: null,
- isOnComposition: false,
- distinguishCancelAndClose: false
- };
- }
- };
- </script>
|