@ -0,0 +1,3 @@ |
|||||||
|
> 1% |
||||||
|
last 2 versions |
||||||
|
not ie <= 8 |
@ -0,0 +1,22 @@ |
|||||||
|
.DS_Store |
||||||
|
node_modules |
||||||
|
/dist |
||||||
|
example.html |
||||||
|
favicon.ico |
||||||
|
# local env files |
||||||
|
.env.local |
||||||
|
.env.*.local |
||||||
|
|
||||||
|
# Log files |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
|
||||||
|
# Editor directories and files |
||||||
|
.idea |
||||||
|
.vscode |
||||||
|
*.suo |
||||||
|
*.ntvs* |
||||||
|
*.njsproj |
||||||
|
*.sln |
||||||
|
*.sw* |
@ -0,0 +1,6 @@ |
|||||||
|
{ |
||||||
|
"tabWidth": 4, |
||||||
|
"singleQuote": true, |
||||||
|
"trailingComma": "none", |
||||||
|
"printWidth": 140 |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
MIT License |
||||||
|
|
||||||
|
Copyright (c) 2016-2019 vue-manage-system |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
of this software and associated documentation files (the "Software"), to deal |
||||||
|
in the Software without restriction, including without limitation the rights |
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
copies of the Software, and to permit persons to whom the Software is |
||||||
|
furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all |
||||||
|
copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
SOFTWARE. |
@ -0,0 +1,197 @@ |
|||||||
|
# vue-manage-system |
||||||
|
|
||||||
|
<a href="https://github.com/vuejs/vue"> |
||||||
|
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue"> |
||||||
|
</a> |
||||||
|
<a href="https://github.com/ElemeFE/element"> |
||||||
|
<img src="https://img.shields.io/badge/element--ui-2.8.2-brightgreen.svg" alt="element-ui"> |
||||||
|
</a> |
||||||
|
<a href="https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE"> |
||||||
|
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license"> |
||||||
|
</a> |
||||||
|
<a href="https://github.com/lin-xin/vue-manage-system/releases"> |
||||||
|
<img src="https://img.shields.io/github/release/lin-xin/vue-manage-system.svg" alt="GitHub release"> |
||||||
|
</a> |
||||||
|
<a href="https://lin-xin.gitee.io/example/work/#/donate"> |
||||||
|
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate"> |
||||||
|
</a> |
||||||
|
|
||||||
|
基于 Vue + Element UI 的后台管理系统解决方案。[线上地址](https://lin-xin.gitee.io/example/work/) |
||||||
|
|
||||||
|
> React + Ant Design 的版本正在开发中,仓库地址:[react-manage-system](https://github.com/lin-xin/react-manage-system) |
||||||
|
|
||||||
|
[English document](https://github.com/lin-xin/manage-system/blob/master/README_EN.md) |
||||||
|
|
||||||
|
## 项目截图 |
||||||
|
|
||||||
|
### 登录 |
||||||
|
|
||||||
|
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms3.png) |
||||||
|
|
||||||
|
### 默认皮肤 |
||||||
|
|
||||||
|
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms1.png) |
||||||
|
|
||||||
|
### 浅绿色皮肤 |
||||||
|
|
||||||
|
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms2.png) |
||||||
|
|
||||||
|
## 赞赏 |
||||||
|
|
||||||
|
请作者喝杯咖啡吧!(微信号:linxin_20) |
||||||
|
|
||||||
|
![微信扫一扫](https://lin-xin.gitee.io/images/weixin.jpg) |
||||||
|
|
||||||
|
## 特别鸣谢 |
||||||
|
|
||||||
|
- [实验楼](https://www.shiyanlou.com?source=vue-manage-system) |
||||||
|
|
||||||
|
## 前言 |
||||||
|
|
||||||
|
该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(Web Management System)开发。基于 vue.js,使用 vue-cli3 脚手架,引用 Element UI 组件库,方便开发快速简洁好看的组件。分离颜色样式,支持手动切换主题色,而且很方便使用自定义主题色。 |
||||||
|
|
||||||
|
## 功能 |
||||||
|
|
||||||
|
- [x] Element UI |
||||||
|
- [x] 登录/注销 |
||||||
|
- [x] Dashboard |
||||||
|
- [x] 表格 |
||||||
|
- [x] Tab 选项卡 |
||||||
|
- [x] 表单 |
||||||
|
- [x] 图表 :bar_chart: |
||||||
|
- [x] 富文本编辑器 |
||||||
|
- [x] markdown 编辑器 |
||||||
|
- [x] 图片拖拽/裁剪上传 |
||||||
|
- [x] 支持切换主题色 :sparkles: |
||||||
|
- [x] 列表拖拽排序 |
||||||
|
- [x] 权限测试 |
||||||
|
- [x] 404 / 403 |
||||||
|
- [x] 三级菜单 |
||||||
|
- [x] 自定义图标 |
||||||
|
- [x] 可拖拽弹窗 |
||||||
|
- [x] 国际化 |
||||||
|
|
||||||
|
## 安装步骤 |
||||||
|
|
||||||
|
``` |
||||||
|
git clone https://github.com/lin-xin/vue-manage-system.git // 把模板下载到本地 |
||||||
|
cd vue-manage-system // 进入模板目录 |
||||||
|
npm install // 安装项目依赖,等待安装完成之后,安装失败可用 cnpm 或 yarn |
||||||
|
|
||||||
|
// 开启服务器,浏览器访问 http://localhost:8080 |
||||||
|
npm run serve |
||||||
|
|
||||||
|
// 执行构建命令,生成的dist文件夹放在服务器下即可访问 |
||||||
|
npm run build |
||||||
|
``` |
||||||
|
|
||||||
|
## 组件使用说明与演示 |
||||||
|
|
||||||
|
### vue-schart |
||||||
|
|
||||||
|
vue.js 封装 sChart.js 的图表组件。访问地址:[vue-schart](https://github.com/linxin/vue-schart) |
||||||
|
|
||||||
|
<p><a href="https://www.npmjs.com/package/vue-schart"><img src="https://img.shields.io/npm/dm/vue-schart.svg" alt="Downloads"></a></p> |
||||||
|
|
||||||
|
```html |
||||||
|
<template> |
||||||
|
<div> |
||||||
|
<schart class="wrapper" canvasId="myCanvas" :options="options"></schart> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Schart from 'vue-schart'; // 导入Schart组件 |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
options: { |
||||||
|
type: 'bar', |
||||||
|
title: { |
||||||
|
text: '最近一周各品类销售图' |
||||||
|
}, |
||||||
|
labels: ['周一', '周二', '周三', '周四', '周五'], |
||||||
|
datasets: [ |
||||||
|
{ |
||||||
|
label: '家电', |
||||||
|
data: [234, 278, 270, 190, 230] |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '百货', |
||||||
|
data: [164, 178, 190, 135, 160] |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '食品', |
||||||
|
data: [144, 198, 150, 235, 120] |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
Schart |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style> |
||||||
|
.wrapper { |
||||||
|
width: 7rem; |
||||||
|
height: 5rem; |
||||||
|
} |
||||||
|
</style> |
||||||
|
``` |
||||||
|
|
||||||
|
## 其他注意事项 |
||||||
|
|
||||||
|
### 一、如果我不想用到上面的某些组件呢,那我怎么在模板中删除掉不影响到其他功能呢? |
||||||
|
|
||||||
|
举个栗子,我不想用 Vue-Quill-Editor 这个组件,那我需要分四步走。 |
||||||
|
|
||||||
|
第一步:删除该组件的路由,在目录 src/router/index.js 中,找到引入改组件的路由,删除下面这段代码。 |
||||||
|
|
||||||
|
```JavaScript |
||||||
|
{ |
||||||
|
// 富文本编辑器组件 |
||||||
|
path: '/editor', |
||||||
|
component: resolve => require(['../components/page/VueEditor.vue'], resolve) |
||||||
|
}, |
||||||
|
``` |
||||||
|
|
||||||
|
第二步:删除引入该组件的文件。在目录 src/components/page/ 删除 VueEditor.vue 文件。 |
||||||
|
|
||||||
|
第三步:删除该页面的入口。在目录 src/components/common/Sidebar.vue 中,找到该入口,删除下面这段代码。 |
||||||
|
|
||||||
|
```js |
||||||
|
{ |
||||||
|
index: 'editor', |
||||||
|
title: '富文本编辑器' |
||||||
|
}, |
||||||
|
``` |
||||||
|
|
||||||
|
第四步:卸载该组件。执行以下命令: |
||||||
|
npm un vue-quill-editor -S |
||||||
|
|
||||||
|
完成。 |
||||||
|
|
||||||
|
### 二、如何切换主题色呢? |
||||||
|
|
||||||
|
第一步:打开 src/main.js 文件,找到引入 element 样式的地方,换成浅绿色主题。 |
||||||
|
|
||||||
|
```javascript |
||||||
|
import 'element-ui/lib/theme-default/index.css'; // 默认主题 |
||||||
|
// import './assets/css/theme-green/index.css'; // 浅绿色主题 |
||||||
|
``` |
||||||
|
|
||||||
|
第二步:打开 src/App.vue 文件,找到 style 标签引入样式的地方,切换成浅绿色主题。 |
||||||
|
|
||||||
|
```javascript |
||||||
|
@import "./assets/css/main.css"; |
||||||
|
@import "./assets/css/color-dark.css"; /*深色主题*/ |
||||||
|
/*@import "./assets/css/theme-green/color-green.css"; !*浅绿色主题*!*/ |
||||||
|
``` |
||||||
|
|
||||||
|
第三步:打开 src/components/common/Sidebar.vue 文件,找到 el-menu 标签,把 background-color/text-color/active-text-color 属性去掉即可。 |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE) |
@ -0,0 +1,196 @@ |
|||||||
|
# vue-manage-system |
||||||
|
|
||||||
|
<a href="https://github.com/vuejs/vue"> |
||||||
|
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue"> |
||||||
|
</a> |
||||||
|
<a href="https://github.com/ElemeFE/element"> |
||||||
|
<img src="https://img.shields.io/badge/element--ui-2.8.2-brightgreen.svg" alt="element-ui"> |
||||||
|
</a> |
||||||
|
<a href="https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE"> |
||||||
|
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license"> |
||||||
|
</a> |
||||||
|
<a href="https://github.com/lin-xin/vue-manage-system/releases"> |
||||||
|
<img src="https://img.shields.io/github/release/lin-xin/vue-manage-system.svg" alt="GitHub release"> |
||||||
|
</a> |
||||||
|
<a href="https://lin-xin.gitee.io/example/work/#/donate"> |
||||||
|
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate"> |
||||||
|
</a> |
||||||
|
|
||||||
|
The web management system solution based on Vue2 and Element-UI。[live demo](https://lin-xin.gitee.io/example/work/) |
||||||
|
|
||||||
|
## Donation |
||||||
|
|
||||||
|
![WeChat](https://lin-xin.gitee.io/images/weixin.jpg) |
||||||
|
|
||||||
|
## Preface |
||||||
|
|
||||||
|
The scheme as a set of multi-function background frame templates, suitable for most of the WEB management system development. Convenient development fast simple good components based on Vue2 and Element-UI. Color separation of color style, support manual switch themes, and it is convenient to use a custom theme color. |
||||||
|
|
||||||
|
## Function |
||||||
|
|
||||||
|
- [x] Element-UI |
||||||
|
- [x] Login/Logout |
||||||
|
- [x] Dashboard |
||||||
|
- [x] Table |
||||||
|
- [x] Tabs |
||||||
|
- [x] From |
||||||
|
- [x] Chart :bar_chart: |
||||||
|
- [x] Editor |
||||||
|
- [x] Markdown |
||||||
|
- [x] Upload pictures by clipping or dragging |
||||||
|
- [x] Support manual switch themes :sparkles: |
||||||
|
- [x] List drag sort |
||||||
|
- [x] Permission |
||||||
|
- [x] 404 / 403 |
||||||
|
- [x] Three level menu |
||||||
|
- [x] Custom icon |
||||||
|
|
||||||
|
## Installation steps |
||||||
|
|
||||||
|
git clone https://github.com/lin-xin/vue-manage-system.git // Clone templates |
||||||
|
cd vue-manage-system // Enter template directory |
||||||
|
npm install // Installation dependency |
||||||
|
|
||||||
|
## Local development |
||||||
|
|
||||||
|
// Open server and access http://localhost:8080 in browser |
||||||
|
npm run serve |
||||||
|
|
||||||
|
## Constructing production |
||||||
|
|
||||||
|
// Constructing project |
||||||
|
npm run build |
||||||
|
|
||||||
|
## Component description and presentation |
||||||
|
|
||||||
|
### vue-schart |
||||||
|
|
||||||
|
Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/linxin/vue-schart) |
||||||
|
|
||||||
|
```html |
||||||
|
<template> |
||||||
|
<div> |
||||||
|
<schart class="wrapper" canvasId="myCanvas" :options="options"></schart> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Schart from 'vue-schart'; // 导入Schart组件 |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
options: { |
||||||
|
type: 'bar', |
||||||
|
title: { |
||||||
|
text: '最近一周各品类销售图' |
||||||
|
}, |
||||||
|
labels: ['周一', '周二', '周三', '周四', '周五'], |
||||||
|
datasets: [ |
||||||
|
{ |
||||||
|
label: '家电', |
||||||
|
data: [234, 278, 270, 190, 230] |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '百货', |
||||||
|
data: [164, 178, 190, 135, 160] |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '食品', |
||||||
|
data: [144, 198, 150, 235, 120] |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
Schart |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style> |
||||||
|
.wrapper { |
||||||
|
width: 7rem; |
||||||
|
height: 5rem; |
||||||
|
} |
||||||
|
</style> |
||||||
|
``` |
||||||
|
|
||||||
|
### element-ui |
||||||
|
|
||||||
|
A desktop component library based on vue.js2.0 . Github : [element](http://element.eleme.io/#/zh-CN/component/layout) |
||||||
|
|
||||||
|
### Vue-Quill-Editor |
||||||
|
|
||||||
|
Quill editor component for Vue2. Github : [vue-quill-editor](https://github.com/surmon-china/vue-quill-editor) |
||||||
|
|
||||||
|
### mavonEditor |
||||||
|
|
||||||
|
A markdown editor based on Vue that supports a variety of personalized features. Github: [mavonEditor](https://github.com/hinesboy/mavonEditor) |
||||||
|
|
||||||
|
### vue-cropperjs |
||||||
|
|
||||||
|
A Vue wrapper component for cropperjs. Github: [vue-cropperjs](https://github.com/Agontuk/vue-cropperjs) |
||||||
|
|
||||||
|
## Notice |
||||||
|
|
||||||
|
### 一、If I don't want to use some components, how can I delete it? |
||||||
|
|
||||||
|
For example, I don't want to use the Vue-Quill-Editor component, I need to take four steps. |
||||||
|
|
||||||
|
The first step to remove the component of the routing. Enter 'src/router/index.js' and delete the code below. |
||||||
|
|
||||||
|
```JavaScript |
||||||
|
{ |
||||||
|
path: '/editor', |
||||||
|
component: resolve => require(['../components/page/VueEditor.vue'], resolve) |
||||||
|
}, |
||||||
|
``` |
||||||
|
|
||||||
|
Second,delete the component files. Enter 'src/components/page/' and delete 'VueEditor.vue' file. |
||||||
|
|
||||||
|
The third step is to delete the entry. Enter 'src/components/common/Sidebar.vue' and delete the code below. |
||||||
|
|
||||||
|
```js |
||||||
|
{ |
||||||
|
index: 'editor', |
||||||
|
title: '富文本编辑器' |
||||||
|
}, |
||||||
|
``` |
||||||
|
|
||||||
|
Finally, uninstall this component. |
||||||
|
npm un vue-quill-editor -S |
||||||
|
|
||||||
|
Complete! |
||||||
|
|
||||||
|
### 二、How to switch themes? |
||||||
|
|
||||||
|
The first step to enter 'src/main.js' and change into green theme. |
||||||
|
|
||||||
|
```javascript |
||||||
|
import 'element-ui/lib/theme-default/index.css'; // default theme |
||||||
|
// import '../static/css/theme-green/index.css'; // green theme |
||||||
|
``` |
||||||
|
|
||||||
|
The second step to enter 'src/App.vue' and change into green theme. |
||||||
|
|
||||||
|
```javascript |
||||||
|
@import "../static/css/main.css"; |
||||||
|
@import "../static/css/color-dark.css"; /*深色主题*/ |
||||||
|
/*@import "../static/css/theme-green/color-green.css"; !*浅绿色主题*!*/ |
||||||
|
``` |
||||||
|
|
||||||
|
Finally,enter 'src/components/common/Sidebar.vue' and find el-menu Tags,delete 'background-color/text-color/active-text-color'。 |
||||||
|
|
||||||
|
## Screenshot |
||||||
|
|
||||||
|
### Default theme |
||||||
|
|
||||||
|
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms1.png) |
||||||
|
|
||||||
|
### Green theme |
||||||
|
|
||||||
|
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms2.png) |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE) |
@ -0,0 +1,5 @@ |
|||||||
|
module.exports = { |
||||||
|
presets: [ |
||||||
|
'@vue/app' |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
{ |
||||||
|
"name": "vue-manage-system", |
||||||
|
"version": "4.2.0", |
||||||
|
"private": true, |
||||||
|
"scripts": { |
||||||
|
"dev": "npm run serve", |
||||||
|
"serve": "vue-cli-service serve", |
||||||
|
"build": "vue-cli-service build" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"axios": "^0.18.0", |
||||||
|
"babel-polyfill": "^6.26.0", |
||||||
|
"element-theme": "^2.0.1", |
||||||
|
"element-ui": "^2.13.0", |
||||||
|
"lodash": "^4.17.20", |
||||||
|
"mavon-editor": "^2.6.17", |
||||||
|
"postcss-px2rem": "^0.3.0", |
||||||
|
"px2rem-loader": "^0.1.9", |
||||||
|
"vue": "^2.6.10", |
||||||
|
"vue-cropperjs": "^3.0.0", |
||||||
|
"vue-i18n": "^8.10.0", |
||||||
|
"vue-pdf": "^4.2.0", |
||||||
|
"vue-quill-editor": "^3.0.6", |
||||||
|
"vue-router": "^3.0.3", |
||||||
|
"vue-schart": "^2.0.0", |
||||||
|
"vuedraggable": "^2.24.2", |
||||||
|
"vuex": "^3.1.2" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@vue/cli-plugin-babel": "^3.9.0", |
||||||
|
"@vue/cli-service": "^3.9.0", |
||||||
|
"element-theme-chalk": "^2.13.0", |
||||||
|
"node-sass": "^4.14.1", |
||||||
|
"sass-loader": "^8.0.0", |
||||||
|
"vue-template-compiler": "^2.6.10" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
module.exports = { |
||||||
|
plugins: { |
||||||
|
autoprefixer: {} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"> |
||||||
|
<link rel="stylesheet" href="//at.alicdn.com/t/font_830376_qzecyukz0s.css"> |
||||||
|
<title>电子竞技在线教学资源管理平台-企业端</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<noscript> |
||||||
|
<strong>We're sorry but vms doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> |
||||||
|
</noscript> |
||||||
|
<div id="app"></div> |
||||||
|
<!-- built files will be auto injected --> |
||||||
|
</body> |
||||||
|
</html> |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 112 KiB |
@ -0,0 +1,23 @@ |
|||||||
|
<template> |
||||||
|
<div id="app"> |
||||||
|
<router-view></router-view> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Setting from '@/setting'; |
||||||
|
export default { |
||||||
|
name: 'App', |
||||||
|
created () { |
||||||
|
//在页面加载时读取sessionStorage里的状态信息 |
||||||
|
if (sessionStorage.getItem(Setting.storeKey) ) { |
||||||
|
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem(Setting.storeKey)))) |
||||||
|
} |
||||||
|
|
||||||
|
//在页面刷新时将vuex里的信息保存到sessionStorage里 |
||||||
|
window.addEventListener("beforeunload",()=>{ |
||||||
|
sessionStorage.getItem(Setting.usernameKey) && sessionStorage.setItem(Setting.storeKey,JSON.stringify(this.$store.state)) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
After Width: | Height: | Size: 672 B |
After Width: | Height: | Size: 239 B |
After Width: | Height: | Size: 318 B |
After Width: | Height: | Size: 199 B |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 683 B |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 449 B |
After Width: | Height: | Size: 213 KiB |
After Width: | Height: | Size: 196 KiB |
After Width: | Height: | Size: 206 KiB |
After Width: | Height: | Size: 217 KiB |
After Width: | Height: | Size: 196 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 209 B |
After Width: | Height: | Size: 875 B |
@ -0,0 +1,30 @@ |
|||||||
|
<template> |
||||||
|
<div class="breadcrumb"> |
||||||
|
<span class="cur">当前位置:</span> |
||||||
|
<el-breadcrumb separator="/"> |
||||||
|
<el-breadcrumb-item :to="{ path: '/' }">超竞教育端</el-breadcrumb-item> |
||||||
|
<el-breadcrumb-item v-for="(item,index) in pages" :key="index" :to="{ path: index == pages.length - 1 ? curRoute : route }">{{item}}</el-breadcrumb-item> |
||||||
|
</el-breadcrumb> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
props: ['data','route'], |
||||||
|
data() { |
||||||
|
return { |
||||||
|
pages: this.data.split('/'), |
||||||
|
curRoute: this.$route.path |
||||||
|
}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
update(data){ |
||||||
|
console.log(2222,data) |
||||||
|
this.pages = data.split('/') |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,124 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<el-dialog |
||||||
|
custom-class="pdf-dia" |
||||||
|
:close-on-click-modal="false" |
||||||
|
:visible.sync="visible" |
||||||
|
@close="closePdf" |
||||||
|
:fullscreen="true" |
||||||
|
:modal="false" |
||||||
|
:append-to-body="true"> |
||||||
|
<div> |
||||||
|
<button type="button" aria-label="Close" class="el-dialog__headerbtn" @click="closePdf"><i class="el-dialog__close el-icon el-icon-close"></i></button> |
||||||
|
<div class="pdf"> |
||||||
|
<p class="arrow"> |
||||||
|
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{grey: currentPage==1}"></span> |
||||||
|
{{currentPage}} / {{pageCount}} |
||||||
|
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span> |
||||||
|
</p> |
||||||
|
<pdf |
||||||
|
class="pdf-wrap" |
||||||
|
:src="src" |
||||||
|
:page="currentPage" |
||||||
|
@num-pages="pageCount=$event" |
||||||
|
@page-loaded="currentPage=$event" |
||||||
|
@loaded="loadPdfHandler" |
||||||
|
> |
||||||
|
</pdf> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import pdf from "vue-pdf"; |
||||||
|
export default { |
||||||
|
props: ['visible','src'], |
||||||
|
data() { |
||||||
|
return { |
||||||
|
pdfVisible: false, |
||||||
|
pdfSrc: '', |
||||||
|
currentPage: 0, |
||||||
|
pageCount: 0, |
||||||
|
fileType: 'pdf', |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { pdf }, |
||||||
|
mounted(){ |
||||||
|
this.addEvent() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
closePdf(){ |
||||||
|
this.$emit('update:visible',false) |
||||||
|
this.$emit('update:src','') |
||||||
|
this.currentPage = 1 |
||||||
|
}, |
||||||
|
changePdfPage (val) { |
||||||
|
if (val === 0 && this.currentPage > 1) { |
||||||
|
this.currentPage-- |
||||||
|
} |
||||||
|
if (val === 1 && this.currentPage < this.pageCount) { |
||||||
|
this.currentPage++ |
||||||
|
} |
||||||
|
}, |
||||||
|
loadPdfHandler (e) { |
||||||
|
this.currentPage = 1 |
||||||
|
}, |
||||||
|
addEvent(){ |
||||||
|
document.onkeydown = e => { |
||||||
|
let key = window.event.keyCode |
||||||
|
if(key == 37){ |
||||||
|
this.changePdfPage(0) |
||||||
|
}else if(key == 39){ |
||||||
|
this.changePdfPage(1) |
||||||
|
} |
||||||
|
} |
||||||
|
this.$once('hook:beforeDestroy',() => { |
||||||
|
document.onkeydown = null |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
/deep/.pdf-dia{ |
||||||
|
border-radius: 0 !important; |
||||||
|
.el-dialog__header{ |
||||||
|
display: none; |
||||||
|
} |
||||||
|
.el-dialog__body{ |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
.el-dialog__headerbtn{ |
||||||
|
top: 10px; |
||||||
|
.el-dialog__close{ |
||||||
|
color: #fff; |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.pdf{ |
||||||
|
.arrow{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
width: 100%; |
||||||
|
padding: 10px 0; |
||||||
|
font-size: 16px; |
||||||
|
color: #fff; |
||||||
|
background-color: #333; |
||||||
|
.turn{ |
||||||
|
margin: 0 10px; |
||||||
|
font-size: 18px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
.pdf-wrap{ |
||||||
|
height: calc(100vh - 45px); |
||||||
|
margin: 0 auto; |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,179 @@ |
|||||||
|
<template> |
||||||
|
<div class="quill" :class="classes"> |
||||||
|
<div ref="editor" :style="styles" v-loading="loading"></div> |
||||||
|
|
||||||
|
<el-upload :action="this.api.fileupload" :before-upload="beforeUpload" :on-success="editorUploadSuccess" style="display: none"> |
||||||
|
<el-button class="editorUpload" size="small" type="primary">点击上传</el-button> |
||||||
|
</el-upload> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Quill from 'quill'; |
||||||
|
import 'quill/dist/quill.core.css'; |
||||||
|
import 'quill/dist/quill.snow.css'; |
||||||
|
import 'quill/dist/quill.bubble.css'; |
||||||
|
import toolbarOptions from './options' |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'quill', |
||||||
|
props: { |
||||||
|
value: { |
||||||
|
type: String, |
||||||
|
default: '' |
||||||
|
}, |
||||||
|
uploading: { |
||||||
|
type: Boolean, |
||||||
|
default: false |
||||||
|
}, |
||||||
|
readonly: { |
||||||
|
type: Boolean, |
||||||
|
default: false |
||||||
|
}, |
||||||
|
border: { |
||||||
|
type: Boolean, |
||||||
|
default: false |
||||||
|
}, |
||||||
|
height: { |
||||||
|
type: Number |
||||||
|
}, |
||||||
|
minHeight: { |
||||||
|
type: Number |
||||||
|
} |
||||||
|
}, |
||||||
|
data () { |
||||||
|
return { |
||||||
|
Quill: null, |
||||||
|
currentValue: '', |
||||||
|
options: { |
||||||
|
theme: 'snow', |
||||||
|
bounds: document.body, |
||||||
|
debug: 'warn', |
||||||
|
modules: { |
||||||
|
toolbar: { |
||||||
|
container: toolbarOptions, |
||||||
|
handlers: { |
||||||
|
'image': function (value) { |
||||||
|
if (value) { |
||||||
|
// 调用iview图片上传 |
||||||
|
document.querySelector('.editorUpload').click() |
||||||
|
} else { |
||||||
|
this.Quill.format('image', false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
placeholder: '', |
||||||
|
readOnly: this.readonly, |
||||||
|
}, |
||||||
|
loading: false |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
classes () { |
||||||
|
return [ |
||||||
|
{ |
||||||
|
'quill-no-border': !this.border |
||||||
|
} |
||||||
|
]; |
||||||
|
}, |
||||||
|
styles () { |
||||||
|
let style = {}; |
||||||
|
if (this.minHeight) { |
||||||
|
style.minHeight = `${this.minHeight}px`; |
||||||
|
} |
||||||
|
if (this.height) { |
||||||
|
style.height = `${this.height}px`; |
||||||
|
} |
||||||
|
return style; |
||||||
|
} |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
value: { |
||||||
|
handler (val) { |
||||||
|
if (val !== this.currentValue) { |
||||||
|
this.currentValue = val; |
||||||
|
if (this.Quill) { |
||||||
|
this.Quill.pasteHTML(this.value); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
immediate: true |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted () { |
||||||
|
this.init(); |
||||||
|
}, |
||||||
|
beforeDestroy () { |
||||||
|
// 在组件销毁后销毁实例 |
||||||
|
this.Quill = null; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
init () { |
||||||
|
const editor = this.$refs.editor; |
||||||
|
// 初始化编辑器 |
||||||
|
this.Quill = new Quill(editor, this.options); |
||||||
|
// 默认值 |
||||||
|
this.Quill.pasteHTML(this.currentValue); |
||||||
|
this.$nextTick(() => { |
||||||
|
document.querySelector('.content').scrollTo(0,0) |
||||||
|
}) |
||||||
|
// 绑定事件 |
||||||
|
this.Quill.on('text-change', (delta, oldDelta, source) => { |
||||||
|
const html = this.$refs.editor.children[0].innerHTML; |
||||||
|
const text = this.Quill.getText(); |
||||||
|
const quill = this.Quill; |
||||||
|
// 更新内部的值 |
||||||
|
this.currentValue = html; |
||||||
|
// 发出事件 v-model |
||||||
|
this.$emit('input', html); |
||||||
|
// 发出事件 |
||||||
|
this.$emit('on-change', { html, text, quill }); |
||||||
|
}); |
||||||
|
// 将一些 quill 自带的事件传递出去 |
||||||
|
this.Quill.on('text-change', (delta, oldDelta, source) => { |
||||||
|
this.$emit('on-text-change', delta, oldDelta, source); |
||||||
|
}); |
||||||
|
this.Quill.on('selection-change', (range, oldRange, source) => { |
||||||
|
this.$emit('on-selection-change', range, oldRange, source); |
||||||
|
}); |
||||||
|
this.Quill.on('editor-change', (eventName, ...args) => { |
||||||
|
this.$emit('on-editor-change', eventName, ...args); |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeUpload(file){ |
||||||
|
this.loading = true |
||||||
|
this.$emit('update:uploading',true) |
||||||
|
}, |
||||||
|
editorUploadSuccess (res) { |
||||||
|
// 获取富文本组件实例 |
||||||
|
let quill = this.Quill |
||||||
|
// 如果上传成功 |
||||||
|
if (res.data.filesResult.fileUrl) { |
||||||
|
// 获取光标所在位置 |
||||||
|
let length = quill.getSelection().index; |
||||||
|
// 插入图片,res为服务器返回的图片链接地址 |
||||||
|
quill.insertEmbed(length, 'image', res.data.filesResult.fileUrl) |
||||||
|
// 调整光标到最后 |
||||||
|
quill.setSelection(length + 1) |
||||||
|
} else { |
||||||
|
this.successMsg('图片插入失败') |
||||||
|
} |
||||||
|
this.loading = false |
||||||
|
this.$emit('update:uploading',false) |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
.quill-no-border{ |
||||||
|
.ql-toolbar.ql-snow{ |
||||||
|
border: none; |
||||||
|
border-bottom: 1px solid #e8eaec; |
||||||
|
} |
||||||
|
.ql-container.ql-snow{ |
||||||
|
border: none; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,16 @@ |
|||||||
|
export default [ |
||||||
|
['bold', 'italic', 'underline', 'strike'], |
||||||
|
['blockquote', 'code-block'], |
||||||
|
[{ 'header': 1 }, { 'header': 2 }], |
||||||
|
[{ 'list': 'ordered' }, { 'list': 'bullet' }], |
||||||
|
[{ 'script': 'sub' }, { 'script': 'super' }], |
||||||
|
[{ 'indent': '-1' }, { 'indent': '+1' }], |
||||||
|
[{ 'direction': 'rtl' }], |
||||||
|
[{ 'size': ['small', false, 'large', 'huge'] }], |
||||||
|
[{ 'header': [1, 2, 3, 4, 5, 6, false] }], |
||||||
|
[{ 'color': [] }, { 'background': [] }], |
||||||
|
[{ 'font': [] }], |
||||||
|
[{ 'align': [] }], |
||||||
|
['clean'], |
||||||
|
['link', 'image', 'video'] |
||||||
|
] |
@ -0,0 +1,30 @@ |
|||||||
|
export const messages = { |
||||||
|
'zh': { |
||||||
|
i18n: { |
||||||
|
breadcrumb: '国际化产品', |
||||||
|
tips: '通过切换语言按钮,来改变当前内容的语言。', |
||||||
|
btn: '切换英文', |
||||||
|
title1: '常用用法', |
||||||
|
p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。', |
||||||
|
p2: '没有什么比信念更能支撑我们度过艰难的时光了。', |
||||||
|
p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。', |
||||||
|
title2: '组件插值', |
||||||
|
info: 'Element组件需要国际化,请参考 {action}。', |
||||||
|
value: '文档' |
||||||
|
} |
||||||
|
}, |
||||||
|
'en': { |
||||||
|
i18n: { |
||||||
|
breadcrumb: 'International Products', |
||||||
|
tips: 'Click on the button to change the current language. ', |
||||||
|
btn: 'Switch Chinese', |
||||||
|
title1: 'Common usage', |
||||||
|
p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.", |
||||||
|
p2: "Nothing can help us endure dark times better than our faith. ", |
||||||
|
p3: "If you can do what you do best and be happy, you're further along in life than most people.", |
||||||
|
title2: 'Component interpolation', |
||||||
|
info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.', |
||||||
|
value: 'documentation' |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="copyright">广州超竞教育投资有限公司版权所有</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
|
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted(){ |
||||||
|
|
||||||
|
}, |
||||||
|
methods: { |
||||||
|
|
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
.copyright{ |
||||||
|
padding: 20px 0; |
||||||
|
color: rgba(0, 0, 0, 0.45); |
||||||
|
font-size: 12px; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,103 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="header"> |
||||||
|
<img class="system-name" src="../../assets/img/system-fullname.png"> |
||||||
|
<el-dropdown class="user-wrap" @command="userCommand"> |
||||||
|
<div class="user"> |
||||||
|
<el-avatar :size="40" :src="avatar"></el-avatar> |
||||||
|
<span class="username">{{username}}</span> |
||||||
|
</div> |
||||||
|
<el-dropdown-menu slot="dropdown"> |
||||||
|
<el-dropdown-item command="help">用户手册</el-dropdown-item> |
||||||
|
<el-dropdown-item command="person">个人资料</el-dropdown-item> |
||||||
|
<el-dropdown-item command="logout">退出登录</el-dropdown-item> |
||||||
|
</el-dropdown-menu> |
||||||
|
</el-dropdown> |
||||||
|
</div> |
||||||
|
<pdf :visible.sync="pdfVisible" :src.sync="pdfSrc"></pdf> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import bus from '@/libs/bus'; |
||||||
|
import Setting from '@/setting'; |
||||||
|
import pdf from '@/components/pdf' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
pdfVisible: false, |
||||||
|
pdfSrc: '', |
||||||
|
avatar: this.$store.state.avatar ? this.$store.state.avatar : 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png', |
||||||
|
showBackList: Setting.layout.hideNavList |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { pdf }, |
||||||
|
computed: { |
||||||
|
username() { |
||||||
|
let username = sessionStorage.getItem(Setting.usernameKey); |
||||||
|
return username ? username : this.name; |
||||||
|
}, |
||||||
|
showBack(){ |
||||||
|
let route = this.$route.name |
||||||
|
if(this.showBackList.includes(route)) return true |
||||||
|
return false |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted(){ |
||||||
|
bus.$on('updateAvatar',avatar => { |
||||||
|
this.avatar = avatar |
||||||
|
}) |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
loginout() { |
||||||
|
sessionStorage.removeItem(Setting.usernameKey); |
||||||
|
sessionStorage.removeItem(Setting.storeKey); |
||||||
|
location.reload() |
||||||
|
}, |
||||||
|
back(){ |
||||||
|
this.$route.name != 'addarticle' ? this.$router.push('match') : this.$router.back() |
||||||
|
}, |
||||||
|
userCommand(command){ |
||||||
|
console.log(command) |
||||||
|
if(command == 'help'){ |
||||||
|
this.pdfVisible = true |
||||||
|
this.pdfSrc = 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20201125/pdf/1331502965949227008.pdf' |
||||||
|
}else if(command == 'person'){ |
||||||
|
this.$router.push('personalCenter') |
||||||
|
}else{ |
||||||
|
this.loginout() |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
.header { |
||||||
|
position: relative; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
padding: 20px 40px 20px 24px; |
||||||
|
font-size: 16px; |
||||||
|
color: #333; |
||||||
|
background-color: #fff; |
||||||
|
box-sizing: border-box; |
||||||
|
.system-name { |
||||||
|
width: 326px; |
||||||
|
} |
||||||
|
.user-wrap { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
|
||||||
|
.user{ |
||||||
|
display: inline-flex; |
||||||
|
align-items: center; |
||||||
|
cursor: pointer; |
||||||
|
.username{ |
||||||
|
margin-left: 10px; |
||||||
|
color: #000; |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,92 @@ |
|||||||
|
<template> |
||||||
|
<div class="main"> |
||||||
|
<v-navbar class="nav"></v-navbar> |
||||||
|
<div class="layout"> |
||||||
|
<v-head></v-head> |
||||||
|
<div class="content"> |
||||||
|
<transition name="move" mode="out-in"> |
||||||
|
<keep-alive :include="tagsList"> |
||||||
|
<router-view class="view"></router-view> |
||||||
|
</keep-alive> |
||||||
|
</transition> |
||||||
|
<el-backtop target=".content"></el-backtop> |
||||||
|
<v-footer ref="footer"></v-footer> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import vHead from '../header/index.vue'; |
||||||
|
import vNavbar from '../navbar/index.vue'; |
||||||
|
import vSidebar from '../sidebar/index.vue'; |
||||||
|
import vFooter from '../footer' |
||||||
|
import bus from '@/libs/bus'; |
||||||
|
import Setting from '@/setting'; |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
tagsList: [], |
||||||
|
collapse: false, |
||||||
|
showSidebar: false, |
||||||
|
hideNavList: Setting.layout.hideNavList |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
vHead, |
||||||
|
vNavbar, |
||||||
|
vSidebar, |
||||||
|
vFooter |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
hideSidebar() { |
||||||
|
let route = this.$route.name |
||||||
|
if(this.hideNavList.includes(route)) return false |
||||||
|
return true |
||||||
|
} |
||||||
|
}, |
||||||
|
created() { |
||||||
|
bus.$on('collapse-content', msg => { |
||||||
|
this.collapse = msg; |
||||||
|
}); |
||||||
|
this.showSidebar = this.$store.state.sidebarMenu |
||||||
|
bus.$on('showMenu', status => { |
||||||
|
this.showSidebar = false |
||||||
|
this.$nextTick(() => { |
||||||
|
this.showSidebar = status |
||||||
|
}) |
||||||
|
}); |
||||||
|
|
||||||
|
// 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。 |
||||||
|
bus.$on('tags', msg => { |
||||||
|
let arr = []; |
||||||
|
for (let i = 0, len = msg.length; i < len; i++) { |
||||||
|
msg[i].name && arr.push(msg[i].name); |
||||||
|
} |
||||||
|
this.tagsList = arr; |
||||||
|
}); |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
.main{ |
||||||
|
display: flex; |
||||||
|
min-width: 1300px; |
||||||
|
height: 100%; |
||||||
|
overflow: hidden; |
||||||
|
.nav{ |
||||||
|
width: 220px; |
||||||
|
} |
||||||
|
.layout{ |
||||||
|
width: calc(100% - 220px); |
||||||
|
.content{ |
||||||
|
height: calc(100vh - 80px); |
||||||
|
padding: 24px 24px 0; |
||||||
|
overflow: auto; |
||||||
|
.view{ |
||||||
|
min-height: calc(100% - 60px); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,269 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="logo"> |
||||||
|
<img src="../../assets/img/logo-full.png" width="125"> |
||||||
|
</div> |
||||||
|
<el-menu |
||||||
|
class="sidebar-el-menu" |
||||||
|
:default-active="onRoutes" |
||||||
|
:collapse="collapse" |
||||||
|
background-color="#141414" |
||||||
|
text-color="#fff" |
||||||
|
active-text-color="#fff" |
||||||
|
unique-opened |
||||||
|
@select="menuSelect" |
||||||
|
> |
||||||
|
<!-- 第一层 --> |
||||||
|
<template v-for="item in menus"> |
||||||
|
<!-- 如果第一层有子菜单,则继续循环 --> |
||||||
|
<template v-if="item.subs"> |
||||||
|
<el-submenu :index="item.index" :key="item.index"> |
||||||
|
<template slot="title"> |
||||||
|
<i :class="item.icon"></i> |
||||||
|
<span slot="title">{{ item.title }}</span> |
||||||
|
</template> |
||||||
|
<!-- 第二层 --> |
||||||
|
<template v-for="subItem in item.subs"> |
||||||
|
<!-- 如果第二层有子菜单,则继续循环 --> |
||||||
|
<template v-if="subItem.subs"> |
||||||
|
<el-submenu :index="subItem.index" :key="subItem.index"> |
||||||
|
<template slot="title"> |
||||||
|
<span slot="title">{{ subItem.title }}</span> |
||||||
|
</template> |
||||||
|
<!-- <el-menu-item v-for="(threeItem,i) in subItem.subs" :key="i" :index="threeItem.index">{{ threeItem.title }}</el-menu-item> --> |
||||||
|
<!-- 第三层 --> |
||||||
|
<template v-for="subItem2 in subItem.subs"> |
||||||
|
<!-- 如果第三层有子菜单,则继续循环 --> |
||||||
|
<template v-if="subItem2.subs"> |
||||||
|
<el-submenu :index="subItem2.index" :key="subItem2.index"> |
||||||
|
<template slot="title"> |
||||||
|
<span slot="title">{{ subItem2.title }}</span> |
||||||
|
</template> |
||||||
|
<!-- <el-menu-item v-for="(fourItem,i) in subItem2.subs" :key="i" :index="fourItem.index">{{ fourItem.title }}</el-menu-item> --> |
||||||
|
<!-- 第四层 --> |
||||||
|
<template v-for="subItem3 in subItem2.subs"> |
||||||
|
<!-- 如果第四层有子菜单,则继续循环 --> |
||||||
|
<template v-if="subItem3.subs"> |
||||||
|
<el-submenu :index="subItem3.index" :key="subItem3.index"> |
||||||
|
<template slot="title"> |
||||||
|
<!-- <i :class="item.icon"></i> --> |
||||||
|
<!-- <span slot="title">{{ subItem2.title }}</span> --> |
||||||
|
{{ subItem3.title }} |
||||||
|
</template> |
||||||
|
<el-menu-item v-for="(fiveItem,i) in subItem3.subs" :key="i" :index="fiveItem.index">{{ fiveItem.title }}</el-menu-item> |
||||||
|
</el-submenu> |
||||||
|
</template> |
||||||
|
<!-- 如果第四层没有子菜单 --> |
||||||
|
<el-menu-item v-else :index="subItem3.index" :key="subItem3.index">{{ subItem3.title }}</el-menu-item> |
||||||
|
</template> |
||||||
|
</el-submenu> |
||||||
|
</template> |
||||||
|
<!-- 如果第三层没有子菜单 --> |
||||||
|
<el-menu-item v-else :index="subItem2.index" :key="subItem2.index">{{ subItem2.title }}</el-menu-item> |
||||||
|
</template> |
||||||
|
</el-submenu> |
||||||
|
</template> |
||||||
|
<!-- 如果第二层没有子菜单 --> |
||||||
|
<el-menu-item v-else :index="subItem.index" :key="subItem.index">{{ subItem.title }}</el-menu-item> |
||||||
|
</template> |
||||||
|
</el-submenu> |
||||||
|
</template> |
||||||
|
<!-- 如果第一层没有子菜单 --> |
||||||
|
<template v-else> |
||||||
|
<el-menu-item :index="item.index" :key="item.index"> |
||||||
|
<i :class="item.icon"></i> |
||||||
|
<span slot="title">{{ item.title }}</span> |
||||||
|
</el-menu-item> |
||||||
|
</template> |
||||||
|
</template> |
||||||
|
</el-menu> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import bus from '@/libs/bus'; |
||||||
|
import Setting from '@/setting'; |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
collapse: false, |
||||||
|
defaultMenus: [ |
||||||
|
{ |
||||||
|
icon: 'el-icon-lx-home', |
||||||
|
index: 'dashboard', |
||||||
|
title: '学校信息管理' |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-user', |
||||||
|
index: 'user', |
||||||
|
title: '学校用户管理' |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-news', |
||||||
|
index: 'course', |
||||||
|
title: '课程资源管理' |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-monitor', |
||||||
|
index: 'backstage', |
||||||
|
title: '实训系统后台' |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-school', |
||||||
|
index: 'match', |
||||||
|
title: '赛事信息管理' |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-document', |
||||||
|
index: 'information', |
||||||
|
title: '官方资讯管理', |
||||||
|
subs: [] |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-takeaway-box', |
||||||
|
index: 'system', |
||||||
|
title: '平台分管设置' |
||||||
|
} |
||||||
|
], |
||||||
|
menus: [], |
||||||
|
actives: { |
||||||
|
dashboard: ['addcustomer'], |
||||||
|
information: ['content','addarticle'], |
||||||
|
match: ['addmatch'], |
||||||
|
course: ['addCourse','courseConfig','courseSection'] |
||||||
|
}, |
||||||
|
}; |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
onRoutes() { |
||||||
|
let actives = this.actives |
||||||
|
for(let i in this.actives){ |
||||||
|
if(actives[i].includes(this.$route.name)) return i |
||||||
|
} |
||||||
|
return this.$route.name |
||||||
|
} |
||||||
|
}, |
||||||
|
created() { |
||||||
|
this.initMenu() |
||||||
|
// 通过 Event Bus 进行组件间通信,来折叠侧边栏 |
||||||
|
bus.$on('collapse', msg => { |
||||||
|
this.collapse = msg; |
||||||
|
bus.$emit('collapse-content', msg); |
||||||
|
}); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
initMenu(){ |
||||||
|
if(Setting.dynamicRoute){ |
||||||
|
let routes = this.$store.state.routes[1].children |
||||||
|
let menus = [] |
||||||
|
let showContent = false |
||||||
|
this.defaultMenus.map(e => { |
||||||
|
routes.find(n => n.path == e.index) && menus.push(e) |
||||||
|
if(e.index == 'information'){ |
||||||
|
if(routes.find(n => n.path == 'information')){ |
||||||
|
menus.map(n => { |
||||||
|
if(n.index == 'information'){ |
||||||
|
n.subs.push({ |
||||||
|
index: 'information', |
||||||
|
title: '栏目管理', |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
if(routes.find(n => n.path == 'content')){ |
||||||
|
showContent = true |
||||||
|
menus.map(n => { |
||||||
|
if(n.index == 'information'){ |
||||||
|
n.subs.push({ |
||||||
|
title: '内容管理', |
||||||
|
index: 'contents', |
||||||
|
subs: [] |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
this.menus = menus |
||||||
|
this.$nextTick(() => { |
||||||
|
setTimeout(() => { |
||||||
|
showContent && this.getContent() |
||||||
|
},500) |
||||||
|
}) |
||||||
|
this.$store.commit('addIndex',{path: menus[0].index}) |
||||||
|
}else{ |
||||||
|
this.menus = this.defaultMenus |
||||||
|
} |
||||||
|
}, |
||||||
|
getContent() { |
||||||
|
let data = { |
||||||
|
page: 1, |
||||||
|
size: 10000 |
||||||
|
} |
||||||
|
this.$get(this.api.queryAllColumns,data).then(res => { |
||||||
|
let contentMenu = [] |
||||||
|
res.data.columnTree.map(n => { |
||||||
|
let temp = { |
||||||
|
index: n.id, |
||||||
|
title: n.name |
||||||
|
} |
||||||
|
if(n.secondColumn.length){ |
||||||
|
temp.subs = [] |
||||||
|
n.secondColumn.map(e => { |
||||||
|
temp.subs.push({ |
||||||
|
index: e.id, |
||||||
|
title: e.name |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
contentMenu.push(temp) |
||||||
|
}) |
||||||
|
let menus = this.menus |
||||||
|
menus.map(n => { |
||||||
|
if(n.index == 'information'){ |
||||||
|
n.subs.map(e => { |
||||||
|
if(e.index == 'contents') e.subs = contentMenu |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
this.menus = menus |
||||||
|
}).catch(res => {}) |
||||||
|
}, |
||||||
|
menuSelect(index,indexPath){ |
||||||
|
if(!isNaN(index)){ |
||||||
|
this.$router.push(`content?id=${index}`) |
||||||
|
}else{ |
||||||
|
this.$router.push(index) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.nav{ |
||||||
|
height: 100%; |
||||||
|
background-color: #141414; |
||||||
|
overflow: auto; |
||||||
|
.logo{ |
||||||
|
padding: 20px 0; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
/deep/.el-menu{ |
||||||
|
border-right: 0 !important; |
||||||
|
.el-menu-item.is-active{ |
||||||
|
background-color: #CC221C !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.sidebar::-webkit-scrollbar { |
||||||
|
width: 0; |
||||||
|
} |
||||||
|
.sidebar-el-menu:not(.el-menu--collapse) { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
.sidebar > ul { |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,141 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<el-menu |
||||||
|
:default-active="onRoutes" |
||||||
|
:collapse="collapse" |
||||||
|
unique-opened |
||||||
|
router |
||||||
|
> |
||||||
|
<template v-for="item in menuList[curMenu]"> |
||||||
|
<template v-if="item.subs"> |
||||||
|
<el-submenu :index="item.index" :key="item.index"> |
||||||
|
<template slot="title"> |
||||||
|
<i :class="item.icon"></i> |
||||||
|
<span slot="title">{{ item.title }}</span> |
||||||
|
</template> |
||||||
|
<template v-for="subItem in item.subs"> |
||||||
|
<el-submenu |
||||||
|
v-if="subItem.subs" |
||||||
|
:index="subItem.index" |
||||||
|
:key="subItem.index" |
||||||
|
> |
||||||
|
<template slot="title">{{ subItem.title }}</template> |
||||||
|
<el-menu-item |
||||||
|
v-for="(threeItem,i) in subItem.subs" |
||||||
|
:key="i" |
||||||
|
:index="threeItem.index" |
||||||
|
>{{ threeItem.title }}</el-menu-item> |
||||||
|
</el-submenu> |
||||||
|
<el-menu-item |
||||||
|
v-else |
||||||
|
:index="subItem.index" |
||||||
|
:key="subItem.index" |
||||||
|
>{{ subItem.title }}</el-menu-item> |
||||||
|
</template> |
||||||
|
</el-submenu> |
||||||
|
</template> |
||||||
|
<template v-else> |
||||||
|
<el-menu-item :index="item.index" :key="item.index"> |
||||||
|
<i :class="item.icon"></i> |
||||||
|
<span slot="title">{{ item.title }}</span> |
||||||
|
</el-menu-item> |
||||||
|
</template> |
||||||
|
</template> |
||||||
|
</el-menu> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import bus from '@/libs/bus'; |
||||||
|
import Setting from '@/setting'; |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
collapse: false, |
||||||
|
curMenu: this.$store.state.sidebarMenu, |
||||||
|
defaultInfoMenu: [ |
||||||
|
{ |
||||||
|
icon: 'el-icon-s-grid', |
||||||
|
index: 'information', |
||||||
|
title: '栏目管理' |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-c-scale-to-original', |
||||||
|
index: 'content', |
||||||
|
title: '内容管理' |
||||||
|
} |
||||||
|
], |
||||||
|
menuList: { |
||||||
|
match: [ |
||||||
|
{ |
||||||
|
icon: 'el-icon-lx-copy', |
||||||
|
index: 'matchintro', |
||||||
|
title: '大赛详情' |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-aim', |
||||||
|
index: 'matchprogress', |
||||||
|
title: '竞赛进展' |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'el-icon-user', |
||||||
|
index: 'matchsignup', |
||||||
|
title: '报名人员' |
||||||
|
}, |
||||||
|
], |
||||||
|
info: [] |
||||||
|
}, |
||||||
|
menus: [] |
||||||
|
}; |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
onRoutes() { |
||||||
|
return this.$route.name |
||||||
|
} |
||||||
|
}, |
||||||
|
created() { |
||||||
|
Setting.dynamicRoute && this.initMenu() |
||||||
|
// 通过 Event Bus 进行组件间通信,来折叠侧边栏 |
||||||
|
bus.$on('collapse', msg => { |
||||||
|
this.collapse = msg; |
||||||
|
bus.$emit('collapse-content', msg); |
||||||
|
}); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
initMenu(){ |
||||||
|
let routes = this.$store.state.routes[1].children |
||||||
|
let menus = [] |
||||||
|
this.defaultInfoMenu.map(e => { |
||||||
|
routes.map(n => { |
||||||
|
e.index == n.path && menus.push(e) |
||||||
|
}) |
||||||
|
}) |
||||||
|
this.menuList.info = menus |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.sidebar{ |
||||||
|
z-index: 2; |
||||||
|
position: fixed; |
||||||
|
top: 120px; |
||||||
|
left: 0; |
||||||
|
bottom: 20px; |
||||||
|
right: 0; |
||||||
|
width: 210px !important; |
||||||
|
&.noNav{ |
||||||
|
top: 80px; |
||||||
|
} |
||||||
|
} |
||||||
|
.sidebar::-webkit-scrollbar { |
||||||
|
width: 0; |
||||||
|
} |
||||||
|
.sidebar-el-menu:not(.el-menu--collapse) { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
.sidebar > ul { |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,185 @@ |
|||||||
|
<template> |
||||||
|
<div class="tags" v-if="showTags"> |
||||||
|
<ul> |
||||||
|
<li class="tags-li" v-for="(item,index) in tagsList" :class="{'active': isActive(item.path)}" :key="index"> |
||||||
|
<router-link :to="item.path" class="tags-li-title"> |
||||||
|
{{item.title}} |
||||||
|
</router-link> |
||||||
|
<span class="tags-li-icon" @click="closeTags(index)"><i class="el-icon-close"></i></span> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div class="tags-close-box"> |
||||||
|
<el-dropdown @command="handleTags"> |
||||||
|
<el-button size="mini" type="primary"> |
||||||
|
标签选项<i class="el-icon-arrow-down el-icon--right"></i> |
||||||
|
</el-button> |
||||||
|
<el-dropdown-menu size="small" slot="dropdown"> |
||||||
|
<el-dropdown-item command="other">关闭其他</el-dropdown-item> |
||||||
|
<el-dropdown-item command="all">关闭所有</el-dropdown-item> |
||||||
|
</el-dropdown-menu> |
||||||
|
</el-dropdown> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import bus from '@/libs/bus'; |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
tagsList: [] |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
isActive(path) { |
||||||
|
return path === this.$route.fullPath; |
||||||
|
}, |
||||||
|
// 关闭单个标签 |
||||||
|
closeTags(index) { |
||||||
|
const delItem = this.tagsList.splice(index, 1)[0]; |
||||||
|
const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1]; |
||||||
|
if (item) { |
||||||
|
delItem.path === this.$route.fullPath && this.$router.push(item.path); |
||||||
|
}else{ |
||||||
|
this.$router.push('/dashboard'); |
||||||
|
} |
||||||
|
}, |
||||||
|
// 关闭全部标签 |
||||||
|
closeAll(){ |
||||||
|
this.tagsList = []; |
||||||
|
this.$router.push('/dashboard'); |
||||||
|
}, |
||||||
|
// 关闭其他标签 |
||||||
|
closeOther(){ |
||||||
|
const curItem = this.tagsList.filter(item => { |
||||||
|
return item.path === this.$route.fullPath; |
||||||
|
}) |
||||||
|
this.tagsList = curItem; |
||||||
|
}, |
||||||
|
// 设置标签 |
||||||
|
setTags(route){ |
||||||
|
const isExist = this.tagsList.some(item => { |
||||||
|
return item.path === route.fullPath; |
||||||
|
}) |
||||||
|
if(!isExist){ |
||||||
|
if(this.tagsList.length >= 8){ |
||||||
|
this.tagsList.shift(); |
||||||
|
} |
||||||
|
this.tagsList.push({ |
||||||
|
title: route.meta.title, |
||||||
|
path: route.fullPath, |
||||||
|
name: route.matched[1].components.default.name |
||||||
|
}) |
||||||
|
} |
||||||
|
bus.$emit('tags', this.tagsList); |
||||||
|
}, |
||||||
|
handleTags(command){ |
||||||
|
command === 'other' ? this.closeOther() : this.closeAll(); |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
showTags() { |
||||||
|
return this.tagsList.length > 0; |
||||||
|
} |
||||||
|
}, |
||||||
|
watch:{ |
||||||
|
$route(newValue, oldValue){ |
||||||
|
this.setTags(newValue); |
||||||
|
} |
||||||
|
}, |
||||||
|
created(){ |
||||||
|
this.setTags(this.$route); |
||||||
|
// 监听关闭当前页面的标签页 |
||||||
|
bus.$on('close_current_tags', () => { |
||||||
|
for (let i = 0, len = this.tagsList.length; i < len; i++) { |
||||||
|
const item = this.tagsList[i]; |
||||||
|
if(item.path === this.$route.fullPath){ |
||||||
|
if(i < len - 1){ |
||||||
|
this.$router.push(this.tagsList[i+1].path); |
||||||
|
}else if(i > 0){ |
||||||
|
this.$router.push(this.tagsList[i-1].path); |
||||||
|
}else{ |
||||||
|
this.$router.push('/'); |
||||||
|
} |
||||||
|
this.tagsList.splice(i, 1); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.tags { |
||||||
|
position: relative; |
||||||
|
height: 30px; |
||||||
|
overflow: hidden; |
||||||
|
background: #fff; |
||||||
|
padding-right: 120px; |
||||||
|
box-shadow: 0 5px 10px #ddd; |
||||||
|
} |
||||||
|
|
||||||
|
.tags ul { |
||||||
|
box-sizing: border-box; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
.tags-li { |
||||||
|
float: left; |
||||||
|
margin: 3px 5px 2px 3px; |
||||||
|
border-radius: 3px; |
||||||
|
font-size: 12px; |
||||||
|
overflow: hidden; |
||||||
|
cursor: pointer; |
||||||
|
height: 23px; |
||||||
|
line-height: 23px; |
||||||
|
border: 1px solid #e9eaec; |
||||||
|
background: #fff; |
||||||
|
padding: 0 5px 0 12px; |
||||||
|
vertical-align: middle; |
||||||
|
color: #666; |
||||||
|
-webkit-transition: all .3s ease-in; |
||||||
|
-moz-transition: all .3s ease-in; |
||||||
|
transition: all .3s ease-in; |
||||||
|
} |
||||||
|
|
||||||
|
.tags-li:not(.active):hover { |
||||||
|
background: #f8f8f8; |
||||||
|
} |
||||||
|
|
||||||
|
.tags-li.active { |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
.tags-li-title { |
||||||
|
float: left; |
||||||
|
max-width: 80px; |
||||||
|
overflow: hidden; |
||||||
|
white-space: nowrap; |
||||||
|
text-overflow: ellipsis; |
||||||
|
margin-right: 5px; |
||||||
|
color: #666; |
||||||
|
} |
||||||
|
|
||||||
|
.tags-li.active .tags-li-title { |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
.tags-close-box { |
||||||
|
position: absolute; |
||||||
|
right: 0; |
||||||
|
top: 0; |
||||||
|
box-sizing: border-box; |
||||||
|
padding-top: 1px; |
||||||
|
text-align: center; |
||||||
|
width: 110px; |
||||||
|
height: 30px; |
||||||
|
background: #fff; |
||||||
|
box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1); |
||||||
|
z-index: 10; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
* @description 生成按钮级别权限组 |
||||||
|
* */ |
||||||
|
|
||||||
|
import store from '@/store'; |
||||||
|
export default function(data){ |
||||||
|
let result = [] |
||||||
|
data.map(e => { |
||||||
|
if(e.select){ |
||||||
|
e.children.map(n => { |
||||||
|
if(n.select){ |
||||||
|
if(n.children.length){ |
||||||
|
result.push(`${e.name}:${n.name}`) |
||||||
|
n.children.map(j => { |
||||||
|
j.select && (e.component ? result.push(`${e.component}:${n.name}:${j.name}`) : result.push(`${n.component}:${j.name}`)) |
||||||
|
}) |
||||||
|
}else{ |
||||||
|
result.push(`${e.component}:${n.name}`) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
store.commit('addBtnPerData',{btnPermissions: result}) |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
import Vue from 'vue'; |
||||||
|
|
||||||
|
// 使用 Event Bus
|
||||||
|
const bus = new Vue(); |
||||||
|
|
||||||
|
export default bus; |
@ -0,0 +1,234 @@ |
|||||||
|
import { Message } from 'element-ui' |
||||||
|
|
||||||
|
const pad2 = str => ('0' + str).substr(-2) |
||||||
|
|
||||||
|
function fMoney (s, n) { |
||||||
|
n = n > 0 && n <= 20 ? n : 2 |
||||||
|
s = parseFloat((s + '').replace(/[^\d\.-]/g, '')).toFixed(n) + '' |
||||||
|
let l = s.split('.')[0].split('').reverse() |
||||||
|
let r = s.split('.')[1] |
||||||
|
let t = '' |
||||||
|
for(let i = 0; i < l.length; i ++ ) { |
||||||
|
t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? ',' : '') |
||||||
|
} |
||||||
|
return t.split('').reverse().join('') + '.' + r |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @description 判断列表1中是否包含了列表2中的某一项 |
||||||
|
* 因为用户权限 access 为数组,includes 方法无法直接得出结论 |
||||||
|
* */ |
||||||
|
function includeArray (list1, list2) { |
||||||
|
let status = false; |
||||||
|
list2.forEach(item => { |
||||||
|
if (list1.includes(item)) status = true; |
||||||
|
}); |
||||||
|
return status; |
||||||
|
} |
||||||
|
|
||||||
|
function toDateTime (date, time) { |
||||||
|
if (!date) return '' |
||||||
|
date = date.toString() |
||||||
|
time = time ? time.toString() : '' |
||||||
|
let str = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}` |
||||||
|
if (date.length == 14) { |
||||||
|
str += ` ${date.substr(8, 2)}:${date.substr(10, 2)}:${date.substr(12, 2)}` |
||||||
|
} else if (date.length == 6) { |
||||||
|
str = `${date.substr(0, 2)}:${date.substr(2, 2)}:${date.substr(4, 2)}` |
||||||
|
} else if (time) { |
||||||
|
str += ` ${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}` |
||||||
|
} |
||||||
|
return str |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function Percentage(num, total) {
|
||||||
|
if (num == 0 || total == 0){ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
return (Math.round(num / total * 10000) / 100.00);// 小数点后两位百分比
|
||||||
|
} |
||||||
|
|
||||||
|
function fMoney2 (m) { |
||||||
|
return parseFloat(m).toFixed(2) |
||||||
|
} |
||||||
|
|
||||||
|
function systemStatus (sts) { |
||||||
|
const status = { |
||||||
|
'1': '运行中', |
||||||
|
'2': '故障中' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
function systemTypeStatus (sts) { |
||||||
|
const status = { |
||||||
|
'1': '工具', |
||||||
|
'2': '实训', |
||||||
|
'3': '网站' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
function systemAttributionStatus (sts) { |
||||||
|
const status = { |
||||||
|
'1': '外部产品', |
||||||
|
'2': '内部系统' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
function courseTypeStatus (sts) { |
||||||
|
const status = { |
||||||
|
'1': '实训课程', |
||||||
|
'2': '理论课程' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
function hoursStatus (sts) { |
||||||
|
const status = { |
||||||
|
'1': '32课时', |
||||||
|
'2': '64课时' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
function roleStatus (sts) { |
||||||
|
const status = { |
||||||
|
'1': '超级管理员', |
||||||
|
'2': '管理员', |
||||||
|
'3': '老师', |
||||||
|
'4': '学生' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
function orderTypeFn (sts) { |
||||||
|
const status = { |
||||||
|
'1': '正式', |
||||||
|
'2': '试用' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
function orderStatusFn (sts) { |
||||||
|
const status = { |
||||||
|
'1': '待发货', |
||||||
|
'2': '已完成', |
||||||
|
'3': '已取消' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
function orderNatureFn (sts) { |
||||||
|
const status = { |
||||||
|
'1': '初签', |
||||||
|
'2': '续签' |
||||||
|
} |
||||||
|
return status[sts] || '未知状态' |
||||||
|
} |
||||||
|
|
||||||
|
// 获取出生日期
|
||||||
|
function getBirth(idCard) { |
||||||
|
var birthday = ""; |
||||||
|
if(idCard != null && idCard != ""){ |
||||||
|
if(idCard.length == 15){ |
||||||
|
birthday = "19"+idCard.slice(6,12); |
||||||
|
} else if(idCard.length == 18){ |
||||||
|
birthday = idCard.slice(6,14); |
||||||
|
}
|
||||||
|
birthday = birthday.replace(/(.{4})(.{2})/,"$1-$2-"); |
||||||
|
//通过正则表达式来指定输出格式为:1990-01-01
|
||||||
|
}
|
||||||
|
return birthday; |
||||||
|
} |
||||||
|
|
||||||
|
// 获取性别
|
||||||
|
function getSex(idCard) { |
||||||
|
var sexStr = ''; |
||||||
|
if (parseInt(idCard.slice(-2, -1)) % 2 == 1) { |
||||||
|
sexStr = 'man'; |
||||||
|
} |
||||||
|
else { |
||||||
|
sexStr = 'woman'; |
||||||
|
} |
||||||
|
return sexStr; |
||||||
|
} |
||||||
|
|
||||||
|
function removeByValue(arr, val) { |
||||||
|
for(var i=0; i<arr.length; i++) { |
||||||
|
if(arr[i] == val) { |
||||||
|
arr.splice(i, 1); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss"
|
||||||
|
function formatDate(fmt,date) { |
||||||
|
var date = date ? date : new Date() |
||||||
|
var o = {
|
||||||
|
"M+" : date.getMonth()+1, //月份
|
||||||
|
"d+" : date.getDate(), //日
|
||||||
|
"h+" : date.getHours(), //小时
|
||||||
|
"m+" : date.getMinutes(), //分
|
||||||
|
"s+" : date.getSeconds(), //秒
|
||||||
|
"q+" : Math.floor((date.getMonth()+3)/3), //季度
|
||||||
|
"S" : date.getMilliseconds() //毫秒
|
||||||
|
};
|
||||||
|
if(/(y+)/.test(fmt)) { |
||||||
|
fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
|
||||||
|
} |
||||||
|
for(var k in o) { |
||||||
|
if(new RegExp("("+ k +")").test(fmt)){ |
||||||
|
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); |
||||||
|
} |
||||||
|
} |
||||||
|
return fmt;
|
||||||
|
} |
||||||
|
|
||||||
|
// 是否IE
|
||||||
|
function isIE() { |
||||||
|
if (!!window.ActiveXObject || "ActiveXObject" in window) return true |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
// 成功提示
|
||||||
|
function successMsg(message) { |
||||||
|
Message.success({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration: 1500}) |
||||||
|
} |
||||||
|
|
||||||
|
// 警告提示
|
||||||
|
function warningMsg(message) { |
||||||
|
Message.warning({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration: 1500}) |
||||||
|
} |
||||||
|
|
||||||
|
// 错误提示
|
||||||
|
function errorMsg(message) { |
||||||
|
Message.error({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration: 1500}) |
||||||
|
} |
||||||
|
|
||||||
|
export { |
||||||
|
fMoney, |
||||||
|
toDateTime, |
||||||
|
Percentage, |
||||||
|
fMoney2, |
||||||
|
systemStatus, |
||||||
|
systemTypeStatus, |
||||||
|
systemAttributionStatus, |
||||||
|
courseTypeStatus, |
||||||
|
hoursStatus, |
||||||
|
roleStatus, |
||||||
|
orderTypeFn, |
||||||
|
orderStatusFn, |
||||||
|
orderNatureFn, |
||||||
|
getBirth, |
||||||
|
getSex, |
||||||
|
removeByValue, |
||||||
|
formatDate, |
||||||
|
isIE, |
||||||
|
successMsg, |
||||||
|
warningMsg, |
||||||
|
errorMsg |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
// rem等比适配配置文件
|
||||||
|
// 基准大小
|
||||||
|
const baseSize = 16 |
||||||
|
// 设置 rem 函数
|
||||||
|
function setRem () { |
||||||
|
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
|
||||||
|
const scale = document.documentElement.clientWidth / 1920 |
||||||
|
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
|
||||||
|
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px' |
||||||
|
} |
||||||
|
// 初始化
|
||||||
|
setRem() |
||||||
|
// 改变窗口大小时重新设置 rem
|
||||||
|
window.onresize = function () { |
||||||
|
setRem() |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
import store from '@/store'; |
||||||
|
import router from '@/router'; |
||||||
|
import generateBtnPermission from '../auth/generateBtnPermission'; |
||||||
|
|
||||||
|
const infoSidebar = ['information','content'] |
||||||
|
const matchSidebar = ['matchintro','matchprogress','matchsignup'] |
||||||
|
const newRoutes = [] |
||||||
|
|
||||||
|
function createMeta(item){ |
||||||
|
let meta = { title: item.name } |
||||||
|
infoSidebar.includes(item.component) && (meta.sidebar = 'info') |
||||||
|
matchSidebar.includes(item.component) && (meta.sidebar = 'match') |
||||||
|
return meta |
||||||
|
} |
||||||
|
|
||||||
|
function createRoute(data){ |
||||||
|
data.map(e => { |
||||||
|
if(e.select && e.component){ |
||||||
|
let meta = createMeta(e) |
||||||
|
newRoutes.push({ |
||||||
|
name: e.component, |
||||||
|
path: e.component, |
||||||
|
component: () => import(`@/pages/${e.component}.vue`), |
||||||
|
meta |
||||||
|
}) |
||||||
|
} |
||||||
|
e.children && e.children.length && createRoute(e.children) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export default function(data,path){ |
||||||
|
generateBtnPermission(data) |
||||||
|
createRoute(data) |
||||||
|
let routes = router.options.routes |
||||||
|
routes[1].children = [...routes[1].children,...newRoutes] |
||||||
|
store.commit("addRoutesData", { routes }) |
||||||
|
router.addRoutes(routes) |
||||||
|
setTimeout(() => { |
||||||
|
!newRoutes.find(n => n.name == 'dashboard') && router.push(newRoutes[0].path) |
||||||
|
},10) |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
import store from '@/store'; |
||||||
|
import router from '@/router'; |
||||||
|
|
||||||
|
export default function(){ |
||||||
|
setTimeout(() => { |
||||||
|
let routes = store.state.routes |
||||||
|
routes.forEach(e => { |
||||||
|
if(e.path == '/'){ |
||||||
|
e.component = () => import('@/layouts/home/index.vue') |
||||||
|
}else{ |
||||||
|
e.component = () => import(`@/pages/${e.path}.vue`) |
||||||
|
} |
||||||
|
|
||||||
|
e.children && e.children.forEach(n => { |
||||||
|
n.path && (n.component = () => import(`@/pages/${n.path}.vue`)) |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
routes.push({ |
||||||
|
path: '*', |
||||||
|
redirect: '404' |
||||||
|
}) |
||||||
|
router.addRoutes(routes) |
||||||
|
},500) |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
import router from '@/router'; |
||||||
|
|
||||||
|
export default function(){ |
||||||
|
const newRouter = createRouter() |
||||||
|
router.matcher = newRouter.matcher |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
import Vue from 'vue'; |
||||||
|
import App from '@/App.vue'; |
||||||
|
import router from '@/router'; |
||||||
|
import ElementUI from 'element-ui'; |
||||||
|
import '@/styles/index.scss' |
||||||
|
import VueI18n from 'vue-i18n'; |
||||||
|
import { messages } from '@/i18n'; |
||||||
|
import 'babel-polyfill'; |
||||||
|
import '@/libs/resize'; |
||||||
|
import api from '@/api'; |
||||||
|
import store from '@/store' |
||||||
|
import {post,get,del,put} from '@/plugins/requests/index.js'; |
||||||
|
import { systemStatus, systemTypeStatus, systemAttributionStatus, courseTypeStatus, hoursStatus, roleStatus, orderTypeFn, orderStatusFn, orderNatureFn, Percentage, removeByValue, formatDate, isIE, successMsg, warningMsg, errorMsg } from './libs/core'; |
||||||
|
import permission from '@/router/permission'; |
||||||
|
import Setting from '@/setting'; |
||||||
|
|
||||||
|
// 插件
|
||||||
|
import plugins from '@/plugins'; |
||||||
|
|
||||||
|
Vue.use(plugins); |
||||||
|
|
||||||
|
Vue.prototype.api = api; |
||||||
|
Vue.prototype.$get = get; |
||||||
|
Vue.prototype.$post = post; |
||||||
|
Vue.prototype.$del = del; |
||||||
|
Vue.prototype.$put = put; |
||||||
|
|
||||||
|
Vue.prototype.systemStatus = systemStatus; |
||||||
|
Vue.prototype.systemTypeStatus = systemTypeStatus; |
||||||
|
Vue.prototype.systemAttributionStatus = systemAttributionStatus; |
||||||
|
Vue.prototype.courseTypeStatus = courseTypeStatus; |
||||||
|
Vue.prototype.hoursStatus = hoursStatus; |
||||||
|
Vue.prototype.roleStatus = roleStatus; |
||||||
|
Vue.prototype.orderTypeFn = orderTypeFn; |
||||||
|
Vue.prototype.orderStatusFn = orderStatusFn; |
||||||
|
Vue.prototype.orderNatureFn = orderNatureFn; |
||||||
|
Vue.prototype.Percentage = Percentage; |
||||||
|
Vue.prototype.removeByValue = removeByValue; |
||||||
|
Vue.prototype.formatDate = formatDate; |
||||||
|
Vue.prototype.isIE = isIE; |
||||||
|
Vue.prototype.successMsg = successMsg; |
||||||
|
Vue.prototype.warningMsg = warningMsg; |
||||||
|
Vue.prototype.errorMsg = errorMsg; |
||||||
|
|
||||||
|
Vue.config.productionTip = false; |
||||||
|
Vue.use(VueI18n); |
||||||
|
Vue.use(ElementUI); |
||||||
|
const i18n = new VueI18n({ |
||||||
|
locale: Setting.i18n.default, |
||||||
|
messages |
||||||
|
}); |
||||||
|
|
||||||
|
new Vue({ |
||||||
|
router, |
||||||
|
store, |
||||||
|
i18n, |
||||||
|
render: h => h(App) |
||||||
|
}).$mount('#app'); |
@ -0,0 +1,56 @@ |
|||||||
|
<template> |
||||||
|
<div class="error-page"> |
||||||
|
<div class="error-code">4<span>0</span>3</div> |
||||||
|
<div class="error-desc">啊哦~ 你没有权限访问该页面哦</div> |
||||||
|
<div class="error-handle"> |
||||||
|
<router-link to="/"> |
||||||
|
<el-button type="primary" size="large">返回首页</el-button> |
||||||
|
</router-link> |
||||||
|
<el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
methods: { |
||||||
|
goBack(){ |
||||||
|
this.$router.go(-1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.error-page{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
flex-direction: column; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background: #f3f3f3; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
.error-code{ |
||||||
|
line-height: 1; |
||||||
|
font-size: 250px; |
||||||
|
font-weight: bolder; |
||||||
|
color: #f02d2d; |
||||||
|
} |
||||||
|
.error-code span{ |
||||||
|
color: #00a854; |
||||||
|
} |
||||||
|
.error-desc{ |
||||||
|
font-size: 30px; |
||||||
|
color: #777; |
||||||
|
} |
||||||
|
.error-handle{ |
||||||
|
margin-top: 30px; |
||||||
|
padding-bottom: 200px; |
||||||
|
} |
||||||
|
.error-btn{ |
||||||
|
margin-left: 100px; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,56 @@ |
|||||||
|
<template> |
||||||
|
<div class="error-page"> |
||||||
|
<div class="error-code">4<span>0</span>4</div> |
||||||
|
<div class="error-desc">啊哦~ 你所访问的页面不存在</div> |
||||||
|
<div class="error-handle"> |
||||||
|
<router-link to="/"> |
||||||
|
<el-button type="primary" size="large">返回首页</el-button> |
||||||
|
</router-link> |
||||||
|
<el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
methods: { |
||||||
|
goBack(){ |
||||||
|
this.$router.go(-1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.error-page{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
flex-direction: column; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background: #f3f3f3; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
.error-code{ |
||||||
|
line-height: 1; |
||||||
|
font-size: 250px; |
||||||
|
font-weight: bolder; |
||||||
|
color: #2d8cf0; |
||||||
|
} |
||||||
|
.error-code span{ |
||||||
|
color: #00a854; |
||||||
|
} |
||||||
|
.error-desc{ |
||||||
|
font-size: 30px; |
||||||
|
color: #777; |
||||||
|
} |
||||||
|
.error-handle{ |
||||||
|
margin-top: 30px; |
||||||
|
padding-bottom: 200px; |
||||||
|
} |
||||||
|
.error-btn{ |
||||||
|
margin-left: 100px; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,250 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'课程资源管理/课程信息'" :route="'course'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="p-title">课程信息</div> |
||||||
|
<div class="page-content"> |
||||||
|
<el-form :disabled="isDetail" label-width="80px" label-suffix=":" size="small"> |
||||||
|
<el-form-item label="课程名称"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-input placeholder="请输入课程名称" v-model="name" clearable maxlength="25"></el-input> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="课程分类"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-select v-model="classificationId" placeholder="请选择课程分类"> |
||||||
|
<el-option v-for="item in classificationList" :key="item.id" :label="item.name" :value="item.id"></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="课程封面"> |
||||||
|
<el-upload class="avatar-uploader" accept=".jpg,.png,.jpeg" :on-remove="handleRemove" :on-error="uploadError" :on-success="uploadSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.fileupload" name="file"> |
||||||
|
<img v-if="coverUrl" :src="coverUrl" class="avatar"> |
||||||
|
<div class="uploader-default" v-else> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<p>上传封面</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div slot="tip" class="el-upload__tip"> |
||||||
|
<p>只能上传jpg/png文件</p> |
||||||
|
<p>课程封面图将按2:1显示,最佳分辨率1400*700</p> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="课程介绍"> |
||||||
|
<quill :border="true" :readonly="isDetail" v-model="description" :height="400" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button type="primary" size="small" v-throttle @click="save" v-show="!isDetail">{{id ? '更新' : '创建'}}</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import quill from '@/components/quill' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
schoolId: this.$store.state.schoolId, |
||||||
|
id: '', |
||||||
|
isDetail: Boolean(this.$route.query.show), |
||||||
|
userId: this.$store.state.userLoginId, |
||||||
|
username: this.$store.state.name, |
||||||
|
classificationId: '', |
||||||
|
coverUrl: '', |
||||||
|
name: '', |
||||||
|
classificationList: [], |
||||||
|
uploadList: [], |
||||||
|
description: '', |
||||||
|
submiting: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.id = this.$route.query.id |
||||||
|
this.getClassification() |
||||||
|
this.id && this.getData() |
||||||
|
}, |
||||||
|
components: { |
||||||
|
quill, |
||||||
|
breadcrumb |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
save() { |
||||||
|
if(this.submiting) return false |
||||||
|
if(!this.name) return this.warningMsg('请填写课程名称') |
||||||
|
if(!this.classificationId) return this.warningMsg('请选择课程分类') |
||||||
|
if(!this.coverUrl) return this.warningMsg('请上传课程封面') |
||||||
|
this.submiting = true |
||||||
|
|
||||||
|
let data = { |
||||||
|
id: this.id, |
||||||
|
classificationId: this.classificationId, |
||||||
|
coverUrl: this.coverUrl, |
||||||
|
description: this.description, |
||||||
|
name: this.name, |
||||||
|
founderId: this.userId, |
||||||
|
schoolId: this.schoolId, |
||||||
|
founderName: this.username, |
||||||
|
distinguish: 1 |
||||||
|
} |
||||||
|
if(this.id){ |
||||||
|
this.$put(this.api.editCourse, data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.$router.back() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
this.submiting = false |
||||||
|
}); |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addCourse, data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
this.$confirm('课程创建成功,是否马上进行课程内容设置?', '提示', { |
||||||
|
type: 'success', |
||||||
|
confirmButtonText: '马上设置', |
||||||
|
cancelButtonText: '稍后操作', |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$router.push(`courseConfig?id=${res.data.courseId}`) |
||||||
|
}).catch(() => { |
||||||
|
this.$router.back() |
||||||
|
}); |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
this.submiting = false |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
getClassification() { |
||||||
|
this.$get(this.api.queryAllClassification).then(res => { |
||||||
|
this.classificationList = res.data.classificationList |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
getData() { |
||||||
|
this.$get(`${this.api.getCourse}/${this.id}`) |
||||||
|
.then(res => { |
||||||
|
let data = res.data.course |
||||||
|
this.name = data.name |
||||||
|
this.classificationId = data.classificationId |
||||||
|
this.description = data.description |
||||||
|
this.coverUrl = data.coverUrl |
||||||
|
this.uploadList.push({ |
||||||
|
name: 'cover.jpg', |
||||||
|
url: this.coverUrl |
||||||
|
}) |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
|
||||||
|
}); |
||||||
|
}, |
||||||
|
// 上传文件 |
||||||
|
handleExceed(files, fileList) { |
||||||
|
this.warningMsg( |
||||||
|
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||||
|
); |
||||||
|
}, |
||||||
|
uploadSuccess(res, file, fileList) { |
||||||
|
this.coverUrl = res.data.filesResult.fileUrl |
||||||
|
// this.uploadList.push({ name: file.name, url: response.message.fileUrl }); |
||||||
|
}, |
||||||
|
uploadError(err, file, fileList) { |
||||||
|
this.$message({ |
||||||
|
message: "上传出错,请重试!", |
||||||
|
type: "error", |
||||||
|
center: true |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeRemove(file, fileList) { |
||||||
|
return this.$confirm(`确定移除 ${file.name}?`); |
||||||
|
}, |
||||||
|
handleRemove(file, fileList) { |
||||||
|
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||||
|
this.coverUrl = '' |
||||||
|
}).catch(res => {}) |
||||||
|
}, |
||||||
|
uploadSure(){ |
||||||
|
this.importVisible = false |
||||||
|
this.pageNo = 1 |
||||||
|
this.staffGradeId = '' |
||||||
|
this.keyword = '' |
||||||
|
this.getTeacher() |
||||||
|
}, |
||||||
|
goback() { |
||||||
|
if(this.isDetail){ |
||||||
|
this.$router.back() |
||||||
|
}else{ |
||||||
|
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$router.back() |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
} |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
$avatar-width: 104px; |
||||||
|
/deep/.avatar-uploader{ |
||||||
|
.el-upload { |
||||||
|
position: relative; |
||||||
|
width: $avatar-width; |
||||||
|
border: 1px dashed #d9d9d9; |
||||||
|
border-radius: 2px; |
||||||
|
cursor: pointer; |
||||||
|
overflow: hidden; |
||||||
|
&:hover { |
||||||
|
border-color: #409EFF; |
||||||
|
} |
||||||
|
.uploader-default{ |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
width: $avatar-width !important; |
||||||
|
height: $avatar-width; |
||||||
|
text-align: center; |
||||||
|
background: rgba(0, 0, 0, 0.04); |
||||||
|
i{ |
||||||
|
font-size: 20px; |
||||||
|
font-weight: bold; |
||||||
|
color: #8c939d; |
||||||
|
} |
||||||
|
p{ |
||||||
|
margin-top: 10px; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
.avatar { |
||||||
|
width: $avatar-width; |
||||||
|
height: $avatar-width; |
||||||
|
display: block; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-upload__tip{ |
||||||
|
margin-top: 0; |
||||||
|
p{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.45); |
||||||
|
line-height: 1; |
||||||
|
&:first-child{ |
||||||
|
margin-bottom: 5px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
/deep/.d-inline-block{ |
||||||
|
width: 216px; |
||||||
|
.el-select,.el-input{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,248 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'官方资讯管理/添加内容'" :route="'information'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="p-title">添加内容</div> |
||||||
|
<div class="page-content"> |
||||||
|
<el-form label-width="90px" label-suffix=":" size="small"> |
||||||
|
<el-form-item label="封面图"> |
||||||
|
<el-upload class="avatar-uploader" accept=".jpg,.png,.jpeg" :on-remove="handleRemove" :on-error="uploadError" :on-success="uploadSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.fileupload" name="file"> |
||||||
|
<img v-if="coverUrl" :src="coverUrl" class="avatar"> |
||||||
|
<div class="uploader-default" v-else> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<p>上传封面</p> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="作者"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-input placeholder="请输入作者" v-model="author" clearable></el-input> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="日期"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-date-picker v-model="date" type="date" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期"></el-date-picker> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="文章标题"> |
||||||
|
<el-input placeholder="请输入文章标题" v-model="title" clearable></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="文章内容"> |
||||||
|
<quill :border="true" v-model="content" :uploading.sync="uploading" :height="400" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button type="primary" v-throttle @click="saveData">确定</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import quill from '@/components/quill' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
columnId: this.$route.query.columnId, |
||||||
|
sort: this.$route.query.sort, |
||||||
|
id: '', |
||||||
|
userId: this.$store.state.userLoginId, |
||||||
|
coverUrl: '', |
||||||
|
uploadList: [], |
||||||
|
uploadDataList: [], |
||||||
|
author: '', |
||||||
|
date: '', |
||||||
|
title: '', |
||||||
|
content: '', |
||||||
|
submiting: false, |
||||||
|
uploading: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
quill, |
||||||
|
breadcrumb |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.id = this.$route.query.id |
||||||
|
this.id && this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
this.$get(`${this.api.getArticle}/${this.id}`) |
||||||
|
.then(res => { |
||||||
|
let data = res.data.article |
||||||
|
this.coverUrl = data.coverUrl |
||||||
|
this.author = data.author |
||||||
|
this.date = data.date |
||||||
|
this.title = data.title |
||||||
|
this.content = data.content |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
|
||||||
|
}); |
||||||
|
}, |
||||||
|
saveData() { |
||||||
|
if(this.submiting) return false |
||||||
|
if(!this.coverUrl) return this.warningMsg('请上传封面图') |
||||||
|
if(!this.author) return this.warningMsg('请填写作者') |
||||||
|
if(!this.date) return this.warningMsg('请选择日期') |
||||||
|
if(!this.title) return this.warningMsg('请填写文章标题') |
||||||
|
if(!this.content) return this.warningMsg('请填写文章内容') |
||||||
|
if(this.uploading) return this.warningMsg('图片正在上传中,请稍等') |
||||||
|
this.submiting = true |
||||||
|
|
||||||
|
let data = { |
||||||
|
id: this.id, |
||||||
|
columnId: this.columnId, |
||||||
|
author: this.author, |
||||||
|
coverUrl: this.coverUrl, |
||||||
|
date: this.date, |
||||||
|
title: this.title, |
||||||
|
content: this.content, |
||||||
|
sort: this.sort |
||||||
|
} |
||||||
|
if(this.id){ |
||||||
|
this.$put(this.api.editArticle, data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.back() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
this.submiting = false |
||||||
|
}) |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addArticle, data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
this.successMsg('创建成功'); |
||||||
|
this.back() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
this.submiting = false |
||||||
|
}) |
||||||
|
} |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.currPage = val; |
||||||
|
}, |
||||||
|
handleExceed(files, fileList) { |
||||||
|
this.warningMsg( |
||||||
|
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||||
|
); |
||||||
|
}, |
||||||
|
uploadSuccess(res, file, fileList) { |
||||||
|
if(this.coverUrl){ |
||||||
|
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {}).catch(res => {}); |
||||||
|
} |
||||||
|
this.coverUrl = res.data.filesResult.fileUrl |
||||||
|
}, |
||||||
|
uploadError(err, file, fileList) { |
||||||
|
this.$message({ |
||||||
|
message: "上传出错,请重试!", |
||||||
|
type: "error", |
||||||
|
center: true |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeRemove(file, fileList) { |
||||||
|
return this.$confirm(`确定移除 ${file.name}?`); |
||||||
|
}, |
||||||
|
handleRemove(file, fileList) { |
||||||
|
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||||
|
this.coverUrl = '' |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
uploadSure(){ |
||||||
|
this.BatchUpload = false |
||||||
|
this.pageNo = 1 |
||||||
|
this.keyword = '' |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
back(){ |
||||||
|
// this.$router.push(`/content?id=${this.columnId}`) |
||||||
|
this.$router.back() |
||||||
|
}, |
||||||
|
goback() { |
||||||
|
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.back() |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
addSponsor(){ |
||||||
|
this.sponsorList.push('') |
||||||
|
}, |
||||||
|
delSponsor(index){ |
||||||
|
this.sponsorList.splice(index,1) |
||||||
|
}, |
||||||
|
addOrganizer(){ |
||||||
|
this.organzinerList.push('') |
||||||
|
}, |
||||||
|
delOrganizer(index){ |
||||||
|
this.organzinerList.splice(index,1) |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
$avatar-width: 104px; |
||||||
|
/deep/.avatar-uploader{ |
||||||
|
.el-upload { |
||||||
|
position: relative; |
||||||
|
width: $avatar-width; |
||||||
|
border: 1px dashed #d9d9d9; |
||||||
|
border-radius: 2px; |
||||||
|
cursor: pointer; |
||||||
|
overflow: hidden; |
||||||
|
&:hover { |
||||||
|
border-color: #409EFF; |
||||||
|
} |
||||||
|
.uploader-default{ |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
width: $avatar-width !important; |
||||||
|
height: $avatar-width; |
||||||
|
text-align: center; |
||||||
|
background: rgba(0, 0, 0, 0.04); |
||||||
|
i{ |
||||||
|
font-size: 20px; |
||||||
|
font-weight: bold; |
||||||
|
color: #8c939d; |
||||||
|
} |
||||||
|
p{ |
||||||
|
margin-top: 10px; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
.avatar { |
||||||
|
width: $avatar-width; |
||||||
|
height: $avatar-width; |
||||||
|
display: block; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-upload__tip{ |
||||||
|
margin-top: 0; |
||||||
|
p{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.45); |
||||||
|
line-height: 1; |
||||||
|
&:first-child{ |
||||||
|
margin-bottom: 5px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
/deep/.d-inline-block{ |
||||||
|
width: 216px; |
||||||
|
.el-select,.el-input{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,504 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'学校信息列表/学校信息'" :route="'dashboard'"></breadcrumb> |
||||||
|
<div class="page m-b-20"> |
||||||
|
<div class="p-title">学校信息</div> |
||||||
|
<div class="page-content"> |
||||||
|
<ul class="list" v-if="isDetail"> |
||||||
|
<li> |
||||||
|
<div class="side"> |
||||||
|
<span class="name"><i class="required">*</i>国家:</span> |
||||||
|
<span class="val">中国</span> |
||||||
|
</div> |
||||||
|
<div class="side"> |
||||||
|
<span class="name"><i class="required">*</i>客户类型:</span> |
||||||
|
<span class="val">{{clientTypeList.find(n => n.value == form.type).name}}</span> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<div class="side"> |
||||||
|
<span class="name"><i class="required">*</i>省份:</span> |
||||||
|
<span class="val">{{provinceList.find(n => n.provinceId == form.provinceId).provinceName}}</span> |
||||||
|
</div> |
||||||
|
<div class="side"> |
||||||
|
<span class="name"><i class="required">*</i>城市:</span> |
||||||
|
<span class="val">{{cityList.find(n => n.cityId == form.cityId).cityName}}</span> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<div class="side"> |
||||||
|
<span class="name"><i class="required">*</i>客户名称:</span> |
||||||
|
<span class="val">{{form.clientName}}</span> |
||||||
|
</div> |
||||||
|
<div class="side"> |
||||||
|
<span class="name"><i class="required">*</i>联系人名称:</span> |
||||||
|
<span class="val">{{form.contactPersonName}}</span> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<div class="side"> |
||||||
|
<span class="name"><i class="required">*</i>手机号:</span> |
||||||
|
<span class="val">{{form.phone}}</span> |
||||||
|
</div> |
||||||
|
<div class="side"></div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<el-form v-else :model="form" :rules="rules" ref="form" label-width="100px" size="small"> |
||||||
|
<el-form-item prop="countries" label="国家"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-select v-model="form.countries" placeholder="请选择国家"> |
||||||
|
<el-option v-for="(item,index) in countryList" :key="index" :label="item.name" :value="item.name"></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="provinceId" label="省份"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-select v-model="form.provinceId" placeholder="" @change="getCity()" @clear="clearprovince()"> |
||||||
|
<el-option v-for="(item,index) in provinceList" :key="index" :label="item.provinceName" :value="item.provinceId"></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="clientName" label="客户名称"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-input placeholder="请输入客户名称" v-model="form.clientName" @change="nameChange"></el-input> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="phone" label="手机号"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-input placeholder="请输入手机号" v-model="form.phone" maxlength="11"></el-input> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="type" label="客户类型"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-select v-model="form.type" placeholder=""> |
||||||
|
<el-option v-for="(item,index) in clientTypeList" :key="index" :label="item.name" :value="item.value"></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="cityId" label="城市"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-select v-model="form.cityId" :disabled="form.provinceId ? false : true" placeholder=""> |
||||||
|
<el-option v-for="(item,index) in cityList" :key="index" :label="item.cityName" :value="item.cityId"></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="contactPersonName" label="联系人名称"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-input placeholder="请输入联系人名称" v-model="form.contactPersonName"></el-input> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button type="primary" size="small" v-if="!isDetail" v-throttle @click="saveAdd">确定</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="page" v-if="id"> |
||||||
|
<div class="p-title">课程权限</div> |
||||||
|
<div class="page-content"> |
||||||
|
<div class="tool" v-if="!isDetail"> |
||||||
|
<ul class="filter"></ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" @click="addCourse">添加课程</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<el-table :data="listData" class="table" ref="table" stripe header-align="center" row-key="id"> |
||||||
|
<el-table-column v-if="!isDetail" type="selection" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||||
|
<el-table-column type="index" width="100" label="序号" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="课程名称"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="gmtCreate" label="创建时间" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="founder" label="创建人" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="章节数" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.row.chapterNum ? scope.row.chapterNum : 0}}章({{scope.row.subsectionNum ? scope.row.subsectionNum : 0}}小节) |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="classification" label="课程分类"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="300" v-if="!isDetail"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<el-dialog title="添加课程" :visible.sync="addVisible" width="50%" @close="closeAdd" :close-on-click-modal="false"> |
||||||
|
<div class="search"> |
||||||
|
<label>搜索:</label> |
||||||
|
<el-input placeholder="请输入课程名称/课程分类" prefix-icon="el-icon-search" v-model="keyword" size="small" clearable></el-input> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table |
||||||
|
:data="coursesData" |
||||||
|
ref="courseTable" |
||||||
|
row-key="id" |
||||||
|
class="table" |
||||||
|
stripe |
||||||
|
header-align="center" |
||||||
|
@selection-change="handleSelectionChange" |
||||||
|
> |
||||||
|
<el-table-column type="selection" width="80" align="center" :reserve-selection="true" :selectable="disabledSelection"></el-table-column> |
||||||
|
<el-table-column type="index" width="60" label="序号" align="center"> |
||||||
|
<template |
||||||
|
slot-scope="scope" |
||||||
|
>{{scope.$index + (pageCourse - 1) * pageSizeCourse + 1}}</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="课程名称"></el-table-column> |
||||||
|
<el-table-column prop="founder" label="创建人" width="100" align="center"></el-table-column> |
||||||
|
<el-table-column label="章节数" width="110" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.row.chapterNum ? scope.row.chapterNum : 0}}章({{scope.row.subsectionNum ? scope.row.subsectionNum : 0}}小节) |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="classification" label="课程分类"></el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination |
||||||
|
background |
||||||
|
@current-change="handleCourseCurrentChange" |
||||||
|
:current-page="pageCourse" |
||||||
|
:page-size="pageSizeCourse" |
||||||
|
layout="total,prev, pager, next" |
||||||
|
:total="totalCourse" |
||||||
|
></el-pagination> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="tag-group"> |
||||||
|
<span class="tag-group__title">已选择:</span> |
||||||
|
<el-tag |
||||||
|
class="course-name" |
||||||
|
v-for="item in multipleSelection" |
||||||
|
:key="item.id" |
||||||
|
type="danger" |
||||||
|
closable |
||||||
|
@close="removeCourse(item)"> |
||||||
|
{{ item.name }} |
||||||
|
</el-tag> |
||||||
|
</div> |
||||||
|
|
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="addVisible = false">取消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="saveCourse">确定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
name: 'addcustomer', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
id: this.$route.query.id, |
||||||
|
isDetail: Boolean(this.$route.query.show), |
||||||
|
schoolId: this.$store.state.schoolId, |
||||||
|
form: { |
||||||
|
countries: '中国', |
||||||
|
clientName: '', |
||||||
|
provinceId: '', |
||||||
|
contactPersonName: '', |
||||||
|
phone: '', |
||||||
|
cityId: '', |
||||||
|
type: 1, |
||||||
|
}, |
||||||
|
rules: { |
||||||
|
type: [ |
||||||
|
{ required: true, message: '请选择客户类型', trigger: 'change' } |
||||||
|
], |
||||||
|
countries: [ |
||||||
|
{ required: true, message: '请选择国家', trigger: 'change' } |
||||||
|
], |
||||||
|
provinceId: [ |
||||||
|
{ required: true, message: '请选择省份', trigger: 'change' } |
||||||
|
], |
||||||
|
cityId: [ |
||||||
|
{ required: true, message: '请选择城市', trigger: 'change' } |
||||||
|
], |
||||||
|
contactPersonName: [ |
||||||
|
{ required: true, message: '请输入管理员姓名', trigger: 'blur' } |
||||||
|
], |
||||||
|
phone: [ |
||||||
|
{ required: true, message: '请输入手机号', trigger: 'blur' }, |
||||||
|
{ |
||||||
|
pattern: /^1[3456789]\d{9}$/, |
||||||
|
message: '请输入正确的手机号', |
||||||
|
trigger: 'blur' |
||||||
|
} |
||||||
|
], |
||||||
|
clientName: [ |
||||||
|
{ required: true, message: '请输入客户名称', trigger: 'blur' } |
||||||
|
], |
||||||
|
}, |
||||||
|
clientTypeList: [{ |
||||||
|
name: '正式', |
||||||
|
value: 1 |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '试用', |
||||||
|
value: 2 |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '到期', |
||||||
|
value: 3 |
||||||
|
}], |
||||||
|
countryList: [{ |
||||||
|
name:'中国' |
||||||
|
}], |
||||||
|
provinceList: this.$store.state.provinceList, |
||||||
|
cityList: [], |
||||||
|
originalName: '', |
||||||
|
nameRepeat: false, |
||||||
|
keyword: '', |
||||||
|
searchTimer: null, |
||||||
|
listData: [], |
||||||
|
multipleSelection: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0, |
||||||
|
addVisible: false, |
||||||
|
coursesData: [], |
||||||
|
pageCourse: 1, |
||||||
|
pageSizeCourse: 10, |
||||||
|
totalCourse: 0, |
||||||
|
submiting: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
breadcrumb |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
if(this.id){ |
||||||
|
this.getData() |
||||||
|
this.getCourses() |
||||||
|
} |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer) |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.initData() |
||||||
|
},500) |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData(){ |
||||||
|
this.$get(`${this.api.getClient}/${this.id}`).then((res) => { |
||||||
|
this.form = res.data.client |
||||||
|
this.originalName = res.data.client.clientName |
||||||
|
this.form.countries = '中国' |
||||||
|
this.getCityData() |
||||||
|
}).catch((res) => { |
||||||
|
}) |
||||||
|
}, |
||||||
|
getCourses(){ |
||||||
|
this.$get(`${this.api.queryBuiltInCourseByCondition}/${this.pageNo}?schoolId=${this.id}`).then((res) => { |
||||||
|
this.listData = res.data.courseList |
||||||
|
this.totals = res.data.total |
||||||
|
}).catch((res) => {}) |
||||||
|
}, |
||||||
|
nameChange(){ |
||||||
|
if(this.form.clientName !== this.originalName){ |
||||||
|
this.$get(`${this.api.getClientName}?clientName=${this.form.clientName}`).then(res => { |
||||||
|
if(res.data.client.length){ |
||||||
|
this.nameRepeat = true |
||||||
|
this.warningMsg('该客户名称已存在') |
||||||
|
}else{ |
||||||
|
this.nameRepeat = false |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
this.nameRepeat = false |
||||||
|
} |
||||||
|
}, |
||||||
|
// 清除省份 |
||||||
|
clearprovince(){ |
||||||
|
this.form.cityId = '' |
||||||
|
}, |
||||||
|
getCity(){ |
||||||
|
this.clearprovince() |
||||||
|
this.getCityData() |
||||||
|
this.pageNo = 1 |
||||||
|
}, |
||||||
|
getCityData(){ |
||||||
|
let data = { |
||||||
|
provinceId: this.form.provinceId |
||||||
|
} |
||||||
|
this.$get(this.api.queryCity,data).then(res => { |
||||||
|
this.cityList = res.data.list |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
saveAdd(){ |
||||||
|
if(this.submiting) return false |
||||||
|
this.$refs.form.validate((valid) => { |
||||||
|
if (valid) { |
||||||
|
if(this.nameRepeat) return this.warningMsg('该客户名称已存在') |
||||||
|
this.form.provinceName = this.provinceList.find(n => n.provinceId == this.form.provinceId).provinceName |
||||||
|
this.form.cityName = this.cityList.find(n => n.cityId == this.form.cityId).cityName |
||||||
|
let data = this.form |
||||||
|
this.submiting = true |
||||||
|
|
||||||
|
if(this.id){ |
||||||
|
this.$post(this.api.updateClient,data).then((res) => { |
||||||
|
this.submiting = false |
||||||
|
this.successMsg('编辑成功') |
||||||
|
this.$router.back() |
||||||
|
}).catch((res) => { |
||||||
|
this.submiting = false |
||||||
|
}) |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addClient,data).then((res) => { |
||||||
|
this.submiting = false |
||||||
|
this.successMsg('添加成功') |
||||||
|
this.$router.back() |
||||||
|
}).catch((res) => { |
||||||
|
this.submiting = false |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
}, |
||||||
|
goback() { |
||||||
|
if(this.isDetail){ |
||||||
|
this.$router.back() |
||||||
|
}else{ |
||||||
|
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$router.back() |
||||||
|
}) |
||||||
|
.catch(() => {}) |
||||||
|
} |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val |
||||||
|
this.getCourses() |
||||||
|
}, |
||||||
|
handleDelete(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteBuiltInCourse}?courseId=${row.id}&schoolId=${this.id}&classificationId=${row.classificationId}`).then(res => { |
||||||
|
this.successMsg('删除成功') |
||||||
|
this.getCourses() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
addCourse(){ |
||||||
|
this.addVisible = true |
||||||
|
this.getAddCourses() |
||||||
|
}, |
||||||
|
closeAdd(){ |
||||||
|
this.keyword = '' |
||||||
|
this.pageCourse = 1 |
||||||
|
this.$refs.courseTable.clearSelection() |
||||||
|
}, |
||||||
|
getAddCourses(){ |
||||||
|
let data = { |
||||||
|
classificationId: '', |
||||||
|
name: this.keyword, |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryCourseByCondition}/${this.pageCourse}`,data).then(res => { |
||||||
|
this.coursesData = res.data.courseList |
||||||
|
this.totalCourse = res.data.total |
||||||
|
}).catch(res => {}) |
||||||
|
}, |
||||||
|
initData(){ |
||||||
|
this.pageCourse = 1 |
||||||
|
this.getAddCourses() |
||||||
|
}, |
||||||
|
handleCourseCurrentChange(val){ |
||||||
|
this.pageCourse = val |
||||||
|
this.getAddCourses() |
||||||
|
}, |
||||||
|
disabledSelection(row,index){ |
||||||
|
let listData = this.listData |
||||||
|
if(listData.find(n => n.id == row.id)) return false |
||||||
|
return true |
||||||
|
}, |
||||||
|
removeCourse(item){ |
||||||
|
this.multipleSelection.splice(this.coursesData.findIndex(n => n.id == item.id),1) |
||||||
|
this.$refs.courseTable.toggleRowSelection(item) |
||||||
|
}, |
||||||
|
saveCourse(){ |
||||||
|
if(!this.multipleSelection.length) return this.errorMsg('请选择课程') |
||||||
|
let ids = this.multipleSelection.map(n => n.id).join(',') |
||||||
|
let classificationIds = Array.from(new Set(this.multipleSelection.map(n => n.classificationId))).join(',') |
||||||
|
this.$post(`${this.api.addBuiltInCourse}?schoolId=${this.id}&courseIds=${ids}&classificationIds=${classificationIds}`).then(res => { |
||||||
|
this.successMsg('添加成功') |
||||||
|
this.addVisible = false |
||||||
|
this.getCourses() |
||||||
|
}).catch(res => {}) |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.search{ |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 20px; |
||||||
|
label{ |
||||||
|
white-space: nowrap; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
.el-input{ |
||||||
|
width: 250px; |
||||||
|
} |
||||||
|
} |
||||||
|
/deep/.d-inline-block{ |
||||||
|
width: 216px; |
||||||
|
.el-select,.el-input{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
.course-name{ |
||||||
|
margin-right: 5px; |
||||||
|
} |
||||||
|
.list{ |
||||||
|
li{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
margin: 32px 0; |
||||||
|
.side{ |
||||||
|
width: 200px; |
||||||
|
&:first-child{ |
||||||
|
margin-right: 100px; |
||||||
|
} |
||||||
|
} |
||||||
|
.name,.val{ |
||||||
|
font-size: 16px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
} |
||||||
|
.name{ |
||||||
|
width: 45%; |
||||||
|
text-align: right; |
||||||
|
} |
||||||
|
.val{ |
||||||
|
width: 55%; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,411 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'赛事信息管理/创建赛事'" :route="'match'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="p-title">创建赛事</div> |
||||||
|
<div class="page-content"> |
||||||
|
<el-form label-width="170px" label-suffix=":" size="small"> |
||||||
|
<el-form-item label="竞赛封面(选填)"> |
||||||
|
<el-upload class="avatar-uploader" accept=".jpg,.png,.jpeg,.gif" :on-remove="handleRemove" :on-error="uploadError" :on-success="uploadSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.fileupload" name="file" > |
||||||
|
<img v-if="coverUrl" :src="coverUrl" class="avatar"> |
||||||
|
<div class="uploader-default" v-else> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<p>上传封面</p> |
||||||
|
</div> |
||||||
|
<div slot="tip" class="el-upload__tip"> |
||||||
|
<p>展示宽度为220,高度140,JPG/PNG/GIF,3MB以内</p> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="竞赛封面长图(选填)"> |
||||||
|
<el-upload class="avatar-uploader avatar-uploader-lg" accept=".jpg,.png,.jpeg,.gif" :on-remove="handleLgRemove" :on-error="uploadError" :on-success="uploadLgSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.fileupload" name="file"> |
||||||
|
<img v-if="carouselUrl" :src="carouselUrl" class="avatar-lg"> |
||||||
|
<div class="uploader-default" v-else> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<p>上传封面</p> |
||||||
|
</div> |
||||||
|
<div slot="tip" class="el-upload__tip"> |
||||||
|
<p>展示宽度为1920,高度300,JPG/PNG/GIF,3MB以内</p> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="竞赛名称"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-input placeholder="请输入竞赛名称" v-model="name" clearable></el-input> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="主办方"> |
||||||
|
<div class="inline-input"> |
||||||
|
<div class="input-wrap" v-for="(item,index) in sponsorList" :key="index"> |
||||||
|
<el-input placeholder="主办方名称" v-model="sponsorList[index]"></el-input> |
||||||
|
<i v-if="sponsorList.length > 1" class="remove" @click="delSponsor(index)"></i> |
||||||
|
<button v-if="index == 0" class="add-btn" @click="addSponsor"> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<span>添加</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="承办方(选填)"> |
||||||
|
<div class="inline-input"> |
||||||
|
<div class="input-wrap" v-for="(item,index) in undertakerList" :key="index"> |
||||||
|
<el-input placeholder="承办方名称" v-model="undertakerList[index]"></el-input> |
||||||
|
<i v-if="undertakerList.length > 1" class="remove" @click="delOrganizer(index)"></i> |
||||||
|
<button v-if="index == 0" class="add-btn" @click="addOrganizer"> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<span>添加</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<button v-if="!undertakerList.length" class="add-btn" @click="addOrganizer"> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<span>添加</span> |
||||||
|
</button> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="报名时间"> |
||||||
|
<el-date-picker v-model="signupTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="pickerOptions"></el-date-picker> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="竞赛时间"> |
||||||
|
<el-date-picker v-model="playTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="pickerOptions"></el-date-picker> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="竞赛详情"> |
||||||
|
<quill :border="true" v-model="description" :height="400" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button size="small" v-throttle @click="save(1)">保存</el-button> |
||||||
|
<el-button type="primary" size="small" v-throttle @click="save(0)">发布</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import quill from '@/components/quill' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
id: '', |
||||||
|
coverUrl: '', |
||||||
|
carouselUrl: '', |
||||||
|
publishStatus: 0, |
||||||
|
userId: this.$store.state.userLoginId, |
||||||
|
username: this.$store.state.name, |
||||||
|
uploadList: [], |
||||||
|
uploadDataList: [], |
||||||
|
coverVisible: false, |
||||||
|
coverImageUrl: '', |
||||||
|
name: '', |
||||||
|
sponsor: '', |
||||||
|
sponsorList: [''], |
||||||
|
undertaker: '', |
||||||
|
undertakerList: [''], |
||||||
|
signUpStartTime: '', |
||||||
|
signUpEndTime: '', |
||||||
|
signupTime: '', |
||||||
|
playTime: '', |
||||||
|
playStartTime: '', |
||||||
|
playEndTime: '', |
||||||
|
description: '', |
||||||
|
pickerOptions: { |
||||||
|
disabledDate: time => { |
||||||
|
return time.getTime() < new Date().getTime() - 86400000 |
||||||
|
} |
||||||
|
}, |
||||||
|
submiting: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
quill, |
||||||
|
breadcrumb |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
signupTime: function(val){ |
||||||
|
if(val){ |
||||||
|
this.signUpStartTime = val[0] |
||||||
|
this.signUpEndTime = val[1] |
||||||
|
}else{ |
||||||
|
this.signUpStartTime = '' |
||||||
|
this.signUpEndTime = '' |
||||||
|
} |
||||||
|
}, |
||||||
|
playTime: function(val){ |
||||||
|
if(val){ |
||||||
|
this.playStartTime = val[0] |
||||||
|
this.playEndTime = val[1] |
||||||
|
}else{ |
||||||
|
this.playStartTime = '' |
||||||
|
this.playEndTime = '' |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.id = this.$route.query.id |
||||||
|
this.isDetail = Boolean(this.$route.query.show) |
||||||
|
this.id && this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
save(status) { |
||||||
|
if(this.submiting) return false |
||||||
|
this.sponsor = this.sponsorList.filter(d=>d).join() |
||||||
|
this.undertaker = this.undertakerList.filter(d=>d).join() |
||||||
|
if(!this.name) return this.warningMsg('请填写竞赛名称') |
||||||
|
if(status == 0){ |
||||||
|
if(!this.sponsor) return this.warningMsg('请填写主办方') |
||||||
|
if(!this.signUpStartTime) return this.warningMsg('请选择报名时间') |
||||||
|
} |
||||||
|
let now = new Date().getTime() |
||||||
|
let signUpStartTime = new Date(this.signUpStartTime).getTime() |
||||||
|
let signUpEndTime = new Date(this.signUpEndTime).getTime() |
||||||
|
let playStartTime = new Date(this.playStartTime).getTime() |
||||||
|
if(signUpStartTime && now > signUpStartTime) return this.warningMsg('报名时间不能早于当前时间') |
||||||
|
if(!this.playStartTime && status == 0) return this.warningMsg('请选择竞赛时间') |
||||||
|
if(playStartTime && playStartTime < signUpEndTime) return this.warningMsg('竞赛时间不能早于报名结束时间') |
||||||
|
if(!this.description && status == 0) return this.warningMsg('请填写竞赛详情') |
||||||
|
|
||||||
|
let data = { |
||||||
|
id: this.id, |
||||||
|
coverUrl: this.coverUrl, |
||||||
|
carouselUrl: this.carouselUrl, |
||||||
|
description: this.description, |
||||||
|
founderId: 1, |
||||||
|
founderName: this.username, |
||||||
|
name: this.name, |
||||||
|
playEndTime: this.playEndTime, |
||||||
|
playStartTime: this.playStartTime, |
||||||
|
publishStatus: status, |
||||||
|
signUpEndTime: this.signUpEndTime, |
||||||
|
signUpStartTime: this.signUpStartTime, |
||||||
|
sponsor: this.sponsor, |
||||||
|
undertaker: this.undertaker |
||||||
|
} |
||||||
|
this.submiting = true |
||||||
|
|
||||||
|
if(this.id){ |
||||||
|
this.$put(this.api.editContest, data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.$router.back() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
this.submiting = false |
||||||
|
}); |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addContest, data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
this.successMsg('创建成功'); |
||||||
|
this.$router.back() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
this.submiting = false |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
getData() { |
||||||
|
this.$get(this.api.getContest + this.id) |
||||||
|
.then(res => { |
||||||
|
if(res.errmessage == 'success'){ |
||||||
|
let info = res.ExperimentalTeaching |
||||||
|
this.coverUrl = info.coverUrl |
||||||
|
this.description = info.description |
||||||
|
this.name = info.name |
||||||
|
|
||||||
|
this.signupTime = [info.signUpStartTime,info.signUpEndTime] |
||||||
|
this.playTime = [info.playStartTime,info.playEndTime] |
||||||
|
}else{ |
||||||
|
this.errorMsg('查询失败'); |
||||||
|
} |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
|
||||||
|
}); |
||||||
|
}, |
||||||
|
handleExceed(files, fileList) { |
||||||
|
this.warningMsg( |
||||||
|
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||||
|
); |
||||||
|
}, |
||||||
|
uploadSuccess(res, file, fileList) { |
||||||
|
if(this.coverUrl){ |
||||||
|
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {}).catch(res => {}); |
||||||
|
} |
||||||
|
this.coverUrl = res.data.filesResult.fileUrl |
||||||
|
}, |
||||||
|
uploadLgSuccess(res, file, fileList) { |
||||||
|
if(this.carouselUrl){ |
||||||
|
let fileName = this.carouselUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {}).catch(res => {}); |
||||||
|
} |
||||||
|
this.carouselUrl = res.data.filesResult.fileUrl |
||||||
|
}, |
||||||
|
uploadError(err, file, fileList) { |
||||||
|
this.$message({ |
||||||
|
message: "上传出错,请重试!", |
||||||
|
type: "error", |
||||||
|
center: true |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeRemove(file, fileList) { |
||||||
|
return this.$confirm(`确定移除 ${file.name}?`); |
||||||
|
}, |
||||||
|
handleRemove(file, fileList) { |
||||||
|
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||||
|
this.coverUrl = '' |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
handleLgRemove(file, fileList) { |
||||||
|
let fileName = this.carouselUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||||
|
this.carouselUrl = '' |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
uploadSure(){ |
||||||
|
this.BatchUpload = false |
||||||
|
this.pageNo = 1 |
||||||
|
this.keyword = '' |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
goback() { |
||||||
|
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$router.back() |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
addSponsor(){ |
||||||
|
this.sponsorList.push('') |
||||||
|
}, |
||||||
|
delSponsor(index){ |
||||||
|
this.sponsorList.splice(index,1) |
||||||
|
}, |
||||||
|
addOrganizer(){ |
||||||
|
this.undertakerList.push('') |
||||||
|
}, |
||||||
|
delOrganizer(index){ |
||||||
|
this.undertakerList.splice(index,1) |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
$upload-width: 220px; |
||||||
|
$upload-height: 140px; |
||||||
|
$upload-lg-height: 150px; |
||||||
|
/deep/.avatar-uploader{ |
||||||
|
.el-upload { |
||||||
|
position: relative; |
||||||
|
width: $upload-width; |
||||||
|
height: $upload-height; |
||||||
|
border: 1px dashed #d9d9d9; |
||||||
|
border-radius: 6px; |
||||||
|
cursor: pointer; |
||||||
|
overflow: hidden; |
||||||
|
&:hover { |
||||||
|
border-color: #cb221c; |
||||||
|
} |
||||||
|
.uploader-default{ |
||||||
|
display: flex; |
||||||
|
height: $upload-height; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
text-align: center; |
||||||
|
background: rgba(0, 0, 0, 0.04); |
||||||
|
i{ |
||||||
|
font-size: 20px; |
||||||
|
font-weight: bold; |
||||||
|
color: #8c939d; |
||||||
|
} |
||||||
|
p{ |
||||||
|
margin-top: 10px; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.avatar-uploader-lg{ |
||||||
|
.el-upload { |
||||||
|
width: 100%; |
||||||
|
max-width: 960px; |
||||||
|
height: $upload-lg-height; |
||||||
|
.uploader-default{ |
||||||
|
height: $upload-lg-height; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.avatar { |
||||||
|
display: block; |
||||||
|
width: $upload-width; |
||||||
|
height: $upload-height; |
||||||
|
} |
||||||
|
.avatar-lg { |
||||||
|
display: block; |
||||||
|
width: 100%; |
||||||
|
height: $upload-lg-height; |
||||||
|
} |
||||||
|
.el-upload__tip{ |
||||||
|
margin-top: 0; |
||||||
|
p{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.45); |
||||||
|
line-height: 1; |
||||||
|
&:first-child{ |
||||||
|
margin-bottom: 5px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/deep/.d-inline-block{ |
||||||
|
width: 216px; |
||||||
|
.el-select,.el-input{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
.inline-input{ |
||||||
|
.input-wrap{ |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 10px; |
||||||
|
|
||||||
|
.el-input{ |
||||||
|
display: inline-block; |
||||||
|
width: 216px; |
||||||
|
margin-right: 8px; |
||||||
|
} |
||||||
|
.remove{ |
||||||
|
width: 16px; |
||||||
|
height: 16px; |
||||||
|
background: url(../assets/img/close.png) 0 0/cover no-repeat; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
.add-btn{ |
||||||
|
margin-left: 32px; |
||||||
|
} |
||||||
|
} |
||||||
|
.add-btn{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
width: 216px; |
||||||
|
line-height: 32px; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
background-color: transparent; |
||||||
|
border: 1px dashed rgba(0, 0, 0, 0.15); |
||||||
|
border-radius: 4px; |
||||||
|
cursor: pointer; |
||||||
|
i{ |
||||||
|
margin-right: 8px; |
||||||
|
font-size: 14px; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,114 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'实验系统后台'"></breadcrumb> |
||||||
|
<ul class="list"> |
||||||
|
<li :class="{active: active == 1}" @click="toSystem(1)"> |
||||||
|
<img src="../assets/img/station1.png" alt=""> |
||||||
|
<p class="name">运营与管理</p> |
||||||
|
<p class="text">电竞赛事运营与管理仿真实训系统</p> |
||||||
|
</li> |
||||||
|
<li :class="{active: active == 2}" @click="toSystem(2)"> |
||||||
|
<img src="../assets/img/station2.png" alt=""> |
||||||
|
<p class="name">编导</p> |
||||||
|
<p class="text">电竞赛事编导仿真实训系统</p> |
||||||
|
</li> |
||||||
|
<li :class="{active: active == 3}" @click="toSystem(3)"> |
||||||
|
<img src="../assets/img/station3.png" alt=""> |
||||||
|
<p class="name">主持与解说</p> |
||||||
|
<p class="text">电竞赛事主持与解说仿真实训系统</p> |
||||||
|
</li> |
||||||
|
<li :class="{active: active == 4}" @click="toSystem(4)"> |
||||||
|
<img src="../assets/img/station4.png" alt=""> |
||||||
|
<p class="name">数据分析</p> |
||||||
|
<p class="text">电竞数据分析仿真实训系统</p> |
||||||
|
</li> |
||||||
|
<li :class="{active: active == 5}" @click="toSystem(5)"> |
||||||
|
<img src="../assets/img/station5.png" alt=""> |
||||||
|
<p class="name">品牌与运营</p> |
||||||
|
<p class="text">电竞品牌运营与管理仿真实训系统</p> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import bus from '@/libs/bus' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
name: 'dashboard', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
active: 0 |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: {breadcrumb}, |
||||||
|
mounted() { |
||||||
|
bus.$emit('setBg','backstage') |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
toSystem(index){ |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.list{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
height: calc(100vh - 165px); |
||||||
|
background-color: #fff; |
||||||
|
|
||||||
|
li{ |
||||||
|
margin: 0 20px; |
||||||
|
cursor: pointer; |
||||||
|
&:nth-child(even){ |
||||||
|
margin-top: 200px; |
||||||
|
} |
||||||
|
|
||||||
|
.name{ |
||||||
|
margin: 10px 0 0; |
||||||
|
line-height: 1; |
||||||
|
font-size: 36px; |
||||||
|
color: #000; |
||||||
|
font-family: youshe; |
||||||
|
} |
||||||
|
.text{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
transition: .2s; |
||||||
|
} |
||||||
|
img{ |
||||||
|
max-width: 232px; |
||||||
|
border: 3px solid transparent; |
||||||
|
transition: .2s; |
||||||
|
} |
||||||
|
&:hover{ |
||||||
|
img{ |
||||||
|
border-color: #CC221C; |
||||||
|
} |
||||||
|
.name,.text{ |
||||||
|
color: #CC221C; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
@media(max-width: 1630px){ |
||||||
|
.list{ |
||||||
|
li{ |
||||||
|
margin: 0 10px; |
||||||
|
.name{ |
||||||
|
font-size: 30px; |
||||||
|
} |
||||||
|
.text{ |
||||||
|
font-size: 12px; |
||||||
|
} |
||||||
|
img{ |
||||||
|
max-width: 160px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,156 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="tool"> |
||||||
|
<ul class="filter"> |
||||||
|
|
||||||
|
</ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" round @click="addClass" v-auth="'course:分类管理:新增'">新增</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<el-table :data="classificationList" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||||
|
<el-table-column type="index" width="100" label="序号" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="课程分类名称"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="300"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="editClass(scope.row)" v-auth="'course:分类管理:修改'">修改</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'course:分类管理:修改'"></el-divider> |
||||||
|
<el-button type="text" @click="handleDelete(scope.row)" v-auth="'course:分类管理:删除'">删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
|
||||||
|
<el-dialog :title="isAddclass ? '添加分类' : '编辑分类'" :visible.sync="classVisible" width="400px" :close-on-click-modal="false" @close="closeColumn"> |
||||||
|
<el-form> |
||||||
|
<el-form-item> |
||||||
|
<el-input placeholder="分类名称" v-model="className"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="classVisible = false">取 消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="classSubmit">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'classification', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
classificationList: [], |
||||||
|
multipleSelection: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
isAddclass: true, |
||||||
|
classVisible: false, |
||||||
|
curRow: {}, |
||||||
|
className: '' |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
this.$get(this.api.queryAllClassification).then(res => { |
||||||
|
this.classificationList = res.data.classificationList |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
addCourse(){ |
||||||
|
this.$router.push('/addcourse') |
||||||
|
}, |
||||||
|
editCourse(row){ |
||||||
|
this.$router.push(`/addcourse?id=${row.id}`) |
||||||
|
}, |
||||||
|
handleDelete(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteClassification}/${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
getRowKeys(row) { |
||||||
|
return row.customerId; |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
closeColumn(){ |
||||||
|
this.className = '' |
||||||
|
this.curRow = {} |
||||||
|
}, |
||||||
|
delAllData() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
// 批量删除 |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
let data = delList.join() |
||||||
|
this.$del(this.api.deleteClassification,data).then(res => { |
||||||
|
this.multipleSelection = []; |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}).catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !'); |
||||||
|
} |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
addClass(){ |
||||||
|
this.isAddClass = true |
||||||
|
this.classVisible = true |
||||||
|
}, |
||||||
|
editClass(row){ |
||||||
|
this.curRow = row |
||||||
|
this.className = row.name |
||||||
|
this.isAddClass = false |
||||||
|
this.classVisible = true |
||||||
|
}, |
||||||
|
classSubmit(){ |
||||||
|
if(!this.className) return this.warningMsg('请填写分类名称') |
||||||
|
let data = { |
||||||
|
name: this.className, |
||||||
|
} |
||||||
|
if(this.curRow.id){ |
||||||
|
data.id = this.curRow.id |
||||||
|
this.$put(this.api.editClassification,data).then(res => { |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.classVisible = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
this.$post(`${this.api.addClassification}/${this.className}?distinguish=1`).then(res => { |
||||||
|
this.successMsg('添加成功'); |
||||||
|
this.classVisible = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
} |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,204 @@ |
|||||||
|
<template> |
||||||
|
<div class="box"> |
||||||
|
<breadcrumb :data="'官方资讯管理/栏目内容管理'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="tabs"> |
||||||
|
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == activeName}" @click="tabChange(index)">{{item}}</a> |
||||||
|
</div> |
||||||
|
<div class="btn-wrap"> |
||||||
|
<el-button class="action-btn" type="primary" size="small" @click="sortSubmit" v-auth="'content:保存排序'">保存排序</el-button> |
||||||
|
<el-button class="action-btn" type="primary" size="small" @click="delAllData" v-auth="'content:批量删除'">批量删除</el-button> |
||||||
|
<el-button class="action-btn" type="primary" size="small" @click="addArticle" v-auth="'content:新增文章'">新增文章</el-button> |
||||||
|
</div> |
||||||
|
<div class="page-content"> |
||||||
|
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||||
|
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||||
|
<el-table-column type="index" width="60" label="序号" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="title" label="标题"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="排序值" width="80" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-input size="small" class="sort-input" width="120" min="1" v-model.number="scope.row.sort" type="number" v-auth="'content:保存排序'"></el-input> |
||||||
|
<span>{{scope.row.sort}}</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="date" label="添加日期" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{transferDate(scope.row.date)}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="170"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="editArticle(scope)" v-auth="'content:编辑'">编辑</el-button> |
||||||
|
<el-divider direction="vertical"></el-divider> |
||||||
|
<el-button type="text" @click="delData(scope.row)" v-auth="'content:删除'">删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="文章发布状态" width="120" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-switch |
||||||
|
class="off" |
||||||
|
v-model="scope.row.status" |
||||||
|
:active-value="0" |
||||||
|
:inactive-value="1" |
||||||
|
style="margin: 0 5px" |
||||||
|
:active-text="scope.row.status ? '关' : '开'" |
||||||
|
@change="switchOff($event,scope.row,scope.$index)" |
||||||
|
v-auth="'content:禁用'" |
||||||
|
></el-switch> |
||||||
|
<span>{{scope.row.status ? '禁用' : '启用'}}</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
activeName: 'first', |
||||||
|
tabs: { |
||||||
|
first: '栏目内容管理' |
||||||
|
}, |
||||||
|
name: this.$store.state.name, |
||||||
|
listData: [], |
||||||
|
multipleSelection: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0, |
||||||
|
columnId: this.$route.query.id |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { breadcrumb }, |
||||||
|
watch: { |
||||||
|
$route(){ |
||||||
|
this.columnId = this.$route.query.id |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData(id){ |
||||||
|
let data = { |
||||||
|
columnId: this.columnId |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryArticleByCondition}/${this.pageNo}/${this.pageSize}`,data).then(res => { |
||||||
|
this.listData = res.data.articleList |
||||||
|
this.totals = res.data.total |
||||||
|
if(!this.listData.length && this.totals){ |
||||||
|
this.pageNo-- |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
addArticle(){ |
||||||
|
this.$router.push(`/addarticle?columnId=${this.columnId}&sort=${this.listData.length+1}`) |
||||||
|
}, |
||||||
|
editArticle(scope){ |
||||||
|
this.$router.push(`/addarticle?columnId=${this.columnId}&id=${scope.row.id}&sort=${scope.$index+1}`) |
||||||
|
}, |
||||||
|
delData(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteArticles}?articleIds=${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
transferDate(date){ |
||||||
|
return date.replace(' 00:00:00','') |
||||||
|
}, |
||||||
|
delAllData() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
|
||||||
|
let title = newArr[0].title |
||||||
|
if(title.length > 14){ |
||||||
|
title = title.substr(0,14) + '……' |
||||||
|
} |
||||||
|
this.$confirm(`此批量删除操作不可逆,是否确认删除${title}等${newArr.length}个选中项?`, '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteArticles}?articleIds=${delList.join(',')}`).then(res => { |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}) |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !') |
||||||
|
} |
||||||
|
}, |
||||||
|
switchOff(val,row,index) { |
||||||
|
this.$put(`${this.api.enableArticle}/${row.id}/${val}`) |
||||||
|
.then(res => { |
||||||
|
val == 1 ? this.warningMsg('该文章已隐藏,对学生端用户不可见') : this.successMsg('该文章已发布,对学生端用户可见') |
||||||
|
}) |
||||||
|
.catch(err => {}) |
||||||
|
}, |
||||||
|
sortSubmit(){ |
||||||
|
if(this.listData.length){ |
||||||
|
if(this.listData.find(n => n.sort < 1)) return this.errorMsg('排序值最小为1') |
||||||
|
let data = {articleList: this.listData} |
||||||
|
this.$post(this.api.articleSort, data).then(res => { |
||||||
|
this.successMsg('保存成功') |
||||||
|
this.getContent(this.columnId) |
||||||
|
}) |
||||||
|
.catch(err => {}) |
||||||
|
}else{ |
||||||
|
this.errorMsg('数据为空') |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.btn-wrap{ |
||||||
|
position: absolute; |
||||||
|
top: 15px; |
||||||
|
right: 15px; |
||||||
|
} |
||||||
|
.sort-input{ |
||||||
|
/deep/.el-input__inner{ |
||||||
|
padding: 0 0 0 10px; |
||||||
|
} |
||||||
|
} |
||||||
|
.sort-input+span{ |
||||||
|
display: none; |
||||||
|
} |
||||||
|
.off+span{ |
||||||
|
display: none; |
||||||
|
} |
||||||
|
</style> |
||||||
|
|
@ -0,0 +1,58 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'课程资源管理/' + tabs[active]" ref="breadcrumb"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="tabs"> |
||||||
|
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a> |
||||||
|
</div> |
||||||
|
<div class="page-content"> |
||||||
|
<courselist v-if="active == 'first'"></courselist> |
||||||
|
<classification v-else></classification> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Setting from '@/setting'; |
||||||
|
import courselist from './courseList.vue'; |
||||||
|
import classification from './classification.vue'; |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
name: 'course', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
active: 'first', |
||||||
|
tabs: { |
||||||
|
first: '课程管理', |
||||||
|
second: '分类管理' |
||||||
|
}, |
||||||
|
showTabs: true |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: {courselist,classification,breadcrumb}, |
||||||
|
mounted() { |
||||||
|
Setting.dynamicRoute && this.initTabs() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
tabChange(index){ |
||||||
|
this.active = index |
||||||
|
this.$refs.breadcrumb.update('课程资源管理/' + this.tabs[this.active]) |
||||||
|
}, |
||||||
|
initTabs(){ |
||||||
|
let btnPermissions = this.$store.state.btnPermissions |
||||||
|
let showStaff = btnPermissions.includes('课程资源管理:课程管理') |
||||||
|
let showRole = btnPermissions.includes('课程资源管理:分类管理') |
||||||
|
|
||||||
|
if(!showStaff || !showRole){ |
||||||
|
this.showTabs = false |
||||||
|
} |
||||||
|
!showStaff && showRole && (this.active = 'second') |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,705 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'课程资源管理/内容设置'" :route="'course'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="relative"> |
||||||
|
<div class="p-title">内容设置</div> |
||||||
|
<div class="btns"> |
||||||
|
<template v-if="!sorting"> |
||||||
|
<el-button type="primary" size="small" round v-throttle @click="addChapter">添加章节</el-button> |
||||||
|
<el-button type="primary" size="small" round v-throttle @click="sort">编辑顺序</el-button> |
||||||
|
</template> |
||||||
|
<template v-else> |
||||||
|
<el-button type="primary" size="small" round v-throttle @click="cancelSort">取消</el-button> |
||||||
|
<el-button type="primary" size="small" round v-throttle @click="saveSort">保存</el-button> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="page-content"> |
||||||
|
<div class="m-b-20" v-for="(chapter,index) in chapters" :key="chapter.id"> |
||||||
|
<div class="flex j-between a-center m-b-10"> |
||||||
|
<div>{{chapter.name}}</div> |
||||||
|
<div> |
||||||
|
<template v-if="!sorting"> |
||||||
|
<el-button class="action-btn" type="primary" size="small" round v-throttle @click="editChapter(chapter)">修改章节名称</el-button> |
||||||
|
<el-button class="action-btn" type="primary" size="small" round v-throttle @click="addSection(chapter.id)">添加小节</el-button> |
||||||
|
<el-button class="action-btn" type="primary" size="small" round v-throttle @click="delChapter(chapter.id)">删除</el-button> |
||||||
|
</template> |
||||||
|
<template v-else> |
||||||
|
<i class="el-icon-top sort-icon" :class="{disabled: index == 0}" style="margin-right: 5px" @click="sortChapter(chapter,'up',index == 0,index)"></i> |
||||||
|
<i class="el-icon-bottom sort-icon" :class="{disabled: index == chapters.length-1}" @click="sortChapter(chapter,'down',index == chapter.length-1,index)"></i> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table :data="chapter.subsectionList" class="table" stripe header-align="center"> |
||||||
|
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> |
||||||
|
<el-table-column prop="name" label="资源名称"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="fileType" label="资源类型" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{transferType(scope.row.fileType)}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="300"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<template v-if="!sorting"> |
||||||
|
<el-button type="text" @click="preview(scope.row)">查看</el-button> |
||||||
|
<el-button type="text" @click="delSection(scope.row)">删除</el-button> |
||||||
|
<el-button type="text" @click="editSectionName(scope.row,chapter.id)">修改小节名称</el-button> |
||||||
|
<el-button type="text" @click="switchFile(scope.row,chapter.id)">更换文件</el-button> |
||||||
|
</template> |
||||||
|
<template v-else> |
||||||
|
<i class="el-icon-top sort-icon" :class="{disabled: scope.$index == 0}" style="margin-right: 5px" @click="sortSection(index,'up',scope.$index == 0,scope.$index)"></i> |
||||||
|
<i class="el-icon-bottom sort-icon" :class="{disabled: scope.$index == chapter.subsectionList.length-1}" @click="sortSection(index,'down',scope.$index == chapter.subsectionList.length-1,scope.$index)"></i> |
||||||
|
</template> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog :title="chapterId ? '编辑章节' : '新增章节'" :visible.sync="chapterVisible" width="24%" :close-on-click-modal="false"> |
||||||
|
<el-form> |
||||||
|
<el-form-item> |
||||||
|
<el-input placeholder="请输入章节名称,便于对小节归类" v-model="chapterName" maxlength="50"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="chapterVisible = false">取消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="chapterSubmit">确定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog title="添加小节" :visible.sync="sectionVisible" width="24%" @close="closeSection" :close-on-click-modal="false"> |
||||||
|
<el-form label-width="80px"> |
||||||
|
<el-form-item label="资源添加"> |
||||||
|
<el-upload |
||||||
|
:before-upload="beforeUpload" |
||||||
|
:on-remove="handleRemove" |
||||||
|
:on-error="uploadError" |
||||||
|
:on-success="uploadSuccess" |
||||||
|
:before-remove="beforeRemove" |
||||||
|
:limit="1" |
||||||
|
:on-exceed="handleExceed" |
||||||
|
:action="this.api.fileupload" |
||||||
|
:file-list="uploadList" |
||||||
|
name="file" |
||||||
|
> |
||||||
|
<el-button size="small"><img src="../assets/img/upload.png" alt=""> 上传资源</el-button> |
||||||
|
</el-upload> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="小节名称"> |
||||||
|
<el-input placeholder="请输入小节名称" v-model="sectionName" maxlength="50"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="sectionVisible = false">取消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="sectionSubmit">确定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog title="更换文件" :visible.sync="switchVisible" width="28%" :close-on-click-modal="false" @close="closeSwitch"> |
||||||
|
<div style="text-align: center"> |
||||||
|
<el-upload |
||||||
|
:before-upload="beforeUpload" |
||||||
|
:on-remove="handleRemove" |
||||||
|
:on-error="uploadError" |
||||||
|
:on-success="uploadSuccess" |
||||||
|
:before-remove="beforeRemove" |
||||||
|
:limit="1" |
||||||
|
:on-exceed="handleExceed" |
||||||
|
:action="this.api.fileupload" |
||||||
|
:file-list="uploadList" |
||||||
|
name="file" |
||||||
|
> |
||||||
|
<el-button size="small"><img src="../assets/img/upload.png" alt=""> 上传资源</el-button> |
||||||
|
</el-upload> |
||||||
|
</div> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="switchVisible = false">取消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="switchSubmit">确定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog title="修改小节名称" :visible.sync="sectionNameVisible" width="24%" :close-on-click-modal="false"> |
||||||
|
<el-form> |
||||||
|
<el-form-item> |
||||||
|
<el-input placeholder="请输入小节名称" v-model="sectionName" maxlength="50"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="sectionNameVisible = false">取消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="sectionNameSubmit">确定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<div v-show="previewImg" class="el-image-viewer__wrapper" :class="{active: previewImg}" style="z-index: 2000"> |
||||||
|
<div class="el-image-viewer__mask"></div> |
||||||
|
<span class="el-image-viewer__btn el-image-viewer__close" @click="previewImg = ''"><i class="el-icon-circle-close" style="color: #fff"></i></span> |
||||||
|
<div class="el-image-viewer__canvas"> |
||||||
|
<img :src="previewImg" class="el-image-viewer__img" style="transform: scale(1) rotate(0deg);margin-top: -1px; max-height: 100%; max-width: 100%;"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div v-show="iframeSrc" class="el-image-viewer__wrapper" :class="{active: iframeSrc}" style="z-index: 2000"> |
||||||
|
<div class="el-image-viewer__mask"></div> |
||||||
|
<span class="el-image-viewer__btn el-image-viewer__close" :class="{'doc-close': isWord}" :style="{top: isWord ? '50px' : '5px'}" @click="closeIframe"><i class="el-icon-circle-close" style="color: #fff"></i></span> |
||||||
|
<div class="el-image-viewer__canvas"> |
||||||
|
<iframe v-if="iframeSrc" class="fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe> |
||||||
|
<template v-if="showMask"> |
||||||
|
<div class="mask" style="width: 200px;height: 30px;top: 53px;right: 320px"></div> |
||||||
|
<div class="mask" style="width: 175px;height: 30px;top: 53px;right: 5px"></div> |
||||||
|
</template> |
||||||
|
<template v-if="showMask1"> |
||||||
|
<div class="word-mask1" style="width: 200px;height: 50px;"></div> |
||||||
|
<div class="word-mask" style="height: 40px;top: 48px;"></div> |
||||||
|
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div> |
||||||
|
</template> |
||||||
|
<template v-if="showMask2 && iframeSrc"> |
||||||
|
<div class="excel-mask1" style="height: 48px;"></div> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div v-show="playAuth" class="el-image-viewer__wrapper" :class="{active: playAuth}" style="z-index: 2000"> |
||||||
|
<div class="el-image-viewer__mask"></div> |
||||||
|
<span class="el-image-viewer__btn el-image-viewer__close" @click="closePlayer"><i class="el-icon-circle-close" style="color: #fff"></i></span> |
||||||
|
<div class="player" id="player"></div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<pdf :visible.sync="pdfVisible" :src.sync="pdfSrc"></pdf> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import { Loading } from 'element-ui'; |
||||||
|
import pdf from '@/components/pdf' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
id: '', |
||||||
|
userId: this.$store.state.userLoginId, |
||||||
|
chapters: [], |
||||||
|
sorting: false, |
||||||
|
uploading: false, |
||||||
|
uploadList: [], |
||||||
|
chapterVisible: false, |
||||||
|
chapterId: '', |
||||||
|
chapterName: '', |
||||||
|
sectionVisible: false, |
||||||
|
sectionName: '', |
||||||
|
sectionId: '', |
||||||
|
switchVisible: false, |
||||||
|
sectionNameVisible: false, |
||||||
|
fileId: '', |
||||||
|
fileName: '', |
||||||
|
fileUrl: '', |
||||||
|
originalFileName: '', |
||||||
|
fileType: '', |
||||||
|
playAuth: '', |
||||||
|
player: null, |
||||||
|
previewImg: '', |
||||||
|
iframeSrc: '', |
||||||
|
curFile: {}, |
||||||
|
isAddSection: false, |
||||||
|
isWord: false, |
||||||
|
isPPT: false, |
||||||
|
isExcel: false, |
||||||
|
showMask: false, |
||||||
|
showMask1: false, |
||||||
|
showMask2: false, |
||||||
|
loadIns: null, |
||||||
|
pdfVisible: false, |
||||||
|
pdfSrc: '', |
||||||
|
previewing: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { pdf,breadcrumb }, |
||||||
|
mounted() { |
||||||
|
this.insertScript() |
||||||
|
this.id = this.$route.query.id |
||||||
|
this.id && this.getData() |
||||||
|
if (window.history && window.history.pushState) { |
||||||
|
history.pushState(null, null, document.URL); |
||||||
|
window.addEventListener("popstate", this.goBack, false); |
||||||
|
} |
||||||
|
}, |
||||||
|
destroyed() { |
||||||
|
window.removeEventListener("popstate", this.goBack, false); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
this.$get(`${this.api.queryChaptersAndSubsections}/${this.id}`) |
||||||
|
.then(res => { |
||||||
|
this.chapters = res.data.chapterList |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
|
||||||
|
}); |
||||||
|
}, |
||||||
|
goBack(){ |
||||||
|
if(this.previewing){ |
||||||
|
this.closeIframe() |
||||||
|
}else{ |
||||||
|
history.back() |
||||||
|
} |
||||||
|
}, |
||||||
|
iframeOnload(){ |
||||||
|
document.querySelector('#fileIframe').onload = e => { |
||||||
|
if(this.isPPT){ |
||||||
|
this.showMask = true |
||||||
|
}else{ |
||||||
|
this.showMask = false |
||||||
|
} |
||||||
|
if(this.isWord){ |
||||||
|
this.showMask1 = true |
||||||
|
}else{ |
||||||
|
this.showMask1 = false |
||||||
|
} |
||||||
|
if(this.isExcel){ |
||||||
|
this.showMask2 = true |
||||||
|
}else{ |
||||||
|
this.showMask2 = false |
||||||
|
} |
||||||
|
this.loadIns.close() |
||||||
|
} |
||||||
|
}, |
||||||
|
insertScript(){ |
||||||
|
const linkTag = document.createElement('link'); |
||||||
|
linkTag.rel = 'stylesheet'; |
||||||
|
linkTag.href = 'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css'; |
||||||
|
document.body.appendChild(linkTag); |
||||||
|
|
||||||
|
const scriptTag = document.createElement('script'); |
||||||
|
scriptTag.type = 'text/javascript'; |
||||||
|
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'; |
||||||
|
document.body.appendChild(scriptTag); |
||||||
|
}, |
||||||
|
// 上传文件 |
||||||
|
beforeUpload(file){ |
||||||
|
let type = this.transferType(file.name.substring(file.name.lastIndexOf('.') + 1)) |
||||||
|
if(type != '视频' && type != '图片' && type != 'pdf' && (file.size / 1024 / 1024) > 10){ |
||||||
|
this.errorMsg('请上传10M以内的文件') |
||||||
|
return false |
||||||
|
} |
||||||
|
this.uploading = true |
||||||
|
this.originalFileName = file.name |
||||||
|
if(this.isAddSection) this.sectionName = file.name.substring(0,file.name.lastIndexOf(".")) |
||||||
|
this.fileType = file.name.substring(file.name.lastIndexOf('.')+1) |
||||||
|
}, |
||||||
|
handleExceed(files, fileList) { |
||||||
|
this.warningMsg( |
||||||
|
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||||
|
); |
||||||
|
}, |
||||||
|
uploadSuccess(res, file, fileList) { |
||||||
|
this.uploading = false |
||||||
|
this.fileId = res.data.filesResult.fileId |
||||||
|
this.fileType = res.data.filesResult.fileType |
||||||
|
this.fileUrl = res.data.filesResult.fileUrl |
||||||
|
this.fileName = res.data.filesResult.ossFileName |
||||||
|
}, |
||||||
|
uploadError(err, file, fileList) { |
||||||
|
this.$message({ |
||||||
|
message: "上传出错,请重试!", |
||||||
|
type: "error", |
||||||
|
center: true |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeRemove(file, fileList) { |
||||||
|
if((file.size / 1024 / 1024) < 10){ |
||||||
|
return this.$confirm(`确定移除 ${file.name}?`); |
||||||
|
} |
||||||
|
}, |
||||||
|
handleRemove(file, fileList) { |
||||||
|
this.uploadList = fileList |
||||||
|
}, |
||||||
|
uploadSure(){ |
||||||
|
this.importVisible = false |
||||||
|
this.pageNo = 1 |
||||||
|
this.staffGradeId = '' |
||||||
|
this.keyword = '' |
||||||
|
this.getTeacher() |
||||||
|
}, |
||||||
|
goback() { |
||||||
|
this.$router.push('course') |
||||||
|
}, |
||||||
|
transferType(ext){ |
||||||
|
if('jpg,jpeg,png,gif,svg,psd'.includes(ext)) return '图片' |
||||||
|
if('mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv'.includes(ext)) return '视频' |
||||||
|
return ext |
||||||
|
}, |
||||||
|
addChapter(){ |
||||||
|
this.chapterName = '' |
||||||
|
this.chapterId = '' |
||||||
|
this.chapterVisible = true |
||||||
|
}, |
||||||
|
sort(){ |
||||||
|
this.sorting = true |
||||||
|
}, |
||||||
|
cancelSort(){ |
||||||
|
this.sorting = false |
||||||
|
}, |
||||||
|
saveSort(){ |
||||||
|
this.chapters.forEach((n,k) => { |
||||||
|
n.sort = k+1 |
||||||
|
n.subsectionList.forEach((j,i) => { |
||||||
|
j.sort = i+1 |
||||||
|
}) |
||||||
|
}) |
||||||
|
let data = { |
||||||
|
chapterVOList: this.chapters |
||||||
|
} |
||||||
|
this.$post(this.api.reorder,data).then(res => { |
||||||
|
this.sorting = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
editChapter(item){ |
||||||
|
this.chapterId = item.id |
||||||
|
this.chapterName = item.name |
||||||
|
this.chapterVisible = true |
||||||
|
}, |
||||||
|
delChapter(id){ |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteChapter}/${id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
closeSection(){ |
||||||
|
this.isAddSection = false |
||||||
|
}, |
||||||
|
addSection(id){ |
||||||
|
this.chapterId = id |
||||||
|
this.sectionName = '' |
||||||
|
this.fileUrl = '' |
||||||
|
this.uploadList = [] |
||||||
|
this.sectionId = '' |
||||||
|
this.isAddSection = true |
||||||
|
this.sectionVisible = true |
||||||
|
}, |
||||||
|
chapterSubmit(){ |
||||||
|
if(!this.chapterName) return this.warningMsg('请填写章节名称') |
||||||
|
let data = { |
||||||
|
courseId: this.id, |
||||||
|
name: this.chapterName |
||||||
|
} |
||||||
|
if(this.chapterId){ |
||||||
|
data.id = this.chapterId |
||||||
|
this.$put(this.api.editChapter, data).then(res => { |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.chapterVisible = false |
||||||
|
this.getData() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addChapter, data).then(res => { |
||||||
|
this.successMsg('添加成功'); |
||||||
|
this.chapterVisible = false |
||||||
|
this.getData() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
sectionSubmit(){ |
||||||
|
if(!this.sectionName) return this.warningMsg('请填写小节名称') |
||||||
|
if(this.uploading) return this.warningMsg('资源正在上传中,请稍候') |
||||||
|
if(!this.fileUrl && !this.fileId) return this.warningMsg('请上传资源') |
||||||
|
let data = { |
||||||
|
id: this.sectionId, |
||||||
|
courseId: this.id, |
||||||
|
chapterId: this.chapterId, |
||||||
|
name: this.sectionName, |
||||||
|
fileId: this.fileId, |
||||||
|
fileUrl: this.fileUrl, |
||||||
|
fileName: this.fileName, |
||||||
|
fileType: this.fileType, |
||||||
|
originalFileName: this.originalFileName |
||||||
|
} |
||||||
|
this.$post(this.api.addSubsection, data).then(res => { |
||||||
|
this.successMsg('添加成功'); |
||||||
|
this.sectionVisible = false |
||||||
|
this.getData() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
}, |
||||||
|
closeSwitch(){ |
||||||
|
this.fileId = '' |
||||||
|
this.fileName = '' |
||||||
|
this.fileType = '' |
||||||
|
this.fileUrl = '' |
||||||
|
this.sectionId = '' |
||||||
|
}, |
||||||
|
preview(row){ |
||||||
|
if(this.transferType(row.fileType) == '视频'){ |
||||||
|
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => { |
||||||
|
this.playAuth = res.data.playAuth |
||||||
|
if(this.player){ |
||||||
|
this.player.replayByVidAndPlayAuth(row.fileId,this.playAuth) |
||||||
|
}else{ |
||||||
|
this.player = new Aliplayer({ |
||||||
|
id: 'player', |
||||||
|
width: '100%', |
||||||
|
autoplay: false, |
||||||
|
vid : row.fileId, |
||||||
|
playauth : this.playAuth, |
||||||
|
encryptType:1, //当播放私有加密流时需要设置。 |
||||||
|
}) |
||||||
|
} |
||||||
|
}).catch(res => {}) |
||||||
|
}else if(this.transferType(row.fileType) == '图片'){ |
||||||
|
this.previewImg = row.fileUrl |
||||||
|
}else if(row.fileType == 'pdf'){ |
||||||
|
this.pdfSrc = row.fileUrl |
||||||
|
this.pdfVisible = true |
||||||
|
}else{ |
||||||
|
this.$get(`${this.api.getSubsection}/${row.id}`).then(res => { |
||||||
|
this.previewing = true |
||||||
|
this.loadIns = Loading.service() |
||||||
|
this.$route.fullPath.includes('#file') || history.pushState({file: true},'文件预览','#' + this.$route.fullPath + '#file') |
||||||
|
if(row.fileType == 'pptx'){ |
||||||
|
this.isPPT = true |
||||||
|
this.isWord = false |
||||||
|
this.isExcel = false |
||||||
|
}else if(row.fileType == 'doc' || row.fileType == 'docx'){ |
||||||
|
this.isPPT = false |
||||||
|
this.isWord = true |
||||||
|
this.isExcel = false |
||||||
|
}else if(row.fileType == 'xls' || row.fileType == 'xlsx'){ |
||||||
|
this.isExcel = true |
||||||
|
this.isPPT = false |
||||||
|
this.isWord = false |
||||||
|
}else{ |
||||||
|
this.isPPT = false |
||||||
|
this.isWord = false |
||||||
|
this.isExcel = false |
||||||
|
} |
||||||
|
this.iframeSrc = res.data.previewUrl |
||||||
|
this.$nextTick(() => { |
||||||
|
this.iframeOnload() |
||||||
|
}) |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
editSectionName(row,chapterId){ |
||||||
|
this.chapterId = chapterId |
||||||
|
this.sectionId = row.id |
||||||
|
this.sectionName = row.name |
||||||
|
this.sectionNameVisible = true |
||||||
|
}, |
||||||
|
switchFile(row,chapterId,sectionId){ |
||||||
|
this.uploadList = [] |
||||||
|
this.curFile = { |
||||||
|
fileId: row.fileId, |
||||||
|
fileName: row.fileName, |
||||||
|
fileType: row.fileType, |
||||||
|
fileUrl: row.fileUrl, |
||||||
|
} |
||||||
|
this.chapterId = chapterId |
||||||
|
this.sectionId = row.id |
||||||
|
this.sectionName = row.sectionName |
||||||
|
|
||||||
|
this.switchVisible = true |
||||||
|
}, |
||||||
|
switchSubmitFile(){ |
||||||
|
let data = { |
||||||
|
id: this.sectionId, |
||||||
|
courseId: this.id, |
||||||
|
chapterId: this.chapterId, |
||||||
|
name: this.sectionName, |
||||||
|
fileId: this.fileId, |
||||||
|
fileName: this.fileName, |
||||||
|
fileType: this.fileType, |
||||||
|
fileUrl: this.fileUrl, |
||||||
|
originalFileName: this.originalFileName |
||||||
|
} |
||||||
|
this.$put(this.api.editSubsection, data).then(res => { |
||||||
|
this.successMsg('更换成功'); |
||||||
|
this.switchVisible = false |
||||||
|
this.getData() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
}, |
||||||
|
switchSubmit(){ |
||||||
|
if(this.uploading) return this.warningMsg('资源正在上传中,请稍候') |
||||||
|
if(!this.fileUrl && !this.fileId) return this.warningMsg('请上传资源') |
||||||
|
if(this.transferType(this.curFile.fileType) == '视频'){ |
||||||
|
let data = { |
||||||
|
videoIdList: [this.sectionId] |
||||||
|
} |
||||||
|
this.$del(`${this.api.removeVideo}/${this.curFile.fileId}`).then(res => { |
||||||
|
this.switchSubmitFile() |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${this.curFile.fileName}`).then(res => { |
||||||
|
this.switchSubmitFile() |
||||||
|
}).catch(res => {}); |
||||||
|
} |
||||||
|
}, |
||||||
|
delSection(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteSubsection}/${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
sortChapter(row,type,disabled,index){ |
||||||
|
if(!disabled){ |
||||||
|
if(type == 'up'){ |
||||||
|
let tempItem = this.chapters.splice(index - 1,1)[0] |
||||||
|
this.chapters.splice(index,0,tempItem) |
||||||
|
}else{ |
||||||
|
let tempItem = this.chapters.splice(index + 1,1)[0] |
||||||
|
this.chapters.splice(index,0,tempItem) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
sortSection(chapterIndex,type,disabled,index){ |
||||||
|
if(!disabled){ |
||||||
|
let list = this.chapters[chapterIndex].subsectionList |
||||||
|
if(type == 'up'){ |
||||||
|
let tempItem = list.splice(index - 1,1)[0] |
||||||
|
list.splice(index,0,tempItem) |
||||||
|
}else{ |
||||||
|
let tempItem = list.splice(index + 1,1)[0] |
||||||
|
list.splice(index,0,tempItem) |
||||||
|
} |
||||||
|
this.chapters[chapterIndex].subsectionList = list |
||||||
|
|
||||||
|
} |
||||||
|
}, |
||||||
|
sectionNameSubmit(){ |
||||||
|
if(!this.sectionName) return this.warningMsg('请填写小节名称') |
||||||
|
let data = { |
||||||
|
id: this.sectionId, |
||||||
|
courseId: this.id, |
||||||
|
chapterId: this.chapterId, |
||||||
|
name: this.sectionName |
||||||
|
} |
||||||
|
this.$put(this.api.editSubsection, data).then(res => { |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.sectionNameVisible = false |
||||||
|
this.getData() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
}, |
||||||
|
closePlayer(){ |
||||||
|
this.playAuth = '' |
||||||
|
this.player.pause() |
||||||
|
}, |
||||||
|
closeIframe(){ |
||||||
|
this.iframeSrc = '' |
||||||
|
this.showMask = false |
||||||
|
this.showMask1 = false |
||||||
|
this.showMask2 = false |
||||||
|
this.previewing = false |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
.btns{ |
||||||
|
position: absolute; |
||||||
|
top: 12px; |
||||||
|
right: 24px; |
||||||
|
.el-button{ |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
} |
||||||
|
.sort-icon{ |
||||||
|
font-size: 24px; |
||||||
|
cursor: pointer; |
||||||
|
&.disabled{ |
||||||
|
color: #ccc; |
||||||
|
cursor: not-allowed |
||||||
|
} |
||||||
|
} |
||||||
|
.el-image-viewer__wrapper{ |
||||||
|
transform: translateY(-10px); |
||||||
|
transition: transform .5s; |
||||||
|
|
||||||
|
&.active{ |
||||||
|
transform: translateY(0) |
||||||
|
} |
||||||
|
} |
||||||
|
.el-image-viewer__close{ |
||||||
|
z-index: 10000; |
||||||
|
top: 15px; |
||||||
|
right: 15px; |
||||||
|
&.doc-close{ |
||||||
|
i{ |
||||||
|
color: #000 !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.player{ |
||||||
|
position: absolute; |
||||||
|
top: 50%; |
||||||
|
left: 50%; |
||||||
|
transform: translate(-50%,-50%); |
||||||
|
width: 1200px !important; |
||||||
|
height: 600px !important; |
||||||
|
} |
||||||
|
.fileIframe{ |
||||||
|
z-index: 1; |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
bottom: 0; |
||||||
|
right: 0; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
.mask{ |
||||||
|
z-index: 1000; |
||||||
|
position: fixed; |
||||||
|
background-color: rgb(57,58,61); |
||||||
|
} |
||||||
|
.word-mask{ |
||||||
|
z-index: 1000; |
||||||
|
position: fixed; |
||||||
|
right: 0; |
||||||
|
width: 100%; |
||||||
|
background-color: rgb(243,242,241); |
||||||
|
} |
||||||
|
.word-mask1{ |
||||||
|
z-index: 1000; |
||||||
|
position: fixed; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
background-color: #2b579a; |
||||||
|
} |
||||||
|
.word-mask2{ |
||||||
|
z-index: 1000; |
||||||
|
position: fixed; |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
.excel-mask1{ |
||||||
|
z-index: 9; |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 20%; |
||||||
|
width: 80%; |
||||||
|
background-color: #107c41; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,210 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="tool"> |
||||||
|
<ul class="filter" style="align-items: flex-start"> |
||||||
|
<li> |
||||||
|
<label>课程分类:</label> |
||||||
|
<el-select v-model="classificationId" clearable placeholder="请选择课程分类" size="small" @change="getData"> |
||||||
|
<el-option label="不限" value=""></el-option> |
||||||
|
<el-option v-for="(item,index) in classificationList" :key="index" :label="item.name" :value="item.id"></el-option> |
||||||
|
</el-select> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>搜索:</label> |
||||||
|
<el-input placeholder="请输入课程名称/创建人" suffix-icon="el-icon-search" v-model="keyword" clearable size="small"></el-input> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" round @click="addCourse" v-auth="'course:课程管理:新增课程'">新增</el-button> |
||||||
|
<el-button type="primary" size="small" round @click="delAllData" v-auth="'course:课程管理:批量删除'">批量删除</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table :data="courseData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||||
|
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||||
|
<el-table-column type="index" width="100" label="序号" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="课程名称"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="gmtCreate" label="创建时间" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="founder" label="创建人" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="章节数" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.row.chapterNum ? scope.row.chapterNum : 0}}章({{scope.row.subsectionNum ? scope.row.subsectionNum : 0}}小节) |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="classification" label="课程分类"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="250"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="editCourse(scope.row)" v-auth="'course:课程管理:编辑信息'">编辑信息</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'course:课程管理:编辑信息'"></el-divider> |
||||||
|
<el-button type="text" @click="config(scope.row)" v-auth="'course:课程管理:配置资源'">内容设置</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'course:课程管理:配置资源'"></el-divider> |
||||||
|
<el-button type="text" @click="preview(scope.row)" v-auth="'course:课程管理:预览'">预览</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'course:课程管理:预览'"></el-divider> |
||||||
|
<el-button type="text" @click="handleDelete(scope.row)" v-auth="'course:课程管理:删除'">删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="可授权状态" align="center" width="120"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-switch |
||||||
|
v-model="scope.row.isEnable" |
||||||
|
:active-value="0" |
||||||
|
:inactive-value="1" |
||||||
|
style="margin: 0 5px" |
||||||
|
:active-text="scope.row.isEnable ? '关' : '开'" |
||||||
|
@change="switchOff($event,scope.row,scope.$index)" |
||||||
|
v-auth="'course:课程管理:禁用'" |
||||||
|
></el-switch> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'dashboard', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
schoolId: this.$store.state.schoolId, |
||||||
|
keyword: '', |
||||||
|
classificationId: '', |
||||||
|
courseData: [], |
||||||
|
multipleSelection: [], |
||||||
|
classificationList: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0, |
||||||
|
}; |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer) |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.initData() |
||||||
|
},500) |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getClassification() |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
let data = { |
||||||
|
classificationId: this.classificationId, |
||||||
|
name: this.keyword, |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryCourseByCondition}/${this.pageNo}`,data).then(res => { |
||||||
|
this.courseData = res.data.courseList |
||||||
|
this.totals = res.data.total |
||||||
|
if(!this.courseData.length && this.totals){ |
||||||
|
this.pageNo-- |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
initData(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
getClassification() { |
||||||
|
this.$get(this.api.queryAllClassification).then(res => { |
||||||
|
this.classificationList = res.data.classificationList |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
changeType(type) { |
||||||
|
this.classificationId = type |
||||||
|
this.initData() |
||||||
|
}, |
||||||
|
preview(row){ |
||||||
|
this.$router.push(`courseSection?id=${row.id}`) |
||||||
|
}, |
||||||
|
config(row){ |
||||||
|
this.$router.push(`courseConfig?id=${row.id}`) |
||||||
|
}, |
||||||
|
addCourse(){ |
||||||
|
this.$router.push('addCourse') |
||||||
|
}, |
||||||
|
editCourse(row){ |
||||||
|
this.$router.push(`addCourse?id=${row.id}`) |
||||||
|
}, |
||||||
|
handleDelete(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteCourse}/${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.initData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
getRowKeys(row) { |
||||||
|
return row.customerId; |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
delAllData() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
this.$confirm(`此批量删除操作不可逆,是否确认删除${newArr[0].name}等${newArr.length}个选中项?`, '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
let data = { |
||||||
|
courseIds: delList.join() |
||||||
|
} |
||||||
|
this.$del(this.api.deleteCourses,data).then(res => { |
||||||
|
this.multipleSelection = []; |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.initData() |
||||||
|
}).catch(res => {}); |
||||||
|
}).catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !'); |
||||||
|
} |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
switchOff(val,row,index) { |
||||||
|
this.$put(`${this.api.enableGlCourse}?courseId=${row.id}&isEnable=${val}`) |
||||||
|
.then(res => { |
||||||
|
this.getData() |
||||||
|
val == 1 ? this.warningMsg('该教学资源已被禁止授权') : this.successMsg('该教学资源已被调至可对院校授权状态') |
||||||
|
}) |
||||||
|
.catch(err => {}); |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
/deep/.tool{ |
||||||
|
.filter{ |
||||||
|
.el-input{ |
||||||
|
min-width: 215px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
||||||
|
|
@ -0,0 +1,448 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="flex p-40"> |
||||||
|
<div class="cover" :class="{'is-word': showMask1}"> |
||||||
|
<img v-if="coverUrl" :src="coverUrl" alt="" width="100%" height="100%"> |
||||||
|
<template v-else-if="iframeSrc"> |
||||||
|
<iframe class="inner fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe> |
||||||
|
<template v-if="showMask"> |
||||||
|
<div class="mask" style="width: 500px;height: 30px;top: 53px;right: 320px"></div> |
||||||
|
<div class="mask" style="width: 175px;height: 30px;top: 53px;right: 5px"></div> |
||||||
|
</template> |
||||||
|
<template v-if="showMask1"> |
||||||
|
<div class="word-mask" style="height: 40px;"></div> |
||||||
|
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div> |
||||||
|
</template> |
||||||
|
<template v-if="showMask2"> |
||||||
|
<div class="excel-mask1" style="height: 48px;"></div> |
||||||
|
</template> |
||||||
|
</template> |
||||||
|
<div class="pdf inner" v-else-if="pdfSrc"> |
||||||
|
<p class="arrow"> |
||||||
|
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{grey: currentPage==1}"></span> |
||||||
|
{{currentPage}} / {{pageCount}} |
||||||
|
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span> |
||||||
|
</p> |
||||||
|
<pdf |
||||||
|
class="pdf-wrap" |
||||||
|
:src="pdfSrc" |
||||||
|
:page="currentPage" |
||||||
|
@num-pages="pageCount=$event" |
||||||
|
@page-loaded="currentPage=$event" |
||||||
|
@loaded="loadPdfHandler"> |
||||||
|
</pdf> |
||||||
|
</div> |
||||||
|
<div class="inner" v-else-if="playAuth"> |
||||||
|
<div class="video_wid" id="player"></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="catalog flex-1"> |
||||||
|
<div class="list"> |
||||||
|
<h4 class="title">{{courseName}}</h4> |
||||||
|
<div class="desc-wrap"> |
||||||
|
<div class="desc" :class="{active: desShrink}" v-html="description"></div> |
||||||
|
<i class="arrow" :class="{active: desShrink}" v-if="description.length > 40"> |
||||||
|
<span>...</span> |
||||||
|
<img src="../assets/img/arrow-down.png" alt="" @click="desShrink = !desShrink"> |
||||||
|
</i> |
||||||
|
</div> |
||||||
|
<div class="chapters"> |
||||||
|
<template v-if="videoList.length"> |
||||||
|
<div class="chapter" v-for="(item,index) in videoList" :key="index"> |
||||||
|
<div class="chapterName">{{item.name}}</div> |
||||||
|
<div class="section" v-if="item.subsectionList.length"> |
||||||
|
<div class="sectionName" v-for="(section,i) in item.subsectionList" :key="i" @click="preview(section)">{{section.name}}</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapState } from 'vuex'; |
||||||
|
import pdf from "vue-pdf"; |
||||||
|
import 'quill/dist/quill.core.css'; |
||||||
|
import 'quill/dist/quill.snow.css'; |
||||||
|
import 'quill/dist/quill.bubble.css'; |
||||||
|
import bus from '@/libs/bus' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
id: this.$route.query.id, |
||||||
|
video: 'http://liuwanr.oss-cn-shenzhen.aliyuncs.com/mp4/20200519/1589871025648.mp4', |
||||||
|
videoSrc: '', |
||||||
|
userId: this.$store.state.userId, |
||||||
|
videoList: [], |
||||||
|
courseName: '', |
||||||
|
description: '', |
||||||
|
coverUrl: '', |
||||||
|
playAuth: '', |
||||||
|
player: null, |
||||||
|
previewImg: '', |
||||||
|
iframeSrc: '', |
||||||
|
isWord: false, |
||||||
|
isPPT: false, |
||||||
|
isExcel: false, |
||||||
|
showMask: false, |
||||||
|
showMask1: false, |
||||||
|
showMask2: false, |
||||||
|
closePosi: { |
||||||
|
top: '80px' |
||||||
|
}, |
||||||
|
pdfVisible: false, |
||||||
|
pdfSrc: '', |
||||||
|
currentPage: 0, // pdf文件页码 |
||||||
|
pageCount: 0, // pdf文件总页数 |
||||||
|
fileType: 'pdf', // 文件类型 |
||||||
|
desShrink: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
...mapState({ |
||||||
|
courseId: state => state.courseId, |
||||||
|
classId: state => state.classId, |
||||||
|
}), |
||||||
|
}, |
||||||
|
components: { pdf }, |
||||||
|
mounted() { |
||||||
|
this.insertScript() |
||||||
|
this.getData() |
||||||
|
this.getChapter() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
async getData(){ |
||||||
|
let res = await this.$get(`${this.api.getCourse}/${this.id}`) |
||||||
|
this.courseName = res.data.course.name |
||||||
|
this.description = res.data.course.description |
||||||
|
this.coverUrl = res.data.course.coverUrl |
||||||
|
}, |
||||||
|
async getChapter(){ |
||||||
|
let res = await this.$get(`${this.api.queryChaptersAndSubsections}/${this.id}`) |
||||||
|
this.videoList = res.data.chapterList |
||||||
|
}, |
||||||
|
insertScript(){ |
||||||
|
const linkTag = document.createElement('link'); |
||||||
|
linkTag.rel = 'stylesheet'; |
||||||
|
linkTag.href = 'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css'; |
||||||
|
document.body.appendChild(linkTag); |
||||||
|
|
||||||
|
const scriptTag = document.createElement('script'); |
||||||
|
scriptTag.type = 'text/javascript'; |
||||||
|
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'; |
||||||
|
document.body.appendChild(scriptTag); |
||||||
|
}, |
||||||
|
transferType(ext){ |
||||||
|
if('jpg,jpeg,png,gif,svg,psd'.includes(ext)) return '图片' |
||||||
|
if('mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv'.includes(ext)) return '视频' |
||||||
|
return ext |
||||||
|
}, |
||||||
|
preview(row){ |
||||||
|
this.player = null |
||||||
|
this.playauth = '' |
||||||
|
this.coverUrl = '' |
||||||
|
this.pdfSrc = '' |
||||||
|
this.iframeSrc = '' |
||||||
|
if(this.transferType(row.fileType) == '视频'){ |
||||||
|
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => { |
||||||
|
this.playAuth = res.data.playAuth |
||||||
|
this.$nextTick(() => { |
||||||
|
if(this.player){ |
||||||
|
this.player.replayByVidAndPlayAuth(row.fileId,this.playAuth) |
||||||
|
}else{ |
||||||
|
this.player = new Aliplayer({ |
||||||
|
id: 'player', |
||||||
|
width: '100%', |
||||||
|
autoplay: false, |
||||||
|
vid : row.fileId, |
||||||
|
playauth : this.playAuth, |
||||||
|
encryptType:1, //当播放私有加密流时需要设置。 |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
}).catch(res => {}) |
||||||
|
}else if(this.transferType(row.fileType) == '图片'){ |
||||||
|
this.coverUrl = row.fileUrl |
||||||
|
}else if(row.fileType == 'pdf'){ |
||||||
|
this.pdfSrc = row.fileUrl |
||||||
|
this.pdfVisible = true |
||||||
|
}else{ |
||||||
|
this.$get(`${this.api.getSubsection}/${row.id}`).then(res => { |
||||||
|
if(row.fileType == 'pptx'){ |
||||||
|
this.isPPT = true |
||||||
|
this.isWord = false |
||||||
|
this.isExcel = false |
||||||
|
}else if(row.fileType == 'doc' || row.fileType == 'docx'){ |
||||||
|
this.isPPT = false |
||||||
|
this.isWord = true |
||||||
|
this.isExcel = false |
||||||
|
}else if(row.fileType == 'xls' || row.fileType == 'xlsx'){ |
||||||
|
this.isExcel = true |
||||||
|
this.isPPT = false |
||||||
|
this.isWord = false |
||||||
|
}else{ |
||||||
|
this.isPPT = false |
||||||
|
this.isWord = false |
||||||
|
this.isExcel = false |
||||||
|
} |
||||||
|
if(this.isPPT){ |
||||||
|
this.showMask = true |
||||||
|
}else{ |
||||||
|
this.showMask = false |
||||||
|
} |
||||||
|
if(this.isWord){ |
||||||
|
this.showMask1 = true |
||||||
|
}else{ |
||||||
|
this.showMask1 = false |
||||||
|
} |
||||||
|
if(this.isExcel){ |
||||||
|
this.showMask2 = true |
||||||
|
}else{ |
||||||
|
this.showMask2 = false |
||||||
|
} |
||||||
|
this.iframeSrc = res.data.previewUrl |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
closePlayer(){ |
||||||
|
this.playAuth = '' |
||||||
|
this.player.pause() |
||||||
|
}, |
||||||
|
closeIframe(){ |
||||||
|
this.iframeSrc = '' |
||||||
|
this.showMask = false |
||||||
|
this.showMask1 = false |
||||||
|
}, |
||||||
|
closePdf(){ |
||||||
|
this.pdfSrc = '' |
||||||
|
this.currentPage = 1 |
||||||
|
}, |
||||||
|
changePdfPage (val) { |
||||||
|
if (val === 0 && this.currentPage > 1) { |
||||||
|
this.currentPage-- |
||||||
|
} |
||||||
|
if (val === 1 && this.currentPage < this.pageCount) { |
||||||
|
this.currentPage++ |
||||||
|
} |
||||||
|
}, |
||||||
|
loadPdfHandler (e) { |
||||||
|
this.currentPage = 1 |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
$height: 700px; |
||||||
|
.video_wid,.cover{ |
||||||
|
position: relative; |
||||||
|
width: 76%; |
||||||
|
max-width: 1400px; |
||||||
|
height: $height !important; |
||||||
|
border: 0; |
||||||
|
} |
||||||
|
.cover{ |
||||||
|
img{ |
||||||
|
border-radius: 8px; |
||||||
|
} |
||||||
|
&.is-word{ |
||||||
|
overflow: hidden; |
||||||
|
} |
||||||
|
} |
||||||
|
.fileIframe{ |
||||||
|
height: $height !important; |
||||||
|
} |
||||||
|
.video_wid,.inner{ |
||||||
|
width: 100%; |
||||||
|
height: 100% !important; |
||||||
|
border: 0; |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
.cover.is-word{ |
||||||
|
.inner{ |
||||||
|
height: calc(100% + 38px) !important; |
||||||
|
margin-top: -38px; |
||||||
|
} |
||||||
|
} |
||||||
|
.video_wid:focus{ |
||||||
|
outline: none; |
||||||
|
} |
||||||
|
.catalog{ |
||||||
|
margin-left: 40px; |
||||||
|
} |
||||||
|
.list{ |
||||||
|
height: $height; |
||||||
|
overflow-y: auto; |
||||||
|
padding: 24px 16px; |
||||||
|
background: #fff; |
||||||
|
.title{ |
||||||
|
margin-bottom: 8px; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
font-size: 20px; |
||||||
|
} |
||||||
|
.desc-wrap{ |
||||||
|
position: relative; |
||||||
|
.desc{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
line-height: 22px; |
||||||
|
@include mul-ellipsis(2); |
||||||
|
&.active{ |
||||||
|
display: block; |
||||||
|
overflow: visible; |
||||||
|
} |
||||||
|
} |
||||||
|
.arrow{ |
||||||
|
position: absolute; |
||||||
|
bottom: 2px; |
||||||
|
right: 0; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
width: 46px; |
||||||
|
background-color: #fff; |
||||||
|
span{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
} |
||||||
|
img{ |
||||||
|
width: 16px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
&.active{ |
||||||
|
span{ |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
img{ |
||||||
|
transform: rotate(180deg); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.chapters{ |
||||||
|
margin-top: 16px; |
||||||
|
max-height: calc(100% - 53px); |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
.chapter{ |
||||||
|
margin-bottom: 20px; |
||||||
|
.chapterName{ |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
.section{ |
||||||
|
padding: 5px 15px; |
||||||
|
margin-top: 8px; |
||||||
|
background: rgba(0, 0, 0, 0.02); |
||||||
|
.sectionName{ |
||||||
|
margin: 10px 0; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
cursor: pointer; |
||||||
|
@include ellipsis; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.el-image-viewer__wrapper{ |
||||||
|
transform: translateY(-10px); |
||||||
|
transition: transform .5s; |
||||||
|
|
||||||
|
&.active{ |
||||||
|
transform: translateY(0) |
||||||
|
} |
||||||
|
} |
||||||
|
.el-image-viewer__close{ |
||||||
|
z-index: 2000; |
||||||
|
top: 15px; |
||||||
|
right: 15px; |
||||||
|
&.doc-close{ |
||||||
|
i{ |
||||||
|
color: #000 !important; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.list::-webkit-scrollbar { |
||||||
|
width: 4px; |
||||||
|
} |
||||||
|
.list::-webkit-scrollbar-thumb { |
||||||
|
border-radius: 10px; |
||||||
|
background: rgba(0, 0, 0, 0.06); |
||||||
|
} |
||||||
|
|
||||||
|
.mask{ |
||||||
|
z-index: 9; |
||||||
|
position: absolute; |
||||||
|
background-color: rgb(57,58,61); |
||||||
|
} |
||||||
|
.word-mask{ |
||||||
|
z-index: 9; |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
width: 100%; |
||||||
|
background-color: rgb(243,242,241); |
||||||
|
} |
||||||
|
.word-mask1{ |
||||||
|
z-index: 9; |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
width: 100%; |
||||||
|
background-color: #185abd; |
||||||
|
} |
||||||
|
.word-mask2{ |
||||||
|
z-index: 9; |
||||||
|
position: absolute; |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
.excel-mask1{ |
||||||
|
z-index: 9; |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 20%; |
||||||
|
width: 60%; |
||||||
|
background-color: #107c41; |
||||||
|
} |
||||||
|
/deep/.pdf-dia{ |
||||||
|
border-radius: 0 !important; |
||||||
|
.el-dialog__header{ |
||||||
|
display: none; |
||||||
|
} |
||||||
|
.el-dialog__body{ |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
.el-dialog__headerbtn{ |
||||||
|
top: 10px; |
||||||
|
.el-dialog__close{ |
||||||
|
color: #fff; |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.pdf{ |
||||||
|
.arrow{ |
||||||
|
padding: 10px 0; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
font-size: 16px; |
||||||
|
color: #fff; |
||||||
|
background-color: #333; |
||||||
|
.turn{ |
||||||
|
margin: 0 10px; |
||||||
|
font-size: 18px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
.pdf-wrap{ |
||||||
|
width: 80%; |
||||||
|
margin: 0 auto; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,245 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'学校信息列表/客户列表'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="p-title">客户列表</div> |
||||||
|
<div class="page-content"> |
||||||
|
<div class="tool"> |
||||||
|
<ul class="filter"> |
||||||
|
<li> |
||||||
|
<label>国家:</label> |
||||||
|
<el-select v-model="form.countries" placeholder="请选择国家" size="small"> |
||||||
|
<el-option v-for="(item,index) in countryList" :key="index" :label="item.name" :value="item.name"></el-option> |
||||||
|
</el-select> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>省份:</label> |
||||||
|
<el-select v-model="form.provinces" clearable placeholder="请选择省份" size="small" @change="getCity()" @clear="clearprovince()"> |
||||||
|
<el-option v-for="(item,index) in provinceList" :key="index" :label="item.provinceName" :value="item.provinceId"></el-option> |
||||||
|
</el-select> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>城市:</label> |
||||||
|
<el-select v-model="form.city" clearable placeholder="请选择城市" size="small" :disabled="form.provinces ? false : true" @change="initData()"> |
||||||
|
<el-option v-for="(item,index) in cityList" :key="index" :label="item.cityName" :value="item.cityId"></el-option> |
||||||
|
</el-select> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>搜索:</label> |
||||||
|
<el-input style="width: 250px" placeholder="请输入客户名称/管理员姓名/电话" suffix-icon="el-icon-search" v-model="keyword" clearable size="small"></el-input> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" round @click="addcustomer" v-auth>新增客户</el-button> |
||||||
|
<el-button type="primary" size="small" round @click="delAllSelection" v-auth>批量删除</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table :data="customerData" ref="table" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||||
|
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||||
|
<el-table-column type="index" width="100" label="序号" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="clientName" label="客户名称"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="provinceName" label="省份" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="cityName" label="城市" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="contactPersonName" label="联系人名称" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="phone" label="手机号" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" width="180" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="show(scope.row)" v-auth>查看</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'dashboard:查看'"></el-divider> |
||||||
|
<el-button type="text" @click="edit(scope.row)" v-auth>编辑</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'dashboard:编辑'"></el-divider> |
||||||
|
<el-button type="text" @click="handleDelete(scope.row)" v-auth>删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="系统使用权限" align="center" width="120"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-switch |
||||||
|
v-model="scope.row.isDisable" |
||||||
|
:active-value="0" |
||||||
|
:inactive-value="1" |
||||||
|
style="margin: 0 10px 0 5px" |
||||||
|
:active-text="scope.row.isDisable ? '关' : '开'" |
||||||
|
@change="switchOff($event,scope.row,scope.$index)" |
||||||
|
v-auth="'dashboard:禁用'" |
||||||
|
></el-switch> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
name: 'dashboard', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
countryList: [{ |
||||||
|
name:'中国' |
||||||
|
}], |
||||||
|
customerData: [], |
||||||
|
keyword: '', |
||||||
|
form: { |
||||||
|
countries:'中国', |
||||||
|
provinces: '', |
||||||
|
city: '', |
||||||
|
}, |
||||||
|
multipleSelection: [], |
||||||
|
provinceList: [], |
||||||
|
cityList: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 1, |
||||||
|
ruleIds: [], |
||||||
|
searchTimer: null |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { breadcrumb }, |
||||||
|
watch: { |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer) |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.initData() |
||||||
|
},500) |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
this.getProvince() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
let data = { |
||||||
|
countries: this.form.countries, |
||||||
|
provinceId: this.form.provinces, |
||||||
|
cityId: this.form.city, |
||||||
|
searchContent: this.keyword |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryClient}/${this.pageNo}/${this.pageSize}`,data).then(res => { |
||||||
|
this.customerData = res.data.list |
||||||
|
this.totals = res.data.total |
||||||
|
if(!this.customerData.length && this.totals){ |
||||||
|
this.pageNo-- |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
initData(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
getProvince(){ |
||||||
|
this.$get(this.api.queryProvince).then(res => { |
||||||
|
this.provinceList = res.data.list |
||||||
|
this.$store.commit("provinceData", { provinceList : res.data.list}) |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
// 清除省份 |
||||||
|
clearprovince(){ |
||||||
|
this.form.city = '' |
||||||
|
}, |
||||||
|
getCity(){ |
||||||
|
this.clearprovince() |
||||||
|
this.getCityData() |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
getCityData(){ |
||||||
|
if(this.form.provinces != ''){ |
||||||
|
let data = { |
||||||
|
provinceId: this.form.provinces |
||||||
|
} |
||||||
|
this.$get(this.api.queryCity,data).then(res => { |
||||||
|
this.cityList = res.data.list |
||||||
|
}).catch(res => {}); |
||||||
|
} |
||||||
|
}, |
||||||
|
addcustomer(){ |
||||||
|
this.$router.push('/addcustomer'); |
||||||
|
}, |
||||||
|
show(row){ |
||||||
|
this.$router.push(`/addcustomer?id=${row.id}&show=1`); |
||||||
|
}, |
||||||
|
edit(row){ |
||||||
|
this.$router.push(`/addcustomer?id=${row.id}`); |
||||||
|
}, |
||||||
|
handleDelete(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$post(`${this.api.deleteClient}?clientIds=${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功') |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
getRowKeys(row) { |
||||||
|
return row.customerId; |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
switchOff(val,row,index) { |
||||||
|
let data = { |
||||||
|
id: row.id, |
||||||
|
isDisable: val |
||||||
|
} |
||||||
|
this.$post(this.api.updateClient,data).then((res) => { |
||||||
|
val == 1 ? this.warningMsg('该院校系统使用权限已关闭') : this.successMsg('该院校系统使用权限已激活') |
||||||
|
}).catch((res) => {}) |
||||||
|
}, |
||||||
|
delAllSelection() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
this.$confirm(`此批量删除操作不可逆,是否确认删除${newArr[0].clientName}等${newArr.length}个选中项?`, '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$post(`${this.api.deleteClient}?clientIds=${delList.join()}`).then(res => { |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
this.multipleSelection = []; |
||||||
|
this.successMsg('删除成功') |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}).catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据') |
||||||
|
} |
||||||
|
}, |
||||||
|
onSearch(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
|
||||||
|
</style> |
||||||
|
|
@ -0,0 +1,46 @@ |
|||||||
|
<template> |
||||||
|
<section class="main"> |
||||||
|
<div class="crumbs"> |
||||||
|
<el-breadcrumb separator="/"> |
||||||
|
<el-breadcrumb-item><i class="el-icon-lx-global"></i> {{$t('i18n.breadcrumb')}}</el-breadcrumb-item> |
||||||
|
</el-breadcrumb> |
||||||
|
</div> |
||||||
|
<div class="container"> |
||||||
|
<span>{{$t('i18n.tips')}}</span> |
||||||
|
<el-button type="primary" @click="$i18n.locale = $i18n.locale === 'zh'?'en':'zh';">{{$t('i18n.btn')}}</el-button> |
||||||
|
<div class="list"> |
||||||
|
<h2>{{$t('i18n.title1')}}</h2> |
||||||
|
<p>{{$t('i18n.p1')}}</p> |
||||||
|
<p>{{$t('i18n.p2')}}</p> |
||||||
|
<p>{{$t('i18n.p3')}}</p> |
||||||
|
</div> |
||||||
|
<h2>{{$t('i18n.title2')}}</h2> |
||||||
|
<div> |
||||||
|
<i18n path="i18n.info" tag="p"> |
||||||
|
<a place="action" href="https://element.eleme.cn/2.0/#/zh-CN/component/i18n">{{ $t('i18n.value') }}</a> |
||||||
|
</i18n> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</section> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data(){ |
||||||
|
return { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.list{ |
||||||
|
padding: 30px 0; |
||||||
|
} |
||||||
|
.list p{ |
||||||
|
margin-bottom: 20px; |
||||||
|
} |
||||||
|
a{ |
||||||
|
color: #cb221c; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,225 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="crumbs"> |
||||||
|
<el-breadcrumb separator="/"> |
||||||
|
<el-breadcrumb-item><i class="el-icon-lx-emoji"></i> 自定义图标</el-breadcrumb-item> |
||||||
|
</el-breadcrumb> |
||||||
|
</div> |
||||||
|
<div class="container"> |
||||||
|
<h2>使用方法</h2> |
||||||
|
<p style="line-height: 50px;"> |
||||||
|
直接通过设置类名为 el-icon-lx-iconName 来使用即可。例如:(共{{iconList.length}}个图标) |
||||||
|
</p> |
||||||
|
<p class="example-p"> |
||||||
|
<i class="el-icon-lx-redpacket_fill" style="font-size: 30px;color: #ff5900"></i> |
||||||
|
<span><i class="el-icon-lx-redpacket_fill"></i></span> |
||||||
|
</p> |
||||||
|
<p class="example-p"> |
||||||
|
<i class="el-icon-lx-weibo" style="font-size: 30px;color:#fd5656"></i> |
||||||
|
<span><i class="el-icon-lx-weibo"></i></span> |
||||||
|
</p> |
||||||
|
<p class="example-p"> |
||||||
|
<i class="el-icon-lx-emojifill" style="font-size: 30px;color: #ffc300"></i> |
||||||
|
<span><i class="el-icon-lx-emojifill"></i></span> |
||||||
|
</p> |
||||||
|
<br> |
||||||
|
<h2>图标</h2> |
||||||
|
<div class="search-box"> |
||||||
|
<el-input class="search" size="large" v-model="keyword" clearable placeholder="请输入图标名称"></el-input> |
||||||
|
</div> |
||||||
|
<ul> |
||||||
|
<li class="icon-li" v-for="(item,index) in list" :key="index"> |
||||||
|
<div class="icon-li-content"> |
||||||
|
<i :class="`el-icon-lx-${item}`"></i> |
||||||
|
<span>{{item}}</span> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data: function(){ |
||||||
|
return { |
||||||
|
keyword: '', |
||||||
|
iconList: [ |
||||||
|
'attentionforbid', |
||||||
|
'attentionforbidfill', |
||||||
|
'attention', |
||||||
|
'attentionfill', |
||||||
|
'tag', |
||||||
|
'tagfill', |
||||||
|
'people', |
||||||
|
'peoplefill', |
||||||
|
'notice', |
||||||
|
'noticefill', |
||||||
|
'mobile', |
||||||
|
'mobilefill', |
||||||
|
'voice', |
||||||
|
'voicefill', |
||||||
|
'unlock', |
||||||
|
'lock', |
||||||
|
'home', |
||||||
|
'homefill', |
||||||
|
'delete', |
||||||
|
'deletefill', |
||||||
|
'notification', |
||||||
|
'notificationfill', |
||||||
|
'notificationforbidfill', |
||||||
|
'like', |
||||||
|
'likefill', |
||||||
|
'comment', |
||||||
|
'commentfill', |
||||||
|
'camera', |
||||||
|
'camerafill', |
||||||
|
'warn', |
||||||
|
'warnfill', |
||||||
|
'time', |
||||||
|
'timefill', |
||||||
|
'location', |
||||||
|
'locationfill', |
||||||
|
'favor', |
||||||
|
'favorfill', |
||||||
|
'skin', |
||||||
|
'skinfill', |
||||||
|
'news', |
||||||
|
'newsfill', |
||||||
|
'record', |
||||||
|
'recordfill', |
||||||
|
'emoji', |
||||||
|
'emojifill', |
||||||
|
'message', |
||||||
|
'messagefill', |
||||||
|
'goods', |
||||||
|
'goodsfill', |
||||||
|
'crown', |
||||||
|
'crownfill', |
||||||
|
'move', |
||||||
|
'add', |
||||||
|
'hot', |
||||||
|
'hotfill', |
||||||
|
'service', |
||||||
|
'servicefill', |
||||||
|
'present', |
||||||
|
'presentfill', |
||||||
|
'pic', |
||||||
|
'picfill', |
||||||
|
'rank', |
||||||
|
'rankfill', |
||||||
|
'male', |
||||||
|
'female', |
||||||
|
'down', |
||||||
|
'top', |
||||||
|
'recharge', |
||||||
|
'rechargefill', |
||||||
|
'forward', |
||||||
|
'forwardfill', |
||||||
|
'info', |
||||||
|
'infofill', |
||||||
|
'redpacket', |
||||||
|
'redpacket_fill', |
||||||
|
'roundadd', |
||||||
|
'roundaddfill', |
||||||
|
'friendadd', |
||||||
|
'friendaddfill', |
||||||
|
'cart', |
||||||
|
'cartfill', |
||||||
|
'more', |
||||||
|
'moreandroid', |
||||||
|
'back', |
||||||
|
'right', |
||||||
|
'shop', |
||||||
|
'shopfill', |
||||||
|
'question', |
||||||
|
'questionfill', |
||||||
|
'roundclose', |
||||||
|
'roundclosefill', |
||||||
|
'roundcheck', |
||||||
|
'roundcheckfill', |
||||||
|
'global', |
||||||
|
'mail', |
||||||
|
'punch', |
||||||
|
'exit', |
||||||
|
'upload', |
||||||
|
'read', |
||||||
|
'file', |
||||||
|
'link', |
||||||
|
'full', |
||||||
|
'group', |
||||||
|
'friend', |
||||||
|
'profile', |
||||||
|
'addressbook', |
||||||
|
'calendar', |
||||||
|
'text', |
||||||
|
'copy', |
||||||
|
'share', |
||||||
|
'wifi', |
||||||
|
'vipcard', |
||||||
|
'weibo', |
||||||
|
'remind', |
||||||
|
'refresh', |
||||||
|
'filter', |
||||||
|
'settings', |
||||||
|
'scan', |
||||||
|
'qrcode', |
||||||
|
'cascades', |
||||||
|
'apps', |
||||||
|
'sort', |
||||||
|
'searchlist', |
||||||
|
'search', |
||||||
|
'edit' |
||||||
|
] |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
list(){ |
||||||
|
return this.iconList.filter((item) => { |
||||||
|
return item.indexOf(this.keyword) !== -1; |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.example-p{ |
||||||
|
height: 45px; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.search-box{ |
||||||
|
text-align: center; |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
.search{ |
||||||
|
width: 300px; |
||||||
|
} |
||||||
|
ul,li{ |
||||||
|
list-style: none; |
||||||
|
} |
||||||
|
.icon-li{ |
||||||
|
display: inline-block; |
||||||
|
padding: 10px; |
||||||
|
width: 120px; |
||||||
|
height: 120px; |
||||||
|
} |
||||||
|
.icon-li-content{ |
||||||
|
display: flex; |
||||||
|
height: 100%; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
.icon-li-content i{ |
||||||
|
font-size: 36px; |
||||||
|
color: #606266; |
||||||
|
} |
||||||
|
.icon-li-content span{ |
||||||
|
margin-top: 10px; |
||||||
|
color: #787878; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,374 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'官方资讯管理/栏目管理'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="tabs"> |
||||||
|
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == activeName}" @click="tabChange(index)">{{item}}</a> |
||||||
|
</div> |
||||||
|
<div class="btn-wrap"> |
||||||
|
<template v-if="sorting"> |
||||||
|
<el-button class="action-btn" type="primary" size="small" round @click="cancelSort">取消</el-button> |
||||||
|
<el-button class="action-btn" type="primary" size="small" round @click="sortSubmit">保存</el-button> |
||||||
|
</template> |
||||||
|
<template v-if="!sorting"> |
||||||
|
<el-button class="action-btn" type="primary" size="small" round @click="openSort" v-auth>更改排序</el-button> |
||||||
|
<el-button class="action-btn" type="primary" size="small" round @click="addColumn" v-auth>添加栏目</el-button> |
||||||
|
</template> |
||||||
|
</div> |
||||||
|
<div class="page-content"> |
||||||
|
<div class="el-table"> |
||||||
|
<div class="list"> |
||||||
|
<div class="thead"> |
||||||
|
<span>栏目名称</span> |
||||||
|
<span><em :class="{hide: sorting}" style="font-style: normal">操作</em></span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<el-tree :data="listData" node-key="id" default-expand-all @node-drop="handleDrop" :draggable="sorting" :allow-drop="allowDrop" :allow-drag="allowDrag"> |
||||||
|
<span class="custom-tree-node" slot-scope="{ node, data }"> |
||||||
|
<span class="name">{{ node.label }}</span> |
||||||
|
<span class="action" v-show="!sorting"> |
||||||
|
<el-button type="text" @click.stop="editType(data)" v-auth>编辑</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'information:编辑'"></el-divider> |
||||||
|
<template v-if="node.level == 1" v-auth="'information:新增'"> |
||||||
|
<el-button type="text" @click.stop="addType(data)">新增</el-button> |
||||||
|
<el-divider direction="vertical"></el-divider> |
||||||
|
</template> |
||||||
|
<el-button type="text" @click.stop="delData(data)" v-auth>删除</el-button> |
||||||
|
</span> |
||||||
|
</span> |
||||||
|
</el-tree> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog :title="isAddColumn ? '添加栏目' : '编辑栏目'" :visible.sync="columnVisible" width="400px" :close-on-click-modal="false" @close="closeColumn"> |
||||||
|
<el-form> |
||||||
|
<el-form-item> |
||||||
|
<el-input placeholder="栏目名称" v-model="columnName"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="columnVisible = false">取 消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="columnSubmit">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog :title="isAddType ? '添加分类' : '编辑分类'" :visible.sync="typeVisible" width="400px" :close-on-click-modal="false" @close="closeType"> |
||||||
|
<el-form> |
||||||
|
<el-form-item> |
||||||
|
<el-input placeholder="分类名称" v-model="typeName"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="typeVisible = false">取 消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="typeSubmit">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
name: 'information', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
activeName: 'first', |
||||||
|
tabs: { |
||||||
|
first: '栏目管理' |
||||||
|
}, |
||||||
|
name: this.$store.state.name, |
||||||
|
originalList: [], |
||||||
|
listData: [], |
||||||
|
multipleSelection: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0, |
||||||
|
columnVisible: false, |
||||||
|
columnName: '', |
||||||
|
typeVisible: false, |
||||||
|
typeName: '', |
||||||
|
curRow: {}, |
||||||
|
sortObj: null, |
||||||
|
sorting: false, |
||||||
|
curParentId: '', |
||||||
|
isAddColumn: false, |
||||||
|
isAddType: false, |
||||||
|
defaultProps: { |
||||||
|
children: 'children', |
||||||
|
label: 'label' |
||||||
|
} |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { breadcrumb }, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
beforeRouteLeave(to, from, next){ |
||||||
|
if(JSON.stringify(this.originalList) !== JSON.stringify(this.listData)){ |
||||||
|
this.$confirm('确定返回?排序尚未保存。', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
next() |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}else{ |
||||||
|
next() |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
let data = { |
||||||
|
page: this.pageNo, |
||||||
|
size: this.pageSize |
||||||
|
} |
||||||
|
this.$get(this.api.queryAllColumns,data).then(res => { |
||||||
|
let columnTree = res.data.columnTree |
||||||
|
let total = columnTree.length |
||||||
|
let list = [] |
||||||
|
columnTree.forEach((n,k) => { |
||||||
|
list.push({ |
||||||
|
id: n.id, |
||||||
|
label: n.name, |
||||||
|
level: n.level, |
||||||
|
parentId: n.parentId, |
||||||
|
sort: n.sort, |
||||||
|
children: [] |
||||||
|
}) |
||||||
|
n.secondColumn.forEach((j,i) => { |
||||||
|
list[k].children.push({ |
||||||
|
id: j.id, |
||||||
|
label: j.name, |
||||||
|
level: j.level, |
||||||
|
parentId: j.parentId, |
||||||
|
sort: j.sort |
||||||
|
}) |
||||||
|
}) |
||||||
|
total += n.secondColumn.length |
||||||
|
}) |
||||||
|
this.listData = list |
||||||
|
this.originalList = JSON.parse(JSON.stringify(this.listData)) |
||||||
|
this.totals = total |
||||||
|
if(!this.listData.length && this.totals){ |
||||||
|
this.pageNo-- |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
delData(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteColumn}/${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
addColumn(){ |
||||||
|
this.isAddColumn = true |
||||||
|
this.columnVisible = true |
||||||
|
}, |
||||||
|
sortSubmit(){ |
||||||
|
let list = JSON.parse(JSON.stringify(this.listData)) |
||||||
|
list.forEach((n,k) => { |
||||||
|
n.name = n.label |
||||||
|
n.parentId = 1 |
||||||
|
n.level = 1 |
||||||
|
n.sort = k+1 |
||||||
|
n.children && n.children.forEach((j,i) => { |
||||||
|
j.name = j.label |
||||||
|
j.parentId = n.id |
||||||
|
j.level = 2 |
||||||
|
j.sort = i+1 |
||||||
|
delete j.label |
||||||
|
j.secondColumn = [] |
||||||
|
}) |
||||||
|
delete n.label |
||||||
|
n.secondColumn = n.children |
||||||
|
n.children = null |
||||||
|
}) |
||||||
|
let data = {columnTree: list} |
||||||
|
this.$post(this.api.reorder,data).then(res => { |
||||||
|
this.successMsg('保存成功'); |
||||||
|
this.sorting = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
columnSubmit(){ |
||||||
|
if(!this.columnName) return this.warningMsg('请填写栏目名称') |
||||||
|
let data = { |
||||||
|
level: 1, |
||||||
|
parentId: 1, |
||||||
|
name: this.columnName |
||||||
|
} |
||||||
|
if(this.curRow.id){ |
||||||
|
data.id = this.curRow.id |
||||||
|
this.$put(this.api.editColumn,data).then(res => { |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.columnVisible = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addColumn,data).then(res => { |
||||||
|
this.successMsg('添加成功'); |
||||||
|
this.columnVisible = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
} |
||||||
|
}, |
||||||
|
addType(row){ |
||||||
|
this.isAddType = true |
||||||
|
this.curRow = row |
||||||
|
this.typeVisible = true |
||||||
|
}, |
||||||
|
editType(row){ |
||||||
|
this.curRow = row |
||||||
|
if(row.level == 1){ |
||||||
|
this.isAddColumn = false |
||||||
|
this.columnVisible = true |
||||||
|
this.columnName = row.label |
||||||
|
}else{ |
||||||
|
this.isAddType = false |
||||||
|
this.typeVisible = true |
||||||
|
this.typeName = row.label |
||||||
|
} |
||||||
|
}, |
||||||
|
typeSubmit(row){ |
||||||
|
if(!this.typeName) return this.warningMsg('请填写分类名称') |
||||||
|
let data = { |
||||||
|
level: 2, |
||||||
|
name: this.typeName |
||||||
|
} |
||||||
|
if(this.curRow.level == 2){ |
||||||
|
data.id = this.curRow.id |
||||||
|
data.parentId = this.curRow.parentId |
||||||
|
this.$put(this.api.editColumn,data).then(res => { |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.typeVisible = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
data.parentId = this.curRow.id |
||||||
|
this.$post(this.api.addColumn,data).then(res => { |
||||||
|
this.successMsg('新增成功'); |
||||||
|
this.typeVisible = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
} |
||||||
|
}, |
||||||
|
cancelSort(){ |
||||||
|
this.sorting = false |
||||||
|
this.listData = JSON.parse(JSON.stringify(this.originalList)) |
||||||
|
this.sortObj.destroy() |
||||||
|
}, |
||||||
|
openSort(){ |
||||||
|
this.sorting = true |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
onSearch(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
closeColumn(){ |
||||||
|
this.columnName = '' |
||||||
|
this.curRow = {} |
||||||
|
}, |
||||||
|
closeType(){ |
||||||
|
this.typeName = '' |
||||||
|
this.curRow = {} |
||||||
|
}, |
||||||
|
handleDrop(draggingNode, dropNode, dropType, ev) { |
||||||
|
// console.log('tree drop: ', dropNode, dropType); |
||||||
|
}, |
||||||
|
allowDrop(draggingNode, dropNode, type) { |
||||||
|
if (dropNode.level == 2 && draggingNode.childNodes.length == 0) { |
||||||
|
return type !== 'inner' |
||||||
|
}else if((draggingNode.childNodes.length > 0 && dropNode.level == 2) || (draggingNode.childNodes.length > 0 && type == 'inner')){ |
||||||
|
return false |
||||||
|
}else { |
||||||
|
return true |
||||||
|
} |
||||||
|
}, |
||||||
|
allowDrag(draggingNode) { |
||||||
|
return draggingNode.data.label.indexOf('三级 3-2-2') === -1; |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.btn-wrap{ |
||||||
|
position: absolute; |
||||||
|
top: 15px; |
||||||
|
right: 15px; |
||||||
|
} |
||||||
|
.list{ |
||||||
|
.thead{ |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
background: rgba(0, 0, 0, 0.04)!important; |
||||||
|
span{ |
||||||
|
padding: 0.75rem 0.625rem; |
||||||
|
text-align: center; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
font-weight: normal; |
||||||
|
box-sizing: border-box; |
||||||
|
&:first-child{ |
||||||
|
padding-left: 23.5vw; |
||||||
|
@media(max-width: 1270px){ |
||||||
|
padding-left: 25.5%; |
||||||
|
} |
||||||
|
} |
||||||
|
&:last-child{ |
||||||
|
width: 16%; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
/deep/.el-tree{ |
||||||
|
.el-tree-node__expand-icon{ |
||||||
|
margin-left: 22.5vw; |
||||||
|
@media(max-width: 1270px){ |
||||||
|
margin-left: 23.5%; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-tree-node__content{ |
||||||
|
padding: 20px; |
||||||
|
border-bottom: 0.0625rem solid #EBEEF5; |
||||||
|
} |
||||||
|
} |
||||||
|
.custom-tree-node { |
||||||
|
flex: 1; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
font-size: 14px; |
||||||
|
padding-right: 8px; |
||||||
|
|
||||||
|
.name{ |
||||||
|
line-height: 44px; |
||||||
|
} |
||||||
|
.action{ |
||||||
|
width: 8.5vw; |
||||||
|
text-align: left; |
||||||
|
@media(max-width: 1270px){ |
||||||
|
width: 16%; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.hide{ |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,205 @@ |
|||||||
|
<template> |
||||||
|
<div class="wrap"> |
||||||
|
<div class="left"> |
||||||
|
<img class="logo" src="../assets/img/logo-full.png" alt=""> |
||||||
|
<img class="name" src="../assets/img/system-name.png" alt=""> |
||||||
|
</div> |
||||||
|
<div class="right"> |
||||||
|
<div v-if="!isReg"> |
||||||
|
<h2>密码登录</h2> |
||||||
|
<el-form :model="loginForm" :rules="loginRules" ref="login" label-width="0px"> |
||||||
|
<el-form-item prop="username"> |
||||||
|
<label class="account"></label> |
||||||
|
<el-input v-model="loginForm.username" placeholder="请输入账号/手机号" @keyup.enter.native="submitForm()"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="password"> |
||||||
|
<label class="password"></label> |
||||||
|
<el-input type="password" placeholder="请输入密码" v-model="loginForm.password" @keyup.enter.native="submitForm()"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-button class="submit" type="primary" @click="submitForm">登录</el-button> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import addRoutes from '@/libs/route/addRoutes'; |
||||||
|
import Setting from '@/setting'; |
||||||
|
export default { |
||||||
|
data: function() { |
||||||
|
return { |
||||||
|
loginForm: { |
||||||
|
username: '', |
||||||
|
// password: 'admin', |
||||||
|
password: '', |
||||||
|
}, |
||||||
|
loginRules: { |
||||||
|
username: [{ required: true, message: '请输入账号', trigger: 'blur' }], |
||||||
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }], |
||||||
|
}, |
||||||
|
roleDialog: false, |
||||||
|
userId: '', |
||||||
|
schoolId: '', |
||||||
|
schoolName: '', |
||||||
|
roleId: '', |
||||||
|
roleList: [] |
||||||
|
}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
updateInfo(data){ |
||||||
|
this.loginForm.username = data.username |
||||||
|
this.loginForm.password = data.password |
||||||
|
}, |
||||||
|
submitForm() { |
||||||
|
this.$refs.login.validate(valid => { |
||||||
|
if (valid) { |
||||||
|
let data = { |
||||||
|
account: this.loginForm.username, |
||||||
|
password: this.loginForm.password |
||||||
|
} |
||||||
|
this.$get(this.api.logins,data).then(res => { |
||||||
|
if(res.success){ |
||||||
|
let user = res.data.userInfo |
||||||
|
if(user.isPort == 0 || user.isPort == 1){ |
||||||
|
let routes = res.data.permissions[0].children |
||||||
|
sessionStorage.setItem(Setting.usernameKey, this.loginForm.username); |
||||||
|
user.userAvatars && this.$store.commit("setAvatarData", { avatar : user.userAvatars}); |
||||||
|
this.$store.commit("userLoginData", { userId : user.userId,accountRole: user.roleId}); |
||||||
|
this.$store.commit("userInfo", { name : user.userName,account: user.account,phone: user.phone,schoolId: user.clientId,schoolName: user.clientName}); |
||||||
|
Setting.dynamicRoute && addRoutes(routes) |
||||||
|
sessionStorage.setItem(Setting.storeKey,JSON.stringify(this.$store.state)) |
||||||
|
this.successMsg('登录成功'); |
||||||
|
let redirect = decodeURIComponent(this.$route.query.redirect || '/dashboard') |
||||||
|
this.$router.replace(redirect) |
||||||
|
}else{ |
||||||
|
this.errorMsg('该用户没有权限') |
||||||
|
} |
||||||
|
}else{ |
||||||
|
this.errorMsg(res.message) |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
.wrap { |
||||||
|
position: relative; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background: url(../assets/img/login_bg.png) 0 0/100% 100% no-repeat; |
||||||
|
overflow: hidden; |
||||||
|
.left{ |
||||||
|
margin-right: 200px; |
||||||
|
img{ |
||||||
|
display: block; |
||||||
|
} |
||||||
|
.logo{ |
||||||
|
max-width: 242px; |
||||||
|
margin-bottom: 60px; |
||||||
|
} |
||||||
|
.name{ |
||||||
|
max-width: 663px; |
||||||
|
} |
||||||
|
} |
||||||
|
.right{ |
||||||
|
padding: 40px 70px 50px; |
||||||
|
background-color: #fff; |
||||||
|
box-sizing: border-box; |
||||||
|
border-radius: 16px; |
||||||
|
|
||||||
|
h2{ |
||||||
|
font-size: 24px; |
||||||
|
color: #000; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.el-form{ |
||||||
|
margin-top: 30px; |
||||||
|
.label{ |
||||||
|
margin-bottom: 10px; |
||||||
|
color: #105CB2; |
||||||
|
} |
||||||
|
/deep/.el-input__inner{ |
||||||
|
position: relative; |
||||||
|
width: 320px; |
||||||
|
height: 46px; |
||||||
|
padding: 0 20px 0 40px; |
||||||
|
line-height: 46px; |
||||||
|
border: 1px solid #E6E6E6; |
||||||
|
border-radius: 8px !important; |
||||||
|
} |
||||||
|
.account,.password{ |
||||||
|
z-index: 10; |
||||||
|
position: absolute; |
||||||
|
top: 11px; |
||||||
|
left: 12px; |
||||||
|
width: 24px; |
||||||
|
height: 24px; |
||||||
|
background: url(../assets/img/account.png) 0 0/100% 100% no-repeat; |
||||||
|
} |
||||||
|
.password{ |
||||||
|
background-image: url(../assets/img/password.png); |
||||||
|
} |
||||||
|
/deep/.el-form-item__error{ |
||||||
|
top: 105%; |
||||||
|
left: auto; |
||||||
|
right: 0; |
||||||
|
color: #FFA94E; |
||||||
|
} |
||||||
|
.submit{ |
||||||
|
width: 100%; |
||||||
|
height: 48px; |
||||||
|
margin-top: 30px; |
||||||
|
line-height: 48px; |
||||||
|
padding: 0; |
||||||
|
font-size: 20px; |
||||||
|
background-color: #cb221c; |
||||||
|
border-radius: 23px; |
||||||
|
border: 0; |
||||||
|
} |
||||||
|
.links{ |
||||||
|
margin: 20px 0 20px; |
||||||
|
} |
||||||
|
.ques{ |
||||||
|
color: #cb221c; |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
.forget{ |
||||||
|
color: #ffa94e; |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
.login-tips{ |
||||||
|
margin-bottom: 20px; |
||||||
|
font-size: 16px; |
||||||
|
color: #105CB2; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.thirdParty{ |
||||||
|
.item{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 20px; |
||||||
|
padding: 10px 0; |
||||||
|
color: #AFB5BB; |
||||||
|
font-size: 16px; |
||||||
|
background-color: #eff0f1; |
||||||
|
border-radius: 36px; |
||||||
|
cursor: pointer; |
||||||
|
img{ |
||||||
|
width: 40px; |
||||||
|
margin-right: 10px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,281 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'赛事信息管理/竞赛列表'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="p-title">竞赛列表</div> |
||||||
|
<div class="page-content"> |
||||||
|
<div class="tool" style="align-items: baseline"> |
||||||
|
<ul class="filter"> |
||||||
|
<li> |
||||||
|
<label>创建时间:</label> |
||||||
|
<div class="single-choice"> |
||||||
|
<dl> |
||||||
|
<dd> |
||||||
|
<span :class="{ active: form.month == item.id }" v-for="(item, index) in dateList" :key="index" @click="changeType(item.id)">{{ item.name }}</span> |
||||||
|
</dd> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>创建区间:</label> |
||||||
|
<el-date-picker v-model="date" align="right" unlink-panels size="small" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable></el-date-picker> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>搜索:</label> |
||||||
|
<el-input placeholder="请输入竞赛名称/创建人" suffix-icon="el-icon-search" v-model="keyword" clearable size="small"></el-input> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<el-button type="primary" size="small" round @click="add" v-auth>创建竞赛</el-button> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table ref="table" :data="matchData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||||
|
<el-table-column type="index" width="60" label="序号" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="竞赛名称"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="applicantNum" label="报名人数" width="100" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.row.applicantNum ? scope.row.applicantNum : 0}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="status" label="状态" width="80" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{transferPublishStatus[scope.row.publishStatus]}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="time" label="竞赛时间" align="center" width="300"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.row.playStartTime}} ~ {{scope.row.playEndTime}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="gmtCreate" label="创建时间" width="150" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="founder" width="100" label="创建人" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="100"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="manage(scope.row)" v-auth>管理</el-button> |
||||||
|
<el-divider direction="vertical"></el-divider> |
||||||
|
<el-button type="text" @click="delData(scope.row)" v-auth>删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="发布状态" align="center" width="120"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-switch |
||||||
|
v-model="scope.row.publishStatus" |
||||||
|
:active-value="0" |
||||||
|
:inactive-value="1" |
||||||
|
style="margin: 0 10px 0 5px" |
||||||
|
:active-text="scope.row.publishStatus ? '关' : '开'" |
||||||
|
@change="switchOff($event,scope.row,scope.$index)" |
||||||
|
v-auth="'match:禁用'" |
||||||
|
></el-switch> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
name: 'match', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
name: this.$store.state.name, |
||||||
|
keyword: '', |
||||||
|
statusList: [ |
||||||
|
{ |
||||||
|
value: '', |
||||||
|
name: '不限' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 1, |
||||||
|
name: '待发布' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 0, |
||||||
|
name: '已发布' |
||||||
|
} |
||||||
|
], |
||||||
|
matchData: [], |
||||||
|
form: { |
||||||
|
month: '', |
||||||
|
publishStatus: '', |
||||||
|
startTime: '', |
||||||
|
endTime: '' |
||||||
|
}, |
||||||
|
multipleSelection: [], |
||||||
|
dateList: [ |
||||||
|
{ |
||||||
|
id: '', |
||||||
|
name: '不限' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
name: '近一个月' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 3, |
||||||
|
name: '近三个月' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 6, |
||||||
|
name: '近六个月' |
||||||
|
} |
||||||
|
], |
||||||
|
date: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0, |
||||||
|
transferPublishStatus: ['已发布','未发布'] |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { breadcrumb }, |
||||||
|
watch: { |
||||||
|
'form.month': function(val){ |
||||||
|
if(val){ |
||||||
|
let unit = 24 * 60 * 60 * 1000 |
||||||
|
this.date = [this.formatDate('yyyy-MM-dd',new Date(new Date().getTime() - unit * 30 * val)),this.formatDate('yyyy-MM-dd',new Date(new Date().getTime() + unit))] |
||||||
|
}else{ |
||||||
|
this.date = [] |
||||||
|
} |
||||||
|
}, |
||||||
|
date: function(val){ |
||||||
|
if(val){ |
||||||
|
this.form.startTime = val[0] |
||||||
|
this.form.endTime = val[1] |
||||||
|
}else{ |
||||||
|
this.form.startTime = '' |
||||||
|
this.form.endTime = '' |
||||||
|
} |
||||||
|
this.initData() |
||||||
|
}, |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer) |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.initData() |
||||||
|
},500) |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
let data = {} |
||||||
|
if(this.form.month) data.month = this.form.month |
||||||
|
if(this.keyword) data.name = this.keyword |
||||||
|
if(this.form.publishStatus !== '') data.publishStatus = this.form.publishStatus |
||||||
|
if(this.form.startTime) data.startTime = this.form.startTime |
||||||
|
if(this.form.endTime) data.endTime = this.form.endTime |
||||||
|
this.$get(`${this.api.queryContestByCondition}/${this.pageNo}/${this.pageSize }`,data).then(res => { |
||||||
|
this.matchData = res.data.contestList |
||||||
|
this.totals = res.data.total |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
if(!this.matchData.length && this.totals){ |
||||||
|
this.pageNo-- |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
initData(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
add(){ |
||||||
|
this.$router.push('addmatch') |
||||||
|
}, |
||||||
|
manage(row){ |
||||||
|
this.$router.push(`matchDetail?id=${row.id}`) |
||||||
|
}, |
||||||
|
|
||||||
|
changeType(type) { |
||||||
|
this.form.month = type |
||||||
|
}, |
||||||
|
delData(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteContest}/${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
delAllData() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
|
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
let data = delList |
||||||
|
this.$post(this.api.deleteContest,data).then(res => { |
||||||
|
this.multipleSelection = []; |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !'); |
||||||
|
} |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
transferTime(date,type){ |
||||||
|
if(date == '0000-00-00 00:00:00') return '---' |
||||||
|
return date |
||||||
|
}, |
||||||
|
switchOff(val,row,index) { |
||||||
|
this.$put(`${this.api.publishContest}/${row.id}/${val}`) |
||||||
|
.then(res => { |
||||||
|
val == 1 ? this.warningMsg('该赛事信息已隐藏对学生端用户不可见') : this.successMsg('该赛事信息已对学生端用户公开') |
||||||
|
}) |
||||||
|
.catch(err => {}); |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
/deep/.tool{ |
||||||
|
.filter{ |
||||||
|
.el-input{ |
||||||
|
min-width: 190px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
@media(max-width: 1640px){ |
||||||
|
.page .page-content .tool .filter{ |
||||||
|
flex-wrap: wrap; |
||||||
|
margin-bottom: -15px; |
||||||
|
li{ |
||||||
|
min-width: 34%; |
||||||
|
margin-bottom: 15px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,51 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'赛事信息管理/大赛详情'" ref="breadcrumb" :route="'match'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="tabs"> |
||||||
|
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a> |
||||||
|
</div> |
||||||
|
<matchintro v-if="active == 'first'"></matchintro> |
||||||
|
<matchprogress v-else-if="active == 'second'"></matchprogress> |
||||||
|
<matchsignup v-else></matchsignup> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import matchintro from './matchintro' |
||||||
|
import matchprogress from './matchprogress' |
||||||
|
import matchsignup from './matchsignup' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
active: 'first', |
||||||
|
tabs: { |
||||||
|
first: '大赛详情', |
||||||
|
second: '竞赛进展', |
||||||
|
third: '报名人员' |
||||||
|
}, |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
matchintro, |
||||||
|
matchprogress, |
||||||
|
matchsignup, |
||||||
|
breadcrumb |
||||||
|
}, |
||||||
|
created() { |
||||||
|
|
||||||
|
}, |
||||||
|
methods: { |
||||||
|
tabChange(index){ |
||||||
|
this.active = index |
||||||
|
this.$refs.breadcrumb.update('赛事信息管理/' + this.tabs[this.active]) |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,400 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="page-content"> |
||||||
|
<el-form label-width="170px" label-suffix=":" size="small"> |
||||||
|
<el-form-item label="竞赛封面(选填)"> |
||||||
|
<el-upload class="avatar-uploader" accept=".jpg,.png,.jpeg,.gif" :on-remove="handleRemove" :on-error="uploadError" :on-success="uploadSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.fileupload" name="file" > |
||||||
|
<img v-if="coverUrl" :src="coverUrl" class="avatar"> |
||||||
|
<div class="uploader-default" v-else> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<p>上传封面</p> |
||||||
|
</div> |
||||||
|
<div slot="tip" class="el-upload__tip"> |
||||||
|
<p>展示宽度为220,高度140,JPG/PNG/GIF,3MB以内</p> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="竞赛封面长图(选填)"> |
||||||
|
<el-upload class="avatar-uploader avatar-uploader-lg" accept=".jpg,.png,.jpeg,.gif" :on-remove="handleLgRemove" :on-error="uploadError" :on-success="uploadLgSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.fileupload" name="file"> |
||||||
|
<img v-if="carouselUrl" :src="carouselUrl" class="avatar-lg"> |
||||||
|
<div class="uploader-default" v-else> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<p>上传封面</p> |
||||||
|
</div> |
||||||
|
<div slot="tip" class="el-upload__tip"> |
||||||
|
<p>展示宽度为1920,高度300,JPG/PNG/GIF,3MB以内</p> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="竞赛名称"> |
||||||
|
<div class="d-inline-block"> |
||||||
|
<el-input placeholder="请输入竞赛名称" v-model="name" clearable></el-input> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="主办方"> |
||||||
|
<div class="inline-input"> |
||||||
|
<div class="input-wrap" v-for="(item,index) in sponsorList" :key="index"> |
||||||
|
<el-input placeholder="主办方名称" v-model="sponsorList[index]"></el-input> |
||||||
|
<i v-if="sponsorList.length > 1" class="remove" @click="delSponsor(index)"></i> |
||||||
|
<button v-if="index == 0" class="add-btn" @click="addSponsor"> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<span>添加</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="承办方(选填)"> |
||||||
|
<div class="inline-input"> |
||||||
|
<div class="input-wrap" v-for="(item,index) in undertakerList" :key="index"> |
||||||
|
<el-input placeholder="承办方名称" v-model="undertakerList[index]"></el-input> |
||||||
|
<i v-if="undertakerList.length > 1" class="remove" @click="delOrganizer(index)"></i> |
||||||
|
<button v-if="index == 0" class="add-btn" @click="addOrganizer"> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<span>添加</span> |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<button v-if="!undertakerList.length" class="add-btn" @click="addOrganizer"> |
||||||
|
<i class="el-icon-plus"></i> |
||||||
|
<span>添加</span> |
||||||
|
</button> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="报名时间"> |
||||||
|
<el-date-picker v-model="signupTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="竞赛时间"> |
||||||
|
<el-date-picker v-model="playTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="竞赛详情"> |
||||||
|
<quill :border="true" v-model="description" :height="400" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button size="small" v-throttle @click="save(1)">保存</el-button> |
||||||
|
<el-button type="primary" v-if="publishStatus == 1" v-throttle @click="save(0)">发布</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import quill from '@/components/quill' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
id: this.$route.query.id || this.$store.state.matchId, |
||||||
|
coverUrl: '', |
||||||
|
carouselUrl: '', |
||||||
|
publishStatus: 0, |
||||||
|
userId: this.$store.state.userLoginId, |
||||||
|
uploadList: [], |
||||||
|
uploadDataList: [], |
||||||
|
name: '', |
||||||
|
sponsor: '', |
||||||
|
sponsorList: [''], |
||||||
|
undertaker: '', |
||||||
|
undertakerList: [], |
||||||
|
signUpStartTime: '', |
||||||
|
signUpEndTime: '', |
||||||
|
signupTime: '', |
||||||
|
playTime: '', |
||||||
|
playStartTime: '', |
||||||
|
playEndTime: '', |
||||||
|
description: '' |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
quill, |
||||||
|
breadcrumb |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
signupTime: function(val){ |
||||||
|
if(val){ |
||||||
|
this.signUpStartTime = val[0] |
||||||
|
this.signUpEndTime = val[1] |
||||||
|
}else{ |
||||||
|
this.signUpStartTime = '' |
||||||
|
this.signUpEndTime = '' |
||||||
|
} |
||||||
|
}, |
||||||
|
playTime: function(val){ |
||||||
|
if(val){ |
||||||
|
this.playStartTime = val[0] |
||||||
|
this.playEndTime = val[1] |
||||||
|
}else{ |
||||||
|
this.playStartTime = '' |
||||||
|
this.playEndTime = '' |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
this.commitId() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
save(status) { |
||||||
|
this.sponsor = this.sponsorList.filter(d=>d).join() |
||||||
|
this.undertaker = this.undertakerList.filter(d=>d).join() |
||||||
|
|
||||||
|
if(!this.name) return this.warningMsg('请填写竞赛名称') |
||||||
|
if(status == 0){ |
||||||
|
if(!this.sponsor) return this.warningMsg('请填写主办方') |
||||||
|
if(!this.signUpStartTime) return this.warningMsg('请选择报名时间') |
||||||
|
} |
||||||
|
let now = new Date().getTime() |
||||||
|
let signUpStartTime = new Date(this.signUpStartTime).getTime() |
||||||
|
let signUpEndTime = new Date(this.signUpEndTime).getTime() |
||||||
|
let playStartTime = new Date(this.playStartTime).getTime() |
||||||
|
// if(signUpStartTime && now > signUpStartTime) return this.warningMsg('报名时间不能早于当前时间') |
||||||
|
if(!this.playStartTime && status == 0) return this.warningMsg('请选择竞赛时间') |
||||||
|
if(playStartTime && playStartTime < signUpEndTime) return this.warningMsg('竞赛时间不能早于报名结束时间') |
||||||
|
if(!this.description && status == 0) return this.warningMsg('请填写竞赛详情') |
||||||
|
|
||||||
|
let data = { |
||||||
|
id: this.id, |
||||||
|
coverUrl: this.coverUrl, |
||||||
|
carouselUrl: this.carouselUrl, |
||||||
|
description: this.description, |
||||||
|
founderId: 1, |
||||||
|
name: this.name, |
||||||
|
playEndTime: this.playEndTime, |
||||||
|
playStartTime: this.playStartTime, |
||||||
|
publishStatus: status ? this.publishStatus : 0, |
||||||
|
signUpEndTime: this.signUpEndTime, |
||||||
|
signUpStartTime: this.signUpStartTime, |
||||||
|
sponsor: this.sponsor, |
||||||
|
undertaker: this.undertaker |
||||||
|
} |
||||||
|
if(this.id){ |
||||||
|
this.$put(this.api.editContest, data).then(res => { |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.$router.back() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addContest, data).then(res => { |
||||||
|
this.successMsg('创建成功'); |
||||||
|
this.$router.back() |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
getData() { |
||||||
|
this.$get(this.api.getContest + '/' + this.id) |
||||||
|
.then(res => { |
||||||
|
let data = res.data.contest |
||||||
|
this.coverUrl = data.coverUrl |
||||||
|
this.carouselUrl = data.carouselUrl |
||||||
|
this.description = data.description |
||||||
|
this.name = data.name |
||||||
|
this.playEndTime = data.playEndTime |
||||||
|
this.playStartTime = data.playStartTime |
||||||
|
this.publishStatus = data.publishStatus |
||||||
|
this.signUpEndTime = data.signUpEndTime |
||||||
|
this.signUpStartTime = data.signUpStartTime |
||||||
|
this.sponsor = data.sponsor |
||||||
|
this.undertaker = data.undertaker |
||||||
|
|
||||||
|
this.signupTime = [data.signUpStartTime,data.signUpEndTime] |
||||||
|
this.playTime = [data.playStartTime,data.playEndTime] |
||||||
|
this.sponsorList = data.sponsor.split(',') |
||||||
|
this.undertakerList = data.undertaker.split(',') |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
|
||||||
|
}); |
||||||
|
}, |
||||||
|
commitId(){ |
||||||
|
this.$store.commit("matchData", { matchId : this.id}) |
||||||
|
}, |
||||||
|
handleExceed(files, fileList) { |
||||||
|
this.warningMsg( |
||||||
|
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||||
|
); |
||||||
|
}, |
||||||
|
uploadSuccess(res, file, fileList) { |
||||||
|
if(this.coverUrl){ |
||||||
|
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {}).catch(res => {}); |
||||||
|
} |
||||||
|
this.coverUrl = res.data.filesResult.fileUrl |
||||||
|
}, |
||||||
|
uploadLgSuccess(res, file, fileList) { |
||||||
|
if(this.carouselUrl){ |
||||||
|
let fileName = this.carouselUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {}).catch(res => {}); |
||||||
|
} |
||||||
|
this.carouselUrl = res.data.filesResult.fileUrl |
||||||
|
}, |
||||||
|
uploadError(err, file, fileList) { |
||||||
|
this.$message({ |
||||||
|
message: "上传出错,请重试!", |
||||||
|
type: "error", |
||||||
|
center: true |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeRemove(file, fileList) { |
||||||
|
return this.$confirm(`确定移除 ${file.name}?`); |
||||||
|
}, |
||||||
|
handleRemove(file, fileList) { |
||||||
|
let fileName = this.coverUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||||
|
this.coverUrl = '' |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
handleLgRemove(file, fileList) { |
||||||
|
let fileName = this.carouselUrl.replace('https://liuwanr.oss-cn-shenzhen.aliyuncs.com/','') |
||||||
|
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => { |
||||||
|
this.carouselUrl = '' |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
uploadSure(){ |
||||||
|
this.BatchUpload = false |
||||||
|
this.pageNo = 1 |
||||||
|
this.keyword = '' |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
goback() { |
||||||
|
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$router.push('/match') |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
addSponsor(){ |
||||||
|
this.sponsorList.push('') |
||||||
|
}, |
||||||
|
delSponsor(index){ |
||||||
|
this.sponsorList.splice(index,1) |
||||||
|
}, |
||||||
|
addOrganizer(){ |
||||||
|
this.undertakerList.push('') |
||||||
|
}, |
||||||
|
delOrganizer(index){ |
||||||
|
this.undertakerList.splice(index,1) |
||||||
|
}, |
||||||
|
|
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
$upload-width: 220px; |
||||||
|
$upload-height: 140px; |
||||||
|
$upload-lg-height: 150px; |
||||||
|
/deep/.avatar-uploader{ |
||||||
|
.el-upload { |
||||||
|
position: relative; |
||||||
|
width: $upload-width; |
||||||
|
height: $upload-height; |
||||||
|
border: 1px dashed #d9d9d9; |
||||||
|
border-radius: 6px; |
||||||
|
cursor: pointer; |
||||||
|
overflow: hidden; |
||||||
|
&:hover { |
||||||
|
border-color: #cb221c; |
||||||
|
} |
||||||
|
.uploader-default{ |
||||||
|
display: flex; |
||||||
|
height: $upload-height; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
text-align: center; |
||||||
|
background: rgba(0, 0, 0, 0.04); |
||||||
|
i{ |
||||||
|
font-size: 20px; |
||||||
|
font-weight: bold; |
||||||
|
color: #8c939d; |
||||||
|
} |
||||||
|
p{ |
||||||
|
margin-top: 10px; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&.avatar-uploader-lg{ |
||||||
|
.el-upload { |
||||||
|
width: 100%; |
||||||
|
max-width: 960px; |
||||||
|
height: $upload-lg-height; |
||||||
|
.uploader-default{ |
||||||
|
height: $upload-lg-height; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.avatar { |
||||||
|
display: block; |
||||||
|
width: $upload-width; |
||||||
|
height: $upload-height; |
||||||
|
} |
||||||
|
.avatar-lg { |
||||||
|
display: block; |
||||||
|
width: 100%; |
||||||
|
height: $upload-lg-height; |
||||||
|
} |
||||||
|
.el-upload__tip{ |
||||||
|
margin-top: 0; |
||||||
|
p{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.45); |
||||||
|
line-height: 1; |
||||||
|
&:first-child{ |
||||||
|
margin-bottom: 5px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/deep/.d-inline-block{ |
||||||
|
width: 216px; |
||||||
|
.el-select,.el-input{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
.inline-input{ |
||||||
|
.input-wrap{ |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 10px; |
||||||
|
|
||||||
|
.el-input{ |
||||||
|
display: inline-block; |
||||||
|
width: 216px; |
||||||
|
margin-right: 8px; |
||||||
|
} |
||||||
|
.remove{ |
||||||
|
width: 16px; |
||||||
|
height: 16px; |
||||||
|
background: url(../assets/img/close.png) 0 0/cover no-repeat; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
.add-btn{ |
||||||
|
margin-left: 32px; |
||||||
|
} |
||||||
|
} |
||||||
|
.add-btn{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
width: 216px; |
||||||
|
line-height: 32px; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
background-color: transparent; |
||||||
|
border: 1px dashed rgba(0, 0, 0, 0.15); |
||||||
|
border-radius: 4px; |
||||||
|
cursor: pointer; |
||||||
|
i{ |
||||||
|
margin-right: 8px; |
||||||
|
font-size: 14px; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,160 @@ |
|||||||
|
<template> |
||||||
|
<div class="page-content"> |
||||||
|
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||||
|
<el-table-column type="index" width="60" label="序号" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="标题"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-input placeholder="请输入标题" v-model="scope.row.title"></el-input> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="详情描述"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-input placeholder="请输入详情描述" type="textarea" v-model="scope.row.description"></el-input> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="状态" width="150"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-select v-model="scope.row.status" clearable placeholder="请选择状态"> |
||||||
|
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option> |
||||||
|
</el-select> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="170"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="saveData(scope.row)">保存</el-button> |
||||||
|
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="plus" @click="addData"> |
||||||
|
<i class="el-icon-circle-plus-outline"></i> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'matchprogress', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
id: this.$store.state.matchId, |
||||||
|
statusList: [ |
||||||
|
{ |
||||||
|
value: 0, |
||||||
|
name: '未完成' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 1, |
||||||
|
name: '进行中' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 2, |
||||||
|
name: '已完成' |
||||||
|
} |
||||||
|
], |
||||||
|
listData: [], |
||||||
|
multipleSelection: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0 |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
this.$get(`${this.api.getContestProgress}/${this.id}`).then(res => { |
||||||
|
this.listData = res.data.contestProgressList |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
saveData(row){ |
||||||
|
let data = row |
||||||
|
if(data.title.length){ |
||||||
|
if(row.id){ |
||||||
|
this.$put(this.api.editContestProgress,data).then(res => { |
||||||
|
this.successMsg('修改成功') |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addContestProgress,data).then(res => { |
||||||
|
this.successMsg('创建成功') |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
} |
||||||
|
}else{ |
||||||
|
this.warningMsg('请填写标题') |
||||||
|
} |
||||||
|
}, |
||||||
|
entry(){ |
||||||
|
this.$router.push('/permission') |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
onSearch(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
handleDelete(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.deleteContestProgress}/${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
addData(){ |
||||||
|
if(this.listData.length){ |
||||||
|
if(this.listData[this.listData.length-1].id){ |
||||||
|
this.listData.push({ |
||||||
|
contestId: this.id, |
||||||
|
id: '', |
||||||
|
title: '', |
||||||
|
description: '', |
||||||
|
status: 0 |
||||||
|
}) |
||||||
|
}else{ |
||||||
|
this.warningMsg('请先保存新数据') |
||||||
|
} |
||||||
|
}else{ |
||||||
|
this.listData.push({ |
||||||
|
contestId: this.id, |
||||||
|
id: '', |
||||||
|
title: '', |
||||||
|
description: '', |
||||||
|
status: 0 |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
.box{ |
||||||
|
height: calc(100vh - 100px); |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
.plus{ |
||||||
|
padding: 15px 0 0; |
||||||
|
text-align: center; |
||||||
|
cursor: pointer; |
||||||
|
i{ |
||||||
|
font-size: 24px; |
||||||
|
color: #cb221c; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,153 @@ |
|||||||
|
<template> |
||||||
|
<div class="page-content"> |
||||||
|
<div class="tool"> |
||||||
|
<ul class="filter"> |
||||||
|
<li> |
||||||
|
<label>搜索:</label> |
||||||
|
<el-input placeholder="请输入姓名/手机号" prefix-icon="el-icon-search" v-model="keyword" clearable size="mini"></el-input> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" round @click="exportAll">全部导出</el-button> |
||||||
|
<el-button type="primary" size="small" round @click="exportBatch">批量导出</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||||
|
<el-table-column type="selection" :selectable="row => row.isDisable!=0" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||||
|
<el-table-column type="index" width="60" label="序号" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.$index + (pageNo - 1) * pageSize + 1}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="school" label="学校"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="username" label="学生姓名"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="account" label="账号"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="phone" label="手机号"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="170"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-switch |
||||||
|
v-model="scope.row.isDisable" |
||||||
|
:active-text="scope.row.isDisable ? '开' : '关'" |
||||||
|
:active-value="1" |
||||||
|
:inactive-value="0" |
||||||
|
style="margin: 0 10px 0 5px" |
||||||
|
@change="switchOff($event,scope.row,scope.$index)" |
||||||
|
></el-switch> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'dashboard', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
id: this.$store.state.matchId, |
||||||
|
keyword: '', |
||||||
|
listData: [], |
||||||
|
multipleSelection: [], |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0 |
||||||
|
}; |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer) |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.getData() |
||||||
|
},500) |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
let data = { |
||||||
|
contestId: this.id |
||||||
|
} |
||||||
|
if(this.keyword) data.name = this.keyword |
||||||
|
this.$get(`${this.api.queryApplicantByCondition}/${this.pageNo}/${this.pageSize}`,data).then(res => { |
||||||
|
this.listData = res.data.applicantList |
||||||
|
this.totals = res.data.total |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
onSearch(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
switchOff(val,row,index) { |
||||||
|
this.$put(`${this.api.disableApplicant}/${row.id}/${val}`) |
||||||
|
.then(res => {}) |
||||||
|
.catch(err => {}); |
||||||
|
}, |
||||||
|
disalbeAllData() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
|
||||||
|
this.$confirm('确定要禁用吗?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
console.log(11,delList.join()) |
||||||
|
this.$put(`${this.api.disableContests}?ids=${delList.join(',')}`).then(res => { |
||||||
|
this.multipleSelection = []; |
||||||
|
this.successMsg('禁用成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !'); |
||||||
|
} |
||||||
|
}, |
||||||
|
exportAll(){ |
||||||
|
location.href = `${this.api.excelExport}/${this.id}` |
||||||
|
}, |
||||||
|
exportBatch(){ |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let data = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
|
||||||
|
// return console.log(11,data) |
||||||
|
location.href = `${this.api.batchExport}?ids=${data.join(',')}` |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !'); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
.box{ |
||||||
|
height: calc(100vh - 100px); |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,275 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="tool"> |
||||||
|
<ul class="filter"></ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" round @click="addMajor" v-auth="'system:角色权限:新增角色'">新增架构</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table :data="listData" stripe header-align="center" row-key="id" :tree-props="treeProps" :indent="9"> |
||||||
|
<el-table-column prop="label" label="架构名称"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<span class="text">{{scope.row.label}}</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" width="200" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="edit(scope.row)">编辑</el-button> |
||||||
|
<el-divider direction="vertical"></el-divider> |
||||||
|
<template v-if="scope.row.isParent"> |
||||||
|
<el-button type="text" @click="addDepartment(scope.row)">添加</el-button> |
||||||
|
<el-divider direction="vertical"></el-divider> |
||||||
|
</template> |
||||||
|
<el-button type="text" @click="del(scope.row)">删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
|
||||||
|
<el-dialog :title="Form.MajorId ? '编辑名称' : '新增架构'" :visible.sync="isaddMajor" width="24%" @close="closeAdd" :close-on-click-modal="false"> |
||||||
|
<el-form ref="Form" :model="Form"> |
||||||
|
<el-form-item prop="majorName"> |
||||||
|
<el-input :placeholder="Form.MajorId ? '请编辑架构名称' : '请输入架构名称'" v-model="Form.majorName" @change="majorChange"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="isaddMajor = false">取 消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="sure('Form')">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog :title="Form.departmentId ? '编辑部门' : '新增部门'" :visible.sync="isAddDepartment" width="24%" @close="closeAdd" :close-on-click-modal="false"> |
||||||
|
<el-form ref="Form" :model="Form"> |
||||||
|
<el-form-item prop="departmentName"> |
||||||
|
<el-input placeholder="请输入部门名称" v-model="Form.departmentName" @change="depChange"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="isAddDepartment = false">取 消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="sureDepartment('Form')">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'role', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
treeProps: {children: 'children', hasChildren: 'hasChildren'}, |
||||||
|
schoolId: this.$store.state.schoolId, |
||||||
|
listData: [], |
||||||
|
isaddMajor: false, |
||||||
|
isAddDepartment: false, |
||||||
|
Form: { |
||||||
|
MajorId: '', |
||||||
|
majorName: '', |
||||||
|
departmentId: '', |
||||||
|
departmentName: '' |
||||||
|
}, |
||||||
|
staffstateProfessId: '', |
||||||
|
staffstateId: '', |
||||||
|
majorNoAdd: true, |
||||||
|
depNoAdd: true |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData(){ |
||||||
|
let data = { |
||||||
|
schoolId: this.schoolId |
||||||
|
} |
||||||
|
this.$get(this.api.queryStaffPro,data).then(res => { |
||||||
|
let firList = res.data.StaffProfessionalArchitectureList |
||||||
|
if(firList){ |
||||||
|
firList.map(e => { |
||||||
|
e.isParent = true |
||||||
|
e.id = e.staffProfessionalArchitectureId |
||||||
|
e.label = e.staffProfessionalArchitectureName |
||||||
|
let data = { |
||||||
|
staffProfessionalArchitectureId: e.staffProfessionalArchitectureId |
||||||
|
} |
||||||
|
this.$get(this.api.queryStaffGrade,data).then(res1 => { |
||||||
|
res1.data.staffGradeList.map(e => { |
||||||
|
e.id = e.staffGradeId |
||||||
|
e.label = e.staffGradeName |
||||||
|
}) |
||||||
|
e.children = res1.data.staffGradeList |
||||||
|
}).catch(res => {}) |
||||||
|
}) |
||||||
|
setTimeout(() => { |
||||||
|
this.listData = firList |
||||||
|
},500) |
||||||
|
} |
||||||
|
}).catch(res => {}) |
||||||
|
}, |
||||||
|
addMajor(){ |
||||||
|
this.Form.MajorId = '' |
||||||
|
this.Form.majorName = '' |
||||||
|
this.isaddMajor = true |
||||||
|
}, |
||||||
|
edit(item){ |
||||||
|
if(item.isParent){ |
||||||
|
this.Form.MajorId = item.staffProfessionalArchitectureId, |
||||||
|
this.Form.majorName = item.staffProfessionalArchitectureName |
||||||
|
this.isaddMajor = true |
||||||
|
}else{ |
||||||
|
this.Form.departmentId = item.staffGradeId, |
||||||
|
this.Form.departmentName = item.staffGradeName |
||||||
|
this.isAddDepartment = true |
||||||
|
for (let j = 0; j < this.listData.length; j++) { |
||||||
|
for (let k = 0; k < this.listData[j].children.length; k++) { |
||||||
|
if(this.listData[j].children[k].staffGradeId == item.staffGradeId){ |
||||||
|
this.Form.MajorId = this.listData[j].staffProfessionalArchitectureId |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
async majorChange(){ |
||||||
|
let res = await this.$get(this.api.queryStaffPAN, { name: this.Form.majorName,schoolId: this.schoolId }); |
||||||
|
if(res.data.StaffProfessionalArchitecture != null){ |
||||||
|
this.warningMsg('该一级部门已存在'); |
||||||
|
this.majorNoAdd = false |
||||||
|
}else{ |
||||||
|
this.majorNoAdd = true |
||||||
|
} |
||||||
|
}, |
||||||
|
async depChange(){ |
||||||
|
let res = await this.$get(this.api.queryStaffName, { staffGradeName: this.Form.departmentName,staffProfessionalArchitectureId: this.Form.MajorId }); |
||||||
|
if(res.data.staffGrade != null){ |
||||||
|
this.warningMsg('该二级部门已存在'); |
||||||
|
this.depNoAdd = false |
||||||
|
}else{ |
||||||
|
this.depNoAdd = true |
||||||
|
} |
||||||
|
}, |
||||||
|
sure(){ |
||||||
|
if(!this.Form.majorName) return this.warningMsg('请输入专业名称') |
||||||
|
if(!this.majorNoAdd) return this.warningMsg('该一级部门已存在') |
||||||
|
let data = { |
||||||
|
staffProfessionalArchitectureName: this.Form.majorName, |
||||||
|
staffProfessionalArchitectureId: this.Form.MajorId, |
||||||
|
schoolId: this.schoolId, |
||||||
|
} |
||||||
|
if(this.Form.MajorId){ |
||||||
|
this.$post(this.api.updateStaffPro,data).then(res => { |
||||||
|
this.successMsg('编辑成功') |
||||||
|
this.isaddMajor = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}) |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addStaffPro,data).then(res => { |
||||||
|
this.successMsg('添加成功') |
||||||
|
this.isaddMajor = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}) |
||||||
|
} |
||||||
|
}, |
||||||
|
// 新增编辑部门 |
||||||
|
addDepartment(item){ |
||||||
|
this.Form.departmentId = '' |
||||||
|
this.Form.departmentName = '' |
||||||
|
this.isAddDepartment = true |
||||||
|
this.Form.MajorId = item.staffProfessionalArchitectureId |
||||||
|
}, |
||||||
|
sureDepartment(Form){ |
||||||
|
if(!this.Form.departmentName) return this.warningMsg('请输入部门名称'); |
||||||
|
if(!this.depNoAdd) return this.warningMsg('该二级部门已存在'); |
||||||
|
let data = { |
||||||
|
schoolId: this.schoolId, |
||||||
|
staffGradeName: this.Form.departmentName, |
||||||
|
staffProfessionalArchitectureId: this.Form.MajorId, |
||||||
|
staffGradeId: this.Form.departmentId |
||||||
|
} |
||||||
|
if(this.Form.departmentId){ |
||||||
|
this.$post(this.api.updateStaffGrade,data).then(res => { |
||||||
|
this.successMsg('编辑成功') |
||||||
|
this.isAddDepartment = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}) |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addStaffGrade,data).then(res => { |
||||||
|
this.successMsg('添加成功') |
||||||
|
this.isAddDepartment = false |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}) |
||||||
|
} |
||||||
|
}, |
||||||
|
closeAdd(){ |
||||||
|
this.$refs.Form.resetFields() |
||||||
|
}, |
||||||
|
del(item){ |
||||||
|
if(item.isParent){ |
||||||
|
this.$confirm('确定要删除该专业吗?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$post(`${this.api.deleteStaffPro}?staffProfessionalArchitectureIds=${item.staffProfessionalArchitectureId}`).then(res => { |
||||||
|
this.getData() |
||||||
|
this.successMsg('删除成功') |
||||||
|
}).catch(res => {}) |
||||||
|
}).catch(() => {}) |
||||||
|
}else{ |
||||||
|
this.$confirm('确定要删除该部门吗?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$post(`${this.api.deleteStaffGrade}?staffGradeIds=${item.staffGradeId}`).then(res => { |
||||||
|
this.getData() |
||||||
|
this.successMsg('删除成功') |
||||||
|
}).catch(res => {}) |
||||||
|
}).catch(() => {}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
/deep/.el-table{ |
||||||
|
th:first-child{ |
||||||
|
.cell{ |
||||||
|
&:before{ |
||||||
|
content: ''; |
||||||
|
display: inline-block; |
||||||
|
padding-left: 25vw; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.el-table__body-wrapper{ |
||||||
|
td:first-child{ |
||||||
|
.cell{ |
||||||
|
display: flex; |
||||||
|
justify-content: flex-end; |
||||||
|
align-items: center; |
||||||
|
flex-direction: row-reverse; |
||||||
|
i{ |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
.text{ |
||||||
|
&:before{ |
||||||
|
content: ''; |
||||||
|
display: inline-block; |
||||||
|
padding-left: 25vw; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-table__placeholder + .text{ |
||||||
|
&:before{ |
||||||
|
padding-left: 26vw; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-table__expand-icon{ |
||||||
|
transform: rotate(90deg); |
||||||
|
&.el-table__expand-icon--expanded{ |
||||||
|
transform: rotate(-90deg); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,434 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="page"> |
||||||
|
<div class="tabs"> |
||||||
|
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a> |
||||||
|
</div> |
||||||
|
<div class="page-content"> |
||||||
|
<div v-if="active == 'first'"> |
||||||
|
<el-form> |
||||||
|
<ul class="list"> |
||||||
|
<li> |
||||||
|
<label>头像</label> |
||||||
|
<div class="avatar-wrap"> |
||||||
|
<img :src="this.$store.state.avatar" class="avatar" /> |
||||||
|
<el-upload :action="this.api.uploadUserAvatars" :data="{userId:this.userId}" name="file" :limit="3" :on-success="getRes"> |
||||||
|
<el-button size="small"><img src="../assets/img/upload.png" alt=""> 上传头像</el-button> |
||||||
|
</el-upload> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>姓名</label> |
||||||
|
<div> |
||||||
|
<el-input v-model="personalInformation.userName" clearable></el-input> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>性别</label> |
||||||
|
<div> |
||||||
|
<el-select v-model="personalInformation.sex"> |
||||||
|
<el-option v-for="item in sexList" :key="item.value" :label="item.name" :value="item.value"></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>所在国家</label> |
||||||
|
<div> |
||||||
|
<el-select |
||||||
|
v-model="personalInformation.countries" |
||||||
|
placeholder |
||||||
|
> |
||||||
|
<el-option |
||||||
|
v-for="item in countryList" |
||||||
|
:key="item.value" |
||||||
|
:label="item.label" |
||||||
|
:value="item.value" |
||||||
|
></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>所在省份</label> |
||||||
|
<div> |
||||||
|
<el-select |
||||||
|
v-model="personalInformation.provinceId" |
||||||
|
placeholder |
||||||
|
@change="id => getCity(id,1)" |
||||||
|
> |
||||||
|
<el-option |
||||||
|
v-for="item in provinceList" |
||||||
|
:key="item.provinceId" |
||||||
|
:label="item.provinceName" |
||||||
|
:value="item.provinceId" |
||||||
|
></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>所在省市</label> |
||||||
|
<div> |
||||||
|
<el-select |
||||||
|
v-model="personalInformation.cityId" |
||||||
|
placeholder |
||||||
|
:disabled="personalInformation.provinceId ? false : true" |
||||||
|
> |
||||||
|
<el-option |
||||||
|
v-for="item in cityList" |
||||||
|
:key="item.cityId" |
||||||
|
:label="item.cityName" |
||||||
|
:value="item.cityId" |
||||||
|
></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>出生年月日</label> |
||||||
|
<div> |
||||||
|
<el-date-picker |
||||||
|
v-model="personalInformation.dateBirth" |
||||||
|
:clearable="false" |
||||||
|
class="block-right" |
||||||
|
type="date"> |
||||||
|
</el-date-picker> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>证件</label> |
||||||
|
<div> |
||||||
|
<el-input v-model="personalInformation.idnumber" clearable></el-input> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>教育程度</label> |
||||||
|
<div> |
||||||
|
<el-select |
||||||
|
v-model="personalInformation.educationDegree" |
||||||
|
placeholder="请选择教育程度" |
||||||
|
> |
||||||
|
<el-option |
||||||
|
v-for="(item,index) in educationDegreeList" |
||||||
|
:key="index" |
||||||
|
:label="item.name" |
||||||
|
:value="item.value" |
||||||
|
></el-option> |
||||||
|
</el-select> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
<div v-else> |
||||||
|
<ul class="list"> |
||||||
|
<li> |
||||||
|
<label>用户账号</label> |
||||||
|
<div> |
||||||
|
<el-input v-model="personalInformation.account" clearable></el-input> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>手机号</label> |
||||||
|
<div> |
||||||
|
<el-input v-model="personalInformation.phone" clearable></el-input> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>邮箱</label> |
||||||
|
<div> |
||||||
|
<el-input v-model="personalInformation.email" clearable></el-input> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>密码</label> |
||||||
|
<div> |
||||||
|
<el-button size="small" @click="bindPassword">更换密码</el-button> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div style="margin-top: 32px"> |
||||||
|
<el-button type="primary" size="small" v-throttle @click="save">更新</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog |
||||||
|
title="更换密码" |
||||||
|
:visible.sync="passwordVisible" |
||||||
|
:close-on-click-modal="false" |
||||||
|
@close="closePassword" |
||||||
|
width="30%"> |
||||||
|
<el-form ref="passwordForm" :model="form" label-width="60px"> |
||||||
|
<el-form-item label="原密码"> |
||||||
|
<el-input type="password" v-model="passwordForm.password" placeholder="请输入原密码"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="新密码"> |
||||||
|
<el-input type="password" v-model="passwordForm.newPassword" placeholder="请输入新密码" @keyup.enter.native="editPassword"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="新密码"> |
||||||
|
<el-input type="password" v-model="passwordForm.reNewPassword" placeholder="请确认新密码" @keyup.enter.native="editPassword"></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button @click="passwordVisible = false">取 消</el-button> |
||||||
|
<el-button type="primary" @click="editPassword">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import _ from 'lodash'; |
||||||
|
import bus from '@/libs/bus' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
active: 'first', |
||||||
|
tabs: { |
||||||
|
first: '用户信息', |
||||||
|
second: '账号信息' |
||||||
|
}, |
||||||
|
userId: this.$store.state.userLoginId, |
||||||
|
personalInformation: { |
||||||
|
name:'', |
||||||
|
workNumber:'', |
||||||
|
password:"", |
||||||
|
phone:'', |
||||||
|
email:'', |
||||||
|
provinceName:'', |
||||||
|
cityName:'', |
||||||
|
schoolName:'', |
||||||
|
professionalName:'', |
||||||
|
}, |
||||||
|
passwordVisible: false, |
||||||
|
passwordForm: { |
||||||
|
password: '', |
||||||
|
newPassword: '', |
||||||
|
reNewPassword: '' |
||||||
|
}, |
||||||
|
sexList: [ |
||||||
|
{ |
||||||
|
name: '男', |
||||||
|
value: 1 |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '女', |
||||||
|
value: 2 |
||||||
|
} |
||||||
|
], |
||||||
|
countryList: [ |
||||||
|
{ |
||||||
|
label: '中国' |
||||||
|
} |
||||||
|
], |
||||||
|
form: {}, |
||||||
|
provinceList: this.$store.state.provinceList, //省份 |
||||||
|
cityList: [], //城市 |
||||||
|
// 教育程度 |
||||||
|
educationDegreeList: [ |
||||||
|
{ |
||||||
|
name: '专科', |
||||||
|
value: 1 |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '本科', |
||||||
|
value: 2 |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '硕士', |
||||||
|
value: 3 |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '博士', |
||||||
|
value: 4 |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '其他', |
||||||
|
value: 5 |
||||||
|
} |
||||||
|
], |
||||||
|
schoolList: [], |
||||||
|
curPassword: '', |
||||||
|
accountRepeat: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getdata(); |
||||||
|
this.getProvince() |
||||||
|
this.getSchoolData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
tabChange(index){ |
||||||
|
this.active = index |
||||||
|
}, |
||||||
|
getProvince(){ |
||||||
|
this.$get(this.api.queryProvince).then(res => { |
||||||
|
this.provinceList = res.data.list |
||||||
|
this.$store.commit("provinceData", { provinceList : this.provinceList}); |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
// 获取城市 |
||||||
|
getCity(id,type){ |
||||||
|
this.personalInformation.cityId = 1 |
||||||
|
this.getCityData() |
||||||
|
}, |
||||||
|
getCityData(index){ |
||||||
|
let provinceId = this.personalInformation.provinceId |
||||||
|
this.$get(this.api.queryCity,{provinceId}).then(res => { |
||||||
|
this.cityList = res.data.list |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
// 获取学校名称 |
||||||
|
getSchoolData(){ |
||||||
|
let data = { |
||||||
|
searchContent: '', |
||||||
|
provinceId: '', |
||||||
|
cityId: '' |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryClient}/1/1000`,data).then(res => { |
||||||
|
this.schoolList = res.data.list |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
accountChange(){ |
||||||
|
this.$get(`${this.api.getAccount}?account=${this.form.account}`).then(res => { |
||||||
|
if(res.data.userInfo){ |
||||||
|
this.accountRepeat = true |
||||||
|
this.warningMsg('该账号已存在') |
||||||
|
}else{ |
||||||
|
this.accountRepeat = false |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
//取得头像地址 |
||||||
|
getRes(res) { |
||||||
|
this.$store.commit('setAvatarData',{avatar:res.message}) |
||||||
|
bus.$emit('updateAvatar',res.message) |
||||||
|
let data = { |
||||||
|
userId: this.userId, |
||||||
|
userAvatars: res.message |
||||||
|
} |
||||||
|
this.$post(this.api.userinfoUpdate,data).then(res => {}).catch(res => {}) |
||||||
|
}, |
||||||
|
uploadHeadImg: function() { |
||||||
|
this.$el.querySelector('.hiddenInput').click(); |
||||||
|
}, |
||||||
|
getdata() { |
||||||
|
this.$get(`${this.api.userinfo}?userId=${this.userId}`) |
||||||
|
.then(res => { |
||||||
|
this.personalInformation = res.data.userInfo |
||||||
|
this.personalInformation.countries = '中国' |
||||||
|
this.curPassword = this.personalInformation.password |
||||||
|
this.$nextTick(() => { |
||||||
|
if(this.personalInformation.provinceId){ |
||||||
|
this.getCityData(1) |
||||||
|
} |
||||||
|
}) |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
console.log(err); |
||||||
|
}); |
||||||
|
}, |
||||||
|
bindPassword() { |
||||||
|
this.passwordVisible = true |
||||||
|
}, |
||||||
|
editPassword() { |
||||||
|
if(!this.passwordForm.password) return this.warningMsg('请输入原密码') |
||||||
|
if(!this.passwordForm.newPassword) return this.warningMsg('请输入新密码') |
||||||
|
if(!this.passwordForm.reNewPassword) return this.warningMsg('请确认新密码') |
||||||
|
if(this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return this.warningMsg('请输入6位数以上的密码') |
||||||
|
if(this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return this.warningMsg('输入的新密码不一致,请重新确认') |
||||||
|
if(this.curPassword === this.passwordForm.newPassword) return this.warningMsg('原密码跟新密码不能一致') |
||||||
|
|
||||||
|
let data = { |
||||||
|
userId: this.personalInformation.userId, |
||||||
|
password: this.passwordForm.password |
||||||
|
} |
||||||
|
this.$post(this.api.userinfoUpdate,data) |
||||||
|
.then(res => { |
||||||
|
if(res.success){ |
||||||
|
this.successMsg('更换成功') |
||||||
|
this.curPassword = this.passwordForm.newPassword |
||||||
|
this.passwordVisible = false |
||||||
|
}else{ |
||||||
|
this.errorMsg('更换失败') |
||||||
|
} |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
console.log(err); |
||||||
|
}); |
||||||
|
}, |
||||||
|
closePassword() { |
||||||
|
this.passwordForm = { |
||||||
|
password: '', |
||||||
|
newPassword: '', |
||||||
|
reNewPassword: '' |
||||||
|
} |
||||||
|
}, |
||||||
|
save() { |
||||||
|
if(this.personalInformation.idnumber && !/(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)/.test(this.personalInformation.idnumber)) return this.warningMsg('请输入正确的证件号码') |
||||||
|
if(this.accountRepeat) return this.warningMsg('该账号已存在') |
||||||
|
if(this.personalInformation.phone && !/^1[3456789]\d{9}$/.test(this.personalInformation.phone)) return this.warningMsg('请输入正确的手机号') |
||||||
|
if(this.personalInformation.email && !/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.personalInformation.email)) return this.warningMsg('请输入正确的邮箱') |
||||||
|
let personalInformation = this.personalInformation |
||||||
|
let userInfoEntity = { |
||||||
|
idnumber: personalInformation.idnumber, |
||||||
|
account: personalInformation.account, |
||||||
|
cityId: personalInformation.cityId, |
||||||
|
countries: personalInformation.countries, |
||||||
|
dateBirth: personalInformation.dateBirth, |
||||||
|
educationDegree: personalInformation.educationDegree, |
||||||
|
email: personalInformation.email, |
||||||
|
phone: personalInformation.phone, |
||||||
|
provinceId: personalInformation.provinceId, |
||||||
|
clientId: personalInformation.clientId, |
||||||
|
clientName: personalInformation.clientName, |
||||||
|
sex: personalInformation.sex, |
||||||
|
userId: personalInformation.userId, |
||||||
|
userName: personalInformation.userName, |
||||||
|
} |
||||||
|
let data = userInfoEntity |
||||||
|
this.$post(this.api.userinfoUpdate,data).then(res => { |
||||||
|
if(res.success){ |
||||||
|
this.successMsg('提交成功') |
||||||
|
this.$router.back() |
||||||
|
}else{ |
||||||
|
this.errorMsg('提交失败') |
||||||
|
} |
||||||
|
}).catch(res => {}) |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
/deep/.page{ |
||||||
|
.page-content{ |
||||||
|
padding-top: 0; |
||||||
|
.list{ |
||||||
|
li{ |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
padding: 16px 0; |
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
||||||
|
label{ |
||||||
|
width: 180px; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
.avatar-wrap{ |
||||||
|
display: inline-flex; |
||||||
|
align-items: center; |
||||||
|
.avatar{ |
||||||
|
width: 64px; |
||||||
|
height: 64px; |
||||||
|
margin-right: 24px; |
||||||
|
border-radius: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-input{ |
||||||
|
width: 320px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,281 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="tool"> |
||||||
|
<ul class="filter"> |
||||||
|
<li> |
||||||
|
<label>搜索:</label> |
||||||
|
<el-input placeholder="请输入角色名称" prefix-icon="el-icon-search" v-model="keyword" clearable size="small"></el-input> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" round @click="addRole" v-auth="'system:角色权限:新增角色'">新增角色</el-button> |
||||||
|
<el-button type="primary" size="small" round @click="delAllSelection" v-auth="'system:角色权限:批量删除'">批量删除</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table :data="roleData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" :row-key="getRowKeys"> |
||||||
|
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||||
|
<el-table-column type="index" width="100" label="序号" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="roleName" label="角色名称" align="center" width="100"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="角色描述" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-input disabled placeholder="该角色用于管理全部功能权限" v-model="scope.row.remark "></el-input> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" width="180" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="showRole(scope.row)" v-auth="'system:角色权限:查看'">查看</el-button> |
||||||
|
<template v-if="scope.row.id != 1"> |
||||||
|
<el-button type="text" @click="editRole(scope.row)" v-auth="'system:角色权限:编辑'">编辑</el-button> |
||||||
|
<el-button type="text" @click="handleDelete(scope.row)" v-auth="'system:角色权限:删除'">删除</el-button> |
||||||
|
</template> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background @current-change="currentChange" :current-page="pageNo" layout="total, prev, pager, next" :total="totals"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog :title="isDetail ? '查看角色' : (isAdd ? '新增角色' : '编辑角色')" :visible.sync="roleVisible" |
||||||
|
width="30%" @close="closeRole" class="dialog" :close-on-click-modal="false"> |
||||||
|
<el-form ref="form" :model="form" label-width="100px" :disabled="isDetail"> |
||||||
|
<el-form-item label="角色名称"> |
||||||
|
<el-input v-model="form.roleName " ref="account" placeholder="请输入角色名称"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="角色描述"> |
||||||
|
<el-input v-model="form.remark " placeholder="请输入角色描述" type="textarea" rows="5"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="role" label="角色权限"> |
||||||
|
<div class="per-wrap"> |
||||||
|
<el-tree |
||||||
|
ref="per" |
||||||
|
:data="permissions" |
||||||
|
show-checkbox |
||||||
|
node-key="id" |
||||||
|
:default-expanded-keys="checkedIds" |
||||||
|
:default-checked-keys="checkedIds" |
||||||
|
:props="defaultProps"> |
||||||
|
</el-tree> |
||||||
|
</div> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer" v-if="!isDetail"> |
||||||
|
<el-button size="small" @click="roleVisible = false">取 消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="saveData">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'role', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
clientId: this.$store.state.schoolId, |
||||||
|
keyword: '', |
||||||
|
form: { |
||||||
|
roleName : '', |
||||||
|
remark : '', |
||||||
|
id: '' |
||||||
|
}, |
||||||
|
isDetail: false, |
||||||
|
roleData:[], |
||||||
|
defaultProps: { |
||||||
|
children: 'children', |
||||||
|
label: 'name' |
||||||
|
}, |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0, |
||||||
|
multipleSelection: [], |
||||||
|
importVisible: false, |
||||||
|
isAdd: true, |
||||||
|
roleVisible: false, |
||||||
|
searchTimer: null, |
||||||
|
permissions: [], |
||||||
|
checkedIds: [] |
||||||
|
}; |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer) |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.getData() |
||||||
|
},500) |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
let data = { |
||||||
|
clientId: this.clientId |
||||||
|
} |
||||||
|
if(this.keyword.length){ |
||||||
|
data.name = this.keyword |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryRoles}/${this.pageNo}/${this.pageSize}`,data).then(res => { |
||||||
|
this.roleData = res.data.items |
||||||
|
this.totals = res.data.total |
||||||
|
if(!this.roleData.length && this.totals){ |
||||||
|
this.pageNo-- |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
closeRole(){ |
||||||
|
this.isDetail = false |
||||||
|
this.form = { |
||||||
|
roleName : '', |
||||||
|
remark : '', |
||||||
|
id: '' |
||||||
|
} |
||||||
|
this.checkedIds = [] |
||||||
|
this.permissions = [] |
||||||
|
}, |
||||||
|
currentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
getPer(){ |
||||||
|
if(!this.permissions.length){ |
||||||
|
this.$get(this.api.queryPermissionMenu).then(res => { |
||||||
|
this.permissions = res.data.children[0].children |
||||||
|
}).catch(res => {}) |
||||||
|
} |
||||||
|
}, |
||||||
|
addRole(){ |
||||||
|
this.isAdd = true |
||||||
|
this.getPer() |
||||||
|
this.checkedIds = [] |
||||||
|
this.permissions.length && this.$refs.per.setCheckedNodes([]) |
||||||
|
this.roleVisible = true |
||||||
|
}, |
||||||
|
handleRolePer(data,permissions){ |
||||||
|
let result = data |
||||||
|
if(permissions.length){ |
||||||
|
permissions.map(e => { |
||||||
|
if(result.includes(e.id) && e.children.length){ |
||||||
|
e.children.every(n => result.includes(n)) || result.splice(result.indexOf(e.id),1) |
||||||
|
} |
||||||
|
e.children.length && this.handleRolePer(data,e.children) |
||||||
|
}) |
||||||
|
} |
||||||
|
return result |
||||||
|
}, |
||||||
|
async getDetail(row){ |
||||||
|
this.getPer() |
||||||
|
let roleRes = await this.$get(`${this.api.getRole}/${row.id}`) |
||||||
|
if(roleRes.success){ |
||||||
|
this.form = roleRes.data.item |
||||||
|
let perRes = await this.$get(`${this.api.toAssign}/${row.id}`) |
||||||
|
if(perRes.success){ |
||||||
|
this.checkedIds = this.handleRolePer(perRes.data.rolePermissions,this.permissions) |
||||||
|
this.$refs.per.setCheckedNodes(this.checkedIds) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
showRole(row){ |
||||||
|
this.isDetail = true |
||||||
|
this.isAdd = false |
||||||
|
this.getDetail(row) |
||||||
|
this.roleVisible = true |
||||||
|
}, |
||||||
|
editRole(row){ |
||||||
|
this.isAdd = false |
||||||
|
this.getDetail(row) |
||||||
|
this.roleVisible = true |
||||||
|
}, |
||||||
|
async saveData() { |
||||||
|
if(!this.form.roleName) return this.warningMsg('请填写角色名称') |
||||||
|
if(!this.form.remark) return this.warningMsg('请填写角色描述') |
||||||
|
// if(!this.$refs.per.getCheckedKeys().length) return this.warningMsg('请选择角色权限') |
||||||
|
let roleData = { |
||||||
|
clientId: this.clientId, |
||||||
|
id: this.form.id, |
||||||
|
roleName: this.form.roleName, |
||||||
|
remark: this.form.remark, |
||||||
|
isPort: 1 |
||||||
|
} |
||||||
|
let roleRes = await this.$post(this.api.saveOrUpdate,roleData) |
||||||
|
if(roleRes.success){ |
||||||
|
let permissionId = [...this.$refs.per.getHalfCheckedKeys(),...this.$refs.per.getCheckedKeys()] |
||||||
|
let perData = { |
||||||
|
clientId: this.clientId, |
||||||
|
roleId: roleRes.data.roleId, |
||||||
|
permissionId, |
||||||
|
isPort: 1 |
||||||
|
} |
||||||
|
let perRes = await this.$post(this.api.doAssign,perData) |
||||||
|
if(perRes.success){ |
||||||
|
this.successMsg('新增成功') |
||||||
|
this.getData() |
||||||
|
this.roleVisible = false |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
handleDelete(row) { |
||||||
|
this.$confirm('该角色下已有账号,删除角色会将该角色下的账号一并删除,是否继续删除?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.removeRole}?roleIds=${row.id}`).then(res => { |
||||||
|
if(res.success){ |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}) |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
getRowKeys(row) { |
||||||
|
return row.id; |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
delAllSelection() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
// 批量删除 |
||||||
|
this.$confirm(`此批量删除操作不可逆,是否确认删除${newArr[0].roleName}等${newArr.length}个选中项?`, '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$del(`${this.api.removeRole}?roleIds=${delList.join()}`).then(res => { |
||||||
|
if(res.success){ |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}) |
||||||
|
}).catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !'); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.no-mb /deep/.el-form-item{ |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
/deep/.el-row{ |
||||||
|
padding: 0 !important; |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
.per-wrap{ |
||||||
|
max-height: 300px; |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,671 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="tool"> |
||||||
|
<ul class="filter"> |
||||||
|
<li> |
||||||
|
<label>筛选:</label> |
||||||
|
<el-cascader :options="orgList" :props="props" collapse-tags clearable size="small" @change="orgChange"></el-cascader> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<label>搜索:</label> |
||||||
|
<el-input style="width: 250px" placeholder="请输入员工姓名/工号/角色名称" v-model="keyword" suffix-icon="el-icon-search" clearable size="small"></el-input> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" round @click="addTeacher" v-auth="'system:员工管理:新增员工'">新增员工</el-button> |
||||||
|
<el-button type="primary" size="small" round @click="batchImport" v-auth="'system:员工管理:批量导入'">批量导入</el-button> |
||||||
|
<el-button type="primary" size="small" round @click="delAllSelection" v-auth="'system:员工管理:批量删除'">批量删除</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange"> |
||||||
|
<el-table-column type="selection" width="80" align="center"></el-table-column> |
||||||
|
<el-table-column type="index" label="序号" width="55" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="userName" label="职工姓名" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="account" label="账号" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="workNumber" label="职工工号" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="staffProfessionalArchitectureName" label="一级部门" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="staffGradeName" label="二级部门" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="roleName" label="角色" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="lastLoginTime" label="上次登录时间" width="160" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" width="160" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="showTeacher(scope.row)" v-auth="'system:员工管理:查看'">查看</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'system:员工管理:查看'"></el-divider> |
||||||
|
<el-button type="text" @click="editTeacher(scope.row)" v-auth="'system:员工管理:编辑'">编辑</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'system:员工管理:编辑'"></el-divider> |
||||||
|
<el-button type="text" @click="delTeacher(scope.row)" v-auth="'system:员工管理:删除'">删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background layout="total,prev, pager, next" :current-page="pageNo" @current-change="handleCurrentChange" :total="total"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog :title="isDetail ? '查看员工' : (isAddManage ? '新增员工' : '编辑员工')" :visible.sync="manageVisible" width="500px" @close="closeTeacher" class="dialog" :close-on-click-modal="false"> |
||||||
|
<el-form ref="manageForm" :model="manageForm" :rules="rules" label-width="120px" label-suffix=":" :disabled="isDetail"> |
||||||
|
<el-form-item prop="userAccount" label="账号"> |
||||||
|
<el-input v-model="manageForm.userAccount" ref="account" placeholder="请输入职工账号" @change="accountChange" maxlength="20"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="userName" label="用户姓名"> |
||||||
|
<el-input v-model="manageForm.userName" placeholder="请输入员工姓名"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="roleValue" label="账号角色"> |
||||||
|
<el-select v-model="manageForm.roleValue" placeholder="请选择账号角色"> |
||||||
|
<el-option v-for="(item,index) in roleList" :key="index" :label="item.roleName" :value="item.id"></el-option> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="uniqueIdentificationAccount" label="唯一标识"> |
||||||
|
<el-input disabled v-model="manageForm.uniqueIdentificationAccount" placeholder="请输入职工工号获取唯一标识"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="workNumber" label="职工工号"> |
||||||
|
<el-input v-model="manageForm.workNumber" placeholder="请输入职工工号" @change="workNumberChange"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="major" label="一级部门"> |
||||||
|
<el-select v-model="manageForm.major" placeholder="请选择一级部门" @change="getDepartment"> |
||||||
|
<el-option v-for="(item,index) in orgList" :key="index" |
||||||
|
:label="item.staffProfessionalArchitectureName" :value="item.staffProfessionalArchitectureId"></el-option> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="managerDepartment" label="二级部门"> |
||||||
|
<el-select v-model="manageForm.managerDepartment" placeholder="请选择二级部门" :disabled="manageForm.major ? false : true"> |
||||||
|
<el-option v-for="(item,index) in managerDepartmentList" :key="index" |
||||||
|
:label="item.staffGradeName" :value="item.staffGradeId"></el-option> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item prop="phone" label="手机号"> |
||||||
|
<el-input v-model="manageForm.phone" placeholder="请输入手机号" maxlength="11"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="email" label="邮箱"> |
||||||
|
<el-input v-model="manageForm.email" placeholder="请输入邮箱"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="email" label="默认密码"> |
||||||
|
<el-input v-model="password" disabled></el-input> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer" v-if="!isDetail"> |
||||||
|
<el-button size="small" @click="manageVisible = false">取 消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="saveSure('manageForm')">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog title="查看员工" :visible.sync="staffShowVisible" width="500px" :close-on-click-modal="false"> |
||||||
|
<ul class="list"> |
||||||
|
<li> |
||||||
|
<span class="name"><i class="required">*</i>账号:</span> |
||||||
|
<span class="val">{{manageForm.userAccount}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name"><i class="required">*</i>用户姓名:</span> |
||||||
|
<span class="val">{{manageForm.userName}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name">账号角色:</span> |
||||||
|
<span class="val">{{manageForm.roleValue ? roleList.find(n => n.id == manageForm.roleValue).roleName : ''}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name">唯一标识:</span> |
||||||
|
<span class="val">{{manageForm.uniqueIdentificationAccount}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name"><i class="required">*</i>职工工号:</span> |
||||||
|
<span class="val">{{manageForm.workNumber}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name"><i class="required">*</i>一级部门:</span> |
||||||
|
<span class="val">{{manageForm.major ? orgList.find(n => n.staffProfessionalArchitectureId == manageForm.major).staffProfessionalArchitectureName : ''}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name"><i class="required">*</i>二级部门:</span> |
||||||
|
<span class="val">{{manageForm.managerDepartment ? managerDepartmentList.find(n => n.staffGradeId == manageForm.managerDepartment).staffGradeName : ''}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name">手机号:</span> |
||||||
|
<span class="val">{{manageForm.phone}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name">邮箱:</span> |
||||||
|
<span class="val">{{manageForm.email}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name">默认密码:</span> |
||||||
|
<span class="val">{{password}}</span> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog title="批量导入" :visible.sync="importVisible" width="400px" :close-on-click-modal="false"> |
||||||
|
<div class="upload-wrap" :class="{lg: uploadFaild}"> |
||||||
|
<el-button class="download" size="small" @click="downLoad"><img src="../assets/img/download.png" alt=""> 模板下载</el-button> |
||||||
|
<el-upload accept=".xls,.xlsx" :on-remove="handleRemove" :on-error="uploadError" :on-success="uploadSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.uploadFileStaff" :file-list="uploadList" :data="{schoolId: this.schoolId}" name="file"> |
||||||
|
<el-button size="small"><img src="../assets/img/upload.png" alt=""> 上传文件</el-button> |
||||||
|
</el-upload> |
||||||
|
<div class="link" v-if="uploadFaild"> |
||||||
|
<el-link type="primary" @click="showFaild">导入失败,查看原因</el-link> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="importVisible = false">取 消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="uploadSure">确 定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import Setting from '@/setting'; |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
pages: 10, |
||||||
|
schoolId: this.$store.state.schoolId, |
||||||
|
props: { multiple: true }, |
||||||
|
orgList: [], |
||||||
|
isDetail: false, |
||||||
|
isAddManage: false, |
||||||
|
manageVisible: false, |
||||||
|
roleList: [ |
||||||
|
{ |
||||||
|
id: '1', |
||||||
|
roleName: '超级管理员(系统默认)' |
||||||
|
},{ |
||||||
|
id: '2', |
||||||
|
roleName: '普通管理员(系统默认)' |
||||||
|
} |
||||||
|
], |
||||||
|
manageForm: { |
||||||
|
clientId: this.$store.state.schoolId, |
||||||
|
clientName: this.$store.state.schoolName, |
||||||
|
manageId: '', |
||||||
|
userName: '', |
||||||
|
roleValue: '', |
||||||
|
phone: '', |
||||||
|
uniqueIdentificationAccount: '', |
||||||
|
workNumber: '', |
||||||
|
email: '', |
||||||
|
major: '', |
||||||
|
managerDepartment: '', |
||||||
|
userAccount: '', |
||||||
|
major: '', |
||||||
|
schoolId: this.schoolId |
||||||
|
}, |
||||||
|
rules: { |
||||||
|
userAccount: [ |
||||||
|
{ required: true, message: '请输入账号', trigger: 'blur' }, |
||||||
|
{ |
||||||
|
pattern: /^[A-Za-z0-9]+$/, |
||||||
|
message: '请输入正确的账号', |
||||||
|
trigger: 'blur' |
||||||
|
} |
||||||
|
], |
||||||
|
userName: [ |
||||||
|
{ required: true, message: '请输入用户姓名', trigger: 'blur' } |
||||||
|
], |
||||||
|
roleValue: [ |
||||||
|
{ required: true, message: '请选择账号角色', trigger: 'change' } |
||||||
|
], |
||||||
|
uniqueIdentificationAccount: [ |
||||||
|
// { required: true, message: '请输入唯一标识', trigger: 'blur' }, |
||||||
|
], |
||||||
|
major: [ |
||||||
|
{ required: true, message: '请选择一级部门', trigger: 'change' } |
||||||
|
], |
||||||
|
workNumber: [ |
||||||
|
{ required: true, message: '请输入职工工号', trigger: 'blur' }, |
||||||
|
{ |
||||||
|
pattern: /^[A-Za-z0-9]+$/, |
||||||
|
message: '请输入正确的职工工号', |
||||||
|
trigger: 'blur' |
||||||
|
} |
||||||
|
], |
||||||
|
managerDepartment: [ |
||||||
|
{ required: true, message: '请选择二级部门', trigger: 'change' } |
||||||
|
], |
||||||
|
phone: [ |
||||||
|
// { required: true, message: '请输入职工手机号', trigger: 'blur' }, |
||||||
|
{ |
||||||
|
pattern: /^1[3456789]\d{9}$/, |
||||||
|
message: '请输入正确的手机号', |
||||||
|
trigger: 'blur' |
||||||
|
} |
||||||
|
], |
||||||
|
email: [ |
||||||
|
// { required: true, message: '请输入邮箱', trigger: 'blur' }, |
||||||
|
{ |
||||||
|
pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/, |
||||||
|
message: '请输入正确的邮箱', |
||||||
|
trigger: 'blur' |
||||||
|
} |
||||||
|
], |
||||||
|
// schoolId: [ |
||||||
|
// { required: true, message: '请选择所在院校', trigger: 'change' } |
||||||
|
// ], |
||||||
|
}, |
||||||
|
staffShowVisible: false, |
||||||
|
listData: [], |
||||||
|
importVisible: false, |
||||||
|
keyword: '', |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
total: 0, |
||||||
|
managerDepartmentList: [], |
||||||
|
teacherDepartmentList: [], |
||||||
|
staffstateProfessId: '', |
||||||
|
staffGradeId: '', |
||||||
|
multipleSelection: [], |
||||||
|
uploadList: [], |
||||||
|
provinceId: this.$store.state.provinceId, |
||||||
|
cityId: this.$store.state.cityId, |
||||||
|
userId: this.$store.state.userId, |
||||||
|
oneDepartmentIds: '', |
||||||
|
twoDepartmentIds: '', |
||||||
|
ProfessionalClassList: [], |
||||||
|
subjectList: [], |
||||||
|
ProfessionalList: [], |
||||||
|
NoAdd: '', |
||||||
|
AccountNoAdd: '', |
||||||
|
NumberNoAdd: '', |
||||||
|
platformId: this.$store.state.platformId, |
||||||
|
schoolList: [], |
||||||
|
uploadFaild: false, |
||||||
|
token: '', |
||||||
|
accountRepeat: false, |
||||||
|
workNumberRepeat: false, |
||||||
|
originalAccount: '', |
||||||
|
originalWorkNumber: '', |
||||||
|
password: Setting.initialPassword, |
||||||
|
submiting: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer) |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.initData() |
||||||
|
},500) |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted(){ |
||||||
|
this.getOrg() |
||||||
|
this.getData() |
||||||
|
this.getRoles() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getOrg(){ |
||||||
|
let data = { |
||||||
|
schoolId: this.schoolId |
||||||
|
} |
||||||
|
this.$get(this.api.queryStaffPro,data).then(res => { |
||||||
|
let firList = res.data.StaffProfessionalArchitectureList |
||||||
|
if(firList){ |
||||||
|
firList.map(e => { |
||||||
|
e.isParent = true |
||||||
|
e.value = e.staffProfessionalArchitectureId |
||||||
|
e.label = e.staffProfessionalArchitectureName |
||||||
|
let data = { |
||||||
|
staffProfessionalArchitectureId: e.staffProfessionalArchitectureId |
||||||
|
} |
||||||
|
this.$get(this.api.queryStaffGrade,data).then(res1 => { |
||||||
|
res1.data.staffGradeList.map(e => { |
||||||
|
e.value = e.staffGradeId |
||||||
|
e.label = e.staffGradeName |
||||||
|
}) |
||||||
|
e.children = res1.data.staffGradeList |
||||||
|
}).catch(res => {}) |
||||||
|
}) |
||||||
|
setTimeout(() => { |
||||||
|
this.orgList = firList |
||||||
|
},500) |
||||||
|
} |
||||||
|
}).catch(res => {}) |
||||||
|
}, |
||||||
|
getData(){ |
||||||
|
let data = { |
||||||
|
staffProfessionalArchitectureIds: this.oneDepartmentIds, |
||||||
|
staffGradeIds: this.twoDepartmentIds, |
||||||
|
searchContent: this.keyword, |
||||||
|
schoolId: this.schoolId |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryStaff}/${this.pageNo}/${this.pageSize}`,data).then(res => { |
||||||
|
this.listData = res.data.staffList |
||||||
|
this.total = res.data.total |
||||||
|
if(!this.listData.length && this.total){ |
||||||
|
this.pageNo-- |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
initData(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
orgChange(node){ |
||||||
|
this.twoDepartmentIds = node.map(n => n[1]).toString() |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
getRoles() { |
||||||
|
this.$get(this.api.getRoles,{clientId: this.schoolId}).then(res => { |
||||||
|
this.roleId = res.data.data[0].id |
||||||
|
this.roleList = this.roleList.concat(res.data.data) |
||||||
|
}) |
||||||
|
}, |
||||||
|
getSchoolData(){ |
||||||
|
let data = { |
||||||
|
schoolName: '' |
||||||
|
} |
||||||
|
this.$get(this.api.querySchool,data).then(res => { |
||||||
|
this.schoolList = res.message |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
closeTeacher(){ |
||||||
|
this.$refs.manageForm.resetFields() |
||||||
|
this.manageForm.managerDepartment = '' |
||||||
|
this.manageForm.major = '' |
||||||
|
this.manageForm.workNumber = '' |
||||||
|
this.manageForm.teacherDepartment = '' |
||||||
|
this.manageForm.teacherMajor = '' |
||||||
|
this.manageForm.teacherWorkNumber = '' |
||||||
|
this.manageForm.userId = '' |
||||||
|
this.manageForm.staffId = '' |
||||||
|
}, |
||||||
|
addTeacher(){ |
||||||
|
this.isDetail = false |
||||||
|
this.manageVisible = true |
||||||
|
this.isAddManage = true |
||||||
|
this.manageForm.manageId = '' |
||||||
|
}, |
||||||
|
getStaffDetail(userId){ |
||||||
|
this.$get(`${this.api.getStaff}/${userId}`).then(res => { |
||||||
|
let user = res.data.userInfo; |
||||||
|
let or = res.data.staff; |
||||||
|
this.manageForm.uniqueIdentificationAccount = user.uniqueIdentificationAccount |
||||||
|
this.manageForm.clientId = user.clientId |
||||||
|
this.manageForm.clientName = user.clientName |
||||||
|
this.manageForm.userName = user.userName |
||||||
|
this.manageForm.phone = user.phone |
||||||
|
this.manageForm.email = user.email |
||||||
|
this.manageForm.userAccount = user.account |
||||||
|
this.originalAccount = Number(user.account) |
||||||
|
this.manageForm.userId = user.userId |
||||||
|
this.manageForm.schoolId = user.schoolId |
||||||
|
this.manageForm.roleValue = or.roleId |
||||||
|
|
||||||
|
this.manageForm.major = or.staffProfessionalArchitectureId |
||||||
|
this.manageForm.managerDepartment = or.staffGradeId |
||||||
|
this.manageForm.workNumber = or.workNumber |
||||||
|
this.originalWorkNumber = or.workNumber |
||||||
|
this.manageForm.staffId = or.staffId |
||||||
|
this.getDepartment(1) |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
editTeacher(row){ |
||||||
|
this.isDetail = false |
||||||
|
this.manageVisible = true |
||||||
|
this.isAddManage = false |
||||||
|
this.AccountNoAdd = false |
||||||
|
this.manageForm.manageId = row.staffId |
||||||
|
this.getStaffDetail(row.staffId) |
||||||
|
}, |
||||||
|
showTeacher(row){ |
||||||
|
this.staffShowVisible = true |
||||||
|
this.isDetail = true |
||||||
|
this.isAddManage = false |
||||||
|
this.AccountNoAdd = false |
||||||
|
this.manageForm.manageId = row.staffId |
||||||
|
this.getStaffDetail(row.staffId) |
||||||
|
}, |
||||||
|
getDepartment(isDetail){ |
||||||
|
if(!isDetail) this.manageForm.managerDepartment = '' |
||||||
|
let data = { |
||||||
|
staffProfessionalArchitectureId: this.manageForm.major |
||||||
|
} |
||||||
|
this.$get(this.api.queryStaffGrade,data).then(res => { |
||||||
|
this.managerDepartmentList = res.data.staffGradeList |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
accountChange(){ |
||||||
|
if(this.manageForm.userAccount !== this.originalAccount){ |
||||||
|
this.$get(`${this.api.getAccount}?account=${this.manageForm.userAccount}`).then(res => { |
||||||
|
if(res.data.userInfo){ |
||||||
|
this.accountRepeat = true |
||||||
|
this.warningMsg('该账号已存在') |
||||||
|
}else{ |
||||||
|
this.accountRepeat = false |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
this.accountRepeat = false |
||||||
|
} |
||||||
|
}, |
||||||
|
workNumberChange(){ |
||||||
|
if(this.manageForm.workNumber !== this.originalWorkNumber){ |
||||||
|
this.$get(`${this.api.getWorkNumber}?workNumber=${this.manageForm.workNumber}`).then(res => { |
||||||
|
if(res.data.staff){ |
||||||
|
this.workNumberRepeat = true |
||||||
|
this.warningMsg('该工号已存在') |
||||||
|
}else{ |
||||||
|
this.workNumberRepeat = false |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
this.workNumberRepeat = false |
||||||
|
} |
||||||
|
}, |
||||||
|
async saveSure(manageForm){ |
||||||
|
if(this.submiting) return false |
||||||
|
this.$refs[manageForm].validate((valid) => { |
||||||
|
if (valid) { |
||||||
|
if(this.accountRepeat) return this.warningMsg('该账号已存在') |
||||||
|
if(this.workNumberRepeat) return this.warningMsg('该工号已存在') |
||||||
|
let data = { |
||||||
|
userInfo: { |
||||||
|
userId: this.manageForm.userId, |
||||||
|
userName: this.manageForm.userName, |
||||||
|
account: this.manageForm.userAccount, |
||||||
|
schoolId: this.schoolId, |
||||||
|
clientId: this.manageForm.clientId, |
||||||
|
clientName: this.manageForm.clientName, |
||||||
|
roleId: this.manageForm.roleValue, |
||||||
|
phone: this.manageForm.phone, |
||||||
|
email: this.manageForm.email, |
||||||
|
isPort: 1, |
||||||
|
uniqueIdentificationAccount: this.manageForm.uniqueIdentificationAccount ? this.manageForm.uniqueIdentificationAccount : Date.parse(new Date()), |
||||||
|
} |
||||||
|
} |
||||||
|
let oneDepartmentName = ''; |
||||||
|
for(let i in this.orgList){ |
||||||
|
if(this.orgList[i].staffProfessionalArchitectureId == this.manageForm.major) { |
||||||
|
oneDepartmentName = this.orgList[i].staffProfessionalArchitectureName |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
let twoDepartmentName = this.managerDepartmentList.find((n) => { |
||||||
|
return n.staffGradeId == this.manageForm.managerDepartment |
||||||
|
}).staffGradeName; |
||||||
|
data.staff = { |
||||||
|
roleId: this.manageForm.roleValue, |
||||||
|
isPort: 1, |
||||||
|
schoolId: this.schoolId, |
||||||
|
clientId: this.manageForm.clientId, |
||||||
|
clientName: this.manageForm.clientName, |
||||||
|
staffId: this.manageForm.staffId, |
||||||
|
userId: this.manageForm.userId, |
||||||
|
workNumber: this.manageForm.workNumber, |
||||||
|
staffProfessionalArchitectureId: this.manageForm.major, |
||||||
|
staffGradeId: this.manageForm.managerDepartment, |
||||||
|
staffProfessionalArchitectureName: oneDepartmentName, |
||||||
|
staffGradeName: twoDepartmentName, |
||||||
|
}; |
||||||
|
this.submiting = true |
||||||
|
|
||||||
|
if(this.manageForm.manageId){ |
||||||
|
this.$post(this.api.updateStaff,data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
this.manageVisible = false |
||||||
|
this.successMsg('编辑成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => { |
||||||
|
this.submiting = false |
||||||
|
}); |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addStaff,data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
this.manageVisible = false |
||||||
|
this.successMsg('添加成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => { |
||||||
|
this.submiting = false |
||||||
|
}); |
||||||
|
} |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
}) |
||||||
|
}, |
||||||
|
delTeacher(row){ |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
let data = { |
||||||
|
staffIds: row.staffId |
||||||
|
} |
||||||
|
this.$del(this.api.deleteStaffs,data).then(res => { |
||||||
|
this.successMsg('删除成功') |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
delAllSelection() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.staffId |
||||||
|
}) |
||||||
|
// 批量删除 |
||||||
|
this.$confirm(`此批量删除操作不可逆,是否确认删除${newArr[0].userName}等${newArr.length}个选中项?`, '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
let data = { |
||||||
|
staffIds: delList.join(',') |
||||||
|
} |
||||||
|
this.$del(this.api.deleteStaffs,data).then(res => { |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
this.successMsg('删除成功') |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}).catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !') |
||||||
|
} |
||||||
|
}, |
||||||
|
batchImport(){ |
||||||
|
this.importVisible = true |
||||||
|
this.uploadList = [] |
||||||
|
this.uploadFaild = false |
||||||
|
}, |
||||||
|
searchTeacher(){ |
||||||
|
this.pageNo = 1; |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
handleCurrentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
downLoad(){ |
||||||
|
location.href = this.api.downloadStaffTemp |
||||||
|
}, |
||||||
|
showFaild(){ |
||||||
|
location.href = `${this.api.exportFailureStaff}?token=${this.token}` |
||||||
|
}, |
||||||
|
// 上传文件 |
||||||
|
handleExceed(files, fileList) { |
||||||
|
this.warningMsg( |
||||||
|
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||||
|
); |
||||||
|
}, |
||||||
|
uploadSuccess(res, file, fileList) { |
||||||
|
this.uploadFaild = false |
||||||
|
if(res.success){ |
||||||
|
if(res.data.data.token){ |
||||||
|
this.token = res.data.data.token |
||||||
|
this.uploadFaild = true |
||||||
|
}else{ |
||||||
|
this.successMsg('上传成功') |
||||||
|
} |
||||||
|
}else{ |
||||||
|
res.data.message ? this.errorMsg(res.data.message) : this.errorMsg('上传失败,请检查数据') |
||||||
|
} |
||||||
|
}, |
||||||
|
uploadError(err, file, fileList) { |
||||||
|
this.$message({ |
||||||
|
message: "上传出错,请重试!", |
||||||
|
type: "error", |
||||||
|
center: true |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeRemove(file, fileList) { |
||||||
|
return this.$confirm(`确定移除 ${file.name}?`); |
||||||
|
}, |
||||||
|
handleRemove(file, fileList) { |
||||||
|
this.uploadList = fileList |
||||||
|
this.uploadFaild = false |
||||||
|
}, |
||||||
|
uploadSure(){ |
||||||
|
this.importVisible = false |
||||||
|
this.pageNo = 1 |
||||||
|
this.keyword = '' |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
/deep/.dialog{ |
||||||
|
.el-form-item{ |
||||||
|
.el-form-item__label{ |
||||||
|
font-size: 16px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
&:before{ |
||||||
|
margin-right: 0; |
||||||
|
color: #CC221C; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.el-input,.el-select{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
.list{ |
||||||
|
li{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
margin: 32px 0; |
||||||
|
.name,.val{ |
||||||
|
font-size: 16px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
} |
||||||
|
.name{ |
||||||
|
width: 45%; |
||||||
|
text-align: right; |
||||||
|
} |
||||||
|
.val{ |
||||||
|
width: 55%; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,68 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'平台分管设置/' + tabs[active]" ref="breadcrumb"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="tabs" v-if="showTabs"> |
||||||
|
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a> |
||||||
|
</div> |
||||||
|
<div class="page-content"> |
||||||
|
<staff v-if="active == 'staff'" v-auth="'平台分管设置:员工管理'"></staff> |
||||||
|
<role v-else-if="active == 'role'" v-auth="'平台分管设置:角色权限'"></role> |
||||||
|
<organization v-else v-auth="'平台分管设置:角色权限'"></organization> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Setting from '@/setting' |
||||||
|
import staff from './staff.vue' |
||||||
|
import role from './role.vue' |
||||||
|
import organization from './organization.vue' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
active: 'staff', |
||||||
|
userId: this.$store.state.userId, |
||||||
|
tabs: { |
||||||
|
staff: '员工管理', |
||||||
|
role: '角色权限', |
||||||
|
organization: '架构管理' |
||||||
|
}, |
||||||
|
showTabs: true |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { |
||||||
|
staff, |
||||||
|
role, |
||||||
|
organization, |
||||||
|
breadcrumb |
||||||
|
}, |
||||||
|
created() { |
||||||
|
Setting.dynamicRoute && this.initTabs() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
tabChange(index){ |
||||||
|
this.active = index |
||||||
|
this.$refs.breadcrumb.update('平台分管设置/' + this.tabs[this.active]) |
||||||
|
}, |
||||||
|
initTabs(){ |
||||||
|
let btnPermissions = this.$store.state.btnPermissions |
||||||
|
let showStaff = btnPermissions.includes('平台分管设置:员工管理') |
||||||
|
let showRole = btnPermissions.includes('平台分管设置:角色权限') |
||||||
|
|
||||||
|
if(!showStaff || !showRole){ |
||||||
|
this.showTabs = false |
||||||
|
} |
||||||
|
!showStaff && showRole && (this.active = 'role') |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.tabs{ |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,474 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<breadcrumb :data="'学校用户管理/用户列表'"></breadcrumb> |
||||||
|
<div class="page"> |
||||||
|
<div class="p-title">用户列表</div> |
||||||
|
<div class="page-content"> |
||||||
|
<div class="tool"> |
||||||
|
<ul class="filter"> |
||||||
|
<li> |
||||||
|
<label>搜索:</label> |
||||||
|
<el-input placeholder="请输入所属学校/用户姓名" suffix-icon="el-icon-search" v-model="keyword" clearable size="small"></el-input> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div> |
||||||
|
<el-button type="primary" size="small" round @click="adduser" v-auth>新增用户</el-button> |
||||||
|
<el-button type="primary" size="small" round @click="batchImport" v-auth>批量导入</el-button> |
||||||
|
<el-button type="primary" size="small" round @click="delAllSelection" v-auth>批量删除</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-table :data="userData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||||
|
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||||
|
<el-table-column type="index" width="80" label="序号" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="clientName" label="所属学校"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="name" label="姓名" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="account" label="账号" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="role" label="账号角色" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{roleStatus(scope.row.roleId)}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="loginNumber" label="登录次数" align="center"> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="lastLoginTime" label="上次登录时间" align="center"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
{{scope.row.lastLoginTime == '0000-00-00 00:00:00' ? '' : scope.row.lastLoginTime}} |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="240"> |
||||||
|
<template slot-scope="scope"> |
||||||
|
<el-button type="text" @click="show(scope.row)" v-auth>查看</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'user:查看'"></el-divider> |
||||||
|
<el-button type="text" @click="edit(scope.row)" v-auth>编辑</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'user:编辑'"></el-divider> |
||||||
|
<el-button type="text" @click="resetPassword(scope.row)" v-auth>重置密码</el-button> |
||||||
|
<el-divider direction="vertical" v-auth="'user:重置密码'"></el-divider> |
||||||
|
<el-button type="text" @click="handleDelete(scope.row)" v-auth>删除</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<div class="pagination"> |
||||||
|
<el-pagination background @current-change="currentChange" :current-page="pageNo" layout="total, prev, pager, next" :total="totals"> |
||||||
|
</el-pagination> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog :title="isAdd ? '新增用户' : '编辑用户'" :visible.sync="userVisible" |
||||||
|
width="500px" @close="closeTeacher" class="dialog" :close-on-click-modal="false"> |
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px" :disabled="isDetail"> |
||||||
|
<el-form-item prop="account" label="账号"> |
||||||
|
<el-input v-model="form.account" ref="account" placeholder="请输入账号" @change="accountChange" maxlength="20"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="name" label="用户姓名"> |
||||||
|
<el-input v-model="form.name" placeholder="请输入用户姓名"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="roleValue" label="账号角色"> |
||||||
|
<el-checkbox-group v-model="form.roleValue" :disabled="true"> |
||||||
|
<el-checkbox label="超级管理员"></el-checkbox> |
||||||
|
</el-checkbox-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="clientId" label="所属学校"> |
||||||
|
<el-select v-model="form.clientId" clearable placeholder="请选择所属学校" filterable style="width: 100%;"> |
||||||
|
<el-option v-for="(item,index) in clientList" :key="index" :label="item.clientName" :value="item.id"></el-option> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<span slot="footer" class="dialog-footer" v-if="!isDetail"> |
||||||
|
<el-button size="small" @click="userVisible = false">取消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="saveData">确定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog title="查看用户" :visible.sync="userShowVisible" width="500px" class="dialog" :close-on-click-modal="false"> |
||||||
|
<ul class="list"> |
||||||
|
<li> |
||||||
|
<span class="name"><i class="required">*</i>账号:</span> |
||||||
|
<span class="val">{{form.account}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name"><i class="required">*</i>用户姓名:</span> |
||||||
|
<span class="val">{{form.name}}</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name">账号角色:</span> |
||||||
|
<span class="val">超级管理员</span> |
||||||
|
</li> |
||||||
|
<li> |
||||||
|
<span class="name"><i class="required">*</i>所属学校:</span> |
||||||
|
<span class="val">{{form.clientId ? clientList.find(n => n.id == form.clientId).clientName : ''}}</span> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</el-dialog> |
||||||
|
|
||||||
|
<el-dialog title="批量导入" :visible.sync="importVisible" width="400px" :close-on-click-modal="false"> |
||||||
|
<div class="upload-wrap" :class="{lg: uploadFaild}"> |
||||||
|
<el-button class="download" size="small" @click="downLoad"><img src="../assets/img/download.png" alt=""> 模板下载</el-button> |
||||||
|
<el-upload accept=".xls,.xlsx" :on-remove="handleRemove" :on-error="uploadError" :on-success="uploadSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.uploadFileUser" :file-list="uploadList" name="file"> |
||||||
|
<el-button size="small"><img src="../assets/img/upload.png" alt=""> 上传文件</el-button> |
||||||
|
</el-upload> |
||||||
|
<div class="link" v-if="uploadFaild"> |
||||||
|
<el-link type="primary" @click="showFaild">导入失败,查看原因</el-link> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<span slot="footer" class="dialog-footer"> |
||||||
|
<el-button size="small" @click="importVisible = false">取消</el-button> |
||||||
|
<el-button size="small" type="primary" @click="uploadSure">确定</el-button> |
||||||
|
</span> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Setting from '@/setting' |
||||||
|
import breadcrumb from '@/components/breadcrumb' |
||||||
|
export default { |
||||||
|
name: 'user', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
clientId: this.$store.state.schoolId, |
||||||
|
form: { |
||||||
|
id: '', |
||||||
|
name: '', |
||||||
|
account: '', |
||||||
|
roleValue: ['超级管理员'], |
||||||
|
clientId: '', |
||||||
|
clientName: '' |
||||||
|
}, |
||||||
|
rules: { |
||||||
|
account: [ |
||||||
|
{ required: true, message: '请输入账号', trigger: 'blur' }, |
||||||
|
{ |
||||||
|
pattern: /^[A-Za-z0-9]+$/, |
||||||
|
message: '请输入正确的账号', |
||||||
|
trigger: 'blur' |
||||||
|
} |
||||||
|
], |
||||||
|
name: [ |
||||||
|
{ required: true, message: '请输入用户姓名', trigger: 'blur' } |
||||||
|
], |
||||||
|
clientId: [ |
||||||
|
{ required: true, message: '请选择所属学校', trigger: 'change' }, |
||||||
|
] |
||||||
|
}, |
||||||
|
userData:[], |
||||||
|
keyword: '', |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
totals: 0, |
||||||
|
multipleSelection: [], |
||||||
|
clientList: [], |
||||||
|
isAdd: true, |
||||||
|
isDetail: false, |
||||||
|
userVisible: false, |
||||||
|
userShowVisible: false, |
||||||
|
searchTimer: null, |
||||||
|
curRow: {}, |
||||||
|
accountRepeat: false, |
||||||
|
uploadList: [], |
||||||
|
importVisible: false, |
||||||
|
uploadFaild: false, |
||||||
|
token: '', |
||||||
|
originalAccount: '', |
||||||
|
submiting: false |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { breadcrumb }, |
||||||
|
watch: { |
||||||
|
keyword: function(val) { |
||||||
|
clearTimeout(this.searchTimer) |
||||||
|
this.searchTimer = setTimeout(() => { |
||||||
|
this.initData() |
||||||
|
},500) |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.getData() |
||||||
|
this.getClient() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getData() { |
||||||
|
let data = { |
||||||
|
searchContent: this.keyword, |
||||||
|
current: this.pageNo, |
||||||
|
pageSize: this.pageSize |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryUser}/${this.pageNo}/${this.pageSize}`,data).then(res => { |
||||||
|
this.userData = res.data.list |
||||||
|
this.totals = res.data.total |
||||||
|
if(!this.userData.length && this.totals){ |
||||||
|
this.pageNo-- |
||||||
|
this.getData() |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
initData(){ |
||||||
|
this.pageNo = 1 |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
accountChange(){ |
||||||
|
if(this.form.account !== this.originalAccount){ |
||||||
|
this.$get(`${this.api.getAccount}?account=${this.form.account}`).then(res => { |
||||||
|
if(res.data.userInfo){ |
||||||
|
this.accountRepeat = true |
||||||
|
this.warningMsg('该账号已存在') |
||||||
|
}else{ |
||||||
|
this.accountRepeat = false |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}else{ |
||||||
|
this.accountRepeat = false |
||||||
|
} |
||||||
|
}, |
||||||
|
getClient(){ |
||||||
|
let data = { |
||||||
|
searchContent: '', |
||||||
|
provinceId: '', |
||||||
|
cityId: '' |
||||||
|
} |
||||||
|
this.$get(`${this.api.queryClient}/1/1000`,data).then(res => { |
||||||
|
this.clientList = res.data.list |
||||||
|
}).catch(res => {}); |
||||||
|
}, |
||||||
|
closeTeacher(){ |
||||||
|
this.$refs.form.clearValidate() |
||||||
|
this.form = { |
||||||
|
id: '', |
||||||
|
name: '', |
||||||
|
account: '', |
||||||
|
roleValue: ['超级管理员'], |
||||||
|
clientId: '', |
||||||
|
clientName: '' |
||||||
|
} |
||||||
|
this.curRow = {} |
||||||
|
}, |
||||||
|
currentChange(val) { |
||||||
|
this.pageNo = val; |
||||||
|
this.getData(); |
||||||
|
}, |
||||||
|
adduser(){ |
||||||
|
this.isDetail = false |
||||||
|
this.isAdd = true |
||||||
|
this.userVisible = true |
||||||
|
}, |
||||||
|
fillForm(row){ |
||||||
|
this.form.id = row.id |
||||||
|
this.form.userId = row.userId |
||||||
|
this.form.account = row.account |
||||||
|
this.originalAccount = Number(row.account) |
||||||
|
this.form.name = row.name |
||||||
|
this.form.clientId = row.clientId |
||||||
|
this.form.clientName = row.clientName |
||||||
|
}, |
||||||
|
show(row){ |
||||||
|
this.fillForm(row) |
||||||
|
this.userShowVisible = true |
||||||
|
}, |
||||||
|
edit(row){ |
||||||
|
this.isDetail = false |
||||||
|
this.isAdd = false |
||||||
|
this.fillForm(row) |
||||||
|
this.userVisible = true |
||||||
|
}, |
||||||
|
saveData() { |
||||||
|
if(this.submiting) return false |
||||||
|
this.$refs.form.validate((valid) => { |
||||||
|
if (valid) { |
||||||
|
if(this.accountRepeat) return this.warningMsg('该账号已存在') |
||||||
|
this.form.clientName = this.clientList.find(n => n.id == this.form.clientId).clientName |
||||||
|
let form = this.form |
||||||
|
let data = { |
||||||
|
userInfo: { |
||||||
|
id: form.id, |
||||||
|
isPort: 2, |
||||||
|
userId: form.userId, |
||||||
|
account: form.account, |
||||||
|
clientId: form.clientId, |
||||||
|
clientName: form.clientName, |
||||||
|
creationTime: this.formatDate(new Date().getTime()), |
||||||
|
roleId: 1, |
||||||
|
uniqueIdentificationAccount: new Date().getTime(), |
||||||
|
userName: form.name, |
||||||
|
}, |
||||||
|
userManagement: { |
||||||
|
id: form.id, |
||||||
|
isPort: 2, |
||||||
|
userId: form.userId, |
||||||
|
account: form.account, |
||||||
|
clientId: form.clientId, |
||||||
|
clientName: form.clientName, |
||||||
|
name: form.name, |
||||||
|
roleId: 1, |
||||||
|
} |
||||||
|
} |
||||||
|
this.submiting = true |
||||||
|
|
||||||
|
if(this.form.id) { |
||||||
|
this.$post(this.api.updateUser,data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
if(res.success) { |
||||||
|
this.successMsg('修改成功'); |
||||||
|
this.userVisible = false |
||||||
|
this.getData() |
||||||
|
}else{ |
||||||
|
this.errorMsg(res.message); |
||||||
|
} |
||||||
|
}).catch(res => { |
||||||
|
this.submiting = false |
||||||
|
}); |
||||||
|
}else{ |
||||||
|
this.$post(this.api.addUser,data).then(res => { |
||||||
|
this.submiting = false |
||||||
|
if(res.success) { |
||||||
|
this.successMsg('新增成功'); |
||||||
|
this.userVisible = false |
||||||
|
this.getData() |
||||||
|
}else{ |
||||||
|
this.errorMsg(res.message); |
||||||
|
} |
||||||
|
}).catch(res => { |
||||||
|
this.submiting = false |
||||||
|
}); |
||||||
|
} |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
}) |
||||||
|
}, |
||||||
|
handleDelete(row) { |
||||||
|
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$post(`${this.api.deleteUser}?userIds=${row.id}`).then(res => { |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}) |
||||||
|
.catch(() => {}); |
||||||
|
}, |
||||||
|
resetPassword(row){ |
||||||
|
this.$confirm(`重置后的密码为:${Setting.initialPassword},确定重置?`, '提示', { |
||||||
|
}).then(() => { |
||||||
|
let data = { |
||||||
|
userId: row.userId, |
||||||
|
password: Setting.initialPassword |
||||||
|
} |
||||||
|
this.$post(this.api.userinfoUpdate,data).then(res => { |
||||||
|
if(res.success){ |
||||||
|
this.successMsg('重置成功') |
||||||
|
}else{ |
||||||
|
this.errorMsg('重置失败') |
||||||
|
} |
||||||
|
}).catch(res => {}); |
||||||
|
}).catch(() => { |
||||||
|
}); |
||||||
|
}, |
||||||
|
getRowKeys(row) { |
||||||
|
return row.userId; |
||||||
|
}, |
||||||
|
handleSelectionChange(val) { |
||||||
|
this.multipleSelection = val; |
||||||
|
}, |
||||||
|
delAllSelection() { |
||||||
|
if(this.multipleSelection.length != ''){ |
||||||
|
let newArr = this.multipleSelection |
||||||
|
let delList = newArr.map(item => { |
||||||
|
return item.id |
||||||
|
}) |
||||||
|
// 批量删除 |
||||||
|
this.$confirm(`此批量删除操作不可逆,是否确认删除${newArr[0].name}等${newArr.length}个选中项?`, '提示', { |
||||||
|
type: 'warning' |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
this.$post(`${this.api.deleteUser}?userIds=${delList.join(',')}`).then(res => { |
||||||
|
this.$refs.table.clearSelection() |
||||||
|
this.multipleSelection = []; |
||||||
|
this.successMsg('删除成功'); |
||||||
|
this.getData() |
||||||
|
}).catch(res => {}); |
||||||
|
}).catch(() => {}); |
||||||
|
}else{ |
||||||
|
this.errorMsg('请先选择数据 !'); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
batchImport(){ |
||||||
|
this.importVisible = true |
||||||
|
this.uploadList = [] |
||||||
|
this.uploadFaild = false |
||||||
|
}, |
||||||
|
handleExceed(files, fileList) { |
||||||
|
this.warningMsg( |
||||||
|
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||||
|
); |
||||||
|
}, |
||||||
|
downLoad(){ |
||||||
|
location.href = this.api.downloadUserTemp |
||||||
|
}, |
||||||
|
showFaild(){ |
||||||
|
location.href = `${this.api.exportFailureUser}?token=${this.token}` |
||||||
|
}, |
||||||
|
uploadSuccess(res, file, fileList) { |
||||||
|
this.uploadFaild = false |
||||||
|
if(res.success){ |
||||||
|
if(res.data.data.token){ |
||||||
|
this.token = res.data.data.token |
||||||
|
this.uploadFaild = true |
||||||
|
}else{ |
||||||
|
this.successMsg('上传成功') |
||||||
|
} |
||||||
|
}else{ |
||||||
|
res.data.message ? this.errorMsg(res.data.message) : this.errorMsg('上传失败,请检查数据') |
||||||
|
} |
||||||
|
}, |
||||||
|
uploadError(err, file, fileList) { |
||||||
|
this.$message({ |
||||||
|
message: "上传出错,请重试!", |
||||||
|
type: "error", |
||||||
|
center: true |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeRemove(file, fileList) { |
||||||
|
return this.$confirm(`确定移除 ${file.name}?`); |
||||||
|
}, |
||||||
|
handleRemove(file, fileList) { |
||||||
|
this.uploadList = fileList |
||||||
|
this.uploadFaild = false |
||||||
|
}, |
||||||
|
uploadSure(){ |
||||||
|
this.importVisible = false |
||||||
|
this.pageNo = 1 |
||||||
|
this.keyword = '' |
||||||
|
this.getData() |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.list{ |
||||||
|
li{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
margin: 32px 0; |
||||||
|
.name,.val{ |
||||||
|
font-size: 16px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
} |
||||||
|
.name{ |
||||||
|
width: 45%; |
||||||
|
text-align: right; |
||||||
|
} |
||||||
|
.val{ |
||||||
|
width: 55%; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
* @description 鉴权指令 |
||||||
|
* 当传入的权限当前用户没有时,会移除该组件 |
||||||
|
* 用例:<Tag v-auth">text</Tag> 或者:<Tag v-auth="'user:编辑'">text</Tag> |
||||||
|
* */ |
||||||
|
import store from '@/store'; |
||||||
|
|
||||||
|
export default { |
||||||
|
inserted (el, binding, vnode) { |
||||||
|
let btnText = '' |
||||||
|
if(binding.value){ |
||||||
|
btnText = binding.value |
||||||
|
}else{ |
||||||
|
btnText = `${vnode.context.$route.name}:${el.innerText}` |
||||||
|
} |
||||||
|
const btnPermissions = store.state.btnPermissions; |
||||||
|
|
||||||
|
if (btnText && btnPermissions && btnPermissions.length) { |
||||||
|
const isPermission = btnPermissions.includes(btnText); |
||||||
|
if (!isPermission) { |
||||||
|
el.parentNode && el.parentNode.removeChild(el); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
/** |
||||||
|
* 插件 |
||||||
|
* */ |
||||||
|
|
||||||
|
// 鉴权指令
|
||||||
|
import directiveAuth from '@/plugins/auth'; |
||||||
|
import throttle from '@/plugins/throttle'; |
||||||
|
|
||||||
|
export default { |
||||||
|
async install (Vue, options) { |
||||||
|
// 指令
|
||||||
|
Vue.directive('auth', directiveAuth); |
||||||
|
Vue.directive('throttle', throttle); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,398 @@ |
|||||||
|
import axios from 'axios'; |
||||||
|
import QS from 'qs'; |
||||||
|
// import store from '../store/index'
|
||||||
|
import { Message } from 'element-ui' |
||||||
|
import router from '@/router/index' |
||||||
|
|
||||||
|
// 环境的切换
|
||||||
|
// if (process.env.NODE_ENV == 'development') {
|
||||||
|
// axios.defaults.baseURL = '/api';
|
||||||
|
// } else if (process.env.NODE_ENV == 'debug') {
|
||||||
|
// axios.defaults.baseURL = '';
|
||||||
|
// } else if (process.env.NODE_ENV == 'production') {
|
||||||
|
// axios.defaults.baseURL = 'http://api.123dailu.com/';
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 请求超时时间
|
||||||
|
axios.defaults.timeout = 60000; |
||||||
|
|
||||||
|
// post请求头
|
||||||
|
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'; |
||||||
|
axios.defaults.headers.Pragma = 'no-cache' |
||||||
|
|
||||||
|
// 请求拦截器
|
||||||
|
// axios.interceptors.request.use(config => {
|
||||||
|
// if (sessionStorage.getItem('token')) {
|
||||||
|
// // 存在将token写入 request header
|
||||||
|
// config.headers.Authorization = `${sessionStorage.getItem('token')}`;
|
||||||
|
// }
|
||||||
|
// return config;
|
||||||
|
// }, err => {
|
||||||
|
// Message.error({
|
||||||
|
// message: '退出登陆',
|
||||||
|
// onClose: function () {
|
||||||
|
// router.push({name: 'login'});
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// return Promise.reject(err);
|
||||||
|
// })
|
||||||
|
|
||||||
|
// 响应拦截器
|
||||||
|
// axios.interceptors.response.use(
|
||||||
|
// response => {
|
||||||
|
// consol.log(response.status)
|
||||||
|
// if (response.status === 200) {
|
||||||
|
// return Promise.resolve(response);
|
||||||
|
// } else {
|
||||||
|
// return Promise.reject(response);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// // 服务器状态码不是200的情况
|
||||||
|
// error => {
|
||||||
|
// if (error.response.status) {
|
||||||
|
// switch (error.response.status) {
|
||||||
|
// // 401: 未登录
|
||||||
|
// // 未登录则跳转登录页面,并携带当前页面的路径
|
||||||
|
// // 在登录成功后返回当前页面,这一步需要在登录页操作。
|
||||||
|
// case 500:
|
||||||
|
// router.replace({
|
||||||
|
// path: '/login',
|
||||||
|
// // query: { redirect: router.currentRoute.fullPath }
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// // 403 token过期
|
||||||
|
// // 登录过期对用户进行提示
|
||||||
|
// // 清除本地token和清空vuex中token对象
|
||||||
|
// // 跳转登录页面
|
||||||
|
// case 403:
|
||||||
|
// // Toast({
|
||||||
|
// // message: '登录过期,请重新登录',
|
||||||
|
// // duration: 1000,
|
||||||
|
// // forbidClick: true
|
||||||
|
// // });
|
||||||
|
// // 清除token
|
||||||
|
// sessionStorage.removeItem('token');
|
||||||
|
// store.commit('loginSuccess', null);
|
||||||
|
// // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
|
||||||
|
// setTimeout(() => {
|
||||||
|
// router.replace({
|
||||||
|
// path: '/login',
|
||||||
|
// query: {
|
||||||
|
// redirect: router.currentRoute.fullPath
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }, 1000);
|
||||||
|
// break;
|
||||||
|
// // 404请求不存在
|
||||||
|
// case 404:
|
||||||
|
// router.replace({
|
||||||
|
// path: '/404',
|
||||||
|
// });
|
||||||
|
// break;
|
||||||
|
// // 其他错误,直接抛出错误提示
|
||||||
|
// default:
|
||||||
|
// router.replace({
|
||||||
|
// path: '/500',
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// return Promise.reject(error.response);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
|
/** |
||||||
|
* get方法,对应get请求 |
||||||
|
*/ |
||||||
|
export function get(url, params){ |
||||||
|
return new Promise((resolve, reject) =>{ |
||||||
|
axios.get(url, { |
||||||
|
params: params
|
||||||
|
}) |
||||||
|
.then(res => { |
||||||
|
if (res.data.status){ |
||||||
|
switch (res.data.status) { |
||||||
|
case 200: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
if (res.data.success) { |
||||||
|
switch (res.data.code) { |
||||||
|
case 200: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
case 10000: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
case 500: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 300: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 404: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 403: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 401: |
||||||
|
Message.error("token失效,请重新登录"); |
||||||
|
sessionStorage.removeItem('token'); |
||||||
|
router.replace('/login') |
||||||
|
break; |
||||||
|
case 405: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 406: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
this.errorMsg(res.data.message); |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
reject(err.data) |
||||||
|
this.$message({ |
||||||
|
showClose: true, |
||||||
|
message: '请求失败,请刷新页面重新进行请求', |
||||||
|
type: 'error' |
||||||
|
}); |
||||||
|
}) |
||||||
|
}); |
||||||
|
} |
||||||
|
/** |
||||||
|
* post方法,对应post请求 |
||||||
|
*/ |
||||||
|
export function post(url, params) { |
||||||
|
return new Promise((resolve, reject) => { |
||||||
|
axios.post(url,params) |
||||||
|
.then(res => { |
||||||
|
if (res.data.status){ |
||||||
|
switch (res.data.status) { |
||||||
|
case 200: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
if (res.data.success) { |
||||||
|
switch (res.data.code) { |
||||||
|
case 200: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
case 201: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
case 500: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 300: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 404: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 403: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 401: |
||||||
|
Message.error("token失效,请重新登录"); |
||||||
|
sessionStorage.removeItem('token'); |
||||||
|
router.replace('/login') |
||||||
|
break; |
||||||
|
case 405: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 406: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
this.errorMsg(res.data.message); |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
reject(err.data) |
||||||
|
this.$message({ |
||||||
|
showClose: true, |
||||||
|
message: '请求失败,请刷新页面重新进行请求', |
||||||
|
type: 'error' |
||||||
|
}); |
||||||
|
}) |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* delete方法,对应delete请求 |
||||||
|
*/ |
||||||
|
export function del(url, params){ |
||||||
|
return new Promise((resolve, reject) =>{ |
||||||
|
axios.delete(url, {params}) |
||||||
|
.then(res => { |
||||||
|
if (res.data.status){ |
||||||
|
switch (res.data.status) { |
||||||
|
case 200: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
if (res.data.success) { |
||||||
|
switch (res.data.code) { |
||||||
|
case 200: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
// case 300:
|
||||||
|
// this.errorMsg(
|
||||||
|
// res.data.errmessage
|
||||||
|
// );
|
||||||
|
// break;
|
||||||
|
case 500: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 404: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
router.replace({ |
||||||
|
path: '/404', |
||||||
|
}); |
||||||
|
break; |
||||||
|
case 403: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 401: |
||||||
|
Message.error("token失效,请重新登录"); |
||||||
|
sessionStorage.removeItem('token'); |
||||||
|
router.replace('/login') |
||||||
|
break; |
||||||
|
case 405: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 406: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
this.errorMsg(res.data.message); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
reject(err.data) |
||||||
|
this.$message({ |
||||||
|
showClose: true, |
||||||
|
message: '请求失败,请刷新页面重新进行请求', |
||||||
|
type: 'error' |
||||||
|
}); |
||||||
|
}) |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* put修改 |
||||||
|
* @param {} url
|
||||||
|
* @param {*} params
|
||||||
|
*/ |
||||||
|
export function put(url, params){ |
||||||
|
return new Promise((resolve, reject) =>{ |
||||||
|
axios.put(url, params) |
||||||
|
.then(res => { |
||||||
|
if (res.data.status){ |
||||||
|
switch (res.data.status) { |
||||||
|
case 200: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
if (res.data.success) { |
||||||
|
switch (res.data.code) { |
||||||
|
case 200: |
||||||
|
resolve(res.data); |
||||||
|
break; |
||||||
|
case 300: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 500: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 404: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 403: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 401: |
||||||
|
Message.error("token失效,请重新登录"); |
||||||
|
sessionStorage.removeItem('token'); |
||||||
|
router.replace('/login') |
||||||
|
break; |
||||||
|
case 405: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
case 406: |
||||||
|
this.errorMsg( |
||||||
|
res.data.errmessage |
||||||
|
); |
||||||
|
break; |
||||||
|
} |
||||||
|
}else{ |
||||||
|
this.errorMsg(res.data.message); |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
.catch(err => { |
||||||
|
reject(err.data) |
||||||
|
this.$message({ |
||||||
|
showClose: true, |
||||||
|
message: '请求失败,请刷新页面重新进行请求', |
||||||
|
type: 'error' |
||||||
|
}); |
||||||
|
}) |
||||||
|
}); |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
/** |
||||||
|
* @description 节流指令 |
||||||
|
* 限制连续快速点击按钮 |
||||||
|
* 用例:<Tag v-throttle>text</Tag> |
||||||
|
* */ |
||||||
|
|
||||||
|
export default{ |
||||||
|
inserted (el, binding, vnode) { |
||||||
|
el.addEventListener('click', () => { |
||||||
|
if (!el.disabled) { |
||||||
|
el.disabled = true |
||||||
|
setTimeout(() => { |
||||||
|
el.disabled = false |
||||||
|
}, binding.value || 1000) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
import router from './index'; |
||||||
|
import store from '@/store'; |
||||||
|
import Setting from '@/setting'; |
||||||
|
import generateRoutes from '@/libs/route/generateRoutes'; |
||||||
|
import bus from '@/libs/bus'; |
||||||
|
|
||||||
|
router.beforeEach((to, from, next) => { |
||||||
|
document.title = to.meta.title ? `${to.meta.title} | ${Setting.titleSuffix}` : Setting.titleSuffix; |
||||||
|
const role = sessionStorage.getItem(Setting.usernameKey); |
||||||
|
if (!role && to.path !== '/login') { |
||||||
|
next('login') |
||||||
|
// if(to.fullPath != '/404' && to.fullPath != '/'){
|
||||||
|
// next({
|
||||||
|
// path: 'login',
|
||||||
|
// query: {redirect: to.fullPath}
|
||||||
|
// })
|
||||||
|
// }else{
|
||||||
|
// next('login')
|
||||||
|
// }
|
||||||
|
} else if(role && to.path == '/login') { |
||||||
|
next('dashboard') |
||||||
|
} else { |
||||||
|
to.meta.title != '404' && store.commit('sidebarData',{sidebarMenu: to.meta.sidebar}) |
||||||
|
if(to.meta.sidebar){ |
||||||
|
bus.$emit('showMenu', true) |
||||||
|
}else{ |
||||||
|
bus.$emit('showMenu', false) |
||||||
|
} |
||||||
|
next(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
Setting.dynamicRoute && generateRoutes() |
@ -0,0 +1,72 @@ |
|||||||
|
export default [ |
||||||
|
{ |
||||||
|
path: '/', |
||||||
|
redirect: 'login' |
||||||
|
}, |
||||||
|
{ |
||||||
|
path: '/', |
||||||
|
component: () => import('@/layouts/home/index.vue'), |
||||||
|
meta: { title: '自述文件' }, |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
name: 'personalcenter', |
||||||
|
path: 'personalcenter', |
||||||
|
component: () => import('@/pages/personalcenter.vue'), |
||||||
|
meta: { |
||||||
|
title: '个人中心' |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'matchDetail', |
||||||
|
path: 'matchDetail', |
||||||
|
component: () => import('@/pages/matchDetail.vue'), |
||||||
|
meta: { title: '大赛简介',sidebar: 'match' } |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'courseSection', |
||||||
|
path: 'courseSection', |
||||||
|
component: () => import('@/pages/courseSection.vue'), |
||||||
|
meta: { title: '课程预览' } |
||||||
|
}, |
||||||
|
|
||||||
|
// {
|
||||||
|
// name: 'course',
|
||||||
|
// path: 'course',
|
||||||
|
// component: () => import('@/pages/course.vue'),
|
||||||
|
// meta: { title: '课程管理' }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'addcourse',
|
||||||
|
// path: 'addcourse',
|
||||||
|
// component: () => import('@/pages/addCourse.vue'),
|
||||||
|
// meta: { title: '新增课程' }
|
||||||
|
// },
|
||||||
|
|
||||||
|
{ |
||||||
|
// 国际化组件
|
||||||
|
name: 'i18n', |
||||||
|
path: 'i18n', |
||||||
|
component: () => import( '@/pages/i18n.vue'), |
||||||
|
meta: { title: '国际化' } |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '404', |
||||||
|
path: '404', |
||||||
|
component: () => import('@/pages/404.vue'), |
||||||
|
meta: { title: '404' } |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: '403', |
||||||
|
path: '403', |
||||||
|
component: () => import('@/pages/403.vue'), |
||||||
|
meta: { title: '403' } |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: 'login', |
||||||
|
path: '/login', |
||||||
|
component: () => import('@/pages/login.vue'), |
||||||
|
meta: { title: '登录' } |
||||||
|
}, |
||||||
|
] |
@ -0,0 +1,21 @@ |
|||||||
|
/** |
||||||
|
* 开发配置 |
||||||
|
* */ |
||||||
|
|
||||||
|
const env = process.env.NODE_ENV; |
||||||
|
|
||||||
|
const Setting = { |
||||||
|
// 是否使用 Mock 的数据,默认 开发环境为 true,生产环境为 false
|
||||||
|
isMock: true, |
||||||
|
// 部署应用包时的基本 URL
|
||||||
|
publicPath: env === 'development' ? './' : '', |
||||||
|
// 生产环境构建文件的目录名
|
||||||
|
outputDir: 'dist', |
||||||
|
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
|
||||||
|
assetsDir: 'static', |
||||||
|
// 开发环境每次保存时 lint 代码,会将 lint 错误输出为编译警告
|
||||||
|
// true || false || error
|
||||||
|
lintOnSave: true, |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports = Setting; |
@ -0,0 +1,116 @@ |
|||||||
|
/** |
||||||
|
* 业务配置 |
||||||
|
* */ |
||||||
|
|
||||||
|
const env = process.env.NODE_ENV; |
||||||
|
|
||||||
|
const Setting = { |
||||||
|
/** |
||||||
|
* 基础配置 |
||||||
|
* */ |
||||||
|
// 网页标题的后缀
|
||||||
|
titleSuffix: '电子竞技在线教学资源管理平台-企业端', |
||||||
|
// 路由模式,可选值为 history 或 hash
|
||||||
|
routerMode: 'hash', |
||||||
|
// 页面切换时,是否显示模拟的进度条
|
||||||
|
showProgressBar: true, |
||||||
|
// 接口请求地址
|
||||||
|
// apiBaseURL: env === 'development' ? 'http://192.168.31.137:8001' : 'http://8.134.8.197:8000',
|
||||||
|
apiBaseURL: env === 'development' ? 'http://8.134.8.197:8001' : 'http://8.134.8.197:8001', |
||||||
|
// 接口请求返回错误时,弹窗的持续时间,单位:秒
|
||||||
|
modalDuration: 3, |
||||||
|
// 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice
|
||||||
|
errorModalType: 'Message', |
||||||
|
// Cookies 默认保存时间,单位:天
|
||||||
|
cookiesExpires: 1, |
||||||
|
/** |
||||||
|
* sessionStorage里state的key |
||||||
|
*/ |
||||||
|
storeKey: 'gz_ent_store', |
||||||
|
/** |
||||||
|
* sessionStorage里username的key |
||||||
|
*/ |
||||||
|
usernameKey: 'gz_ent_username', |
||||||
|
/** |
||||||
|
* 默认密码 |
||||||
|
*/ |
||||||
|
initialPassword: '111aaa', |
||||||
|
/** |
||||||
|
* 多语言配置 |
||||||
|
* */ |
||||||
|
i18n: { |
||||||
|
// 默认语言
|
||||||
|
default: 'zh', |
||||||
|
// 是否根据用户电脑配置自动设置语言(仅第一次有效)
|
||||||
|
auto: false |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 布局配置 |
||||||
|
* */ |
||||||
|
// 侧边菜单宽度,单位 px,不可动态修改,需与 setting.less 的 @menuSideWidth 保持一致
|
||||||
|
menuSideWidth: 256, |
||||||
|
layout: { |
||||||
|
// 需要隐藏顶栏的页面路径
|
||||||
|
hideNavList: ['matchintro','matchprogress','matchsignup','addarticle'], |
||||||
|
// 侧边栏风格,可选值为 dark 或 light
|
||||||
|
siderTheme: 'dark', |
||||||
|
// 顶栏风格,可选值为 light、dark 或 primary
|
||||||
|
headerTheme: 'light', |
||||||
|
// 顶栏是否置顶,开启后会覆盖侧边栏,需开启 headerFix
|
||||||
|
headerStick: false, |
||||||
|
// 是否开启多 Tabs 页签
|
||||||
|
tabs: true, |
||||||
|
// 多 Tabs 页签是否显示图标,开启 tabs 时有效
|
||||||
|
showTabsIcon: true, |
||||||
|
// 是否固定多 Tabs 多页签
|
||||||
|
tabsFix: true, |
||||||
|
// 是否固定侧边栏
|
||||||
|
siderFix: true, |
||||||
|
// 是否固定顶栏
|
||||||
|
headerFix: true, |
||||||
|
// 是否在下滑时隐藏顶栏,需开启 headerFix,如果开启了 tabsFix,Tabs 也会被隐藏
|
||||||
|
headerHide: false, |
||||||
|
// 是否显示顶部菜单栏
|
||||||
|
// 一般来说,侧边的菜单栏足以满足大部分业务,如需动态切换侧边栏,可开启此选项启用顶部一级菜单,此时侧边栏将作为二级菜单
|
||||||
|
headerMenu: false, |
||||||
|
// 侧边菜单栏是否开启手风琴模式
|
||||||
|
menuAccordion: true, |
||||||
|
// 是否显示折叠侧边栏按钮,移动端下会自动强制开启
|
||||||
|
showSiderCollapse: true, |
||||||
|
// 侧边菜单栏是否默认折起
|
||||||
|
menuCollapse: false, |
||||||
|
// 侧边菜单折起时,是否在子菜单前显示父级菜单名称
|
||||||
|
showCollapseMenuTitle: false, |
||||||
|
// 是否显示重载按钮
|
||||||
|
showReload: true, |
||||||
|
// 是否显示搜索
|
||||||
|
showSearch: true, |
||||||
|
// 是否显示通知
|
||||||
|
showNotice: true, |
||||||
|
// 是否显示全屏
|
||||||
|
showFullscreen: true, |
||||||
|
// 在手机访问时,是否在顶部显示小尺寸 logo
|
||||||
|
showMobileLogo: true, |
||||||
|
// 是否显示全局面包屑,开启 headerMenu 时不可用
|
||||||
|
showBreadcrumb: true, |
||||||
|
// 全局面包屑是否显示图标,开启 showBreadcrumb 时有效
|
||||||
|
showBreadcrumbIcon: false, |
||||||
|
// 是否显示日志入口,开启与否,不影响日志记录,如不希望用户看到可关闭
|
||||||
|
showLog: true, |
||||||
|
// 是否显示多语言
|
||||||
|
showI18n: true, |
||||||
|
// 是否支持动态修改布局配置,移动端下会自动强制关闭
|
||||||
|
enableSetting: true, |
||||||
|
// 退出登录时,是否二次确认
|
||||||
|
logoutConfirm: true |
||||||
|
}, |
||||||
|
/** |
||||||
|
* 功能配置 |
||||||
|
* */ |
||||||
|
// 相同路由,不同参数间进行切换,是否强力更新
|
||||||
|
sameRouteForceUpdate: false, |
||||||
|
// 是否使用动态路由
|
||||||
|
dynamicRoute: true |
||||||
|
}; |
||||||
|
|
||||||
|
export default Setting; |
@ -0,0 +1,85 @@ |
|||||||
|
import Vue from 'vue'; |
||||||
|
import Vuex from 'vuex'; |
||||||
|
Vue.use(Vuex); |
||||||
|
const store = new Vuex.Store({ |
||||||
|
state: { |
||||||
|
avatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png', |
||||||
|
customerId:'', |
||||||
|
courseId:'', |
||||||
|
userId: '', |
||||||
|
roleId: '', |
||||||
|
manager:{}, |
||||||
|
provinceList: [], |
||||||
|
configId: '', |
||||||
|
systemId: '', |
||||||
|
orderId: '', |
||||||
|
userLoginId: '', |
||||||
|
accountRole: '', |
||||||
|
name:'', |
||||||
|
account:'', |
||||||
|
phone:'', |
||||||
|
schoolId: '', |
||||||
|
schoolName: '', |
||||||
|
routes: [], |
||||||
|
btnPermissions: [], |
||||||
|
indexPath: '', |
||||||
|
sidebarMenu: false, |
||||||
|
matchId: '', |
||||||
|
}, |
||||||
|
mutations:{ |
||||||
|
userData (state, payload) { |
||||||
|
state.userId = payload.user_id, |
||||||
|
state.roleId = payload.roleId |
||||||
|
}, |
||||||
|
customerData (state, payload) { |
||||||
|
state.customerId = payload.customer_id |
||||||
|
}, |
||||||
|
courseData (state, payload) { |
||||||
|
state.courseId = payload.course_id |
||||||
|
}, |
||||||
|
managerData (state, payload) { |
||||||
|
state.manager = payload.form |
||||||
|
}, |
||||||
|
provinceData (state, payload) { |
||||||
|
state.provinceList = payload.provinceList |
||||||
|
}, |
||||||
|
configData (state, payload) { |
||||||
|
state.configId = payload.config_id |
||||||
|
}, |
||||||
|
systemData (state, payload) { |
||||||
|
state.systemId = payload.system_id |
||||||
|
state.orderId = payload.order_id |
||||||
|
}, |
||||||
|
setAvatarData (state, payload) { |
||||||
|
state.avatar = payload.avatar |
||||||
|
}, |
||||||
|
userLoginData (state, payload) { |
||||||
|
state.userLoginId = payload.userId |
||||||
|
state.accountRole = payload.accountRole |
||||||
|
}, |
||||||
|
userInfo(state,payload){ |
||||||
|
state.name = payload.name |
||||||
|
state.account = payload.account |
||||||
|
state.phone = payload.phone |
||||||
|
state.schoolId = payload.schoolId |
||||||
|
state.schoolName = payload.schoolName |
||||||
|
}, |
||||||
|
sidebarData (state, payload) { |
||||||
|
state.sidebarMenu = payload.sidebarMenu |
||||||
|
}, |
||||||
|
matchData (state, payload) { |
||||||
|
state.matchId = payload.matchId |
||||||
|
}, |
||||||
|
addRoutesData (state, payload) { |
||||||
|
state.routes = payload.routes |
||||||
|
}, |
||||||
|
addBtnPerData (state, payload) { |
||||||
|
state.btnPermissions = payload.btnPermissions |
||||||
|
}, |
||||||
|
addIndex (state, payload) { |
||||||
|
state.indexPath = payload.path |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
export default store; |
@ -0,0 +1,359 @@ |
|||||||
|
@import "./default/index.scss"; |
||||||
|
|
||||||
|
@font-face{ |
||||||
|
font-family: youshe; |
||||||
|
src: url('font/YouSheBiaoTiHei.ttf'); |
||||||
|
} |
||||||
|
|
||||||
|
[v-cloak] { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
|
||||||
|
::-webkit-scrollbar { |
||||||
|
width: 6px; |
||||||
|
} |
||||||
|
::-webkit-scrollbar-thumb { |
||||||
|
border-radius: 10px; |
||||||
|
background: rgba(0, 0, 0, 0.06); |
||||||
|
} |
||||||
|
|
||||||
|
.required{ |
||||||
|
font-size: 16px; |
||||||
|
color: #CC221C; |
||||||
|
font-style: normal; |
||||||
|
} |
||||||
|
|
||||||
|
.breadcrumb{ |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
margin-bottom: 20px; |
||||||
|
.cur,.el-breadcrumb__inner,.el-breadcrumb__separator{ |
||||||
|
color: rgba(0,0,0,.45) !important; |
||||||
|
font-weight: 400 !important; |
||||||
|
font-size: 12px; |
||||||
|
} |
||||||
|
.el-breadcrumb__item:last-of-type .el-breadcrumb__inner{ |
||||||
|
color: rgba(0,0,0,.85) !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.el-button--primary.action-btn{ |
||||||
|
color: #CC221C !important; |
||||||
|
font-size: 14px !important; |
||||||
|
background-color: #fff !important; |
||||||
|
border-radius: 4px !important; |
||||||
|
} |
||||||
|
|
||||||
|
.el-input{ |
||||||
|
.el-input__inner{ |
||||||
|
border-color: rgba(0, 0, 0, 0.15); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.page{ |
||||||
|
position: relative; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 8px; |
||||||
|
.p-title{ |
||||||
|
padding-left: 24px; |
||||||
|
line-height: 56px; |
||||||
|
font-size: 16px; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
border-bottom: 1px solid rgba(0,0,0,.06); |
||||||
|
} |
||||||
|
.page-content{ |
||||||
|
padding: 24px; |
||||||
|
.tool{ |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
margin-bottom: 24px; |
||||||
|
.filter{ |
||||||
|
display: inline-flex; |
||||||
|
align-items: center; |
||||||
|
flex: 1; |
||||||
|
li{ |
||||||
|
display: inline-flex; |
||||||
|
align-items: center; |
||||||
|
margin-right: 30px; |
||||||
|
label{ |
||||||
|
font-size: 14px; |
||||||
|
line-height: 14px; |
||||||
|
color: rgba(0,0,0,.65); |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.single-choice{ |
||||||
|
dl { |
||||||
|
display: flex; |
||||||
|
line-height: 30px; |
||||||
|
dt { |
||||||
|
color: rgba(0,0,0,.65); |
||||||
|
font-size: 14px; |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
dd { |
||||||
|
display: inline-flex; |
||||||
|
align-items: center; |
||||||
|
flex-wrap: wrap; |
||||||
|
span { |
||||||
|
padding: 0 10px; |
||||||
|
margin: 0 10px; |
||||||
|
color: #333; |
||||||
|
font-size: 14px; |
||||||
|
line-height: 1.8; |
||||||
|
white-space: nowrap; |
||||||
|
|
||||||
|
cursor: pointer; |
||||||
|
&:hover { |
||||||
|
color: #CC221C; |
||||||
|
} |
||||||
|
&.active { |
||||||
|
border-radius: 4px; |
||||||
|
color: #fff; |
||||||
|
background-color: #CC221C; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.el-button--primary{ |
||||||
|
@extend .action-btn; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.pagination { |
||||||
|
margin: 20px 0; |
||||||
|
text-align: center; |
||||||
|
button,.number{ |
||||||
|
color: rgba(0,0,0,.65) !important; |
||||||
|
background-color: transparent !important; |
||||||
|
border: 1px solid rgba(0, 0, 0, 0.15) !important; |
||||||
|
border-radius: 4px !important; |
||||||
|
} |
||||||
|
button i{ |
||||||
|
color: #333; |
||||||
|
} |
||||||
|
.active{ |
||||||
|
color: #fff !important; |
||||||
|
background-color: #CC221C !important; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.el-table{ |
||||||
|
border-radius: 8px; |
||||||
|
border: 1px solid rgba(0, 0, 0, 0.06); |
||||||
|
border-bottom: 0; |
||||||
|
.cell{ |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
font-size: 14px; |
||||||
|
.el-checkbox{ |
||||||
|
&:before{ |
||||||
|
content: '全选'; |
||||||
|
margin-right: 5px; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
font-size: 14px; |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
th{ |
||||||
|
background: rgba(0, 0, 0, 0.04)!important; |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
font-weight: normal; |
||||||
|
.cell{ |
||||||
|
.el-checkbox{ |
||||||
|
&:before{ |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.el-checkbox__inner{ |
||||||
|
border-radius: 4px; |
||||||
|
transition: none !important; |
||||||
|
} |
||||||
|
.el-checkbox__input.is-indeterminate .el-checkbox__inner{ |
||||||
|
background-color: #FFFFFF; |
||||||
|
border-color: #DCDFE6; |
||||||
|
} |
||||||
|
.el-switch__core{ |
||||||
|
background-color: #bfbfbf; |
||||||
|
} |
||||||
|
.el-switch__label--right{ |
||||||
|
z-index: 2; |
||||||
|
position: absolute; |
||||||
|
right: 8px; |
||||||
|
margin-left: 0; |
||||||
|
color: #fff !important; |
||||||
|
} |
||||||
|
.el-switch__label--right.is-active{ |
||||||
|
left: 8px; |
||||||
|
right: auto; |
||||||
|
} |
||||||
|
.el-switch__label--right span{ |
||||||
|
font-size: 12px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.tabs{ |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
padding: 0 24px; |
||||||
|
margin-bottom: 20px; |
||||||
|
border-bottom: 1px solid rgba(0,0,0,.06); |
||||||
|
.item{ |
||||||
|
position: relative; |
||||||
|
padding: 20px 0; |
||||||
|
margin-right: 40px; |
||||||
|
font-size: 16px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
cursor: pointer; |
||||||
|
&:after{ |
||||||
|
content: ''; |
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
width: 100%; |
||||||
|
height: 3px; |
||||||
|
border-bottom: 3px solid transparent; |
||||||
|
border-radius: 2px; |
||||||
|
} |
||||||
|
&.active{ |
||||||
|
font-weight: 500; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
} |
||||||
|
&.active:after{ |
||||||
|
border-bottom-color: $--color-primary; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.el-message{ |
||||||
|
padding: 11px 20px; |
||||||
|
.el-message__icon{ |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
.el-message__content{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
} |
||||||
|
.el-icon-close{ |
||||||
|
font-size: 14px; |
||||||
|
color: #92998d; |
||||||
|
} |
||||||
|
.el-message--success{ |
||||||
|
border: 1px solid #B7EB8F; |
||||||
|
background: #F6FFED; |
||||||
|
.el-message__icon{ |
||||||
|
color: #00c700; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-message--warning{ |
||||||
|
border: 1px solid #FFE58F; |
||||||
|
background: #FFFBE6; |
||||||
|
.el-message__icon{ |
||||||
|
color: #ffa900; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.el-message-box{ |
||||||
|
padding-bottom: 24px; |
||||||
|
.el-message-box__header{ |
||||||
|
padding: 32px 32px 12px 50px; |
||||||
|
span{ |
||||||
|
font-size: 16px; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
font-weight: 500; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-message-box__status{ |
||||||
|
top: -30px; |
||||||
|
} |
||||||
|
.el-message-box__status + .el-message-box__message{ |
||||||
|
font-size: 14px; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
} |
||||||
|
.el-message-box__btns{ |
||||||
|
padding-right: 32px; |
||||||
|
&.el-icon-warning{ |
||||||
|
color: #ffa900; |
||||||
|
} |
||||||
|
} |
||||||
|
.el-button--primary,.el-button--primary:hover, .el-button--primary:focus{ |
||||||
|
background: #CC221C; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.el-dialog__wrapper{ |
||||||
|
.el-dialog{ |
||||||
|
border-radius: 4px; |
||||||
|
.el-dialog__header{ |
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
||||||
|
.el-dialog__title{ |
||||||
|
font-size: 16px; |
||||||
|
color: rgba(0, 0, 0, 0.85); |
||||||
|
} |
||||||
|
} |
||||||
|
.el-dialog__footer{ |
||||||
|
padding: 10px 16px; |
||||||
|
border-top: 1px solid rgba(0, 0, 0, 0.06); |
||||||
|
.el-button{ |
||||||
|
font-size: 14px; |
||||||
|
border-radius: 4px; |
||||||
|
border-color: rgba(0, 0, 0, 0.15); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.upload-wrap{ |
||||||
|
position: relative; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
padding: 34px 0; |
||||||
|
.el-button{ |
||||||
|
span{ |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
color: rgba(0, 0, 0, 0.65); |
||||||
|
font-size: 14px; |
||||||
|
img{ |
||||||
|
margin-right: 8px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
&>.el-button{ |
||||||
|
margin-right: 32px; |
||||||
|
} |
||||||
|
.el-upload-list{ |
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
.link{ |
||||||
|
position: absolute; |
||||||
|
bottom: -20px; |
||||||
|
left: 0; |
||||||
|
width: 100%; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
&.lg{ |
||||||
|
padding-bottom: 50px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@media(max-width: 1600px){ |
||||||
|
.el-table{ |
||||||
|
.el-switch__label--right.is-active{ |
||||||
|
left: 8px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
/* 改变主题色变量 */ |
||||||
|
|
||||||
|
$--color-primary: #CC221C; |
||||||
|
|
||||||
|
/* 改变 icon 字体路径变量,必需 */ |
||||||
|
$--font-path: '~element-ui/lib/theme-chalk/fonts'; |
||||||
|
@import "~element-ui/packages/theme-chalk/src/index"; |