'admin-21.06.24:新增拖动指令及其演示界面、优化登录页,锁屏界面'

This commit is contained in:
lyt 2021-06-24 18:02:13 +08:00
parent 54bbaa1946
commit 0c2026d37e
11 changed files with 302 additions and 8 deletions

View File

@ -2,6 +2,15 @@
🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等适配手机、平板、pc 的后台开源免费模板库vue2.x 请切换 vue-prev-admin 分支) 🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等适配手机、平板、pc 的后台开源免费模板库vue2.x 请切换 vue-prev-admin 分支)
## 1.0.7
`2021.06.24`
- 🌟 更新 依赖更新最新版本
- 🎉 新增 拖动指令及其演示界面
- 🎯 优化 锁屏界面,解锁提示
- 🎯 优化 登录页在手机上显示的效果
## 1.0.6 ## 1.0.6
`2021.06.23` `2021.06.23`

View File

@ -1,6 +1,6 @@
{ {
"name": "vue-next-admin", "name": "vue-next-admin",
"version": "1.0.6", "version": "1.0.7",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
@ -13,8 +13,8 @@
"cropperjs": "^1.5.12", "cropperjs": "^1.5.12",
"echarts": "^5.1.2", "echarts": "^5.1.2",
"echarts-wordcloud": "^2.0.0", "echarts-wordcloud": "^2.0.0",
"element-plus": "^1.0.2-beta.48", "element-plus": "^1.0.2-beta.51",
"mitt": "^2.1.0", "mitt": "^3.0.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"print-js": "^1.6.0", "print-js": "^1.6.0",
"qrcodejs2-fixes": "^0.0.2", "qrcodejs2-fixes": "^0.0.2",

View File

@ -48,6 +48,7 @@ export default {
pagesPreview: 'Large preview', pagesPreview: 'Large preview',
pagesWaves: 'Wave effect', pagesWaves: 'Wave effect',
pagesTree: 'tree alter table', pagesTree: 'tree alter table',
pagesDrag: 'Drag command',
chartIndex: 'chartIndex', chartIndex: 'chartIndex',
personal: 'personal', personal: 'personal',
tools: 'tools', tools: 'tools',

View File

@ -48,6 +48,7 @@ export default {
pagesPreview: '大图预览', pagesPreview: '大图预览',
pagesWaves: '波浪效果', pagesWaves: '波浪效果',
pagesTree: '树形改表格', pagesTree: '树形改表格',
pagesDrag: '拖动指令',
chartIndex: '大数据图表', chartIndex: '大数据图表',
personal: '个人中心', personal: '个人中心',
tools: '工具类集合', tools: '工具类集合',

View File

@ -48,6 +48,7 @@ export default {
pagesPreview: '大圖預覽', pagesPreview: '大圖預覽',
pagesWaves: '波浪效果', pagesWaves: '波浪效果',
pagesTree: '樹形改表格', pagesTree: '樹形改表格',
pagesDrag: '拖動指令',
chartIndex: '大資料圖表', chartIndex: '大資料圖表',
personal: '個人中心', personal: '個人中心',
tools: '工具類集合', tools: '工具類集合',

View File

@ -19,6 +19,10 @@
</div> </div>
<div class="layout-lock-screen-date-box-info">{{ time.mdq }}</div> <div class="layout-lock-screen-date-box-info">{{ time.mdq }}</div>
</div> </div>
<div class="layout-lock-screen-date-top">
<i class="el-icon-top"></i>
<div class="layout-lock-screen-date-top-text">上滑解锁</div>
</div>
</div> </div>
<transition name="el-zoom-in-center"> <transition name="el-zoom-in-center">
<div v-show="isShowLoockLogin" class="layout-lock-screen-login"> <div v-show="isShowLoockLogin" class="layout-lock-screen-login">
@ -52,11 +56,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { nextTick, onMounted, reactive, toRefs, ref, onUnmounted, getCurrentInstance } from 'vue'; import { nextTick, onMounted, reactive, toRefs, ref, onUnmounted, getCurrentInstance, defineComponent } from 'vue';
import { useStore } from '/@/store/index'; import { useStore } from '/@/store/index';
import { formatDate } from '/@/utils/formatTime'; import { formatDate } from '/@/utils/formatTime';
import { Local } from '/@/utils/storage'; import { Local } from '/@/utils/storage';
export default { export default defineComponent({
name: 'layoutLockScreen', name: 'layoutLockScreen',
setup() { setup() {
const { proxy } = getCurrentInstance() as any; const { proxy } = getCurrentInstance() as any;
@ -182,7 +186,7 @@ export default {
...toRefs(state), ...toRefs(state),
}; };
}, },
}; });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -204,7 +208,7 @@ export default {
} }
.layout-lock-screen-img { .layout-lock-screen-img {
@extend .layout-lock-screen-fixed; @extend .layout-lock-screen-fixed;
background-image: url('https://img6.bdstatic.com/img/image/pcindex/sunjunpchuazhoutu.JPG'); background-image: url('https://gitee.com/lyt-top/vue-next-admin-images/raw/master/images/03.jpg');
background-size: 100% 100%; background-size: 100% 100%;
z-index: 9999991; z-index: 9999991;
} }
@ -234,6 +238,53 @@ export default {
font-size: 16px; font-size: 16px;
} }
} }
&-top {
width: 40px;
height: 40px;
line-height: 40px;
border-radius: 100%;
border: 1px solid rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.1);
color: #ffffff;
opacity: 0.8;
position: absolute;
right: 30px;
bottom: 50px;
text-align: center;
overflow: hidden;
transition: all 0.3s ease;
i {
transition: all 0.3s ease;
}
&-text {
opacity: 0;
position: absolute;
top: 150%;
font-size: 12px;
color: #ffffff;
left: 50%;
line-height: 1.2;
transform: translate(-50%, -50%);
transition: all 0.3s ease;
width: 35px;
}
&:hover {
border: 1px solid rgba(255, 255, 255, 0.5);
background: rgba(255, 255, 255, 0.2);
color: #ffffff;
opacity: 1;
transition: all 0.3s ease;
i {
transform: translateY(-40px);
transition: all 0.3s ease;
}
.layout-lock-screen-date-top-text {
opacity: 1;
top: 50%;
transition: all 0.3s ease;
}
}
}
} }
&-login { &-login {
position: relative; position: relative;

View File

@ -755,6 +755,21 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
icon: 'iconfont icon-shuxingtu', icon: 'iconfont icon-shuxingtu',
}, },
}, },
{
path: '/pages/drag',
name: 'pagesDrag',
component: () => import('/@/views/pages/drag/index.vue'),
meta: {
title: 'message.router.pagesDrag',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'el-icon-thumb',
},
},
], ],
}, },
{ {

View File

@ -14,6 +14,7 @@
padding: 20px 0 !important; padding: 20px 0 !important;
border-radius: 0 !important; border-radius: 0 !important;
box-shadow: unset !important; box-shadow: unset !important;
border: none !important;
} }
.login-copyright { .login-copyright {
display: none !important; display: none !important;

View File

@ -52,3 +52,158 @@ export function wavesDirective(app: App) {
}, },
}); });
} }
/**
*
* @description 使v-drag="[dragDom,dragHeader]" `<div v-drag="['.drag-container .el-dialog', '.drag-container .el-dialog__header']"></div>`
* @description dragDom dragHeader Header
* @link https://github.com/element-plus/element-plus/issues/522
* @lick https://blog.csdn.net/weixin_46391323/article/details/105228020?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-10&spm=1001.2101.3001.4242
*/
export function dragDirective(app: App) {
app.directive('drag', {
mounted(el, binding) {
if (!binding.value) return false;
const dragDom = document.querySelector(binding.value[0]) as HTMLElement;
const dragHeader = document.querySelector(binding.value[1]) as HTMLElement;
dragHeader.onmouseover = () => (dragHeader.style.cursor = `move`);
/**
* pc端
* onmousedown
* onmousemove
* onmouseup
*/
dragHeader.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dragHeader.offsetLeft;
const disY = e.clientY - dragHeader.offsetTop;
// body当前宽度
const screenWidth = document.body.clientWidth;
// 可见区域高度(应为body高度可某些环境下无法获取)
const screenHeight = document.documentElement.clientHeight;
// 对话框宽度
const dragDomWidth = dragDom.offsetWidth;
// 对话框高度
const dragDomheight = dragDom.offsetHeight;
const minDragDomLeft = dragDom.offsetLeft;
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
const minDragDomTop = dragDom.offsetTop;
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
// 获取到的值带px 正则匹配替换
let styL: any = getComputedStyle(dragDom).left;
let styT: any = getComputedStyle(dragDom).top;
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
} else {
styL = +styL.replace(/\px/g, '');
styT = +styT.replace(/\px/g, '');
}
document.onmousemove = (e) => {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX;
let top = e.clientY - disY;
// 边界处理
if (-left > minDragDomLeft) {
left = -minDragDomLeft;
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft;
}
if (-top > minDragDomTop) {
top = -minDragDomTop;
} else if (top > maxDragDomTop) {
top = maxDragDomTop;
}
// 移动当前元素
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
};
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
};
};
/**
*
* ontouchstart ontouchstart
* ontouchmove ontouchmove
* ontouchend ontouchend
*/
dragHeader.ontouchstart = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.touches[0].clientX - dragHeader.offsetLeft;
const disY = e.touches[0].clientY - dragHeader.offsetTop;
// body当前宽度
const screenWidth = document.body.clientWidth;
// 可见区域高度(应为body高度可某些环境下无法获取)
const screenHeight = document.documentElement.clientHeight;
// 对话框宽度
const dragDomWidth = dragDom.offsetWidth;
// 对话框高度
const dragDomheight = dragDom.offsetHeight;
const minDragDomLeft = dragDom.offsetLeft;
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
const minDragDomTop = dragDom.offsetTop;
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
// 获取到的值带px 正则匹配替换
let styL: any = getComputedStyle(dragDom).left;
let styT: any = getComputedStyle(dragDom).top;
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
} else {
styL = +styL.replace(/\px/g, '');
styT = +styT.replace(/\px/g, '');
}
document.ontouchmove = (e) => {
// 通过事件委托,计算移动的距离
let left = e.touches[0].clientX - disX;
let top = e.touches[0].clientY - disY;
// 边界处理
if (-left > minDragDomLeft) {
left = -minDragDomLeft;
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft;
}
if (-top > minDragDomTop) {
top = -minDragDomTop;
} else if (top > maxDragDomTop) {
top = maxDragDomTop;
}
// 移动当前元素
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
};
document.ontouchend = () => {
document.ontouchmove = null;
document.ontouchend = null;
};
};
},
});
}

