You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
6.5 KiB
263 lines
6.5 KiB
<template>
|
|
<!-- 模块样式 -->
|
|
<div v-if="value" :class="[hook, {'v-box--simple' : simple}, `v-box`]">
|
|
<div class="v-box__mask" :style="{opacity}"></div>
|
|
<div class="v-box__container" :style="{width: `${width}px`}">
|
|
<!-- 主题样式 -->
|
|
<header class="v-box__title" :class="movable ? `v-box--move` : `v-box--normal`">
|
|
<em class="v-box__name">{{ title }}</em>
|
|
<i :class="[`v-box__icon`, {'v-box--close-hide' : hideclose}]" @click.stop="handleClose($event)"></i>
|
|
</header>
|
|
<div class="v-box__content">
|
|
<slot></slot>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
props: {
|
|
width: {
|
|
type: Number,
|
|
default: 400
|
|
},
|
|
|
|
value: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
|
|
opacity: {
|
|
type: Number,
|
|
default: 0.7
|
|
},
|
|
|
|
title: {
|
|
type: String,
|
|
default: `System Tips`
|
|
},
|
|
|
|
// 盒子是否可移动
|
|
movable: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
|
|
// 关闭按钮
|
|
hideclose: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
|
|
load: {
|
|
type: Function,
|
|
default: null,
|
|
},
|
|
|
|
close: {
|
|
type: Function,
|
|
default: null,
|
|
},
|
|
|
|
hook: {
|
|
type: String,
|
|
default: ``,
|
|
},
|
|
|
|
// 简洁模式 - 去除标题
|
|
simple: {
|
|
type: Boolean,
|
|
default: false,
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
// 控制滚动条的加载 - overflow属性
|
|
value(theNew, theOld) {
|
|
// debugger;
|
|
let overstep = theNew ? 'hidden' : 'auto';
|
|
document.body.style.overflow = overstep;
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
|
|
handleClose($event) {
|
|
// 触发父组件的回调动作
|
|
if (!this.hideclose) {
|
|
// 发布到父组件关闭弹框
|
|
this.$emit('input', false);
|
|
if (this.close) this.close(this); // close方法
|
|
else this.$emit('onclose', this); // close事件
|
|
}
|
|
}
|
|
|
|
},
|
|
created(){
|
|
if (this.before) this.before(); // before方法
|
|
else this.$emit('onbefore', this); // before事件
|
|
},
|
|
// 组件加载完毕的回调动作
|
|
mounted() {
|
|
if (this.load) this.load(this); // load方法
|
|
else this.$emit('onload', this); // load事件
|
|
},
|
|
|
|
updated() {
|
|
// 当盒子从无到有 并且可点击时 绑定事件
|
|
if (this.value && this.movable) {
|
|
|
|
const v_box = document.querySelector('.v-box__container'),
|
|
v_title = v_box.querySelector('.v-box__title');
|
|
|
|
// 绑定拖拽事件,box代理title的事件
|
|
const me = this;
|
|
|
|
v_box.onmousedown = function (event) {
|
|
|
|
// 只在title上触发,拒绝其他冒泡
|
|
if (v_title && event.target != v_title) return;
|
|
|
|
//初始化 鼠标相对盒子的坐标
|
|
const evt = window.event || event;
|
|
const relPos = {
|
|
x: evt.offsetX,
|
|
y: evt.offsetY
|
|
};
|
|
|
|
//计算盒子在页面中移动的区域
|
|
const area = {
|
|
maxL: document.documentElement.clientWidth - me.width,
|
|
maxT: document.documentElement.clientHeight - me.height
|
|
};
|
|
|
|
document.onmousemove = function (event) {
|
|
|
|
// "use strict";
|
|
// 盒子始终和鼠标保持同样的相对坐标
|
|
// 现获取鼠标在页面中的绝对坐标值
|
|
const evt = window.event || event;
|
|
let mx = evt.clientX - relPos.x,
|
|
my = evt.clientY - relPos.y;
|
|
|
|
//判断临界条件
|
|
if (mx < 0) mx = 0;
|
|
else if (mx > area.maxL) mx = area.maxL;
|
|
|
|
if (my < 0) my = 0;
|
|
else if (my > area.maxT) my = area.maxT;
|
|
|
|
//让盒子移动到该位置,加上之前居中减少的尺寸
|
|
v_box.style.left = `${mx + v_box.offsetWidth / 2}px`;
|
|
v_box.style.top = `${my + v_box.offsetHeight / 2}px`;
|
|
};
|
|
};
|
|
|
|
v_box.onmouseup = function () {
|
|
document.onmousemove = null;
|
|
};
|
|
}
|
|
},
|
|
|
|
// 盒子关闭后 销毁DOM时 回调动作
|
|
destroyed() {
|
|
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
/* @height : `document.documentElement.clientHeight`; */
|
|
|
|
.v-box {
|
|
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
// 固定在页面上方
|
|
position: fixed;
|
|
left: 0;
|
|
top: 0;
|
|
z-index: 2001; // element蒙层权重为2000 需要比它大
|
|
|
|
// 去除页面滚动条
|
|
overflow: hidden;
|
|
|
|
.v-box__mask {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: absolute;
|
|
z-index: 100;
|
|
// 遮罩层背景色
|
|
background: #000;
|
|
}
|
|
|
|
.v-box__container {
|
|
|
|
background: white;
|
|
border-radius: 4px;
|
|
overflow: hidden; // 解决圆角益处的问题
|
|
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
|
|
|
// 盒子居中显示
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%); // 减去自身尺寸的50%
|
|
z-index: 1000;
|
|
|
|
.v-box__title {
|
|
height: 52px;
|
|
padding: 15px;
|
|
border-bottom: 1px solid #4e4e5d;
|
|
// border-radius: 10px 10px 0px 0px;
|
|
|
|
@include flexible(row);
|
|
|
|
// 主轴方向两端对齐
|
|
justify-content: space-between;
|
|
|
|
.v-box__name {
|
|
// width: 196px;
|
|
height: 22px;
|
|
@include font(Metropolis-Bold, 18, 22);
|
|
}
|
|
|
|
.v-box__icon {
|
|
width: 18px;
|
|
height: 18px;
|
|
background: url("../assets/img/icon-close.svg") no-repeat center center;
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
|
|
.v-box__content {
|
|
@include font($face, 14, 16);
|
|
padding: 14px;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// 模块样式
|
|
.v-box--simple {
|
|
.v-box__title {
|
|
display: none !important;
|
|
}
|
|
}
|
|
|
|
// 状态样式
|
|
.v-box--move {
|
|
cursor: move;
|
|
}
|
|
|
|
.v-box--normal {
|
|
cursor: default;
|
|
}
|
|
|
|
.v-box--close-hide {
|
|
display: none;
|
|
}
|
|
</style>
|
|
|