离校前端框架,包括数据字典、工作队伍、新闻公告模块
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)
+ }
+}
+