项目管理、课程管理、资讯管理、赛事管理

dev_2022-05-11
yujialong 3 years ago
parent 0a042d07c8
commit 245397841c
  1. 170
      src/api/index.js
  2. BIN
      src/assets/img/arrow-down.png
  3. BIN
      src/assets/img/close.png
  4. BIN
      src/assets/img/upload.png
  5. 19
      src/components/quill/index.vue
  6. 1
      src/layouts/home/index.vue
  7. 31
      src/layouts/navbar/index.vue
  8. 8
      src/libs/auth/generateBtnPermission.js
  9. 9
      src/libs/route/addRoutes.js
  10. 3
      src/libs/util.js
  11. 2
      src/main.js
  12. 90
      src/pages/account/login/index.vue
  13. 4
      src/pages/achievement/ass/index.vue
  14. 4
      src/pages/achievement/edit/index.vue
  15. 1
      src/pages/achievement/list/index.vue
  16. 3
      src/pages/achievement/show/index.vue
  17. 379
      src/pages/assessment/add/index.vue
  18. 170
      src/pages/assessment/list/index.vue
  19. 286
      src/pages/course/courseManagement/add.vue
  20. 742
      src/pages/course/courseManagement/contentSettings.vue
  21. 219
      src/pages/course/courseManagement/index.vue
  22. 495
      src/pages/course/courseManagement/preview.vue
  23. 66
      src/pages/course/index.vue
  24. 166
      src/pages/course/sortManagement/index.vue
  25. 577
      src/pages/evaluation/list/index.vue
  26. 397
      src/pages/information/columnManage/index.vue
  27. 267
      src/pages/information/contentManage/addArticle.vue
  28. 197
      src/pages/information/contentManage/contentList.vue
  29. 102
      src/pages/information/contentManage/index.vue
  30. 64
      src/pages/information/index.vue
  31. 472
      src/pages/match/add.vue
  32. 279
      src/pages/match/index.vue
  33. 61
      src/pages/match/manage/index.vue
  34. 421
      src/pages/match/manage/matchDetail.vue
  35. 162
      src/pages/match/manage/matchProgress.vue
  36. 154
      src/pages/match/manage/matchSignup.vue
  37. 1191
      src/pages/project/add/index.vue
  38. 1080
      src/pages/project/add/index.vue.copy
  39. 418
      src/pages/project/list/index.vue
  40. 42
      src/pages/setting/person/index.vue
  41. 393
      src/pages/student/list/index.vue
  42. 3
      src/pages/system/list/index.vue
  43. 46
      src/pages/system/list/role.vue
  44. 26
      src/pages/system/list/staff.vue
  45. 4
      src/pages/system/list/staffSide.vue
  46. 2
      src/plugins/auth/index.js
  47. 2
      src/plugins/requests/index.js
  48. 24
      src/router/index.js
  49. 41
      src/router/modules/course.js
  50. 29
      src/router/modules/information.js
  51. 35
      src/router/modules/match.js
  52. 8
      src/router/routes.js
  53. 197
      src/setting.js
  54. 26
      src/store/modules/info.js
  55. 19
      src/store/modules/match.js
  56. 2
      src/store/modules/project.js
  57. 19
      src/store/modules/user.js
  58. 6
      vue.config.js