View File

@ -1,15 +1,18 @@
import type { App } from 'vue'; import type { App } from 'vue';
import { authDirective } from '/@/utils/authDirective'; import { authDirective } from '/@/utils/authDirective';
import { wavesDirective } from '/@/utils/customDirective'; import { wavesDirective, dragDirective } from '/@/utils/customDirective';
/** /**
* v-xxx * v-xxx
* @methods authDirective v-auth * @methods authDirective v-auth
* @methods wavesDirective v-waves * @methods wavesDirective v-waves
* @methods dragDirective v-drag
*/ */
export function directive(app: App) { export function directive(app: App) {
// 用户权限指令 // 用户权限指令
authDirective(app); authDirective(app);
// 按钮波浪指令 // 按钮波浪指令
wavesDirective(app); wavesDirective(app);
// 自定义拖动指令
dragDirective(app);
} }

View File

@ -0,0 +1,57 @@
<template>
<div class="drag-container">
<el-card shadow="hover" header="拖动指令效果v-drag作用于 Dialog 对话框">
<el-button type="primary" @click="dialogVisible = true" size="small" icon="el-icon-thumb">点击打开 Dialog</el-button>
</el-card>
<el-card shadow="hover" header="自定义div" class="mt15">
<div class="drag-dom">
<div class="drag-header">
<el-button type="success" size="small" icon="el-icon-thumb" v-drag="['.drag-container .drag-dom', '.drag-container .drag-header']"
>按住进行拖动测试</el-button
>
</div>
</div>
</el-card>
<el-dialog v-model="dialogVisible" width="769px">
<template #title>
<div v-drag="['.drag-container .el-dialog', '.drag-container .el-dialog__header']">拖动指令效果v-drag</div>
</template>
<p>鼠标放标题头进行 Dialog 对话框拖动</p>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false" size="small"> </el-button>
<el-button type="primary" @click="dialogVisible = false" size="small"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, defineComponent } from 'vue';
export default defineComponent({
name: 'pagesDrag',
setup() {
const state = reactive({
dialogVisible: false,
});
return {
...toRefs(state),
};
},
});
</script>
<style scoped lang="scss">
.drag-container {
.drag-dom {
position: relative;
display: inline-block;
.drag-header {
display: inline-block;
}
}
}
</style>