This commit is contained in:
zhangwei 2019-01-20 15:36:26 +08:00
parent e384b8dfea
commit 5066865682
34 changed files with 1366 additions and 301 deletions

View File

@ -6,6 +6,12 @@
<script>
export default{
name: 'App'
name: 'App',
created() {
// sessionStorage
if (sessionStorage.getItem('store')) {
this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store'))))
}
}
}
</script>

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function fetchList(query) {
return request({
url: '/article/list',
url: '/ueditor/list',
method: 'get',
params: query
})
@ -10,9 +10,8 @@ export function fetchList(query) {
export function fetchArticle(id) {
return request({
url: '/article/detail',
method: 'get',
params: { id }
url: '/ueditor/detail/' + id,
method: 'get'
})
}
@ -39,3 +38,18 @@ export function updateArticle(data) {
data
})
}
export function saveArticle(data) {
return request({
url: '/ueditor/save',
method: 'post',
data
})
}
export function deleteArticle(id) {
return request({
url: '/ueditor/del/' + id,
method: 'get'
})
}

49
src/api/grade.js Normal file
View File

@ -0,0 +1,49 @@
import request from '@/utils/request'
// 获取组List信息
export function fetchList(query) {
return request({
url: '/grade/list',
method: 'get',
params: query
})
}
export function getClassList(query) {
return request({
url: '/class/list',
method: 'get',
params: query
})
}
export function fetchStuList(listQuery) {
return request({
url: '/stu/' + listQuery.type,
method: 'get'
})
}
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
})
}

50
src/api/group.js Normal file
View File

@ -0,0 +1,50 @@
import request from '@/utils/request'
// 获取组List信息
export function fetchGroupList(query) {
return request({
url: '/group/list',
method: 'get',
params: query
})
}
export function fetchMemberList(id) {
return request({
url: '/group/getMembers',
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: '/group/addGroup',
method: 'post',
data
})
}
export function deleteGroup(id) {
return request({
url: '/group/delete',
method: 'get',
params: { id }
})
}

View File