@ -1,16 +1,151 @@
import Setting from '@/setting'
// let host = 'http://192.168.31.125:9090'//林
// let host = 'http://192.168.31.152:9090'//榕
let host = Setting.apiBaseURL
let uploadURL = Setting.upload.apiURL
let host1 = 'http://39.108.250.202:8080/'
import Setting from '@/setting';
// let host = Setting.apiBaseURL
let host = 'http://192.168.31.151:9000/'; // 榕
// let host = 'http://192.168.31.125:9000/'; // 坤
let xsHost = 'http://39.108.250.202:9000/'; // 线上
let uploadURL = Setting.upload.apiURL;
let host1 = 'http://39.108.250.202:8080/'; // 川大
export default {
fileupload: `${uploadURL}oss/manage/fileupload`,
logins: `${host}liuwanr/userInfo/adminLogins`, //登录
queryToken: `${host}liuwanr/userInfo/queryToken`,
// fileupload: `${uploadURL}oss/manage/fileupload`,
queryToken: `${host}liuwanr/userInfo/queryToken`,
logins: `${host}users/users/user/login`, //登录
verification:`${host}users/users/user/captcha`,// 验证码图片
// bindPhoneOrEmail:`${host}users/users/userAccount/bindPhoneOrEmail`,// 绑定手机
// sendPhoneOrEmailCode:`${host} users/users/userAccount/sendPhoneOrEmailCode`,// 手机验证码
// 考核管理
pageByCondition: `${host}occupationlab/assessment/pageByCondition`, // 考核管理列表
saveAssessment: `${host}occupationlab/assessment/saveAssessment`, // 创建考核
modifyAssessment: `${host}occupationlab/assessment/modifyAssessment`, // 编辑考核
getDetailById: `${host}occupationlab/assessment/getDetailById`, // 根据考核Id查询考核详情
deleteAssessment: `${host}occupationlab/assessment/deleteAssessment`, // 单个、批量删除
collectPaper: `${host}occupationlab/assessment/collectPaper`, // 收卷(提前结束)
// 学生组织架构
treeList: `${host}occupationlab/architecture/treeList`, // 学生组织架构树形列表
// 测评管理
questionsList: `${host}occupationlab/questions/list`, // 题库列表查询
questionsSave: `${host}occupationlab/questions/save`, // 新增题目
questionsUpdate: `${host}occupationlab/questions/update`, // 根据试题id修改试题信息
questionsDetail: `${host}occupationlab/questions/detail`, // 查看当前题库信息
questionsDelete: `${host}occupationlab/questions/delete`, // 根据主键删除
questionsIsDisable: `${host}occupationlab/questions/isDisable`, // 是否禁用试题
questionsTemplate: `${Setting.apiBaseURL}template/试题导入模板.xlsx`, //excel模板文件下载
questionsImport: `${host}occupationlab/questions/importQuestion`, // 批量导入题库
questionsExportFailure: `${host}occupationlab/questions/exportFailure`, // 批量导入题库失败数据导出
questionsInfo: `${host}occupationlab/questions/info`, // 测评规则信息的展示
questionsUpdateRules: `${host}occupationlab/questions/updateEvaluationRules`, // 修改测评规则信息
// 项目管理
avgValues: `${host}occupationlab/projectManage/avgValues`, // 平均分分配值
deleteProjectManage: `${host}occupationlab/projectManage/deleteProjectManage`, // 新增项目管理
getProjectBySystemId: `${host}occupationlab/projectManage/getProjectBySystemId`, // 根据系统id获取全部项目(项目中没有用上这个接口)
queryNameIsExist: `${host}occupationlab/projectManage/queryNameIsExist`, // 新增/编辑项目管理名称判重
queryProjectManage: `${host}occupationlab/projectManage/queryProjectManage`, // 项目管理列表(分页、筛选)
updateIsOpen: `${host}occupationlab/projectManage/updateIsOpen`, // 更新开启状态
getProjectDetail: `${host}occupationlab/projectManage/getProjectDetail`, // 根据项目id查询详情
addProjectManage: `${host}occupationlab/projectManage/addProjectManage`, // 新增项目管理
updateProjectManage: `${host}occupationlab/projectManage/updateProjectManage`, // 修改项目管理
copyProjectManage: `${host}occupationlab/projectManage/copyProjectManage`, // 复制项目管理
// 判分点
getBcJudgmentPoint: `${host}judgment/bcJudgmentPoint/getBcJudgmentPoint`, // 获取编程类判分点列表(分页)
getLcJudgmentPoint: `${host}judgment/lcJudgmentPoint/queryAllJudgmentPoint`, // 获取流程类判分点列表(分页)
// 赛事管理
addContest: `${host}occupationlab/enterprise/match/contest/addContest`,
deleteContest: `${host}occupationlab/enterprise/match/contest/deleteContest`,
editContest: `${host}occupationlab/enterprise/match/contest/editContest`,
publishContest: `${host}occupationlab/enterprise/match/contest/publishContest`,
getContest: `${host}occupationlab/enterprise/match/contest/getContest`,
queryContestByCondition: `${host}occupationlab/enterprise/match/contest/queryContestByCondition`,
// 竞赛进展
addContestProgress: `${host}occupationlab/enterprise/match/contest-progress/addContestProgress`,
deleteContestProgress: `${host}occupationlab/enterprise/match/contest-progress/deleteContestProgress`,
getContestProgress: `${host}occupationlab/enterprise/match/contest-progress/getContestProgress`,
editContestProgress: `${host}occupationlab/enterprise/match/contest-progress/editContestProgress`,
// 报名人员
addApplicant: `${host}occupationlab/enterprise/match/applicant/addApplicant`,
disableContests: `${host}occupationlab/enterprise/match/applicant/disableContests`,
excelExport: `${host}occupationlab/enterprise/match/applicant/excelExport`,
queryApplicantByCondition: `${host}occupationlab/enterprise/match/applicant/queryApplicantByCondition`,
disableApplicant: `${host}occupationlab/enterprise/match/applicant/disableApplicant`,
batchExport: `${host}occupationlab/enterprise/match/applicant/batchExport`,
// 栏目管理
addColumn: `${host}occupationlab/enterprise/information/column/addColumn`,
deleteColumn: `${host}occupationlab/enterprise/information/column/deleteColumn`,
editColumn: `${host}occupationlab/enterprise/information/column/editColumn`,
queryAllColumns: `${host}occupationlab/enterprise/information/column/queryAllColumns`,
columnReorder: `${host}occupationlab/enterprise/information/column/reorder`,
// 内容管理
addArticle: `${host}occupationlab/enterprise/information/article/addArticle`,
deleteArticles: `${host}occupationlab/enterprise/information/article/deleteArticles`,
editArticle: `${host}occupationlab/enterprise/information/article/editArticle`,
enableArticle: `${host}occupationlab/enterprise/information/article/enableArticle`,
getArticle: `${host}occupationlab/enterprise/information/article/getArticle`,
getArticles: `${host}occupationlab/enterprise/information/article/getArticles`,
queryArticleByCondition: `${host}occupationlab/enterprise/information/article/queryArticleByCondition`,
articleSort: `${host}occupationlab/enterprise/information/article/articleSort`,
// 课程管理
queryCourseByCondition: `${host}occupationlab/management/edu/course/queryCourseByCondition`, // 课程列表分页条件查询
addCourse: `${host}occupationlab/management/edu/course/addCourse`, // 添加课程
deleteCourse: `${host}occupationlab/management/edu/course/deleteCourse`, // 根据id删除课程
deleteCourses: `${host}occupationlab/management/edu/course/deleteCourses`, // 批量删除课程
editCourse: `${host}occupationlab/management/edu/course/editCourse`, // 修改课程
enableCourse: `${host}occupationlab/management/schoolCourse/enableGlCourse`, // 是否启用管理端课程
getCourse: `${host}occupationlab/management/edu/course/getCourse`, // 根据id查询课程
// 分类管理
queryGlClassification: `${host}occupationlab/management/edu/courseClassification/queryGlClassification`,
deleteClassification: `${host}occupationlab/management/edu/courseClassification/deleteClassification`,
addClassification: `${host}occupationlab/management/edu/courseClassification/addClassification`,
editClassification: `${host}occupationlab/management/edu/courseClassification/editClassification`,
// 课程章节管理
addChapter: `${host}occupationlab/management/edu/courseChapter/addChapter`,
chapterReorder: `${host}occupationlab/management/edu/courseChapter/chapterReorder`,
deleteChapter: `${host}occupationlab/management/edu/courseChapter/deleteChapter`,
editChapter: `${host}occupationlab/management/edu/courseChapter/editChapter`,
queryChaptersAndSubsections: `${host}occupationlab/management/edu/courseChapter/queryChaptersAndSubsections`,
reorder: `${host}occupationlab/management/edu/courseChapter/reorder`,
// 课程小节管理
addSubsection: `${host}occupationlab/management/edu/courseSubsection/addSubsection`, // 添加小节
deleteSubsection: `${host}occupationlab/management/edu/courseSubsection/deleteSubsection`, // 根据id删除小节
editSubsection: `${host}occupationlab/management/edu/courseSubsection/editSubsection`, // 修改小节
getSubsection: `${host}occupationlab/management/edu/courseSubsection/getSubsection`, // 根据小节id获取预览文件地址
updateLogInNumber: `${host}liuwanr/userInfo/updateLogInNumber`, //用户登录修改登录次数和登陆时间
// 阿里云文件/视频管理
fileDeletion: `${host}nakadai/nakadai/oss/fileDeletion`, // 删除OSS文件
fileupload: `${host}nakadai/nakadai/oss/fileUpload`, // 文件上传
getPlayAuth: `${host}occupationlab/oss/manage/getPlayAuth`,
removeMoreVideo: `${host}occupationlab/oss/manage/removeMoreVideo`,
removeVideo: `${host}occupationlab/oss/manage/removeVideo`,
updateLogInNumber: `${host}liuwanr/userInfo/updateLogInNumber`, //用户登录修改登录次数和登陆时间
uploadUserAvatars: `${host}liuwanr/userInfo/uploadUserAvatars`, //上传头像
queryProvince: `${host}liuwanr/province/queryProvince`, //查询省份
queryCity: `${host}liuwanr/city/queryCity`, //查询城市
@ -51,12 +186,12 @@ export default {
info: `${host}evaluation/tms/evaluationrules/info`, //测评规则信息的展示
update: `${host}evaluation/tms/evaluationrules/update`, //修改测评规则信息
delete: `${host}evaluation/tms/questions/delete`, //批量删除试题信息
questionsTemplate: `${host}template/试题导入模板.xlsx`, //excel模板文件下载
// questionsTemplate: `${host}template/试题导入模板.xlsx`, //excel模板文件下载
import: `${host}evaluation/tms/questions/import`, //通过excel批量导入
infoId: `${host}evaluation/tms/questions/info/`, //根据试题id查询试题详情信息
isenable: `${host}evaluation/tms/questions/isenable`, //是否禁用试题
save: `${host}evaluation/tms/questions/save`, //新增一道试题
questionsUpdate: `${host}evaluation/tms/questions/update`, //根据试题id修改试题信息
// questionsUpdate: `${host}evaluation/tms/questions/update`, //根据试题id修改试题信息
upload: `${host}evaluation/tms/questions/upload`, //excel模板文件上传
export_failure: `${host}evaluation/tms/questions/export_failure`, //导出导入失败的数据和失败原因
@ -69,10 +204,10 @@ export default {
getInvitationCode: `${host}evaluation/tms/exp/getInvitationCode`, //查询邀请码是否存在
expInfo1: `${host}evaluation/tms/exp/upload`, //实验教学提前结束
queryAllManagements: `${host}project/ProjectManagement/queryAllManagements`, //项目管理列表信息
// queryAllManagements: `${host}project/ProjectManagement/queryAllManagements`, //项目管理列表信息
queryManagements: `${host}project/ProjectManagement/queryManagements`, //项目管理列表信息
addRole: `${host}project/ProjectManagement/addRole`, //新增案例对象
avgValues: `${host}project/ProjectManagement/avgValues`, //平均分配分值
// avgValues: `${host}project/ProjectManagement/avgValues`, //平均分配分值
getByRoleId: `${host}project/ProjectManagement/getByRoleId`, //根据角色id查询信息
getByjudgmentPointsId: `${host}project/ProjectManagement/getByjudgmentPointsId`, //实验任务表格信息的展示
queryAllJudgmentPoints: `${host}project/ProjectManagement/queryAllJudgmentPoints`, //添加判分点面板的数据展示+条件筛选
@ -140,8 +275,8 @@ export default {
queryAchievementNew: `${host}evaluation/Achievement/newList`,
queryEvaluationReport: `${host}evaluation/Achievement/queryEvaluationReport`,
queryReport: `${host}evaluation/Achievement/queryReport`,
queryArchievement: `${host}evaluation/tms/classTech/queryExperimentalReport`, //查看教学实验报告
queryVirtualReport: `${host}evaluation/tms/classTech/queryVirtualReport`, //查看虚仿实验报告
queryArchievement: `${host}evaluation/tms/classTech/queryExperimentalReport`, //查看教学实验报告
queryVirtualReport: `${host}evaluation/tms/classTech/queryVirtualReport`, //查看虚仿实验报告
// 教师评语
addComment: `${host}evaluation/comment/addComment`,
@ -164,4 +299,5 @@ export default {
firstLevel: `${host1}sichuan/point/firstLevel`,
secondaryLevel: `${host1}sichuan/point/secondaryLevel`,
thirdLevel: `${host1}sichuan/point/thirdLevel`,
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

@ -2,13 +2,21 @@
<div class="quill" ref="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-upload
:headers="headers"
: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 util from '@/libs/util'
import Setting from '@/setting'
import Quill from 'quill';
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
@ -50,6 +58,9 @@
},
data () {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
Quill: null,
currentValue: '',
options: {
@ -169,15 +180,15 @@
//
let quill = this.Quill
//
if (res.data.filesResult.fileUrl) {
if (res.filesResult.fileUrl) {
//
let length = quill.getSelection().index;
// res
quill.insertEmbed(length, 'image', res.data.filesResult.fileUrl)
quill.insertEmbed(length, 'image', res.filesResult.fileUrl)
//
quill.setSelection(length + 1)
} else {
this.$message.success('图片插入失败')
util.successMsg('图片插入失败')
}
this.loading = false
},

@ -39,6 +39,7 @@ export default {
...mapActions('user', [
'logout'
]),
// ,退
autoLogout(){
let lastTime = new Date().getTime()
document.onmousedown = () => {

@ -37,6 +37,16 @@ export default {
return {
active: this.$route.path,
defaultMenus: [
{
icon: 'el-icon-user',
index: '/student/list',
title: '学生管理'
},
{
icon: 'el-icon-receiving',
index: '/evaluation/list',
title: '测评管理'
},
{
icon: 'el-icon-takeaway-box',
index: '/assessment/list',
@ -48,20 +58,25 @@ export default {
title: '成绩管理'
},
{
icon: 'el-icon-receiving',
index: '/evaluation/list',
title: '测评管理'
icon: 'el-icon-news',
index: '/course/list',
title: '理论课程管理'
},
{
icon: 'el-icon-document',
index: '/information/list',
title: '资讯管理'
},
{
icon: 'el-icon-school',
index: '/match/list',
title: '赛事管理'
},
{
icon: 'el-icon-postcard',
index: '/project/list',
title: '实验项目管理'
},
{
icon: 'el-icon-user',
index: '/student/list',
title: '学生管理'
},
{
icon: 'el-icon-setting',
index: '/system/list',

@ -6,20 +6,16 @@ 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.path ? result.push(`${e.path}:${n.name}:${j.name}`) : result.push(`${n.path}:${j.name}`))
e.menuUrl ? result.push(`${e.menuUrl}:${n.name}:${j.name}`) : result.push(`${n.menuUrl}:${j.name}`)
})
}else{
result.push(`${e.path}:${n.name}`)
}
result.push(`${e.menuUrl}:${n.name}`)
}
})
}
})
store.dispatch('auth/addBtnAuth',result)
}

@ -11,15 +11,15 @@ function createMeta(item){
function createRoute(data){
data.map(e => {
if(e.select && e.path){
if(e.menuUrl){
let meta = createMeta(e)
newRoutes.push({
name: e.path,
path: e.path,
path: () => import(`@/pages/${e.path}.vue`),
name: e.menuUrl,
path: e.menuUrl,
meta
})
}
// 递归生成路由集合
e.children && e.children.length && createRoute(e.children)
})
}
@ -28,5 +28,4 @@ export default function(data,path){
generateBtnPermission(data)
createRoute(data)
store.dispatch('auth/addRoutes',newRoutes)
// router.addRoutes(routes)
}

@ -147,14 +147,17 @@ const util = {
},
// 成功提示
successMsg(message,duration = 3000) {
Message.closeAll();
return Message.success({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration})
},
// 警告提示
warningMsg(message,duration = 3000) {
Message.closeAll();
return Message.warning({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration})
},
// 错误提示
errorMsg(message,duration = 3000) {
Message.closeAll();
return Message.error({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration})
},
// 传入roleId,返回角色名称

@ -30,7 +30,7 @@ Vue.prototype.$put = put;
Vue.config.productionTip = false;
Vue.use(VueI18n);
Vue.use(ElementUI);
Vue.use(ElementUI, { size: 'small' });
const i18n = new VueI18n({
locale: Setting.i18n.default,
messages

@ -7,40 +7,56 @@
<div class="main">
<div class="box">
<el-tabs v-model="type">
<el-tab-pane label="账号登录" name="0">
<el-form :model="param" :rules="rules" ref="param" label-width="0px" style="margin-top: 40px">
<el-form-item prop="username">
<el-input v-model="param.username" placeholder="请输入账号"></el-input>
<el-tabs v-model="tabName">
<el-tab-pane label="账号登录" name="1">
<el-form v-if="tabName === '1'" :model="param" :rules="rules" ref="param" label-width="0px" style="margin-top: 40px">
<el-form-item prop="account">
<el-input v-model="param.account" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
placeholder="请输入密码"
v-model="param.password"
>
</el-input>
</el-form-item>
<el-form-item prop="code">
<el-input
placeholder="请输入验证码"
v-model="param.code"
@keyup.enter.native="submitForm('param')"
>
</el-input>
<img style="cursor: pointer;" @click="blur" :src="verificationIMG" class="verification" alt="">
</el-form-item>
<el-button class="btn" type="primary" @click="submitForm('param')">马上登录</el-button>
</el-form>
</el-tab-pane>
<el-tab-pane label="手机号/邮箱登录" name="1">
<el-form :model="phoneParam" :rules="phoneRules" ref="phoneParam" label-width="0px" style="margin-top: 40px">
<el-form-item prop="userphone">
<el-input v-model="phoneParam.userphone" placeholder="请输入手机号/邮箱"></el-input>
<el-tab-pane label="手机号/邮箱登录" name="2">
<el-form v-if="tabName === '2'" :model="param" :rules="rules" ref="param" label-width="0px" style="margin-top: 40px">
<el-form-item prop="account">
<el-input v-model="param.account" placeholder="请输入手机号/邮箱"></el-input>
</el-form-item>
<el-form-item prop="phonePassword">
<el-form-item prop="password">
<el-input
type="password"
placeholder="请输入密码"
v-model="phoneParam.phonePassword"
@keyup.enter.native="submitForm('phoneParam')"
v-model="param.password"
>
</el-input>
</el-form-item>
<el-form-item prop="code">
<el-input
placeholder="请输入验证码"
v-model="param.code"
@keyup.enter.native="submitForm('param')"
>
</el-input>
<img style="cursor: pointer;" @click="blur" :src="verificationIMG" class="verification" alt="">
</el-form-item>
<el-button class="btn" type="primary" @click="submitForm('phoneParam')">马上登录</el-button>
<el-button class="btn" type="primary" @click="submitForm('param')">马上登录</el-button>
</el-form>
</el-tab-pane>
</el-tabs>
@ -60,23 +76,21 @@ export default {
data: function() {
return {
isHh: Setting.isHh,
tabName: "1",
param: {
username: '',
password: ''
account: 'admin',
password: '111aaa',
code: '', //
random: '', //
distinguish: null, // ,1,2
platform: 3, // 123
},
rules: {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
},
phoneParam: {
userphone: '',
phonePassword: ''
},
phoneRules: {
userphone: [{ required: true, message: '请输入手机号/邮箱', trigger: 'blur' }],
phonePassword: [{ required: true, message: '请输入密码', trigger: 'blur' }],
},
type: '0'
verificationIMG: ""
};
},
components: {
@ -89,21 +103,24 @@ export default {
submitForm(form) {
this.$refs[form].validate(valid => {
if (valid) {
let data = {
account: this.type == '0' ? this.param.username : this.phoneParam.userphone,
password: this.type == '0' ? this.param.password : this.phoneParam.phonePassword,
source: this.type
}
this.login(data).then(() => {
this.param.distinguish = this.tabName === '1' ? 1 : 2;
this.login(this.param).then(() => {
let redirect = this.$route.query.redirect ? decodeURIComponent(this.$route.query.redirect) : '/index'
this.$router.replace(redirect)
}).catch(res => {})
} else {
return util.errorMsg('请输入账号和密码')
return util.errorMsg('请检查表单数据')
}
});
},
blur() {
this.param.random = Math.floor(Math.random()*999999999);
this.verificationIMG = this.api.verification+'?random='+`${this.param.random}`;
}
},
created(){
this.blur();
}
};
</script>
@ -180,6 +197,15 @@ export default {
border:1px solid rgba(220,220,220,1);
border-radius:2px;
}
.verification{
position: absolute;
top: 1px;
right: 1px;
width: 160px;
height: 78px;
}
.btn {
width: 100%;
height: 88px;

@ -163,7 +163,7 @@ export default {
})
.then(() => {
this.$post(`${this.api.deleteReport}?reportId=${row.reportId}&recordId=${row.recordId}`).then(res => {
this.$message.success('删除成功');
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
})
@ -183,7 +183,7 @@ export default {
})
.then(() => {
this.$post(`${this.api.deleteReport}?${delList.join('&')}&${delList1.join('&')}`).then(res => {
this.$message.success('删除成功')
util.successMsg('删除成功')
this.getData()
}).catch(res => {})
})

@ -293,7 +293,7 @@
this.isEdit = true
},
handleExceed(files, fileList) {
this.$message.warning(
util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
@ -302,7 +302,7 @@
util.successMsg('上传成功')
this.getSgin()
}else{
util.errorMsg(res.errmessage)
$message.error(res.errmessage)
}
},
goback() {

@ -155,6 +155,7 @@ export default {
}
},
mounted() {
// systemIdsystemIdsystemId
this.systemId = this.lastSystemId ? this.lastSystemId : Setting.systemId
this.getData()
},

@ -251,9 +251,6 @@ import Setting from '@/setting'
})
}
},
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;

@ -19,29 +19,19 @@
clearable
maxlength="15"
class="inline-input"
@change="judgeExpName"
></el-input>
</div>
</el-card>
<el-card shadow="hover" class="mgr20 m-b-20">
<div>
<p class="m-b-20">班级名称</p>
<el-input
placeholder="请输入班级名称"
v-model="experimentalClassName"
clearable
maxlength="15"
class="inline-input"
></el-input>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<div>
<p class="m-b-20">发布方式</p>
<el-radio :disabled="id ? true : false" v-model="type" label="1" class="fons">手动发布</el-radio>
<el-radio :disabled="id ? true : false" v-model="type" label="2" class="fons">定时发布</el-radio>
<el-radio-group v-model="type" :disabled="id ? true : false">
<el-radio :label="1">手动发布</el-radio>
<el-radio :label="2">定时发布</el-radio>
</el-radio-group>
</div>
</el-card>
<!-- 根据发布方式判断时间的显示 -->
@ -74,7 +64,7 @@
<el-card shadow="hover" class="mgr20 m-b-20">
<div>
<p class="m-b-20">系统</p>
<p class="m-b-20">课程</p>
<div class="inline-input">
<el-select v-model="systemId" placeholder="请选择" @change="initData">
<el-option
@ -110,15 +100,15 @@
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
<el-table-column prop="auth" label="项目权限" align="center">
<template slot-scope="scope">
{{projectPermissionsList[scope.row.projectPermissions]}}
{{ founderKeys[scope.row.founder] }}
</template>
</el-table-column>
<el-table-column prop="creater" label="创建人" align="center">
<template slot-scope="scope">
{{roleStatus(scope.row.founder)}}
{{ permissionsKeys[scope.row.permissions] }}
</template>
</el-table-column>
<el-table-column prop="creationTime" label="创建时间" align="center"></el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showProject(scope.row)">查看</el-button>
@ -136,15 +126,63 @@
</div>
</el-card>
<el-card shadow="hover" class="mgr20 m-b-20">
<div>
<p class="m-b-20">考核发布</p>
<el-radio-group v-model="isSpecify">
<el-radio :label="1">指定范围</el-radio>
<el-radio :label="0">无指定范围</el-radio>
</el-radio-group>
</div>
<div v-show="isSpecify === 1" style='padding-top: 24px;'>
<p class="m-b-20">班级名称</p>
<el-input
placeholder="请输入班级名称"
v-model="filterClassName"
class="inline-input"
clearable
></el-input>
<div v-show='tagList.length' style="padding: 24px 0">
<el-tag
v-for="(tag, index) in tagList"
:key="index"
closable
@close="handleCloseTag(tag)"
style="margin-right: 10px"
>
{{tag.className}}
</el-tag>
</div>
<el-tree
ref="tree"
node-key="id"
show-checkbox
highlight-current
default-expand-all
:data="classTreeList"
:default-checked-keys="defaultCheckedList"
:filter-node-method="filterNode"
:props="defaultProps"
@check="handleCheck"
>
</el-tree>
</div>
</el-card>
<!-- 邀请码 -->
<el-card shadow="hover">
<el-card v-if='isSpecify === 0' shadow="hover" class="m-b-20">
<div style="margin-bottom: 10px">
<p class="m-b-20">设置邀请码</p>
<el-radio v-model="isCode" label="0"></el-radio>
<el-radio v-model="isCode" label="1"></el-radio>
<el-radio-group v-model="isEnableCode">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</div>
<div v-show="isCode == 0">
<el-input style="display: inline-block;width: auto;margin-right: 10px" v-model.number="invitationCode" maxlength="6" placeholder="请设置6个数字"></el-input>
<div v-if="isEnableCode === 0">
<el-input style="display: inline-block;width: auto;margin-right: 10px" type="number" v-model="invitationCode" maxlength="6" placeholder="请设置6个数字"></el-input>
<el-button type="text" @click="createInv">随机</el-button>
</div>
</el-card>
@ -158,11 +196,33 @@ import { mapState, mapActions } from 'vuex'
export default {
data() {
return {
founderKeys: {
0: '系统',
1: '老师'
},
permissionsKeys: {
0: '练习',
1: '考核',
2: '竞赛'
},
id: '',
roleStatus: util.getRoleName,
type: 1, // (1 2)
isSpecify: 1, // (1 2)
filterClassName: "", //
tagList: [], //
classTreeList: [], //
defaultCheckedList: [], //
allCheckedNodes: [], //
allCheckedKeys: [], // key
defaultProps: {
children: 'children',
label: 'organizationName'
}, //
schoolId: Setting.schoolId, // id Setting.schoolId
systemId: Setting.systemId,
systemList: Setting.systemList,
isDetail: true,
roleStatus: util.getRoleName,
isDetail: Boolean(this.$route.query.show),
duration: {
day: '',
hour: '',
@ -175,12 +235,10 @@ export default {
experimentalNumber: 0,
projectId: '',
projectName: '',
status: '',
status: 0, // (0 1 2)
surplusTime: '',
experimentalName: '',//
experimentalClassName: '', //
type: '1',
isCode: '0', //
isEnableCode: 0, //
startTime: '0000-00-00 00:00:00', //
stopTime: '0000-00-00 00:00:00', //
invitationCode: '',
@ -216,13 +274,13 @@ export default {
]),
},
mounted() {
console.log(22,this.assFields)
// console.log(22,this.assFields)
this.date = [util.formatDate("yyyy-MM-dd hh:mm:ss",new Date(new Date().getTime() + 300000)),util.formatDate("yyyy-MM-dd hh:mm:ss",new Date(new Date().getTime() + 300000))]
this.id = this.$route.query.id
this.isDetail = Boolean(this.$route.query.show)
this.id && this.getData()
this.getProjectData()
this.recoveryData()
this.getClassTreeData()
},
beforeDestroy(){
if(!this.isToProject) this.setAss({})
@ -245,23 +303,117 @@ export default {
this.searchTimer = setTimeout(() => {
this.initData()
},500)
},
filterClassName(val) {
this.$refs.tree.filter(val);
}
},
methods: {
...mapActions('project', [
'setAss'
]),
handleCloseTag(tag) { //
let tagIndex = this.tagList.findIndex( i => i.classId === tag.classId);
this.tagList.splice(tagIndex, 1);
//
let classIndex = this.allCheckedNodes.findIndex( i => i.id === tag.id);
// keys
let studentsKeys = [];
if(this.allCheckedNodes[classIndex].children && this.allCheckedNodes[classIndex].children.length) {
studentsKeys = this.allCheckedNodes[classIndex].children.map( i => i.id);
}
let filterKeys = [...studentsKeys, this.allCheckedNodes[classIndex].id];
let setKeys = []; //
this.allCheckedKeys.forEach(i => {
if(!filterKeys.includes(i)){
setKeys.push(i)
}
}); //
this.allCheckedKeys = setKeys; // key
console.log("所有节点keys===",JSON.stringify(this.allCheckedKeys));
console.log("当前班级和学生keys===",JSON.stringify(filterKeys));
console.log("设置选中的节点===",JSON.stringify(setKeys));
let tempArr = [];
this.allCheckedNodes.forEach(i => {
if(!filterKeys.includes(i.id)){
tempArr.push(i)
}
});
this.allCheckedNodes = tempArr; //
this.$refs.tree.setCheckedKeys(setKeys);
},
handleCheck(data, checked) { //
console.log(checked);
// console.log(JSON.stringify(checked.checkedNodes));
//
let checkedClass = checked.checkedNodes.filter( i => i.level === 3);
let halfCheckedClass = checked.halfCheckedNodes.filter( i => i.level === 3);
this.tagList = [...checkedClass, ...halfCheckedClass].map(i => {
return {classId: i.id, className: i.organizationName}
});
//
this.allCheckedNodes = [...checked.checkedNodes, ...checked.halfCheckedNodes];
// key
let tempArr = checked.checkedNodes.filter( i => i.level === 3 || i.level === 4);
this.allCheckedKeys = tempArr.map(i => i.id);
},
filterNode(value, data) { //
if (!value) return true;
return data.organizationName.indexOf(value) !== -1;
},
toTreeId(data) { // idid+id,便key
if (!data) return data;
let result;
if (Array.isArray(data)) {
result = [];
data.forEach(item => {
if (item.level < 4 && item.children && item.children.length) {
item.children = this.toTreeId(item.children);
} else if (item.level === 4) {
item.id = `${item.parentId}-${item.id}`;
}
result.push(item);
});
}
return result;
},
getClassTreeData () { //
this.$post(`${this.api.treeList}?schoolId=${this.schoolId}`).then(res => {
let {status, list} = res;
if (status === 200 && list) {
this.classTreeList = this.toTreeId(res.list);
} else {
util.errorMsg(res.message);
}
}).catch(err => {
console.log(err);
});
},
getProjectData(){
let data = {
pageNo: this.page,
schoolId: this.schoolId, // id
platformId: 1, // :1 :3
permissions: 1, // (0: 1: 2:)
projectName: this.keyword, //
systemId: this.systemId, // id
founder: 0, // (0: 1:)
state: 1, // (0:稿 1:)
pageNum: this.page,
pageSize: 10000,
userId: this.userId,
systemId: this.systemId,
projectName: this.keyword,
projectPermissions: 1,
}
this.$get(this.api.queryAllManagements,data).then(res => {
let list = res.pageInfo.list
this.$post(this.api.queryProjectManage, data).then(res => {
let { status, data } = res;
if (status === 200 && data) {
let list = data.records;
let result = []
list.map(n => {
n.enable || result.push(n)
@ -269,7 +421,10 @@ export default {
this.projectDataAll = result
this.total = result.length
this.handlePage()
}).catch(res => {});
}
}).catch(err => {
console.log(err);
});
},
handlePage(){
let list = this.projectDataAll
@ -284,112 +439,155 @@ export default {
if(JSON.stringify(this.assFields) != '{}'){
let info = this.assFields
this.experimentDuration = info.experimentDuration
this.experimentalClassName = info.experimentalClassName
this.experimentalName = info.experimentalName
this.invitationCode = info.invitationCode
this.isCode = String(info.isCode)
this.isEnableCode = info.isEnableCode
this.projectId = info.projectId
this.startTime = info.startTime
this.stopTime = info.stopTime
this.surplusTime = info.surplusTime
this.type = String(info.type)
this.type = info.type
this.expNameRepeat = info.expNameRepeat
this.formatDuration()
}
},
upload() {
if(!this.experimentalName) return this.$message.warning('请填写考核名称')
if(this.expNameRepeat) return this.$message.warning('考核名称重复,请重新输入')
if(!this.experimentalClassName) return this.$message.warning('请填写班级名称')
if(this.type == 1){
this.status = 1
}else{
if(new Date().getTime() > new Date(this.startTime).getTime()) return this.$message.warning('开始时间不能早于当前时间')
this.status = 1
upload() { //
if(!this.experimentalName) return util.warningMsg('请填写考核名称')
if(this.expNameRepeat) return util.warningMsg('考核名称重复,请重新输入')
if(this.type !== 1){
if(new Date().getTime() > new Date(this.startTime).getTime()) return util.warningMsg('开始时间不能早于当前时间')
let timestamp = new Date(new Date(this.stopTime).getTime() - new Date(this.startTime).getTime())
let minute = 1000 * 60
let hour = minute * 60
let day = hour * 24
this.experimentDuration = `${Math.floor(timestamp / day)}d${Math.floor(timestamp % day / hour)}h${Math.floor(timestamp % day % hour / minute)}m`
}
if(this.type == 1 && this.experimentDuration == '0d0h0m') return this.$message.warning('请填写实验时长')
if(this.type == 2 && this.startTime == '0000-00-00 00:00:00') return this.$message.warning('请填写实验时间')
if(!this.projectId) return this.$message.warning('请选择实训项目')
if(this.type == 1 && this.experimentDuration == '0d0h0m') return util.warningMsg('请填写实验时长')
if(this.type == 2 && this.startTime == '0000-00-00 00:00:00') return util.warningMsg('请填写实验时间')
if(!this.projectId) return util.warningMsg('请选择实训项目')
this.projectName = this.projectData.find(n => n.projectId == this.projectId).projectName
if(this.isCode == 0){
if(!this.invitationCode) return this.$message.warning('请设置邀请码')
if(!this.invitationCode || String(this.invitationCode).length < 6 || isNaN(this.invitationCode)) return this.$message.warning('请输入6位纯数字邀请码')
// if(this.invRepeat) return this.$message.warning('')
if(this.isSpecify === 0 && this.isEnableCode == 0){
if(!this.invitationCode) return util.warningMsg('请设置邀请码')
if(!this.invitationCode || String(this.invitationCode).length < 6 || isNaN(this.invitationCode)) return util.warningMsg('请输入6位纯数字邀请码')
// if(this.invRepeat) return util.warningMsg('')
}
let classId = "";
let stuInfo = [];
if (this.isSpecify === 1) {
if (!this.tagList.length) {
util.warningMsg('请选择学生')
return;
} else {
let ids = this.tagList.map(i => i.classId);
classId = ids.toString();
let nodes = this.allCheckedNodes.filter( i => i.level === 4);
nodes.forEach(i => {
let arr = i.id.split("-")
stuInfo.push({classId: arr[0], stuAccountId: arr[1]})
});
}
}
let data = {
id: this.id,
experimentDuration: this.experimentDuration,
creationTime: this.id ? this.creationTime : util.formatDate("yyyy-MM-dd hh:mm:ss"),
experimentalClassName: this.experimentalClassName,
createTime: this.id ? this.createTime : util.formatDate("yyyy-MM-dd hh:mm:ss"),
experimentalName: this.experimentalName,
experimentalNumber: this.experimentalNumber,
invitationCode: this.invitationCode,
isCode: this.isCode,
isEnableCode: this.isEnableCode,
projectId: this.projectId,
projectName: this.projectName,
status: Number(this.status),
status: this.status,
surplusTime: this.surplusTime,
type: Number(this.type),
type: this.type,
userId: this.userId,
systemId: this.systemId
systemId: this.systemId,
isSpecify: this.isSpecify,
classId,
stuInfo,
}
if(this.type == 2){
data.startTime = this.startTime
data.stopTime = this.stopTime
}else{
data.startTime = '0000-00-00 00:00:00'
data.stopTime = '0000-00-00 00:00:00'
}
if(this.id){
this.$post(this.api.expUpdate, data).then(res => {
this.$post(this.api.modifyAssessment, data).then(res => {
util.successMsg('修改成功');
this.$router.back()
})
.catch(err => {
console.log(err);
});
}else{
this.$post(this.api.expSave, data).then(res => {
this.$post(this.api.saveAssessment, data).then(res => {
if (res.status === 200) {
util.successMsg('创建成功');
this.$router.back()
} else {
}
})
.catch(err => {
console.log(err);
});
}
},
getData() {
this.$get(this.api.expInfo + this.id)
this.$get(`${this.api.getDetailById}?id=${this.id}`)
.then(res => {
if(res.errmessage == 'success'){
let info = res.ExperimentalTeaching
this.creationTime = info.creationTime
if(res.status == 200){
let info = res.data;
this.createTime = info.createTime
this.experimentDuration = info.experimentDuration
this.experimentalClassName = info.experimentalClassName
this.experimentalName = info.experimentalName
this.experimentalNumber = info.experimentalNumber
this.invitationCode = info.invitationCode
this.isCode = String(info.isCode)
this.isEnableCode = info.isEnableCode
this.projectId = info.projectId
this.projectName = info.projectName
this.startTime = info.startTime
this.status = info.status
this.stopTime = info.stopTime
this.surplusTime = info.surplusTime
this.type = String(info.type)
this.type = info.type
this.formatDuration()
//
this.formatDuration();
//
if (info.stuInfo && info.stuInfo.length) {
let keys = info.stuInfo.map(i => {
return `${i.classId}-${i.stuAccountId}`;
});
this.$nextTick(function () {
this.$refs.tree.setCheckedKeys(keys);
});
}
//
this.allCheckedNodes = this.$refs.tree.getCheckedNodes().concat(this.$refs.tree.getHalfCheckedNodes());
// key
let tempArr = this.$refs.tree.getCheckedNodes().filter( i => i.level === 3 || i.level === 4);
this.allCheckedKeys = tempArr.map(i => i.id);
this.tagList = this.allCheckedNodes.map(i => {
let obj = {};
if (i.level === 3) {
obj = { classId: i.id, className: i.organizationName }
}
return obj;
})
}else{
util.errorMsg('查询失败');
util.errorMsg(res.message);
}
})
.catch(err => {
console.log(err);
});
},
formatDuration(){
@ -405,10 +603,9 @@ export default {
let data = {
id: this.id,
experimentDuration: this.experimentDuration,
experimentalClassName: this.experimentalClassName,
experimentalName: this.experimentalName,
invitationCode: this.invitationCode,
isCode: this.isCode,
isEnableCode: this.isEnableCode,
projectId: this.projectId,
startTime: this.startTime,
stopTime: this.stopTime,
@ -421,11 +618,11 @@ export default {
},
toProject(){
this.handleCacheData()
this.$router.push('/project')
this.$router.push('/project/list/?show=1')
},
showProject(row){
this.handleCacheData()
this.$router.push(`/addproject?id=${row.projectId}&show=1`)
this.$router.push(`/project/add?projectId=${row.projectId}&show=1`)
},
goBack() {
if(this.isDetail){
@ -444,7 +641,7 @@ export default {
this.$get(this.api.getInvitationCode, { invitationCode: this.invitationCode })
.then(res => {
if(res.InvitationCode) {
this.$message.warning('邀请码重复,请重新输入')
util.warningMsg('邀请码重复,请重新输入')
this.invRepeat = true
}else{
this.invRepeat = false
@ -463,19 +660,7 @@ export default {
handleCurrentChange(val){
this.page = val
this.handlePage()
},
judgeExpName(){
this.$get(this.api.expCheck, { experimentalName: util.encodeStr(this.experimentalName) })
.then(res => {
if(res.errmessage != 'success') {
this.$message.warning('考核名称重复,请重新输入')
this.expNameRepeat = true
}else{
this.expNameRepeat = false
}
})
.catch(err => {});
},
},
};
</script>

@ -35,7 +35,7 @@
</el-select>
</li>
<li>
<el-input size="small" placeholder="请输入实验班级/项目名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
<el-input size="small" placeholder="请输入实验班级/项目名称" prefix-icon="el-icon-search" v-model="keyWord" clearable></el-input>
</li>
</ul>
<div>
@ -45,17 +45,17 @@
</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.status!=2" width="50" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="selection" :selectable="row => row.status!=1" width="50" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center">
<template slot-scope="scope">
{{scope.$index + (page - 1) * pageSize + 1}}
{{scope.$index + (pageNum - 1) * pageSize + 1}}
</template>
</el-table-column>
<el-table-column prop="experimentalClassName" label="实验班级" align="center">
<el-table-column prop="className" label="实验班级" align="center">
</el-table-column>
<el-table-column prop="experimentalName" label="考核名称" min-width="120" align="center">
<el-table-column prop="experimentalName" label="考核名称" align="center">
</el-table-column>
<el-table-column prop="projectName" label="项目名称" align="center">
<el-table-column prop="projectName" label="项目名称" width="250" show-overflow-tooltip align="center">
</el-table-column>
<el-table-column prop="experimentalNumber" label="实验人数" align="center">
</el-table-column>
@ -63,7 +63,7 @@
</el-table-column>
<el-table-column label="邀请码" align="center">
<template slot-scope="scope">
<span>{{scope.row.isCode == 0 ? scope.row.invitationCode : ''}}</span>
<span>{{scope.row.isEnableCode == 0 ? scope.row.invitationCode : ''}}</span>
</template>
</el-table-column>
<el-table-column prop="adminName" label="发布类型" align="center">
@ -71,23 +71,23 @@
<span>{{types[scope.row.type]}}</span>
</template>
</el-table-column>
<el-table-column prop="creationTime" width="150" label="创建时间" align="center">
<el-table-column prop="createTime" width="150" label="创建时间" align="center">
</el-table-column>
<el-table-column prop="startTime" width="150" label="起始时间" align="center">
<template slot-scope="scope">
<span>{{transferTime(scope.row.startTime,scope.row.type)}}</span>
</template>
</el-table-column>
<el-table-column prop="stopTime" width="150" label="结束时间" align="center">
<el-table-column prop="endTime" width="150" label="结束时间" align="center">
<template slot-scope="scope">
<span>{{transferTime(scope.row.stopTime,scope.row.type)}}</span>
</template>
</el-table-column>
<el-table-column prop="surplusTime" label="倒计时" align="center">
<!-- <template slot-scope="scope">
<span v-if="scope.row.status == 2" v-countdown="scope.row.surplusTime">{{scope.row.surplusTime}}</span>
<template slot-scope="scope">
<span v-if="scope.row.status == 1" v-countdown="scope.row.surplusTime">{{scope.row.surplusTime}}</span>
<span v-else>00:00:00</span>
</template> -->
</template>
</el-table-column>
<el-table-column label="实验状态" align="center">
<template slot-scope="scope">
@ -96,22 +96,22 @@
</el-table-column>
<el-table-column label="操作" align="center" width="170">
<template slot-scope="scope">
<template v-if="scope.row.status == 1">
<template v-if="scope.row.status == 0">
<el-button type="text" @click="start(scope.row)" v-auth>启动</el-button>
<el-button type="text" @click="edit(scope.row)" v-auth>修改</el-button>
</template>
<template v-else-if="scope.row.status == 2">
<template v-else-if="scope.row.status == 1">
<el-button type="text" @click="finish(scope.row)" v-auth>提前结束</el-button>
</template>
<template v-else-if="scope.row.status == 3">
<template v-else-if="scope.row.status == 2">
<el-button type="text" @click="show(scope.row)" v-auth>查看成绩</el-button>
</template>
<el-button v-if="scope.row.status == 1 || scope.row.status == 3" type="text" @click="delData(scope.row)" v-auth>删除</el-button>
<el-button v-if="scope.row.status == 0 || scope.row.status == 2" type="text" @click="delData(scope.row)" v-auth>删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page"></el-pagination>
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="pageNum"></el-pagination>
</div>
</div>
</template>
@ -119,13 +119,10 @@
<script>
import Setting from '@/setting'
import util from '@/libs/util'
import { mapState, mapActions } from 'vuex'
export default {
data() {
return {
systemList: Setting.systemList,
systemId: '',
keyword: '',
typeList: [
{
value: '',
@ -140,7 +137,6 @@ export default {
name: '定时发布'
}
],
status: ['','待开始','进行中','已完成'],
types: ['','手动发布','定时发布'],
statusList: [
{
@ -148,28 +144,19 @@ export default {
name: '不限'
},
{
value: 1,
value: 0,
name: '待开始'
},
{
value: 2,
value: 1,
name: '进行中'
},
{
value: 3,
value: 2,
name: '已完成'
}
],
listData: [],
form: {
type: '',
status: '',
startTime: '',
stopTime: '',
month: '',
searchContent: ''
},
multipleSelection: [],
status: ['待开始','进行中','已完成'],
dateList: [
{
id: '',
@ -189,9 +176,21 @@ export default {
}
],
date: [],
page: 1,
pageSize: 10,
total: 0,
systemList: Setting.systemList,
systemId: '',
keyWord: '', //
form: {
type: '',
status: '',
startTime: '',
endTime: '',
month: ''
},
pageNum: 1, //
pageSize: 10, // 10
total: 0, //
listData: [], //
multipleSelection: [], //
ruleIds: [],
timer: null
};
@ -220,15 +219,15 @@ export default {
}
},
computed: {
...mapState('user', [
'schoolId'
]),
role() {
return this.name === 'admin' ? '超级管理员' : '普通用户';
}
},
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))]
this.date = [util.formatDate('yyyy-MM-dd',new Date(new Date().getTime() - unit * 30 * val)),util.formatDate('yyyy-MM-dd',new Date(new Date().getTime() + unit))]
}else{
this.date = []
}
@ -236,54 +235,54 @@ export default {
date: function(val){
if(val){
this.form.startTime = val[0]
this.form.stopTime = val[1]
this.form.endTime = val[1]
}else{
this.form.startTime = ''
this.form.stopTime = ''
this.form.endTime = ''
}
this.initData()
},
keyword: function(val) {
keyWord: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.initData()
},500)
}
},
computed: {
role() {
return this.name === 'admin' ? '超级管理员' : '普通用户';
}
},
mounted() {
this.getData()
this.timer = setInterval(this.getData,1000)
this.$once('hook:beforeDestroy',() => {
clearInterval(this.timer)
})
// this.timer = setInterval(this.getData,1000)
// this.$once('hook:beforeDestroy',() => {
// clearInterval(this.timer)
// })
},
methods: {
getData() {
let data = {
type: this.form.type,
startTime: this.form.startTime,
stopTime: this.form.stopTime,
endTime: this.form.endTime,
month: this.form.month,
searchContent: util.encodeStr(this.keyword),
status: this.form.status,
page: this.page,
size: this.pageSize,
systemId: this.systemId,
schoolId: this.schoolId ? this.schoolId : ''
keyWord: this.keyWord,
pageNum: this.pageNum,
pageSize: this.pageSize,
systemId: this.systemId
}
this.$get(this.api.expList,data).then(res => {
this.listData = res.list.list
this.total = res.list.totalCount
}).catch(res => {});
this.$post(this.api.pageByCondition,data).then(res => {
if (res.status === 200) {
this.listData = res.list;
this.total = res.total;
} else {
util.errorMsg(res.message);
}
}).catch(err => {
console.log(err);
});
},
initData(){
this.$refs.table.clearSelection()
this.page = 1
this.pageNum = 1
this.getData()
},
add(){
@ -298,15 +297,17 @@ export default {
start(row){
let data = {
id: row.id,
startTime: this.formatDate("yyyy-MM-dd hh:mm:ss",new Date()),
status: 2
startTime: util.formatDate("yyyy-MM-dd hh:mm:ss",new Date()),
status: 1
}
this.$post(this.api.expUpdate,data).then(res => {
if(res.errmessage == 'success') {
this.$post(this.api.modifyAssessment, data).then(res => {
if(res.status === 200) {
util.successMsg('启动成功!')
this.getData()
}
}).catch(res => {});
}).catch(err => {
console.log(err);
});
},
finish(row){
this.$confirm('确定要提前结束吗?', '提示', {
@ -315,15 +316,17 @@ export default {
.then(() => {
let data = {
id: row.id,
stopTime: this.formatDate("yyyy-MM-dd hh:mm:ss",new Date()),
status: 3
endTime: util.formatDate("yyyy-MM-dd hh:mm:ss",new Date()),
status: 2
}
this.$post(this.api.expUpdate,data).then(res => {
if(res.errmessage == 'success') {
this.$post(`${this.api.collectPaper}?id=${row.id}`).then(res => {
if(res.status === 200) {
util.successMsg('提前结束成功!')
this.getData()
}
}).catch(res => {})
}).catch(err => {
console.log(err);
})
})
.catch(() => {})
},
@ -332,7 +335,7 @@ export default {
type: 'warning'
})
.then(() => {
this.$post(this.api.expDelete,[row.id]).then(res => {
this.$post(this.api.deleteAssessment,[row.id]).then(res => {
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
@ -340,18 +343,15 @@ export default {
.catch(() => {});
},
delAllData() {
if(this.multipleSelection.length != ''){
let newArr = this.multipleSelection
let delList = newArr.map(item => {
return item.id
if(this.multipleSelection.length){
let ids = this.multipleSelection.map(item => {
return item.projectId
})
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
let data = delList
this.$post(this.api.expDelete,data).then(res => {
this.$post(this.api.deleteAssessment, ids).then(res => {
this.multipleSelection = [];
this.$refs.table.clearSelection()
util.successMsg('删除成功');
@ -367,11 +367,11 @@ export default {
this.multipleSelection = val;
},
onSearch(){
this.page = 1
this.pageNum = 1
this.getData()
},
handleCurrentChange(val) {
this.page = val;
this.pageNum = val;
this.getData();
},
transferTime(date,type){

@ -0,0 +1,286 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="id ? '编辑课程' : '新增课程'"></el-page-header>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<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"
:headers="headers"
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>
</el-card>
</div>
</template>
<script>
import util from '@/libs/util'
import Setting from '@/setting'
import quill from '@/components/quill'
export default {
name: 'courseAddEdit',
data() {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
schoolId: Setting.schoolId,
id: '',
isDetail: Boolean(this.$route.query.show),
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
},
methods: {
//
goBack() {
this.$router.back();
},
save() {
if (this.submiting) return false
if (!this.name) return util.warningMsg('请填写课程名称');
if (!this.classificationId) return util.warningMsg('请选择课程分类');
if (!this.coverUrl) return util.warningMsg('请上传课程封面');
this.submiting = true
let data = {
id: this.id,
classificationId: this.classificationId,
coverUrl: this.coverUrl,
description: this.description,
name: this.name,
schoolId: this.schoolId,
founderId: this.userId,
founderName: this.username,
distinguish: 1
}
if (this.id) {
this.$put(this.api.editCourse, data).then(res => {
this.submiting = false
util.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.queryGlClassification).then(res => {
this.classificationList = res.classificationList
}).catch(res => {
});
},
getData() {
this.$get(`${this.api.getCourse}/${this.id}`)
.then(res => {
let data = res.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) {
util.warningMsg('当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!');
},
uploadSuccess(res, file, fileList) {
this.coverUrl = res.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,742 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="'内容设置'"></el-page-header>
</div>
</el-card>
<!--内容设置-->
<el-card shadow="hover" class="m-b-20">
<div class="page">
<div class="relative">
<div class="p-title">内容设置</div>
<div class="btns" style="top: -10px">
<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>
<el-divider></el-divider>
<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"
:headers="headers"
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>
</el-card>
</div>
</template>
<script>
import util from '@/libs/util'
import Setting from '@/setting'
import { Loading } from 'element-ui';
import pdf from '@/components/pdf'
export default {
name: 'contentSettings',
data() {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
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 },
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.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) {
util.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) {
util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
uploadSuccess(res, file, fileList) {
this.uploading = false
this.fileId = res.filesResult.fileId
this.fileType = res.filesResult.fileType
this.fileUrl = res.filesResult.fileUrl
this.fileName = res.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 => {
util.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 util.warningMsg('请填写章节名称')
let data = {
courseId: this.id,
name: this.chapterName
}
if (this.chapterId) {
data.id = this.chapterId
this.$put(this.api.editChapter, data).then(res => {
util.successMsg('修改成功');
this.chapterVisible = false
this.getData()
})
.catch(err => {
});
} else {
this.$post(this.api.addChapter, data).then(res => {
util.successMsg('添加成功');
this.chapterVisible = false
this.getData()
})
.catch(err => {
});
}
},
sectionSubmit() {
if (!this.sectionName) return util.warningMsg('请填写小节名称')
if (this.uploading) return util.warningMsg('资源正在上传中,请稍候')
if (!this.fileUrl && !this.fileId) return util.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 => {
util.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 => {
util.successMsg('更换成功');
this.switchVisible = false
this.getData()
})
.catch(err => {
});
},
switchSubmit() {
if (this.uploading) return util.warningMsg('资源正在上传中,请稍候')
if (!this.fileUrl && !this.fileId) return util.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 => {
util.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 util.warningMsg('请填写小节名称')
let data = {
id: this.sectionId,
courseId: this.id,
chapterId: this.chapterId,
name: this.sectionName
}
this.$put(this.api.editSubsection, data).then(res => {
util.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,219 @@
<template>
<!-- 课程管理 -->
<div style="padding-top: 24px">
<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 + (current - 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="current">
</el-pagination>
</div>
</div>
</template>
<script>
import util from '@/libs/util'
export default {
name: 'courseManagement',
data() {
return {
schoolId: this.$store.state.schoolId,
keyword: '',
classificationId: '',
courseData: [],
multipleSelection: [],
classificationList: [],
current: 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.current}/${this.pageSize}`, data).then(res => {
this.courseData = res.courseList
this.totals = res.total
if (!this.courseData.length && this.totals) {
this.current--
this.getData()
}
}).catch(res => {
});
},
initData() {
this.current = 1
this.getData()
},
getClassification() {
this.$get(this.api.queryGlClassification).then(res => {
this.classificationList = res.classificationList
}).catch(res => {
});
},
changeType(type) {
this.classificationId = type
this.initData()
},
preview(row) {
this.$router.push(`/course/preview?id=${row.id}`)
},
config(row) {
this.$router.push(`/course/contentSettings?id=${row.id}`)
},
addCourse() {
this.$router.push('/course/add')
},
editCourse(row) {
this.$router.push(`/course/add?id=${row.id}`)
},
handleDelete(row) {
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', {
type: 'warning'
})
.then(() => {
this.$del(`${this.api.deleteCourse}/${row.id}`).then(res => {
util.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()
util.successMsg('删除成功');
this.initData()
}).catch(res => {
});
}).catch(() => {
});
} else {
util.errorMsg('请先选择数据 !');
}
},
handleCurrentChange(val) {
this.current = val;
this.getData();
},
switchOff(val, row, index) {
this.$put(`${this.api.enableCourse}?courseId=${row.id}&isEnable=${val}`)
.then(res => {
this.getData()
val == 1 ? util.warningMsg('该教学资源已隐藏,对学生端用户不可见') : util.successMsg('该教学资源已公开,对学生端用户可见')
})
.catch(err => {
});
}
}
}
</script>
<style lang="scss" scoped>
/deep/ .tool {
.filter {
.el-input {
min-width: 215px;
}
}
}
</style>

@ -0,0 +1,495 @@
<template>
<!-- 课程预览 -->
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="'课程预览'"></el-page-header>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<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>
</el-card>
</div>
</template>
<script>
import util from '@/libs/util'
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';
export default {
name: 'coursePreview',
data() {
return {
id: this.$route.query.id,
video: 'http://liuwanr.oss-cn-shenzhen.aliyuncs.com/mp4/20200519/1589871025648.mp4',
videoSrc: '',
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
}
},
components: { pdf },
mounted() {
this.insertScript()
this.getData()
this.getChapter()
},
methods: {
goBack() {
this.$router.back();
},
async getData() {
let res = await this.$get(`${this.api.getCourse}/${this.id}`)
this.courseName = res.course.name
this.description = res.course.description
this.coverUrl = res.course.coverUrl
},
async getChapter() {
let res = await this.$get(`${this.api.queryChaptersAndSubsections}/${this.id}`)
this.videoList = res.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.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.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,66 @@
<template>
<!-- 理论课程管理 -->
<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">
<!-- 课程管理 -->
<CourseManagement v-if="active == 'first'" />
<!-- 分类管理 -->
<SortManagement v-else />
</div>
</div>
</template>
<script>
import Setting from '@/setting';
import { mapState } from 'vuex'
import CourseManagement from "./courseManagement";
import SortManagement from "./sortManagement";
export default {
name: 'course',
components: {
CourseManagement,
SortManagement
},
data() {
return {
active: 'first', //
tabs: {
first: '课程管理',
second: '分类管理'
},
showTabs: true
}
},
computed: {
...mapState('auth', [
'routes'
])
},
methods: {
tabChange(index) {
this.active = index;
},
initTabs() {
let btnPermissions = this.routes;
let showStaff = btnPermissions.includes('课程资源管理:课程管理');
let showRole = btnPermissions.includes('课程资源管理:分类管理');
if (!showStaff || !showRole) {
this.showTabs = false;
}
!showStaff && showRole && (this.active = 'second')
}
},
mounted() {
Setting.dynamicRoute && this.initTabs()
}
}
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,166 @@
<template>
<!-- 分类管理 -->
<div>
<div class="tool">
<ul class="filter">
</ul>
<div style="margin-top: 24px">
<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>
import util from '@/libs/util'
export default {
name: 'sortManagement',
data() {
return {
classificationList: [],
multipleSelection: [],
pageNo: 1,
pageSize: 10,
isAddclass: true,
classVisible: false,
curRow: {},
className: ''
}
},
mounted() {
this.getData()
},
methods: {
getData() {
this.$get(this.api.queryGlClassification).then(res => {
this.classificationList = res.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 => {
util.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 = [];
util.successMsg('删除成功');
this.getData()
}).catch(res => {
});
}).catch(() => {
});
} else {
util.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 util.warningMsg('请填写分类名称')
let data = {
name: this.className
}
if (this.curRow.id) {
data.id = this.curRow.id
this.$put(this.api.editClassification, data).then(res => {
util.successMsg('修改成功');
this.classVisible = false
this.getData()
}).catch(res => {
});
} else {
this.$post(`${this.api.addClassification}/${this.className}?distinguish=1`).then(res => {
util.successMsg('添加成功');
this.classVisible = false
this.getData()
}).catch(res => {
});
}
}
}
}
</script>
<style lang="scss" scoped>
</style>

@ -1,229 +1,245 @@
<template>
<div class="page">
<h6 class="p-title">筛选</h6>
<div class="tool">
<ul class="filter">
<div class='page'>
<h6 class='p-title'>筛选</h6>
<div class='tool'>
<ul class='filter'>
<li>
<label>题目类型</label>
<el-radio-group v-model="subject" @change="initData">
<el-radio-group v-model='subject' @change='initData'>
<el-radio
v-for="(item,index) in subjectList"
:key="index"
:label="item.id"
>{{item.name}}</el-radio>
v-for='(item,index) in subjectList'
:key='index'
:label='item.id'
>{{ item.name }}
</el-radio>
</el-radio-group>
</li>
<li>
<el-input size="small" placeholder="请输入题干" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
<el-input size='small' placeholder='请输入题干' prefix-icon='el-icon-search' v-model='keyword'
clearable></el-input>
</li>
</ul>
<div>
<el-button type="primary" size="small" @click="getInfo" v-auth>测评设置</el-button>
<el-button type="primary" size="small" @click="addTopics" v-auth>新增题目</el-button>
<el-button type="primary" size="small" @click="showBatchUpload" v-auth>批量上传</el-button>
<el-button type="primary" size="small" @click="delAllData" v-auth>批量删除</el-button>
<el-button type='primary' size='small' @click='getInfo' v-auth>测评设置</el-button>
<el-button type='primary' size='small' @click='addTopics' v-auth>新增题目</el-button>
<el-button type='primary' size='small' @click='showBatchUpload' v-auth>批量上传</el-button>
<el-button type='primary' size='small' @click='delAllData' v-auth>批量删除</el-button>
</div>
</div>
<el-table :data="listData" ref="table" row-key="id" class="table" stripe header-align="center" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<el-table :data='listData' ref='table' row-key='id' class='table' stripe header-align='center'
@selection-change='handleSelectionChange'>
<el-table-column type='selection' width='55' align='center' :reserve-selection='true'></el-table-column>
<el-table-column type='index' width='100' label='序号' align='center'>
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
slot-scope='scope'
>{{ scope.$index + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="questionStem" label="题干" align="center"></el-table-column>
<el-table-column prop="questionTypeName" label="题型" align="center"></el-table-column>
<el-table-column prop="modifyTime" label="时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<el-table-column prop='questionStem' label='题干' align='center'></el-table-column>
<el-table-column prop='questionType' label='题型' align='center'>
<template slot-scope="scope">
<template v-if="scope.row.isEnable">
<el-button type="text" @click="showQues(scope.row)" v-auth>查看</el-button>
<span>{{questionType[scope.row.questionType]}}</span>
</template>
</el-table-column>
<el-table-column prop='updateTime' label='时间' align='center'></el-table-column>
<el-table-column label='操作' align='center'>
<template slot-scope='scope'>
<template v-if='scope.row.isEnable'>
<el-button type='text' @click='showQues(scope.row)' v-auth>查看</el-button>
</template>
<template v-else>
<el-button type="text" @click="editQues(scope.row)" v-auth>修改</el-button>
<el-button type='text' @click='editQues(scope.row)' v-auth>修改</el-button>
</template>
<el-switch
v-model="scope.row.isEnable"
v-model='scope.row.isEnable'
:active-text="scope.row.isEnable ? '关闭' : '启用'"
:active-value="1"
:inactive-value="0"
style="margin: 0 10px 0 5px"
@change="switchQues($event,scope.row,scope.$index)"
:active-value='1'
:inactive-value='0'
style='margin: 0 10px 0 5px'
@change='switchQues($event,scope.row,scope.$index)'
v-auth="'evaluation:禁用'"
></el-switch>
<el-button type="text" @click="delData(scope.row)" v-auth>删除</el-button>
<el-button type='text' @click='delData(scope.row)' v-auth>删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background @current-change="handleCurrentChange" :current-page="page" :page-size="pageSize" layout="total,prev, pager, next" :total="total"></el-pagination>
<div class='pagination'>
<el-pagination background @current-change='handleCurrentChange' :current-page='page' :page-size='pageSize'
layout='total,prev, pager, next' :total='total'></el-pagination>
</div>
<el-dialog title="测评设置" :visible.sync="SetEvaluation" width="30%" :close-on-click-modal="false">
<div style="margin-bottom: 15px;">
<span class="radio">题目选择</span>
<el-radio v-model="info.evaluationType" label="1">随机</el-radio>
<el-radio v-model="info.evaluationType" label="0">自定义</el-radio>
<el-dialog title='测评设置' :visible.sync='SetEvaluation' width='30%' :close-on-click-modal='false'>
<div style='margin-bottom: 15px;'>
<span class='radio'>题目选择</span>
<el-radio v-model='info.evaluationType' label='1'>随机</el-radio>
<el-radio v-model='info.evaluationType' label='0'>自定义</el-radio>
</div>
<!-- 随机 -->
<el-card shadow="hover" class="card_m" v-show="info.evaluationType==1">
<div class="input flex_around">
<el-card shadow='hover' class='card_m' v-show='info.evaluationType==1'>
<div class='input flex_around'>
<span>测评题目总数</span>
<el-input placeholder="请输入题目数量" type="number" v-model="info.questionNum"></el-input>
<el-input placeholder='请输入题目数量' type='number' v-model='info.questionNum'></el-input>
<span>(总数{{ info.totalQuestionNum }})</span>
</div>
</el-card>
<!-- 自定义 -->
<el-card shadow="hover" class="card_m" v-show="info.evaluationType==0">
<div class="input">
<div class="check-wrap" :class="{checked: info.isSingleEnable}">
<el-checkbox v-model="info.isSingleEnable">单选题</el-checkbox>
<el-input placeholder="请输入题目数量" type="number" v-model="info.singleNum" :disabled="!info.isSingleEnable"></el-input>
<el-card shadow='hover' class='card_m' v-show='info.evaluationType==0'>
<div class='input'>
<div class='check-wrap' :class='{checked: info.isSingleEnable}'>
<el-checkbox v-model='info.isSingleEnable'>单选题</el-checkbox>
<el-input placeholder='请输入题目数量' type='number' v-model='info.singleNum'
:disabled='!info.isSingleEnable'></el-input>
<span>(总数{{ info.totalSingleNum }})</span>
</div>
<div class="check-wrap" :class="{checked: info.isMultipleEnable}">
<el-checkbox v-model="info.isMultipleEnable">多选题</el-checkbox>
<el-input placeholder="请输入题目数量" type="number" v-model="info.multipleNum" :disabled="!info.isMultipleEnable"></el-input>
<div class='check-wrap' :class='{checked: info.isMultipleEnable}'>
<el-checkbox v-model='info.isMultipleEnable'>多选题</el-checkbox>
<el-input placeholder='请输入题目数量' type='number' v-model='info.multipleNum'
:disabled='!info.isMultipleEnable'></el-input>
<span>(总数{{ info.totalMultipleNum }})</span>
</div>
<div class="check-wrap" :class="{checked: info.isJudgmentEnable}">
<el-checkbox v-model="info.isJudgmentEnable">判断题</el-checkbox>
<el-input placeholder="请输入题目数量" type="number" v-model="info.judgmentNum" :disabled="!info.isJudgmentEnable"></el-input>
<div class='check-wrap' :class='{checked: info.isJudgmentEnable}'>
<el-checkbox v-model='info.isJudgmentEnable'>判断题</el-checkbox>
<el-input placeholder='请输入题目数量' type='number' v-model='info.judgmentNum'
:disabled='!info.isJudgmentEnable'></el-input>
<span>(总数{{ info.totalJudgmentNum }})</span>
</div>
</div>
</el-card>
<div class="jobNumber">
<div class="input">
<span style="margin:0px 15px 0px 35px">测评时长</span>
<el-input placeholder="请输入时间" type="number" v-model="info.duration"></el-input>
<span style="margin-left:15px">分钟</span>
<div class='jobNumber'>
<div class='input'>
<span style='margin:0px 15px 0px 35px'>测评时长</span>
<el-input placeholder='请输入时间' type='number' v-model='info.duration'></el-input>
<span style='margin-left:15px'>分钟</span>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="SetEvaluation = false"> </el-button>
<el-button size="small" type="primary" @click="submitSetEva"> </el-button>
<span slot='footer' class='dialog-footer'>
<el-button size='small' @click='SetEvaluation = false'> </el-button>
<el-button size='small' type='primary' @click='submitSetEva'> </el-button>
</span>
</el-dialog>
<el-dialog :title="topicsTitle" :visible.sync="NewTopics" width="30%" @close="closeTopics" :close-on-click-modal="false">
<el-dialog :title='topicsTitle' :visible.sync='NewTopics' width='30%' @close='closeTopics'
:close-on-click-modal='false'>
<el-form
:model="topicForm"
:rules="rules"
:disabled="isShowTopics"
ref="topicForm"
label-width="70px"
class="demo-topicForm"
:model='topicForm'
:rules='rules'
:disabled='isShowTopics'
ref='topicForm'
label-width='70px'
class='demo-topicForm'
>
<el-form-item label="题型" prop="questionType">
<el-radio-group v-model="topicForm.questionType" @change="questionTypeChange">
<el-radio label="单选题"></el-radio>
<el-radio label="多选题"></el-radio>
<el-radio label="判断题"></el-radio>
<el-form-item label='题型' prop='questionType'>
<el-radio-group v-model='topicForm.questionType' @change='questionTypeChange'>
<el-radio label='单选题'></el-radio>
<el-radio label='多选题'></el-radio>
<el-radio label='判断题'></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="题干" prop="questionStem">
<el-input type="textarea" v-model="topicForm.questionStem"></el-input>
<el-form-item label='题干' prop='questionStem'>
<el-input type='textarea' v-model='topicForm.questionStem'></el-input>
</el-form-item>
<el-form-item label="选项" prop="optionA">
<div class="input flex_around bt">
<el-form-item label='选项' prop='optionA'>
<div class='input flex_around bt'>
<span>A</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionA"></el-input>
<el-checkbox v-model="topicForm.aisTrue">设为正确答案</el-checkbox>
<el-input placeholder='请输入题目' v-model='topicForm.optionA'></el-input>
<el-checkbox v-model='topicForm.aisTrue'>设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<div class='input flex_around bt'>
<span>B</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionB"></el-input>
<el-checkbox v-model="topicForm.bisTrue">设为正确答案</el-checkbox>
<el-input placeholder='请输入题目' v-model='topicForm.optionB'></el-input>
<el-checkbox v-model='topicForm.bisTrue'>设为正确答案</el-checkbox>
</div>
<template v-if="topicForm.questionType != '判断题'">
<div class="input flex_around bt">
<div class='input flex_around bt'>
<span>C</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionC"></el-input>
<el-checkbox v-model="topicForm.cisTrue">设为正确答案</el-checkbox>
<el-input placeholder='请输入题目' v-model='topicForm.optionC'></el-input>
<el-checkbox v-model='topicForm.cisTrue'>设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<div class='input flex_around bt'>
<span>D</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionD"></el-input>
<el-checkbox v-model="topicForm.disTrue">设为正确答案</el-checkbox>
<el-input placeholder='请输入题目' v-model='topicForm.optionD'></el-input>
<el-checkbox v-model='topicForm.disTrue'>设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<div class='input flex_around bt'>
<span>E</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionE"></el-input>
<el-checkbox v-model="topicForm.eisTrue">设为正确答案</el-checkbox>
<el-input placeholder='请输入题目' v-model='topicForm.optionE'></el-input>
<el-checkbox v-model='topicForm.eisTrue'>设为正确答案</el-checkbox>
</div>
<div class="input flex_around">
<div class='input flex_around'>
<span>F</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionF"></el-input>
<el-checkbox v-model="topicForm.fisTrue">设为正确答案</el-checkbox>
<el-input placeholder='请输入题目' v-model='topicForm.optionF'></el-input>
<el-checkbox v-model='topicForm.fisTrue'>设为正确答案</el-checkbox>
</div>
</template>
</el-form-item>
<el-form-item label="答案解析" prop="answerAnalysis">
<el-input type="textarea" v-model="topicForm.answerAnalysis"></el-input>
<el-form-item label='答案解析' prop='answerAnalysis'>
<el-input type='textarea' v-model='topicForm.answerAnalysis'></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer" v-show="!isShowTopics">
<el-button size="small" @click="NewTopics = false"> </el-button>
<el-button size="small" type="primary" @click="saveTopics"> </el-button>
<div slot='footer' class='dialog-footer' v-show='!isShowTopics'>
<el-button size='small' @click='NewTopics = false'> </el-button>
<el-button size='small' type='primary' @click='saveTopics'> </el-button>
</div>
</el-dialog>
<el-dialog title="批量上传" :visible.sync="BatchUpload" width="30%" @close="closeUpload" :close-on-click-modal="false">
<el-card shadow="hover" class="card_m" v-show="this.label=1">
<div class="Upload">
<div class="bt" @click="downloadTem">
<el-link :underline="false">
<el-dialog title='批量上传' :visible.sync='BatchUpload' width='30%' @close='closeUpload'
:close-on-click-modal='false'>
<el-card shadow='hover' class='card_m' v-show='this.label=1'>
<div class='Upload'>
<div class='bt' @click='downloadTem'>
<el-link :underline='false'>
1.请下载模板
<i class="el-icon-download"></i>
<i class='el-icon-download'></i>
</el-link>
</div>
<div>
<el-upload
accept=".xls,.xlsx"
:on-remove="handleDataRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.import"
:file-list="uploadDataList"
name="file"
accept='.xls,.xlsx'
:on-remove='handleDataRemove'
:on-error='uploadError'
:on-success='uploadSuccess'
:before-remove='beforeRemove'
:limit='1'
:on-exceed='handleExceed'
:action='questionsImport'
:file-list='uploadDataList'
name='file'
>
<el-link :underline="false">
<el-link :underline='false'>
2.请点击批量导入
<i class="el-icon-upload"></i>
<i class='el-icon-upload'></i>
</el-link>
</el-upload>
<el-link v-if="uploadFaild" type="primary" @click="showFaild">部分数据导入失败查看失败原因</el-link>
<el-link v-if='uploadFaild' type='primary' @click='showFaild'>部分数据导入失败查看失败原因</el-link>
</div>
</div>
</el-card>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="BatchUpload = false"> </el-button>
<el-button size="small" type="primary" @click="uploadSure"> </el-button>
<span slot='footer' class='dialog-footer'>
<el-button size='small' @click='BatchUpload = false'> </el-button>
<el-button size='small' type='primary' @click='uploadSure'> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import util from '@/libs/util'
import Setting from '@/setting'
import { mapState, mapActions } from 'vuex';
import util from '@/libs/util';
import Setting from '@/setting';
export default {
data() {
return {
questionsImport: this.api.questionsImport,
topicForm: {
answer: '',
questionType : '单选题',
questionStem : '',
questionType: '单选题',
questionStem: '',
optionA: '',
optionB: '',
optionC: '',
@ -240,7 +256,7 @@ export default {
},
rules: {
questionType: [{ required: true, message: '请选择题型', trigger: 'change' }],
questionStem: [{ required: true, message: '请填写题干', trigger: 'blur' }],
questionStem: [{ required: true, message: '请填写题干', trigger: 'blur' }]
// optionA: [{ required: true, message: '', trigger: 'change' }],
// optionB: [{ required: true, message: '', trigger: 'change' }]
},
@ -287,44 +303,50 @@ export default {
uploadDataList: [],
searchTimer: null,
uploadFaild: false,
token: ''
exportCode: ''
};
},
mounted() {
this.getData()
this.getData();
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData()
},500)
this.initData();
}, 500);
}
},
methods: {
getData() {
this.$get(this.api.list, {
page: this.page,
size: this.pageSize,
this.$post(this.api.questionsList, {
pageNum: this.page,
pageSize: this.pageSize,
questionStem: util.encodeStr(this.keyword),
questionType: this.subject
})
.then(res => {
this.listData = res.page.list
this.total = res.page.totalCount
if(res.status === 200) {
this.listData = res.page.records;
this.total = res.page.total;
} else {
util.errorMsg(res.message);
}
})
.catch(err => {})
.catch(err => {
console.log(err);
});
},
initData() {
this.page = 1
this.getData()
this.$refs.table.clearSelection()
this.page = 1;
this.getData();
this.$refs.table.clearSelection();
},
resetForm() {
this.topicForm = {
answer: '',
questionType : '',
questionStem : '',
questionType: '',
questionStem: '',
optionA: '',
optionB: '',
optionC: '',
@ -338,211 +360,233 @@ export default {
eisTrue: false,
fisTrue: false,
answerAnalysis: ''
}
};
this.$nextTick(() => {
this.$refs.topicForm.clearValidate()
})
this.$refs.topicForm.clearValidate();
});
},
handleCurrentChange(val) {
this.page = val
this.getData()
this.page = val;
this.getData();
},
addTopics() {
this.topicForm.id = ''
this.topicsTitle = '新增题目'
this.NewTopics = true
this.topicForm.id = '';
this.topicsTitle = '新增题目';
this.NewTopics = true;
},
getDetail(id) {
this.$get(this.api.infoId + id).then(res => {
this.topicForm = res.questions
this.topicForm.id = id
this.topicForm.questionType = this.questionType[this.topicForm.questionType]
this.NewTopics = true
}).catch(res => {});
this.$get(`${this.api.questionsDetail}`, {id}).then(res => {
if (res.status === 200) {
this.topicForm = res.questions;
this.topicForm.id = id;
this.topicForm.questionType = res.questions.questionTypeName;
this.NewTopics = true;
} else {
util.errorMsg(res.message);
}
}).catch(err => {
console.log(err);
});
},
editQues(row) {
this.topicsTitle = '编辑题目'
this.getDetail(row.id)
this.topicsTitle = '编辑题目';
this.getDetail(row.id);
},
showQues(row) {
this.topicsTitle = '查看题目'
this.isShowTopics = true
this.getDetail(row.id)
this.topicsTitle = '查看题目';
this.isShowTopics = true;
this.getDetail(row.id);
},
closeTopics() {
this.isShowTopics = false
this.resetForm()
this.isShowTopics = false;
this.resetForm();
},
switchQues(val, row, index) {
this.$put(this.api.isenable, [row.id])
this.$post(`${this.api.questionsIsDisable}?id=${row.id}`)
.then(res => {
if (res.status == 400) {
util.errorMsg(res.errmessage)
row.isEnable = row.isEnable == 1 ? 0 : 1
util.errorMsg(res.message);
row.isEnable = row.isEnable == 1 ? 0 : 1;
}
})
.catch(err => {});
.catch(err => {
});
},
delData(row) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(this.api.delete,[row.id]).then(res => {
this.$post(`${this.api.questionsDelete}?ids=${row.id}`).then(res => {
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
this.getData();
}).catch(res => {
});
})
.catch(() => {});
.catch(() => {
});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllData() {
if(this.multipleSelection.length != ''){
let newArr = this.multipleSelection
let delList = newArr.map(item => {
if(this.multipleSelection.length){
let ids = this.multipleSelection.map(item => {
return item.id
})
});
let strIds = ids.toString();
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
let data = delList
this.$post(this.api.delete,data).then(res => {
this.$post(`${this.api.questionsDelete}?ids=${strIds}`).then(res => {
this.multipleSelection = [];
this.$refs.table.clearSelection()
this.$refs.table.clearSelection();
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
this.getData();
}).catch(err => {
console.log(err);
});
})
.catch(() => {});
.catch(() => {
});
} else {
util.errorMsg('请先选择题目 !');
}
},
downloadTem() {
location.href = this.api.questionsTemplate
location.href = this.api.questionsTemplate;
},
getInfo() {
this.$get(this.api.info).then(res => {
this.info = res.data
this.info.evaluationType = this.info.evaluationType.toString()
this.info.isSingleEnable = Boolean(this.info.isSingleEnable)
this.info.isMultipleEnable = Boolean(this.info.isMultipleEnable)
this.info.isJudgmentEnable = Boolean(this.info.isJudgmentEnable)
this.SetEvaluation = true
}).catch(res => {});
this.$get(this.api.questionsInfo).then(res => {
this.info = res.data;
this.info.evaluationType = this.info.evaluationType.toString();
this.info.isSingleEnable = Boolean(this.info.isSingleEnable);
this.info.isMultipleEnable = Boolean(this.info.isMultipleEnable);
this.info.isJudgmentEnable = Boolean(this.info.isJudgmentEnable);
this.SetEvaluation = true;
}).catch(res => {
});
},
questionTypeChange() {
for (let i in this.topicForm) {
if(i.includes('isTrue')) this.topicForm[i] = false
if (i.includes('isTrue')) this.topicForm[i] = false;
}
},
submitSetEva() {
let info = this.info
let info = this.info;
if (info.evaluationType == 0) {
let allEmpty = true
if(!info.isSingleEnable && !info.isMultipleEnable && !info.isJudgmentEnable) return this.$message.warning('请至少选择一种题型')
if(info.isSingleEnable == 1 && info.singleNum != 0) allEmpty = false
if(info.isMultipleEnable == 1 && info.multipleNum != 0) allEmpty = false
if(info.isJudgmentEnable == 1 && info.judgmentNum != 0) allEmpty = false
if(allEmpty) return this.$message.warning('请至少选中一种类型,并数量大于0')
if(info.isSingleEnable == 1 && info.singleNum > info.totalSingleNum) return this.$message.warning('单选题大于总数,请重新输入')
if(info.isMultipleEnable == 1 && info.multipleNum > info.totalMultipleNum) return this.$message.warning('多选题大于总数,请重新输入')
if(info.isJudgmentEnable == 1 && info.judgmentNum > info.totalJudgmentNum) return this.$message.warning('判断题大于总数,请重新输入')
let allEmpty = true;
if (!info.isSingleEnable && !info.isMultipleEnable && !info.isJudgmentEnable) return util.warningMsg('请至少选择一种题型');
if (info.isSingleEnable == 1 && info.singleNum != 0) allEmpty = false;
if (info.isMultipleEnable == 1 && info.multipleNum != 0) allEmpty = false;
if (info.isJudgmentEnable == 1 && info.judgmentNum != 0) allEmpty = false;
if (allEmpty) return util.warningMsg('请至少选中一种类型,并数量大于0');
if (info.isSingleEnable == 1 && info.singleNum > info.totalSingleNum) return util.warningMsg('单选题大于总数,请重新输入');
if (info.isMultipleEnable == 1 && info.multipleNum > info.totalMultipleNum) return util.warningMsg('多选题大于总数,请重新输入');
if (info.isJudgmentEnable == 1 && info.judgmentNum > info.totalJudgmentNum) return util.warningMsg('判断题大于总数,请重新输入');
} else {
if(info.questionNum === '') return this.$message.warning('请输入测评题目总数')
if(info.questionNum == 0) return this.$message.warning('测评题目总数不得为0')
if (info.questionNum === '') return util.warningMsg('请输入测评题目总数');
if (info.questionNum == 0) return util.warningMsg('测评题目总数不得为0');
}
if(info.duration === '') return this.$message.warning('请输入测评时长')
if(info.duration == 0) return this.$message.warning('测评时长不得为0')
this.info.isSingleEnable = Number(this.info.isSingleEnable)
this.info.isMultipleEnable = Number(this.info.isMultipleEnable)
this.info.isJudgmentEnable = Number(this.info.isJudgmentEnable)
this.$put(this.api.update,this.info).then(res => {
if(res.errmessage == 'success'){
if (info.duration === '') return util.warningMsg('请输入测评时长');
if (info.duration == 0) return util.warningMsg('测评时长不得为0');
this.info.isSingleEnable = Number(this.info.isSingleEnable);
this.info.isMultipleEnable = Number(this.info.isMultipleEnable);
this.info.isJudgmentEnable = Number(this.info.isJudgmentEnable);
this.$post(this.api.questionsUpdateRules, this.info).then(res => {
if (res.status === 200) {
util.successMsg('提交成功!');
this.SetEvaluation = false
this.SetEvaluation = false;
} else {
util.errorMsg(res.message);
}
}).catch(res => {});
}).catch(err => {
console.log(err);
});
},
saveTopics() {
this.$refs.topicForm.validate((valid) => {
if (valid) {
let topicForm = this.topicForm
let optionCount = 0
let answer = ''
let isInvalidAnswer = false
let topicForm = this.topicForm;
let optionCount = 0;
let answer = '';
let isInvalidAnswer = false;
for (let n in topicForm) {
if (n.includes('option')) {
topicForm[n] != '' && ++optionCount
topicForm[n] != '' && ++optionCount;
}
if (n.includes('isTrue') && topicForm[n]) {
let curOpt = n.replace('isTrue','')
answer += curOpt
if(!topicForm[`option${curOpt.toUpperCase()}`].length) isInvalidAnswer = true
let curOpt = n.replace('isTrue', '');
answer += curOpt;
if (!topicForm[`option${curOpt.toUpperCase()}`].length) isInvalidAnswer = true;
}
}
if(optionCount < 2) return this.$message.warning('请至少添加两个选项!');
if(!answer) return this.$message.warning('请设置正确答案!');
if(topicForm.questionType != '多选题' && answer.length > 1) return this.$message.warning('单选题、判断题只能设置一个正确答案!');
if(isInvalidAnswer) return this.$message.warning('正确答案选项为空,请重新设置!');
this.topicForm.questionType = this.questionType.indexOf(this.topicForm.questionType)
this.topicForm.answer = answer.toUpperCase()
if (optionCount < 2) return util.warningMsg('请至少添加两个选项!');
if (!answer) return util.warningMsg('请设置正确答案!');
if (topicForm.questionType != '多选题' && answer.length > 1) return util.warningMsg('单选题、判断题只能设置一个正确答案!');
if (isInvalidAnswer) return util.warningMsg('正确答案选项为空,请重新设置!');
this.topicForm.questionType = this.questionType.indexOf(this.topicForm.questionType);
this.topicForm.answer = answer.toUpperCase();
if (this.topicForm.id) {
this.$put(this.api.questionsUpdate,this.topicForm).then(res => {
if(res.errmessage == 'success') {
this.$post(this.api.questionsUpdate, this.topicForm).then(res => {
if (res.status === 200) {
util.successMsg('提交成功!');
this.NewTopics = false
this.getData()
this.NewTopics = false;
this.getData();
} else {
util.errorMsg(res.message);
}
}).catch(res => {});
}).catch(err => {
console.log(err);
});
} else {
this.$post(this.api.save,this.topicForm).then(res => {
if(res.errmessage == 'success') {
this.$post(this.api.questionsSave, this.topicForm).then(res => {
if (res.status === 200) {
util.successMsg('提交成功!');
this.NewTopics = false
this.getData()
this.NewTopics = false;
this.getData();
} else {
util.errorMsg(res.message);
}
}).catch(res => {});
}).catch(err => {
console.log(err);
});
}
} else {
return false;
}
})
});
},
showBatchUpload() {
this.BatchUpload = true
this.BatchUpload = true;
},
handleExceed(files, fileList) {
this.$message.warning(
util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
uploadSuccess(res, file, fileList) {
this.uploadFaild = false
if(res.data.token){
this.token = res.data.token
this.uploadFaild = true
this.uploadFaild = false;
console.log(JSON.stringify(res));
let {message, status, data } = res;
if (status === 200) {
util.successMsg(`上传成功:${data.successNum},上传失败:${data.failureNum}`);
if (data.failureNum !== "0") {
this.exportCode = data.exportCode;
this.uploadFaild = true;
}
}
},
showFaild() {
location.href = `${this.api.export_failure}?token=${this.token}`
location.href = `${this.api.questionsExportFailure}?exportCode=${this.exportCode}`;
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
message: '上传出错,请重试!',
type: 'error',
center: true
});
},
@ -550,80 +594,95 @@ export default {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
this.uploadList = fileList
this.uploadList = fileList;
},
handleDataRemove(file, fileList) {
this.uploadList = fileList
this.uploadFaild = false
this.uploadList = fileList;
this.uploadFaild = false;
},
uploadSure() {
this.BatchUpload = false
this.page = 1
this.keyword = ''
this.getData()
this.BatchUpload = false;
this.page = 1;
this.keyword = '';
this.getData();
},
closeUpload() {
this.uploadFaild = false
this.uploadList = []
this.uploadDataList = []
this.uploadFaild = false;
this.uploadList = [];
this.uploadDataList = [];
}
}
};
</script>
<style lang="scss" scoped>
<style lang='scss' scoped>
::v-deep .el-checkbox-group {
font-size: 2px;
}
.Upload {
text-align: center;
}
.bt {
margin-bottom: 15px;
}
.bt_one {
margin-left: 10px;
}
.Bank_m {
margin-bottom: 20px;
}
.Bank img {
width: 15px;
height: 15px;
margin-right: 10px;
}
.Bank span {
font-size: 16px;
}
.jobNumber {
margin: 10px 0;
}
.flex_around {
display: flex;
justify-content: space-around;
align-items: center;
}
.card_m {
margin: 10px 0 20px 0;
}
.input ::v-deep .el-input {
width: 50%;
}
.radio {
margin: 0 15px 0 30px;
font-weight: 600;
}
.mag {
margin-right: 20px;
}
.check-wrap {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.check-wrap .el-input {
margin: 0 15px;
}
.check-wrap.checked {
color: #9076FF;
}

@ -0,0 +1,397 @@
<template>
<div>
<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' style='padding-top: 24px; margin-top: 24px'>
<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 util from '@/libs/util'
export default {
name: 'columnManage',
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'
}
};
},
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.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 => {
util.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.columnReorder, data).then(res => {
util.successMsg('保存成功');
this.sorting = false;
this.getData();
}).catch(res => {
});
},
columnSubmit() {
if (!this.columnName) return util.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 => {
util.warningMsg('修改成功');
this.columnVisible = false;
this.getData();
}).catch(res => {
});
} else {
this.$post(this.api.addColumn, data).then(res => {
util.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 util.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 => {
util.successMsg('修改成功');
this.typeVisible = false;
this.getData();
}).catch(res => {
});
} else {
data.parentId = this.curRow.id;
this.$post(this.api.addColumn, data).then(res => {
util.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,267 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="'新增文章'"></el-page-header>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<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"
:headers="headers"
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>
</el-card>
</div>
</template>
<script>
import quill from '@/components/quill'
import util from '@/libs/util'
import Setting from '@/setting'
export default {
name: 'addArticle',
data() {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
columnId: this.$route.query.columnId,
sort: this.$route.query.sort,
id: '',
coverUrl: '',
uploadList: [],
uploadDataList: [],
author: '',
date: '',
title: '',
content: '',
submiting: false,
uploading: false
};
},
components: {
quill
},
mounted() {
this.id = this.$route.query.id
this.id && this.getData()
},
methods: {
//
goBack() {
this.$router.back();
},
getData() {
this.$get(`${this.api.getArticle}/${this.id}`)
.then(res => {
let data = res.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 util.warningMsg('请上传封面图')
if(!this.author) return util.warningMsg('请填写作者')
if(!this.date) return util.warningMsg('请选择日期')
if(!this.title) return util.warningMsg('请填写文章标题')
if(!this.content) return util.warningMsg('请填写文章内容')
if(this.uploading) return util.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
util.successMsg('修改成功');
this.back()
})
.catch(err => {
this.submiting = false
})
}else{
this.$post(this.api.addArticle, data).then(res => {
this.submiting = false
util.successMsg('创建成功');
this.back()
})
.catch(err => {
this.submiting = false
})
}
},
handleCurrentChange(val) {
this.currPage = val;
},
handleExceed(files, fileList) {
util.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.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,197 @@
<template>
<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" style='padding-top: 24px'>
<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>
</template>
<script>
import util from '@/libs/util'
export default {
data() {
return {
activeName: 'first',
tabs: {
first: '栏目内容管理'
},
listData: [],
multipleSelection: [],
pageNo: 1,
pageSize: 10,
totals: 0,
};
},
props: {
columnId: ""
},
watch: {
columnId(){
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.articleList
this.totals = res.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(`/information/addarticle?columnId=${this.columnId}&sort=${this.listData.length+1}`)
},
editArticle(scope){
this.$router.push(`/information/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 => {
util.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()
util.successMsg('删除成功');
this.getData()
}).catch(res => {})
})
.catch(() => {});
}else{
util.errorMsg('请先选择数据 !')
}
},
switchOff(val,row,index) {
this.$put(`${this.api.enableArticle}/${row.id}/${val}`)
.then(res => {
val == 1 ? util.errorMsg('该文章已隐藏,对学生端用户不可见') : util.successMsg('该文章已发布,对学生端用户可见')
})
.catch(err => {})
},
sortSubmit(){
if(this.listData.length){
if(this.listData.find(n => n.sort < 1)) return util.errorMsg('排序值最小为1')
let data = {articleList: this.listData}
this.$post(this.api.articleSort, data).then(res => {
util.successMsg('保存成功')
this.getContent(this.columnId)
})
.catch(err => {})
}else{
util.errorMsg('数据为空')
}
}
}
};
</script>
<style lang="scss" scoped>
.btn-wrap{
text-align: right;
}
.sort-input{
/deep/.el-input__inner{
padding: 0 0 0 10px;
}
}
.sort-input+span{
display: none;
}
.off+span{
display: none;
}
</style>

@ -0,0 +1,102 @@
<template>
<!-- 内容管理 -->
<div>
<el-row :gutter="20">
<el-col :span="3">
<div class="menu-con">
<el-menu
ref="columnMenu"
unique-opened
text-color="#303133"
:default-active="activeName"
@select="handleSelect"
>
<template v-for="item in menuList">
<template v-if="item.secondColumn && item.secondColumn.length">
<el-submenu :index="item.id">
<template slot="title">
<span>{{ item.name }}</span>
</template>
<el-menu-item v-for="item2 in item.secondColumn" :index="item2.id">{{ item2.name }}</el-menu-item>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="item.id">{{ item.name }}</el-menu-item>
</template>
</template>
</el-menu>
</div>
</el-col>
<el-col :span="21">
<ContentList v-show="menuList.length" :columnId="columnId" />
</el-col>
</el-row>
</div>
</template>
<script>
import ContentList from './contentList'
import { mapActions } from 'vuex'
export default {
name: 'contentManage',
components: {
ContentList
},
data() {
return {
menuList: [],
activeName: this.$store.state.info.columnId,
columnId: ""
}
},
mounted() {
this.getMenuData();
},
methods: {
...mapActions('info', [
'setColumnId'
]),
getMenuData() {
this.$get(this.api.queryAllColumns, { page: 1, size: 10000 }).then(res => {
this.menuList = res.columnTree;
if (this.menuList.length) {
if (this.menuList[0].secondColumn && this.menuList[0].secondColumn.length) {
this.columnId = this.menuList[0].secondColumn[0].id;
} else {
this.columnId = this.menuList[0].id;
}
if (!this.$store.state.info.columnId) {
this.setColumnId(this.columnId);
} else {
this.columnId = this.$store.state.info.columnId;
}
}
}).catch(err => {
});
},
handleSelect(key, keyPath) {
this.columnId = key;
this.setColumnId(key);
}
}
};
</script>
<style lang="scss" scoped>
.menu-con {
height: calc(100vh - 250px);
border-right: solid 1px #e6e6e6;
background-color: #F2F6FC;
overflow: hidden;
.el-menu{
background-color: transparent;
.el-submenu{
background-color: transparent;
}
.el-menu-item.is-active{
color: #ffffff;
background-color: #9278FF;
}
}
}
</style>

@ -0,0 +1,64 @@
<template>
<!-- 资讯管理 -->
<div class="page">
<el-tabs v-model="tabsName" tab-position="left" @tab-click="handleClick">
<el-tab-pane name="1">
<span slot="label"><i class="el-icon-collection-tag"></i> 栏目管理</span>
<columnManage v-if="tabsName === '1'" />
</el-tab-pane>
<el-tab-pane name="2">
<span slot="label"><i class="el-icon-document"></i> 内容管理</span>
<ContentManage v-if="tabsName === '2'" />
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import ColumnManage from './columnManage'
import ContentManage from './contentManage'
import { mapActions } from 'vuex'
export default {
components: {
ColumnManage,
ContentManage
},
data() {
return {
tabsName: this.$store.state.info.tabsName,
}
},
methods: {
...mapActions('info', [
'setTabsName'
]),
handleClick(tab, event) {
this.setTabsName(tab.name)
}
},
mounted() {
}
}
</script>
<style lang="scss" scoped>
.page .el-tabs--left {
height: calc(100vh - 250px);
/deep/ .el-tabs__item {
height: 60px;
line-height: 60px;
}
/deep/ el-tabs__active-bar {
height: 60px;
transform: translateY(60px);
}
.el-menu {
border-right: 0;
}
}
</style>

@ -0,0 +1,472 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="'创建赛事'"></el-page-header>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<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'
:headers="headers"
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高度140JPG/PNG/GIF3MB以内</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'
:headers="headers"
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高度300JPG/PNG/GIF3MB以内</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>
</el-card>
</div>
</template>
<script>
import util from '@/libs/util'
import Setting from '@/setting'
import quill from '@/components/quill';
export default {
name: 'add',
data() {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
schoolId: Setting.schoolId,
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
},
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: {
//
goBack() {
this.$router.back();
},
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 util.warningMsg('请填写竞赛名称');
if (status == 0) {
if (!this.sponsor) return util.warningMsg('请填写主办方');
if (!this.signUpStartTime) return util.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 util.warningMsg('报名时间不能早于当前时间');
if (!this.playStartTime && status == 0) return util.warningMsg('请选择竞赛时间');
if (playStartTime && playStartTime < signUpEndTime) return util.warningMsg('竞赛时间不能早于报名结束时间');
if (!this.description && status == 0) return util.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;
util.successMsg('修改成功');
this.$router.back();
})
.catch(err => {
this.submiting = false;
});
} else {
this.$post(this.api.addContest, data).then(res => {
this.submiting = false;
util.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 {
util.errorMsg('查询失败');
}
})
.catch(err => {
});
},
handleExceed(files, fileList) {
util.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.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.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,279 @@
<template>
<div class="page">
<h6 class="p-title">筛选</h6>
<div class="tool mul">
<ul class="filter">
<li>
<label>创建时间</label>
<div class="single-choice">
<dl>
<dd>
<el-radio-group size="small" v-model="form.month" @change="changeType">
<el-radio v-for="(item,index) in dateList" :key="index" :label="item.id" border>{{item.name}}</el-radio>
</el-radio-group>
</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>
<div>
<el-button type="primary" size="small" round @click="add" v-auth>创建竞赛</el-button>
</div>
</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>
</template>
<script>
import util from '@/libs/util'
export default {
name: 'match',
data() {
return {
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: ['已发布','未发布']
};
},
watch: {
'form.month': function(val){
if(val){
let unit = 24 * 60 * 60 * 1000
this.date = [util.formatDate('yyyy-MM-dd',new Date(new Date().getTime() - unit * 30 * val)),util.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.contestList
this.totals = res.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('add')
},
manage(row){
this.$router.push(`manage?id=${row.id}`)
},
changeType() {
this.$refs.table.clearSelection()
this.initData();
},
delData(row) {
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', {
type: 'warning'
})
.then(() => {
this.$del(`${this.api.deleteContest}/${row.id}`).then(res => {
util.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()
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
}else{
util.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 ? util.warningMsg('该赛事信息已隐藏对学生端用户不可见') : util.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,61 @@
<template>
<!-- 赛事管理 -->
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="'赛事管理'"></el-page-header>
</div>
</el-card>
<div class="page" style="margin-bottom: 24px">
<div class="tabs">
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a>
</div>
<!-- 大赛详情 -->
<MatchDetail v-if="active == 'first'" />
<!-- 竞赛进展 -->
<MatchProgress v-else-if="active == 'second'" />
<!-- 报名人员 -->
<MatchSignup v-else />
</div>
</div>
</template>
<script>
import MatchDetail from './matchDetail'
import MatchProgress from './matchProgress'
import MatchSignup from './matchSignup'
export default {
name: 'matchManage',
data() {
return {
active: 'first',
tabs: {
first: '大赛详情',
second: '竞赛进展',
third: '报名人员'
},
};
},
components: {
MatchDetail,
MatchProgress,
MatchSignup
},
created() {
},
methods: {
goBack() {
this.$router.back();
},
tabChange(index){
this.active = index
}
}
};
</script>
<style scoped>
</style>

@ -0,0 +1,421 @@
<template>
<!-- 大赛详情 -->
<div style='padding: 24px'>
<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高度140JPG/PNG/GIF3MB以内</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高度300JPG/PNG/GIF3MB以内</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 util from '@/libs/util'
export default {
name: 'matchDetail',
data() {
return {
id: this.$route.query.id,
coverUrl: '',
carouselUrl: '',
publishStatus: 0,
uploadList: [],
uploadDataList: [],
name: '',
sponsor: '',
sponsorList: [''],
undertaker: '',
undertakerList: [],
signUpStartTime: '',
signUpEndTime: '',
signupTime: '',
playTime: '',
playStartTime: '',
playEndTime: '',
description: ''
};
},
components: {
quill
},
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 util.warningMsg('请填写竞赛名称')
if(status == 0){
if(!this.sponsor) return util.warningMsg('请填写主办方')
if(!this.signUpStartTime) return util.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.$$message.warning('')
if(!this.playStartTime && status == 0) return util.warningMsg('请选择竞赛时间')
if(playStartTime && playStartTime < signUpEndTime) return util.warningMsg('竞赛时间不能早于报名结束时间')
if(!this.description && status == 0) return util.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 => {
util.successMsg('修改成功');
this.$router.back()
})
.catch(err => {
});
}else{
this.$post(this.api.addContest, data).then(res => {
util.successMsg('创建成功');
this.$router.back()
})
.catch(err => {
});
}
},
getData() {
this.$get(this.api.getContest + '/' + this.id)
.then(res => {
let data = res.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("setMatchData", { matchId : this.id})
},
handleExceed(files, fileList) {
util.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.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.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,162 @@
<template>
<!-- 竞赛进展 -->
<div class="page-content" style='padding: 24px'>
<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>
import util from '@/libs/util'
export default {
name: 'matchProgress',
data() {
return {
id: this.$route.query.id,
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.contestProgressList
}).catch(res => {});
},
saveData(row){
let data = row
if(data.title.length){
if(row.id){
this.$put(this.api.editContestProgress,data).then(res => {
util.successMsg('修改成功')
this.getData()
}).catch(res => {});
}else{
this.$post(this.api.addContestProgress,data).then(res => {
util.successMsg('创建成功')
this.getData()
}).catch(res => {});
}
}else{
util.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 => {
util.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{
util.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,154 @@
<template>
<!-- 报名人员 -->
<div class="page-content" style='padding: 24px'>
<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>
import util from '@/libs/util'
import Setting from '@/setting'
export default {
name: 'matchSignup',
data() {
return {
token: util.local.get(Setting.tokenKey),
id: this.$route.query.id,
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 = [];
util.successMsg('禁用成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
}else{
util.errorMsg('请先选择数据 !');
}
},
exportAll(){
location.href = `${this.api.excelExport}/${this.id}/token=${this.token}`
},
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(',')}/token=${this.token}`
}else{
util.errorMsg('请先选择数据 !');
}
}
}
};
</script>
<style scoped>
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,28 +1,33 @@
<template>
<div class="page">
<el-page-header class="m-b-20" content="实验项目管理" @back="goBack"></el-page-header>
<div>
<el-card v-if="showBack" shadow="hover" class="m-b-20">
<el-page-header content="实验项目管理" @back="goBack"></el-page-header>
</el-card>
<div class="page">
<h6 class="p-title">筛选</h6>
<div class="tool mul">
<ul class="filter">
<li>
<label>创建人</label>
<el-select size="small" v-model="queryData.founder" clearable placeholder="请选择创建人" @change="initData">
<el-option v-for="(item,index) in founder" :key="index" :label="item.label" :value="item.value"></el-option>
<el-select size="small" v-model="queryData.founder" clearable placeholder="请选择创建人"
@change="initData">
<el-option v-for="(item,index) in founderList" :key="index" :label="item.label"
:value="item.value"></el-option>
</el-select>
</li>
<li>
<label>状态</label>
<el-select size="small" v-model="queryData.state" clearable placeholder="请选择状态" @change="initData">
<el-option v-for="(item,index) in state" :key="index" :label="item.label" :value="item.value"></el-option>
<el-option v-for="(item,index) in stateList" :key="index" :label="item.label"
:value="item.value"></el-option>
</el-select>
</li>
<li>
<label>权限</label>
<el-select size="small" v-model="queryData.projectPermissions" placeholder="请选择" @change="initData">
<el-select size="small" v-model="queryData.permissions" placeholder="请选择" @change="initData">
<el-option
v-for="item in projectPermissions"
v-for="item in permissionsList"
:key="item.value"
:label="item.label"
:value="item.value"
@ -41,7 +46,8 @@
</el-select>
</li>
<li>
<el-input size="small" placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
<el-input size="small" placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model="keyword"
clearable></el-input>
</li>
</ul>
<div>
@ -50,50 +56,61 @@
</div>
</div>
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange">
<el-table :data="listData" class="table" ref="table" stripe header-align="center"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template slot-scope="scope">{{ scope.$index + (page - 1) * pageSize + 1 }}</template>
</el-table-column>
<el-table-column prop="projectName" label="实验项目名称" align="center">
<el-table-column prop="projectName" label="实验项目名称" align="center"></el-table-column>
<el-table-column prop="founder" label="创建人" align="center">
<template slot-scope="scope">
{{ founderKeys[scope.row.founder] }}
</template>
</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.projectPermissions == 2 ? '竞赛' : projectPermissions.find(n => n.value === scope.row.projectPermissions).label}}
{{ permissionsKeys[scope.row.permissions] }}
</template>
</el-table-column>
<el-table-column prop="creationTime" label="创建时间" align="center">
</el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center"></el-table-column>
<el-table-column prop="status" label="状态" align="center">
<template slot-scope="scope">
{{transferStatus(scope.row.state)}}
{{ stateKeys[scope.row.state] }}
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="text" @click="edit(scope.row)" v-auth v-if="roleId == 1 || (roleId == 13 && scope.row.founder != '超级管理员') || (roleId == 14 && scope.row.founder == '老师')">编辑</el-button>
<el-button type="text" @click="delData(scope.row)" v-auth v-if="roleId == 1 || (roleId == 13 && scope.row.founder != '超级管理员') || (roleId == 14 && scope.row.founder == '老师')">删除</el-button>
<el-button type="text" @click="copyData(scope.row)" v-auth>复制</el-button>
<el-button type="text" @click="edit(scope.row)" v-auth>
<!--v-if="roleId == 1 || (roleId == 13 && scope.row.founder != '超级管理员') || (roleId == 14 && scope.row.founder == '老师')"-->
编辑
</el-button>
<el-button type="text" @click="handleDelete(scope.row.projectId)" v-auth>
<!--v-if="roleId == 1 || (roleId == 13 && scope.row.founder != '超级管理员') || (roleId == 14 && scope.row.founder == '老师')"-->
删除
</el-button>
<el-button type="text" @click="copyData(scope.row.projectId)" v-auth>复制</el-button>
<el-switch
v-model="scope.row.enable"
:active-text="scope.row.enable ? '关闭' : '启用'"
v-model="scope.row.isOpen"
:active-text="scope.row.isOpen ? '关闭' : '启用'"
:active-value="0"
:inactive-value="1"
style="margin: 0 10px 0 10px"
@change="switchOff($event,scope.row,scope.$index)"
@change="switchOff(scope.row)"
></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background @current-change="handleCurrentChange" :current-page="page" layout="total, prev, pager, next" :total="total"></el-pagination>
<el-pagination background @current-change="handleCurrentChange" :current-page="page"
layout="total, prev, pager, next" :total="total"></el-pagination>
</div>
<el-dialog title="复制" :visible.sync="copyVisible" width="24%" center :close-on-click-modal="false">
<el-form>
<el-form-item>
<el-input placeholder="请输入项目名称" v-model="projectName" @change="projectNameExistis"></el-input>
<!--前端不用做名称判重了@change='projectNameExistis'-->
<el-input placeholder="请输入项目名称" v-model="projectName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
@ -102,86 +119,92 @@
</span>
</el-dialog>
</div>
</div>
</template>
<script>
import Setting from '@/setting'
import util from '@/libs/util'
import { mapState, mapActions } from 'vuex'
import Setting from '@/setting';
import { mapState, mapActions } from 'vuex';
export default {
data() {
return {
showBack: JSON.stringify(this.assFields) == '{}' ? false : true,
roleIdEd: this.roleId ? 13 : this.roleId,// roleId13roleId14113,1413.>
showBack: Boolean(this.$route.query.show),
roleIdEd: this.roleId ? 13 : this.roleId,// roleId13roleId14113,1413>
systemId: '',
systemList: Setting.systemList,
queryData: {
projectPermissions: "",
founder: "",
state: "",
projectName: "",
schoolId: Setting.schoolId, // id
platformId: 1, // :1 :3
founder: 0, // (0: 1:)
state: "", // (0:稿 1:)
permissions: "", // (0: 1: 2:)
},
keyword: '',
status: '',
listData: [],
total: 0,
projectPermissions: [
permissionsList: [
{
value: "",
label: "不限"
value: '',
label: '不限'
},
{
value: 0,
label: "练习"
label: '练习'
},
{
value: 1,
label: "考核"
},
// {
// value: 2,
// label: ""
// }
],
founder: [
{
value: "",
label: "不限"
label: '考核'
},
{
value: 1,
label: "超级管理员"
value: 2,
label: '竞赛'
}
],
permissionsKeys: {
0: '练习',
1: '考核',
2: '竞赛'
},
founderList: [
{
value: 13,
label: "管理员"
value: 0,
label: '系统'
},
{
value: 14,
label: "老师"
value: 1,
label: '老师'
}
],
state: [
founderKeys: {
0: '系统',
1: '老师'
},
stateList: [
{
value: "",
label: "不限"
value: '',
label: '不限'
},
{
value: 0,
label: "草稿箱"
label: '草稿箱'
},
{
value: 1,
label: "已发布"
label: '已发布'
}
],
stateKeys: {
0: '草稿箱',
1: '已发布'
},
page: 1,
pageSize: 10,
multipleSelection: [],
copyVisible: false,
projectName: '',
projectNameRepeat: false,
currentRow: {},
currentRow: {}, //
listDataAll: []
};
},
@ -191,199 +214,164 @@ export default {
]),
...mapState('project', [
'lastSystemId', 'assFields'
]),
])
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData()
},500)
this.initData();
}, 500);
}
},
mounted() {
this.systemId = this.lastSystemId ? this.lastSystemId : Setting.systemId
// systemIdsystemIdsystemId
this.systemId = this.lastSystemId ? this.lastSystemId : Setting.systemId;
console.log(this.systemId, '外面的sysid');
this.getData()
this.getData();
},
methods: {
...mapActions('project', [
'setSystemId'
]),
getData() {
this.setSystemId(this.systemId)
let data = this.queryData
data.userId = this.userId
data.systemId = this.systemId
data.pageNo = this.page
data.pageSize = this.pageSize
data.projectName = util.encodeStr(this.keyword)
data.systemId = this.systemId
this.$get(this.api.queryAllManagements,data).then(res => {
let list = res.pageInfo.list
let newList = []
list.map(n => {
if(n.founder.includes(',')){
n.founder = '管理员'
}else{
n.founder = util.getRoleName(n.founder)
this.setSystemId(this.systemId);
let data = {
...this.queryData,
projectName: this.keyword,
pageNum: this.page,
pageSize: this.pageSize,
systemId: this.systemId
};
this.$post(this.api.queryProjectManage, data).then(res => {
let { status, data } = res;
if (status === 200 && data) {
this.listData = data.records;
this.total = data.total;
}
})
this.listData = list
this.total = res.pageInfo.total
}).catch(res => {});
}).catch(err => {
console.log(err);
});
},
initData() {
this.page = 1
this.getData()
this.page = 1;
this.getData();
},
handlePage(){
let list = this.listDataAll
let result = list.slice((this.page - 1) * this.pageSize,this.page * this.pageSize)
this.listData = result
handleCurrentChange(val) { //
this.page = val;
this.getData();
},
transferStatus(status){
return status == 1 ? '已发布' : '草稿箱'
add() { //
this.setSystemId(this.systemId);
this.$router.push('/project/add');
},
handleCurrentChange(val){
this.page = val
this.getData()
edit(row) { //
this.setSystemId(row.systemId);
this.$router.push(`/project/add?projectId=${row.projectId}`);
},
add(){
this.setSystemId(this.systemId)
this.$router.push('add')
},
edit(row){
console.log(row,'编辑触发');
this.setSystemId(row.systemId)
this.$router.push(`add?id=${row.projectId}`)
},
handleSelectionChange(val) {
handleSelectionChange(val) { //
this.multipleSelection = val;
},
delData(row) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(this.api.removeProjectManagement,[row.projectId]).then(res => {
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
},
delAllData() {
if(this.multipleSelection.length != ''){
let newArr = this.multipleSelection
let delList = newArr.map(item => {
delAllData() { //
if (this.multipleSelection.length) {
let ids = this.multipleSelection.map(item => {
return item.projectId
})
});
let strIds = ids.toString();
this.handleDelete(strIds);
} else {
util.errorMsg("请先选择项目");
}
},
handleDelete(ids) { //
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(this.api.removeProjectManagement,delList).then(res => {
this.multipleSelection = [];
this.$refs.table.clearSelection()
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
}).then(() => {
this.$post(`${this.api.deleteProjectManage}?projectIds=${ids}&platformId=${this.queryData.platformId}`).then(res => {
if (res.status === 200) {
util.successMsg("删除成功");
this.getData();
} else {
util.errorMsg('请先选择项目 !');
util.errorMsg(res.message);
}
}).catch(err => {
console.log(err);
});
}).catch(() => {
this.$message.info('已取消删除');
});
},
projectNameExistis(){
let data = {
projectName: util.encodeStr(this.projectName)
}
this.$get(this.api.isNameExistis,data).then(res => {
if(res.status != 200){
this.projectNameRepeat = true
this.$message.warning('该项目名称已存在')
switchOff(row) { //
this.$get(`${this.api.updateIsOpen}?isOpen=${row.isOpen}&projectId=${row.projectId}&platformId=${this.queryData.platformId}`).then(res => {
if (res.status === 200) {
util.successMsg('更新启用状态成功');
this.getData();
} else {
this.projectNameRepeat = false
util.errorMsg(res.message);
}
}).catch(res => {})
}).catch(err => {
console.log(err);
});
},
copyData(row){
this.currentRow.management = {
caseDescription: row.caseDescription,
experimentSuggests: row.experimentSuggests,
experimentalGoal: row.experimentalGoal,
founder: row.founder,
isstartexperimentSuggests: row.isstartexperimentSuggests,
isstartexperimental: row.isstartexperimental,
projectName: row.projectName,
projectPermissions: row.projectPermissions,
state: row.state,
systemId: row.systemId,
userId: row.userId,
knowledgePoints: row.knowledgePoints,
experimentIntroduction: row.experimentIntroduction
projectNameExistis() { //
if (this.projectName) {
this.$post(this.api.queryNameIsExist, { projectName: this.projectName }).then(res => {
if (res.status === 200) {
this.projectNameRepeat = false;
} else {
this.projectNameRepeat = true;
}
this.currentRow.founder = row.founder
this.projectName = row.projectName
this.projectNameRepeat = true
this.copyVisible = true
let data = {
projectId: row.projectId
}).catch(err => {
this.projectNameRepeat = true;
});
} else {
this.projectNameRepeat = false;
}
},
copyData(projectId) { // id
this.copyVisible = true;
this.$get(`${this.api.getProjectDetail}?projectId=${projectId}`).then(res => {
if (res.status === 200) {
this.projectName = res.projectManage.projectName;
this.currentRow = {
projectManage: res.projectManage,
projectJudgmentList: res.projectJudgmentVos
}
this.$get(this.api.getZZJudgmentPoints,data).then((res) => {
this.currentRow.roleId = res.message.roleList.map(n => n.roleId)
let scoreList = res.message.scoreIndexList
let scores = []
for(let i in scoreList){
scores = scores.concat(scoreList[i])
}
let point = res.message.judgmentPointsList
point.map(n => {
let same = scores.find(e => e.judgmentPointsId == n.judgmentPointsId)
if(same) n.score = same.score
})
this.currentRow.pooints = point
this.$message.warning('请修改项目名称')
})
}).catch(err => {
console.log(err);
});
},
copySubmit() {
if(!this.projectName.length) return this.$message.warning('请填写项目名称')
if(this.projectNameRepeat) return this.$message.warning('该项目名称已存在')
let data = this.currentRow
data.management.projectName = this.projectName
data.founder = this.roleId
data.management.founder = this.roleId
data.management.userId = this.userId
data.pooints.map(n => {
n.userId = this.userId
})
let systemId = this.currentRow.management.systemId
let url = this.api.addProjectManagement
if(systemId == 2 || systemId == 3) url = this.api.addProjectManagementTrad
this.$post(url,data).then((res) => {
util.successMsg('复制成功');
this.copyVisible = false
this.getData()
})
},
switchOff(val,row,index) {
this.$get(this.api.enableProject,{
id: row.projectId,
enable: row.enable
})
.then(res => {
if(res.status != 200){
util.errorMsg(res.errmessage)
row.enable = row.enable == 1 ? 0 : 1
if (!this.projectName) {
util.warningMsg("请输入项目名称");
return;
}
})
.catch(err => {});
},
goBack() {
this.$router.back()
;
if (this.projectNameRepeat) {
util.warningMsg("该项目名称已存在");
return;
}
this.currentRow.projectManage.projectName = this.projectName;
this.currentRow.projectManage.projectId = "";
this.currentRow.projectJudgmentList.forEach(i => {
i.projectId = "";
});
this.$post(`${this.api.copyProjectManage}`, this.currentRow).then(res => {
if (res.status === 200) {
this.initData();
util.successMsg("复制实验项目成功");
this.copyVisible = false;
} else {
util.errorMsg(res.message);
}
}).catch(err => {
console.log(err);
});
},
goBack() { //
this.$router.back();
}
}
};
</script>

@ -580,7 +580,7 @@ export default {
schoolId: this.personalInformation.schoolId
});
if(res.message.user.length){
this.$message.warning('该账号已存在');
util.warningMsg('该账号已存在');
this.accountReapeat = true
}else{
this.accountReapeat = false
@ -673,7 +673,7 @@ export default {
this.archivesList.forEach((n,k) => {
if(!n.personalCareerId) isEmpty = true
})
if(isEmpty) return this.$message.warning('请选择职业');
if(isEmpty) return util.warningMsg('请选择职业');
this.showArch = true
this.concatArch()
},
@ -689,12 +689,12 @@ export default {
this.passwordVisible = true
},
editPassword() {
if(!this.passwordForm.password) return this.$message.warning('请输入原密码')
if(!this.passwordForm.newPassword) return this.$message.warning('请输入新密码')
if(!this.passwordForm.reNewPassword) return this.$message.warning('请确认新密码')
if(this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return this.$message.warning('请输入6位数以上的密码')
if(this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return this.$message.warning('输入的新密码不一致,请重新确认')
if(this.passwordForm.password === this.passwordForm.newPassword) return this.$message.warning('原密码跟新密码不能一致')
if(!this.passwordForm.password) return util.warningMsg('请输入原密码')
if(!this.passwordForm.newPassword) return util.warningMsg('请输入新密码')
if(!this.passwordForm.reNewPassword) return util.warningMsg('请确认新密码')
if(this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return util.warningMsg('请输入6位数以上的密码')
if(this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return util.warningMsg('输入的新密码不一致,请重新确认')
if(this.passwordForm.password === this.passwordForm.newPassword) return util.warningMsg('原密码跟新密码不能一致')
let data = this.passwordForm
data.userid = this.userId
@ -859,9 +859,9 @@ export default {
if(!n.personalCareerId) isEmpty = true
n.userId = this.userId
})
if(isEmpty) return this.$message.warning('请选择职业')
if(this.accountReapeat) return this.$message.warning('该账号已存在')
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.$message.warning('请输入正确的证件号码')
if(isEmpty) return util.warningMsg('请选择职业')
if(this.accountReapeat) return util.warningMsg('该账号已存在')
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 util.warningMsg('请输入正确的证件号码')
let personalInformation = this.personalInformation
let userInfoEntity = {
idNumber: personalInformation.idNumber,
@ -951,8 +951,8 @@ export default {
}
},
sendEmailCode(){
if(!this.email) return this.$message.warning('请输入邮箱')
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return this.$message.warning('请输入正确的邮箱')
if(!this.email) return util.warningMsg('请输入邮箱')
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return util.warningMsg('请输入正确的邮箱')
let data = {
userId: this.userId,
email: this.email,
@ -966,9 +966,9 @@ export default {
}).catch(res => {});
},
emailSubmit(){
if(!this.email) return this.$message.warning('请输入邮箱')
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return this.$message.warning('请输入正确的邮箱')
if(!this.emailCode) return this.$message.warning('请输入验证码')
if(!this.email) return util.warningMsg('请输入邮箱')
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return util.warningMsg('请输入正确的邮箱')
if(!this.emailCode) return util.warningMsg('请输入验证码')
let data = {
userId: this.userId,
email: this.email,
@ -990,8 +990,8 @@ export default {
}
},
sendPhoneCode(){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
if(!this.phone) return util.warningMsg('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return util.warningMsg('请输入正确的手机号')
let data = {
userId: this.userId,
phone: this.phone,
@ -1005,9 +1005,9 @@ export default {
}).catch(res => {});
},
phoneSubmit(){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
if(!this.phoneCode) return this.$message.warning('请输入验证码')
if(!this.phone) return util.warningMsg('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return util.warningMsg('请输入正确的手机号')
if(!this.phoneCode) return util.warningMsg('请输入验证码')
let data = {
userId: this.userId,
phone: this.phone,

@ -1,4 +1,73 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="6">
<div class="page">
<div class="m-b-20">
<h6 class="p-title">学生</h6>
<div>
<el-button type="text">所有学生</el-button>
</div>
<div>
<el-button type="text">未加入班级的学生</el-button>
</div>
</div>
<el-divider></el-divider>
<div>
<div class="flex-between m-b-20">
<h6 class="p-title" style="margin-bottom: 0">学生组织架构</h6>
<el-button type="text">添加</el-button>
</div>
<div>
<el-tree
:data="treeData"
node-key="id"
default-expand-all
:expand-on-click-node="false"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span style="display: inline-block; margin-right: 20px">{{ node.label }}</span>
<span>
<el-button
type="text"
icon="el-icon-edit-outline"
@click="() => handleEdit(node, data)">
</el-button>
<el-button
type="text"
icon="el-icon-circle-plus-outline"
@click="() => handleAdd(node, data)">
</el-button>
</span>
</span>
</el-tree>
</div>
</div>
<el-dialog title="新增" :visible.sync="departmentVisible" :close-on-click-modal="false" width="30%">
<el-form ref="departmentForm" :model="departmentForm" label-width="60px">
<el-form-item label="部门名称">
<el-input v-model.trim="departmentForm.name" placeholder="请输入"></el-input>
</el-form-item>
<el-form-item label="上级部门">
<el-cascader
v-model="cascaderValue"
:options="cascaderData"
@change="handleChangeCascader"
>
</el-cascader>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="Visible = false"> </el-button>
<el-button size="small" type="primary" @click="departmentSubmit"> </el-button>
</span>
</el-dialog>
</div>
</el-col>
<el-col :span="18">
<div class="page">
<h6 class="p-title">筛选</h6>
<div class="tool">
@ -91,7 +160,9 @@
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" :close-on-click-modal="false">
<div style="text-align: center">
<div style="margin-bottom: 10px;"><el-button type="primary" @click="downLoad">模板下载<i class="el-icon-download el-icon--right"></i></el-button></div>
<div style="margin-bottom: 10px;">
<el-button type="primary" @click="downLoad">模板下载<i class="el-icon-download el-icon--right"></i></el-button>
</div>
<el-upload
accept=".xls,.xlsx"
:on-remove="handleRemove"
@ -132,21 +203,260 @@
</span>
</el-dialog>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import Setting from '@/setting'
import util from '@/libs/util'
import { mapState, mapActions } from 'vuex'
export default {
data() {
return {
departmentVisible: false,
departmentForm: {
name: ""
},
cascaderValue: [], //
cascaderData: [{
value: 'zhinan',
label: '指南',
children: [{
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'yizhi',
label: '一致'
}, {
value: 'fankui',
label: '反馈'
}, {
value: 'xiaolv',
label: '效率'
}, {
value: 'kekong',
label: '可控'
}]
}, {
value: 'daohang',
label: '导航',
children: [{
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'zujian',
label: '组件',
children: [{
value: 'basic',
label: 'Basic',
children: [{
value: 'layout',
label: 'Layout 布局'
}, {
value: 'color',
label: 'Color 色彩'
}, {
value: 'typography',
label: 'Typography 字体'
}, {
value: 'icon',
label: 'Icon 图标'
}, {
value: 'button',
label: 'Button 按钮'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}, {
value: 'input',
label: 'Input 输入框'
}, {
value: 'input-number',
label: 'InputNumber 计数器'
}, {
value: 'select',
label: 'Select 选择器'
}, {
value: 'cascader',
label: 'Cascader 级联选择器'
}, {
value: 'switch',
label: 'Switch 开关'
}, {
value: 'slider',
label: 'Slider 滑块'
}, {
value: 'time-picker',
label: 'TimePicker 时间选择器'
}, {
value: 'date-picker',
label: 'DatePicker 日期选择器'
}, {
value: 'datetime-picker',
label: 'DateTimePicker 日期时间选择器'
}, {
value: 'upload',
label: 'Upload 上传'
}, {
value: 'rate',
label: 'Rate 评分'
}, {
value: 'form',
label: 'Form 表单'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table 表格'
}, {
value: 'tag',
label: 'Tag 标签'
}, {
value: 'progress',
label: 'Progress 进度条'
}, {
value: 'tree',
label: 'Tree 树形控件'
}, {
value: 'pagination',
label: 'Pagination 分页'
}, {
value: 'badge',
label: 'Badge 标记'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}, {
value: 'loading',
label: 'Loading 加载'
}, {
value: 'message',
label: 'Message 消息提示'
}, {
value: 'message-box',
label: 'MessageBox 弹框'
}, {
value: 'notification',
label: 'Notification 通知'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu 导航菜单'
}, {
value: 'tabs',
label: 'Tabs 标签页'
}, {
value: 'breadcrumb',
label: 'Breadcrumb 面包屑'
}, {
value: 'dropdown',
label: 'Dropdown 下拉菜单'
}, {
value: 'steps',
label: 'Steps 步骤条'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog 对话框'
}, {
value: 'tooltip',
label: 'Tooltip 文字提示'
}, {
value: 'popover',
label: 'Popover 弹出框'
}, {
value: 'card',
label: 'Card 卡片'
}, {
value: 'carousel',
label: 'Carousel 走马灯'
}, {
value: 'collapse',
label: 'Collapse 折叠面板'
}]
}]
}, {
value: 'ziyuan',
label: '资源',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'jiaohu',
label: '组件交互文档'
}]
}], //
treeData: [{
id: 1,
label: '一级 1',
children: [{
id: 4,
label: '二级 1-1',
children: [{
id: 9,
label: '三级 1-1-1'
}, {
id: 10,
label: '三级 1-1-2'
}]
}]
}, {
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
}, {
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}], //
isDetail: false,
keyword: '',
schoolId: Setting.schoolId,
form: {
userName: '',
account: '',
phone: '',
uniqueIdentificationAccount: '',
workNumber: '',
@ -211,7 +521,6 @@ export default {
accountReapeat: false,
phoneRepeat: false,
workNumberReapeat: false,
isDetail: false,
resetVisible: false,
passwordVisible: false,
passwordForm: {
@ -240,6 +549,19 @@ export default {
}
},
methods: {
handleAdd(node, data) { //
console.log(node)
console.log(data)
},
handleEdit(node, data) { //
},
handleChangeCascader(value) {
console.log(value);
},
departmentSubmit() { //
},
getData() {
let data = {
schoolId: this.schoolId,
@ -250,7 +572,8 @@ export default {
this.$get(this.api.queryStudent, data).then(res => {
this.listData = res.data.list
this.total = res.data.totalCount
}).catch(res => {});
}).catch(res => {
});
},
initData() {
this.$refs.table.clearSelection()
@ -260,9 +583,9 @@ export default {
saveData() {
this.$refs.form.validate((valid) => {
if (valid) {
if(this.accountReapeat) return this.$message.warning(this.accountMsg)
if(this.workNumberReapeat) return this.$message.warning('该学生学号已存在')
if(this.phoneRepeat) return this.$message.warning('该手机号已存在')
if (this.accountReapeat) return util.warningMsg(this.accountMsg)
if (this.workNumberReapeat) return util.warningMsg('该学生学号已存在')
if (this.phoneRepeat) return util.warningMsg('该手机号已存在')
this.form.schoolName = this.schoolList.find(n => n.schoolId == this.form.schoolId).schoolName
if (this.form.studentId) {
this.$put(this.api.updateStudent, this.form).then(res => {
@ -273,7 +596,8 @@ export default {
} else {
util.errorMsg(res.message);
}
}).catch(res => {});
}).catch(res => {
});
} else {
this.form.uniqueIdentificationAccount = new Date().getTime()
this.$post(this.api.addStudent, this.form).then(res => {
@ -284,7 +608,8 @@ export default {
} else {
util.errorMsg(res.message);
}
}).catch(res => {});
}).catch(res => {
});
}
} else {
return false;
@ -303,7 +628,7 @@ export default {
} else {
this.accountMsg = '该账号已存在'
}
this.$message.warning(this.accountMsg)
util.warningMsg(this.accountMsg)
this.accountReapeat = true
} else {
this.accountReapeat = false
@ -316,7 +641,7 @@ export default {
schoolId: this.schoolId
});
if (JSON.stringify(res.message) != '{}') {
this.$message.warning('该学生学号已存在');
util.warningMsg('该学生学号已存在');
this.workNumberReapeat = true
} else {
this.workNumberReapeat = false
@ -325,7 +650,7 @@ export default {
async phoneChange() {
let res = await this.$get(this.api.queryPhone, { phone: this.regForm.phone });
if (res.message.length != 0) {
this.$message.warning('该手机号已存在');
util.warningMsg('该手机号已存在');
this.phoneRepeat = true
} else {
this.phoneRepeat = false
@ -351,7 +676,8 @@ export default {
}
this.$get(this.api.querySchool, data).then(res => {
this.schoolList = res.message
}).catch(res => {});
}).catch(res => {
});
},
closeStudent() {
this.isDetail = false
@ -364,7 +690,6 @@ export default {
uniqueIdentificationAccount: '',
workNumber: '',
email: '',
account: '',
roleId: 4,
schoolAppellationId: this.schoolId
}
@ -397,9 +722,11 @@ export default {
this.$post(this.api.daleteStudent, [row.studentId]).then(res => {
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
}).catch(res => {
});
})
.catch(() => {});
.catch(() => {
});
},
getRowKeys(row) {
return row.userId;
@ -423,18 +750,20 @@ export default {
this.$refs.table.clearSelection()
util.successMsg('删除成功');
this.getData()
}).catch(res => {});
}).catch(() => {});
}).catch(res => {
});
}).catch(() => {
});
} else {
util.errorMsg('请先选择数据 !');
}
},
resetPassword(row) {
this.$confirm(`重置后的密码为:${this.$config.initialPassword},确定重置?`, '提示', {
}).then(() => {
this.$confirm(`重置后的密码为:${this.$config.initialPassword},确定重置?`, '提示', {}).then(() => {
this.$put(this.api.reSetPassword, [row.userId]).then(res => {
if (res.errmessage == 'success') util.successMsg('重置成功')
}).catch(res => {});
}).catch(res => {
});
}).catch(() => {
});
},
@ -445,8 +774,10 @@ export default {
disableAccount: row.disableAccount ? 0 : 1
}
this.$put(this.api.disableAccount, data)
.then(res => {})
.catch(err => {});
.then(res => {
})
.catch(err => {
});
},
closePassword() {
this.passwordForm = {
@ -456,12 +787,12 @@ export default {
}
},
editPassword() {
if(!this.passwordForm.password) return this.$message.warning('请输入原密码')
if(!this.passwordForm.newPassword) return this.$message.warning('请输入新密码')
if(!this.passwordForm.reNewPassword) return this.$message.warning('请确认新密码')
if(this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return this.$message.warning('请输入6位数以上的密码')
if(this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return this.$message.warning('输入的新密码不一致,请重新确认')
if(this.passwordForm.password === this.passwordForm.newPassword) return this.$message.warning('原密码跟新密码不能一致')
if (!this.passwordForm.password) return util.warningMsg('请输入原密码')
if (!this.passwordForm.newPassword) return util.warningMsg('请输入新密码')
if (!this.passwordForm.reNewPassword) return util.warningMsg('请确认新密码')
if (this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return util.warningMsg('请输入6位数以上的密码')
if (this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return util.warningMsg('输入的新密码不一致,请重新确认')
if (this.passwordForm.password === this.passwordForm.newPassword) return util.warningMsg('原密码跟新密码不能一致')
let data = this.passwordForm
data.userid = this.userId
@ -478,7 +809,7 @@ export default {
},
//
handleExceed(files, fileList) {
this.$message.warning(
util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
@ -517,7 +848,7 @@ export default {
this.page = 1
this.keyword = ''
this.getData()
},
}
}
};
</script>

@ -26,7 +26,7 @@ export default {
},
computed: {
...mapState('auth', [
'btns'
'routes'
])
},
components: {
@ -34,6 +34,7 @@ export default {
role
},
created() {
console.log("routes===", this.routes);
Setting.dynamicRoute && this.initTabs()
},
methods: {

@ -81,41 +81,6 @@ export default {
description: '',
},
listData:[],
data: [{
id: 1,
label: '一级 1',
children: [{
id: 4,
label: '二级 1-1',
children: [{
id: 9,
label: '三级 1-1-1'
}, {
id: 10,
label: '三级 1-1-2'
}]
}]
}, {
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
}, {
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}],
defaultProps: {
children: 'children',
label: 'name'
@ -213,10 +178,12 @@ export default {
this.checkedIds = []
this.permissions = []
},
//
getPer(row){
if(!this.permissions.length){
this.$get(this.api.roleTree).then(res => {
let data = res.data
//
let yw = data.findIndex(n => n.name == '业务后台')
yw != -1 && data.splice(yw,1)
try {
@ -242,11 +209,13 @@ export default {
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){
// ,idid,,,
e.children.every(n => result.includes(n)) || result.splice(result.indexOf(e.id),1)
}
e.children && e.children.length && this.handleRolePer(data,e.children)
@ -275,9 +244,10 @@ export default {
this.roleVisible = true
},
async saveData() {
if(!this.form.name) return this.$message.warning('请填写角色名称')
if(!this.form.description) return this.$message.warning('请填写角色描述')
if(!this.$refs.per.getCheckedKeys().length) return this.$message.warning('请选择角色权限')
if(!this.form.name) return util.warningMsg('请填写角色名称')
if(!this.form.description) return util.warningMsg('请填写角色描述')
if(!this.$refs.per.getCheckedKeys().length) return util.warningMsg('请选择角色权限')
// ,(),
let permissionIds = [...this.$refs.per.getHalfCheckedKeys(),...this.$refs.per.getCheckedKeys()]
let data = {
roleId: this.form.roleId,

@ -504,7 +504,7 @@ export default {
async phoneChange(){
let res = await this.$get(this.api.queryPhone, { phone: this.teacherForm.phone });
if(res.message.length != 0){
this.$message.warning('该手机号已存在');
util.warningMsg('该手机号已存在');
this.NoAdd = false
}else{
this.NoAdd = true
@ -513,7 +513,7 @@ export default {
async emailChange(){
let res = await this.$get(this.api.queryEmail, { email: this.teacherForm.email });
if(res.message.length != 0){
this.$message.warning('该邮箱已存在');
util.warningMsg('该邮箱已存在');
this.emailNoAdd = false
}else{
this.emailNoAdd = true
@ -537,7 +537,7 @@ export default {
this.accountMsg = '该账号已存在'
}
this.$message.warning(this.accountMsg)
util.warningMsg(this.accountMsg)
this.teacherForm.email = user.email
this.teacherForm.phone = user.phone
this.teacherForm.uniqueIdentificationAccount = user.uniqueIdentificationAccount
@ -599,7 +599,7 @@ export default {
}
let res = await this.$get(this.api.queryWorkNumberIsExist, data);
if(JSON.stringify(res.message) != '{}'){
this.$message.warning(msg);
util.warningMsg(msg);
type == 13 ? (this.managerNumberNoAdd = false) : (this.teacherNumberNoAdd = false)
}else{
let timestamp = Date.parse(new Date());
@ -611,21 +611,21 @@ export default {
this.$refs[teacherForm].validate((valid) => {
if (valid) {
if(this.isAddteacher) {
if(this.isManager && this.isTeacher) return this.$message.warning('该用户已经是老师和管理员,请重新添加');
if(this.isManager && !this.teacherForm.roleValue.some((n) => n == '老师')) return this.$message.warning('该用户已经是管理员');
if(this.isTeacher && !this.teacherForm.roleValue.some((n) => n == '管理员')) return this.$message.warning('该用户已经是老师');
if(!this.AccountNoAdd) return this.$message.warning(this.accountMsg)
if(this.isManager && this.isTeacher) return util.warningMsg('该用户已经是老师和管理员,请重新添加');
if(this.isManager && !this.teacherForm.roleValue.some((n) => n == '老师')) return util.warningMsg('该用户已经是管理员');
if(this.isTeacher && !this.teacherForm.roleValue.some((n) => n == '管理员')) return util.warningMsg('该用户已经是老师');
if(!this.AccountNoAdd) return util.warningMsg(this.accountMsg)
if(this.NoAdd == '' && this.teacherForm.phone){
this.phoneChange()
if(!this.NoAdd) return false
}else if(this.NoAdd === false){
return this.$message.warning('该手机号已存在')
return util.warningMsg('该手机号已存在')
}else if(this.emailNoAdd === false){
return this.$message.warning('该邮箱已存在')
return util.warningMsg('该邮箱已存在')
}
}
if(!this.managerNumberNoAdd) return this.$message.warning('该管理员工号已存在');
if(!this.teacherNumberNoAdd) return this.$message.warning('该老师工号已存在');
if(!this.managerNumberNoAdd) return util.warningMsg('该管理员工号已存在');
if(!this.teacherNumberNoAdd) return util.warningMsg('该老师工号已存在');
let roleId = []
this.teacherForm.roleValue.includes('管理员') && roleId.push(13)
@ -763,7 +763,7 @@ export default {
},
//
handleExceed(files, fileList) {
this.$message.warning(
util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},

@ -123,7 +123,7 @@ export default {
async majorChange(){
let res = await this.$get(this.api.queryStaffPAN, { name: this.Form.majorName,schoolId: this.schoolId });
if(res.message.length != 0){
this.$message.warning('该一级部门已存在');
util.warningMsg('该一级部门已存在');
this.majorNoAdd = false
}else{
this.majorNoAdd = true
@ -132,7 +132,7 @@ export default {
sure(Form){
this.$refs[Form].validate((valid) => {
if (valid) {
if(!this.majorNoAdd) return this.$message.warning('该一级部门已存在');
if(!this.majorNoAdd) return util.warningMsg('该一级部门已存在');
let data = {
staffProfessionalArchitectureName: this.Form.majorName,
staffProfessionalArchitectureId: this.Form.MajorId,

@ -8,6 +8,7 @@ import store from '@/store'
export default {
inserted (el, binding, vnode) {
let btnText = ''
// 如果有传值,就取传的值,否则,就取页面路由和按钮名字拼接起来
if(binding.value){
btnText = binding.value
}else{
@ -17,6 +18,7 @@ export default {
if (btnText && btnPermissions && btnPermissions.length) {
const isPermission = btnPermissions.includes(btnText)
// 如果按钮集合里没有该权限,就把该按钮给去除
if (!isPermission) {
el.parentNode && el.parentNode.removeChild(el)
}

@ -35,7 +35,7 @@ service.interceptors.response.use(
}else if(!res.status){
return Promise.resolve(res).catch(e => {})
}else {
util.errorMsg(res.errmessage)
util.errorMsg(res.errmessage || res.message)
return Promise.reject(res)
}
},

@ -1,22 +1,22 @@
import Vue from 'vue'
import Router from 'vue-router'
import routes from './routes'
import Setting from '@/setting'
import Vue from 'vue';
import Router from 'vue-router';
import routes from './routes';
import Setting from '@/setting';
Vue.use(Router)
Vue.use(Router);
const createRouter = () => new Router({
mode: Setting.routerMode,
    base: process.env.BASE_URL,
mode: Setting.routerMode,
base: process.env.BASE_URL,
scrollBehavior: () => ({ y: 0 }),
routes
})
});
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher
const newRouter = createRouter();
router.matcher = newRouter.matcher;
}
let router = createRouter()
let router = createRouter();
export default router
export default router;

@ -0,0 +1,41 @@
import BasicLayout from '@/layouts/home'
const meta = {}
const pre = 'course-'
export default {
path: '/course',
name: 'course',
redirect: {
name: `${pre}list`
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import('@/pages/course'),
meta: { title: '理论课程管理' }
},
{
name: `${pre}add`,
path: `add`,
component: () => import('@/pages/course/courseManagement/add'),
meta: { title: '新增课程' }
},
{
name: `${pre}preview`,
path: `preview`,
component: () => import('@/pages/course/courseManagement/preview'),
meta: { title: '课程预览' }
},
{
name: `${pre}contentSettings`,
path: `contentSettings`,
component: () => import('@/pages/course/courseManagement/contentSettings'),
meta: { title: '内容设置' }
},
]
};

@ -0,0 +1,29 @@
import BasicLayout from '@/layouts/home'
const meta = {}
const pre = 'information-'
export default {
path: '/information',
name: 'information',
redirect: {
name: `${pre}list`
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import('@/pages/information'),
meta: { title: '资讯管理' }
},
{
name: `${pre}addArticle`,
path: `addArticle`,
component: () => import('@/pages/information/contentManage/addArticle'),
meta: { title: '新增文章' }
},
]
};

@ -0,0 +1,35 @@
import BasicLayout from '@/layouts/home'
const meta = {}
const pre = 'match-'
export default {
path: '/match',
name: 'match',
redirect: {
name: `${pre}list`
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import('@/pages/match'),
meta: { title: '赛事管理' }
},
{
name: `${pre}add`,
path: `add`,
component: () => import('@/pages/match/add'),
meta: { title: '创建赛事' }
},
{
name: `${pre}manage`,
path: `manage`,
component: () => import('@/pages/match/manage'),
meta: { title: '管理赛事' }
},
]
};

@ -5,6 +5,9 @@ import project from './modules/project'
import student from './modules/student'
import system from './modules/system'
import setting from './modules/setting'
import course from './modules/course'
import match from './modules/match'
import information from './modules/information'
import BasicLayout from '@/layouts/home'
@ -15,7 +18,7 @@ const frameIn = [
},
{
path: '/index',
redirect: '/assessment',
redirect: '/student',
},
{
path: '/',
@ -30,6 +33,9 @@ const frameIn = [
student,
system,
setting,
course,
match,
information
]
/**

@ -1,125 +1,104 @@
/**
* 业务配置
* */
const url = location.host;
const isDev = process.env.NODE_ENV === 'development'; // 开发环境
const isHh = url.includes('10.196.131.73'); //是否是河海版本
const isCH = url.includes('120.78.127.12'); //是否是巢湖版本
const isBeta = isDev || url.includes('120.78.198.231'); //是否是职站测试(本地亦调用测试服接口)
const isPro = location.host.includes('occupationlab.com'); //是否是职站生产
const isDev = process.env.NODE_ENV === 'development'
const url = location.host
const isHh = url.includes('10.196.131.73') //是否是河海版本
const isBeta = isDev || url.includes('120.78.198.231') //是否是职站测试(本地亦调用测试服接口)
let host = "";
let title = "";
let schoolId = null;
let systemList = [];
const Setting = {
if (isHh) {
// 河海
host = "http://10.196.131.73/";
title = "教师管理端";
schoolId = 729;
systemList = [
{ id: 1, label: 'Python程序设计教学系统', },
{ id: 4, label: '经济金融建模实验教学系统' },
{ id: 6, label: '金融随机过程实验教学系统' },
{ id: 7, label: '量化投资策略建模实验教学系统' },
{ id: 8, label: '大数据分析实验教学系统' }
];
} else if (isCH) {
// 巢湖
host = "http://120.78.127.12/";
title = "教师管理端";
schoolId = 1006;
systemList = [
{ id: 8, label: '大数据分析实验教学系统' }
];
} else if (isBeta) {
// 职站测试
host = "http://120.78.198.231/";
title = "职站服务端管理系统";
schoolId = 2105;
systemList = [
{ id: 1, label: 'Python程序设计教学系统' },
// { id: 2, label: '跨国仿真系统' },
// { id: 3, label: '期权期货系统' },
{ id: 4, label: '经济金融建模实验教学系统' },
{ id: 5, label: 'Python可视化实验教学系统' },
{ id: 6, label: '金融随机过程实验教学系统' },
{ id: 7, label: '量化投资策略建模实验教学系统' },
{ id: 8, label: '大数据分析实验教学系统' },
{ id: 9, label: 'Python数据清洗教学实验系统' },
{ id: 10, label: 'Python数据采集(爬虫)教学实验系统' },
{ id: 11, label: '银行综合系统' },
];
} else if (isPro) {
// 职站生产
host = "http://www.occupationlab.com/";
title = "职站服务端管理系统";
schoolId = 2105;
systemList = [
{ id: 1, label: 'Python程序设计教学系统' },
{ id: 4, label: '经济金融建模实验教学系统' },
{ id: 5, label: 'Python可视化实验教学系统' },
{ id: 6, label: '金融随机过程实验教学系统' },
{ id: 7, label: '量化投资策略建模实验教学系统' },
{ id: 8, label: '大数据分析实验教学系统' },
{ id: 9, label: 'Python数据清洗教学实验系统' },
{ id: 10, label: 'Python数据采集(爬虫)教学实验系统' }
];
} else {
console.log("其它版本");
}
const Setting = {
/**
* 基础配置
* */
// 网页标题的后缀
titleSuffix: isHh ? '教师管理端' : '职站服务端管理系统',
// 路由模式,可选值为 history 或 hash
routerMode: 'hash',
// 页面切换时,是否显示模拟的进度条
showProgressBar: true,
// 接口请求地址
apiBaseURL: (isDev || url.includes('120.78.198.231')) ? 'http://120.78.198.231/' : (url.includes('10.196.131.73') ? 'http://10.196.131.73/' : 'http://www.occupationlab.com/'),
// 是否是河海版本
isHh,
// 学校id,河海为729,职站为2105
schoolId: isHh ? 729 : 2105,
// 默认系统id
systemId: 1,
titleSuffix: title, // 网页标题的后缀
routerMode: 'hash', // 路由模式,可选值为 history 或 hash
showProgressBar: true, // 页面切换时,是否显示模拟的进度条
apiBaseURL: host, // 接口请求地址
isHh, // 是否是河海版本
isCH, // 是否是巢湖版本
isBeta, // 是否是职站测试
isPro, // 是否是职站生产
schoolId, // 学校id
systemId: systemList[0].id, // 默认系统id
// 子系统列表.改的时候留意要改的是哪个环境,别影响到了其他环境
systemList: isHh ? [{
id: 1,
label: 'Python程序设计教学系统'
}
,{
id: 4,
label: '经济金融建模实验教学系统'
},
{
id: 6,
label: '金融随机过程实验教学系统'
},{
id: 7,
label: '量化投资策略建模实验教学系统'
},{
id: 8,
label: '大数据分析实验教学系统'
}] : (isBeta ? [{
id: 1,
label: 'Python程序设计教学系统'
}
// 下面这两个是川大和科大子系统,目前没有在职站开启,只有在科大川大才会开放对应的子系统
// ,{
// id: 2,
// label: '跨国仿真系统'
// },{
// id: 3,
// label: '期权期货系统'
// }
,{
id: 4,
label: '经济金融建模实验教学系统'
},{
id: 5,
label: 'Python可视化实验教学系统'
},{
id: 6,
label: '金融随机过程实验教学系统'
},{
id: 7,
label: '量化投资策略建模实验教学系统'
},{
id: 8,
label: '大数据分析实验教学系统'
},{
id: 9,
label: 'Python数据清洗教学实验系统'
},{
id: 10,
label: 'Python数据采集(爬虫)教学实验系统'
}] : [{
id: 1,
label: 'Python程序设计教学系统'
},{
id: 4,
label: '经济金融建模实验教学系统'
},{
id: 5,
label: 'Python可视化实验教学系统'
},{
id: 6,
label: '金融随机过程实验教学系统'
},{
id: 7,
label: '量化投资策略建模实验教学系统'
},{
id: 8,
label: '大数据分析实验教学系统'
},{
id: 9,
label: 'Python数据清洗教学实验系统'
},{
id: 10,
label: 'Python数据采集(爬虫)教学实验系统'
}]),
// 长时间未操作,自动退出登录时间
autoLogoutTime: 3600000,
// 新增项目跳转判分点数据存储cookie的key
projectData: 'sta_data',
// 接口请求返回错误时,弹窗的持续时间,单位:秒
modalDuration: 3,
// 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice
errorModalType: 'Message',
// Cookies 默认保存时间,单位:天
cookiesExpires: 1,
// token在localStorage的时间(毫秒)
tokenExpires: 1296000000,
// 以后如果卖给了其他学校,要给该学校单独开放子系统的话,就在下面这个数组里加判断就行,然后把需要开放的子系统放出来。不要复制这个职站项目另起一个项目,这样学校一多就很难维护了
systemList,
autoLogoutTime: 3600000, // 长时间未操作,自动退出登录时间
projectData: 'sta_data', // 新增项目跳转判分点数据存储cookie的key
modalDuration: 3, // 接口请求返回错误时,弹窗的持续时间,单位:秒
errorModalType: 'Message', // 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice
cookiesExpires: 1, // Cookies 默认保存时间,单位:天
tokenExpires: 1296000000, // token在localStorage的时间(毫秒)
/**
* 免登录保存的token的key
* localStorage里保存的token的key
*/
tokenKey: 'oc_server_token',
/**
* sessionStorage里state的key
* localStorage里保存的vuex的key
*/
storeKey: 'oc_server_store',
/**
@ -146,7 +125,7 @@ const Setting = {
* */
// 相同路由,不同参数间进行切换,是否强力更新
sameRouteForceUpdate: false,
// 是否使用动态路由
// 是否使用动态路由(即角色权限,开启了的话就会取后端返回的权限树来显示头部导肮和页面按钮)
dynamicRoute: false,
// 文件上传
upload: {

@ -0,0 +1,26 @@
/**
* 资讯相关
* */
export default {
namespaced: true,
state: {
tabsName: '2',
columnId: ""
},
mutations: {
SET_TABS_NAME: (state, name) => {
state.tabsName = name
},
SET_COLUMN_ID: (state, id) => {
state.columnId = id
},
},
actions: {
setTabsName({ state,commit },name) {
commit('SET_TABS_NAME',name)
},
setColumnId({ state,commit },id) {
commit('SET_COLUMN_ID',id)
},
}
}

@ -0,0 +1,19 @@
/**
* 赛事相关
* */
export default {
namespaced: true,
state: {
matchId: '',
},
mutations: {
SET_MATCH_ID: (state, id) => {
state.matchId = id
},
},
actions: {
setMatchId({ state,commit },id) {
commit('SET_MATCH_ID',id)
},
}
}

@ -17,7 +17,7 @@
},
SET_ASS: (state, assFields) => {
state.assFields = assFields
},
}
},
actions: {
setSystemId({ state, commit }, systemId) {

@ -12,7 +12,7 @@ export default {
namespaced: true,
state: {
avatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
userId: '',
userId: 3,
userName: '',
schoolId: '',
roleId: '',
@ -36,23 +36,22 @@ export default {
},
actions: {
login({ state,commit }, userInfo) {
const { account, password, source } = userInfo
return new Promise((resolve, reject) => {
get(api.logins,{
account,
password,
source,
}).then(res => {
post(api.logins, userInfo).then(res => {
console.log(JSON.stringify(res));
if(res.status == 200){
let data = res.message.retvalue
res.message.listValue && Setting.dynamicRoute && addRoutes(res.message.listValue)
let { data } = res;
// 生成路由权限
// 每个系统都是用这套角色权限代码的,后端也是基本一样,除了个别字段可能会不一样
// 总体来说就两个步骤: 1是生成能够访问的路由的数组集合,2是生成能看到的按钮的数组集合
//res.message.listValue && Setting.dynamicRoute && addRoutes(res.message.listValue)
util.local.set(Setting.tokenKey,data.token,Setting.tokenExpires)
util.successMsg('登录成功')
console.log(data,'登录保存的数据');
commit('SET_INFO',data)
resolve()
}else{
util.errorMsg(res.errmessage)
util.errorMsg(res.errmessage || res.message)
reject(res)
}
}).catch(error => {

@ -10,9 +10,9 @@ module.exports = {
},
}
},
publicPath: Setting.publicPath,
  outputDir: Setting.outputDir,
  assetsDir: Setting.assetsDir,
publicPath: Setting.publicPath,
outputDir: Setting.outputDir,
assetsDir: Setting.assetsDir,
devServer: {
port: 8081 // 固定端口
}

Loading…
Cancel
Save