diff --git a/src/directives/auth.ts b/src/directives/auth.ts new file mode 100644 index 0000000..812806a --- /dev/null +++ b/src/directives/auth.ts @@ -0,0 +1,22 @@ +import {permission} from '@/utils/permission' + +export default { + mounted(el, binding) { + const {value} = binding + if (Array.isArray(value)) { + let ishas = false; + value.forEach(item => { + if (permission(item)) { + ishas = true; + } + }) + if (!ishas) { + el.parentNode && el.parentNode.removeChild(el) + } + } else { + if (!permission(value)) { + el.parentNode && el.parentNode.removeChild(el); + } + } + } +}; diff --git a/src/directives/copy.ts b/src/directives/copy.ts new file mode 100644 index 0000000..e9cbcc9 --- /dev/null +++ b/src/directives/copy.ts @@ -0,0 +1,29 @@ +import {ElMessage} from 'element-plus' + +export default { + mounted(el, binding) { + el.$value = binding.value + el.handler = () => { + const textarea = document.createElement('textarea') + textarea.readOnly = true + textarea.style.position = 'absolute' + textarea.style.left = '-9999px' + textarea.value = el.$value + document.body.appendChild(textarea) + textarea.select() + textarea.setSelectionRange(0, textarea.value.length) + const result = document.execCommand('Copy') + if (result) { + ElMessage.success("复制成功") + } + document.body.removeChild(textarea) + } + el.addEventListener('click', el.handler) + }, + updated(el, binding) { + el.$value = binding.value + }, + unmounted(el) { + el.removeEventListener('click', el.handler) + } +} diff --git a/src/directives/drag.ts b/src/directives/drag.ts new file mode 100644 index 0000000..5a6e0f0 --- /dev/null +++ b/src/directives/drag.ts @@ -0,0 +1,44 @@ +export default { + mounted(el, binding) { + let oDiv = el; //当前元素 + let firstTime: number; + let lastTime: number; + //禁止选择网页上的文字 + // document.onselectstart = function() { + // return false; + // }; + oDiv.onmousedown = function (e) { + //鼠标按下,计算当前元素距离可视区的距离 + let disX = e.clientX - oDiv.offsetLeft; + let disY = e.clientY - oDiv.offsetTop; + document.onmousemove = function (e) { + oDiv.setAttribute('drag-flag', true); + firstTime = new Date().getTime(); + //通过事件委托,计算移动的距离 + let l = e.clientX - disX; + let t = e.clientY - disY; + + //移动当前元素 + + if (t > 0 && t < document.body.clientHeight - 50) { + oDiv.style.top = t + "px"; + } + if (l > 0 && l < document.body.clientWidth - 50) { + oDiv.style.left = l + "px"; + } + + + } + document.onmouseup = function () { + lastTime = new Date().getTime(); + if ((lastTime - firstTime) > 200) { + oDiv.setAttribute('drag-flag', false); + } + document.onmousemove = null; + document.onmouseup = null; + }; + //return false不加的话可能导致黏连,就是拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效 + return false; + }; + } +} diff --git a/src/directives/excludeRole.ts b/src/directives/excludeRole.ts new file mode 100644 index 0000000..d8e4231 --- /dev/null +++ b/src/directives/excludeRole.ts @@ -0,0 +1,22 @@ +import {rolePermission} from '@/utils/permission' + +export default { + mounted(el, binding) { + const {value} = binding + if (Array.isArray(value)) { + let ishas = false + value.forEach(item => { + if (rolePermission(item)) { + ishas = true + } + }) + if (ishas) { + el.parentNode.removeChild(el) + } + } else { + if (rolePermission(value)) { + el.parentNode.removeChild(el) + } + } + } +} diff --git a/src/directives/role.ts b/src/directives/role.ts new file mode 100644 index 0000000..9831715 --- /dev/null +++ b/src/directives/role.ts @@ -0,0 +1,22 @@ +import {rolePermission} from '@/utils/permission' + +export default { + mounted(el, binding) { + const {value} = binding + if (Array.isArray(value)) { + let ishas = false; + value.forEach(item => { + if (rolePermission(item)) { + ishas = true; + } + }) + if (!ishas) { + el.parentNode && el.parentNode.removeChild(el) + } + } else { + if (!rolePermission(value)) { + el.parentNode && el.parentNode.removeChild(el); + } + } + } +}; diff --git a/src/directives/time.ts b/src/directives/time.ts new file mode 100644 index 0000000..eaaff3e --- /dev/null +++ b/src/directives/time.ts @@ -0,0 +1,79 @@ +import tools from '@/utils/tools' + +var Time = { + //获取当前时间戳 + getUnix: function () { + var date = new Date(); + return date.getTime(); + }, + //获取今天0点0分0秒的时间戳 + getTodayUnix: function () { + var date = new Date(); + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + return date.getTime(); + }, + //获取今年1月1日0点0秒的时间戳 + getYearUnix: function () { + var date = new Date(); + date.setMonth(0); + date.setDate(1); + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + return date.getTime(); + }, + //获取标准年月日 + getLastDate: function (time) { + var date = new Date(time); + var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1; + var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate(); + return date.getFullYear() + '-' + month + '-' + day; + }, + //转换时间 + getFormateTime: function (timestamp) { + timestamp = new Date(timestamp) + var now = this.getUnix(); + var today = this.getTodayUnix(); + //var year = this.getYearUnix(); + var timer = (now - timestamp) / 1000; + var tip = ''; + + if (timer <= 0) { + tip = '刚刚'; + } else if (Math.floor(timer / 60) <= 0) { + tip = '刚刚'; + } else if (timer < 3600) { + tip = Math.floor(timer / 60) + '分钟前'; + } else if (timer >= 3600 && (timestamp - today >= 0)) { + tip = Math.floor(timer / 3600) + '小时前'; + } else if (timer / 86400 <= 31) { + tip = Math.ceil(timer / 86400) + '天前'; + } else { + tip = this.getLastDate(timestamp); + } + return tip; + } +} + +export default (el, binding) => { + let {value, modifiers} = binding + if (!value) { + return false + } + if (value.toString().length == 10) { + value = value * 1000 + } + if (modifiers.tip) { + el.innerHTML = Time.getFormateTime(value) + el.__timeout__ = setInterval(() => { + el.innerHTML = Time.getFormateTime(value) + }, 60000) + } else { + const format = el.getAttribute('format') || undefined + el.innerHTML = tools.dateFormat(value, format) + } +} diff --git a/src/layout/components/NavMenu.vue b/src/layout/components/NavMenu.vue index 8d4d083..9bdde93 100644 --- a/src/layout/components/NavMenu.vue +++ b/src/layout/components/NavMenu.vue @@ -4,35 +4,36 @@ - + diff --git a/src/layout/components/sideM.vue b/src/layout/components/sideM.vue index 5762f0f..9fe20b3 100644 --- a/src/layout/components/sideM.vue +++ b/src/layout/components/sideM.vue @@ -1,14 +1,20 @@ - diff --git a/src/layout/components/tags.vue b/src/layout/components/tags.vue index 6a11b78..b2a4920 100644 --- a/src/layout/components/tags.vue +++ b/src/layout/components/tags.vue @@ -83,6 +83,7 @@ onMounted(() => { }) watch(route, (e) => { + console.log(111) addViewTags(e); //判断标签容器是否出现滚动条 nextTick(() => { @@ -92,7 +93,7 @@ watch(route, (e) => { let targetTag = tags.querySelector(".active") targetTag.scrollIntoView() //显示提示 - if (!tipDisplayed) { + if (!tipDisplayed.value) { proxy.$msgbox({ type: 'warning', center: true, @@ -100,14 +101,13 @@ watch(route, (e) => { message: '当前标签数量过多,可通过鼠标滚轴滚动标签栏。关闭标签数量可减少系统性能消耗。', confirmButtonText: '知道了' }) - tipDisplayed = true + tipDisplayed.value = true } - } }) }) -watch(() => contextMenuVisible, (value) => { +watch(contextMenuVisible, (value) => { var cm = function (e) { let sp = document.getElementById("contextmenu"); if (sp && !sp.contains(e.target)) { @@ -173,7 +173,7 @@ function closeSelectedTag(tag, autoPushLatestView = true) { //tag右键 function openContextMenu(e, tag) { contextMenuItem = tag; - contextMenuVisible = true; + contextMenuVisible.value = true; left.value = e.clientX + 1; top.value = e.clientY + 1; @@ -267,7 +267,7 @@ function openWindow() { closeSelectedTag(nowTag) } window.open(url); - contextMenuVisible = false + contextMenuVisible.value = false } //横向滚动 diff --git a/src/layout/components/topbar.vue b/src/layout/components/topbar.vue index 8bb1434..468da6a 100644 --- a/src/layout/components/topbar.vue +++ b/src/layout/components/topbar.vue @@ -4,7 +4,13 @@ @@ -16,34 +22,46 @@ - diff --git a/src/pi.ts b/src/pi.ts index 040ec75..9c4d5eb 100644 --- a/src/pi.ts +++ b/src/pi.ts @@ -1,10 +1,24 @@ import * as elIcons from '@element-plus/icons-vue' import {App} from "vue"; import * as piIcons from '@assets/icons' +import auth from './directives/auth' +import role from './directives/role' +import excludeRole from './directives/excludeRole' +import time from './directives/time' +import copy from './directives/copy' +import drag from './directives/drag' import errorHandler from "@/utils/errorHandler"; export default { install(app: App) { + //注册全局指令 + app.directive('auth', auth) + app.directive('role', role) + app.directive('exclude-role', excludeRole) + app.directive('time', time) + app.directive('copy', copy) + app.directive('drag', drag) + //统一注册el-icon图标 for (let icon in elIcons) { app.component(`ElIcon${icon}`, elIcons[icon]) diff --git a/src/utils/errorHandler.ts b/src/utils/errorHandler.ts index 8feda5c..91c6138 100644 --- a/src/utils/errorHandler.ts +++ b/src/utils/errorHandler.ts @@ -2,32 +2,29 @@ * 全局代码错误捕捉 * 比如 null.length 就会被捕捉到 */ -import {nextTick} from "vue"; - export default (error, vm)=>{ //过滤HTTP请求错误 if(error.status || error.status==0){ return false } - // var errorMap = { - // InternalError: "Javascript引擎内部错误", - // ReferenceError: "未找到对象", - // TypeError: "使用了错误的类型或对象", - // RangeError: "使用内置对象时,参数超范围", - // SyntaxError: "语法错误", - // EvalError: "错误的使用了Eval", - // URIError: "URI错误" - // } - // var errorName = errorMap[error.name] || "未知错误" + var errorMap = { + InternalError: "Javascript引擎内部错误", + ReferenceError: "未找到对象", + TypeError: "使用了错误的类型或对象", + RangeError: "使用内置对象时,参数超范围", + SyntaxError: "语法错误", + EvalError: "错误的使用了Eval", + URIError: "URI错误" + } + var errorName = errorMap[error.name] || "未知错误" console.error(`[PI error]: ${error}`); - //throw error; vm.$nextTick(() => { - // vm.$notify.error({ - // title: errorName, - // message: error - // }); + vm.$notify.error({ + title: errorName, + message: error + }); }) } diff --git a/src/utils/permission.ts b/src/utils/permission.ts new file mode 100644 index 0000000..b74aa5b --- /dev/null +++ b/src/utils/permission.ts @@ -0,0 +1,25 @@ +import tools from '@/utils/tools'; + +export function permission(data) { + let permissions = tools.data.get("PERMISSIONS"); + if (!permissions) { + return false; + } + return permissions.includes(data); +} + +export function noPermission(data) { + return !permission(data); +} + +export function rolePermission(data) { + let roles = tools.data.get("ROLE"); + if (!roles) { + return false; + } + return roles.includes(data); +} + +export function noRolePermission(data) { + return !rolePermission(data); +} diff --git a/src/utils/tools.ts b/src/utils/tools.ts index 83c9a60..4a01ec4 100644 --- a/src/utils/tools.ts +++ b/src/utils/tools.ts @@ -102,6 +102,32 @@ const tools = { element.webkitRequestFullscreen(); } } + }, + /* 复制对象 */ + objCopy: function (obj) { + return JSON.parse(JSON.stringify(obj)); + }, + /* 日期格式化 */ + dateFormat: function (date, fmt='yyyy-MM-dd hh:mm:ss') { + date = new Date(date) + var o = { + "M+" : date.getMonth()+1, //月份 + "d+" : date.getDate(), //日 + "h+" : date.getHours(), //小时 + "m+" : date.getMinutes(), //分 + "s+" : date.getSeconds(), //秒 + "q+" : Math.floor((date.getMonth()+3)/3), //季度 + "S" : date.getMilliseconds() //毫秒 + }; + if(/(y+)/.test(fmt)) { + fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length)); + } + for(var k in o) { + if(new RegExp("("+ k +")").test(fmt)){ + fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); + } + } + return fmt; } }