@ -1,21 +1,22 @@
import request from '@/utils/request'
export function loginByUsername(username, password) {
export function loginByUsername(username, password, fid) {
const data = {
username,
password
password,
fid
}
return request({
url: '/login/login',
method: 'post',
data
url: '/user/login',
method: 'get',
params: data
})
}
export function logout() {
return request({
url: '/login/logout',
method: 'post'
url: '/user/logout',
method: 'get'
})
}

222
src/api/user.js Normal file
View File

@ -0,0 +1,222 @@
import request from '@/utils/request'
export function fetchTeacherList(query) {
return request({
url: '/teacher/list',
method: 'get',
params: query
})
}
export function fetchStuList(query) {
return request({
url: '/student/list',
method: 'get',
params: query
})
}
export function fetchGroupList(query) {
return request({
url: '/group/list',
method: 'get',
params: query
})
}
export function updateTeacher(data) {
return request({
url: '/teacher/update',
method: 'post',
data
})
}
export function deleteTeacher(query) {
return request({
url: '/teacher/delete',
method: 'get',
params: query
})
}
export function fetchList(query) {
return request({
url: '/user/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 createStudent(data) {
return request({
url: '/student/update',
method: 'post',
data
})
}
export function saveArticle(data) {
return request({
url: '/ueditor/save',
method: 'post',
data
})
}
export function fetchGradeList(query) {
return request({
url: '/grade/list',
method: 'get',
params: query
})
}
export function fetchClassList(query) {
return request({
url: '/class/list',
method: 'get',
params: query
})
}
export function updateStudent(data) {
return request({
url: '/student/update',
method: 'post',
data
})
}
export function updateGrade(data) {
return request({
url: '/grade/update',
method: 'post',
data
})
}
export function fetchUploadUserList(query) {
return request({
url: '/ueditor/getUploadUserList',
method: 'get',
params: query
})
}
export function downloadFile(url, name) {
var data = window.UEDITOR_HOME_URL + 'ueditor/download?url=' + url + '&name=' + name
window.location.href = data
}
export function downloadZip(articleId, name) {
var data = window.UEDITOR_HOME_URL + 'ueditor/downloadZip?articleId=' + articleId + '&name=' + name
window.location.href = data
}
export function deleteAttachment(query) {
return request({
url: '/ueditor/deleteAttachment',
method: 'get',
params: query
})
}
export function fetchCourseList(query) {
return request({
url: '/course/list',
method: 'get',
params: query
})
}
export function deleteStudent(data) {
return request({
url: '/student/del',
method: 'post',
data
})
}
// 删除年级
export function deleteGrade(id) {
return request({
url: '/grade/del/' + id,
method: 'get'
})
}
export function fetchScheduleList(query) {
return request({
url: '/course/schedule',
method: 'get',
params: query
})
}
export function fetchCourseByClassId(classId) {
return request({
url: '/course/' + classId,
method: 'get'
})
}
export function updateSchedule(data) {
return request({
url: '/course/update',
method: 'post',
data
})
}
// 根据fid获取xy_school学校表信息
export function fetchSchool(query) {
return request({
url: '/system/school',
method: 'get',
params: query
})
}
// 更新学校消息
export function updateSchool(data) {
return request({
url: '/system/update',
method: 'post',
data
})
}
// 获取微信模板列表
export function fetchTemplateList(query) {
return request({
url: '/system/templateList',
method: 'get',
params: query
})
}
// 为班级添加课程
export function addCourseClass(data) {
return request({
url: '/teacher/addCourseClass',
method: 'post',
data
})
}

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,8 @@
export default {
route: {
dashboard: 'Dashboard',
UEditor: 'UEditor',
group: 'group',
introduction: 'Introduction',
documentation: 'Documentation',
guide: 'Guide',

View File

@ -28,7 +28,7 @@ const messages = {
const i18n = new VueI18n({
// set locale
// options: en | zh | es
locale: Cookies.get('language') || 'en',
locale: Cookies.get('language') || 'zh',
// set locale messages
messages
})

View File

@ -1,6 +1,8 @@
export default {
route: {
dashboard: '首页',
UEditor: '编辑',
group: '小组',
introduction: '简述',
documentation: '文档',
guide: '引导页',
@ -29,6 +31,9 @@ export default {
lineChart: '折线图',
mixChart: '混合图表',
example: '综合实例',
notice: '公告',
createNotice: '创建公告',
noticeList: '公告列表',
nested: '路由嵌套',
menu1: '菜单1',
'menu1-1': '菜单1-1',
@ -53,6 +58,7 @@ export default {
page401: '401',
page404: '404',
errorLog: '错误日志',
myExample: '我的例子',
excel: 'Excel',
exportExcel: 'Export Excel',
selectExcel: 'Export Selected',
@ -62,7 +68,10 @@ export default {
theme: '换肤',
clipboardDemo: 'Clipboard',
i18n: '国际化',
externalLink: '外链'
externalLink: '外链',
laoshiguanli: '教师管理',
nianjiguanli: '年级管理',
xueshengguanli: '学生管理'
},
navbar: {
logOut: '退出登录',
@ -129,6 +138,38 @@ export default {
cancel: '取 消',
confirm: '确 定'
},
student: {
name: '姓名',
sex: '性别',
birth: '出生日期',
number: '身份证号',
address: '地址',
enrollment_time: '入学时间',
dynamicTips1: '固定表头, 按照表头顺序排序',
dynamicTips2: '不固定表头, 按照点击顺序排序',
dragTips1: '默认顺序',
dragTips2: '拖拽后顺序',
title: '标题',
importance: '重要性',
type: '类型',
remark: '点评',
search: '搜索',
add: '添加',
export: '导出',
reviewer: '审核人',
id: '序号',
date: '时间',
author: '作者',
readings: '阅读数',
status: '状态',
actions: '操作',
edit: '编辑',
publish: '发布',
draft: '草稿',
delete: '删除',
cancel: '取 消',
confirm: '确 定'
},
errorLog: {
tips: '请点击右上角bug小图标',
description: '现在的管理后台基本都是spa的形式了它增强了用户体验但同时也会增加页面出问题的可能性可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常,你可以在其中进行错误处理或者异常上报。',
@ -156,5 +197,34 @@ export default {
close: '关闭',
closeOthers: '关闭其它',
closeAll: '关闭所有'
}
},
group: {
name: '组 名',
add: '新 建 组',
member: '成 员',
delete: '删 除 组',
system: '系 统 组', // 系统自动生成的组。比如:老师按角色分为(语文组,数学组,小学组等); 学生分为(班级); 学生家长(班级)
comment: '组 描 述',
github: '项 目 地 址',
screenfull: '全 屏',
theme: '换 肤',
size: '布 局 大 小'
},
date: '日 期',
id: '序 号',
name: '姓 名',
createDate: '创 建 时 间',
comment: '描 述',
createUser: '创 建 者',
edit: '编辑',
create: '创建',
publish: '发 布',
draft: '草 稿',
delete: '删 除',
save: '保存',
cancel: '取 消',
confirm: '确 定',
detail: '详 情',
action: '操作',
export: '导出Excel'
}

View File

@ -9,12 +9,17 @@ import 'element-ui/lib/theme-chalk/index.css'
import '@/styles/index.scss' // global css
import '@/styles/schedule.css' // global css
import App from './App'
import router from './router'
import store from './store'
import i18n from './lang' // Internationalization
import './icons' // icon
// 引入图片库样式
import './assets/iconfont/iconfont.css'
// 使用svg需引入该js
import './assets/iconfont/iconfont.js'
import './errorLog' // error log
import './permission' // permission control
import './mock' // simulation data
@ -40,3 +45,4 @@ new Vue({
i18n,
render: h => h(App)
})
window.UEDITOR_HOME_URL = process.env.BASE_API + '/'

View File

@ -13,6 +13,7 @@ for (let i = 0; i < count; i++) {
timestamp: +Mock.Random.date('T'),
author: '@first',
reviewer: '@first',
fileList: [],
title: '@title(5, 10)',
content_short: '我是测试数据',
content: baseContent,

43
src/mock/grade.js Normal file
View File

@ -0,0 +1,43 @@
import Mock from 'mockjs'
const List = []
const count = 3
const Random = Mock.Random
for (let i = 0; i < count; i++) {
List.push(Mock.mock({
id: '@id',
timestamp: +Mock.Random.date('T'),
name1: Random.ctitle(2, 4), // 班级名称
school: Random.ctitle(2, 4) + '小学', // 所在学校
name: Random.date('yyyy') + '级' + Random.integer(1, 20) + '班'// 年级+班级
}))
}
const stuList = []
for (let i = 0; i < 40; i++) {
stuList.push(Mock.mock({
id: '@id',
timestamp: +Mock.Random.date('T'),
name: '@cname', // 名字
city: '@city',
address: '@province' + '@city' + '@county',
tel: /^1[385][1-9]\d{8}/,
school: Random.ctitle(2, 4) + '小学', // 所在学校
grade: Random.date('yyyy') + '级' + Random.integer(1, 20) + '班'// 年级+班级
}))
}
export default {
getClassList: () => {
return {
total: List.length,
result: List
}
},
fetchStuList: () => {
return {
total: stuList.length,
result: stuList
}
}
}

View File

@ -1,15 +1,16 @@
import Mock from 'mockjs'
import loginAPI from './login'
import articleAPI from './article'
import grade from './grade'
import remoteSearchAPI from './remoteSearch'
import transactionAPI from './transaction'
// 修复在使用 MockJS 情况下,设置 withCredentials = true且未被拦截的跨域请求丢失 Cookies 的问题
// https://github.com/nuysoft/Mock/issues/300
// * 修复 Mock 情况下,设置 withCredentials = true且未被拦截的跨域请求丢失 Cookies 的问题
// 请求中丢失session导致每次请求sessionId不同
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false
this.custom.xhr.withCredentials = this.withCredentials || true
}
this.proxy_send(...arguments)
}
@ -19,9 +20,9 @@ Mock.XHR.prototype.send = function() {
// })
// 登录相关
Mock.mock(/\/login\/login/, 'post', loginAPI.loginByUsername)
// Mock.mock(/\/user\/login/, 'post', loginAPI.loginByUsername)
Mock.mock(/\/login\/logout/, 'post', loginAPI.logout)
Mock.mock(/\/user\/info\.*/, 'get', loginAPI.getUserInfo)
// Mock.mock(/\/user\/info\.*/, 'get', loginAPI.getUserInfo)
// 文章相关
Mock.mock(/\/article\/list/, 'get', articleAPI.getList)
@ -36,4 +37,10 @@ Mock.mock(/\/search\/user/, 'get', remoteSearchAPI.searchUser)
// 账单相关
Mock.mock(/\/transaction\/list/, 'get', transactionAPI.getList)
// 根据uid获取对应班级列表。学生有一个班级老师有多个
// Mock.mock(/\/class\/list/, 'get', grade.classList)
// 根据uid获取班级信息
// Mock.mock(/\/class\/\w*/, 'get', grade.getClassList)
// 根据班级ID获取学生信息
Mock.mock(/\/stu\/\w*/, 'get', grade.fetchStuList)
export default Mock

View File

@ -1,34 +1,35 @@
import { param2Obj } from '@/utils'
// import { param2Obj } from '@/utils'
const userMap = {
admin: {
roles: ['admin'],
token: 'admin',
introduction: '我是超级管理员',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Super Admin'
},
editor: {
roles: ['editor'],
token: 'editor',
introduction: '我是编辑',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Normal Editor'
}
}
// const userMap = {
// admin: {
// roles: ['admin'],
// token: 'admin',
// introduction: '我是超级管理员',
// avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
// name: 'Super Admin'
// },
// editor: {
// roles: ['editor'],
// token: 'editor',
// introduction: '我是编辑',
// avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
// name: 'Normal Editor'
// }
// }
export default {
loginByUsername: config => {
const { username } = JSON.parse(config.body)
return userMap[username]
},
getUserInfo: config => {
const { token } = param2Obj(config.url)
if (userMap[token]) {
return userMap[token]
} else {
return false
}
},
logout: () => 'success'
// loginByUsername: config => {
// debugger
// const { username } = JSON.parse(config.body)
// return userMap[username]
// },
// getUserInfo: config => {
// const { token } = param2Obj(config.url)
// if (userMap[token]) {
// return userMap[token]
// } else {
// return false
// }
// },
// logout: () => 'success'
}

View File

@ -9,7 +9,9 @@ NProgress.configure({ showSpinner: false })// NProgress Configuration
// permission judge function
function hasPermission(roles, permissionRoles) {
if (roles.indexOf('admin') >= 0) return true // admin permission passed directly
if (roles.includes(1) || roles.includes(0)) {
return true // admin permission passed directly
}
if (!permissionRoles) return true
return roles.some(role => permissionRoles.indexOf(role) >= 0)
}
@ -26,7 +28,7 @@ router.beforeEach((to, from, next) => {
} else {
if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
store.dispatch('GetUserInfo').then(res => { // 拉取user_info
const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop']
const roles = res.data.result.roles // note: roles must be a array! such as: ['editor','develop']
store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
@ -49,7 +51,7 @@ router.beforeEach((to, from, next) => {
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
if (whiteList.indexOf(to.path) !== -1 || (to.meta.title && to.meta.title === 'notice')) { // 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页

View File

@ -6,12 +6,6 @@ Vue.use(Router)
/* Layout */
import Layout from '@/views/layout/Layout'
/* Router Modules */
import componentsRouter from './modules/components'
import chartsRouter from './modules/charts'
import tableRouter from './modules/table'
import nestedRouter from './modules/nested'
/** note: Submenu only appear when children.length>=1
* detail see https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
**/
@ -58,6 +52,12 @@ export const constantRouterMap = [
component: () => import('@/views/errorPage/404'),
hidden: true
},
{
path: '/notice/:id(\\d+)',
component: () => import('@/views/notice/show'),
hidden: true,
meta: { title: 'notice', icon: 'notice', noCache: true }
},
{
path: '/401',
component: () => import('@/views/errorPage/401'),
@ -112,258 +112,227 @@ export default new Router({
export const asyncRouterMap = [
{
path: '/permission',
path: '/notice',
component: Layout,
redirect: '/permission/index',
alwaysShow: true, // will always show the root menu
redirect: '/notice/list',
name: 'Notice',
meta: {
title: 'permission',
icon: 'lock',
roles: ['admin', 'editor'] // you can set roles in root nav
},
children: [
{
path: 'page',
component: () => import('@/views/permission/page'),
name: 'PagePermission',
meta: {
title: 'pagePermission',
roles: ['admin'] // or you can only set roles in sub nav
}
},
{
path: 'directive',
component: () => import('@/views/permission/directive'),
name: 'DirectivePermission',
meta: {
title: 'directivePermission'
// if do not set roles, means: this page does not require permission
}
}
]
},
{
path: '/icon',
component: Layout,
children: [
{
path: 'index',
component: () => import('@/views/svg-icons/index'),
name: 'Icons',
meta: { title: 'icons', icon: 'icon', noCache: true }
}
]
},
/** When your routing table is too long, you can split it into small modules**/
componentsRouter,
chartsRouter,
nestedRouter,
tableRouter,
{
path: '/example',
component: Layout,
redirect: '/example/list',
name: 'Example',
meta: {
title: 'example',
title: 'notice',
icon: 'example'
},
children: [
{
path: 'create',
component: () => import('@/views/example/create'),
name: 'CreateArticle',
meta: { title: 'createArticle', icon: 'edit' }
component: () => import('@/views/components-demo/uEditor'),
name: 'CreateNotice',
meta: { title: 'createNotice', icon: 'edit' }
},
{
path: 'edit/:id(\\d+)',
component: () => import('@/views/example/edit'),
name: 'EditArticle',
meta: { title: 'editArticle', noCache: true },
component: () => import('@/views/components-demo/uEditor'),
name: 'EditNotice',
meta: { title: '公告编辑', noCache: true },
hidden: true
},
{
path: 'list',
component: () => import('@/views/example/list'),
name: 'ArticleList',
meta: { title: 'articleList', icon: 'list' }
component: () => import('@/views/notice/list'),
name: 'NoticeList',
meta: { title: 'noticeList', icon: 'list' }
}
]
},
{
path: '/tab',
path: '/laoshiguanli',
component: Layout,
children: [
{
path: 'index',
component: () => import('@/views/tab/index'),
name: 'Tab',
meta: { title: 'tab', icon: 'tab' }
component: () => import('@/views/teacher/complexTable'),
name: 'laoshiguanli',
meta: { title: 'laoshiguanli', icon: 'laoshiguanli' }
}
]
},
{
path: '/error',
path: '/nianjiguanli',
component: Layout,
redirect: 'noredirect',
name: 'ErrorPages',
children: [
{
path: 'index',
component: () => import('@/views/grade/complexTable'),
name: 'nianjiguanli',
meta: { title: 'nianjiguanli', icon: 'nianjiguanli' }
}
]
},
{
path: '/xueshengguanli',
component: Layout,
children: [
{
path: 'index',
component: () => import('@/views/student/complexTable'),
name: 'xueshengguanli',
meta: { title: 'xueshengguanli', icon: 'xueshengguanli', noCache: true }
}
]
},
{
path: '/myclass',
component: Layout,
children: [
{
path: 'index',
component: () => import('@/views/myclass/index'),
name: '执教班级',
meta: { title: '执教班级', icon: 'tab' }
}
]
},
{
path: '/group',
component: Layout,
redirect: '/group/index',
children: [
{
path: 'index',
component: () => import('@/views/group/index'),
name: 'group',
meta: { title: 'group', icon: 'group' }
}
]
},
{
path: '/leave',
component: Layout,
redirect: '/leave/list',
name: 'Leave',
meta: {
title: 'errorPages',
icon: '404'
title: '请假',
icon: 'qingjia'
},
children: [
{
path: '401',
component: () => import('@/views/errorPage/401'),
name: 'Page401',
meta: { title: 'page401', noCache: true }
path: 'create',
component: () => import('@/views/components-demo/uEditor'),
name: 'CreateLeave',
meta: { title: '创建请假', icon: 'edit' }
},
{
path: '404',
component: () => import('@/views/errorPage/404'),
name: 'Page404',
meta: { title: 'page404', noCache: true }
}
]
},
{
path: '/error-log',
component: Layout,
redirect: 'noredirect',
children: [
path: 'edit/:id(\\d+)',
component: () => import('@/views/components-demo/uEditor'),
name: 'EditNotice',
meta: { title: '编辑请假', noCache: true },
hidden: true
},
{
path: 'log',
component: () => import('@/views/errorLog/index'),
name: 'ErrorLog',
meta: { title: 'errorLog', icon: 'bug' }
path: 'list',
component: () => import('@/views/leave/list'),
name: 'LeaveList',
meta: { title: '我的请假', icon: 'list' }
}
]
},
{
path: '/excel',
path: '/form',
component: Layout,
redirect: '/excel/export-excel',
name: 'Excel',
redirect: '/form/list',
name: 'Form',
meta: {
title: 'excel',
icon: 'excel'
title: '表单',
icon: 'biaodan'
},
children: [
{
path: 'export-excel',
component: () => import('@/views/excel/exportExcel'),
name: 'ExportExcel',
meta: { title: 'exportExcel' }
path: 'create',
component: () => import('@/views/form/create'),
name: 'CreateForm',
meta: { title: '新建表单', icon: 'edit' }
},
{
path: 'export-selected-excel',
component: () => import('@/views/excel/selectExcel'),
name: 'SelectExcel',
meta: { title: 'selectExcel' }
path: 'edit/:id(\\d+)',
component: () => import('@/views/components-demo/uEditor'),
name: 'EditNotice',
meta: { title: '编辑请假', noCache: true },
hidden: true
},
{
path: 'upload-excel',
component: () => import('@/views/excel/uploadExcel'),
name: 'UploadExcel',
meta: { title: 'uploadExcel' }
path: 'list',
component: () => import('@/views/leave/list'),
name: 'LeaveList',
meta: { title: '我的请假', icon: 'list' }
}
]
},
{
path: '/zip',
path: '/module',
component: Layout,
redirect: '/zip/download',
alwaysShow: true,
meta: { title: 'zip', icon: 'zip' },
redirect: '/module/list',
name: 'Module',
meta: {
title: '模块管理',
icon: 'biaodan'
},
children: [
{
path: 'download',
component: () => import('@/views/zip/index'),
name: 'ExportZip',
meta: { title: 'exportZip' }
path: 'create',
component: () => import('@/views/form/create'),
name: 'CreateForm',
meta: { title: '新建模块', icon: 'edit' }
},
{
path: 'edit/:id(\\d+)',
component: () => import('@/views/components-demo/uEditor'),
name: 'EditNotice',
meta: { title: '编辑请假', noCache: true },
hidden: true
},
{
path: 'list',
component: () => import('@/views/module/complexTable'),
name: 'ModuleList',
meta: { title: '模块列表', icon: 'list' }
}
]
},
{
path: '/pdf',
path: '/system',
component: Layout,
redirect: '/pdf/index',
meta: { title: 'PDF', icon: 'pdf' },
redirect: '/system/list',
name: 'System',
meta: {
title: '系统管理',
icon: 'biaodan'
},
children: [
{
path: 'index',
component: () => import('@/views/pdf/index'),
name: 'PDF',
meta: { title: 'PDF' }
}
]
},
{
path: '/pdf/download',
component: () => import('@/views/pdf/download'),
hidden: true
},
{
path: '/theme',
component: Layout,
redirect: 'noredirect',
children: [
path: 'school',
component: () => import('@/views/system/schoolForm'),
name: 'SchoolForm',
meta: { title: '系统管理', icon: 'edit' }
},
{
path: 'index',
component: () => import('@/views/theme/index'),
name: 'Theme',
meta: { title: 'theme', icon: 'theme' }
}
]
},
{
path: '/clipboard',
component: Layout,
redirect: 'noredirect',
children: [
path: 'wechatTemplate',
component: () => import('@/views/system/wechatTemplate'),
name: 'WechatTemplate',
meta: { title: '微信消息模板', icon: 'edit' }
},
{
path: 'index',
component: () => import('@/views/clipboard/index'),
name: 'ClipboardDemo',
meta: { title: 'clipboardDemo', icon: 'clipboard' }
}
]
},
{
path: '/i18n',
component: Layout,
children: [
path: 'edit/:id(\\d+)',
component: () => import('@/views/components-demo/uEditor'),
name: 'EditNotice',
meta: { title: '编辑请假', noCache: true },
hidden: true
},
{
path: 'index',
component: () => import('@/views/i18n-demo/index'),
name: 'I18n',
meta: { title: 'i18n', icon: 'international' }
path: 'list',
component: () => import('@/views/module/complexTable'),
name: 'ModuleList',
meta: { title: '模块列表', icon: 'list' }
}
]
},
{
path: 'external-link',
component: Layout,
children: [
{
path: 'https://github.com/PanJiaChen/vue-element-admin',
meta: { title: 'externalLink', icon: 'link' }
}
]
},
{ path: '*', redirect: '/404', hidden: true }
]

View File

@ -25,10 +25,10 @@ const componentsRouter = {
meta: { title: 'markdown' }
},
{
path: 'json-editor',
component: () => import('@/views/components-demo/jsonEditor'),
name: 'JsonEditorDemo',
meta: { title: 'jsonEditor' }
path: 'ueditor',
component: () => import('@/views/components-demo/uEditor'),
name: 'uEditorDemo',
meta: { title: 'UEditor' }
},
{
path: 'splitpane',

View File

@ -8,12 +8,15 @@ const getters = {
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name,
fid: state => state.user.fid,
uid: state => state.user.uid,
introduction: state => state.user.introduction,
status: state => state.user.status,
roles: state => state.user.roles,
setting: state => state.user.setting,
permission_routers: state => state.permission.routers,
addRouters: state => state.permission.addRouters,
errorLogs: state => state.errorLog.logs
errorLogs: state => state.errorLog.logs,
user: state => state.user
}
export default getters

View File

@ -7,7 +7,7 @@ const app = {
withoutAnimation: false
},
device: 'desktop',
language: Cookies.get('language') || 'en',
language: Cookies.get('language') || 'zh',
size: Cookies.get('size') || 'medium'
},
mutations: {

View File

@ -7,7 +7,7 @@ import { asyncRouterMap, constantRouterMap } from '@/router'
*/
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
return roles.some(role => route.meta.roles.indexOf(role) >= 0)
} else {
return true
}
@ -50,7 +50,7 @@ const permission = {
return new Promise(resolve => {
const { roles } = data
let accessedRouters
if (roles.includes('admin')) {
if (data.roles.includes(1) || data.roles.includes(0)) {
accessedRouters = asyncRouterMap
} else {
accessedRouters = filterAsyncRouter(asyncRouterMap, roles)

View File

@ -1,16 +1,19 @@
import { loginByUsername, logout, getUserInfo } from '@/api/login'
import { Message } from 'element-ui'
import { getToken, setToken, removeToken } from '@/utils/auth'
const user = {
state: {
user: '',
status: '',
code: '',
token: getToken(),
admin: false,
name: '',
fid: '',
uid: '',
roles: [],
avatar: '',
introduction: '',
roles: [],
setting: {
articlePlatform: []
}
@ -35,6 +38,16 @@ const user = {
SET_NAME: (state, name) => {
state.name = name
},
SET_FID: (state, fid) => {
state.fid = fid
},
SET_ADMIN: (state, admin) => {
state.admin = admin
},
SET_UID: (state, uid) => {
state.uid = uid
},
// 头像
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
@ -47,12 +60,27 @@ const user = {
// 用户名登录
LoginByUsername({ commit }, userInfo) {
const username = userInfo.username.trim()
userInfo.fid = 1
const fid = parseInt(userInfo.fid)
return new Promise((resolve, reject) => {
loginByUsername(username, userInfo.password).then(response => {
const data = response.data
commit('SET_TOKEN', data.token)
setToken(response.data.token)
resolve()
loginByUsername(username, userInfo.password, fid).then(response => {
if (response.data.code === 200) {
const data = response.data.result
commit('SET_TOKEN', data.token)
commit('SET_FID', fid)
commit('SET_NAME', data.name)
commit('SET_ADMIN', data.roles.includes(1))
commit('SET_UID', data.uid)
setToken(data.token)
resolve()
} else {
Message({
message: response.data.message,
type: 'error',
duration: 4 * 1000
})
resolve()
}
}).catch(error => {
reject(error)
})
@ -63,21 +91,18 @@ const user = {
GetUserInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getUserInfo(state.token).then(response => {
// 由于mockjs 不支持自定义状态码只能这样hack
if (!response.data) {
reject('Verification failed, please login again.')
var data = response.data.result
if (!data) { // 由于mockjs 不支持自定义状态码只能这样hack
reject('error')
}
const data = response.data
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', data.roles)
} else {
reject('getInfo: roles must be a non-null array!')
reject('getInfo: roles must be a non-null array !')
}
commit('SET_NAME', data.name)
commit('SET_AVATAR', data.avatar)
commit('SET_INTRODUCTION', data.introduction)
commit('SET_AVATAR', 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif')
commit('SET_INTRODUCTION', '我是超级管理员')
resolve(response)
}).catch(error => {
reject(error)

View File

@ -199,3 +199,47 @@ code {
.multiselect--active {
z-index: 1000 !important;
}
.el-table--medium td, .el-table--medium th {
padding: 3px 0;
}
// cell-style="padding:0"
// 表格cell
.el-table td{
padding: 0px 0;
}
// 输入框
.el-input--medium .el-input__inner {
height: 30px;
line-height: 30px;
}
// 标准按钮
.el-button--medium {
padding: 8px 10px;
}
#online li div span.file-title {
height: 18px;
}
.el-form-item {
margin-bottom: 14px;
}
.el-dialog__body {
padding: 10px 20px;
color: #606266;
font-size: 14px;
}
.el-table--enable-row-hover .el-table__body tr:hover>td{
background-color: #ecfffa;
}
img {
max-width: 100%;
}

145
src/styles/schedule.css Normal file
View File

@ -0,0 +1,145 @@
body{background-color: white;}
.tr_btn {
width: 100%;
height: 35px;
}
.td_btn {
height: 35px;
line-height: 35px;
font-family: "微软雅黑";
font-weight: bold;
}
.tr_top {
width: 100%;
height: 25px;
}
.td_top_title {
width: 10%;
height: 25px;
line-height: 25px;
font-family: "微软雅黑";
font-size: 15px;;
font-weight: bold;
text-align: center;
float: left;
color:#007BFF;
}
.td_top_data {
width: 12%;
height: 25px;
line-height: 25px;
font-family: "楷体";
font-size: 15px;
font-weight: bold;
text-align: center;
float: left;
}
.td_top_data_change {
font-size: 17px;
font-family: "楷体";
color: white;
background-color: #9FCDFF;
}
.tr_week {
width: 100%;
}
.td_week_title {
width: 10%;
font-family: "微软雅黑";
font-weight: bold;
text-align: center;
float: left;
}
.td_week_title_content {
height: 40px;
margin-top: 2px;
background-color: #EBEBEB;
line-height: 40px;
}
.td_week_data {
width: 12%;
font-family: "微软雅黑";
font-weight: bold;
float: left;
}
.td_week_data_content:active {
color: black;
background-color: #9FCDFF;
}
.td_week_data_content:visited {
color: black;
}
.td_week_data_content {
height: 40px;
padding: 2px;
margin-top:2px;
margin-left: 2px;
text-align: center;
background-color: #f0f0f0;
border-radius: 5px;
position: relative;
max-height: 40px;
overflow: hidden;
}
.td_week_data_content::after {
/** content: "..."; */
position: absolute;
bottom: 0;
right: 0;
padding-left: 20px;
/*background: -webkit-linear-gradient(left, transparent, #fff 100%);
background: -o-linear-gradient(right, transparent, #fff 100%);
background: -moz-linear-gradient(right, transparent, #fff 100%);
background: linear-gradient(to right, transparent, #fff 100%);*/
}
.td_color{
background-color: white;
border-radius: 0;
}
.td_color::after {
content: "";
position: absolute;
bottom: 0;
right: 0;
background: -webkit-linear-gradient(left, transparent, #fff 100%);
background: -o-linear-gradient(right, transparent, #fff 100%);
background: -moz-linear-gradient(right, transparent, #fff 100%);
background: linear-gradient(to right, transparent, #fff 100%);
}
.td_color:active {
background-color: white;
}
.td_color:visited {
background-color:white;
}
.show{
width: 100%;
height: auto;
word-wrap:break-word;
word-break:break-all;
overflow: hidden;
}

View File

@ -6,6 +6,7 @@
transition: margin-left .28s;
margin-left: $sideBarWidth;
position: relative;
background-color: #FCFAF7;
}
// 侧边栏 Sidebar container

View File

@ -12,4 +12,4 @@ $panGreen: #30B08F;
$menuBg:#304156;
$subMenuBg:#1f2d3d;
$menuHover:#001528;
$sideBarWidth: 180px;
$sideBarWidth: 200px;

View File

@ -3,9 +3,12 @@
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
if (arguments.length === 0 || time == null) {
return null
}
if (typeof time === 'string') {
return time
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
@ -164,6 +167,17 @@ export function objectMerge(target, source) {
return target
}
export function scrollTo(element, to, duration) {
if (duration <= 0) return
const difference = to - element.scrollTop
const perTick = (difference / duration) * 10
setTimeout(() => {
element.scrollTop = element.scrollTop + perTick
if (element.scrollTop === to) return
scrollTo(element, to, duration - 10)
}, 10)
}
export function toggleClass(element, className) {
if (!element || !className) {
return
@ -289,3 +303,153 @@ export function uniqueArr(arr) {
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
// 获取d当前时间多少天后的日期和对应星期
export function getDates(days) {
// todate默认参数是当前日期可以传入对应时间
var dateArry = []
for (var i = 0; i < days; i++) {
var dateObj = dateLater(getCurrentMonthFirst(), i)
dateArry.push(dateObj)
}
return dateArry
}
/** * 传入时间后几天 * param传入时间dates:"2018-04-02",later:往后多少天 */
export function dateLater(dates, later) {
var dateObj = {}
var show_day = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
var date = new Date(dates)
date.setDate(date.getDate() + later)
var day = date.getDay()
dateObj.year = date.getFullYear()
dateObj.month = ((date.getMonth() + 1) < 10 ? ('0' + (date.getMonth() + 1)) : date.getMonth() + 1)
dateObj.day = (date.getDate() < 10 ? ('0' + date.getDate()) : date.getDate())
dateObj.week = show_day[day]
return dateObj
}
// 获取当前时间
export function getCurrentMonthFirst() {
var date = new Date()
var todate = date.getFullYear() + '-' + ((date.getMonth() + 1) < 10 ? ('0' + (date.getMonth() + 1)) : date.getMonth() + 1) + '-' + (date.getDate() < 10 ? ('0' + date.getDate()) : date.getDate())
return todate
}
export function getDays() {
var data = new Date()
var setData = ''
var weeks = dateLater(data, 0).week
switch (weeks) {
case '周一':
setData = [
dateLater(data, 0).day,
dateLater(data, 1).day,
dateLater(data, 2).day,
dateLater(data, 3).day,
dateLater(data, 4).day,
dateLater(data, 5).day,
dateLater(data, 6).day
]
break
case '周二':
setData = [
dateLater(data, -1).day,
dateLater(data, 0).day,
dateLater(data, 1).day,
dateLater(data, 2).day,
dateLater(data, 3).day,
dateLater(data, 4).day,
dateLater(data, 5).day
]
break
case '周三':
setData = [
dateLater(data, -2).day,
dateLater(data, -1).day,
dateLater(data, 0).day,
dateLater(data, 1).day,
dateLater(data, 2).day,
dateLater(data, 3).day,
dateLater(data, 4).day
]
break
case '周四':
setData = [
dateLater(data, -3).day,
dateLater(data, -2).day,
dateLater(data, -1).day,
dateLater(data, 0).day,
dateLater(data, 1).day,
dateLater(data, 2).day,
dateLater(data, 3).day
]
break
case '周五':
setData = [
dateLater(data, -4).day,
dateLater(data, -3).day,
dateLater(data, -2).day,
dateLater(data, -1).day,
dateLater(data, 0).day,
dateLater(data, 1).day,
dateLater(data, 2).day
]
break
case '周六':
setData = [
dateLater(data, -5).day,
dateLater(data, -4).day,
dateLater(data, -3).day,
dateLater(data, -2).day,
dateLater(data, -1).day,
dateLater(data, 0).day,
dateLater(data, 1).day
]
break
case '周日':
setData = [
dateLater(data, -6).day,
dateLater(data, -5).day,
dateLater(data, -4).day,
dateLater(data, -3).day,
dateLater(data, -2).day,
dateLater(data, -1).day,
dateLater(data, 0).day
]
break
default:
break
}
if (setData !== '') {
return setData
} else {
return ''
}
}
export function getYear() {
var Year = new Date().getFullYear()
var setData = [Year - 1, Year, Year - 2, Year - 3]
return setData
}
export function formatMonth() {
var date = new Date()
var month = date.getMonth() + 1
return month
}
export function formatDay(time) {
var date = new Date()
var day = date.getDate()
if (time === day) return true
return false
}
export function getWeeks(week) {
var data = new Date()
var weeks = dateLater(data, 0).week
if (weeks === week) return true
return false
}

View File

@ -2,11 +2,14 @@ import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import { MessageBox } from 'element-ui'
// create an axios instance
const service = axios.create({
baseURL: process.env.BASE_API, // api 的 base_url
timeout: 5000 // request timeout
timeout: 5000, // request timeout
// mock可能导致此属性生效。mock/index.js文件已修复
withCredentials: true // 是否允许发送Cookie 如果为true 则服务器的 Access-control-Allow-Credentials 必须为 true 来源为 XMLHttpRequest的withCredentials配置项
})
// request interceptor
@ -16,6 +19,7 @@ service.interceptors.request.use(
if (store.getters.token) {
// 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改
config.headers['X-Token'] = getToken()
config.headers['UID'] = store.state.user.uid
}
return config
},
@ -28,40 +32,59 @@ service.interceptors.request.use(
// response interceptor
service.interceptors.response.use(
response => response,
// response => response,
/**
* 下面的注释为通过在response里自定义code来标示请求状态
* 当code返回如下情况则说明权限有问题登出并返回到登录页
* 如想通过 xmlhttprequest 来状态码标识 逻辑可写在下面error中
* 以下代码均为样例请结合自生需求加以修改若不需要则可删除
*/
// response => {
// const res = response.data
// if (res.code !== 20000) {
// Message({
// message: res.message,
// type: 'error',
// duration: 5 * 1000
// })
// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// // 请自行在引入 MessageBox
// // import { Message, MessageBox } from 'element-ui'
// MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
// confirmButtonText: '重新登录',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// store.dispatch('FedLogOut').then(() => {
// location.reload() // 为了重新实例化vue-router对象 避免bug
// })
// })
// }
// return Promise.reject('error')
// } else {
// return response.data
// }
// },
response => {
const res = response.data
if (!res.code) {
console.log('mock数据请求...' + response.data)
return response
} else if (res.code !== 200) {
// Message({
// message: res.message,
// type: 'error',
// duration: 5 * 1000
// })
// 退出登录
if (res.code === 50068) {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
} else if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
// 请自行在引入 MessageBox
// import { Message, MessageBox } from 'element-ui'
MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
} else if (res.code === 601) { // 主键冲突
Message({
message: res.message,
type: 'error',
duration: 5 * 1000
})
} else {
Message({
message: '其他异常: ' + res.message,
type: 'error',
duration: 5 * 1000
})
}
return Promise.reject()
} else {
return response
}
},
error => {
console.log('err' + error) // for debug
Message({

View File

@ -3,8 +3,9 @@
*/
export function isvalidUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
if (str === '') {
return '用户名不能为空!'
}
}
/* 合法uri*/
@ -40,3 +41,8 @@ export function validateEmail(email) {
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return re.test(email)
}
export function isvalidStr(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}