离校前端框架,包括数据字典、工作队伍、新闻公告模块
diff --git a/leave-school-vue/src/directive/clipboard/clipboard.js b/leave-school-vue/src/directive/clipboard/clipboard.js
new file mode 100644
index 0000000..49c9b39
--- /dev/null
+++ b/leave-school-vue/src/directive/clipboard/clipboard.js
@@ -0,0 +1,49 @@
+// Inspired by https://github.com/Inndy/vue-clipboard2
+const Clipboard = require('clipboard')
+if (!Clipboard) {
+  throw new Error('you shold npm install `clipboard` --save at first ')
+}
+
+export default {
+  bind(el, binding) {
+    if (binding.arg === 'success') {
+      el._v_clipboard_success = binding.value
+    } else if (binding.arg === 'error') {
+      el._v_clipboard_error = binding.value
+    } else {
+      const clipboard = new Clipboard(el, {
+        text() { return binding.value },
+        action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
+      })
+      clipboard.on('success', e => {
+        const callback = el._v_clipboard_success
+        callback && callback(e) // eslint-disable-line
+      })
+      clipboard.on('error', e => {
+        const callback = el._v_clipboard_error
+        callback && callback(e) // eslint-disable-line
+      })
+      el._v_clipboard = clipboard
+    }
+  },
+  update(el, binding) {
+    if (binding.arg === 'success') {
+      el._v_clipboard_success = binding.value
+    } else if (binding.arg === 'error') {
+      el._v_clipboard_error = binding.value
+    } else {
+      el._v_clipboard.text = function() { return binding.value }
+      el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
+    }
+  },
+  unbind(el, binding) {
+    if (binding.arg === 'success') {
+      delete el._v_clipboard_success
+    } else if (binding.arg === 'error') {
+      delete el._v_clipboard_error
+    } else {
+      el._v_clipboard.destroy()
+      delete el._v_clipboard
+    }
+  }
+}
diff --git a/leave-school-vue/src/directive/clipboard/index.js b/leave-school-vue/src/directive/clipboard/index.js
new file mode 100644
index 0000000..02c9816
--- /dev/null
+++ b/leave-school-vue/src/directive/clipboard/index.js
@@ -0,0 +1,13 @@
+import Clipboard from './clipboard'
+
+const install = function(Vue) {
+  Vue.directive('Clipboard', Clipboard)
+}
+
+if (window.Vue) {
+  window.clipboard = Clipboard
+  Vue.use(install); // eslint-disable-line
+}
+
+Clipboard.install = install
+export default Clipboard
diff --git a/leave-school-vue/src/directive/el-dragDialog/drag.js b/leave-school-vue/src/directive/el-dragDialog/drag.js
new file mode 100644
index 0000000..68e0852
--- /dev/null
+++ b/leave-school-vue/src/directive/el-dragDialog/drag.js
@@ -0,0 +1,77 @@
+export default{
+  bind(el, binding, vnode) {
+    const dialogHeaderEl = el.querySelector('.el-dialog__header')
+    const dragDom = el.querySelector('.el-dialog')
+    dialogHeaderEl.style.cssText += ';cursor:move;'
+    dragDom.style.cssText += ';top:0px;'
+
+    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
+    const getStyle = (function() {
+      if (window.document.currentStyle) {
+        return (dom, attr) => dom.currentStyle[attr]
+      } else {
+        return (dom, attr) => getComputedStyle(dom, false)[attr]
+      }
+    })()
+
+    dialogHeaderEl.onmousedown = (e) => {
+      // 鼠标按下,计算当前元素距离可视区的距离
+      const disX = e.clientX - dialogHeaderEl.offsetLeft
+      const disY = e.clientY - dialogHeaderEl.offsetTop
+
+      const dragDomWidth = dragDom.offsetWidth
+      const dragDomheight = dragDom.offsetHeight
+
+      const screenWidth = document.body.clientWidth
+      const screenHeight = document.body.clientHeight
+
+      const minDragDomLeft = dragDom.offsetLeft
+      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
+
+      const minDragDomTop = dragDom.offsetTop
+      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight
+
+      // 获取到的值带px 正则匹配替换
+      let styL = getStyle(dragDom, 'left')
+      let styT = getStyle(dragDom, 'top')
+
+      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 = function(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;`
+
+        // emit onDrag event
+        vnode.child.$emit('dragDialog')
+      }
+
+      document.onmouseup = function(e) {
+        document.onmousemove = null
+        document.onmouseup = null
+      }
+    }
+  }
+}
diff --git a/leave-school-vue/src/directive/el-dragDialog/index.js b/leave-school-vue/src/directive/el-dragDialog/index.js
new file mode 100644
index 0000000..29facbf
--- /dev/null
+++ b/leave-school-vue/src/directive/el-dragDialog/index.js
@@ -0,0 +1,13 @@
+import drag from './drag'
+
+const install = function(Vue) {
+  Vue.directive('el-drag-dialog', drag)
+}
+
+if (window.Vue) {
+  window['el-drag-dialog'] = drag
+  Vue.use(install); // eslint-disable-line
+}
+
+drag.install = install
+export default drag
diff --git a/leave-school-vue/src/directive/permission/index.js b/leave-school-vue/src/directive/permission/index.js
new file mode 100644
index 0000000..e5dadd3
--- /dev/null
+++ b/leave-school-vue/src/directive/permission/index.js
@@ -0,0 +1,13 @@
+import permission from './permission'
+
+const install = function(Vue) {
+  Vue.directive('permission', permission)
+}
+
+if (window.Vue) {
+  window['permission'] = permission
+  Vue.use(install); // eslint-disable-line
+}
+
+permission.install = install
+export default permission
diff --git a/leave-school-vue/src/directive/permission/permission.js b/leave-school-vue/src/directive/permission/permission.js
new file mode 100644
index 0000000..17b85d7
--- /dev/null
+++ b/leave-school-vue/src/directive/permission/permission.js
@@ -0,0 +1,23 @@
+
+import store from '@/store'
+
+export default{
+  inserted(el, binding, vnode) {
+    const { value } = binding
+    const roles = store.getters && store.getters.roles
+
+    if (value && value instanceof Array && value.length > 0) {
+      const permissionRoles = value
+
+      const hasPermission = roles.some(role => {
+        return permissionRoles.includes(role)
+      })
+
+      if (!hasPermission) {
+        el.parentNode && el.parentNode.removeChild(el)
+      }
+    } else {
+      throw new Error(`need roles! Like v-permission="['admin','editor']"`)
+    }
+  }
+}
diff --git a/leave-school-vue/src/directive/sticky.js b/leave-school-vue/src/directive/sticky.js
new file mode 100644
index 0000000..bc23466
--- /dev/null
+++ b/leave-school-vue/src/directive/sticky.js
@@ -0,0 +1,91 @@
+const vueSticky = {}
+let listenAction
+vueSticky.install = Vue => {
+  Vue.directive('sticky', {
+    inserted(el, binding) {
+      const params = binding.value || {}
+      const stickyTop = params.stickyTop || 0
+      const zIndex = params.zIndex || 1000
+      const elStyle = el.style
+
+      elStyle.position = '-webkit-sticky'
+      elStyle.position = 'sticky'
+      // if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
+      // if (~elStyle.position.indexOf('sticky')) {
+      //     elStyle.top = `${stickyTop}px`;
+      //     elStyle.zIndex = zIndex;
+      //     return
+      // }
+      const elHeight = el.getBoundingClientRect().height
+      const elWidth = el.getBoundingClientRect().width
+      elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
+
+      const parentElm = el.parentNode || document.documentElement
+      const placeholder = document.createElement('div')
+      placeholder.style.display = 'none'
+      placeholder.style.width = `${elWidth}px`
+      placeholder.style.height = `${elHeight}px`
+      parentElm.insertBefore(placeholder, el)
+
+      let active = false
+
+      const getScroll = (target, top) => {
+        const prop = top ? 'pageYOffset' : 'pageXOffset'
+        const method = top ? 'scrollTop' : 'scrollLeft'
+        let ret = target[prop]
+        if (typeof ret !== 'number') {
+          ret = window.document.documentElement[method]
+        }
+        return ret
+      }
+
+      const sticky = () => {
+        if (active) {
+          return
+        }
+        if (!elStyle.height) {
+          elStyle.height = `${el.offsetHeight}px`
+        }
+
+        elStyle.position = 'fixed'
+        elStyle.width = `${elWidth}px`
+        placeholder.style.display = 'inline-block'
+        active = true
+      }
+
+      const reset = () => {
+        if (!active) {
+          return
+        }
+
+        elStyle.position = ''
+        placeholder.style.display = 'none'
+        active = false
+      }
+
+      const check = () => {
+        const scrollTop = getScroll(window, true)
+        const offsetTop = el.getBoundingClientRect().top
+        if (offsetTop < stickyTop) {
+          sticky()
+        } else {
+          if (scrollTop < elHeight + stickyTop) {
+            reset()
+          }
+        }
+      }
+      listenAction = () => {
+        check()
+      }
+
+      window.addEventListener('scroll', listenAction)
+    },
+
+    unbind() {
+      window.removeEventListener('scroll', listenAction)
+    }
+  })
+}
+
+export default vueSticky
+
diff --git a/leave-school-vue/src/directive/waves/index.js b/leave-school-vue/src/directive/waves/index.js
new file mode 100644
index 0000000..65f9b30
--- /dev/null
+++ b/leave-school-vue/src/directive/waves/index.js
@@ -0,0 +1,13 @@
+import waves from './waves'
+
+const install = function(Vue) {
+  Vue.directive('waves', waves)
+}
+
+if (window.Vue) {
+  window.waves = waves
+  Vue.use(install); // eslint-disable-line
+}
+
+waves.install = install
+export default waves
diff --git a/leave-school-vue/src/directive/waves/waves.css b/leave-school-vue/src/directive/waves/waves.css
new file mode 100644
index 0000000..af7a7ef
--- /dev/null
+++ b/leave-school-vue/src/directive/waves/waves.css
@@ -0,0 +1,26 @@
+.waves-ripple {
+    position: absolute;
+    border-radius: 100%;
+    background-color: rgba(0, 0, 0, 0.15);
+    background-clip: padding-box;
+    pointer-events: none;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    -webkit-transform: scale(0);
+    -ms-transform: scale(0);
+    transform: scale(0);
+    opacity: 1;
+}
+
+.waves-ripple.z-active {
+    opacity: 0;
+    -webkit-transform: scale(2);
+    -ms-transform: scale(2);
+    transform: scale(2);
+    -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
+    transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
+    transition: opacity 1.2s ease-out, transform 0.6s ease-out;
+    transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
+}
\ No newline at end of file
diff --git a/leave-school-vue/src/directive/waves/waves.js b/leave-school-vue/src/directive/waves/waves.js
new file mode 100644
index 0000000..ac1d861
--- /dev/null
+++ b/leave-school-vue/src/directive/waves/waves.js
@@ -0,0 +1,42 @@
+import './waves.css'
+
+export default{
+  bind(el, binding) {
+    el.addEventListener('click', e => {
+      const customOpts = Object.assign({}, binding.value)
+      const opts = Object.assign({
+        ele: el, // 波纹作用元素
+        type: 'hit', // hit点击位置扩散center中心点扩展
+        color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
+      }, customOpts)
+      const target = opts.ele
+      if (target) {
+        target.style.position = 'relative'
+        target.style.overflow = 'hidden'
+        const rect = target.getBoundingClientRect()
+        let ripple = target.querySelector('.waves-ripple')
+        if (!ripple) {
+          ripple = document.createElement('span')
+          ripple.className = 'waves-ripple'
+          ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
+          target.appendChild(ripple)
+        } else {
+          ripple.className = 'waves-ripple'
+        }
+        switch (opts.type) {
+          case 'center':
+            ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
+            ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
+            break
+          default:
+            ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
+            ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
+        }
+        ripple.style.backgroundColor = opts.color
+        ripple.className = 'waves-ripple z-active'
+        return false
+      }
+    }, false)
+  }
+}
+