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 @@
- {}'>
-
+ {}'>
+
+
+
- {{navMenu.meta.title}}
-
+ {{ navMenu.meta.title }}
+
-
- {{navMenu.meta.title}}
-
+
+
+
+ {{ navMenu.meta.title }}
+
-
+
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 @@
-
+
+
+
+
+
-
+
-
{{ $CONFIG.APP_NAME }}
+
{{ config.APP_NAME }}
-
+
@@ -18,119 +24,107 @@
-
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 @@
- {{item.meta.title}}
+
+
+
+
+ {{ item.meta.title }}
+
@@ -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;
}
}