Compare commits
No commits in common. 'master' and 'develop' have entirely different histories.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 380 KiB |
Binary file not shown.
@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App'
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body .el-table th.gutter{
|
||||
display: table-cell!important;
|
||||
}
|
||||
</style>
|
||||
@ -1,41 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function fetchList(query) {
|
||||
return request({
|
||||
url: '/article/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchArticle(id) {
|
||||
return request({
|
||||
url: '/article/detail',
|
||||
method: 'get',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchPv(pv) {
|
||||
return request({
|
||||
url: '/article/pv',
|
||||
method: 'get',
|
||||
params: { pv }
|
||||
})
|
||||
}
|
||||
|
||||
export function createArticle(data) {
|
||||
return request({
|
||||
url: '/article/create',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateArticle(data) {
|
||||
return request({
|
||||
url: '/article/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getToken() {
|
||||
return request({
|
||||
url: '/qiniu/upload/token', // 假地址 自行替换
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function searchUser(name) {
|
||||
return request({
|
||||
url: '/search/user',
|
||||
method: 'get',
|
||||
params: { name }
|
||||
})
|
||||
}
|
||||
|
||||
export function transactionList(query) {
|
||||
return request({
|
||||
url: '/transaction/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getRoutes() {
|
||||
return request({
|
||||
url: '/routes',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getRoles() {
|
||||
return request({
|
||||
url: '/roles',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function addRole(data) {
|
||||
return request({
|
||||
url: '/role',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateRole(id, data) {
|
||||
return request({
|
||||
url: `/role/${id}`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteRole(id) {
|
||||
return request({
|
||||
url: `/role/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function login(data) {
|
||||
return request({
|
||||
url: '/system/sysUser/login',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function twoLogin(data) {
|
||||
return request({
|
||||
url: '/system/sysUser/twoLogin',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function getInfo() {
|
||||
return request({
|
||||
url: '/system/sysUser/getCurrentUser',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/system/sysUser/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
// Inspired by https://github.com/Inndy/vue-clipboard2
|
||||
const Clipboard = require('clipboard')
|
||||
if (!Clipboard) {
|
||||
throw new Error('you should 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
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
|
||||
@ -1,77 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
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
|
||||
@ -1,41 +0,0 @@
|
||||
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
|
||||
|
||||
/**
|
||||
* How to use
|
||||
* <el-table height="100px" v-el-height-adaptive-table="{bottomOffset: 30}">...</el-table>
|
||||
* el-table height is must be set
|
||||
* bottomOffset: 30(default) // The height of the table from the bottom of the page.
|
||||
*/
|
||||
|
||||
const doResize = (el, binding, vnode) => {
|
||||
const { componentInstance: $table } = vnode
|
||||
|
||||
const { value } = binding
|
||||
|
||||
if (!$table.height) {
|
||||
throw new Error(`el-$table must set the height. Such as height='100px'`)
|
||||
}
|
||||
const bottomOffset = (value && value.bottomOffset) || 30
|
||||
|
||||
if (!$table) return
|
||||
|
||||
const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
|
||||
$table.layout.setHeight(height)
|
||||
$table.doLayout()
|
||||
}
|
||||
|
||||
export default {
|
||||
bind(el, binding, vnode) {
|
||||
el.resizeListener = () => {
|
||||
doResize(el, binding, vnode)
|
||||
}
|
||||
// parameter 1 is must be "Element" type
|
||||
addResizeListener(window.document.body, el.resizeListener)
|
||||
},
|
||||
inserted(el, binding, vnode) {
|
||||
doResize(el, binding, vnode)
|
||||
},
|
||||
unbind(el) {
|
||||
removeResizeListener(window.document.body, el.resizeListener)
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
import adaptive from './adaptive'
|
||||
|
||||
const install = function(Vue) {
|
||||
Vue.directive('el-height-adaptive-table', adaptive)
|
||||
}
|
||||
|
||||
if (window.Vue) {
|
||||
window['el-height-adaptive-table'] = adaptive
|
||||
Vue.use(install); // eslint-disable-line
|
||||
}
|
||||
|
||||
adaptive.install = install
|
||||
export default adaptive
|
||||
@ -1,13 +0,0 @@
|
||||
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
|
||||
@ -1,22 +0,0 @@
|
||||
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']"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
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
|
||||
@ -1,26 +0,0 @@
|
||||
.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;
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
import './waves.css'
|
||||
|
||||
const context = '@@wavesContext'
|
||||
|
||||
function handleClick(el, binding) {
|
||||
function handle(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.documentElement.scrollTop ||
|
||||
document.body.scrollTop) + 'px'
|
||||
ripple.style.left =
|
||||
(e.pageX - rect.left - ripple.offsetWidth / 2 - document.documentElement.scrollLeft ||
|
||||
document.body.scrollLeft) + 'px'
|
||||
}
|
||||
ripple.style.backgroundColor = opts.color
|
||||
ripple.className = 'waves-ripple z-active'
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (!el[context]) {
|
||||
el[context] = {
|
||||
removeHandle: handle
|
||||
}
|
||||
} else {
|
||||
el[context].removeHandle = handle
|
||||
}
|
||||
|
||||
return handle
|
||||
}
|
||||
|
||||
export default {
|
||||
bind(el, binding) {
|
||||
el.addEventListener('click', handleClick(el, binding), false)
|
||||
},
|
||||
update(el, binding) {
|
||||
el.removeEventListener('click', el[context].removeHandle, false)
|
||||
el.addEventListener('click', handleClick(el, binding), false)
|
||||
},
|
||||
unbind(el) {
|
||||
el.removeEventListener('click', el[context].removeHandle, false)
|
||||
el[context] = null
|
||||
delete el[context]
|
||||
}
|
||||
}
|
||||
@ -1,97 +0,0 @@
|
||||
// import parseTime, formatTime and set to filter
|
||||
export { parseTime, formatTime } from '@/utils'
|
||||
|
||||
/**
|
||||
* Show plural label if time is plural number
|
||||
* @param {number} time
|
||||
* @param {string} label
|
||||
* @return {string}
|
||||
*/
|
||||
function pluralize(time, label) {
|
||||
if (time === 1) {
|
||||
return time + label
|
||||
}
|
||||
return time + label + 's'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} time
|
||||
*/
|
||||
export function timeAgo(time) {
|
||||
const between = Date.now() / 1000 - Number(time)
|
||||
if (between < 3600) {
|
||||
return pluralize(~~(between / 60), ' minute')
|
||||
} else if (between < 86400) {
|
||||
return pluralize(~~(between / 3600), ' hour')
|
||||
} else {
|
||||
return pluralize(~~(between / 86400), ' day')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Number formatting
|
||||
* like 10000 => 10k
|
||||
* @param {number} num
|
||||
* @param {number} digits
|
||||
*/
|
||||
export function numberFormatter(num, digits) {
|
||||
const si = [
|
||||
{ value: 1E18, symbol: 'E' },
|
||||
{ value: 1E15, symbol: 'P' },
|
||||
{ value: 1E12, symbol: 'T' },
|
||||
{ value: 1E9, symbol: 'G' },
|
||||
{ value: 1E6, symbol: 'M' },
|
||||
{ value: 1E3, symbol: 'k' }
|
||||
]
|
||||
for (let i = 0; i < si.length; i++) {
|
||||
if (num >= si[i].value) {
|
||||
return (num / si[i].value + 0.1).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
|
||||
}
|
||||
}
|
||||
return num.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 10000 => "10,000"
|
||||
* @param {number} num
|
||||
*/
|
||||
export function toThousandFilter(num) {
|
||||
return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
|
||||
}
|
||||
|
||||
/**
|
||||
* Upper case first char
|
||||
* @param {String} string
|
||||
*/
|
||||
export function uppercaseFirst(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1)
|
||||
}
|
||||
|
||||
export function calcAge(timestamp) {
|
||||
const targetDateTime = new Date(timestamp);
|
||||
const nowDateTime = new Date();
|
||||
const year = nowDateTime.getFullYear() - targetDateTime.getFullYear();
|
||||
const month = nowDateTime.getMonth() - targetDateTime.getMonth();
|
||||
const day = nowDateTime.getDate() - targetDateTime.getDate();
|
||||
if (month > 0) {
|
||||
return year;
|
||||
} else if (month === 0) {
|
||||
if (day >= 0) {
|
||||
return year;
|
||||
} else {
|
||||
return year - 1;
|
||||
}
|
||||
} else {
|
||||
return year - 1;
|
||||
}
|
||||
}
|
||||
|
||||
export function formatStatisticsNumber(value) {
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
if (value < 9999) {
|
||||
return value;
|
||||
}
|
||||
return (value / 10000.0).toFixed(1) + 'w';
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import 'normalize.css/normalize.css' // a modern alternative to CSS resets
|
||||
|
||||
import Element from 'element-ui'
|
||||
import './styles/element-variables.scss'
|
||||
|
||||
import '@/styles/index.scss' // global css
|
||||
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
import router from './router'
|
||||
|
||||
import './icons' // icon
|
||||
import './permission' // permission control
|
||||
import './utils/error-log' // error log
|
||||
import './utils/calendars'
|
||||
|
||||
import * as filters from './filters' // global filters
|
||||
import formRules from './utils/formRules' // global filters
|
||||
import request from './utils/request'
|
||||
import echarts from 'echarts'
|
||||
import svga from 'vue-svga'
|
||||
import { hasPermission } from './utils/btnPermission.js' // 按钮权限指令
|
||||
|
||||
Vue.use(hasPermission) // 按钮权限指令
|
||||
Vue.use(svga)
|
||||
Vue.prototype.$echarts = echarts;
|
||||
|
||||
/**
|
||||
* If you don't want to use mock-server
|
||||
* you want to use MockJs for mock api
|
||||
* you can execute: mockXHR()
|
||||
*
|
||||
* Currently MockJs will be used in the production environment,
|
||||
* please remove it before going online! ! !
|
||||
*/
|
||||
// import { mockXHR } from '../mock'
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
// mockXHR()
|
||||
}
|
||||
|
||||
Vue.use(Element, {
|
||||
size: Cookies.get('size') || 'medium' // set element-ui default size
|
||||
})
|
||||
// 表单参数校验规则
|
||||
Vue.prototype.formRules = formRules
|
||||
Vue.prototype.cfg = {
|
||||
apiDomain: process.env.VUE_APP_BASE_API,
|
||||
imageDomain: process.env.VUE_APP_IMAGE_BASE_API
|
||||
}
|
||||
/**
|
||||
* 防按钮重复提交
|
||||
* @param vue
|
||||
* @param key
|
||||
*/
|
||||
Vue.prototype.disableBtn = (vue, key) => {
|
||||
vue[key] = true;
|
||||
setTimeout(() => {
|
||||
vue[key] = false;
|
||||
}, 3000);
|
||||
}
|
||||
Vue.prototype.getUrlParam = key => {
|
||||
const re = new RegExp('[?|&]' + key + '=(.*?)(&|$|#)(#?)');
|
||||
const r = window.location.href.match(re);
|
||||
if (r != null) return decodeURIComponent(r[1]);
|
||||
return null;
|
||||
}
|
||||
|
||||
// register global utility filters
|
||||
Object.keys(filters).forEach(key => {
|
||||
Vue.filter(key, filters[key])
|
||||
})
|
||||
|
||||
/**
|
||||
* 将字典设置到Vue的过滤器中
|
||||
* @param name
|
||||
*/
|
||||
Vue.prototype.registerFilter = function(name) {
|
||||
request({
|
||||
url: `/common/dict/getDictDataByName/${name}`
|
||||
}).then(function(res) {
|
||||
const data = res.data;
|
||||
Vue.filter('filter' + name, function(value) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].code + '' === value + '') {
|
||||
return data[i].text;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
})
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 字符长度过滤
|
||||
*/
|
||||
Vue.prototype.charFilter = function(length) {
|
||||
Vue.filter('charFilter', function(value) {
|
||||
if (!value) return '';
|
||||
if (value.length > length) {
|
||||
return value.slice(0, length) + '...';
|
||||
}
|
||||
return value;
|
||||
})
|
||||
}
|
||||
|
||||
Vue.config.productionTip = false
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
})
|
||||
@ -1,216 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="search-container">
|
||||
<el-input v-model="searchForm.uniCode" class="search-input" placeholder="请输入唯一编码" :clearable="true" />
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList({pageNo: 1})">搜索</el-button>
|
||||
</div>
|
||||
<div class="function-buttons">
|
||||
<el-button v-hasPermission="['sys_base_param_add']" type="primary" size="small" icon="el-icon-edit" @click="showAdd">新增</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%">
|
||||
<el-table-column align="center" label="#" width="80" type="index" />
|
||||
|
||||
<el-table-column width="" align="center" label="唯一编码">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.uniCode }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="值">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.value }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="描述" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.description }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="操作人">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.operator }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="数据状态">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.status | filterEnumStatus }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="更新时间">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.updateTime | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="scope.row.status == 0" v-hasPermission="['sys_base_param_edit']" type="text" @click="showUpdate(scope.row)">编辑</el-button>
|
||||
<el-button v-if="scope.row.status == 0" v-hasPermission="['sys_base_param_audit']" type="text" @click="audit(scope.row)">审核</el-button>
|
||||
<el-button v-if="scope.row.status == 1" v-hasPermission="['sys_base_param_unAudit']" type="text" @click="unaudit(scope.row)">取消审核</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.pageNo" :limit.sync="listQuery.pageSize" @pagination="pageChange" />
|
||||
</div>
|
||||
<el-dialog title="编辑" :visible.sync="formData.formDialog" :close-on-click-modal="false">
|
||||
<el-form ref="saveForm" :model="formData.props" :rules="formData.rules" label-width="180px">
|
||||
<el-form-item label="唯一编码" prop="uniCode">
|
||||
<el-input v-model="formData.props.uniCode" placeholder="请输入唯一编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="值" prop="value">
|
||||
<el-input v-model="formData.props.value" placeholder="请输入值" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="formData.props.description" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="formData.formDialog = false">取 消</el-button>
|
||||
<el-button type="primary" :disabled="btnSubmitDisabled" @click="save">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
|
||||
import request from '@/utils/request'
|
||||
|
||||
export default {
|
||||
name: 'SysBaseParamList',
|
||||
components: { Pagination },
|
||||
data() {
|
||||
return {
|
||||
btnSubmitDisabled: false,
|
||||
list: null,
|
||||
total: 0,
|
||||
listLoading: true,
|
||||
listQuery: {
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
formData: {
|
||||
formDialog: false,
|
||||
// 表单字段, 请自行删除不需要的
|
||||
props: {
|
||||
uniCode: '',
|
||||
value: '',
|
||||
description: ''
|
||||
},
|
||||
// 表单校验规则, 默认增加了必填, 请自行限制长度或者其他修改
|
||||
rules: {
|
||||
uniCode: this.formRules({ required: true, min: 1, max: 50 }),
|
||||
value: this.formRules({ required: true, min: 1, max: 2000 }),
|
||||
description: this.formRules({ required: true, min: 1, max: 300 })
|
||||
}
|
||||
},
|
||||
searchForm: {
|
||||
uniCode: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.registerFilter('EnumStatus');
|
||||
this.getList({
|
||||
pageNo: this.listQuery.pageNo
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
pageChange(page, limit) {
|
||||
this.getList({
|
||||
pageNo: page.page,
|
||||
pageSize: limit
|
||||
})
|
||||
},
|
||||
getList(params) {
|
||||
var _this = this;
|
||||
this.listLoading = true
|
||||
request({
|
||||
url: '/system/sysBaseParam/getPageList',
|
||||
method: 'post',
|
||||
data: {
|
||||
pageNo: params.pageNo,
|
||||
pageSize: params.pageSize ? params.pageSize : this.listQuery.pageSize,
|
||||
...this.searchForm
|
||||
}
|
||||
}).then(res => {
|
||||
const data = res.data
|
||||
_this.list = data.rows
|
||||
_this.total = data.total
|
||||
_this.listLoading = false
|
||||
})
|
||||
},
|
||||
audit(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'post',
|
||||
url: `/system/sysBaseParam/audit?id=${data.id}`,
|
||||
data: {}
|
||||
}).then(res => {
|
||||
_this.$message.success('审核成功');
|
||||
data.status = 1;
|
||||
})
|
||||
},
|
||||
unaudit(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'post',
|
||||
url: `/system/sysBaseParam/unaudit?id=${data.id}`,
|
||||
data: {}
|
||||
}).then(res => {
|
||||
_this.$message.success('取消审核成功');
|
||||
data.status = 0;
|
||||
})
|
||||
},
|
||||
showAdd: function() {
|
||||
this.formData.props = {
|
||||
id: '',
|
||||
uniCode: '',
|
||||
value: '',
|
||||
description: ''
|
||||
}
|
||||
this.formData.formDialog = true;
|
||||
},
|
||||
showUpdate: function(data) {
|
||||
this.formData.props = {
|
||||
id: data.id,
|
||||
uniCode: data.uniCode,
|
||||
value: data.value,
|
||||
description: data.description
|
||||
}
|
||||
this.formData.formDialog = true;
|
||||
},
|
||||
save: function() {
|
||||
var _this = this;
|
||||
this.disableBtn(this, 'btnSubmitDisabled');
|
||||
this['$refs'].saveForm.validate(function(valid) {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
request({
|
||||
url: '/system/sysBaseParam/save',
|
||||
method: 'post',
|
||||
data: _this.formData.props
|
||||
}).then(res => {
|
||||
_this.$message.success('保存成功');
|
||||
_this.getList({
|
||||
pageNo: 1,
|
||||
pageSize: _this.listQuery.pageSize
|
||||
});
|
||||
_this.formData.formDialog = false;
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@ -1,352 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="search-container">
|
||||
<el-input v-model="searchForm.name" class="search-input" placeholder="请输入菜单名称" :clearable="true" />
|
||||
<el-input v-model="searchForm.identity" class="search-input" placeholder="请输入权限标识" :clearable="true" />
|
||||
<common-select v-model="searchForm.type" name="EnumSysResourceType" placetext="请选择菜单类型" @input="getList({pageNo: 1})" />
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList({pageNo: 1})">搜索</el-button>
|
||||
</div>
|
||||
<div class="function-buttons">
|
||||
<el-button v-hasPermission="['sys_resource_add']" type="primary" size="small" icon="el-icon-edit" @click="showAdd">新增</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%" row-key="id" :tree-props="{children: 'children'}">
|
||||
<el-table-column align="center" label="#" width="80" type="index" />
|
||||
<el-table-column width="" align="center" label="菜单名称">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="资源路径">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.url }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="权限标识">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.identity }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="排序">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.sort }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="菜单类型">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.type | filterEnumSysResourceType }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="是否显示">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.isShow | filterEnumYesNo }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="操作人">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.operator }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="更新时间">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.updateTime | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="100" align="center" label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="scope.row.status == 0" v-hasPermission="['sys_resource_edit']" type="text" @click="showUpdate(scope.row)">编辑</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.pageNo" :limit.sync="listQuery.pageSize" @pagination="pageChange" />
|
||||
</div>
|
||||
<!-- todo 调整表单字段 -->
|
||||
<el-dialog title="编辑" :visible.sync="formData.formDialog" :close-on-click-modal="false">
|
||||
<el-form ref="saveForm" :model="formData.props" :rules="formData.rules" label-width="180px">
|
||||
<el-form-item label="菜单名称" prop="name">
|
||||
<el-input v-model="formData.props.name" placeholder="请输入菜单名称" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="权限标识" prop="identity">
|
||||
<el-input v-model="formData.props.identity" placeholder="请输入权限标识" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单类型" prop="type">
|
||||
<common-select v-model="formData.props.type" :disabled="formData.props.id!=''" name="EnumSysResourceType" placetext="请选择菜单类型" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.props.type != 0 " label="" prop="parentId" style="max-height: 500px;overflow: auto">
|
||||
<el-tree
|
||||
ref="tree"
|
||||
:data="elTree.list"
|
||||
default-expand-all
|
||||
node-key="id"
|
||||
:props="elTree.defaultProps"
|
||||
:highlight-current="true"
|
||||
:expand-on-click-node="false"
|
||||
:current-node-key="currentLivingId"
|
||||
style="height:100%; margin-top:30px; background-color:#FFF;"
|
||||
@node-click="handleNodeClick"
|
||||
>
|
||||
<span slot-scope="{ node, data }" class="custom-tree-node">
|
||||
<span>
|
||||
<i :class="data.icon" />{{ data.label }}
|
||||
</span>
|
||||
</span>
|
||||
</el-tree>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.props.type != 2" label="资源路径" prop="url">
|
||||
<el-input v-model="formData.props.url" placeholder="资源路径" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input v-model="formData.props.sort" type="number" placeholder="请输入排序" :clearable="true" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="是否显示" prop="isShow">
|
||||
<common-select
|
||||
ref="EnumYesNo"
|
||||
v-model="formData.props.isShow"
|
||||
name="EnumYesNo"
|
||||
placetext="请选择显示类型"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="formData.formDialog = false">取 消</el-button>
|
||||
<el-button type="primary" :disabled="btnSubmitDisabled" @click="save">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
|
||||
import request from '@/utils/request'
|
||||
import CommonSelect from '@/components/wejoy/CommonSelect'
|
||||
|
||||
export default {
|
||||
name: 'SysResourceList',
|
||||
components: { Pagination, CommonSelect },
|
||||
data() {
|
||||
return {
|
||||
btnSubmitDisabled: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
listLoading: true,
|
||||
listQuery: {
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
currentLivingId: '',
|
||||
formData: {
|
||||
formDialog: false,
|
||||
// 表单字段, 请自行删除不需要的
|
||||
props: {
|
||||
name: '',
|
||||
url: '',
|
||||
parentId: '',
|
||||
icon: '',
|
||||
sort: '',
|
||||
type: '',
|
||||
status: '',
|
||||
operator: '',
|
||||
updateTime: '',
|
||||
rootPath: '',
|
||||
isShow: '',
|
||||
identity: ''
|
||||
},
|
||||
// 表单校验规则, 默认增加了必填, 请自行限制长度或者其他修改
|
||||
rules: {
|
||||
name: this.formRules({
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 100
|
||||
}),
|
||||
url: this.formRules({
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 100
|
||||
}),
|
||||
parentId: this.formRules({ required: true }),
|
||||
icon: this.formRules({ required: true }),
|
||||
sort: this.formRules({
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 10
|
||||
}),
|
||||
type: this.formRules({ required: true }),
|
||||
status: this.formRules({ required: true }),
|
||||
operator: this.formRules({ required: true }),
|
||||
updateTime: this.formRules({ required: true }),
|
||||
rootPath: this.formRules({ required: true }),
|
||||
isShow: this.formRules({ required: true }),
|
||||
identity: this.formRules({
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 100
|
||||
})
|
||||
}
|
||||
},
|
||||
searchForm: {
|
||||
name: '',
|
||||
status: 0,
|
||||
type: '0',
|
||||
identity: ''
|
||||
},
|
||||
elTree: {
|
||||
list: [],
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.registerFilter('EnumSysResourceType');
|
||||
this.registerFilter('EnumYesNo');
|
||||
this.getList({
|
||||
pageNo: this.listQuery.pageNo
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
pageChange(page) {
|
||||
this.getList({
|
||||
pageNo: page.page,
|
||||
pageSize: page.limit
|
||||
})
|
||||
},
|
||||
getList(params) {
|
||||
this.listLoading = true
|
||||
request({
|
||||
url: '/system/sysResource/getPageTreeList',
|
||||
method: 'post',
|
||||
data: {
|
||||
pageNo: params.pageNo,
|
||||
pageSize: params.pageSize ? params.pageSize : this.listQuery.pageSize,
|
||||
...this.searchForm
|
||||
}
|
||||
}).then(res => {
|
||||
const data = res.data;
|
||||
this.list = data.rows;
|
||||
this.total = data.total;
|
||||
this.listQuery.pageNo = params.pageNo;
|
||||
this.listLoading = false;
|
||||
}, () => {
|
||||
this.listLoading = false;
|
||||
})
|
||||
},
|
||||
audit(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'post',
|
||||
url: `/system/sysResource/audit?id=${data.id}`
|
||||
}).then(res => {
|
||||
_this.$message.success('审核成功');
|
||||
data.status = 1;
|
||||
})
|
||||
},
|
||||
unaudit(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'post',
|
||||
url: `/system/sysResource/unaudit?id=${data.id}`
|
||||
}).then(res => {
|
||||
_this.$message.success('取消审核成功');
|
||||
data.status = 0;
|
||||
})
|
||||
},
|
||||
showAdd: function() {
|
||||
// todo 清除表单中的数据
|
||||
this.getResourceTree(null);
|
||||
this.formData.props = {
|
||||
id: '',
|
||||
name: '',
|
||||
url: '',
|
||||
parentId: '',
|
||||
icon: '',
|
||||
sort: '',
|
||||
type: '',
|
||||
status: '',
|
||||
operator: '',
|
||||
updateTime: '',
|
||||
rootPath: '',
|
||||
isShow: '1',
|
||||
identity: ''
|
||||
}
|
||||
this.formData.formDialog = true;
|
||||
},
|
||||
showUpdate: function(data) {
|
||||
this.getResourceTree(data);
|
||||
// todo 设置数据进入表单
|
||||
this.formData.props = {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
url: data.url,
|
||||
parentId: data.parentId,
|
||||
sort: data.sort.toString(),
|
||||
type: data.type.toString(),
|
||||
status: data.status,
|
||||
rootPath: data.rootPath,
|
||||
isShow: data.isShow.toString(),
|
||||
identity: data.identity
|
||||
}
|
||||
this.formData.formDialog = true;
|
||||
},
|
||||
save: function() {
|
||||
var _this = this;
|
||||
this.disableBtn(this, 'btnSubmitDisabled');
|
||||
this['$refs'].saveForm.validate(function(valid) {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
if (_this.formData.props.type === 0) {
|
||||
_this.formData.props.parentId = 0;
|
||||
}
|
||||
// todo 注意构造参数_this.formData.props
|
||||
request({
|
||||
url: '/system/sysResource/save',
|
||||
method: 'post',
|
||||
data: _this.formData.props
|
||||
}).then(res => {
|
||||
_this.$message.success('保存成功');
|
||||
_this.getList({
|
||||
pageNo: 1,
|
||||
pageSize: _this.listQuery.pageSize
|
||||
});
|
||||
_this.formData.formDialog = false;
|
||||
})
|
||||
});
|
||||
},
|
||||
getResourceTree(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'get',
|
||||
url: `/system/sysResource/getResourceTree`
|
||||
}).then(res => {
|
||||
_this.elTree.list = res.data;
|
||||
if (data != null && data.type !== 0) {
|
||||
_this.currentLivingId = data.parentId;
|
||||
_this.$nextTick(function() {
|
||||
_this.$refs.tree.setCurrentKey(this.currentLivingId);
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleNodeClick(node, data, value) {
|
||||
this.formData.props.parentId = node.id;
|
||||
this.formData.props.parentName = node.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -1,342 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="search-container">
|
||||
<el-input v-model="keywords" class="search-input" placeholder="请输入角色名" :clearable="true" @keyup.enter.native="getList({pageNo:1})" />
|
||||
<el-button type="primary" size="small" icon="el-icon-search" @click="getList({pageNo:1})">搜索</el-button>
|
||||
</div>
|
||||
<div class="function-buttons">
|
||||
<el-button v-hasPermission="['sys_role_add']" type="primary" size="small" icon="el-icon-edit" @click="save">新增</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row>
|
||||
<el-table-column align="center" label="序号" width="120px" type="index" />
|
||||
|
||||
<el-table-column align="center" label="角色名">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" label="描 述">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.description }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" label="添加时间">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.createTime | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-hasPermission="['sys_role_edit']" type="text" @click="update(scope.row)">编辑</el-button>
|
||||
<el-button v-hasPermission="['sys_role_addResource']" type="text" @click="assignmentShow(scope.row)">分配权限</el-button>
|
||||
<el-popconfirm
|
||||
title="确认删除吗?"
|
||||
confirm-button-type="warning"
|
||||
confirm-button-text="删除"
|
||||
class="customConfirm"
|
||||
@onConfirm="del(scope.row.id)"
|
||||
>
|
||||
<el-button slot="reference" v-hasPermission="['sys_role_delete']" type="text">删除</el-button>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.pageNo" :limit.sync="listQuery.pageSize" @pagination="pageChange" />
|
||||
</div>
|
||||
<div>
|
||||
<el-dialog title="更新" :visible.sync="saveForm.visible">
|
||||
<el-form ref="saveForm" :model="saveForm.props" :rules="saveForm.rules" label-width="80px">
|
||||
<el-form-item label="角色名" prop="name">
|
||||
<el-input v-model="saveForm.props.name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描 述" prop="description">
|
||||
<el-input v-model="saveForm.props.description" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel('saveForm')">取 消</el-button>
|
||||
<el-button type="primary" @click="doSave">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog title="分配权限" :visible.sync="assignment.visible">
|
||||
<el-form ref="saveForm" label-width="80px" style="max-height: 500px;overflow: auto">
|
||||
<el-tree
|
||||
ref="tree"
|
||||
:data="assignment.list"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
default-expand-all
|
||||
:props="assignment.defaultProps"
|
||||
:default-checked-keys="assignment.roleResourceIdList"
|
||||
@check="handleClick"
|
||||
/>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="assignment.visible = false">取 消</el-button>
|
||||
<el-button type="primary" :disabled="btnSubmitDisabled" @click="assignmentSave">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
|
||||
import request from '@/utils/request'
|
||||
export default {
|
||||
name: 'TopicList',
|
||||
components: { Pagination },
|
||||
data() {
|
||||
return {
|
||||
btnSubmitDisabled: false,
|
||||
visible: false,
|
||||
list: null,
|
||||
keywords: null,
|
||||
total: 0,
|
||||
listLoading: true,
|
||||
listQuery: {
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
saveForm: {
|
||||
visible: false,
|
||||
props: {
|
||||
id: '',
|
||||
name: '',
|
||||
description: '',
|
||||
createTime: ''
|
||||
},
|
||||
rules: {
|
||||
name: this.formRules({
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 100
|
||||
}),
|
||||
description: this.formRules({
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 100
|
||||
}),
|
||||
postImgPath: this.formRules({
|
||||
required: true
|
||||
}),
|
||||
title: this.formRules({
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 100
|
||||
}),
|
||||
announcement: this.formRules({
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 200
|
||||
}),
|
||||
validDateRange: this.formRules({
|
||||
type: 'array',
|
||||
required: true
|
||||
}),
|
||||
contentPath: this.formRules({
|
||||
required: true
|
||||
})
|
||||
}
|
||||
},
|
||||
assignment: {
|
||||
visible: false,
|
||||
list: [],
|
||||
resourcesIds: [],
|
||||
roleResourceIdList: [],
|
||||
defaultProps: {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList({
|
||||
pageNo: this.listQuery.pageNo
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
pageChange(page) {
|
||||
this.getList({
|
||||
pageNo: page.page
|
||||
})
|
||||
},
|
||||
getList(params) {
|
||||
this.listLoading = true;
|
||||
const pageNo = params.pageNo ? params.pageNo : this.listQuery.pageNo;
|
||||
request({
|
||||
url: '/system/sysRole/getPageList',
|
||||
method: 'post',
|
||||
data: {
|
||||
name: this.keywords,
|
||||
pageNo: pageNo,
|
||||
pageSize: this.listQuery.pageSize
|
||||
}
|
||||
}).then(res => {
|
||||
const data = res.data;
|
||||
this.list = data.rows;
|
||||
this.total = data.total;
|
||||
if (data.pageCount < pageNo) {
|
||||
this.listQuery.pageNo = data.pageCount;
|
||||
}
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
save() {
|
||||
this.saveForm.props = {
|
||||
id: '',
|
||||
name: '',
|
||||
description: '',
|
||||
createTime: ''
|
||||
};
|
||||
this.saveForm.visible = true
|
||||
},
|
||||
update(data) {
|
||||
this.saveForm.props = {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
description: data.description
|
||||
};
|
||||
this.saveForm.visible = true
|
||||
},
|
||||
del(id) {
|
||||
const _this = this;
|
||||
request({
|
||||
url: '/system/sysRole/delete',
|
||||
method: 'post',
|
||||
params: {
|
||||
id: id
|
||||
}
|
||||
}).then(res => {
|
||||
this.$message.success('删除成功')
|
||||
this.getList({
|
||||
pageNo: (this.list.length === 1 && _this.listQuery.pageNo !== 1) ? _this.listQuery.pageNo - 1 : _this.listQuery.pageNo
|
||||
});
|
||||
})
|
||||
},
|
||||
doSave() {
|
||||
const _this = this;
|
||||
this.$refs.saveForm.validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
request({
|
||||
url: '/system/sysRole/save',
|
||||
method: 'post',
|
||||
data: {
|
||||
id: _this.saveForm.props.id,
|
||||
description: _this.saveForm.props.description,
|
||||
name: _this.saveForm.props.name
|
||||
}
|
||||
}).then(res => {
|
||||
_this.$message.success('保存成功');
|
||||
_this.getList({
|
||||
pageNo: 1
|
||||
});
|
||||
_this.saveForm.visible = false;
|
||||
})
|
||||
});
|
||||
},
|
||||
postImgUploadSuccess(res, file) {
|
||||
if (res.code !== 200) {
|
||||
this.$message.error('上传失败: ' + res.message);
|
||||
return;
|
||||
}
|
||||
this.saveForm.props.postImgPath = res.data.url;
|
||||
},
|
||||
// 取消
|
||||
cancel(formName) {
|
||||
this.$refs[formName].clearValidate();
|
||||
this.$refs[formName].resetFields();
|
||||
this.saveForm.visible = false;
|
||||
},
|
||||
assignmentShow(data) {
|
||||
this.saveForm.props.id = data.id;
|
||||
this.assignment.resourcesIds = [];
|
||||
this.assignment.roleResourceIdList = [];
|
||||
this.getRoleResourceIdList(data.id);
|
||||
},
|
||||
getResourceTree(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'get',
|
||||
url: `/system/sysResource/getResourceTree`
|
||||
}).then(res => {
|
||||
_this.assignment.list = res.data;
|
||||
if (data != null) {
|
||||
_this.$nextTick(function() {
|
||||
_this.$refs.tree.setCheckedKeys(data);
|
||||
})
|
||||
}
|
||||
this.assignment.visible = true
|
||||
})
|
||||
},
|
||||
getRoleResourceIdList(roleId) {
|
||||
var _this = this;
|
||||
request({
|
||||
url: `/system/sysRoleResource/getResourcesIdListByRoleId`,
|
||||
method: 'post',
|
||||
data: {
|
||||
roleId: roleId
|
||||
}
|
||||
}).then(res => {
|
||||
_this.assignment.roleResourceIdList = res.data.checkedTreeList;
|
||||
_this.assignment.resourcesIds = res.data.treeList;
|
||||
_this.getResourceTree(_this.assignment.roleResourceIdList)
|
||||
})
|
||||
},
|
||||
handleClick(nodeObj, selectedObj) {
|
||||
this.assignment.resourcesIds = selectedObj.checkedKeys.concat(selectedObj.halfCheckedKeys);
|
||||
},
|
||||
assignmentSave() {
|
||||
const _this = this;
|
||||
this.btnSubmitDisabled = true;
|
||||
request({
|
||||
url: '/system/sysRoleResource/addResource',
|
||||
method: 'post',
|
||||
data: {
|
||||
resourcesIds: this.assignment.resourcesIds,
|
||||
roleId: _this.saveForm.props.id
|
||||
}
|
||||
}).then(res => {
|
||||
_this.$message.success('保存成功');
|
||||
_this.assignment.visible = false;
|
||||
_this.btnSubmitDisabled = false;
|
||||
}).catch(e => {
|
||||
_this.btnSubmitDisabled = false;
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.el-upload:hover {
|
||||
border-color: #409EFF;
|
||||
}
|
||||
.upload-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
line-height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
.post-image {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@ -1,235 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="search-container">
|
||||
<el-input v-model="searchForm.username" class="search-input" clearable placeholder="请输入登录账号" />
|
||||
<el-input v-model="searchForm.phone" class="search-input" clearable placeholder="请输入手机号" />
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList({pageNo: 1})">搜索</el-button>
|
||||
</div>
|
||||
<div class="function-buttons" />
|
||||
<div>
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%">
|
||||
<el-table-column align="center" label="#" width="80" type="index" />
|
||||
|
||||
<el-table-column width="" align="center" label="用户昵称">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.nickname }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="登录账号">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.username }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="手机号">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.phone }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="登录时间">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.loginTime | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="注册时间">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.createTime | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.pageNo" :limit.sync="listQuery.pageSize" @pagination="pageChange" />
|
||||
</div>
|
||||
<!-- todo 调整表单字段 -->
|
||||
<el-dialog title="编辑" :visible.sync="formData.formDialog" :close-on-click-modal="false">
|
||||
<el-form ref="saveForm" :model="formData.props" :rules="formData.rules" label-width="180px">
|
||||
<el-form-item label="用户昵称" prop="nickname">
|
||||
<el-input v-model="formData.props.nickname" placeholder="请输入用户昵称" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录账号" prop="username">
|
||||
<el-input v-model="formData.props.username" placeholder="请输入登录账号" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input v-model="formData.props.password" placeholder="请输入密码" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-input v-model="formData.props.phone" placeholder="请输入手机号" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据状态" prop="status">
|
||||
<el-input v-model="formData.props.status" placeholder="请输入数据状态" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录时间" prop="loginTime">
|
||||
<el-input v-model="formData.props.loginTime" placeholder="请输入登录时间" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="更新时间" prop="updateTime">
|
||||
<el-input v-model="formData.props.updateTime" placeholder="请输入更新时间" :clearable="true" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="formData.formDialog = false">取 消</el-button>
|
||||
<el-button type="primary" :disabled="btnSubmitDisabled" @click="save">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
|
||||
import request from '@/utils/request'
|
||||
|
||||
export default {
|
||||
name: 'AppUserList',
|
||||
components: { Pagination },
|
||||
data() {
|
||||
return {
|
||||
btnSubmitDisabled: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
listLoading: true,
|
||||
listQuery: {
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
formData: {
|
||||
formDialog: false,
|
||||
// 表单字段, 请自行删除不需要的
|
||||
props: {
|
||||
nickname: '',
|
||||
username: '',
|
||||
password: '',
|
||||
phone: '',
|
||||
status: '',
|
||||
loginTime: '',
|
||||
updateTime: ''
|
||||
},
|
||||
// 表单校验规则, 默认增加了必填, 请自行限制长度或者其他修改
|
||||
rules: {
|
||||
nickname: this.formRules({ required: true }),
|
||||
username: this.formRules({ required: true }),
|
||||
password: this.formRules({ required: true }),
|
||||
phone: this.formRules({ required: true }),
|
||||
status: this.formRules({ required: true }),
|
||||
loginTime: this.formRules({ required: true }),
|
||||
updateTime: this.formRules({ required: true })
|
||||
}
|
||||
},
|
||||
searchForm: {
|
||||
username: '',
|
||||
phone: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList({
|
||||
pageNo: this.listQuery.pageNo
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
pageChange(page) {
|
||||
this.getList({
|
||||
pageNo: page.page,
|
||||
pageSize: page.limit
|
||||
})
|
||||
},
|
||||
getList(params) {
|
||||
this.listLoading = true
|
||||
request({
|
||||
url: '/user/appUser/getPageList',
|
||||
method: 'post',
|
||||
data: {
|
||||
pageNo: params.pageNo,
|
||||
pageSize: params.pageSize ? params.pageSize : this.listQuery.pageSize,
|
||||
...this.searchForm
|
||||
}
|
||||
}).then(res => {
|
||||
const data = res.data;
|
||||
this.list = data.rows;
|
||||
this.total = data.total;
|
||||
this.listQuery.pageNo = params.pageNo;
|
||||
this.listLoading = false;
|
||||
}, () => {
|
||||
this.listLoading = false;
|
||||
})
|
||||
},
|
||||
audit(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'post',
|
||||
url: `/user/appUser/audit?id=${data.id}`,
|
||||
data: {}
|
||||
}).then(res => {
|
||||
_this.$message.success('审核成功');
|
||||
data.status = 1;
|
||||
})
|
||||
},
|
||||
unaudit(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'post',
|
||||
url: `/user/appUser/unaudit?id=${data.id}`,
|
||||
data: {}
|
||||
}).then(res => {
|
||||
_this.$message.success('取消审核成功');
|
||||
data.status = 0;
|
||||
})
|
||||
},
|
||||
showAdd: function() {
|
||||
// todo 清除表单中的数据
|
||||
this.formData.props = {
|
||||
id: '',
|
||||
nickname: '',
|
||||
username: '',
|
||||
password: '',
|
||||
phone: '',
|
||||
status: '',
|
||||
loginTime: '',
|
||||
updateTime: ''
|
||||
}
|
||||
this.formData.formDialog = true;
|
||||
},
|
||||
showUpdate: function(data) {
|
||||
// todo 设置数据进入表单
|
||||
this.formData.props = {
|
||||
id: data.id,
|
||||
nickname: data.nickname,
|
||||
username: data.username,
|
||||
password: data.password,
|
||||
phone: data.phone,
|
||||
status: data.status,
|
||||
loginTime: data.loginTime,
|
||||
updateTime: data.updateTime
|
||||
}
|
||||
this.formData.formDialog = true;
|
||||
},
|
||||
save: function() {
|
||||
var _this = this;
|
||||
this.disableBtn(this, 'btnSubmitDisabled');
|
||||
this['$refs'].saveForm.validate(function(valid) {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// todo 注意构造参数_this.formData.props
|
||||
request({
|
||||
url: '/user/appUser/save',
|
||||
method: 'post',
|
||||
data: _this.formData.props
|
||||
}).then(res => {
|
||||
_this.$message.success('保存成功');
|
||||
_this.getList({
|
||||
pageNo: 1,
|
||||
pageSize: _this.listQuery.pageSize
|
||||
});
|
||||
_this.formData.formDialog = false;
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -1,215 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="search-container">
|
||||
<el-input v-model="searchForm.weaponryName" class="search-input" clearable placeholder="请输入武器名称" />
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList({pageNo: 1})">搜索</el-button>
|
||||
</div>
|
||||
<div class="function-buttons" />
|
||||
<div>
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%">
|
||||
<el-table-column align="center" label="#" width="80" type="index" />
|
||||
|
||||
<el-table-column width="" align="center" label="武器">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.weaponryName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="归还数量">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.num }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="" align="center" label="归还时间">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.createTime | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.pageNo" :limit.sync="listQuery.pageSize" @pagination="pageChange" />
|
||||
</div>
|
||||
<!-- todo 调整表单字段 -->
|
||||
<el-dialog title="编辑" :visible.sync="formData.formDialog" :close-on-click-modal="false">
|
||||
<el-form ref="saveForm" :model="formData.props" :rules="formData.rules" label-width="180px">
|
||||
<el-form-item label="武器ID" prop="weaponryId">
|
||||
<el-input v-model="formData.props.weaponryId" placeholder="请输入武器ID" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="记录ID" prop="lendRecordId">
|
||||
<el-input v-model="formData.props.lendRecordId" placeholder="请输入记录ID" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="借出数量" prop="num">
|
||||
<el-input v-model="formData.props.num" placeholder="请输入借出数量" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="归还时间" prop="returnTime">
|
||||
<el-input v-model="formData.props.returnTime" placeholder="请输入归还时间" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据状态" prop="status">
|
||||
<el-input v-model="formData.props.status" placeholder="请输入数据状态" :clearable="true" />
|
||||
</el-form-item>
|
||||
<el-form-item label="更新时间" prop="updateTime">
|
||||
<el-input v-model="formData.props.updateTime" placeholder="请输入更新时间" :clearable="true" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="formData.formDialog = false">取 消</el-button>
|
||||
<el-button type="primary" :disabled="btnSubmitDisabled" @click="save">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
|
||||
import request from '@/utils/request'
|
||||
|
||||
export default {
|
||||
name: 'WeaponryReturnRecordList',
|
||||
components: { Pagination },
|
||||
data() {
|
||||
return {
|
||||
btnSubmitDisabled: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
listLoading: true,
|
||||
listQuery: {
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
formData: {
|
||||
formDialog: false,
|
||||
// 表单字段, 请自行删除不需要的
|
||||
props: {
|
||||
weaponryId: '',
|
||||
weaponryName: '',
|
||||
lendRecordId: '',
|
||||
num: '',
|
||||
returnTime: '',
|
||||
status: '',
|
||||
updateTime: ''
|
||||
},
|
||||
// 表单校验规则, 默认增加了必填, 请自行限制长度或者其他修改
|
||||
rules: {
|
||||
weaponryId: this.formRules({ required: true }),
|
||||
lendRecordId: this.formRules({ required: true }),
|
||||
num: this.formRules({ required: true }),
|
||||
returnTime: this.formRules({ required: true }),
|
||||
status: this.formRules({ required: true }),
|
||||
updateTime: this.formRules({ required: true })
|
||||
}
|
||||
},
|
||||
searchForm: {
|
||||
weaponryName: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList({
|
||||
pageNo: this.listQuery.pageNo
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
pageChange(page) {
|
||||
this.getList({
|
||||
pageNo: page.page,
|
||||
pageSize: page.limit
|
||||
})
|
||||
},
|
||||
getList(params) {
|
||||
this.listLoading = true
|
||||
request({
|
||||
url: '/weaponry/weaponryReturnRecord/getPageList',
|
||||
method: 'post',
|
||||
data: {
|
||||
pageNo: params.pageNo,
|
||||
pageSize: params.pageSize ? params.pageSize : this.listQuery.pageSize,
|
||||
...this.searchForm
|
||||
}
|
||||
}).then(res => {
|
||||
const data = res.data;
|
||||
this.list = data.rows;
|
||||
this.total = data.total;
|
||||
this.listQuery.pageNo = params.pageNo;
|
||||
this.listLoading = false;
|
||||
}, () => {
|
||||
this.listLoading = false;
|
||||
})
|
||||
},
|
||||
audit(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'post',
|
||||
url: `/weaponry/weaponryReturnRecord/audit?id=${data.id}`,
|
||||
data: {}
|
||||
}).then(res => {
|
||||
_this.$message.success('审核成功');
|
||||
data.status = 1;
|
||||
})
|
||||
},
|
||||
unaudit(data) {
|
||||
var _this = this;
|
||||
request({
|
||||
method: 'post',
|
||||
url: `/weaponry/weaponryReturnRecord/unaudit?id=${data.id}`,
|
||||
data: {}
|
||||
}).then(res => {
|
||||
_this.$message.success('取消审核成功');
|
||||
data.status = 0;
|
||||
})
|
||||
},
|
||||
showAdd: function() {
|
||||
// todo 清除表单中的数据
|
||||
this.formData.props = {
|
||||
id: '',
|
||||
weaponryId: '',
|
||||
lendRecordId: '',
|
||||
num: '',
|
||||
returnTime: '',
|
||||
status: '',
|
||||
updateTime: ''
|
||||
}
|
||||
this.formData.formDialog = true;
|
||||
},
|
||||
showUpdate: function(data) {
|
||||
// todo 设置数据进入表单
|
||||
this.formData.props = {
|
||||
id: data.id,
|
||||
weaponryId: data.weaponryId,
|
||||
lendRecordId: data.lendRecordId,
|
||||
num: data.num,
|
||||
returnTime: data.returnTime,
|
||||
status: data.status,
|
||||
updateTime: data.updateTime
|
||||
}
|
||||
this.formData.formDialog = true;
|
||||
},
|
||||
save: function() {
|
||||
var _this = this;
|
||||
this.disableBtn(this, 'btnSubmitDisabled');
|
||||
this['$refs'].saveForm.validate(function(valid) {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// todo 注意构造参数_this.formData.props
|
||||
request({
|
||||
url: '/weaponry/weaponryReturnRecord/save',
|
||||
method: 'post',
|
||||
data: _this.formData.props
|
||||
}).then(res => {
|
||||
_this.$message.success('保存成功');
|
||||
_this.getList({
|
||||
pageNo: 1,
|
||||
pageSize: _this.listQuery.pageSize
|
||||
});
|
||||
_this.formData.formDialog = false;
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -1,23 +0,0 @@
|
||||
<template>
|
||||
<div class="chart-container">
|
||||
<chart height="100%" width="100%" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Chart from '@/components/Charts/Keyboard'
|
||||
|
||||
export default {
|
||||
name: 'KeyboardChart',
|
||||
components: { Chart }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-container{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: calc(100vh - 84px);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
<template>
|
||||
<div class="chart-container">
|
||||
<chart height="100%" width="100%" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Chart from '@/components/Charts/LineMarker'
|
||||
|
||||
export default {
|
||||
name: 'LineChart',
|
||||
components: { Chart }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-container{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: calc(100vh - 84px);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
<template>
|
||||
<div class="chart-container">
|
||||
<chart height="100%" width="100%" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Chart from '@/components/Charts/MixChart'
|
||||
|
||||
export default {
|
||||
name: 'MixChart',
|
||||
components: { Chart }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-container{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: calc(100vh - 84px);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="use clipboard directly" name="directly">
|
||||
<el-input v-model="inputData" placeholder="Please input" style="width:400px;max-width:100%;" />
|
||||
<el-button type="primary" icon="document" @click="handleCopy(inputData,$event)">
|
||||
copy
|
||||
</el-button>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="use clipboard by v-directive" name="v-directive">
|
||||
<el-input v-model="inputData" placeholder="Please input" style="width:400px;max-width:100%;" />
|
||||
<el-button v-clipboard:copy="inputData" v-clipboard:success="clipboardSuccess" type="primary" icon="document">
|
||||
copy
|
||||
</el-button>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import clip from '@/utils/clipboard' // use clipboard directly
|
||||
import clipboard from '@/directive/clipboard/index.js' // use clipboard by v-directive
|
||||
|
||||
export default {
|
||||
name: 'ClipboardDemo',
|
||||
directives: {
|
||||
clipboard
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'directly',
|
||||
inputData: 'https://github.com/PanJiaChen/vue-element-admin'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCopy(text, event) {
|
||||
clip(text, event)
|
||||
},
|
||||
clipboardSuccess() {
|
||||
this.$message({
|
||||
message: 'Copy successfully',
|
||||
type: 'success',
|
||||
duration: 1500
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<aside>This is based on
|
||||
<a class="link-type" href="//github.com/dai-siki/vue-image-crop-upload"> vue-image-crop-upload</a>.
|
||||
Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.
|
||||
</aside>
|
||||
|
||||
<pan-thumb :image="image" />
|
||||
|
||||
<el-button type="primary" icon="upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="imagecropperShow=true">
|
||||
Change Avatar
|
||||
</el-button>
|
||||
|
||||
<image-cropper
|
||||
v-show="imagecropperShow"
|
||||
:key="imagecropperKey"
|
||||
:width="300"
|
||||
:height="300"
|
||||
url="https://httpbin.org/post"
|
||||
lang-type="en"
|
||||
@close="close"
|
||||
@crop-upload-success="cropSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ImageCropper from '@/components/ImageCropper'
|
||||
import PanThumb from '@/components/PanThumb'
|
||||
|
||||
export default {
|
||||
name: 'AvatarUploadDemo',
|
||||
components: { ImageCropper, PanThumb },
|
||||
data() {
|
||||
return {
|
||||
imagecropperShow: false,
|
||||
imagecropperKey: 0,
|
||||
image: 'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cropSuccess(resData) {
|
||||
this.imagecropperShow = false
|
||||
this.imagecropperKey = this.imagecropperKey + 1
|
||||
this.image = resData.files.avatar
|
||||
},
|
||||
close() {
|
||||
this.imagecropperShow = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.avatar{
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,154 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<aside>
|
||||
When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner
|
||||
</aside>
|
||||
<aside>
|
||||
You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally
|
||||
</aside>
|
||||
<div class="placeholder-container">
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
</div>
|
||||
<!-- you can add element-ui's tooltip -->
|
||||
<el-tooltip placement="top" content="tooltip">
|
||||
<back-to-top :custom-style="myBackToTopStyle" :visibility-height="300" :back-position="50" transition-name="fade" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BackToTop from '@/components/BackToTop'
|
||||
|
||||
export default {
|
||||
name: 'BackToTopDemo',
|
||||
components: { BackToTop },
|
||||
data() {
|
||||
return {
|
||||
// customizable button style, show/hide critical point, return position
|
||||
myBackToTopStyle: {
|
||||
right: '50px',
|
||||
bottom: '50px',
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
'border-radius': '4px',
|
||||
'line-height': '45px', // 请保持与高度一致以垂直居中 Please keep consistent with height to center vertically
|
||||
background: '#e7eaf1'// 按钮的背景颜色 The background color of the button
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.placeholder-container div {
|
||||
margin: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,218 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<aside>
|
||||
<a href="https://github.com/PanJiaChen/vue-countTo" target="_blank">countTo-component</a>
|
||||
</aside>
|
||||
<count-to
|
||||
ref="example"
|
||||
:start-val="_startVal"
|
||||
:end-val="_endVal"
|
||||
:duration="_duration"
|
||||
:decimals="_decimals"
|
||||
:separator="_separator"
|
||||
:prefix="_prefix"
|
||||
:suffix="_suffix"
|
||||
:autoplay="false"
|
||||
class="example"
|
||||
/>
|
||||
<div style="margin-left: 25%;margin-top: 40px;">
|
||||
<label class="label" for="startValInput">startVal:
|
||||
<input v-model.number="setStartVal" type="number" name="startValInput">
|
||||
</label>
|
||||
<label class="label" for="endValInput">endVal:
|
||||
<input v-model.number="setEndVal" type="number" name="endVaInput">
|
||||
</label>
|
||||
<label class="label" for="durationInput">duration:
|
||||
<input v-model.number="setDuration" type="number" name="durationInput">
|
||||
</label>
|
||||
<div class="startBtn example-btn" @click="start">
|
||||
Start
|
||||
</div>
|
||||
<div class="pause-resume-btn example-btn" @click="pauseResume">
|
||||
pause/resume
|
||||
</div>
|
||||
<br>
|
||||
<label class="label" for="decimalsInput">decimals:
|
||||
<input v-model.number="setDecimals" type="number" name="decimalsInput">
|
||||
</label>
|
||||
<label class="label" for="separatorInput">separator:
|
||||
<input v-model="setSeparator" name="separatorInput">
|
||||
</label>
|
||||
<label class="label" for="prefixInput">prefix:
|
||||
<input v-model="setPrefix" name="prefixInput">
|
||||
</label>
|
||||
<label class="label" for="suffixInput">suffix:
|
||||
<input v-model="setSuffix" name="suffixInput">
|
||||
</label>
|
||||
</div>
|
||||
<aside><count-to :start-val='{{ _startVal }}' :end-val='{{ _endVal }}' :duration='{{ _duration }}'
|
||||
:decimals='{{ _decimals }}' :separator='{{ _separator }}' :prefix='{{ _prefix }}' :suffix='{{ _suffix }}'
|
||||
:autoplay=false></aside>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import countTo from 'vue-count-to'
|
||||
|
||||
export default {
|
||||
name: 'CountToDemo',
|
||||
components: { countTo },
|
||||
data() {
|
||||
return {
|
||||
setStartVal: 0,
|
||||
setEndVal: 2017,
|
||||
setDuration: 4000,
|
||||
setDecimals: 0,
|
||||
setSeparator: ',',
|
||||
setSuffix: ' rmb',
|
||||
setPrefix: '¥ '
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
_startVal() {
|
||||
if (this.setStartVal) {
|
||||
return this.setStartVal
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
_endVal() {
|
||||
if (this.setEndVal) {
|
||||
return this.setEndVal
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
_duration() {
|
||||
if (this.setDuration) {
|
||||
return this.setDuration
|
||||
} else {
|
||||
return 100
|
||||
}
|
||||
},
|
||||
_decimals() {
|
||||
if (this.setDecimals) {
|
||||
if (this.setDecimals < 0 || this.setDecimals > 20) {
|
||||
alert('digits argument must be between 0 and 20')
|
||||
return 0
|
||||
}
|
||||
return this.setDecimals
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
_separator() {
|
||||
return this.setSeparator
|
||||
},
|
||||
_suffix() {
|
||||
return this.setSuffix
|
||||
},
|
||||
_prefix() {
|
||||
return this.setPrefix
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
start() {
|
||||
this.$refs.example.start()
|
||||
},
|
||||
pauseResume() {
|
||||
this.$refs.example.pauseResume()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.example-btn {
|
||||
display: inline-block;
|
||||
margin-bottom: 0;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
-ms-touch-action: manipulation;
|
||||
touch-action: manipulation;
|
||||
cursor: pointer;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
line-height: 1.5;
|
||||
padding: 4px 15px;
|
||||
font-size: 12px;
|
||||
border-radius: 4px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1);
|
||||
transition: all .3s cubic-bezier(.645, .045, .355, 1);
|
||||
position: relative;
|
||||
color: rgba(0, 0, 0, .65);
|
||||
background-color: #fff;
|
||||
border-color: #d9d9d9;
|
||||
}
|
||||
|
||||
.example-btn:hover {
|
||||
color: #4AB7BD;
|
||||
background-color: #fff;
|
||||
border-color: #4AB7BD;
|
||||
}
|
||||
.example {
|
||||
font-size: 50px;
|
||||
color: #F6416C;
|
||||
display: block;
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
font-size: 80px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #2f4f4f;
|
||||
font-size: 16px;
|
||||
display: inline-block;
|
||||
margin: 15px 30px 15px 0;
|
||||
}
|
||||
|
||||
input {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: 4px 7px;
|
||||
width: 70px;
|
||||
height: 28px;
|
||||
cursor: text;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
color: rgba(0, 0, 0, .65);
|
||||
background-color: #fff;
|
||||
background-image: none;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
-webkit-transition: all .3s;
|
||||
transition: all .3s;
|
||||
}
|
||||
|
||||
.startBtn {
|
||||
margin-left: 20px;
|
||||
font-size: 20px;
|
||||
color: #30B08F;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.startBtn:hover {
|
||||
background-color: #30B08F;
|
||||
color: #fff;
|
||||
border-color: #30B08F;
|
||||
}
|
||||
|
||||
.pause-resume-btn {
|
||||
font-size: 20px;
|
||||
color: #E65D6E;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.pause-resume-btn:hover {
|
||||
background-color: #E65D6E;
|
||||
color: #fff;
|
||||
border-color: #E65D6E;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<aside>drag-list base on
|
||||
<a href="https://github.com/SortableJS/Vue.Draggable" target="_blank">Vue.Draggable</a>
|
||||
</aside>
|
||||
<div class="editor-container">
|
||||
<dnd-list :list1="list1" :list2="list2" list1-title="List" list2-title="Article pool" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DndList from '@/components/DndList'
|
||||
import { fetchList } from '@/api/article'
|
||||
|
||||
export default {
|
||||
name: 'DndListDemo',
|
||||
components: { DndList },
|
||||
data() {
|
||||
return {
|
||||
list1: [],
|
||||
list2: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
this.listLoading = true
|
||||
fetchList().then(response => {
|
||||
this.list1 = response.data.items.splice(0, 5)
|
||||
this.list2 = response.data.items
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<el-button type="primary" @click="dialogTableVisible = true">
|
||||
open a Drag Dialog
|
||||
</el-button>
|
||||
<el-dialog v-el-drag-dialog :visible.sync="dialogTableVisible" title="Shipping address" @dragDialog="handleDrag">
|
||||
<el-select ref="select" v-model="value" placeholder="请选择">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<el-table :data="gridData">
|
||||
<el-table-column property="date" label="Date" width="150" />
|
||||
<el-table-column property="name" label="Name" width="200" />
|
||||
<el-table-column property="address" label="Address" />
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import elDragDialog from '@/directive/el-drag-dialog' // base on element-ui
|
||||
|
||||
export default {
|
||||
name: 'DragDialogDemo',
|
||||
directives: { elDragDialog },
|
||||
data() {
|
||||
return {
|
||||
dialogTableVisible: false,
|
||||
options: [
|
||||
{ value: '选项1', label: '黄金糕' },
|
||||
{ value: '选项2', label: '双皮奶' },
|
||||
{ value: '选项3', label: '蚵仔煎' },
|
||||
{ value: '选项4', label: '龙须面' }
|
||||
],
|
||||
value: '',
|
||||
gridData: [{
|
||||
date: '2016-05-02',
|
||||
name: 'John Smith',
|
||||
address: 'No.1518, Jinshajiang Road, Putuo District'
|
||||
}, {
|
||||
date: '2016-05-04',
|
||||
name: 'John Smith',
|
||||
address: 'No.1518, Jinshajiang Road, Putuo District'
|
||||
}, {
|
||||
date: '2016-05-01',
|
||||
name: 'John Smith',
|
||||
address: 'No.1518, Jinshajiang Road, Putuo District'
|
||||
}, {
|
||||
date: '2016-05-03',
|
||||
name: 'John Smith',
|
||||
address: 'No.1518, Jinshajiang Road, Putuo District'
|
||||
}]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// v-el-drag-dialog onDrag callback function
|
||||
handleDrag() {
|
||||
this.$refs.select.blur()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,66 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container board">
|
||||
<Kanban :key="1" :list="list1" :group="group" class="kanban todo" header-text="Todo" />
|
||||
<Kanban :key="2" :list="list2" :group="group" class="kanban working" header-text="Working" />
|
||||
<Kanban :key="3" :list="list3" :group="group" class="kanban done" header-text="Done" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Kanban from '@/components/Kanban'
|
||||
|
||||
export default {
|
||||
name: 'DragKanbanDemo',
|
||||
components: {
|
||||
Kanban
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
group: 'mission',
|
||||
list1: [
|
||||
{ name: 'Mission', id: 1 },
|
||||
{ name: 'Mission', id: 2 },
|
||||
{ name: 'Mission', id: 3 },
|
||||
{ name: 'Mission', id: 4 }
|
||||
],
|
||||
list2: [
|
||||
{ name: 'Mission', id: 5 },
|
||||
{ name: 'Mission', id: 6 },
|
||||
{ name: 'Mission', id: 7 }
|
||||
],
|
||||
list3: [
|
||||
{ name: 'Mission', id: 8 },
|
||||
{ name: 'Mission', id: 9 },
|
||||
{ name: 'Mission', id: 10 }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.board {
|
||||
width: 1000px;
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.kanban {
|
||||
&.todo {
|
||||
.board-column-header {
|
||||
background: #4A9FF9;
|
||||
}
|
||||
}
|
||||
&.working {
|
||||
.board-column-header {
|
||||
background: #f9944a;
|
||||
}
|
||||
}
|
||||
&.done {
|
||||
.board-column-header {
|
||||
background: #2ac06d;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<el-drag-select v-model="value" style="width:500px;" multiple placeholder="请选择">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-drag-select>
|
||||
|
||||
<div style="margin-top:30px;">
|
||||
<el-tag v-for="item of value" :key="item" style="margin-right:15px;">
|
||||
{{ item }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ElDragSelect from '@/components/DragSelect' // base on element-ui
|
||||
|
||||
export default {
|
||||
name: 'DragSelectDemo',
|
||||
components: { ElDragSelect },
|
||||
data() {
|
||||
return {
|
||||
value: ['Apple', 'Banana', 'Orange'],
|
||||
options: [{
|
||||
value: 'Apple',
|
||||
label: 'Apple'
|
||||
}, {
|
||||
value: 'Banana',
|
||||
label: 'Banana'
|
||||
}, {
|
||||
value: 'Orange',
|
||||
label: 'Orange'
|
||||
}, {
|
||||
value: 'Pear',
|
||||
label: 'Pear'
|
||||
}, {
|
||||
value: 'Strawberry',
|
||||
label: 'Strawberry'
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,31 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<aside>
|
||||
Based on <a class="link-type" href="https://github.com/rowanwins/vue-dropzone"> dropzone </a>.
|
||||
Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.
|
||||
</aside>
|
||||
<div class="editor-container">
|
||||
<dropzone id="myVueDropzone" url="https://httpbin.org/post" @dropzone-removedFile="dropzoneR" @dropzone-success="dropzoneS" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Dropzone from '@/components/Dropzone'
|
||||
|
||||
export default {
|
||||
name: 'DropzoneDemo',
|
||||
components: { Dropzone },
|
||||
methods: {
|
||||
dropzoneS(file) {
|
||||
console.log(file)
|
||||
this.$message({ message: 'Upload success', type: 'success' })
|
||||
},
|
||||
dropzoneR(file) {
|
||||
console.log(file)
|
||||
this.$message({ message: 'Delete success', type: 'success' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<aside>Json-Editor is base on <a href="https://github.com/codemirror/CodeMirror" target="_blank">CodeMirrorr</a>. Lint
|
||||
base on <a
|
||||
href="https://github.com/codemirror/CodeMirror/blob/master/addon/lint/json-lint.js"
|
||||
target="_blank"
|
||||
>json-lint</a>.</aside>
|
||||
<div class="editor-container">
|
||||
<json-editor ref="jsonEditor" v-model="value" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import JsonEditor from '@/components/JsonEditor'
|
||||
|
||||
const jsonData = '[{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"CORN"}],"name":""},{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"XAGUSD"},{"market_type":"forexdata","symbol":"AUTD"},{"market_type":"forexdata","symbol":"AGTD"}],"name":"贵金属"},{"items":[{"market_type":"forexdata","symbol":"CORN"},{"market_type":"forexdata","symbol":"WHEAT"},{"market_type":"forexdata","symbol":"SOYBEAN"},{"market_type":"forexdata","symbol":"SUGAR"}],"name":"农产品"},{"items":[{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"USOIL"},{"market_type":"forexdata","symbol":"NGAS"}],"name":"能源化工"}]'
|
||||
|
||||
export default {
|
||||
name: 'JsonEditorDemo',
|
||||
components: { JsonEditor },
|
||||
data() {
|
||||
return {
|
||||
value: JSON.parse(jsonData)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.editor-container{
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,169 +0,0 @@
|
||||
<template>
|
||||
<div class="mixin-components-container">
|
||||
<el-row>
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>Buttons</span>
|
||||
</div>
|
||||
<div style="margin-bottom:50px;">
|
||||
<el-col :span="4" class="text-center">
|
||||
<router-link class="pan-btn blue-btn" to="/documentation/index">
|
||||
Documentation
|
||||
</router-link>
|
||||
</el-col>
|
||||
<el-col :span="4" class="text-center">
|
||||
<router-link class="pan-btn light-blue-btn" to="/icon/index">
|
||||
Icons
|
||||
</router-link>
|
||||
</el-col>
|
||||
<el-col :span="4" class="text-center">
|
||||
<router-link class="pan-btn pink-btn" to="/excel/export-excel">
|
||||
Excel
|
||||
</router-link>
|
||||
</el-col>
|
||||
<el-col :span="4" class="text-center">
|
||||
<router-link class="pan-btn green-btn" to="/table/complex-table">
|
||||
Table
|
||||
</router-link>
|
||||
</el-col>
|
||||
<el-col :span="4" class="text-center">
|
||||
<router-link class="pan-btn tiffany-btn" to="/example/create">
|
||||
Form
|
||||
</router-link>
|
||||
</el-col>
|
||||
<el-col :span="4" class="text-center">
|
||||
<router-link class="pan-btn yellow-btn" to="/theme/index">
|
||||
Theme
|
||||
</router-link>
|
||||
</el-col>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20" style="margin-top:50px;">
|
||||
<el-col :span="6">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>Material Design 的input</span>
|
||||
</div>
|
||||
<div style="height:100px;">
|
||||
<el-form :model="demo" :rules="demoRules">
|
||||
<el-form-item prop="title">
|
||||
<md-input v-model="demo.title" icon="search" name="title" placeholder="输入标题">
|
||||
标题
|
||||
</md-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>图片hover效果</span>
|
||||
</div>
|
||||
<div class="component-item">
|
||||
<pan-thumb width="100px" height="100px" image="https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191">
|
||||
vue-element-admin
|
||||
</pan-thumb>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>水波纹 waves v-directive</span>
|
||||
</div>
|
||||
<div class="component-item">
|
||||
<el-button v-waves type="primary">
|
||||
水波纹效果
|
||||
</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>hover text</span>
|
||||
</div>
|
||||
<div class="component-item">
|
||||
<mallki class-name="mallki-text" text="vue-element-admin" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20" style="margin-top:50px;">
|
||||
<el-col :span="8">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>Share</span>
|
||||
</div>
|
||||
<div class="component-item" style="height:420px;">
|
||||
<dropdown-menu :items="articleList" style="margin:0 auto;" title="系列文章" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PanThumb from '@/components/PanThumb'
|
||||
import MdInput from '@/components/MDinput'
|
||||
import Mallki from '@/components/TextHoverEffect/Mallki'
|
||||
import DropdownMenu from '@/components/Share/DropdownMenu'
|
||||
import waves from '@/directive/waves/index.js' // 水波纹指令
|
||||
|
||||
export default {
|
||||
name: 'ComponentMixinDemo',
|
||||
components: {
|
||||
PanThumb,
|
||||
MdInput,
|
||||
Mallki,
|
||||
DropdownMenu
|
||||
},
|
||||
directives: {
|
||||
waves
|
||||
},
|
||||
data() {
|
||||
const validate = (rule, value, callback) => {
|
||||
if (value.length !== 6) {
|
||||
callback(new Error('请输入六个字符'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
demo: {
|
||||
title: ''
|
||||
},
|
||||
demoRules: {
|
||||
title: [{ required: true, trigger: 'change', validator: validate }]
|
||||
},
|
||||
articleList: [
|
||||
{ title: '基础篇', href: 'https://juejin.im/post/59097cd7a22b9d0065fb61d2' },
|
||||
{ title: '登录权限篇', href: 'https://juejin.im/post/591aa14f570c35006961acac' },
|
||||
{ title: '实战篇', href: 'https://juejin.im/post/593121aa0ce4630057f70d35' },
|
||||
{ title: 'vue-admin-template 篇', href: 'https://juejin.im/post/595b4d776fb9a06bbe7dba56' },
|
||||
{ title: 'v4.0 篇', href: 'https://juejin.im/post/5c92ff94f265da6128275a85' },
|
||||
{ title: '优雅的使用 icon', href: 'https://juejin.im/post/59bb864b5188257e7a427c09' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mixin-components-container {
|
||||
background-color: #f0f2f5;
|
||||
padding: 30px;
|
||||
min-height: calc(100vh - 84px);
|
||||
}
|
||||
.component-item{
|
||||
min-height: 100px;
|
||||
}
|
||||
</style>
|
||||
@ -1,67 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<aside><strong>SplitPane</strong> If you've used
|
||||
<a href="https://codepen.io/" target="_blank"> codepen</a>,
|
||||
<a href="https://jsfiddle.net/" target="_blank"> jsfiddle </a>will not be unfamiliar.
|
||||
<a href="https://github.com/PanJiaChen/vue-split-pane" target="_blank"> Github repository</a>
|
||||
</aside>
|
||||
<split-pane split="vertical" @resize="resize">
|
||||
<template slot="paneL">
|
||||
<div class="left-container" />
|
||||
</template>
|
||||
<template slot="paneR">
|
||||
<split-pane split="horizontal">
|
||||
<template slot="paneL">
|
||||
<div class="top-container" />
|
||||
</template>
|
||||
<template slot="paneR">
|
||||
<div class="bottom-container" />
|
||||
</template>
|
||||
</split-pane>
|
||||
</template>
|
||||
</split-pane>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import splitPane from 'vue-splitpane'
|
||||
|
||||
export default {
|
||||
name: 'SplitpaneDemo',
|
||||
components: { splitPane },
|
||||
methods: {
|
||||
resize() {
|
||||
console.log('resize')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.components-container {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.left-container {
|
||||
background-color: #F38181;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.right-container {
|
||||
background-color: #FCE38A;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.top-container {
|
||||
background-color: #FCE38A;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.bottom-container {
|
||||
width: 100%;
|
||||
background-color: #95E1D3;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,135 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<sticky :z-index="10" class-name="sub-navbar">
|
||||
<el-dropdown trigger="click">
|
||||
<el-button plain>
|
||||
Platform<i class="el-icon-caret-bottom el-icon--right" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown" class="no-border">
|
||||
<el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
|
||||
<el-checkbox v-for="item in platformsOptions" :key="item.key" :label="item.key">
|
||||
{{ item.name }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
<el-dropdown trigger="click">
|
||||
<el-button plain>
|
||||
Link<i class="el-icon-caret-bottom el-icon--right" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown" class="no-padding no-border" style="width:300px">
|
||||
<el-input v-model="url" placeholder="Please enter the content">
|
||||
<template slot="prepend">
|
||||
Url
|
||||
</template>
|
||||
</el-input>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
|
||||
<div class="time-container">
|
||||
<el-date-picker v-model="time" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="Release time" />
|
||||
</div>
|
||||
|
||||
<el-button style="margin-left: 10px;" type="success">
|
||||
publish
|
||||
</el-button>
|
||||
</sticky>
|
||||
|
||||
<div class="components-container">
|
||||
<aside>
|
||||
Sticky header, When the page is scrolled to the preset position will be sticky on the top.
|
||||
</aside>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<sticky :sticky-top="200">
|
||||
<el-button type="primary"> placeholder</el-button>
|
||||
</sticky>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
<div>placeholder</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Sticky from '@/components/Sticky'
|
||||
|
||||
export default {
|
||||
name: 'StickyDemo',
|
||||
components: { Sticky },
|
||||
data() {
|
||||
return {
|
||||
time: '',
|
||||
url: '',
|
||||
platforms: ['a-platform'],
|
||||
platformsOptions: [
|
||||
{ key: 'a-platform', name: 'platformA' },
|
||||
{ key: 'b-platform', name: 'platformB' },
|
||||
{ key: 'c-platform', name: 'platformC' }
|
||||
],
|
||||
pickerOptions: {
|
||||
disabledDate(time) {
|
||||
return time.getTime() > Date.now()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.components-container div {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.time-container {
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@ -1,36 +0,0 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<aside>
|
||||
Rich text is a core feature of the management backend, but at the same time it is a place with lots of pits. In the process of selecting rich texts, I also took a lot of detours. The common rich texts on the market have been basically used, and I finally chose Tinymce. See the more detailed rich text comparison and introduction.
|
||||
<a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/component/rich-editor.html">Documentation</a>
|
||||
</aside>
|
||||
<div>
|
||||
<tinymce v-model="content" :height="300" />
|
||||
</div>
|
||||
<div class="editor-content" v-html="content" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Tinymce from '@/components/Tinymce'
|
||||
|
||||
export default {
|
||||
name: 'TinymceDemo',
|
||||
components: { Tinymce },
|
||||
data() {
|
||||
return {
|
||||
content:
|
||||
`<h1 style="text-align: center;">Welcome to the TinyMCE demo!</h1><p style="text-align: center; font-size: 15px;"><img title="TinyMCE Logo" src="//www.tinymce.com/images/glyph-tinymce@2x.png" alt="TinyMCE Logo" width="110" height="97" /><ul>
|
||||
<li>Our <a href="//www.tinymce.com/docs/">documentation</a> is a great resource for learning how to configure TinyMCE.</li><li>Have a specific question? Visit the <a href="https://community.tinymce.com/forum/">Community Forum</a>.</li><li>We also offer enterprise grade support as part of <a href="https://tinymce.com/pricing">TinyMCE premium subscriptions</a>.</li>
|
||||
</ul>`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.editor-content{
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,118 +0,0 @@
|
||||
<template>
|
||||
<el-card class="box-card-component" style="margin-left:8px;">
|
||||
<div slot="header" class="box-card-header">
|
||||
<img src="https://wpimg.wallstcn.com/e7d23d71-cf19-4b90-a1cc-f56af8c0903d.png">
|
||||
</div>
|
||||
<div style="position:relative;">
|
||||
<pan-thumb :image="avatar" class="panThumb" />
|
||||
<mallki class-name="mallki-text" text="vue-element-admin" />
|
||||
<div style="padding-top:35px;" class="progress-item">
|
||||
<span>Vue</span>
|
||||
<el-progress :percentage="70" />
|
||||
</div>
|
||||
<div class="progress-item">
|
||||
<span>JavaScript</span>
|
||||
<el-progress :percentage="18" />
|
||||
</div>
|
||||
<div class="progress-item">
|
||||
<span>Css</span>
|
||||
<el-progress :percentage="12" />
|
||||
</div>
|
||||
<div class="progress-item">
|
||||
<span>ESLint</span>
|
||||
<el-progress :percentage="100" status="success" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import PanThumb from '@/components/PanThumb'
|
||||
import Mallki from '@/components/TextHoverEffect/Mallki'
|
||||
|
||||
export default {
|
||||
components: { PanThumb, Mallki },
|
||||
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
success: 'success',
|
||||
pending: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
statisticsData: {
|
||||
article_count: 1024,
|
||||
pageviews_count: 1024
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'name',
|
||||
'avatar',
|
||||
'roles'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" >
|
||||
.box-card-component{
|
||||
.el-card__header {
|
||||
padding: 0px!important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.box-card-component {
|
||||
.box-card-header {
|
||||
position: relative;
|
||||
height: 220px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: all 0.2s linear;
|
||||
&:hover {
|
||||
transform: scale(1.1, 1.1);
|
||||
filter: contrast(130%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.mallki-text {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.panThumb {
|
||||
z-index: 100;
|
||||
height: 70px!important;
|
||||
width: 70px!important;
|
||||
position: absolute!important;
|
||||
top: -45px;
|
||||
left: 0px;
|
||||
border: 5px solid #ffffff;
|
||||
background-color: #fff;
|
||||
margin: auto;
|
||||
box-shadow: none!important;
|
||||
/deep/ .pan-info {
|
||||
box-shadow: none!important;
|
||||
}
|
||||
}
|
||||
.progress-item {
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
@media only screen and (max-width: 1510px){
|
||||
.mallki-text{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,135 +0,0 @@
|
||||
<template>
|
||||
<div :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '350px'
|
||||
},
|
||||
autoResize: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
chartData: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
chartData: {
|
||||
deep: true,
|
||||
handler(val) {
|
||||
this.setOptions(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initChart()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(this.$el, 'macarons')
|
||||
this.setOptions(this.chartData)
|
||||
},
|
||||
setOptions({ expectedData, actualData } = {}) {
|
||||
this.chart.setOption({
|
||||
xAxis: {
|
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
boundaryGap: false,
|
||||
axisTick: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
bottom: 20,
|
||||
top: 30,
|
||||
containLabel: true
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross'
|
||||
},
|
||||
padding: [5, 10]
|
||||
},
|
||||
yAxis: {
|
||||
axisTick: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['expected', 'actual']
|
||||
},
|
||||
series: [{
|
||||
name: 'expected', itemStyle: {
|
||||
normal: {
|
||||
color: '#FF005A',
|
||||
lineStyle: {
|
||||
color: '#FF005A',
|
||||
width: 2
|
||||
}
|
||||
}
|
||||
},
|
||||
smooth: true,
|
||||
type: 'line',
|
||||
data: expectedData,
|
||||
animationDuration: 2800,
|
||||
animationEasing: 'cubicInOut'
|
||||
},
|
||||
{
|
||||
name: 'actual',
|
||||
smooth: true,
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#3888fa',
|
||||
lineStyle: {
|
||||
color: '#3888fa',
|
||||
width: 2
|
||||
},
|
||||
areaStyle: {
|
||||
color: '#f3f8ff'
|
||||
}
|
||||
}
|
||||
},
|
||||
data: actualData,
|
||||
animationDuration: 2800,
|
||||
animationEasing: 'quadraticOut'
|
||||
}]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,181 +0,0 @@
|
||||
<template>
|
||||
<el-row :gutter="40" class="panel-group">
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('newVisitis')">
|
||||
<div class="card-panel-icon-wrapper icon-people">
|
||||
<svg-icon icon-class="peoples" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
New Visits
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('messages')">
|
||||
<div class="card-panel-icon-wrapper icon-message">
|
||||
<svg-icon icon-class="message" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Messages
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('purchases')">
|
||||
<div class="card-panel-icon-wrapper icon-money">
|
||||
<svg-icon icon-class="money" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Purchases
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('shoppings')">
|
||||
<div class="card-panel-icon-wrapper icon-shopping">
|
||||
<svg-icon icon-class="shopping" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Shoppings
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CountTo from 'vue-count-to'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CountTo
|
||||
},
|
||||
methods: {
|
||||
handleSetLineChartData(type) {
|
||||
this.$emit('handleSetLineChartData', type)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.panel-group {
|
||||
margin-top: 18px;
|
||||
|
||||
.card-panel-col {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.card-panel {
|
||||
height: 108px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: #666;
|
||||
background: #fff;
|
||||
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
|
||||
border-color: rgba(0, 0, 0, .05);
|
||||
|
||||
&:hover {
|
||||
.card-panel-icon-wrapper {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.icon-people {
|
||||
background: #40c9c6;
|
||||
}
|
||||
|
||||
.icon-message {
|
||||
background: #36a3f7;
|
||||
}
|
||||
|
||||
.icon-money {
|
||||
background: #f4516c;
|
||||
}
|
||||
|
||||
.icon-shopping {
|
||||
background: #34bfa3
|
||||
}
|
||||
}
|
||||
|
||||
.icon-people {
|
||||
color: #40c9c6;
|
||||
}
|
||||
|
||||
.icon-message {
|
||||
color: #36a3f7;
|
||||
}
|
||||
|
||||
.icon-money {
|
||||
color: #f4516c;
|
||||
}
|
||||
|
||||
.icon-shopping {
|
||||
color: #34bfa3
|
||||
}
|
||||
|
||||
.card-panel-icon-wrapper {
|
||||
float: left;
|
||||
margin: 14px 0 0 14px;
|
||||
padding: 16px;
|
||||
transition: all 0.38s ease-out;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.card-panel-icon {
|
||||
float: left;
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.card-panel-description {
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin: 26px;
|
||||
margin-left: 0px;
|
||||
|
||||
.card-panel-text {
|
||||
line-height: 18px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: 16px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.card-panel-num {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:550px) {
|
||||
.card-panel-description {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.card-panel-icon-wrapper {
|
||||
float: none !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 !important;
|
||||
|
||||
.svg-icon {
|
||||
display: block;
|
||||
margin: 14px auto !important;
|
||||
float: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,79 +0,0 @@
|
||||
<template>
|
||||
<div :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '300px'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initChart()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(this.$el, 'macarons')
|
||||
|
||||
this.chart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
left: 'center',
|
||||
bottom: '10',
|
||||
data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'WEEKLY WRITE ARTICLES',
|
||||
type: 'pie',
|
||||
roseType: 'radius',
|
||||
radius: [15, 95],
|
||||
center: ['50%', '38%'],
|
||||
data: [
|
||||
{ value: 320, name: 'Industries' },
|
||||
{ value: 240, name: 'Technology' },
|
||||
{ value: 149, name: 'Forex' },
|
||||
{ value: 100, name: 'Gold' },
|
||||
{ value: 59, name: 'Forecasts' }
|
||||
],
|
||||
animationEasing: 'cubicInOut',
|
||||
animationDuration: 2600
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,81 +0,0 @@
|
||||
<template>
|
||||
<li :class="{ completed: todo.done, editing: editing }" class="todo">
|
||||
<div class="view">
|
||||
<input
|
||||
:checked="todo.done"
|
||||
class="toggle"
|
||||
type="checkbox"
|
||||
@change="toggleTodo( todo)"
|
||||
>
|
||||
<label @dblclick="editing = true" v-text="todo.text" />
|
||||
<button class="destroy" @click="deleteTodo( todo )" />
|
||||
</div>
|
||||
<input
|
||||
v-show="editing"
|
||||
v-focus="editing"
|
||||
:value="todo.text"
|
||||
class="edit"
|
||||
@keyup.enter="doneEdit"
|
||||
@keyup.esc="cancelEdit"
|
||||
@blur="doneEdit"
|
||||
>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Todo',
|
||||
directives: {
|
||||
focus(el, { value }, { context }) {
|
||||
if (value) {
|
||||
context.$nextTick(() => {
|
||||
el.focus()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
todo: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editing: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteTodo(todo) {
|
||||
this.$emit('deleteTodo', todo)
|
||||
},
|
||||
editTodo({ todo, value }) {
|
||||
this.$emit('editTodo', { todo, value })
|
||||
},
|
||||
toggleTodo(todo) {
|
||||
this.$emit('toggleTodo', todo)
|
||||
},
|
||||
doneEdit(e) {
|
||||
const value = e.target.value.trim()
|
||||
const { todo } = this
|
||||
if (!value) {
|
||||
this.deleteTodo({
|
||||
todo
|
||||
})
|
||||
} else if (this.editing) {
|
||||
this.editTodo({
|
||||
todo,
|
||||
value
|
||||
})
|
||||
this.editing = false
|
||||
}
|
||||
},
|
||||
cancelEdit(e) {
|
||||
e.target.value = this.todo.text
|
||||
this.editing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,127 +0,0 @@
|
||||
<template>
|
||||
<section class="todoapp">
|
||||
<!-- header -->
|
||||
<header class="header">
|
||||
<input class="new-todo" autocomplete="off" placeholder="Todo List" @keyup.enter="addTodo">
|
||||
</header>
|
||||
<!-- main section -->
|
||||
<section v-show="todos.length" class="main">
|
||||
<input id="toggle-all" :checked="allChecked" class="toggle-all" type="checkbox" @change="toggleAll({ done: !allChecked })">
|
||||
<label for="toggle-all" />
|
||||
<ul class="todo-list">
|
||||
<todo
|
||||
v-for="(todo, index) in filteredTodos"
|
||||
:key="index"
|
||||
:todo="todo"
|
||||
@toggleTodo="toggleTodo"
|
||||
@editTodo="editTodo"
|
||||
@deleteTodo="deleteTodo"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
<!-- footer -->
|
||||
<footer v-show="todos.length" class="footer">
|
||||
<span class="todo-count">
|
||||
<strong>{{ remaining }}</strong>
|
||||
{{ remaining | pluralize('item') }} left
|
||||
</span>
|
||||
<ul class="filters">
|
||||
<li v-for="(val, key) in filters" :key="key">
|
||||
<a :class="{ selected: visibility === key }" @click.prevent="visibility = key">{{ key | capitalize }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- <button class="clear-completed" v-show="todos.length > remaining" @click="clearCompleted">
|
||||
Clear completed
|
||||
</button> -->
|
||||
</footer>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Todo from './Todo.vue'
|
||||
|
||||
const STORAGE_KEY = 'todos'
|
||||
const filters = {
|
||||
all: todos => todos,
|
||||
active: todos => todos.filter(todo => !todo.done),
|
||||
completed: todos => todos.filter(todo => todo.done)
|
||||
}
|
||||
const defalutList = [
|
||||
{ text: 'star this repository', done: false },
|
||||
{ text: 'fork this repository', done: false },
|
||||
{ text: 'follow author', done: false },
|
||||
{ text: 'vue-element-admin', done: true },
|
||||
{ text: 'vue', done: true },
|
||||
{ text: 'element-ui', done: true },
|
||||
{ text: 'axios', done: true },
|
||||
{ text: 'webpack', done: true }
|
||||
]
|
||||
export default {
|
||||
components: { Todo },
|
||||
filters: {
|
||||
pluralize: (n, w) => n === 1 ? w : w + 's',
|
||||
capitalize: s => s.charAt(0).toUpperCase() + s.slice(1)
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visibility: 'all',
|
||||
filters,
|
||||
// todos: JSON.parse(window.localStorage.getItem(STORAGE_KEY)) || defalutList
|
||||
todos: defalutList
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
allChecked() {
|
||||
return this.todos.every(todo => todo.done)
|
||||
},
|
||||
filteredTodos() {
|
||||
return filters[this.visibility](this.todos)
|
||||
},
|
||||
remaining() {
|
||||
return this.todos.filter(todo => !todo.done).length
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setLocalStorage() {
|
||||
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(this.todos))
|
||||
},
|
||||
addTodo(e) {
|
||||
const text = e.target.value
|
||||
if (text.trim()) {
|
||||
this.todos.push({
|
||||
text,
|
||||
done: false
|
||||
})
|
||||
this.setLocalStorage()
|
||||
}
|
||||
e.target.value = ''
|
||||
},
|
||||
toggleTodo(val) {
|
||||
val.done = !val.done
|
||||
this.setLocalStorage()
|
||||
},
|
||||
deleteTodo(todo) {
|
||||
this.todos.splice(this.todos.indexOf(todo), 1)
|
||||
this.setLocalStorage()
|
||||
},
|
||||
editTodo({ todo, value }) {
|
||||
todo.text = value
|
||||
this.setLocalStorage()
|
||||
},
|
||||
clearCompleted() {
|
||||
this.todos = this.todos.filter(todo => !todo.done)
|
||||
this.setLocalStorage()
|
||||
},
|
||||
toggleAll({ done }) {
|
||||
this.todos.forEach(todo => {
|
||||
todo.done = done
|
||||
this.setLocalStorage()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './index.scss';
|
||||
</style>
|
||||
@ -1,55 +0,0 @@
|
||||
<template>
|
||||
<el-table :data="list" style="width: 100%;padding-top: 15px;">
|
||||
<el-table-column label="Order_No" min-width="200">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.order_no | orderNoFilter }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Price" width="195" align="center">
|
||||
<template slot-scope="scope">
|
||||
¥{{ scope.row.price | toThousandFilter }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Status" width="100" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag :type="row.status | statusFilter">
|
||||
{{ row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { transactionList } from '@/api/remote-search'
|
||||
|
||||
export default {
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
success: 'success',
|
||||
pending: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
},
|
||||
orderNoFilter(str) {
|
||||
return str.substring(0, 30)
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
transactionList().then(response => {
|
||||
this.list = response.data.items.slice(0, 8)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,56 +0,0 @@
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
$_sidebarElm: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$_initResizeEvent()
|
||||
this.$_initSidebarResizeEvent()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$_destroyResizeEvent()
|
||||
this.$_destroySidebarResizeEvent()
|
||||
},
|
||||
// to fixed bug when cached by keep-alive
|
||||
// https://github.com/PanJiaChen/vue-element-admin/issues/2116
|
||||
activated() {
|
||||
this.$_initResizeEvent()
|
||||
this.$_initSidebarResizeEvent()
|
||||
},
|
||||
deactivated() {
|
||||
this.$_destroyResizeEvent()
|
||||
this.$_destroySidebarResizeEvent()
|
||||
},
|
||||
methods: {
|
||||
// use $_ for mixins properties
|
||||
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
||||
$_resizeHandler() {
|
||||
return debounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
}, 100)()
|
||||
},
|
||||
$_initResizeEvent() {
|
||||
window.addEventListener('resize', this.$_resizeHandler)
|
||||
},
|
||||
$_destroyResizeEvent() {
|
||||
window.removeEventListener('resize', this.$_resizeHandler)
|
||||
},
|
||||
$_sidebarResizeHandler(e) {
|
||||
if (e.propertyName === 'width') {
|
||||
this.$_resizeHandler()
|
||||
}
|
||||
},
|
||||
$_initSidebarResizeEvent() {
|
||||
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
||||
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
|
||||
},
|
||||
$_destroySidebarResizeEvent() {
|
||||
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,124 +0,0 @@
|
||||
<template>
|
||||
<div class="dashboard-editor-container">
|
||||
<github-corner class="github-corner" />
|
||||
|
||||
<panel-group @handleSetLineChartData="handleSetLineChartData" />
|
||||
|
||||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
|
||||
<line-chart :chart-data="lineChartData" />
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="32">
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<raddar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<pie-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<bar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="8">
|
||||
<el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;">
|
||||
<transaction-table />
|
||||
</el-col>
|
||||
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
|
||||
<todo-list />
|
||||
</el-col>
|
||||
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
|
||||
<box-card />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GithubCorner from '@/components/GithubCorner'
|
||||
import PanelGroup from './components/PanelGroup'
|
||||
import LineChart from './components/LineChart'
|
||||
import RaddarChart from './components/RaddarChart'
|
||||
import PieChart from './components/PieChart'
|
||||
import BarChart from './components/BarChart'
|
||||
import TransactionTable from './components/TransactionTable'
|
||||
import TodoList from './components/TodoList'
|
||||
import BoxCard from './components/BoxCard'
|
||||
|
||||
const lineChartData = {
|
||||
newVisitis: {
|
||||
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 145]
|
||||
},
|
||||
messages: {
|
||||
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
||||
actualData: [180, 160, 151, 106, 145, 150, 130]
|
||||
},
|
||||
purchases: {
|
||||
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
||||
actualData: [120, 90, 100, 138, 142, 130, 130]
|
||||
},
|
||||
shoppings: {
|
||||
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 130]
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'DashboardAdmin',
|
||||
components: {
|
||||
GithubCorner,
|
||||
PanelGroup,
|
||||
LineChart,
|
||||
RaddarChart,
|
||||
PieChart,
|
||||
BarChart,
|
||||
TransactionTable,
|
||||
TodoList,
|
||||
BoxCard
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lineChartData: lineChartData.newVisitis
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSetLineChartData(type) {
|
||||
this.lineChartData = lineChartData[type]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-editor-container {
|
||||
padding: 32px;
|
||||
background-color: rgb(240, 242, 245);
|
||||
position: relative;
|
||||
|
||||
.github-corner {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
border: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.chart-wrapper {
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:1024px) {
|
||||
.chart-wrapper {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,92 +0,0 @@
|
||||
<template>
|
||||
<div v-hasPermission="['homePage']" class="sy-main">
|
||||
<el-col :span="23" :offset="1" class="sy-main-head">武器装备平台</el-col>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DashboardEditor',
|
||||
components: { },
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
jumpTo(item) {
|
||||
if (item.type === 0) {
|
||||
this.$router.push({ path: item.url })
|
||||
}
|
||||
if (item.type === 1) {
|
||||
window.open(item.url);
|
||||
}
|
||||
if (item.type === 3) {
|
||||
this.dialogVisible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sy-main {
|
||||
width: 100%;
|
||||
background: #FFFFFF;
|
||||
opacity: 1;
|
||||
border-radius: 4px;
|
||||
font-family: Microsoft YaHei;
|
||||
min-width: 900px;
|
||||
}
|
||||
.sy-main-head{
|
||||
height: 75px;
|
||||
padding-top: 24px;
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
color: #1D2023;
|
||||
opacity: 1;
|
||||
}
|
||||
.sy-main-content{
|
||||
height: 288px;
|
||||
background: #F7F8F9;
|
||||
opacity: 1;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.sy-main-content-head{
|
||||
width: 100%;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
color: #1D2023;
|
||||
opacity: 1;
|
||||
margin-top: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.sy-main-content-icon{
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
position:relative
|
||||
}
|
||||
.sy-main-content-icon-img{
|
||||
width: 97px;
|
||||
height: 96px;
|
||||
}
|
||||
.sy-main-content-text{
|
||||
margin-top: 40px;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
line-height: 0px;
|
||||
color: #2D7ACF;
|
||||
opacity: 1;
|
||||
text-align: center;
|
||||
}
|
||||
.sy-main-content-text-span{
|
||||
cursor:pointer
|
||||
}
|
||||
.tip {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
@ -1,31 +0,0 @@
|
||||
<template>
|
||||
<div class="dashboard-container">
|
||||
<component :is="currentRole" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import adminDashboard from './admin'
|
||||
import editorDashboard from './editor'
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
components: { adminDashboard, editorDashboard },
|
||||
data() {
|
||||
return {
|
||||
currentRole: 'adminDashboard'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'roles'
|
||||
])
|
||||
},
|
||||
created() {
|
||||
if (!this.roles.includes('admin')) {
|
||||
this.currentRole = 'editorDashboard'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--error code-->
|
||||
{{ a.a }}
|
||||
<!--error code-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ErrorTestA'
|
||||
}
|
||||
</script>
|
||||
@ -1,11 +0,0 @@
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
created() {
|
||||
this.b = b // eslint-disable-line
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<div class="errPage-container">
|
||||
<ErrorA />
|
||||
<ErrorB />
|
||||
<h3>Please click the bug icon in the upper right corner</h3>
|
||||
<aside>
|
||||
Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.
|
||||
<a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/guide/advanced/error.html">
|
||||
Document introduction
|
||||
</a>
|
||||
</aside>
|
||||
<a href="#">
|
||||
<img src="https://wpimg.wallstcn.com/360e4842-4db5-42d0-b078-f9a84a825546.gif">
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ErrorA from './components/ErrorTestA'
|
||||
import ErrorB from './components/ErrorTestB'
|
||||
|
||||
export default {
|
||||
name: 'ErrorLog',
|
||||
components: { ErrorA, ErrorB }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.errPage-container {
|
||||
padding: 30px;
|
||||
}
|
||||
</style>
|
||||
@ -1,99 +0,0 @@
|
||||
<template>
|
||||
<div class="errPage-container">
|
||||
<el-button icon="arrow-left" class="pan-back-btn" @click="back">
|
||||
返回
|
||||
</el-button>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<h1 class="text-jumbo text-ginormous">
|
||||
Oops!
|
||||
</h1>
|
||||
gif来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面
|
||||
<h2>你没有权限去该页面</h2>
|
||||
<h6>如有不满请联系你领导</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li>或者你可以去:</li>
|
||||
<li class="link-type">
|
||||
<router-link to="/dashboard">
|
||||
回首页
|
||||
</router-link>
|
||||
</li>
|
||||
<li class="link-type">
|
||||
<a href="https://www.taobao.com/">随便看看</a>
|
||||
</li>
|
||||
<li><a href="#" @click.prevent="dialogVisible=true">点我看图</a></li>
|
||||
</ul>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog :visible.sync="dialogVisible" title="随便看">
|
||||
<img :src="ewizardClap" class="pan-img">
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import errGif from '@/assets/401_images/401.gif'
|
||||
|
||||
export default {
|
||||
name: 'Page401',
|
||||
data() {
|
||||
return {
|
||||
errGif: errGif + '?' + +new Date(),
|
||||
ewizardClap: 'https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646',
|
||||
dialogVisible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
if (this.$route.query.noGoBack) {
|
||||
this.$router.push({ path: '/dashboard' })
|
||||
} else {
|
||||
this.$router.go(-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.errPage-container {
|
||||
width: 800px;
|
||||
max-width: 100%;
|
||||
margin: 100px auto;
|
||||
.pan-back-btn {
|
||||
background: #008489;
|
||||
color: #fff;
|
||||
border: none!important;
|
||||
}
|
||||
.pan-gif {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
.pan-img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
.text-jumbo {
|
||||
font-size: 60px;
|
||||
font-weight: 700;
|
||||
color: #484848;
|
||||
}
|
||||
.list-unstyled {
|
||||
font-size: 14px;
|
||||
li {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
a {
|
||||
color: #008489;
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,228 +0,0 @@
|
||||
<template>
|
||||
<div class="wscn-http404-container">
|
||||
<div class="wscn-http404">
|
||||
<div class="pic-404">
|
||||
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
|
||||
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
</div>
|
||||
<div class="bullshit">
|
||||
<div class="bullshit__oops">OOPS!</div>
|
||||
<div class="bullshit__info">All rights reserved
|
||||
<a style="color:#20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
|
||||
</div>
|
||||
<div class="bullshit__headline">{{ message }}</div>
|
||||
<div class="bullshit__info">Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
|
||||
<a href="" class="bullshit__return-home">Back to home</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'Page404',
|
||||
computed: {
|
||||
message() {
|
||||
return 'The webmaster said that you can not enter this page...'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wscn-http404-container{
|
||||
transform: translate(-50%,-50%);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
}
|
||||
.wscn-http404 {
|
||||
position: relative;
|
||||
width: 1200px;
|
||||
padding: 0 50px;
|
||||
overflow: hidden;
|
||||
.pic-404 {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 600px;
|
||||
overflow: hidden;
|
||||
&__parent {
|
||||
width: 100%;
|
||||
}
|
||||
&__child {
|
||||
position: absolute;
|
||||
&.left {
|
||||
width: 80px;
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
animation-name: cloudLeft;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
&.mid {
|
||||
width: 46px;
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
animation-name: cloudMid;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
&.right {
|
||||
width: 62px;
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
animation-name: cloudRight;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes cloudLeft {
|
||||
0% {
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 33px;
|
||||
left: 188px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 81px;
|
||||
left: 92px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 97px;
|
||||
left: 60px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudMid {
|
||||
0% {
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 40px;
|
||||
left: 360px;
|
||||
opacity: 1;
|
||||
}
|
||||
70% {
|
||||
top: 130px;
|
||||
left: 180px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 160px;
|
||||
left: 120px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudRight {
|
||||
0% {
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 120px;
|
||||
left: 460px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 180px;
|
||||
left: 340px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 200px;
|
||||
left: 300px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bullshit {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 300px;
|
||||
padding: 30px 0;
|
||||
overflow: hidden;
|
||||
&__oops {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 40px;
|
||||
color: #1482f0;
|
||||
opacity: 0;
|
||||
margin-bottom: 20px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__headline {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
opacity: 0;
|
||||
margin-bottom: 10px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.1s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__info {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
color: grey;
|
||||
opacity: 0;
|
||||
margin-bottom: 30px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.2s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 110px;
|
||||
height: 36px;
|
||||
background: #1482f0;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
opacity: 0;
|
||||
font-size: 14px;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(60px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,291 +0,0 @@
|
||||
<template>
|
||||
<div class="createPost-container">
|
||||
<el-form ref="postForm" :model="postForm" :rules="rules" class="form-container">
|
||||
|
||||
<sticky :z-index="10" :class-name="'sub-navbar '+postForm.status">
|
||||
<CommentDropdown v-model="postForm.comment_disabled" />
|
||||
<PlatformDropdown v-model="postForm.platforms" />
|
||||
<SourceUrlDropdown v-model="postForm.source_uri" />
|
||||
<el-button v-loading="loading" style="margin-left: 10px;" type="success" @click="submitForm">
|
||||
Publish
|
||||
</el-button>
|
||||
<el-button v-loading="loading" type="warning" @click="draftForm">
|
||||
Draft
|
||||
</el-button>
|
||||
</sticky>
|
||||
|
||||
<div class="createPost-main-container">
|
||||
<el-row>
|
||||
<Warning />
|
||||
|
||||
<el-col :span="24">
|
||||
<el-form-item style="margin-bottom: 40px;" prop="title">
|
||||
<MDinput v-model="postForm.title" :maxlength="100" name="name" required>
|
||||
Title
|
||||
</MDinput>
|
||||
</el-form-item>
|
||||
|
||||
<div class="postInfo-container">
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label-width="60px" label="Author:" class="postInfo-container-item">
|
||||
<el-select v-model="postForm.author" :remote-method="getRemoteUserList" filterable default-first-option remote placeholder="Search user">
|
||||
<el-option v-for="(item,index) in userListOptions" :key="item+index" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="10">
|
||||
<el-form-item label-width="120px" label="Publish Time:" class="postInfo-container-item">
|
||||
<el-date-picker v-model="displayTime" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="Select date and time" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label-width="90px" label="Importance:" class="postInfo-container-item">
|
||||
<el-rate
|
||||
v-model="postForm.importance"
|
||||
:max="3"
|
||||
:colors="['#99A9BF', '#F7BA2A', '#FF9900']"
|
||||
:low-threshold="1"
|
||||
:high-threshold="3"
|
||||
style="display:inline-block"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item style="margin-bottom: 40px;" label-width="70px" label="Summary:">
|
||||
<el-input v-model="postForm.content_short" :rows="1" type="textarea" class="article-textarea" autosize placeholder="Please enter the content" />
|
||||
<span v-show="contentShortLength" class="word-counter">{{ contentShortLength }}words</span>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="content" style="margin-bottom: 30px;">
|
||||
<Tinymce ref="editor" v-model="postForm.content" :height="400" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="image_uri" style="margin-bottom: 30px;">
|
||||
<Upload v-model="postForm.image_uri" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Tinymce from '@/components/Tinymce'
|
||||
import Upload from '@/components/Upload/SingleImage3'
|
||||
import MDinput from '@/components/MDinput'
|
||||
import Sticky from '@/components/Sticky' // 粘性header组件
|
||||
import { validURL } from '@/utils/validate'
|
||||
import { fetchArticle } from '@/api/article'
|
||||
import { searchUser } from '@/api/remote-search'
|
||||
import Warning from './Warning'
|
||||
import { CommentDropdown, PlatformDropdown, SourceUrlDropdown } from './Dropdown'
|
||||
|
||||
const defaultForm = {
|
||||
status: 'draft',
|
||||
title: '', // 文章题目
|
||||
content: '', // 文章内容
|
||||
content_short: '', // 文章摘要
|
||||
source_uri: '', // 文章外链
|
||||
image_uri: '', // 文章图片
|
||||
display_time: undefined, // 前台展示时间
|
||||
id: undefined,
|
||||
platforms: ['a-platform'],
|
||||
comment_disabled: false,
|
||||
importance: 0
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'ArticleDetail',
|
||||
components: { Tinymce, MDinput, Upload, Sticky, Warning, CommentDropdown, PlatformDropdown, SourceUrlDropdown },
|
||||
props: {
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const validateRequire = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
this.$message({
|
||||
message: rule.field + '为必传项',
|
||||
type: 'error'
|
||||
})
|
||||
callback(new Error(rule.field + '为必传项'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateSourceUri = (rule, value, callback) => {
|
||||
if (value) {
|
||||
if (validURL(value)) {
|
||||
callback()
|
||||
} else {
|
||||
this.$message({
|
||||
message: '外链url填写不正确',
|
||||
type: 'error'
|
||||
})
|
||||
callback(new Error('外链url填写不正确'))
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
postForm: Object.assign({}, defaultForm),
|
||||
loading: false,
|
||||
userListOptions: [],
|
||||
rules: {
|
||||
image_uri: [{ validator: validateRequire }],
|
||||
title: [{ validator: validateRequire }],
|
||||
content: [{ validator: validateRequire }],
|
||||
source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
|
||||
},
|
||||
tempRoute: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
contentShortLength() {
|
||||
return this.postForm.content_short.length
|
||||
},
|
||||
displayTime: {
|
||||
// set and get is useful when the data
|
||||
// returned by the back end api is different from the front end
|
||||
// back end return => "2013-06-25 06:59:25"
|
||||
// front end need timestamp => 1372114765000
|
||||
get() {
|
||||
return (+new Date(this.postForm.display_time))
|
||||
},
|
||||
set(val) {
|
||||
this.postForm.display_time = new Date(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.isEdit) {
|
||||
const id = this.$route.params && this.$route.params.id
|
||||
this.fetchData(id)
|
||||
} else {
|
||||
this.postForm = Object.assign({}, defaultForm)
|
||||
}
|
||||
|
||||
// Why need to make a copy of this.$route here?
|
||||
// Because if you enter this page and quickly switch tag, may be in the execution of the setTagsViewTitle function, this.$route is no longer pointing to the current page
|
||||
// https://github.com/PanJiaChen/vue-element-admin/issues/1221
|
||||
this.tempRoute = Object.assign({}, this.$route)
|
||||
},
|
||||
methods: {
|
||||
fetchData(id) {
|
||||
fetchArticle(id).then(response => {
|
||||
this.postForm = response.data
|
||||
|
||||
// just for test
|
||||
this.postForm.title += ` Article Id:${this.postForm.id}`
|
||||
this.postForm.content_short += ` Article Id:${this.postForm.id}`
|
||||
|
||||
// set tagsview title
|
||||
this.setTagsViewTitle()
|
||||
|
||||
// set page title
|
||||
this.setPageTitle()
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
setTagsViewTitle() {
|
||||
const title = 'Edit Article'
|
||||
const route = Object.assign({}, this.tempRoute, { title: `${title}-${this.postForm.id}` })
|
||||
this.$store.dispatch('tagsView/updateVisitedView', route)
|
||||
},
|
||||
setPageTitle() {
|
||||
const title = 'Edit Article'
|
||||
document.title = `${title} - ${this.postForm.id}`
|
||||
},
|
||||
submitForm() {
|
||||
console.log(this.postForm)
|
||||
this.$refs.postForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
this.$notify({
|
||||
title: '成功',
|
||||
message: '发布文章成功',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
this.postForm.status = 'published'
|
||||
this.loading = false
|
||||
} else {
|
||||
console.log('error submit!!')
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
draftForm() {
|
||||
if (this.postForm.content.length === 0 || this.postForm.title.length === 0) {
|
||||
this.$message({
|
||||
message: '请填写必要的标题和内容',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$message({
|
||||
message: '保存成功',
|
||||
type: 'success',
|
||||
showClose: true,
|
||||
duration: 1000
|
||||
})
|
||||
this.postForm.status = 'draft'
|
||||
},
|
||||
getRemoteUserList(query) {
|
||||
searchUser(query).then(response => {
|
||||
if (!response.data.items) return
|
||||
this.userListOptions = response.data.items.map(v => v.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/styles/mixin.scss";
|
||||
|
||||
.createPost-container {
|
||||
position: relative;
|
||||
|
||||
.createPost-main-container {
|
||||
padding: 40px 45px 20px 50px;
|
||||
|
||||
.postInfo-container {
|
||||
position: relative;
|
||||
@include clearfix;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.postInfo-container-item {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.word-counter {
|
||||
width: 40px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.article-textarea /deep/ {
|
||||
textarea {
|
||||
padding-right: 40px;
|
||||
resize: none;
|
||||
border: none;
|
||||
border-radius: 0px;
|
||||
border-bottom: 1px solid #bfcbd9;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,41 +0,0 @@
|
||||
<template>
|
||||
<el-dropdown :show-timeout="100" trigger="click">
|
||||
<el-button plain>
|
||||
{{ !comment_disabled?'Comment: opened':'Comment: closed' }}
|
||||
<i class="el-icon-caret-bottom el-icon--right" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown" class="no-padding">
|
||||
<el-dropdown-item>
|
||||
<el-radio-group v-model="comment_disabled" style="padding: 10px;">
|
||||
<el-radio :label="true">
|
||||
Close comment
|
||||
</el-radio>
|
||||
<el-radio :label="false">
|
||||
Open comment
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
comment_disabled: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,46 +0,0 @@
|
||||
<template>
|
||||
<el-dropdown :hide-on-click="false" :show-timeout="100" trigger="click">
|
||||
<el-button plain>
|
||||
Platfroms({{ platforms.length }})
|
||||
<i class="el-icon-caret-bottom el-icon--right" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown" class="no-border">
|
||||
<el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
|
||||
<el-checkbox v-for="item in platformsOptions" :key="item.key" :label="item.key">
|
||||
{{ item.name }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
required: true,
|
||||
default: () => [],
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
platformsOptions: [
|
||||
{ key: 'a-platform', name: 'a-platform' },
|
||||
{ key: 'b-platform', name: 'b-platform' },
|
||||
{ key: 'c-platform', name: 'c-platform' }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
platforms: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,38 +0,0 @@
|
||||
<template>
|
||||
<el-dropdown :show-timeout="100" trigger="click">
|
||||
<el-button plain>
|
||||
Link
|
||||
<i class="el-icon-caret-bottom el-icon--right" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown" class="no-padding no-border" style="width:400px">
|
||||
<el-form-item label-width="0px" style="margin-bottom: 0px" prop="source_uri">
|
||||
<el-input v-model="source_uri" placeholder="Please enter the content">
|
||||
<template slot="prepend">
|
||||
URL
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
source_uri: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,3 +0,0 @@
|
||||
export { default as CommentDropdown } from './Comment'
|
||||
export { default as PlatformDropdown } from './Platform'
|
||||
export { default as SourceUrlDropdown } from './SourceUrl'
|
||||
@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<aside>
|
||||
Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support
|
||||
caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching
|
||||
effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all
|
||||
pages directly. See details
|
||||
<a
|
||||
href="https://panjiachen.github.io/vue-element-admin-site/guide/essentials/tags-view.html"
|
||||
target="_blank"
|
||||
>Document</a>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<article-detail :is-edit="false" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ArticleDetail from './components/ArticleDetail'
|
||||
|
||||
export default {
|
||||
name: 'CreateForm',
|
||||
components: { ArticleDetail }
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<article-detail :is-edit="true" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ArticleDetail from './components/ArticleDetail'
|
||||
|
||||
export default {
|
||||
name: 'EditForm',
|
||||
components: { ArticleDetail }
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,112 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%">
|
||||
<el-table-column align="center" label="ID" width="80">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.id }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="180px" align="center" label="Date">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="120px" align="center" label="Author">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.author }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="100px" label="Importance">
|
||||
<template slot-scope="scope">
|
||||
<svg-icon v-for="n in +scope.row.importance" :key="n" icon-class="star" class="meta-item__icon" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column class-name="status-col" label="Status" width="110">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag :type="row.status | statusFilter">
|
||||
{{ row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column min-width="300px" label="Title">
|
||||
<template slot-scope="{row}">
|
||||
<router-link :to="'/example/edit/'+row.id" class="link-type">
|
||||
<span>{{ row.title }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" label="Actions" width="120">
|
||||
<template slot-scope="scope">
|
||||
<router-link :to="'/example/edit/'+scope.row.id">
|
||||
<el-button type="primary" size="small" icon="el-icon-edit">
|
||||
Edit
|
||||
</el-button>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fetchList } from '@/api/article'
|
||||
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
|
||||
|
||||
export default {
|
||||
name: 'ArticleList',
|
||||
components: { Pagination },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'info',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
total: 0,
|
||||
listLoading: true,
|
||||
listQuery: {
|
||||
page: 1,
|
||||
limit: 20
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
fetchList(this.listQuery).then(response => {
|
||||
this.list = response.data.items
|
||||
this.total = response.data.total
|
||||
this.listLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.edit-input {
|
||||
padding-right: 100px;
|
||||
}
|
||||
.cancel-btn {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,34 +0,0 @@
|
||||
<template>
|
||||
<div style="display:inline-block;">
|
||||
<label class="radio-label">Cell Auto-Width: </label>
|
||||
<el-radio-group v-model="autoWidth">
|
||||
<el-radio :label="true" border>
|
||||
True
|
||||
</el-radio>
|
||||
<el-radio :label="false" border>
|
||||
False
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
autoWidth: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,39 +0,0 @@
|
||||
<template>
|
||||
<div style="display:inline-block;">
|
||||
<label class="radio-label">Book Type: </label>
|
||||
<el-select v-model="bookType" style="width:120px;">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: 'xlsx'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: ['xlsx', 'csv', 'txt']
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
bookType: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,27 +0,0 @@
|
||||
<template>
|
||||
<div style="display:inline-block;">
|
||||
<label class="radio-label" style="padding-left:0;">Filename: </label>
|
||||
<el-input v-model="filename" placeholder="Please enter the file name (default excel-list)" style="width:345px;" prefix-icon="el-icon-document" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filename: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,116 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<div>
|
||||
<FilenameOption v-model="filename" />
|
||||
<AutoWidthOption v-model="autoWidth" />
|
||||
<BookTypeOption v-model="bookType" />
|
||||
<el-button :loading="downloadLoading" style="margin:0 0 20px 20px;" type="primary" icon="document" @click="handleDownload">
|
||||
Export Excel
|
||||
</el-button>
|
||||
<a href="https://panjiachen.github.io/vue-element-admin-site/feature/component/excel.html" target="_blank" style="margin-left:15px;">
|
||||
<el-tag type="info">Documentation</el-tag>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="listLoading" :data="list" element-loading-text="拼命加载中" border fit highlight-current-row>
|
||||
<el-table-column align="center" label="Id" width="95">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.$index }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Title">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.title }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Author" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag>{{ scope.row.author }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Readings" width="115" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.pageviews }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="Date" width="220">
|
||||
<template slot-scope="scope">
|
||||
<i class="el-icon-time" />
|
||||
<span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fetchList } from '@/api/article'
|
||||
import { parseTime } from '@/utils'
|
||||
// options components
|
||||
import FilenameOption from './components/FilenameOption'
|
||||
import AutoWidthOption from './components/AutoWidthOption'
|
||||
import BookTypeOption from './components/BookTypeOption'
|
||||
|
||||
export default {
|
||||
name: 'ExportExcel',
|
||||
components: { FilenameOption, AutoWidthOption, BookTypeOption },
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true,
|
||||
downloadLoading: false,
|
||||
filename: '',
|
||||
autoWidth: true,
|
||||
bookType: 'xlsx'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
fetchList().then(response => {
|
||||
this.list = response.data.items
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleDownload() {
|
||||
this.downloadLoading = true
|
||||
import('@/vendor/Export2Excel').then(excel => {
|
||||
const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
|
||||
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
|
||||
const list = this.list
|
||||
const data = this.formatJson(filterVal, list)
|
||||
excel.export_json_to_excel({
|
||||
header: tHeader,
|
||||
data,
|
||||
filename: this.filename,
|
||||
autoWidth: this.autoWidth,
|
||||
bookType: this.bookType
|
||||
})
|
||||
this.downloadLoading = false
|
||||
})
|
||||
},
|
||||
formatJson(filterVal, jsonData) {
|
||||
return jsonData.map(v => filterVal.map(j => {
|
||||
if (j === 'timestamp') {
|
||||
return parseTime(v[j])
|
||||
} else {
|
||||
return v[j]
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.radio-label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
line-height: 40px;
|
||||
padding: 0 12px 0 30px;
|
||||
}
|
||||
</style>
|
||||
@ -1,101 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="document" @click="handleDownload">Export</el-button>
|
||||
|
||||
<el-table
|
||||
ref="multipleTable"
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column align="center" label="Id" width="95">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.$index }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Main Information" align="center">
|
||||
<el-table-column label="Title">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.title }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Author" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag>{{ scope.row.author }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Readings" width="115" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.pageviews }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="Date" width="220">
|
||||
<template slot-scope="scope">
|
||||
<i class="el-icon-time" />
|
||||
<span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fetchList } from '@/api/article'
|
||||
import { parseTime } from '@/utils'
|
||||
|
||||
export default {
|
||||
name: 'MergeHeader',
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true,
|
||||
downloadLoading: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
fetchList(this.listQuery).then(response => {
|
||||
this.list = response.data.items
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleDownload() {
|
||||
this.downloadLoading = true
|
||||
import('@/vendor/Export2Excel').then(excel => {
|
||||
const multiHeader = [['Id', 'Main Information', '', '', 'Date']]
|
||||
const header = ['', 'Title', 'Author', 'Readings', '']
|
||||
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
|
||||
const list = this.list
|
||||
const data = this.formatJson(filterVal, list)
|
||||
const merges = ['A1:A2', 'B1:D1', 'E1:E2']
|
||||
excel.export_json_to_excel({
|
||||
multiHeader,
|
||||
header,
|
||||
merges,
|
||||
data
|
||||
})
|
||||
this.downloadLoading = false
|
||||
})
|
||||
},
|
||||
formatJson(filterVal, jsonData) {
|
||||
return jsonData.map(v => filterVal.map(j => {
|
||||
if (j === 'timestamp') {
|
||||
return parseTime(v[j])
|
||||
} else {
|
||||
return v[j]
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,107 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-input v-model="filename" placeholder="Please enter the file name (default excel-list)" style="width:350px;" prefix-icon="el-icon-document" />
|
||||
<el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="document" @click="handleDownload">
|
||||
Export Selected Items
|
||||
</el-button>
|
||||
<a href="https://panjiachen.github.io/vue-element-admin-site/feature/component/excel.html" target="_blank" style="margin-left:15px;">
|
||||
<el-tag type="info">Documentation</el-tag>
|
||||
</a>
|
||||
<el-table
|
||||
ref="multipleTable"
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="拼命加载中"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" align="center" />
|
||||
<el-table-column align="center" label="Id" width="95">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.$index }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Title">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.title }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Author" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag>{{ scope.row.author }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Readings" width="115" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.pageviews }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="PDate" width="220">
|
||||
<template slot-scope="scope">
|
||||
<i class="el-icon-time" />
|
||||
<span>{{ scope.row.display_time }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fetchList } from '@/api/article'
|
||||
|
||||
export default {
|
||||
name: 'SelectExcel',
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true,
|
||||
multipleSelection: [],
|
||||
downloadLoading: false,
|
||||
filename: ''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
fetchList(this.listQuery).then(response => {
|
||||
this.list = response.data.items
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.multipleSelection = val
|
||||
},
|
||||
handleDownload() {
|
||||
if (this.multipleSelection.length) {
|
||||
this.downloadLoading = true
|
||||
import('@/vendor/Export2Excel').then(excel => {
|
||||
const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
|
||||
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
|
||||
const list = this.multipleSelection
|
||||
const data = this.formatJson(filterVal, list)
|
||||
excel.export_json_to_excel({
|
||||
header: tHeader,
|
||||
data,
|
||||
filename: this.filename
|
||||
})
|
||||
this.$refs.multipleTable.clearSelection()
|
||||
this.downloadLoading = false
|
||||
})
|
||||
} else {
|
||||
this.$message({
|
||||
message: 'Please select at least one item',
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
},
|
||||
formatJson(filterVal, jsonData) {
|
||||
return jsonData.map(v => filterVal.map(j => v[j]))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,42 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<upload-excel-component :on-success="handleSuccess" :before-upload="beforeUpload" />
|
||||
<el-table :data="tableData" border highlight-current-row style="width: 100%;margin-top:20px;">
|
||||
<el-table-column v-for="item of tableHeader" :key="item" :prop="item" :label="item" />
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UploadExcelComponent from '@/components/UploadExcel/index.vue'
|
||||
|
||||
export default {
|
||||
name: 'UploadExcel',
|
||||
components: { UploadExcelComponent },
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
tableHeader: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
beforeUpload(file) {
|
||||
const isLt1M = file.size / 1024 / 1024 < 1
|
||||
|
||||
if (isLt1M) {
|
||||
return true
|
||||
}
|
||||
|
||||
this.$message({
|
||||
message: 'Please do not upload files larger than 1m in size.',
|
||||
type: 'warning'
|
||||
})
|
||||
return false
|
||||
},
|
||||
handleSuccess({ results, header }) {
|
||||
this.tableData = results
|
||||
this.tableHeader = header
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,36 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<aside>
|
||||
The guide page is useful for some people who entered the project for the first time. You can briefly introduce the
|
||||
features of the project. Demo is based on
|
||||
<a href="https://github.com/kamranahmedse/driver.js" target="_blank">driver.js.</a>
|
||||
</aside>
|
||||
<el-button icon="el-icon-question" type="primary" @click.prevent.stop="guide">
|
||||
Show Guide
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Driver from 'driver.js' // import driver.js
|
||||
import 'driver.js/dist/driver.min.css' // import driver.js css
|
||||
import steps from './steps'
|
||||
|
||||
export default {
|
||||
name: 'Guide',
|
||||
data() {
|
||||
return {
|
||||
driver: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.driver = new Driver()
|
||||
},
|
||||
methods: {
|
||||
guide() {
|
||||
this.driver.defineSteps(steps)
|
||||
this.driver.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,53 +0,0 @@
|
||||
const steps = [
|
||||
{
|
||||
element: '#hamburger-container',
|
||||
popover: {
|
||||
title: 'Hamburger',
|
||||
description: 'Open && Close sidebar',
|
||||
position: 'bottom'
|
||||
}
|
||||
},
|
||||
{
|
||||
element: '#breadcrumb-container',
|
||||
popover: {
|
||||
title: 'Breadcrumb',
|
||||
description: 'Indicate the current page location',
|
||||
position: 'bottom'
|
||||
}
|
||||
},
|
||||
{
|
||||
element: '#header-search',
|
||||
popover: {
|
||||
title: 'Page Search',
|
||||
description: 'Page search, quick navigation',
|
||||
position: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
element: '#screenfull',
|
||||
popover: {
|
||||
title: 'Screenfull',
|
||||
description: 'Set the page into fullscreen',
|
||||
position: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
element: '#size-select',
|
||||
popover: {
|
||||
title: 'Switch Size',
|
||||
description: 'Switch the system size',
|
||||
position: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
element: '#tags-view-container',
|
||||
popover: {
|
||||
title: 'Tags view',
|
||||
description: 'The history of the page you visited',
|
||||
position: 'bottom'
|
||||
},
|
||||
padding: 0
|
||||
}
|
||||
]
|
||||
|
||||
export default steps
|
||||
@ -1,74 +0,0 @@
|
||||
const elementIcons = [
|
||||
'info',
|
||||
'error',
|
||||
'success',
|
||||
'warning',
|
||||
'question',
|
||||
'back',
|
||||
'arrow-left',
|
||||
'arrow-down',
|
||||
'arrow-right',
|
||||
'arrow-up',
|
||||
'caret-left',
|
||||
'caret-bottom',
|
||||
'caret-top',
|
||||
'caret-right',
|
||||
'd-arrow-left',
|
||||
'd-arrow-right',
|
||||
'minus',
|
||||
'plus',
|
||||
'remove',
|
||||
'circle-plus',
|
||||
'remove-outline',
|
||||
'circle-plus-outline',
|
||||
'close',
|
||||
'check',
|
||||
'circle-close',
|
||||
'circle-check',
|
||||
'circle-close-outline',
|
||||
'circle-check-outline',
|
||||
'zoom-out',
|
||||
'zoom-in',
|
||||
'd-caret',
|
||||
'sort',
|
||||
'sort-down',
|
||||
'sort-up',
|
||||
'tickets',
|
||||
'document',
|
||||
'goods',
|
||||
'sold-out',
|
||||
'news',
|
||||
'message',
|
||||
'date',
|
||||
'printer',
|
||||
'time',
|
||||
'bell',
|
||||
'mobile-phone',
|
||||
'service',
|
||||
'view',
|
||||
'menu',
|
||||
'more',
|
||||
'more-outline',
|
||||
'star-on',
|
||||
'star-off',
|
||||
'location',
|
||||
'location-outline',
|
||||
'phone',
|
||||
'phone-outline',
|
||||
'picture',
|
||||
'picture-outline',
|
||||
'delete',
|
||||
'search',
|
||||
'edit',
|
||||
'edit-outline',
|
||||
'rank',
|
||||
'refresh',
|
||||
'share',
|
||||
'setting',
|
||||
'upload',
|
||||
'upload2',
|
||||
'download',
|
||||
'loading'
|
||||
]
|
||||
|
||||
export default elementIcons
|
||||
@ -1,91 +0,0 @@
|
||||
<template>
|
||||
<div class="icons-container">
|
||||
<aside>
|
||||
<a href="https://panjiachen.github.io/vue-element-admin-site/guide/advanced/icon.html" target="_blank">Add and use
|
||||
</a>
|
||||
</aside>
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane label="Icons">
|
||||
<div v-for="item of svgIcons" :key="item" @click="handleClipboard(generateIconCode(item),$event)">
|
||||
<el-tooltip placement="top">
|
||||
<div slot="content">
|
||||
{{ generateIconCode(item) }}
|
||||
</div>
|
||||
<div class="icon-item">
|
||||
<svg-icon :icon-class="item" class-name="disabled" />
|
||||
<span>{{ item }}</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Element-UI Icons">
|
||||
<div v-for="item of elementIcons" :key="item" @click="handleClipboard(generateElementIconCode(item),$event)">
|
||||
<el-tooltip placement="top">
|
||||
<div slot="content">
|
||||
{{ generateElementIconCode(item) }}
|
||||
</div>
|
||||
<div class="icon-item">
|
||||
<i :class="'el-icon-' + item" />
|
||||
<span>{{ item }}</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import clipboard from '@/utils/clipboard'
|
||||
import svgIcons from './svg-icons'
|
||||
import elementIcons from './element-icons'
|
||||
|
||||
export default {
|
||||
name: 'Icons',
|
||||
data() {
|
||||
return {
|
||||
svgIcons,
|
||||
elementIcons
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generateIconCode(symbol) {
|
||||
return `<svg-icon icon-class="${symbol}" />`
|
||||
},
|
||||
generateElementIconCode(symbol) {
|
||||
return `<i class="el-icon-${symbol}" />`
|
||||
},
|
||||
handleClipboard(text, event) {
|
||||
clipboard(text, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icons-container {
|
||||
margin: 10px 20px 0;
|
||||
overflow: hidden;
|
||||
|
||||
.icon-item {
|
||||
margin: 20px;
|
||||
height: 85px;
|
||||
text-align: center;
|
||||
width: 100px;
|
||||
float: left;
|
||||
font-size: 30px;
|
||||
color: #24292e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue