shuishen
2021-07-27 87b0fa598f0a01a07884deb83c14741f8021e1ff
Merge branch 'master' of http://s16s652780.51mypc.cn:49896/r/zhba_enterprises
31 files modified
40 files added
11748 ■■■■ changed files
package-lock.json 10 ●●●●● patch | view | raw | blame | history
package.json 2 ●●●●● patch | view | raw | blame | history
src/api/applyexam/applyexam.js 120 ●●●●● patch | view | raw | blame | history
src/api/exam/answer.js 124 ●●●●● patch | view | raw | blame | history
src/api/exam/course.js 57 ●●●●● patch | view | raw | blame | history
src/api/exam/exam.js 84 ●●●●● patch | view | raw | blame | history
src/api/exam/examRecord.js 58 ●●●●● patch | view | raw | blame | history
src/api/exam/knowledge.js 18 ●●●●● patch | view | raw | blame | history
src/api/exam/subject.js 74 ●●●●● patch | view | raw | blame | history
src/api/exam/subjectCategory.js 41 ●●●●● patch | view | raw | blame | history
src/api/examapi/applyexam.js 47 ●●●●● patch | view | raw | blame | history
src/api/examapi/examSubjects.js 37 ●●●●● patch | view | raw | blame | history
src/api/examapi/examination.js 39 ●●●●● patch | view | raw | blame | history
src/api/examapi/performance.js 21 ●●●●● patch | view | raw | blame | history
src/api/examapi/subject.js 23 ●●●●● patch | view | raw | blame | history
src/assets/css/_fonts.scss 3 ●●●●● patch | view | raw | blame | history
src/assets/css/_responsive.scss 11 ●●●●● patch | view | raw | blame | history
src/assets/css/_theme_color.scss 29 ●●●●● patch | view | raw | blame | history
src/assets/css/mixin.scss 79 ●●●●● patch | view | raw | blame | history
src/assets/css/style.scss 1084 ●●●●● patch | view | raw | blame | history
src/assets/css/subject.scss 81 ●●●●● patch | view | raw | blame | history
src/assets/css/transition.scss 12 ●●●●● patch | view | raw | blame | history
src/components/Subjects/Choices/index.vue 89 ●●●●● patch | view | raw | blame | history
src/components/Subjects/Judgement/index.vue 81 ●●●●● patch | view | raw | blame | history
src/components/Subjects/MultipleChoices/index.vue 99 ●●●●● patch | view | raw | blame | history
src/components/Subjects/PracticalOperation/index.vue 190 ●●●●● patch | view | raw | blame | history
src/components/Subjects/ShortAnswer/index.vue 73 ●●●●● patch | view | raw | blame | history
src/components/Tinymce/components/editorImage.vue 103 ●●●●● patch | view | raw | blame | history
src/components/Tinymce/index.vue 162 ●●●●● patch | view | raw | blame | history
src/components/Tinymce/plugins.js 7 ●●●●● patch | view | raw | blame | history
src/components/Tinymce/toolbar.js 6 ●●●●● patch | view | raw | blame | history
src/config/env.js 2 ●●● patch | view | raw | blame | history
src/config/iconList.js 11 ●●●●● patch | view | raw | blame | history
src/const/constant.js 10 ●●●●● patch | view | raw | blame | history
src/const/errorCode.js 12 ●●●●● patch | view | raw | blame | history
src/store/modules/common.js 10 ●●●● patch | view | raw | blame | history
src/styles/element-ui.scss 141 ●●●●● patch | view | raw | blame | history
src/views/applyexam/index.vue 461 ●●●●● patch | view | raw | blame | history
src/views/authority/role.vue 2 ●●● patch | view | raw | blame | history
src/views/desk/notice.vue 2 ●●● patch | view | raw | blame | history
src/views/dispatch/dispatch.vue 1 ●●●● patch | view | raw | blame | history
src/views/dispatch/dispatchChildoperable.vue 149 ●●●● patch | view | raw | blame | history
src/views/exam/examSubjects.vue 328 ●●●●● patch | view | raw | blame | history
src/views/exam/examination.vue 478 ●●●●● patch | view | raw | blame | history
src/views/exam/performance.vue 398 ●●●●● patch | view | raw | blame | history
src/views/exam/startexam.vue 388 ●●●●● patch | view | raw | blame | history
src/views/exam/subject.vue 263 ●●●●● patch | view | raw | blame | history
src/views/exam/topicDetails.vue 211 ●●●●● patch | view | raw | blame | history
src/views/recruitmentManagement/index.vue 2 ●●● patch | view | raw | blame | history
src/views/resource/attach.vue 2 ●●● patch | view | raw | blame | history
src/views/resource/oss.vue 760 ●●●● patch | view | raw | blame | history
src/views/securityEquipment/car.vue 3 ●●●● patch | view | raw | blame | history
src/views/securityEquipment/equipments.vue 3 ●●●● patch | view | raw | blame | history
src/views/securityEquipment/gun.js 11 ●●●●● patch | view | raw | blame | history
src/views/securityEquipment/gun.vue 3 ●●●● patch | view | raw | blame | history
src/views/securityGuard/data.js 876 ●●●● patch | view | raw | blame | history
src/views/securityGuard/securityGuard.vue 5 ●●●●● patch | view | raw | blame | history
src/views/securityUnit/data.js 21 ●●●●● patch | view | raw | blame | history
src/views/securityUnit/index.vue 5 ●●●●● patch | view | raw | blame | history
src/views/singleperformance/index.vue 398 ●●●●● patch | view | raw | blame | history
src/views/startexam/index.vue 663 ●●●●● patch | view | raw | blame | history
src/views/system/client.vue 594 ●●●● patch | view | raw | blame | history
src/views/system/dept.vue 2 ●●● patch | view | raw | blame | history
src/views/system/dict.vue 186 ●●●● patch | view | raw | blame | history
src/views/system/dictbiz.vue 654 ●●●● patch | view | raw | blame | history
src/views/system/menu.vue 755 ●●●● patch | view | raw | blame | history
src/views/system/topmenu.vue 629 ●●●● patch | view | raw | blame | history
src/views/system/user.vue 2 ●●● patch | view | raw | blame | history
src/views/trainingRegistration/index.vue 5 ●●●●● patch | view | raw | blame | history
src/views/workreport/data.js 432 ●●●● patch | view | raw | blame | history
src/views/workreport/workreport.vue 6 ●●●● patch | view | raw | blame | history
package-lock.json
@@ -7471,6 +7471,11 @@
        "commander": "*"
      }
    },
    "moment": {
      "version": "2.29.1",
      "resolved": "https://registry.nlark.com/moment/download/moment-2.29.1.tgz",
      "integrity": "sha1-sr52n6MZQL6e7qZGnAdeNQBvo9M="
    },
    "move-concurrently": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -11938,6 +11943,11 @@
      "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
      "dev": true
    },
    "vue2-countdown": {
      "version": "1.0.8",
      "resolved": "https://registry.npm.taobao.org/vue2-countdown/download/vue2-countdown-1.0.8.tgz",
      "integrity": "sha1-4PILava62zPPmcjMPfUdLHfy7zU="
    },
    "vuex": {
      "version": "3.6.2",
      "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
package.json
@@ -21,6 +21,7 @@
    "js-cookie": "^2.2.0",
    "js-md5": "^0.7.3",
    "mockjs": "^1.0.1-beta3",
    "moment": "^2.29.1",
    "node-gyp": "^5.0.6",
    "nprogress": "^0.2.0",
    "portfinder": "^1.0.23",
@@ -29,6 +30,7 @@
    "vue-axios": "^2.1.2",
    "vue-i18n": "^8.7.0",
    "vue-router": "^3.0.1",
    "vue2-countdown": "^1.0.8",
    "vuex": "^3.1.1"
  },
  "devDependencies": {
src/api/applyexam/applyexam.js
New file
@@ -0,0 +1,120 @@
import request from '@/router/axios';
export const getList = (current, size, params, deptId) => {
  return request({
    url: '/api/blade-user/page',
    method: 'get',
    params: {
      ...params,
      current,
      size,
      deptId,
    }
  })
}
export const remove = (ids) => {
  return request({
    url: '/api/blade-user/remove',
    method: 'post',
    params: {
      ids,
    }
  })
}
export const add = (row) => {
  return request({
    url: '/api/blade-user/submit',
    method: 'post',
    data: row
  })
}
export const update = (row) => {
  return request({
    url: '/api/blade-user/update',
    method: 'post',
    data: row
  })
}
export const updatePlatform = (userId, userType, userExt) => {
  return request({
    url: '/api/blade-user/update-platform',
    method: 'post',
    params: {
      userId,
      userType,
      userExt,
    }
  })
}
export const getUser = (id) => {
  return request({
    url: '/api/blade-user/detail',
    method: 'get',
    params: {
      id,
    }
  })
}
export const getUserPlatform = (id) => {
  return request({
    url: '/api/blade-user/platform-detail',
    method: 'get',
    params: {
      id,
    }
  })
}
export const getUserInfo = () => {
  return request({
    url: '/api/blade-user/info',
    method: 'get',
  })
}
export const resetPassword = (userIds) => {
  return request({
    url: '/api/blade-user/reset-password',
    method: 'post',
    params: {
      userIds,
    }
  })
}
export const updatePassword = (oldPassword, newPassword, newPassword1) => {
  return request({
    url: '/api/blade-user/update-password',
    method: 'post',
    params: {
      oldPassword,
      newPassword,
      newPassword1,
    }
  })
}
export const updateInfo = (row) => {
  return request({
    url: '/api/blade-user/update-info',
    method: 'post',
    data: row
  })
}
export const grant = (userIds, roleIds) => {
  return request({
    url: '/api/blade-user/grant',
    method: 'post',
    params: {
      userIds,
      roleIds,
    }
  })
}
src/api/exam/answer.js
New file
@@ -0,0 +1,124 @@
import request from '@/router/axios'
const baseAnswerUrl = '/api/exam/v1/answer/'
export function fetchAnswerList(query) {
  return request({
    url: baseAnswerUrl + 'answerList',
    method: 'get',
    params: query
  })
}
export function getAnswer(id) {
  return request({
    url: baseAnswerUrl + id,
    method: 'get'
  })
}
export function getAnswerInfo(id, query) {
  return request({
    url: baseAnswerUrl + id + '/info',
    method: 'get',
    params: query
  })
}
export function getAnswerListInfo(id, query) {
  return request({
    url: baseAnswerUrl + 'record/' + id + '/answerListInfo',
    method: 'get',
    params: query
  })
}
export function addAnswer(obj) {
  return request({
    url: baseAnswerUrl,
    method: 'post',
    data: obj
  })
}
export function putAnswer(obj) {
  return request({
    url: baseAnswerUrl,
    method: 'put',
    data: obj
  })
}
export function delAnswer(id) {
  return request({
    url: baseAnswerUrl + id,
    method: 'delete'
  })
}
export function save(obj) {
  return request({
    url: baseAnswerUrl + 'save',
    method: 'post',
    data: obj
  })
}
export const saveAndNext = (params) => {
  return request({
    url: '/api/examScore/saveExamScore',
    method: 'post',
    data: {
      // "allGrade": 0,
      "allScore": 200,
      "candidateNo": params.securityId + '  ',
      "company": params.company,
      "examName": params.examName,
      "examResultVOS": params.examResultVOS,
      "examTime": params.examTime,
      "examType": Number(params.examType),
      "learnGrade": 0,
      "papersId": Number(params.papersId),
      "securityName": params.securityName
    }
  })
}
export function anonymousUserSaveAndNext(obj, nextType, nextSubjectId, nextSubjectType) {
  let url = baseAnswerUrl + 'anonymousUser/saveAndNext?nextType=' + nextType
  if (nextSubjectId !== undefined) {
    url += '&nextSubjectId=' + nextSubjectId
  }
  if (nextSubjectType !== undefined) {
    url += '&nextSubjectType=' + nextSubjectType
  }
  return request({
    url: url,
    method: 'post',
    data: obj
  })
}
export function submit(obj) {
  return request({
    url: baseAnswerUrl + 'submit',
    method: 'post',
    data: obj
  })
}
export function anonymousUserSubmit(obj) {
  return request({
    url: baseAnswerUrl + 'anonymousUser/submit',
    method: 'post',
    data: obj
  })
}
export function anonymousUserSubmitAll(obj, examinationId, identifier) {
  return request({
    url: baseAnswerUrl + 'anonymousUser/submitAll/' + examinationId + '?identifier=' + identifier,
    method: 'post',
    data: obj
  })
}
src/api/exam/course.js
New file
@@ -0,0 +1,57 @@
import request from '@/router/axios'
const baseCourseUrl = '/api/exam/v1/course/'
export function courseList (query) {
  return request({
    url: baseCourseUrl + 'courseList',
    method: 'get',
    params: query
  })
}
export function fetchCourseList (query) {
  return request({
    url: baseCourseUrl + 'courseList',
    method: 'get',
    params: query
  })
}
export function getObj (id) {
  return request({
    url: baseCourseUrl + id,
    method: 'get'
  })
}
export function addObj (obj) {
  return request({
    url: baseCourseUrl,
    method: 'post',
    data: obj
  })
}
export function putObj (obj) {
  return request({
    url: baseCourseUrl,
    method: 'put',
    data: obj
  })
}
export function delObj (id) {
  return request({
    url: baseCourseUrl + id,
    method: 'delete'
  })
}
export function delAllObj (obj) {
  return request({
    url: baseCourseUrl + 'deleteAll',
    method: 'post',
    data: obj
  })
}
src/api/exam/exam.js
New file
@@ -0,0 +1,84 @@
import request from '@/router/axios'
const baseExaminationUrl = '/api/exam/v1/examination/'
export function fetchList (query) {
  return request({
    url: baseExaminationUrl + 'examinationList',
    method: 'get',
    params: query
  })
}
export function fetchAllSubjectList (query) {
  return request({
    url: baseExaminationUrl + 'anonymousUser/allSubjectList',
    method: 'get',
    params: query
  })
}
export function getObj (id, query) {
  return request({
    url: baseExaminationUrl + id,
    method: 'get',
    params: query
  })
}
export function anonymousUserGetObj (id, query) {
  return request({
    url: baseExaminationUrl + 'anonymousUser/' + id,
    method: 'get',
    params: query
  })
}
export const getSubjectIds = (param) => {
  return request({
    url: '/api/exampaper/queryPagerSubject/',
    method: 'get',
    params: {
      ...param
    }
  })
}
export function anonymousUserGetSubjectIds (id, query) {
  return request({
    url: baseExaminationUrl + 'anonymousUser/' + id + '/subjectIds',
    method: 'get',
    params: query
  })
}
export function addObj (obj) {
  return request({
    url: baseExaminationUrl,
    method: 'post',
    data: obj
  })
}
export function putObj (obj) {
  return request({
    url: baseExaminationUrl,
    method: 'put',
    data: obj
  })
}
export function delObj (id) {
  return request({
    url: baseExaminationUrl + id,
    method: 'delete'
  })
}
export function delAllObj (obj) {
  return request({
    url: baseExaminationUrl + 'deleteAll',
    method: 'post',
    data: obj
  })
}
src/api/exam/examRecord.js
New file
@@ -0,0 +1,58 @@
import request from '@/router/axios'
const baseExamRecordUrl = '/api/exam/v1/examRecord/'
export function fetchList (query) {
  return request({
    url: baseExamRecordUrl + 'examRecordList',
    method: 'get',
    params: query
  })
}
export function getObj (id, query) {
  return request({
    url: baseExamRecordUrl + id,
    method: 'get',
    params: query
  })
}
export function addObj (obj) {
  return request({
    url: baseExamRecordUrl,
    method: 'post',
    data: obj
  })
}
export function start (obj) {
  return request({
    url: baseExamRecordUrl + 'start',
    method: 'post',
    data: obj
  })
}
export function anonymousUserStart (obj) {
  return request({
    url: baseExamRecordUrl + 'anonymousUser/start',
    method: 'post',
    params: obj
  })
}
export function getCurrentTime () {
  return request({
    url: '/api/exampaper/getdate',
    method: 'get'
  })
}
// 查询成绩详情
export function examRecordDetails (id) {
  return request({
    url: baseExamRecordUrl + id + '/details',
    method: 'get'
  })
}
src/api/exam/knowledge.js
New file
@@ -0,0 +1,18 @@
import request from '@/router/axios'
const baseKnowledgeUrl = '/api/exam/v1/knowledge/'
export function fetchKnowledgeList (query) {
  return request({
    url: baseKnowledgeUrl + 'knowledgeList',
    method: 'get',
    params: query
  })
}
export function getObj (id) {
  return request({
    url: baseKnowledgeUrl + id,
    method: 'get'
  })
}
src/api/exam/subject.js
New file
@@ -0,0 +1,74 @@
import request from '@/router/axios'
const baseSubjectUrl = '/api/exam/v1/subject/'
export function subjectList () {
  return request({
    url: baseSubjectUrl + 'subjectList',
    method: 'get'
  })
}
export function fetchSubjectList (query) {
  return request({
    url: baseSubjectUrl + 'subjectList',
    method: 'get',
    params: query
  })
}
export function getObj (id, query) {
  return request({
    url: baseSubjectUrl + id,
    method: 'get',
    params: query
  })
}
export function addSubject (obj) {
  return request({
    url: baseSubjectUrl,
    method: 'post',
    data: obj
  })
}
export function putSubject (obj) {
  return request({
    url: baseSubjectUrl,
    method: 'put',
    data: obj
  })
}
export function delSubject (id) {
  return request({
    url: baseSubjectUrl + id,
    method: 'delete'
  })
}
export function delAllSubject (obj) {
  return request({
    url: baseSubjectUrl + 'deleteAll',
    method: 'post',
    data: obj
  })
}
export function getSubjectAnswer (obj) {
  return request({
    url: '/api/examSubjectChoices/details',
    method: 'get',
    params: obj
  })
}
export function anonymousUserGetSubjectAnswer (obj) {
  return request({
    url: baseSubjectUrl + 'anonymousUser/subjectAnswer',
    method: 'get',
    params: obj
  })
}
src/api/exam/subjectCategory.js
New file
@@ -0,0 +1,41 @@
import request from '@/router/axios'
const baseSubjectCategoryUrl = '/api/exam/v1/subjectCategory/'
export function fetchTree (query) {
  return request({
    url: baseSubjectCategoryUrl + 'categories',
    method: 'get',
    params: query
  })
}
export function addObj (obj) {
  return request({
    url: baseSubjectCategoryUrl,
    method: 'post',
    data: obj
  })
}
export function getObj (id) {
  return request({
    url: baseSubjectCategoryUrl + id,
    method: 'get'
  })
}
export function delObj (id) {
  return request({
    url: baseSubjectCategoryUrl + id,
    method: 'delete'
  })
}
export function putObj (obj) {
  return request({
    url: baseSubjectCategoryUrl,
    method: 'put',
    data: obj
  })
}
src/api/examapi/applyexam.js
New file
@@ -0,0 +1,47 @@
import request from '@/router/axios';
export const getApplyList = (current, size, params) => {
  return request({
    url: '/api/apply/page',
    method: 'get',
    params: {
      ...params,
      current,
      size
    }
  })
}
export const addApply = (row) => {
  return request({
    url: '/api/apply/submit',
    method: 'post',
    data: row
  })
}
export const remove = (ids) => {
  return request({
    url: '/api/apply/remove',
    method: 'post',
    params: {
      ids,
    }
  })
}
export const getMenu = (id) => {
  return request({
    url: '/api/apply/detail',
    method: 'get',
    params: {
      id,
    }
  })
}
src/api/examapi/examSubjects.js
New file
@@ -0,0 +1,37 @@
import request from '@/router/axios';
export const getPaperList = (current, size, params) => {
  return request({
    url: '/api/examSubjectChoices/getEexPaperChoices',
    method: 'get',
    params: {
      ...params,
      current,
      size
    }
  })
}
export const updatePaper = (row) => {
  return request({
    url: '/api/examSubjectChoices/updateChoicesValue',
    method: 'post',
    params: {
      ...row
    }
  })
}
export const remove = (params) => {
  return request({
    url: '/api/exampaper/UnbindSubject',
    method: 'get',
    params: {
      ...params
    }
  })
}
src/api/examapi/examination.js
New file
@@ -0,0 +1,39 @@
import request from '@/router/axios';
export const getList = (current, size, params) => {
  return request({
    url: '/api/exampaper/page',
    method: 'get',
    params: {
      ...params,
      current,
      size
    }
  })
}
export const remove = (ids) => {
  return request({
    url: '/api/exampaper/remove',
    method: 'post',
    params: {
      ids,
    }
  })
}
export const add = (row) => {
  return request({
    url: '/api/exampaper/submit',
    method: 'post',
    data: row
  })
}
export const update = (row) => {
  return request({
    url: '/api/exampaper/update',
    method: 'post',
    data: row
  })
}
src/api/examapi/performance.js
New file
@@ -0,0 +1,21 @@
import request from '@/router/axios';
export const getList = (current, size, params) => {
  return request({
    url: '/api/examScore/page',
    method: 'get',
    params: {
      ...params,
      current,
      size
    }
  })
}
export const update = (row) => {
  return request({
    url: '/api/examScore/updateExamScore',
    method: 'post',
    data: row
  })
}
src/api/examapi/subject.js
New file
@@ -0,0 +1,23 @@
import request from '@/router/axios';
export const getList = (current, size, params) => {
  return request({
    url: '/api/examSubjectChoices/page',
    method: 'get',
    params: {
      ...params,
      current,
      size
    }
  })
}
export const remove = (ids) => {
  return request({
    url: '/api/examSubjectChoices/remove',
    method: 'post',
    params: {
      ids,
    }
  })
}
src/assets/css/_fonts.scss
New file
@@ -0,0 +1,3 @@
// Fonts
$opensans-font: 'Open Sans', sans-serif;
$raleway-font: 'Raleway', sans-serif;
src/assets/css/_responsive.scss
New file
@@ -0,0 +1,11 @@
$breakpoint-xl: 'only screen and (min-width:1200px)';
$breakpoint-lg: 'only screen and (min-width:992px) and (max-width:1199px)';
$breakpoint-md: 'only screen and (min-width:768px) and (max-width:991px)';
$breakpoint-sm: 'only screen and (min-width:576px) and (max-width:767px)';
$breakpoint-xs: 'only screen and (max-width:767px)';
$breakpoint-xs-landscape: 'only screen and (min-width:480px) and (max-width:767px)';
src/assets/css/_theme_color.scss
New file
@@ -0,0 +1,29 @@
// Heading Color
$heading-color: rgba(0, 0, 0, 0.8);
// Text Color
$text-color: #5a5a5a;
// Default Background
$bg-default: #3762f0;
// Gray Background
$bg-gray: #f7f7f7;
// White Color
$white-color: #ffffff;
// Dark Color
$dark-color: #1b1b1b;
// Border Color
$border-color: #ebebeb;
// Hover Color
$hover-color: #2c56df;
// Footer Color
$footer-color: #252525;
// Border Color
$border-color: #ebebeb;
src/assets/css/mixin.scss
New file
@@ -0,0 +1,79 @@
@mixin wh($w,$h:$w) {
  width: $w;
  height: $h;
}
@mixin trans-duration($time) {
  -webkit-transition-duration: $time;
  transition-duration: $time;
}
@mixin transition($value) {
  -webkit-transition: $value;
  transition: $value;
}
@mixin transform($value) {
  -webkit-transform: $value;
  transform: $value;
}
@mixin animation($value) {
  -webkit-animation: $value;
  animation: $value;
}
@mixin flex-direction($value) {
  -webkit-box-orient: horizontal;
  -webkit-box-direction: reverse;
  -ms-flex-direction: $value;
  flex-direction: $value;
}
@mixin align-items($value) {
  -webkit-box-align: $value;
  -ms-flex-align: $value;
  -ms-grid-row-align: $value;
  align-items: $value;
}
@mixin display-flex($value) {
  display: -webkit-box;
  display: -ms-flexbox;
  display: $value;
}
@mixin justify-content-between {
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  justify-content: space-between;
}
@mixin justify-content($value) {
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
}
@mixin justify-content-end {
  -webkit-box-pack: end;
  -ms-flex-pack: end;
  justify-content: flex-end;
}
@mixin flex($value) {
  -webkit-box-flex: 0;
  -ms-flex: $value;
  flex: $value;
}
@mixin flex-wrap($value) {
  -ms-flex-wrap: $value;
  flex-wrap: $value;
}
@mixin bg-gradients {
  background: #0d104d;
  background: -webkit-linear-gradient(to right, #0d104d, #28408b);
  background: linear-gradient(to right, #0d104d, #28408b);
}
src/assets/css/style.scss
New file
@@ -0,0 +1,1084 @@
@import 'theme_color';
@import '_fonts';
@import 'mixin';
@import 'responsive';
@import 'transition';
* {
  margin: 0;
  padding: 0;
}
body {
  font-family: $opensans-font;
  font-size: 14px;
  font-weight: 400;
  margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  color: $heading-color;
  line-height: 1.3;
  font-weight: 700;
}
p {
  font-family: $raleway-font;
  color: $text-color;
  font-size: 14px;
  line-height: 1.8;
  font-weight: 400;
}
a,
a:hover,
a:focus {
  @include trans-duration(500ms);
  text-decoration: none;
  outline: 0 solid transparent;
  color: $heading-color;
  font-weight: 600;
  font-size: 14px;
}
ul,
ol {
  margin: 0;
  li {
    list-style: none;
  }
}
img {
  height: auto;
  max-width: 100%;
}
.padding-80-0 {
  padding-top: 80px;
  padding-bottom: 0;
}
.mb-80 {
  margin-bottom: 80px;
}
.mb-12 {
  margin-bottom: 12px;
}
.mr-100 {
  margin-right: 100px;
}
.ml-100 {
  margin-left: 100px;
}
.padding-80 {
  padding-top: 80px;
  padding-bottom: 80px;
}
.mb-30 {
  margin-bottom: 30px;
}
.w-100 {
  width: 100%;
}
.justify-content-center {
  @include justify-content(center);
}
.align-items-center {
  @include align-items(center)
}
.d-flex {
  display: -ms-flexbox;
  display: flex;
}
.text-center {
  text-align: center;
}
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
.justify-content-between {
  @include justify-content-between
}
.header-area.vue-fixed-header--isFixed {
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
}
.header-area {
  z-index: 1500 !important;
  background-color: $white-color;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
  .clever-main-menu {
    position: relative;
    width: 100%;
    height: 70px;
    .classy-navbar {
      padding: .5em 2em;
      display: flex;
      align-items: center;
      justify-content: space-between!important;
      .nav-brand {
        color: #565656;
        display: inline-block;
        margin-right: 30px;
        font-size: 30px;
        font-weight: 600;
      }
      .nav-brand:focus, .classy-navbar .nav-brand:hover {
        font-size: 26px;
        font-weight: 500;
      }
    }
    .classynav {
      .el-menu--horizontal {
        border-bottom: none;
        .el-menu-item {
          padding: 0 12px;
          display: block;
          border-bottom: none;
        }
        .el-submenu {
          .el-submenu__title {
            border-bottom: none !important;
          }
        }
      }
    }
    .classynav ul li a {
      color: rgba(0, 0, 0, 0.45);
      font-weight: 600;
      @media #{$breakpoint-lg} {
        padding: 0 8px;
      }
      &:hover,
      &:focus {
        color: $heading-color;
      }
    }
    .classy-nav-container a {
      @include trans-duration(500ms);
      color: #232323;
      display: inline-block;
      text-decoration: none;
      outline: 0;
    }
    .search-area {
      position: relative;
      width: 230px;
      height: 40px;
      margin: 0 50px;
      @media #{$breakpoint-lg} {
        width: 170px;
        margin: 0 15px;
      }
      @media #{$breakpoint-md} {
        margin: 15px auto;
      }
      @media #{$breakpoint-xs} {
        margin: 15px auto;
      }
      input {
        width: 100%;
        height: 40px;
        border-radius: 6px;
        border: 1px solid $border-color;
        padding: 0 15px 0 50px;
        font-size: 14px;
        color: rgba(0, 0, 0, 0.35);
        font-weight: 600;
        @include trans-duration(500ms);
        &:focus {
          border: 1px solid rgba(0, 0, 0, 0.5);
        }
      }
    }
  }
}
.classy-nav-container * {
  box-sizing: border-box;
}
.classy-navbar-toggler {
  border: none;
  background-color: transparent;
  cursor: pointer;
  display: none;
}
@media only screen and (min-width: 992px) and (max-width: 1199px) {
  .clever-main-menu .classynav ul li a {
    padding: 0 8px;
  }
}
.clever-main-menu .classynav ul li a:hover, .clever-main-menu .classynav ul li a:focus {
  color: rgba(0, 0, 0, 0.8);
}
@media only screen and (min-width: 992px) and (max-width: 1199px) {
  .clever-main-menu .search-area form {
    width: 170px;
    margin: 0 15px;
  }
}
@media only screen and (min-width: 768px) and (max-width: 991px) {
  .clever-main-menu .search-area form {
    margin: 15px auto;
  }
}
@media only screen and (max-width: 767px) {
  .clever-main-menu .search-area form {
    margin: 15px auto;
  }
}
.classycloseIcon, .dd-trigger {
  position: absolute;
  display: none;
}
.breakpoint-off .classynav {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-align: center;
  align-items: center;
}
.breakpoint-off .classynav, .classy-navbar {
  -webkit-box-align: center;
  -ms-grid-row-align: center;
}
.register-login-area {
  position: relative;
  z-index: 1;
}
.btn:not(:disabled):not(.disabled) {
  cursor: pointer;
}
.register-login-area a {
  position: relative;
  display: inline-block;
  padding: 0 20px;
  height: 40px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-size: 14px;
  color: #3762f0;
  line-height: 40px;
}
.classy-nav-container a, .classy-nav-container a:focus, .classy-nav-container a:hover {
  @include trans-duration(500ms);
  text-decoration: none;
  outline: 0;
  font-size: 14px;
  font-weight: 400;
}
.btn:not(:disabled):not(.disabled).active, .btn:not(:disabled):not(.disabled):active {
  background-image: none;
}
.btn:not(:disabled):not(.disabled) {
  cursor: pointer;
}
.register-login-area a.active, .register-login-area a:hover, .register-login-area a:focus {
  background-color: #d7e0fc;
  font-weight: 600;
  color: #3762f0;
}
.register-login-area a {
  position: relative;
  display: inline-block;
  padding: 0 20px;
  height: 40px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-size: 14px;
  color: #3762f0;
  line-height: 40px;
}
.classy-nav-container a, .classy-nav-container a:focus, .classy-nav-container a:hover {
  @include trans-duration(500ms);
  text-decoration: none;
  outline: 0;
  font-size: 14px;
  font-weight: 400;
}
.el-menu-link {
  color: rgba(0, 0, 0, 0.45)!important;
  font-size: 14px;
  padding: 0 20px;
  cursor: pointer;
}
/* 首页 */
.hero-area {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 325px;
  align-items: center!important;
  background-image: url("/static/img/bg-img/bg1.jpg");
  background-attachment: fixed;
  background-position: center center;
  background-size: cover;
  background-repeat: no-repeat;
  ::after {
    background-color: rgba(0, 0, 0, 0.1);
    position: absolute;
    z-index: -1;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    content: "";
  }
  .hero-content {
    text-align: center;
    h2 {
      font-size: 40px;
      margin-bottom: 10px;
      font-weight: 700;
      color: $white-color;
    }
    h4 {
      font-size: 22px;
      margin-bottom: 20px;
      font-weight: 500;
      color: $white-color;
    }
  }
}
.btn:not(:disabled):not(.disabled) {
  cursor: pointer;
}
.clever-btn {
  @include trans-duration(300ms);
  display: inline-block;
  min-width: 160px;
  height: 40px;
  background-color: #3762f0;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-size: 14px;
  color: $white-color;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 0 30px;
  line-height: 40px;
  text-align: center;
}
.single-cool-facts-area {
  text-align: center;
  position: relative;
  z-index: 1;
  padding: 30px;
  border: 1px solid #ebebeb;
  border-radius: 6px;
  margin-bottom: 80px !important;
  cursor: pointer;
}
.popular-courses-area {
  position: relative;
  background-repeat: repeat;
  background-image: url(/static/img/core-img/texture.png);
  height: 600px;
}
.section-heading {
  position: relative;
  z-index: 1;
  margin-bottom: 70px;
  text-align: center;
  h3 {
    font-size: 30px;
    margin-bottom: 0;
    @media #{$breakpoint-xs} {
      font-size: 24px;
    }
  }
  &.text-left {
    text-align: left !important;
  }
  &.white {
    h3 {
      color: $white-color;
    }
  }
}
.single-popular-course {
  position: relative;
  z-index: 1;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
  border-radius: 6px;
  background-color: $white-color;
  cursor: pointer;
  img {
    display: block;
    width: 100%;
    border-radius: 6px 6px 0 0;
  }
  .course-content {
    padding: 25px;
    h4 {
      margin-bottom: 5px;
    }
    .meta {
      margin-bottom: 15px;
      span {
        color: rgba(0, 0, 0, 0.4);
        font-size: 5px;
        margin-right: 10px;
      }
      a {
        color: rgba(0, 0, 0, 0.4);
        display: inline-block;
        font-size: 14px;
        font-weight: 400;
        margin-right: 10px;
        &:hover {
          color: #000;
        }
      }
    }
    p {
      margin-bottom: 0;
    }
  }
  .seat-rating-fee {
    display: inline-flex;
    width: 100%;
    height: 40px;
    background-color: $bg-gray;
    border-radius: 0 0 6px 6px;
    .seat-rating {
      font-size: 12px;
      color: rgba(0, 0, 0, 0.3);
      font-weight: 600;
      height: 100%;
      align-items: center;
      div {
        display: inline-block;
        padding: 0 20px;
        border-right: 1px solid $border-color;
        height: 100%;
        line-height: 40px;
      }
      i {
        font-size: 13px;
        color: rgba(0, 0, 0, 0.3);
      }
    }
    .course-fee {
      a {
        display: inline-block;
        width: 70px;
        height: 40px;
        border-radius: 0 0 6px 0;
        background-color: #e3d21b;
        text-align: center;
        line-height: 40px;
        font-size: 12px;
        font-weight: 700;
        text-transform: uppercase;
        color: $white-color;
        letter-spacing: 0.75px;
        &.free {
          background-color: $bg-default;
        }
      }
    }
  }
}
.single-blog-area {
  position: relative;
  z-index: 1;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
  border-radius: 6px;
  cursor: pointer;
  img {
    display: block;
    width: 100%;
    border-radius: 6px 6px 0 0;
  }
  .blog-content {
    padding: 25px;
    .blog-headline {
      display: block;
      h4 {
        margin-bottom: 5px;
        margin-left: -1px;
        @include trans-duration(500ms);
        &:hover,
        &:focus {
          color: $hover-color;
        }
      }
    }
    .meta {
      margin-bottom: 15px;
      span {
        color: rgba(0, 0, 0, 0.4);
        font-size: 5px;
        margin-right: 10px;
      }
      a {
        color: rgba(0, 0, 0, 0.4);
        display: inline-block;
        font-size: 14px;
        font-weight: 400;
        margin-right: 10px;
        @media #{$breakpoint-xs} {
          font-size: 12px;
        }
        &:hover {
          color: #000;
        }
      }
    }
    p {
      margin-bottom: 0;
    }
  }
}
/* 返回顶部 */
.go-top-box {
  background-color: $white-color;
  position: fixed;
  right: 50px;
  bottom: 150px;
  width: 40px;
  height: 40px;
  border-radius: 20px;
  cursor: pointer;
  transition: .3s;
  box-shadow: 0 0 6px rgba(0,0,0,.12);
  z-index: 5;
}
.top-icon {
  color: #409eff;
  display: block !important;
  line-height: 40px !important;
  text-align: center;
  font-size: 18px;
}
.content-container {
  margin-top: 2rem;
  margin-left: 100px;
  margin-right: 100px;
}
.single-course-intro {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 350px;
  .single-course-intro-content {
    width: 425px;
    height: auto;
    padding: 30px;
    background-color: $white-color;
    border-radius: 6px;
    @media #{$breakpoint-xs} {
      width: 280px;
    }
    .ratings {
      margin-bottom: 20px;
      i {
        color: #e3d21b;
        font-size: 13px;
        padding: 0 3px;
        display: inline-block;
      }
    }
    h3 {
      font-size: 30px;
      margin-bottom: 10px;
      @media #{$breakpoint-xs} {
        font-size: 24px;
      }
    }
    .meta {
      margin-bottom: 30px;
      span {
        color: rgba(0, 0, 0, 0.4);
        font-size: 5px;
        margin-right: 10px;
      }
      a {
        color: rgba(0, 0, 0, 0.4);
        display: inline-block;
        font-size: 14px;
        font-weight: 400;
        margin-right: 10px;
        &:hover {
          color: #000;
        }
      }
    }
    .price {
      font-size: 12px;
      text-transform: uppercase;
      color: $bg-default;
      letter-spacing: 0.75px;
      font-weight: 700;
    }
  }
}
.clever-description {
  position: relative;
  z-index: 1;
  .about-course {
    padding: 40px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
    h4 {
      margin-bottom: 20px;
      display: block;
    }
    p {
      font-size: 16px;
      line-height: 1.9;
      &:last-child {
        margin-bottom: 0;
      }
    }
    @media #{$breakpoint-xs} {
      padding: 30px;
    }
  }
  .all-instructors {
    padding: 40px 40px 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
    @media #{$breakpoint-xs} {
      padding: 30px 30px 0;
    }
    h4 {
      margin-bottom: 25px;
      display: block;
    }
    .single-instructor {
      position: relative;
      z-index: 1;
      background-color: $bg-gray;
      border-radius: 6px;
      .instructor-thumb {
        @include flex(0 0 80px);
        width: 80px;
        max-width: 80px;
        height: 80px;
      }
      .instructor-info {
        padding-left: 25px;
        h5 {
          font-size: 18px;
          margin-bottom: 5px;
          @media #{$breakpoint-xs} {
            font-size: 14px;
          }
        }
        span {
          font-weight: 400;
          color: rgba(0, 0, 0, 0.4);
          font-size: 14px;
        }
      }
    }
  }
  .clever-faqs {
    padding: 40px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
    h4 {
      margin-bottom: 25px;
      display: block;
    }
    @media #{$breakpoint-xs} {
      padding: 30px;
    }
  }
}
.about-curriculum {
  padding: 40px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
  h4 {
    margin-bottom: 20px;
    display: block;
  }
  p {
    font-size: 16px;
    line-height: 1.9;
    &:last-child {
      margin-bottom: 0;
    }
  }
  @media #{$breakpoint-xs} {
    padding: 30px;
  }
}
.curriculum-level {
  padding: 40px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
  h4 {
    margin-bottom: 20px;
    display: block;
  }
  h5 {
    color: rgba(0, 0, 0, 0.6);
    font-size: 18px;
  }
  .curriculum-list {
    li {
      display: block;
      margin-bottom: 10px;
      font-family: $raleway-font;
      font-size: 14px;
      font-weight: 400;
      color: rgba(0, 0, 0, 0.5);
      &:last-child {
        margin-bottom: 0;
      }
      i {
        color: #e3d21b;
        margin-right: 5px;
        display: inline-block;
      }
      ul {
        display: block;
        margin-top: 10px;
        padding-left: 25px;
        li {
          margin-bottom: 0;
          @include display-flex(flex);
          @include justify-content-between;
          padding: 10px 0;
          border-bottom: 1px solid $border-color;
          span {
            span {
              text-decoration: underline;
            }
          }
        }
      }
    }
  }
  @media #{$breakpoint-xs} {
    padding: 30px;
  }
}
.about-review {
  padding: 40px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
  h4 {
    margin-bottom: 20px;
    display: block;
  }
  p {
    font-size: 16px;
    line-height: 1.9;
    &:last-child {
      margin-bottom: 0;
    }
  }
  @media #{$breakpoint-xs} {
    padding: 30px;
  }
}
.clever-ratings {
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
  @media #{$breakpoint-xs} {
    @include flex-wrap(wrap);
  }
  .total-ratings {
    @include flex(0 0 235px);
    min-width: 235px;
    width: 235px;
    border-right: 1px solid $border-color;
    height: 250px;
    @media #{$breakpoint-xs} {
      @include flex(0 0 100%);
      min-width: 100%;
      width: 100%;
      border-right: none;
      border-bottom: 1px solid $border-color;
    }
    h2 {
      font-size: 60px;
      margin-bottom: 5px;
    }
    .ratings-- {
      margin-bottom: 10px;
      i {
        font-size: 18px;
        display: inline-block;
        padding: 0 5px;
        color: #e3d21b;
      }
    }
    span {
      font-size: 12px;
      color: rgba(0, 0, 0, 0.3);
    }
  }
  .rating-viewer {
    padding: 50px 40px 35px;
    @media #{$breakpoint-xs} {
      padding: 40px 30px 25px;
    }
    span {
      color: rgba(0, 0, 0, 0.3);
      font-size: 12px;
      text-transform: uppercase;
      padding-right: 15px;
      @media #{$breakpoint-lg} {
        padding-right: 5px;
        font-size: 11px;
      }
      @media #{$breakpoint-xs} {
        padding-right: 5px;
        font-size: 11px;
      }
    }
    .progress {
      width: 300px;
      margin-right: 15px;
      height: 10px;
      border-radius: 0;
      background-color: #f1f1f1;
      @media #{$breakpoint-lg} {
        width: 200px;
      }
      @media #{$breakpoint-md} {
        width: 140px;
      }
      @media #{$breakpoint-xs} {
        width: 140px;
      }
      .progress-bar {
        background-color: #b3b3b3;
      }
    }
  }
  .single-review {
    padding: 40px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
    @media #{$breakpoint-xs} {
      padding: 30px;
    }
    p {
      margin-bottom: 0;
    }
    .review-admin {
      .thumb {
        @include flex(0 0 40px);
        max-width: 40px;
        width: 40px;
      }
      .text {
        padding-left: 15px;
        h6 {
          font-size: 14px;
          margin-bottom: 0;
        }
        span {
          font-size: 12px;
          color: rgba(0, 0, 0, 0.4);
        }
      }
    }
    .ratings {
      i {
        font-size: 14px;
        display: inline-block;
        padding: 0 3px;
        color: #e3d21b;
      }
    }
  }
}
.about-members {
  padding: 40px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
  @media #{$breakpoint-xs} {
    padding: 30px;
  }
  h4 {
    margin-bottom: 20px;
    display: block;
  }
  p {
    font-size: 16px;
    line-height: 1.9;
    &:last-child {
      margin-bottom: 0;
    }
  }
}
.all-instructors {
  padding: 40px 40px 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
  @media #{$breakpoint-xs} {
    padding: 30px 30px 0;
  }
  h4 {
    margin-bottom: 25px;
    display: block;
  }
  .single-instructor {
    position: relative;
    z-index: 1;
    background-color: $bg-gray;
    border-radius: 6px;
    .instructor-thumb {
      @include flex(0 0 80px);
      width: 80px;
      max-width: 80px;
      height: 80px;
    }
    .instructor-info {
      padding-left: 25px;
      h5 {
        font-size: 18px;
        margin-bottom: 5px;
        @media #{$breakpoint-xs} {
          font-size: 14px;
        }
      }
      span {
        font-weight: 400;
        color: rgba(0, 0, 0, 0.4);
        font-size: 14px;
      }
    }
  }
}
.sidebar-widget {
  position: relative;
  z-index: 1;
  padding: 35px 30px;
  border: 1px solid $border-color;
  border-bottom: none;
  &:last-child {
    border-bottom: 1px solid $border-color;
  }
  h4 {
    margin-bottom: 20px;
    font-size: 24px;
    display: block;
  }
  .features-list {
    li {
      @include display-flex(flex);
      @include justify-content-between;
      margin-bottom: 5px;
      h6 {
        color: rgba(0, 0, 0, 0.3);
        font-size: 14px;
        @media #{$breakpoint-xs} {
          font-size: 14px;
        }
        i {
          margin-right: 10px;
        }
      }
    }
  }
  .single--courses {
    position: relative;
    z-index: 1;
    margin-bottom: 20px;
    &:last-child {
      margin-bottom: 0;
    }
    .thumb {
      @include flex(0 0 80px);
      width: 80px;
      max-width: 80px;
      height: 50px;
      border-radius: 6px;
      cursor: pointer;
      img {
        border-radius: 6px;
      }
    }
    .content {
      padding-left: 20px;
      h5 {
        font-size: 18px;
        margin-bottom: 5px;
        color: rgba(0, 0, 0, 0.35);
        @media #{$breakpoint-xs} {
          font-size: 14px;
        }
      }
      h6 {
        font-size: 12px;
        color: #e3d21b;
        margin-bottom: 0;
      }
    }
  }
}
.single-course-content {
  .el-tabs__nav {
    margin-bottom: 20px;
  }
  .el-tabs__active-bar {
    height: 0!important;
  }
  .el-tabs__nav-wrap::after {
    height: 0;
  }
  .el-tab-pane {
    margin: 20px;
  }
  .el-tabs__header {
    margin-left: 30px;
  }
}
src/assets/css/subject.scss
New file
@@ -0,0 +1,81 @@
.subject-exam-title{
  font-size: 18px;
  line-height: 25px;
  padding: 18px 20px;
  border-bottom: 1px solid #DEDEDE;
  margin-bottom: 12px;
}
.subject {
  padding-left: 30px;
  padding-right: 75px;
}
.subject-content{
  margin-top: 18px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-weight: 300;
  background: #fff;
  z-index: 1;
  position: relative;
}
/* 题目 */
.subject-title {
  font-size: 18px;
  line-height: 22px;
  .subject-title-number {
    display: inline-block;
    line-height: 22px;
  }
  .subject-title-content {
    // display: inline-block;
  }
}
.subject-options {
  margin: 0;
  padding: 0;
  list-style: none;
  > li {
    position: relative;
    font-size: 24px;
    .toggle {
      opacity: 0;
      text-align: center;
      width: 35px;
      /* auto, since non-WebKit browsers doesn't support input styling */
      height: auto;
      position: absolute;
      top: 0;
      bottom: 0;
      margin: auto 0;
      border: none;
      /* Mobile Safari */
      -webkit-appearance: none;
      appearance: none;
    }
    .toggle+label {
      background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
      background-repeat: no-repeat;
      background-position: center left;
      background-size: 30px;
    }
    .toggle:checked+label {
      background-size: 30px;
      background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
    }
    label {
      word-break: break-all;
      padding: 10px 10px 10px 45px;
      display: block;
      line-height: 1.0;
      transition: color 0.4s;
    }
    /* 选项名称 */
    .subject-option-prefix {
      font-size: 16px;
      display: inline-block
    }
  }
}
.subject-answer {
  padding: 16px;
}
src/assets/css/transition.scss
New file
@@ -0,0 +1,12 @@
.fade-transform-leave-active,
.fade-transform-enter-active {
  transition: all .5s;
}
.fade-transform-enter {
  opacity: 0;
  transform: translateY(30px);
}
.fade-transform-leave-to {
  opacity: 0;
  transform: translateY(30px);
}
src/components/Subjects/Choices/index.vue
New file
@@ -0,0 +1,89 @@
<template>
    <div>
        <div class="subject-content">
            <div class="subject-title">
                {{ index }}
                <span class="subject-title-content"
                      v-html="subjectInfo.subjectName" />
                <span class="subject-title-content">
                    (&nbsp;单选题&nbsp;<span v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;{{subjectInfo.score}}分&nbsp;</span>)
                </span>
            </div>
            <ul class="subject-options"
                v-for="option in options"
                :key="option.id">
                <li class="subject-option">
                    <input class="toggle"
                           type="checkbox"
                           :checked="userAnswer === option.optionName"
                           :id="'option' + option.id"
                           @change="toggleOption(option)">
                    <label :for="'option' + option.id">
                        <span class="subject-option-prefix">{{ option.optionName + '.' }}&nbsp;</span>
                        <span v-html="option.optionContent"
                              class="subject-option-prefix" />
                    </label>
                </li>
            </ul>
        </div>
    </div>
</template>
<script>
export default {
    name: 'Choices',
    data () {
        return {
            subjectCount: 0,
            subjectInfo: {
                subjectName: '',
                score: 0
            },
            options: [],
            userAnswer: '',
            index: ''
        }
    },
    methods: {
        getAnswer () {
            return this.userAnswer
        },
        setAnswer (answer) {
            this.userAnswer = answer
        },
        setSubjectInfo (subject, subjectCount, index) {
            this.subjectCount = subjectCount
            this.subjectInfo = subject
            if (subject.hasOwnProperty('examSubjectOptions')) {
                this.options = subject.examSubjectOptions
                console.log(this.options)
            }
            if (subject.hasOwnProperty('answer')) {
                console.log(subject.answer);
                this.setAnswer(subject.answer)
            }
            this.index = index + '.'
            console.log(subject, subjectCount, index, this.options, 5656565656)
        },
        getSubjectInfo () {
            this.subjectInfo.options = this.options
            return this.subjectInfo
        },
        // 选中选项
        toggleOption (option) {
            this.userAnswer = option.optionName
        }
    }
}
</script>
<style lang="scss" scoped>
@import '../../../assets/css/subject.scss';
.subject-options > li label {
    height: 36px;
    line-height: 28px !important;
}
</style>
src/components/Subjects/Judgement/index.vue
New file
@@ -0,0 +1,81 @@
<template>
    <div>
        <div class="subject-content">
            <div class="subject-title">
                {{ index }}
                <span class="subject-title-content"
                      v-html="subjectInfo.subjectName" />
                <span class="subject-title-content">
                    (&nbsp;判断题&nbsp;<span v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;{{subjectInfo.score}}分&nbsp;</span>)
                </span>
            </div>
            <ul class="subject-options"
                v-for="option in options"
                :key="option.id">
                <li class="subject-option">
                    <input class="toggle"
                           type="checkbox"
                           :checked="userAnswer === option.optionName"
                           :id="'option' + option.id"
                           @change="toggleOption(option)">
                    <label :for="'option' + option.id">
                        <span class="subject-option-prefix">{{ option.optionName }}&nbsp;</span>
                    </label>
                </li>
            </ul>
        </div>
    </div>
</template>
<script>
export default {
    name: 'Judgement',
    data () {
        return {
            subjectCount: 0,
            subjectInfo: {
                subjectName: '',
                score: 0
            },
            options: [
                { id: 1, optionName: '正确' },
                { id: 2, optionName: '错误' }
            ],
            userAnswer: '',
            index: ''
        }
    },
    methods: {
        getAnswer () {
            return this.userAnswer
        },
        setAnswer (answer) {
            this.userAnswer = answer
        },
        setSubjectInfo (subject, subjectCount, index) {
            this.subjectCount = subjectCount
            this.subjectInfo = subject
            if (subject.hasOwnProperty('answer')) {
                this.setAnswer(subject.answer)
            }
            this.index = index + '.'
        },
        getSubjectInfo () {
            this.subjectInfo.options = this.options
            return this.subjectInfo
        },
        // 选中选项
        toggleOption (option) {
            this.userAnswer = option.optionName
        }
    }
}
</script>
<style lang="scss" scoped>
@import '../../../assets/css/subject.scss';
.subject-options > li label {
    height: 36px;
    line-height: 28px !important;
}
</style>
src/components/Subjects/MultipleChoices/index.vue
New file
@@ -0,0 +1,99 @@
<template>
    <div>
        <div class="subject-content">
            <div class="subject-title">
                {{ index }}
                <span class="subject-title-content"
                      v-html="subjectInfo.subjectName" />
                <span class="subject-title-content">
                    (&nbsp;多选题&nbsp;<span v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;{{subjectInfo.score}}分&nbsp;</span>)
                </span>
            </div>
            <ul class="subject-options"
                v-for="option in options"
                :key="option.id">
                <li class="subject-option">
                    <input class="toggle"
                           type="checkbox"
                           :checked="isChecked(option.optionName)"
                           :id="'option' + option.id"
                           @change="toggleOption($event, option)">
                    <label :for="'option' + option.id">
                        <span class="subject-option-prefix">{{ option.optionName + '.' }}&nbsp;</span>
                        <span v-html="option.optionContent"
                              class="subject-option-prefix" />
                    </label>
                </li>
            </ul>
        </div>
    </div>
</template>
<script>
export default {
    name: 'MultipleChoices',
    data () {
        return {
            subjectCount: 0,
            subjectInfo: {
                subjectName: '',
                score: 0
            },
            options: [],
            userAnswer: [],
            index: ''
        }
    },
    watch: {
    },
    methods: {
        getAnswer () {
            return this.userAnswer.join(',')
        },
        setAnswer (answer) {
            // if (isNotEmpty(answer)) {
            this.userAnswer = answer.split(',')
            // }
        },
        setSubjectInfo (subject, subjectCount, index) {
            this.subjectCount = subjectCount
            this.subjectInfo = subject
            if (subject.hasOwnProperty('examSubjectOptions')) {
                this.options = subject.examSubjectOptions
            }
            if (subject.hasOwnProperty('answer')) {
                this.setAnswer(subject.answer)
            }
            this.index = index + '.'
        },
        getSubjectInfo () {
            this.subjectInfo.options = this.options
            return this.subjectInfo
        },
        // 选中选项
        toggleOption ($event, option) {
            if ($event.target.checked) {
                if (!this.userAnswer.includes(option.optionName)) {
                    this.userAnswer.push(option.optionName)
                }
            } else {
                this.userAnswer.splice(this.userAnswer.findIndex(item => item === option.optionName), 1)
            }
        },
        isChecked (optionName) {
            return this.userAnswer.includes(optionName)
        }
    }
}
</script>
<style lang="scss" scoped>
@import '../../../assets/css/subject.scss';
.subject-options > li label {
    height: 36px;
    line-height: 28px !important;
}
</style>
src/components/Subjects/PracticalOperation/index.vue
New file
@@ -0,0 +1,190 @@
<template>
    <div>
        <div class="subject-content">
            <div class="subject-title">
                {{ index }}
                <span class="subject-title-content"
                      v-html="subjectInfo.subjectName" />
                <span class="subject-title-content">
                    (&nbsp;实操题&nbsp;<span v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;{{subjectInfo.score}}分&nbsp;</span>)
                </span>
            </div>
            <ul class="subject-options"
                v-for="(option, index) in options"
                :key="option.id">
                <li class="subject-option pbox">
                    <span class="num"
                          @click="selectCheckbox($event, option)"> {{ userAnswer[index].value }} </span>
                    <label :for="'option' + option.id">
                        <span class="subject-option-prefix">{{ option.optionName + '.' }}&nbsp;</span>
                        <span v-html="option.optionContent"
                              class="subject-option-prefix" />
                    </label>
                </li>
            </ul>
        </div>
    </div>
</template>
<script>
export default {
    name: 'MultipleChoices',
    data () {
        return {
            subjectCount: 0,
            subjectInfo: {
                subjectName: '',
                score: 0
            },
            options: [],
            userAnswer: [],
            index: ''
        }
    },
    watch: {
    },
    methods: {
        getAnswer () {
            return this.userAnswer
        },
        setAnswer (answer, option) {
            console.log(answer);
            if (answer != '') {
                this.userAnswer = answer
            } else {
                this.userAnswer = []
                option.forEach(item => {
                    this.userAnswer.push({ key: item.optionName, value: '' })
                })
            }
        },
        setSubjectInfo (subject, subjectCount, index) {
            this.subjectCount = subjectCount
            this.subjectInfo = subject
            if (subject.hasOwnProperty('examSubjectOptions')) {
                this.options = subject.examSubjectOptions
            }
            if (subject.hasOwnProperty('answer')) {
                this.setAnswer(subject.answer, subject.examSubjectOptions)
            }
            this.index = index + '.'
        },
        getSubjectInfo () {
            this.subjectInfo.options = this.options
            return this.subjectInfo
        },
        selectCheckbox ($event, option) {
            var flag = false;
            this.userAnswer.forEach(item => {
                if (item.value != "") {
                    flag = true
                }
            })
            this.userAnswer
            if (flag == true) {
                // 其中最少有一个有值的
                var onlyFlag = false;
                var onlyValue = '';
                var ind = 0;
                this.userAnswer.forEach(item => {
                    if (item.value != '' && item.value > ind) {
                        ind = item.value
                    }
                })
                this.userAnswer.forEach(item => {
                    if (item.key == option.optionName) {
                        if (item.value != '') {
                            onlyValue = item.value
                            onlyFlag = true
                            item.value = ''
                        } else {
                            item.value = ind + 1
                        }
                    }
                })
                this.userAnswer.forEach(item => {
                    if (onlyFlag == true) {
                        if (item.value > onlyValue) {
                            item.value -= 1
                        }
                    }
                })
            } else {
                // 全部都为空
                this.userAnswer.forEach(item => {
                    if (item.key == option.optionName) {
                        item.value = 1
                    }
                })
            }
            console.log(this.userAnswer)
        },
        isChecked (optionName) {
            return this.userAnswer.includes(optionName)
        }
    }
}
</script>
<style lang="scss" scoped>
@import '../../../assets/css/subject.scss';
.pbox .num {
    // margin: 2px;
    // text-align: center;
    // vertical-align: middle;
    // display: inline-block;
    // width: 20px;
    // height: 20px;
    // border: 1px solid #999;
    width: 26px;
    height: 26px;
    position: absolute;
    top: 0;
    bottom: 0;
    margin: auto 0;
    // opacity: 0;
    text-align: center;
    font-size: 18px;
    font-weight: bold;
    border: 1px solid #cfcfcf;
    background-color: #ff9;
    cursor: pointer;
}
.subject-options > li label {
    height: 36px;
    line-height: 28px !important;
}
.pbox.checked {
    border: 1px solid #99f;
    background-color: #ccf;
}
.pbox.checked .num {
    border: 1px solid #ff0;
    background-color: #ff9;
}
</style>
src/components/Subjects/ShortAnswer/index.vue
New file
@@ -0,0 +1,73 @@
<template>
  <div>
    <div class="subject-content">
      <div class="subject-title">
        {{ index }}
        <span class="subject-title-content" v-html="subjectInfo.subjectName"/>
        <span class="subject-title-content" v-if="subjectInfo.score !== undefined && subjectInfo.score !== 0">&nbsp;({{subjectInfo.score}})分</span>
        <div class="subject-tinymce">
          <tinymce ref="editor" :height="height" v-model="userAnswer"/>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import Tinymce from '@/components/Tinymce'
export default {
  name: 'ShortAnswer',
  components: {
    Tinymce
  },
  props: {
    height: {
      type: Number,
      required: false,
      default: 300
    }
  },
  data () {
    return {
      subjectCount: 0,
      subjectInfo: {
        subjectName: '',
        score: 0
      },
      userAnswer: '',
      index: ''
    }
  },
  methods: {
    getAnswer () {
      return this.userAnswer
    },
    setAnswer (answer) {
      this.userAnswer = answer
    },
    setSubjectInfo (subject, subjectCount, index) {
      this.subjectCount = subjectCount
      this.subjectInfo = subject
      if (subject.hasOwnProperty('answer')) {
        this.setAnswer(subject.answer.answer)
      }
      this.index = index + '.'
    },
    getSubjectInfo () {
      return this.subjectInfo
    }
  }
}
</script>
<style lang="scss" scoped>
  @import "../../../assets/css/subject.scss";
  .subject-tinymce {
    margin: 12px;
  }
  .subject-options > li label {
    height: 36px;
    line-height: 28px !important;
}
</style>
src/components/Tinymce/components/editorImage.vue
New file
@@ -0,0 +1,103 @@
<template>
  <div class="upload-container">
    <el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">上传图片
    </el-button>
    <el-dialog :visible.sync="dialogVisible">
      <el-upload
        :multiple="true"
        :file-list="fileList"
        :show-file-list="true"
        :on-remove="handleRemove"
        :on-success="handleSuccess"
        :before-upload="beforeUpload"
        class="editor-slide-upload"
        action="https://httpbin.org/post"
        list-type="picture-card">
        <el-button size="small" type="primary">点击上传</el-button>
      </el-upload>
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="handleSubmit">确 定</el-button>
    </el-dialog>
  </div>
</template>
<script>
// import { getToken } from 'api/qiniu'
export default {
  name: 'EditorSlideUpload',
  props: {
    color: {
      type: String,
      default: '#1890ff'
    }
  },
  data () {
    return {
      dialogVisible: false,
      listObj: {},
      fileList: []
    }
  },
  methods: {
    checkAllSuccess () {
      return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
    },
    handleSubmit () {
      const arr = Object.keys(this.listObj).map(v => this.listObj[v])
      if (!this.checkAllSuccess()) {
        this.$message('请等待所有图片上传成功 或 出现了网络问题,请刷新页面重新上传!')
        return
      }
      this.$emit('successCBK', arr)
      this.listObj = {}
      this.fileList = []
      this.dialogVisible = false
    },
    handleSuccess (response, file) {
      const uid = file.uid
      const objKeyArr = Object.keys(this.listObj)
      for (let i = 0, len = objKeyArr.length; i < len; i++) {
        if (this.listObj[objKeyArr[i]].uid === uid) {
          this.listObj[objKeyArr[i]].url = response.files.file
          this.listObj[objKeyArr[i]].hasSuccess = true
          return
        }
      }
    },
    handleRemove (file) {
      const uid = file.uid
      const objKeyArr = Object.keys(this.listObj)
      for (let i = 0, len = objKeyArr.length; i < len; i++) {
        if (this.listObj[objKeyArr[i]].uid === uid) {
          delete this.listObj[objKeyArr[i]]
          return
        }
      }
    },
    beforeUpload (file) {
      const _self = this
      const _URL = window.URL || window.webkitURL
      const fileName = file.uid
      this.listObj[fileName] = {}
      return new Promise((resolve, reject) => {
        const img = new Image()
        img.src = _URL.createObjectURL(file)
        img.onload = function () {
          _self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
        }
        resolve(true)
      })
    }
  }
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.editor-slide-upload {
  margin-bottom: 20px;
  /deep/ .el-upload--picture-card {
    width: 100%;
  }
}
</style>
src/components/Tinymce/index.vue
New file
@@ -0,0 +1,162 @@
<template>
  <div :class="{fullscreen:fullscreen}" class="tinymce-container editor-container">
    <textarea :id="tinymceId" class="tinymce-textarea"/>
  </div>
</template>
<script>
import editorImage from './components/editorImage'
import plugins from './plugins'
import toolbar from './toolbar'
export default {
  name: 'Tinymce',
  components: { editorImage },
  props: {
    id: {
      type: String,
      default: function () {
        return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
      }
    },
    value: {
      type: String,
      default: ''
    },
    toolbar: {
      type: Array,
      required: false,
      default () {
        return []
      }
    },
    menubar: {
      type: String,
      default: 'file edit insert view format table'
    },
    height: {
      type: Number,
      required: false,
      default: 360
    }
  },
  data () {
    return {
      hasChange: false,
      hasInit: false,
      tinymceId: this.id,
      fullscreen: false,
      languageTypeList: {
        'en': 'en',
        'zh': 'zh_CN'
      }
    }
  },
  computed: {
    language () {
      return this.languageTypeList['zh']
    }
  },
  watch: {
    value (val) {
      if (!this.hasChange && this.hasInit) {
        this.$nextTick(() =>
          window.tinymce.get(this.tinymceId).setContent(val || ''))
      }
    },
    language () {
      this.destroyTinymce()
      this.$nextTick(() => this.initTinymce())
    }
  },
  mounted () {
    this.initTinymce()
  },
  activated () {
    this.initTinymce()
  },
  deactivated () {
    this.destroyTinymce()
  },
  destroyed () {
    this.destroyTinymce()
  },
  methods: {
    initTinymce () {
      const _this = this
      window.tinymce.init({
        language: this.language,
        selector: `#${this.tinymceId}`,
        height: this.height,
        body_class: 'panel-body ',
        object_resizing: false,
        toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
        menubar: this.menubar,
        plugins: plugins,
        end_container_on_empty_block: true,
        powerpaste_word_import: 'clean',
        code_dialog_height: 450,
        code_dialog_width: 1000,
        advlist_bullet_styles: 'square',
        advlist_number_styles: 'default',
        imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
        default_link_target: '_blank',
        link_title: false,
        nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
        init_instance_callback: editor => {
          if (_this.value) {
            editor.setContent(_this.value)
          }
          _this.hasInit = true
          editor.on('NodeChange Change KeyUp SetContent', () => {
            this.hasChange = true
            this.$emit('input', editor.getContent())
          })
        },
        setup (editor) {
          editor.on('FullscreenStateChanged', (e) => {
            _this.fullscreen = e.state
          })
        }
      })
    },
    destroyTinymce () {
      if (window.tinymce.get(this.tinymceId)) {
        window.tinymce.get(this.tinymceId).destroy()
      }
    },
    setContent (value) {
      window.tinymce.get(this.tinymceId).setContent(value)
    },
    getContent () {
      return window.tinymce.get(this.tinymceId).getContent()
    }
  }
}
</script>
<style scoped>
.tinymce-container {
  position: relative;
}
.tinymce-container>>>.mce-fullscreen {
  z-index: 10000;
}
.tinymce-textarea {
  visibility: hidden;
  z-index: -1;
}
.editor-custom-btn-container {
  position: absolute;
  right: 4px;
  top: 4px;
  /*z-index: 2005;*/
}
.fullscreen .editor-custom-btn-container {
  z-index: 10000;
  position: fixed;
}
.editor-upload-btn {
  display: inline-block;
}
</style>
src/components/Tinymce/plugins.js
New file
@@ -0,0 +1,7 @@
// Any plugins you want to use has to be imported
// Detail plugins list see https://www.tinymce.com/docs/plugins/
// Custom builds see https://www.tinymce.com/download/custom-builds/
const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
export default plugins
src/components/Tinymce/toolbar.js
New file
@@ -0,0 +1,6 @@
// Here is a list of the toolbar
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
const toolbar = ['bold italic underline strikethrough alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
export default toolbar
src/config/env.js
@@ -1,5 +1,5 @@
// 阿里矢量图标库配置
let iconfontVersion = ['567566_pwc3oottzol'];
let iconfontVersion = ['567566_pwc3oottzol', '2680691_r9wggg2tnk'];
let iconfontUrl = `//at.alicdn.com/t/font_$key.css`;
let baseUrl = '';
src/config/iconList.js
@@ -66,6 +66,17 @@
      "iconfont iconicon_add",
      "iconfont icongithub",
      "iconfont icongitee2",
      "iconfont icon-baoming",
      "iconfont icon-tiku",
      "iconfont icon-duoxiaoliankaokaowuguanli",
      "iconfont icon-kaoshi",
      "iconfont icon-shijuan",
      "iconfont icon-chengji",
    ]
  },
  {
src/const/constant.js
New file
@@ -0,0 +1,10 @@
export const nextSubjectType = {
  last: 1,
  next: 0,
  current: 2
}
export const answerType = {
  'true': 'right',
  'false': 'incorrect'
}
src/const/errorCode.js
New file
@@ -0,0 +1,12 @@
export default {
  '478': '验证码错误,请重新输入',
  '479': '验证码已过期,请重新输入',
  '401': '当前操作没有权限',
  '403': '当前操作没有权限',
  '400': '用户名不存在或密码错误',
  '500': '服务器内部错误,请反馈给管理员',
  '4015': '服务不可用',
  '4020': '验证码错误',
  '4026': '验证码已过期,请重新获取',
  'default': '系统未知错误,请反馈给管理员'
}
src/store/modules/common.js
@@ -8,13 +8,13 @@
const common = {
  state: {
    language: getStore({name: 'language'}) || 'zh',
    language: getStore({ name: 'language' }) || 'zh',
    isCollapse: false,
    isFullScren: false,
    isMenu: true,
    isShade: false,
    screen: -1,
    isLock: getStore({name: 'isLock'}) || false,
    isLock: getStore({ name: 'isLock' }) || false,
    showTag: true,
    showDebug: true,
    showCollapse: true,
@@ -24,9 +24,9 @@
    showTheme: true,
    showMenu: true,
    showColor: true,
    colorName: getStore({name: 'colorName'}) || '#409EFF',
    themeName: getStore({name: 'themeName'}) || 'theme-default',
    lockPasswd: getStore({name: 'lockPasswd'}) || '',
    colorName: getStore({ name: 'colorName' }) || '#409EFF',
    themeName: getStore({ name: 'themeName' }) || 'theme-bule',
    lockPasswd: getStore({ name: 'lockPasswd' }) || '',
    website: website,
  },
  mutations: {
src/styles/element-ui.scss
@@ -25,7 +25,6 @@
  display: none;
}
.el-message__icon,
.el-message__content {
  display: inline-block;
@@ -49,12 +48,19 @@
  padding: 0 !important;
}
.el-dropdown-menu__item--divided:before, .el-menu, .el-menu--horizontal > .el-menu-item:not(.is-disabled):focus, .el-menu--horizontal > .el-menu-item:not(.is-disabled):hover, .el-menu--horizontal > .el-submenu .el-submenu__title:hover {
.el-dropdown-menu__item--divided:before,
.el-menu,
.el-menu--horizontal > .el-menu-item:not(.is-disabled):focus,
.el-menu--horizontal > .el-menu-item:not(.is-disabled):hover,
.el-menu--horizontal > .el-submenu .el-submenu__title:hover {
  background-color: transparent;
}
.el-dropdown-menu__item--divided:before, .el-menu, .el-menu--horizontal > .el-menu-item:not(.is-disabled):focus, .el-menu--horizontal > .el-menu-item:not(.is-disabled):hover, .el-menu--horizontal > .el-submenu .el-submenu__title:hover {
.el-dropdown-menu__item--divided:before,
.el-menu,
.el-menu--horizontal > .el-menu-item:not(.is-disabled):focus,
.el-menu--horizontal > .el-menu-item:not(.is-disabled):hover,
.el-menu--horizontal > .el-submenu .el-submenu__title:hover {
  background-color: transparent !important;
}
@@ -69,3 +75,130 @@
.el-divider--horizontal {
  margin: 12px 0 !important;
}
//表格斑马纹
.el-table tr:nth-child(2n -1) {
  // background-color: rgba($color: #000000, $alpha: 0.1) !important;
}
//顶部搜索栏
.el-card.is-never-shadow.avue-crud__search {
  position: absolute !important;
  width: calc(100% - 220px) !important;
  z-index: 500 !important;
  border: none !important;
  box-shadow: none !important;
  height: 40px;
}
//取消顶部搜索栏
.user .el-card.is-never-shadow.avue-crud__search {
  position: relative !important;
  width: auto !important;
  z-index: 500 !important;
  border: none !important;
  box-shadow: none !important;
  height: auto;
}
.desk .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 360px) !important;
}
.securityGuard .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 300px) !important;
  left: 120px;
}
.securityUnit .el-card.is-never-shadow.avue-crud__search {
  left: 200px;
  width: calc(100% - 380px) !important;
}
.equipments .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 380px) !important;
  left: 200px;
}
.dispatch .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 380px) !important;
  left: 200px;
}
.dispatchChildoperable .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 280px) !important;
  left: 90px;
}
.workreply .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 380px) !important;
  left: 200px !important;
}
.recruitmentManagement .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 380px) !important;
  left: 200px !important;
}
.hasButOne .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 300px) !important;
  left: 120px !important;
}
.hasButTwo .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 380px) !important;
  left: 200px !important;
}
.topmenu .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 390px) !important;
  left: 220px !important;
}
.hasButThree .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 510px) !important;
  left: 310px !important;
}
.avue-form {
  position: relative;
  top: -10px;
}
//顶部按钮栏
.avue-crud__menu {
  height: 60px;
}
//顶部按钮
.avue-crud .avue-crud__left .el-button,
.avue-crud .avue-crud__right .el-button,
.avue-form .avue-crud__left .el-button,
.avue-form .avue-crud__right .el-button {
  position: relative;
  top: 5px;
}
//左侧导航栏
.avue-logo {
  background-color: #409eff !important;
  color: #fff !important;
}
.avue-sidebar {
  background-color: #fff !important;
}
.avue-header {
  background-color: #409eff !important;
  color: #fff !important;
}
.avue-sidebar .el-menu-item span,
.avue-sidebar .el-submenu__title span,
.avue-sidebar .el-submenu__title i,
.avue-sidebar .el-menu-item i {
  color: #000 !important;
}
// 菜单 活动背景
.avue-sidebar .el-menu-item.is-active {
  background-color: #409eff !important;
}
.avue-sidebar .el-menu-item.is-active span,
.el-menu-item.is-active i {
  color: #fff !important;
}
//top 导航 按钮
.el-menu--horizontal > .el-menu-item.is-active,
.avue-top,
.el-dropdown {
  color: #fff !important;
}
src/views/applyexam/index.vue
New file
@@ -0,0 +1,461 @@
/*
 * @Author: Morpheus
 * @Date: 2021-07-05 16:31:54
 * @Last Modified by: Morpheus
 * @Last Modified time: 2021-07-19 19:39:45
 * menu-name 报名考试
 */
<template>
    <el-row class="morpheus-box">
        <el-col :span="24">
            <el-card>
                <div class="exam-card-body">
                    <avue-crud v-model="obj"
                               class="company-box"
                               :option="questionBankOption"
                               :search.sync="questionBankSearch"
                               :table-loading="questionBankLoading"
                               :data="questionBankData"
                               ref="questionBankCrud"
                               :page.sync="questionBankPage"
                               @on-load="questionBankOnLoad"
                               @selection-change="questionBankSelectionChange"
                               @search-change="questionBankSearchChange"
                               @search-reset="questionBankSearchReset"
                               @current-change="questionBankCurrentChange"
                               @size-change="questionBankSizeChange"
                               @row-save="questionBankRowSave"
                               @row-del="questionBankRowDel">
                        <!-- 自定义按钮 -->
                        <!-- <template slot="menuLeft">
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">新增
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">删除
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">导出
                            </el-button>
                        </template> -->
                        <template slot="menuLeft">
                            <el-button type="danger"
                                       size="small"
                                       icon="el-icon-delete"
                                       @click="questionBankHandleDelete">删 除
                            </el-button>
                        </template>
                    </avue-crud>
                </div>
            </el-card>
        </el-col>
    </el-row>
</template>
<script>
import {
    getApplyList,
    addApply,
    remove
} from "@/api/examapi/applyexam";
import { mapState } from 'vuex'
export default {
    data () {
        return {
            obj: {
                name: '张三',
            },
            questionBankOption: {
                // 操作栏多余按钮去除
                delBtn: true,
                editBtn: false,
                addBtn: true,
                selection: true,
                menu: true,
                // 导出按钮
                excelBtn: true,
                viewBtn: false,
                // title: '题库',
                align: 'center',
                height: 'auto',
                calcHeight: 80,
                tip: false,
                searchShow: true,
                searchMenuSpan: 4,
                index: true,
                indexLabel: '序号',
                //dialogType: 'drawer',
                dialogClickModal: false,
                // 操作栏宽度
                menuWidth: 286,
                column: [
                    {
                        label: "保安姓名",
                        prop: "name",
                        type: 'tree',
                        dicUrl: '',
                        search: true,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        props: {
                            label: "title",
                            value: "id",
                        },
                        rules: [{
                            required: true,
                            message: "请选择保安姓名",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "试卷名称",
                        prop: "examName",
                        type: 'tree',
                        dicUrl: '/api/exampaper/page-tree',
                        // search: true,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        props: {
                            label: "examName",
                            value: "id",
                        },
                        rules: [{
                            required: true,
                            message: "请选择试卷名称",
                            trigger: "blur"
                        }],
                        width: 220
                    },
                    {
                        label: "所属公司",
                        prop: "deptName",
                        search: true,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请选择所属公司",
                            trigger: "blur"
                        }],
                        width: 220
                    },
                    {
                        label: "准考证号",
                        prop: "candidateNo",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请选择准考证号",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "试卷分数",
                        prop: "paperScore",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false
                    },
                    {
                        label: "报名时间",
                        prop: "applyTime",
                        type: "datetime",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        // 表单新增时是否禁止
                        addDisabled: true,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        value: (new Date().getFullYear() + '-' + (new Date().getMonth() + 1 < 10
                            ? "0" + (new Date().getMonth() + 1)
                            : new Date().getMonth() + 1) + '-' + (new Date().getDate() < 10
                                ? "0" + new Date().getDate()
                                : new Date().getDate()) + ' ' + (new Date().getHours() < 10
                                    ? "0" + new Date().getHours()
                                    : new Date().getHours()) + ':' + (new Date().getMinutes() < 10
                                        ? "0" + new Date().getMinutes()
                                        : new Date().getMinutes()) + ':' + (new Date().getSeconds() < 10
                                            ? "0" + new Date().getSeconds()
                                            : new Date().getSeconds())),
                        width: 250
                    },
                    {
                        label: "考试时间",
                        prop: "examTime",
                        type: "datetime",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        width: 250
                    }
                ]
            },
            questionBankSearch: {},
            questionBankLoading: true,
            questionBankData: [
            ],
            questionBankPage: {
                pageSize: 10,
                currentPage: 1,
                total: 16
            },
            questionBankQuery: {},
            questionBankSelectionList: [],
        }
    },
    watch: {
        "form.examname": {
            // form是表单或者表格绑定的数据集,v-model='form'
            handler (val) {
                if (val) {
                    //地址截取,从县/区开始截取,并且取从县区第一个出现的位置开始
                    var address = val.formattedAddress.toString();
                    if (address.search("县") != -1) {
                        this.form.address = address.substring(
                            address.indexOf("县") + 1,
                            address.length
                        );
                    }
                    if (address.search("区") != -1) {
                        this.form.address = address.substring(
                            address.indexOf("区") + 1,
                            address.length
                        );
                    }
                }
            },
            immediate: true,
        },
    },
    created () {
      console.log(this.userInfo)
      if (this.userInfo.role_name.indexOf('ksxtadmin') != -1) {
        this.questionBankOption.column[0].dicUrl = "/api/blade-system/dept/lazy-tree-user?parentId="
      } else {
        this.questionBankOption.column[0].dicUrl = "/api/blade-system/dept/lazy-tree-user?parentId=" + this.userInfo.dept_id
      }
    },
    mounted () {
    },
    computed: {
        ...mapState({
            userInfo: state => state.user.userInfo
        }),
        ids () {
            let ids = [];
            this.questionBankSelectionList.forEach(ele => {
                ids.push(ele.id);
            });
            return ids.join(",");
        },
    },
    methods: {
        questionBankOnLoad (page, params = {}) {
            this.questionBankLoading = false;
            getApplyList(page.currentPage, page.pageSize, Object.assign(params, this.questionBankQuery)).then(res => {
                const data = res.data.data;
                this.questionBankPage.total = data.total;
                this.questionBankData = data.records;
                this.questionBankLoading = false;
                this.questionBankSelectionClear();
            });
        },
        questionBankSelectionClear () {
            this.questionBankSelectionList = [];
            this.$refs.questionBankCrud.toggleSelection();
        },
        questionBankSelectionChange (list) {
            this.questionBankSelectionList = list;
        },
        questionBankSearchChange (params, done) {
            this.questionBankQuery = params;
            this.questionBankPage.currentPage = 1;
            this.questionBankOnLoad(this.questionBankPage, params);
            done();
        },
        questionBankSearchReset () {
            this.questionBankQuery = {};
            this.questionBankOnLoad(this.questionBankPage);
        },
        questionBankCurrentChange (currentPage) {
            this.questionBankPage.currentPage = currentPage;
        },
        questionBankSizeChange (pageSize) {
            this.questionBankPage.pageSize = pageSize;
        },
        // 新增
        questionBankRowSave (row, done, loading) {
            addApply({ userId: row.name, examId: row.examName, applyTime: row.applyTime }).then(() => {
                this.questionBankOnLoad(this.questionBankPage);
                this.$message({
                    type: "success",
                    message: "操作成功!"
                });
                done();
            }, error => {
                window.console.log(error);
                loading();
            });
        },
        questionBankRowDel (row) {
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(row.id);
                })
                .then(() => {
                    this.questionBankOnLoad(this.questionBankPage);
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    });
                });
        },
        questionBankHandleDelete () {
            if (this.questionBankSelectionList.length === 0) {
                this.$message.warning("请选择至少一条数据");
                return;
            }
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(this.ids);
                })
                .then(() => {
                    this.questionBankOnLoad(this.questionBankPage);
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    });
                    this.$refs.questionBankCrud.toggleSelection();
                });
        },
    }
}
</script>
<style lang="scss" scoped>
</style>
src/views/authority/role.vue
@@ -1,5 +1,5 @@
<template>
  <basic-container>
  <basic-container class="hasButThree">
    <avue-crud
      :option="option"
      :table-loading="loading"
src/views/desk/notice.vue
@@ -1,5 +1,5 @@
<template>
  <basic-container>
  <basic-container class="desk">
    <avue-crud
      :option="option"
      :table-loading="loading"
src/views/dispatch/dispatch.vue
@@ -112,6 +112,7 @@
      option: {
        tip: false,
        // card: true,
        index: true,
        searchSize: "mini",
        searchMenuSpan: 6,
        height: 623,
src/views/dispatch/dispatchChildoperable.vue
@@ -81,6 +81,7 @@
export default {
  data() {
    let baseUrl = "https://cli.avuejs.com/api/area";
    return {
      // typeTABS: {}, //标签页
      // optionTABS: {
@@ -158,7 +159,7 @@
        // addBtn: false,
        // menuWidth: 160,
        align: "center",
        // selection: true,
        selection: true,
        column: [
          // 派遣服务公司登记
          // {
@@ -171,50 +172,73 @@
          //     // editDisplay: false,
          //     // addDisplay: false
          // },
          {
            label: "保安公司",
            prop: "deptId",
            labelWidth: 120,
            searchLabelWidth: 120,
            searchSpan: 4,
            dicUrl:
              "/api/blade-system/dept/security_lazy-tree?parentId=1413470343230877697",
            props: {
              label: "title",
              value: "id",
            },
            search: true,
            overHidden: true,
            type: "select",
            rules: [
              {
                required: true,
                message: "请输入保安公司",
                trigger: "blur",
              },
            ],
          },
          // {
          //   label: "保安公司",
          //   prop: "deptId",
          //   labelWidth: 120,
          //   searchLabelWidth: 120,
          //   searchSpan: 4,
          //   dicUrl:
          //     "/api/blade-system/dept/security_lazy-tree?parentId=1413470343230877697",
          //   props: {
          //     label: "title",
          //     value: "id",
          //   },
          //   search: true,
          //   overHidden: true,
          //   type: "select",
          //   rules: [
          //     {
          //       required: true,
          //       message: "请输入保安公司",
          //       trigger: "blur",
          //     },
          //   ],
          // },
          {
            label: "派遣单位",
            prop: "dispatcherCompany",
            addDisplay: false,
            editDisplay: false,
          },
          // {
          //   label: "派遣单位",
          //   prop: "dispatcherUnitId",
          //   labelWidth: 120,
          //   searchLabelWidth: 120,
          //   dicUrl: "/api/dispatcherUnit/page-tree",
          //   props: {
          //     label: "name",
          //     value: "id",
          //   },
          //   hide: true,
          //   searchSpan: 4,
          //   search: true,
          //   overHidden: true,
          //   type: "tree",
          //   rules: [
          //     {
          //       required: true,
          //       message: "请输入保安公司",
          //       trigger: "blur",
          //     },
          //   ],
          // },
          {
            label: "派遣单位",
            prop: "dispatcherUnitId",
            label: "保安公司",
            prop: "deptId",
            labelWidth: 120,
            searchLabelWidth: 120,
            dicUrl: "/api/dispatcherUnit/page-tree",
            props: {
              label: "name",
              value: "id",
            },
            hide: true,
            searchSpan: 4,
            search: true,
            overHidden: true,
            type: "tree",
            cascaderItem: ["name"],
            // cascaderItem: ["city", "area"],
            props: {
              label: "title",
              value: "id",
            },
            dicUrl: `/api/blade-system/dept/security_lazy-tree?parentId=1413470343230877697`,
            rules: [
              {
                required: true,
@@ -224,21 +248,66 @@
            ],
          },
          {
            label: "保安人名称",
            width: 120,
            label: "保安员",
            prop: "name",
            search: true,
            searchSpan: 4,
            labelWidth: 120,
            searchLabelWidth: 120,
            // overHidden: true
            type: "tree",
            cell: true,
            props: {
              label: "realName",
              value: "id",
            },
            dicUrl: `/api/blade-user/page-security-unit?deptId={{deptId}}`,
            rules: [
              {
                required: true,
                message: "请输入保安人名称",
                trigger: "click",
                message: "请选择保安",
                trigger: "blur",
              },
            ],
          },
          // {
          //   width: 120,
          //   label: "保安人名称",
          //   prop: "area",
          //   cell: true,
          //   props: {
          //     label: "name",
          //     value: "code",
          //   },
          //   type: "select",
          //   dicUrl: `${baseUrl}/getArea/{{key}}`,
          //   rules: [
          //     {
          //       required: true,
          //       message: "请选择地区",
          //       trigger: "blur",
          //     },
          //   ],
          // },
          // {
          //   label: "保安人名称",
          //   prop: "name",
          //   search: true,
          //   searchSpan: 4,
          //   labelWidth: 120,
          //   searchLabelWidth: 120,
          //   // overHidden: true
          //   type: "tree",
          //   dicUrl: "/api/blade-user/page-security",
          //   props: {
          //     label: "realName",
          //     value: "postId",
          //   },
          //   rules: [
          //     {
          //       required: true,
          //       message: "请输入保安人名称",
          //       trigger: "click",
          //     },
          //   ],
          // },
          {
            label: "身份证",
            prop: "cardid",
src/views/exam/examSubjects.vue
New file
@@ -0,0 +1,328 @@
/*
 * @Author: Morpheus
 * @Date: 2021-07-05 16:31:54
 * @Last Modified by: Morpheus
 * @Last Modified time: 2021-07-18 15:47:06
 * menu-name 题目管理
 */
<template>
    <el-row class="morpheus-box">
        <el-col :span="24">
            <el-card>
                <div class="exam-card-body">
                    <avue-crud v-model="obj"
                               class="company-box"
                               :option="questionBankOption"
                               :search.sync="questionBankSearch"
                               :table-loading="questionBankLoading"
                               :data="questionBankData"
                               ref="questionBankCrud"
                               :page.sync="questionBankPage"
                               @on-load="questionBankOnLoad"
                               @selection-change="questionBankSelectionChange"
                               @search-change="questionBankSearchChange"
                               @search-reset="questionBankSearchReset"
                               @current-change="questionBankCurrentChange"
                               @size-change="questionBankSizeChange"
                               @row-save="questionBankRowSave"
                               @row-update="questionBankRowUpdate"
                               @row-del="questionBankRowDel">
                        <!-- 自定义按钮 -->
                        <!-- <template slot="menuLeft">
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">新增
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">删除
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">导出
                            </el-button>
                        </template> -->
                        <template slot-scope="{row}"
                                  slot="examstate">
                            <el-tag>{{row.examstate == 0 ? '已发布' : '草稿'}}</el-tag>
                        </template>
                        <!-- <template slot="menu">
                            <el-button type="text"
                                       size="mini"
                                       icon="el-icon-delete"
                                       @click="questionBankHandleDel">删除
                            </el-button>
                        </template> -->
                    </avue-crud>
                </div>
            </el-card>
        </el-col>
    </el-row>
</template>
<script>
import {
    getPaperList,
    updatePaper,
    remove
} from "@/api/examapi/examSubjects";
export default {
    data () {
        var validatePass = (rule, value, callback) => {
            console.log(value)
            if (value == undefined || value == '') {
                callback(new Error('请输入分数'));
                return;
            } else if (value !== '' && isNaN(value) == true) {
                callback(new Error('请输入数字'));
            } else if (value <= 0) {
                callback(new Error('分数设置请大于0'));
            } else {
                callback();
            }
        };
        return {
            obj: {
                name: '张三',
            },
            questionBankOption: {
                // 操作栏多余按钮去除
                delBtn: true,
                editBtn: true,
                addBtn: false,
                selection: false,
                // 导出按钮
                excelBtn: false,
                viewBtn: false,
                align: 'center',
                height: 'auto',
                calcHeight: 80,
                tip: false,
                searchShow: true,
                searchMenuSpan: 4,
                index: true,
                  indexLabel: '序号',
                //dialogType: 'drawer',
                dialogClickModal: false,
                // 操作栏宽度
                menu: true,
                menuWidth: 180,
                column: [
                    {
                        label: "题目名称",
                        prop: "subjectName",
                        span: 24,
                        search: true,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        row: true,
                        rules: [{
                            required: true,
                            message: "请输入考试名称",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "题目类型",
                        prop: "choicesType",
                        type: "select",
                        search: true,
                        searchSpan: 4,
                        searchLabelWidth: 80,
                        value: 0,
                        dicData: [{
                            label: '单选题',
                            value: 0
                        }, {
                            label: '多选题',
                            value: 1,
                        }, {
                            label: '判断题',
                            value: 2,
                        }],
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        width: 106
                    },
                    {
                        label: "分值",
                        prop: "score",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
                        width: 106
                    }
                ]
            },
            questionBankSearch: {},
            questionBankLoading: true,
            questionBankData: [],
            questionBankPage: {
                pageSize: 10,
                currentPage: 1,
                total: 16
            },
            questionBankQuery: {},
            questionBankSelectionList: [],
        }
    },
    created () {
    },
    mounted () {
    },
    methods: {
        questionBankOnLoad (page, params = {}) {
            this.questionBankLoading = false;
            this.questionBankQuery.id = this.$route.query.id;
            getPaperList(page.currentPage, page.pageSize, Object.assign(params, this.questionBankQuery)).then(res => {
                const data = res.data.data;
                this.questionBankPage.total = data.total;
                this.questionBankData = data.records;
                this.questionBankLoading = false;
                this.questionBankSelectionClear();
            });
        },
        questionBankSelectionClear () {
            this.questionBankSelectionList = [];
            this.$refs.questionBankCrud.toggleSelection();
        },
        questionBankSelectionChange (list) {
            this.questionBankSelectionList = list;
        },
        questionBankSearchChange (params, done) {
            this.questionBankQuery = params;
            this.questionBankPage.currentPage = 1;
            this.questionBankOnLoad(this.questionBankPage, params);
            done();
        },
        questionBankSearchReset () {
            this.questionBankQuery = {};
            this.questionBankOnLoad(this.questionBankPage);
        },
        questionBankCurrentChange (currentPage) {
            this.questionBankPage.currentPage = currentPage;
        },
        questionBankSizeChange (pageSize) {
            this.questionBankPage.pageSize = pageSize;
        },
        questionBankRowDel (row) {
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove({ paperid: this.$route.query.id, subjectid: row.id });
                })
                .then(() => {
                    this.questionBankOnLoad(this.questionBankPage);
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    });
                });
        },
        questionBankRowSave (row, done, loading) {
            console.log(row, 898989);
            add(row).then(() => {
                this.initFlag = false;
                this.onLoad(this.page);
                this.$message({
                    type: "success",
                    message: "操作成功!"
                });
                done();
            }, error => {
                window.console.log(error);
                loading();
            });
        },
        questionBankRowUpdate (row, index, done, loading) {
            updatePaper({ value: row.score, id: row.id }).then(() => {
                this.questionBankOnLoad(this.questionBankPage);
                this.$message({
                    type: "success",
                    message: "操作成功!"
                });
                done();
            }, error => {
                window.console.log(error);
                loading();
            });
        },
    }
}
</script>
<style lang="scss" scoped>
</style>
src/views/exam/examination.vue
New file
@@ -0,0 +1,478 @@
/*
 * @Author: Morpheus
 * @Date: 2021-07-05 16:31:54
 * @Last Modified by: Morpheus
 * @Last Modified time: 2021-07-18 17:11:18
 * menu-name 试卷管理
 */
<template>
    <el-row class="morpheus-box">
        <el-col :span="24">
            <el-card>
                <div class="exam-card-body">
                    <avue-crud v-model="form"
                               class="company-box"
                               :option="questionBankOption"
                               :search.sync="questionBankSearch"
                               :table-loading="questionBankLoading"
                               :data="questionBankData"
                               ref="questionBankCrud"
                               :page.sync="questionBankPage"
                               @on-load="questionBankOnLoad"
                               @selection-change="questionBankSelectionChange"
                               @search-change="questionBankSearchChange"
                               @search-reset="questionBankSearchReset"
                               @current-change="questionBankCurrentChange"
                               @size-change="questionBankSizeChange"
                               @row-save="questionBankRowSave"
                               @row-update="questionBankRowUpdate"
                               @row-del="questionBankRowDel">
                        <!-- 自定义按钮 -->
                        <!-- <template slot="menuLeft">
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">新增
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">删除
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">导出
                            </el-button>
                        </template> -->
                        <template slot="menuLeft">
                            <el-button type="danger"
                                       size="small"
                                       icon="el-icon-delete"
                                       @click="questionBankHandleDelete">删 除
                            </el-button>
                        </template>
                        <template slot-scope="{row}"
                                  slot="examStatus">
                            <el-tag>{{row.examStatus == 0 ? '已发布' : '草稿'}}</el-tag>
                        </template>
                        <template slot-scope="{row}"
                                  slot="menu">
                            <el-button type="text"
                                       size="mini"
                                       icon="el-icon-document"
                                       @click="subjectManagement(row)">题目管理
                            </el-button>
                        </template>
                    </avue-crud>
                </div>
            </el-card>
        </el-col>
    </el-row>
</template>
<script>
import {
    getList,
    add,
    remove,
    update
} from "@/api/examapi/examination";
export default {
    data () {
        var validatePass = (rule, value, callback) => {
            console.log(value)
            if (value == undefined || value == '') {
                callback(new Error('请输入分数'));
                return;
            } else if (value !== '' && isNaN(value) == true) {
                callback(new Error('请输入数字'));
            } else if (value <= 0) {
                callback(new Error('分数设置请大于0'));
            } else {
                callback();
            }
        };
        return {
            form: {},
            questionBankOption: {
                // 操作栏多余按钮去除
                delBtn: true,
                editBtn: true,
                addBtn: true,
                selection: true,
                menu: true,
                // 导出按钮
                excelBtn: false,
                viewBtn: true,
                // title: '题库',
                align: 'center',
                height: 'auto',
                calcHeight: 80,
                tip: false,
                searchShow: true,
                searchMenuSpan: 4,
                index: true,
                indexLabel: '序号',
                //dialogType: 'drawer',
                dialogClickModal: false,
                // 操作栏宽度
                menuWidth: 284,
                labelWidth: 140,
                column: [
                    {
                        label: "试卷名称",
                        prop: "examName",
                        search: true,
                        searchSpan: 4,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入试卷名称",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "试卷分数",
                        prop: "totalScore",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
                        width: 100
                    },
                    {
                        label: "考试时间",
                        prop: "examTime",
                        type: "daterange",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        startPlaceholder: '考试开始时间',
                        endPlaceholder: '考试结束时间',
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        // display: false,
                        hide: true,
                        rules: [{
                            required: true,
                            message: "请选择考试时间",
                            trigger: "blur"
                        }],
                        width: 250
                    },
                    {
                        label: "考试开始时间",
                        prop: "startTime",
                        type: "datetime",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: false,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        width: 180
                    },
                    {
                        label: "考试结束时间",
                        prop: "endTime",
                        type: "datetime",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: false,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        width: 180
                    },
                    {
                        label: "创建人",
                        prop: "creator",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: true,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: false,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        hide: true,
                        display: false,
                    },
                    {
                        label: "备注",
                        prop: "remark",
                        span: 24,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false
                    },
                    {
                        label: "注意事项",
                        prop: "examAttention",
                        type: "textarea",
                        span: 24,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        width: 240
                    },
                ]
            },
            questionBankSearch: {},
            questionBankLoading: true,
            questionBankData: [
            ],
            questionBankPage: {
                pageSize: 10,
                currentPage: 1,
                total: 16
            },
            questionBankQuery: {},
            questionBankSelectionList: [],
        }
    },
    created () {
    },
    mounted () {
    },
    computed: {
        ids () {
            let ids = [];
            this.questionBankSelectionList.forEach(ele => {
                ids.push(ele.id);
            });
            return ids.join(",");
        },
    },
    watch: {
    },
    methods: {
        questionBankOnLoad (page, params = {}) {
            this.questionBankLoading = false;
            getList(page.currentPage, page.pageSize, Object.assign(params, this.questionBankQuery)).then(res => {
                const data = res.data.data;
                this.questionBankPage.total = data.total;
                this.questionBankData = data.records;
                this.questionBankLoading = false;
                this.questionBankSelectionClear();
            });
        },
        questionBankSelectionClear () {
            this.questionBankSelectionList = [];
            this.$refs.questionBankCrud.toggleSelection();
        },
        questionBankSelectionChange (list) {
            this.questionBankSelectionList = list;
        },
        questionBankSearchChange (params, done) {
            this.questionBankQuery = params;
            this.questionBankPage.currentPage = 1;
            this.questionBankOnLoad(this.questionBankPage, params);
            done();
        },
        questionBankSearchReset () {
            this.questionBankQuery = {};
            this.questionBankOnLoad(this.questionBankPage);
        },
        questionBankCurrentChange (currentPage) {
            this.questionBankPage.currentPage = currentPage;
        },
        questionBankSizeChange (pageSize) {
            this.questionBankPage.pageSize = pageSize;
        },
        // 新增
        questionBankRowSave (row, done, loading) {
            row.startTime = row.examTime[0]
            row.endTime = row.examTime[1]
            row.examTime = JSON.stringify(row.examTime)
            add(row).then(() => {
                this.questionBankOnLoad(this.questionBankPage);
                this.$message({
                    type: "success",
                    message: "操作成功!"
                });
                done();
            }, error => {
                window.console.log(error);
                loading();
            });
        },
        questionBankRowUpdate (row, index, done, loading) {
            if (Array.isArray(row.examTime) != true) {
                row.examTime = row.examTime.split(",")
            }
            row.startTime = row.examTime[0]
            row.endTime = row.examTime[1]
            row.examTime = JSON.stringify(row.examTime)
            update(row).then(() => {
                this.questionBankOnLoad(this.questionBankPage);
                this.$message({
                    type: "success",
                    message: "操作成功!"
                });
                done();
            }, error => {
                window.console.log(error);
                loading();
            });
        },
        questionBankRowDel (row) {
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(row.id);
                })
                .then(() => {
                    this.questionBankOnLoad(this.questionBankPage);
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    });
                });
        },
        questionBankHandleDelete () {
            if (this.questionBankSelectionList.length === 0) {
                this.$message.warning("请选择至少一条数据");
                return;
            }
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(this.ids);
                })
                .then(() => {
                    this.questionBankOnLoad(this.questionBankPage);
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    });
                    this.$refs.questionBankCrud.toggleSelection();
                });
        },
        subjectManagement (row) {
            this.$router.push({
                path: `/exam/subjects/${row.id}`,
                query: row
            })
        }
    }
}
</script>
<style lang="scss" scoped>
</style>
src/views/exam/performance.vue
New file
@@ -0,0 +1,398 @@
/*
 * @Author: Morpheus
 * @Date: 2021-07-05 16:31:54
 * @Last Modified by: Morpheus
 * @Last Modified time: 2021-07-18 19:44:47
 * menu-name 成绩管理
 */
<template>
    <el-row class="morpheus-box">
        <el-col :span="24">
            <el-card>
                <div class="exam-card-body">
                    <avue-crud v-model="obj"
                               class="company-box"
                               :option="questionBankOption"
                               :search.sync="questionBankSearch"
                               :table-loading="questionBankLoading"
                               :data="questionBankData"
                               ref="questionBankCrud"
                               :page.sync="questionBankPage"
                               @on-load="questionBankOnLoad"
                               @selection-change="questionBankSelectionChange"
                               @search-change="questionBankSearchChange"
                               @search-reset="questionBankSearchReset"
                               @current-change="questionBankCurrentChange"
                               @size-change="questionBankSizeChange"
                               @row-update="questionBankRowUpdate">
                        <template slot-scope="{ row }"
                                  slot="learnGrade">
                            {{ row.learnGrade == -1 ? "暂未录入" : row.learnGrade }}
                        </template>
                        <!-- 自定义按钮 -->
                        <!-- <template slot="menuLeft">
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">新增
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">删除
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">导出
                            </el-button>
                        </template> -->
                    </avue-crud>
                </div>
            </el-card>
        </el-col>
    </el-row>
</template>
<script>
import {
    getList,
    update
} from "@/api/examapi/performance";
export default {
    data () {
        var validatePass = (rule, value, callback) => {
            console.log(value)
            if (value == undefined || value == '') {
                callback(new Error('请输入实操成绩'));
                return;
            } else if (value !== '' && isNaN(value) == true) {
                callback(new Error('请输入数字'));
            } else if (value <= 0) {
                callback(new Error('分数设置请大于0'));
            } else if (value > 100) {
                callback(new Error('分数设置请小于100'));
            } else {
                callback();
            }
        };
        return {
            obj: {
                name: '张三',
            },
            questionBankOption: {
                // 操作栏多余按钮去除
                delBtn: false,
                editBtn: true,
                addBtn: false,
                selection: false,
                // 导出按钮
                excelBtn: true,
                excelBtnText: '成绩导出',
                viewBtn: true,
                title: '成绩',
                align: 'center',
                height: 'auto',
                calcHeight: 80,
                tip: false,
                searchShow: true,
                searchMenuSpan: 4,
                index: true,
                indexLabel: '序号',
                //dialogType: 'drawer',
                dialogClickModal: false,
                // 操作栏宽度
                menu: true,
                menuWidth: 136,
                labelWidth: 120,
                column: [
                    {
                        label: "试卷名称",
                        prop: "examName",
                        search: true,
                        searchSpan: 4,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入试卷名称",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "保安姓名",
                        prop: "securityName",
                        search: true,
                        searchSpan: 4,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入保安姓名",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "所属公司",
                        prop: "company",
                        search: true,
                        searchSpan: 4,
                        dicUrl: '/api/blade-system/dept/tree',
                        props: {
                            label: "title",
                            value: "id",
                        },
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入所属公司",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "考试时间",
                        prop: "examTime",
                        type: "datetime",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        width: 250,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                    },
                    {
                        label: "理论成绩",
                        prop: "theoryGrade",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                    },
                    {
                        label: "实操成绩",
                        prop: "learnGrade",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
                    },
                    {
                        label: "总成绩",
                        prop: "allGrade",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入考试名称",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "是否合格",
                        prop: "qualified",
                        type: 'select',
                        slot: true,
                        search: true,
                        searchSpan: 4,
                        dicData: [{
                            label: '合格',
                            value: 0
                        }, {
                            label: '不合格',
                            value: 1,
                        }, {
                            label: '暂未录实操成绩',
                            value: 2,
                        }],
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入考试名称",
                            trigger: "blur"
                        }]
                    },
                ]
            },
            questionBankSearch: {},
            questionBankLoading: true,
            questionBankData: [
            ],
            questionBankPage: {
                pageSize: 10,
                currentPage: 1,
                total: 16
            },
            questionBankQuery: {},
            questionBankSelectionList: [],
        }
    },
    created () {
    },
    mounted () {
    },
    methods: {
        questionBankOnLoad (page, params = {}) {
            this.questionBankLoading = false;
            getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
                const data = res.data.data;
                this.questionBankPage.total = data.total;
                this.questionBankData = data.records;
                this.questionBankLoading = false;
                this.questionBankSelectionClear();
            });
        },
        questionBankSelectionClear () {
            this.questionBankSelectionList = [];
            this.$refs.questionBankCrud.toggleSelection();
        },
        questionBankSelectionChange (list) {
            this.questionBankSelectionList = list;
        },
        questionBankSearchChange (params, done) {
            this.questionBankQuery = params;
            this.questionBankPage.currentPage = 1;
            this.questionBankOnLoad(this.questionBankPage, params);
            done();
        },
        questionBankSearchReset () {
            this.questionBankQuery = {};
            this.questionBankOnLoad(this.questionBankPage);
        },
        questionBankCurrentChange (currentPage) {
            this.questionBankPage.currentPage = currentPage;
        },
        questionBankSizeChange (pageSize) {
            this.questionBankPage.pageSize = pageSize;
        },
        questionBankRowUpdate (row, index, done, loading) {
            update({ theoryGrade: row.theoryGrade, learnGrade: row.learnGrade, id: row.id }).then(() => {
                this.questionBankOnLoad(this.questionBankPage);
                this.$message({
                    type: "success",
                    message: "操作成功!"
                });
                done();
            }, error => {
                window.console.log(error);
                loading();
            });
        },
    }
}
</script>
<style lang="scss" scoped>
</style>
src/views/exam/startexam.vue
New file
@@ -0,0 +1,388 @@
/*
 * @Author: Morpheus
 * @Date: 2021-07-05 16:31:54
 * @Last Modified by: Morpheus
 * @Last Modified time: 2021-07-18 17:09:52
 * menu-name 考试管理
 */
<template>
    <el-row class="morpheus-box">
        <el-col :span="24">
            <el-card>
                <div class="exam-card-body">
                    <avue-crud v-model="form"
                               class="company-box"
                               :option="questionBankOption"
                               :search.sync="questionBankSearch"
                               :table-loading="questionBankLoading"
                               :data="questionBankData"
                               ref="questionBankCrud"
                               :page.sync="questionBankPage"
                               @on-load="questionBankOnLoad"
                               @selection-change="questionBankSelectionChange"
                               @search-change="questionBankSearchChange"
                               @search-reset="questionBankSearchReset"
                               @current-change="questionBankCurrentChange"
                               @size-change="questionBankSizeChange">
                        <!-- 自定义按钮 -->
                        <!-- <template slot="menuLeft">
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">新增
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">删除
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">导出
                            </el-button>
                        </template> -->
                        <template slot-scope="{row}"
                                  slot="examStatus">
                            <el-tag>{{row.examStatus == 0 ? '已发布' : '草稿'}}</el-tag>
                        </template>
                        <template slot-scope="{row}"
                                  slot="menu">
                            <el-button type="text"
                                       size="mini"
                                       icon="icon-kaoshi"
                                       class="start-kaoshi"
                                       @click="startExam(row)">开始考试
                            </el-button>
                        </template>
                    </avue-crud>
                </div>
            </el-card>
        </el-col>
    </el-row>
</template>
<script>
import {
    getList,
} from "@/api/examapi/examination";
export default {
    data () {
        var validatePass = (rule, value, callback) => {
            console.log(value)
            if (value == undefined || value == '') {
                callback(new Error('请输入分数'));
                return;
            } else if (value !== '' && isNaN(value) == true) {
                callback(new Error('请输入数字'));
            } else if (value <= 0) {
                callback(new Error('分数设置请大于0'));
            } else {
                callback();
            }
        };
        return {
            form: {},
            questionBankOption: {
                // 操作栏多余按钮去除
                delBtn: false,
                editBtn: false,
                addBtn: false,
                selection: false,
                menu: true,
                // 导出按钮
                excelBtn: false,
                viewBtn: true,
                // title: '题库',
                align: 'center',
                height: 'auto',
                calcHeight: 80,
                tip: false,
                searchShow: true,
                searchMenuSpan: 4,
                index: true,
                indexLabel: '序号',
                //dialogType: 'drawer',
                dialogClickModal: false,
                // 操作栏宽度
                menuWidth: 246,
                labelWidth: 140,
                column: [
                    {
                        label: "试卷名称",
                        prop: "examName",
                        search: true,
                        searchSpan: 4,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入试卷名称",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "试卷分数",
                        prop: "totalScore",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
                        width: 100
                    },
                    {
                        label: "考试时间",
                        prop: "examTime",
                        type: "daterange",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        startPlaceholder: '考试开始时间',
                        endPlaceholder: '考试结束时间',
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        // display: false,
                        hide: true,
                        rules: [{
                            required: true,
                            message: "请选择考试时间",
                            trigger: "blur"
                        }],
                        width: 250
                    },
                    {
                        label: "考试开始时间",
                        prop: "startTime",
                        type: "datetime",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: false,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        width: 180
                    },
                    {
                        label: "考试结束时间",
                        prop: "endTime",
                        type: "datetime",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: false,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        width: 180
                    },
                    {
                        label: "创建人",
                        prop: "creator",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: true,
                        // 表单新增时是否可见
                        addDisplay: false,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: false,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        hide: true,
                        display: false,
                    },
                    {
                        label: "备注",
                        prop: "remark",
                        span: 24,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false
                    },
                    {
                        label: "注意事项",
                        prop: "examAttention",
                        type: "textarea",
                        span: 24,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        width: 240
                    },
                ]
            },
            questionBankSearch: {},
            questionBankLoading: true,
            questionBankData: [
            ],
            questionBankPage: {
                pageSize: 10,
                currentPage: 1,
                total: 16
            },
            questionBankQuery: {},
            questionBankSelectionList: [],
        }
    },
    created () {
    },
    mounted () {
    },
    computed: {
        ids () {
            let ids = [];
            this.questionBankSelectionList.forEach(ele => {
                ids.push(ele.id);
            });
            return ids.join(",");
        },
    },
    watch: {
    },
    methods: {
        questionBankOnLoad (page, params = {}) {
            this.questionBankLoading = false;
            getList(page.currentPage, page.pageSize, Object.assign(params, this.questionBankQuery)).then(res => {
                const data = res.data.data;
                this.questionBankPage.total = data.total;
                this.questionBankData = data.records;
                this.questionBankLoading = false;
                this.questionBankSelectionClear();
            });
        },
        questionBankSelectionClear () {
            this.questionBankSelectionList = [];
            this.$refs.questionBankCrud.toggleSelection();
        },
        questionBankSelectionChange (list) {
            this.questionBankSelectionList = list;
        },
        questionBankSearchChange (params, done) {
            this.questionBankQuery = params;
            this.questionBankPage.currentPage = 1;
            this.questionBankOnLoad(this.questionBankPage, params);
            done();
        },
        questionBankSearchReset () {
            this.questionBankQuery = {};
            this.questionBankOnLoad(this.questionBankPage);
        },
        questionBankCurrentChange (currentPage) {
            this.questionBankPage.currentPage = currentPage;
        },
        questionBankSizeChange (pageSize) {
            this.questionBankPage.pageSize = pageSize;
        },
        startExam (row) {
            this.$router.push({
                path: `/startexam/${row.id}`,
                query: row
            })
        }
    }
}
</script>
<style lang="scss" scoped>
</style>
src/views/exam/subject.vue
New file
@@ -0,0 +1,263 @@
/*
 * @Author: Morpheus
 * @Date: 2021-07-05 16:31:54
 * @Last Modified by: Morpheus
 * @Last Modified time: 2021-07-18 16:04:26
 * menu-name 题库查询
 */
<template>
    <el-row class="morpheus-box">
        <el-col :span="24">
            <el-card>
                <div class="exam-card-body">
                    <avue-crud class="company-box"
                               :option="questionBankOption"
                               :search.sync="questionBankSearch"
                               :table-loading="questionBankLoading"
                               :data="questionBankData"
                               ref="questionBankCrud"
                               :page.sync="questionBankPage"
                               @on-load="questionBankOnLoad"
                               @selection-change="questionBankSelectionChange"
                               @search-change="questionBankSearchChange"
                               @search-reset="questionBankSearchReset"
                               @current-change="questionBankCurrentChange"
                               @size-change="questionBankSizeChange"
                               @row-del="questionBankHandleDel">
                        <template slot="menuLeft">
                            <el-button type="danger"
                                       size="small"
                                       icon="el-icon-delete"
                                       @click="questionBankHandleDelete">删 除
                            </el-button>
                        </template>
                    </avue-crud>
                </div>
            </el-card>
        </el-col>
    </el-row>
</template>
<script>
import {
    getList,
    remove,
} from "@/api/examapi/subject";
export default {
    data () {
        return {
            questionBankOption: {
                // 操作栏多余按钮去除
                delBtn: true,
                editBtn: false,
                addBtn: false,
                selection: true,
                menu: true,
                // 导出按钮
                excelBtn: true,
                excelBtnText: '题库导出',
                title: '题库',
                align: 'center',
                height: 'auto',
                calcHeight: 80,
                tip: false,
                searchShow: true,
                searchMenuSpan: 4,
                index: true,
                indexLabel: '序号',
                viewBtn: true,
                //dialogType: 'drawer',
                dialogClickModal: false,
                // 操作栏宽度
                menuWidth: 226,
                column: [
                    {
                        label: "题目名称",
                        prop: "subjectName",
                        search: true,
                        slot: true,
                    },
                    {
                        label: "题目类型",
                        prop: "choicesType",
                        search: true,
                        type: "select",
                        dicData: [{
                            label: '单选题',
                            value: 0
                        }, {
                            label: '多选题',
                            value: 1,
                        }, {
                            label: '判断题',
                            value: 2,
                        }],
                        slot: true,
                        width: 96,
                    },
                    {
                        label: "题目分值",
                        prop: "score",
                        slot: true,
                        width: 96,
                    },
                    {
                        label: "参考答案",
                        prop: "answer",
                        slot: true,
                        width: 96,
                    },
                    {
                        label: "创建人",
                        prop: "creator",
                        slot: true,
                        width: 96,
                    },
                    {
                        label: "创建时间",
                        prop: "createDate",
                        slot: true,
                        width: 130,
                    },
                    {
                        label: "修改人",
                        prop: "modifier",
                        slot: true,
                        width: 96,
                    },
                    {
                        label: "修改时间",
                        prop: "modifyDate",
                        slot: true,
                        width: 130,
                    }
                ]
            },
            questionBankSearch: {},
            questionBankLoading: true,
            questionBankData: [
            ],
            questionBankPage: {
                pageSize: 10,
                currentPage: 1,
                total: 16
            },
            questionBankQuery: {},
            questionBankSelectionList: [],
        }
    },
    created () {
    },
    mounted () {
    },
     computed: {
        ids () {
            let ids = [];
            this.questionBankSelectionList.forEach(ele => {
                ids.push(ele.id);
            });
            return ids.join(",");
        },
    },
    methods: {
        questionBankOnLoad (page, params = {}) {
            this.questionBankLoading = false;
            getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
                const data = res.data.data;
                this.questionBankPage.total = data.total;
                this.questionBankData = data.records;
                this.questionBankLoading = false;
                this.questionBankSelectionClear();
            });
        },
        questionBankSelectionClear () {
            this.questionBankSelectionList = [];
            this.$refs.questionBankCrud.toggleSelection();
        },
        questionBankSelectionChange (list) {
            this.questionBankSelectionList = list;
        },
        questionBankSearchChange (params, done) {
            this.questionBankQuery = params;
            this.questionBankPage.currentPage = 1;
            this.questionBankOnLoad(this.questionBankPage, params);
            done();
        },
        questionBankSearchReset () {
            this.questionBankQuery = {};
            this.questionBankOnLoad(this.questionBankPage);
        },
        questionBankCurrentChange (currentPage) {
            this.questionBankPage.currentPage = currentPage;
        },
        questionBankSizeChange (pageSize) {
            this.questionBankPage.pageSize = pageSize;
        },
        questionBankHandleDel (row) {
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(row.id);
                })
                .then(() => {
                    this.questionBankOnLoad(this.questionBankPage);
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    });
                });
        },
        questionBankHandleDelete () {
            if (this.questionBankSelectionList.length === 0) {
                this.$message.warning("请选择至少一条数据");
                return;
            }
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(this.ids);
                })
                .then(() => {
                    this.questionBankOnLoad(this.questionBankPage);
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    });
                    this.$refs.questionBankCrud.toggleSelection();
                });
        },
    }
}
</script>
<style lang="scss" scoped>
</style>
src/views/exam/topicDetails.vue
New file
@@ -0,0 +1,211 @@
/*
 * @Author: Morpheus
 * @Date: 2021-07-13 11:19:28
 * @Last Modified by: Morpheus
 * @Last Modified time: 2021-07-15 16:40:40
 */
<template>
    <div class="app-container">
        <el-tabs v-model="activeName"
                 @tab-click="handleClick">
            <el-tab-pane label="单选题"
                         name="first">
                <div>
                    <el-row>
                        <el-col :span="12">
                        </el-col>
                    </el-row>
                </div>
                <avue-form v-model="form"
                           :option="option">
                    <template slot-scope="scope"
                              slot="text">
                        <div>
                            <el-input v-model="form.text"
                                      placeholder="这里是自定的表单"></el-input>
                        </div>
                    </template>
                    <template slot-scope="scope"
                              slot="rate">
                        <div>
                            <avue-rate v-model="form.rate"></avue-rate>
                        </div>
                    </template>
                    <template slot="provinceType"
                              slot-scope="{item,value,label}">
                        <span>{{ item }}</span>
                    </template>
                </avue-form>
            </el-tab-pane>
            <el-tab-pane label="多选题"
                         name="second">多选题</el-tab-pane>
            <el-tab-pane label="判断题"
                         name="third">判断题</el-tab-pane>
        </el-tabs>
    </div>
</template>
<script>
export default {
    data () {
        return {
            activeName: 'first',
            rateObj: {
                state: '一般',
                value: 4
            },
            tempSubject: {
            },
            dialogStatus: '',
            dialogStatusType: {
            },
            subjectsType:
                '',
            form: {
                text: '',
                rate: 4
            },
            option: {
                labelWidth: 120,
                column: [
                    {
                        label: '分值',
                        prop: 'text',
                        formslot: true,
                        labelslot: true,
                        errorslot: true,
                        rules: [{
                            required: true,
                            message: "请输入姓名",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: '难度',
                        prop: 'rate',
                        formslot: true,
                        labelslot: true,
                    },
                    {
                        label: "参考答案",
                        prop: "sex",
                        span: 6,
                        type: "radio",
                        dicData: [{
                            label: 'A',
                            value: 0
                        }, {
                            label: 'B',
                            value: 1
                        }, {
                            label: 'C',
                            value: 2
                        }, {
                            label: 'D',
                            value: 3
                        }],
                        errorslot: true,
                        rules: [{
                            required: true,
                            message: "请选择答案",
                            trigger: "blur"
                        }],
                        mock: {
                            type: 'dic'
                        }
                    },
                    {
                        type: 'ueditor',
                        component: 'AvueUeditor',
                        label: '题目名称',
                        span: 24,
                        display: true,
                        action: '',
                        oss: '',
                        props: {},
                        ali: {},
                        qiniu: {},
                        prop: 'titleName',
                        rules: [{
                            required: true,
                            message: "请输入题目名称",
                            trigger: "blur"
                        }],
                    },
                    {
                        label: '',
                        labelWidth: 40,
                        prop: 'divider',
                        component: 'elDivider',//ele分割线
                        span: 24,
                        event: {
                            click: () => {
                                this.$message.success('点击方法')
                            },
                        },
                        params: {
                            html: '<h2 style="font-size: 16px; font-weight: normal"> 选项列表 </h2>',
                            contentPosition: "center",
                        }
                    },
                    {
                        label: "题目名称",
                        prop: "content",
                        component: 'AvueUeditor',
                        options: {
                            action: '/api/blade-resource/oss/endpoint/put-file',
                            props: {
                                res: "data",
                                url: "link",
                            }
                        },
                        hide: true,
                        minRows: 6,
                        span: 24,
                        rules: [{
                            required: true,
                            message: "请输入题目名称",
                            trigger: "blur"
                        }],
                    }
                ]
            }
        }
    },
    methods: {
        handleTabChange () { },
        handleSelectSubject () { },
        dialogSubjectFormVisible () { },
        createSubjectData () { },
        updateSubjectData () { },
        updateAndAddSubjectData () { },
        handleClick (tab, event) {
            console.log(tab, event);
        }
    }
}
</script>
<style lang="scss" scoped>
.dialog-footer {
    margin-top: 20px;
}
</style>
src/views/recruitmentManagement/index.vue
@@ -56,7 +56,7 @@
        viewBtn: true,
        searchSize: "mini",
        searchMenuSpan: 6,
        height: 627,
        height: 693,
        menuWidth: 210,
        align: "center",
        selection: true,
src/views/resource/attach.vue
@@ -1,5 +1,5 @@
<template>
  <basic-container>
  <basic-container class="hasButTwo">
    <avue-crud
      :option="option"
      :table-loading="loading"
src/views/resource/oss.vue
@@ -1,415 +1,457 @@
<template>
  <basic-container>
    <avue-crud :option="option"
               :table-loading="loading"
               :data="data"
               :page.sync="page"
               :permission="permissionList"
               v-model="form"
               ref="crud"
               @row-update="rowUpdate"
               @row-save="rowSave"
               @row-del="rowDel"
               :before-open="beforeOpen"
               @search-change="searchChange"
               @search-reset="searchReset"
               @selection-change="selectionChange"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad">
  <basic-container class="hasButOne">
    <avue-crud
      :option="option"
      :table-loading="loading"
      :data="data"
      :page.sync="page"
      :permission="permissionList"
      v-model="form"
      ref="crud"
      @row-update="rowUpdate"
      @row-save="rowSave"
      @row-del="rowDel"
      :before-open="beforeOpen"
      @search-change="searchChange"
      @search-reset="searchReset"
      @selection-change="selectionChange"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
      @on-load="onLoad"
    >
      <template slot="menuLeft">
        <el-button type="danger"
                   size="small"
                   icon="el-icon-delete"
                   plain
                   v-if="permission.oss_delete"
                   @click="handleDelete">删 除
        <el-button
          type="danger"
          size="small"
          icon="el-icon-delete"
          plain
          v-if="permission.oss_delete"
          @click="handleDelete"
          >删 除
        </el-button>
      </template>
      <template slot-scope="scope" slot="menu">
        <el-button type="text"
                   icon="el-icon-video-play"
                   size="small"
                   v-if="userInfo.role_name.includes('admin')"
                   @click="handleDebug(scope.row)">调试
        <el-button
          type="text"
          icon="el-icon-video-play"
          size="small"
          v-if="userInfo.role_name.includes('admin')"
          @click="handleDebug(scope.row)"
          >调试
        </el-button>
        <el-button type="text"
                   icon="el-icon-circle-check"
                   size="small"
                   v-if="permission.oss_enable"
                   @click.stop="handleEnable(scope.row)">启用
        <el-button
          type="text"
          icon="el-icon-circle-check"
          size="small"
          v-if="permission.oss_enable"
          @click.stop="handleEnable(scope.row)"
          >启用
        </el-button>
      </template>
      <template slot-scope="{row}"
                slot="status">
        <el-tag>{{row.statusName}}</el-tag>
      <template slot-scope="{ row }" slot="status">
        <el-tag>{{ row.statusName }}</el-tag>
      </template>
      <template slot-scope="{row}"
                slot="category">
        <el-tag>{{row.categoryName}}</el-tag>
      <template slot-scope="{ row }" slot="category">
        <el-tag>{{ row.categoryName }}</el-tag>
      </template>
    </avue-crud>
    <el-dialog title="对象存储上传调试"
               append-to-body
               :visible.sync="box"
               width="550px">
      <avue-form ref="form" :option="debugOption" v-model="debugForm" @submit="handleSubmit"/>
    <el-dialog
      title="对象存储上传调试"
      append-to-body
      :visible.sync="box"
      width="550px"
    >
      <avue-form
        ref="form"
        :option="debugOption"
        v-model="debugForm"
        @submit="handleSubmit"
      />
    </el-dialog>
  </basic-container>
</template>
<script>
  import {getList, getDetail, add, update, remove, enable} from "@/api/resource/oss";
  import {mapGetters} from "vuex";
  import func from "@/util/func";
import {
  getList,
  getDetail,
  add,
  update,
  remove,
  enable,
} from "@/api/resource/oss";
import { mapGetters } from "vuex";
import func from "@/util/func";
  export default {
    data() {
      return {
        form: {},
        query: {},
        loading: true,
        box: false,
        page: {
          pageSize: 10,
          currentPage: 1,
          total: 0
        },
        selectionList: [],
        option: {
          height: 'auto',
          calcHeight: 30,
          tip: false,
          searchShow: true,
          searchMenuSpan: 6,
          border: true,
          index: true,
          viewBtn: true,
          selection: true,
          menuWidth: 300,
          labelWidth: 100,
          dialogWidth: 880,
          dialogClickModal: false,
          column: [
            {
              label: "分类",
              type: "radio",
              value: 1,
              span: 24,
              width: 100,
              searchLabelWidth: 50,
              row: true,
              dicUrl: "/api/blade-system/dict/dictionary?code=oss",
              props: {
                label: "dictValue",
                value: "dictKey"
              },
              dataType: "number",
              slot: true,
              prop: "category",
              search: true,
              rules: [{
export default {
  data() {
    return {
      form: {},
      query: {},
      loading: true,
      box: false,
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
      },
      selectionList: [],
      option: {
        height: "auto",
        calcHeight: 30,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        border: true,
        index: true,
        viewBtn: true,
        selection: true,
        menuWidth: 300,
        labelWidth: 100,
        dialogWidth: 880,
        dialogClickModal: false,
        column: [
          {
            label: "分类",
            type: "radio",
            value: 1,
            span: 24,
            width: 100,
            searchLabelWidth: 50,
            row: true,
            dicUrl: "/api/blade-system/dict/dictionary?code=oss",
            props: {
              label: "dictValue",
              value: "dictKey",
            },
            dataType: "number",
            slot: true,
            prop: "category",
            search: true,
            rules: [
              {
                required: true,
                message: "请选择分类",
                trigger: "blur"
              }]
            },
            {
              label: "资源编号",
              prop: "ossCode",
              span: 24,
              width: 120,
              search: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "资源编号",
            prop: "ossCode",
            span: 24,
            width: 120,
            search: true,
            rules: [
              {
                required: true,
                message: "请输入资源编号",
                trigger: "blur"
              }]
            },
            {
              label: "资源地址",
              prop: "endpoint",
              span: 24,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "资源地址",
            prop: "endpoint",
            span: 24,
            rules: [
              {
                required: true,
                message: "请输入资源地址",
                trigger: "blur"
              }]
            },
            {
              label: "空间名",
              prop: "bucketName",
              span: 24,
              width: 120,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "空间名",
            prop: "bucketName",
            span: 24,
            width: 120,
            rules: [
              {
                required: true,
                message: "请输入空间名",
                trigger: "blur"
              }]
            },
            {
              label: "accessKey",
              prop: "accessKey",
              span: 24,
              search: true,
              width: 200,
              overHidden: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "accessKey",
            prop: "accessKey",
            span: 24,
            search: true,
            width: 200,
            overHidden: true,
            rules: [
              {
                required: true,
                message: "请输入accessKey",
                trigger: "blur"
              }]
            },
            {
              label: "secretKey",
              prop: "secretKey",
              span: 24,
              width: 200,
              overHidden: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "secretKey",
            prop: "secretKey",
            span: 24,
            width: 200,
            overHidden: true,
            rules: [
              {
                required: true,
                message: "请输入secretKey",
                trigger: "blur"
              }]
            },
            {
              label: "appId",
              prop: "appId",
              span: 24,
              hide: true,
              display: false,
            },
            {
              label: "region",
              prop: "region",
              span: 24,
              hide: true,
              display: false,
            },
            {
              label: "是否启用",
              prop: "status",
              span: 24,
              width: 80,
              align: "center",
              slot: true,
              addDisplay: false,
              editDisplay: false,
              viewDisplay: false,
            },
            {
              label: "备注",
              prop: "remark",
              span: 24,
              hide: true,
            },
          ]
        },
        data: [],
        debugForm: {
          code: '',
        },
        debugOption: {
          submitText: "提交",
          column: [
            {
              label: "资源编号",
              prop: "code",
              disabled: true,
              span: 24,
            },
            {
              label: "上传背景",
              prop: "backgroundUrl",
              type: 'upload',
              listType: 'picture-img',
              action: '/api/blade-resource/oss/endpoint/put-file',
              propsHttp: {
                res: 'data',
                url: 'link',
                trigger: "blur",
              },
              span: 24,
            ],
          },
          {
            label: "appId",
            prop: "appId",
            span: 24,
            hide: true,
            display: false,
          },
          {
            label: "region",
            prop: "region",
            span: 24,
            hide: true,
            display: false,
          },
          {
            label: "是否启用",
            prop: "status",
            span: 24,
            width: 80,
            align: "center",
            slot: true,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: false,
          },
          {
            label: "备注",
            prop: "remark",
            span: 24,
            hide: true,
          },
        ],
      },
      data: [],
      debugForm: {
        code: "",
      },
      debugOption: {
        submitText: "提交",
        column: [
          {
            label: "资源编号",
            prop: "code",
            disabled: true,
            span: 24,
          },
          {
            label: "上传背景",
            prop: "backgroundUrl",
            type: "upload",
            listType: "picture-img",
            action: "/api/blade-resource/oss/endpoint/put-file",
            propsHttp: {
              res: "data",
              url: "link",
            },
          ]
            span: 24,
          },
        ],
      },
    };
  },
  watch: {
    "form.category"() {
      const category = func.toInt(this.form.category);
      this.$refs.crud.option.column.filter((item) => {
        if (item.prop === "appId") {
          item.display = category === 4;
        }
        if (item.prop === "region") {
          item.display = category === 4;
        }
      });
    },
    "debugForm.code"() {
      const column = this.findObject(this.debugOption.column, "backgroundUrl");
      column.action = `/api/blade-resource/oss/endpoint/put-file?code=${this.debugForm.code}`;
    },
  },
  computed: {
    ...mapGetters(["userInfo", "permission"]),
    permissionList() {
      return {
        addBtn: this.vaildData(this.permission.oss_add),
        viewBtn: this.vaildData(this.permission.oss_view),
        delBtn: this.vaildData(this.permission.oss_delete),
        editBtn: this.vaildData(this.permission.oss_edit),
      };
    },
    watch: {
      'form.category'() {
        const category = func.toInt(this.form.category);
        this.$refs.crud.option.column.filter(item => {
          if (item.prop === "appId") {
            item.display = category === 4;
          }
          if (item.prop === "region") {
            item.display = category === 4;
          }
        });
      },
      'debugForm.code'() {
        const column = this.findObject(this.debugOption.column, "backgroundUrl");
        column.action = `/api/blade-resource/oss/endpoint/put-file?code=${this.debugForm.code}`;
      }
    ids() {
      let ids = [];
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids.join(",");
    },
    computed: {
      ...mapGetters(["userInfo", "permission"]),
      permissionList() {
        return {
          addBtn: this.vaildData(this.permission.oss_add),
          viewBtn: this.vaildData(this.permission.oss_view),
          delBtn: this.vaildData(this.permission.oss_delete),
          editBtn: this.vaildData(this.permission.oss_edit)
        };
      },
      ids() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids.join(",");
      }
    },
    methods: {
      rowSave(row, done, loading) {
        add(row).then(() => {
  },
  methods: {
    rowSave(row, done, loading) {
      add(row).then(
        () => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          done();
        }, error => {
        },
        (error) => {
          window.console.log(error);
          loading();
        });
      },
      rowUpdate(row, index, done, loading) {
        update(row).then(() => {
        }
      );
    },
    rowUpdate(row, index, done, loading) {
      update(row).then(
        () => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          done();
        }, error => {
        },
        (error) => {
          window.console.log(error);
          loading();
        });
      },
      rowDel(row) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(row.id);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      searchReset() {
        this.query = {};
        this.onLoad(this.page);
      },
      searchChange(params, done) {
        this.query = params;
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
      },
      selectionChange(list) {
        this.selectionList = list;
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
      },
      handleEnable(row) {
        this.$confirm("是否确定启用这条配置?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return enable(row.id);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
      },
      handleDebug(row) {
        this.box = true;
        this.debugForm.code = row.ossCode;
        this.debugForm.backgroundUrl = '';
      },
      handleSubmit(form, done) {
        this.$message({
          type: "success",
          message: `获取到图片地址:[${form.backgroundUrl}]`
        });
        done();
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
      );
    },
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
        })
          .then(() => {
            return remove(this.ids);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
      },
      beforeOpen(done, type) {
        if (["edit", "view"].includes(type)) {
          getDetail(this.form.id).then(res => {
            this.form = res.data.data;
        });
    },
    searchReset() {
      this.query = {};
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      this.query = params;
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      this.$refs.crud.toggleSelection();
    },
    handleEnable(row) {
      this.$confirm("是否确定启用这条配置?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return enable(row.id);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
        }
        done();
      },
      currentChange(currentPage) {
        this.page.currentPage = currentPage;
      },
      sizeChange(pageSize) {
        this.page.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
      },
      onLoad(page, params = {}) {
        this.loading = true;
        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.loading = false;
          this.selectionClear();
          this.$refs.crud.toggleSelection();
        });
    },
    handleDebug(row) {
      this.box = true;
      this.debugForm.code = row.ossCode;
      this.debugForm.backgroundUrl = "";
    },
    handleSubmit(form, done) {
      this.$message({
        type: "success",
        message: `获取到图片地址:[${form.backgroundUrl}]`,
      });
      done();
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
        return;
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          this.$refs.crud.toggleSelection();
        });
    },
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDetail(this.form.id).then((res) => {
          this.form = res.data.data;
        });
      }
    }
  };
      done();
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.query);
    },
    onLoad(page, params = {}) {
      this.loading = true;
      getList(
        page.currentPage,
        page.pageSize,
        Object.assign(params, this.query)
      ).then((res) => {
        const data = res.data.data;
        this.page.total = data.total;
        this.data = data.records;
        this.loading = false;
        this.selectionClear();
      });
    },
  },
};
</script>
src/views/securityEquipment/car.vue
@@ -48,9 +48,10 @@
      option: {
        // card: true,
        tip: false,
        index: true,
        searchSize: "mini",
        searchMenuSpan: 6,
        height: 627,
        height: 693,
        menuWidth: 160,
        align: "center",
        selection: true,
src/views/securityEquipment/equipments.vue
@@ -50,7 +50,8 @@
        tip: false,
        searchSize: "mini",
        searchMenuSpan: 6,
        height: 627,
        height: 693,
        index: true,
        menuWidth: 160,
        align: "center",
        selection: true,
src/views/securityEquipment/gun.js
@@ -14,11 +14,13 @@
        prop: "id",
        hide: true,
        editDisplay: false,
        addDisplay: false
        addDisplay: false,
        labelWidth: 160,
    },
    {
        label: "公务用枪证编号",
        prop: "gunCardNumber",
        labelWidth: 160,
        searchLabelWidth: 130,
        search: true,
        rules: [{
@@ -30,6 +32,7 @@
    {
        label: "发证单位名称",
        searchLabelWidth: 110,
        labelWidth: 160,
        prop: "issueUnit",
        rules: [{
            required: true,
@@ -41,6 +44,7 @@
    {
        label: "公务用枪编号",
        prop: "cardNumber",
        labelWidth: 160,
        searchLabelWidth: 110,
        rules: [{
            required: true,
@@ -53,6 +57,7 @@
        label: "枪型",
        prop: "gunMode",
        width: 70,
        labelWidth: 160,
        rules: [{
            required: true,
            message: "请输入枪型",
@@ -63,6 +68,7 @@
    {
        label: "保安公司",
        prop: "tenantName",
        labelWidth: 160,
        rules: [{
            required: true,
            message: "请输入组织机构",
@@ -89,6 +95,7 @@
    {
        label: "责任人",
        prop: "personInCharge",
        labelWidth: 160,
        rules: [{
            required: true,
            message: "请输入责任人",
@@ -97,6 +104,7 @@
    },
    {
        label: "发证日期",
        labelWidth: 160,
        prop: "issueTime",
        // search: true,
        type: "date",
@@ -114,6 +122,7 @@
    {
        label: "有效日期",
        prop: "validTime",
        labelWidth: 160,
        // search: true,
        type: "date",
        format: "yyyy-MM-dd",
src/views/securityEquipment/gun.vue
@@ -50,7 +50,8 @@
        tip: false,
        searchSize: "mini",
        searchMenuSpan: 6,
        height: 627,
        height: 693,
        index: true,
        menuWidth: 160,
        align: "center",
        selection: true,
src/views/securityGuard/data.js
@@ -1,314 +1,314 @@
//保安员基本信息
export var securityBaseInfoColumn = [{
        label: "",
        labelWidth: "20",
        type: 'title',
        prop: "title",
        span: 24,
        styles: {
            fontSize: '24px'
        }
    },
    {
        label: "所属保安公司",
        prop: "deptId",
        type: "tree",
        dicUrl: "/api/blade-system/dept/security_lazy-tree?parentId=1413470343230877697",
        // dicUrl: "/api/blade-system/dept/lazy-tree?parentId=0",
        props: {
            label: "title",
            value: "id",
        },
        disabled: true,
        span: 24,
    },
    {
        label: "登录账号",
        prop: "account",
        disabled: true
    },
    {
        label: "用户姓名",
        prop: "realName",
        disabled: true,
    },
    {
        label: "用户昵称",
        prop: "name",
        disabled: true
    },
    {
        label: "手机号码",
        prop: "phone",
        disabled: true
    },
    {
        label: "电子邮箱",
        prop: "email",
        disabled: true
    },
    {
        label: "身份证号",
        prop: "cardid",
        disabled: true
    },
    {
        label: "籍贯",
        prop: "nativeplace",
        disabled: true
    },
    {
        label: "民族",
        prop: "nation",
        disabled: true
    },
    {
        label: "是否持证",
        prop: "hold",
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=equipage",
        props: {
            label: "dictValue",
            value: "dictKey",
        },
        type: "select",
        disabled: true
    },
    {
        label: "保安员证编号",
        prop: "securitynumber",
        disabled: true
    },
    {
        label: "所属辖区",
        prop: "jurisdiction",
        // multiple: true,
        type: "tree",
        dicUrl: "/api/jurisdiction/lazy-tree?parentId=0",
        props: {
            label: "title",
            value: "id",
        },
        disabled: true
    },
    {
        label: "最高学历",
        prop: "education",
        type: "select",
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=educationType",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        dataType: "number",
        slot: true,
        disabled: true
    },
    {
        label: "政治面貌",
        prop: "politicaloutlook",
        disabled: true
    },
    {
        label: "身高",
        prop: "height",
        disabled: true
    },
    {
        label: "联系地址",
        prop: "address",
        disabled: true
    },
    {
        label: "户口所在地",
        prop: "registered",
        disabled: true
    },
    {
        label: "入职时间",
        prop: "rtime",
        type: 'date',
        format: "yyyy-MM-dd",
        valueFormat: "yyyy-MM-dd",
        disabled: true
    },
    {
        label: "用户性别",
        prop: "sex",
        type: "select",
        dicData: [{
                label: "男",
                value: 1
            },
            {
                label: "女",
                value: 2
            },
            {
                label: "未知",
                value: 3
            }
        ],
        disabled: true
    },
    {
        label: "用户生日",
        type: "date",
        prop: "birthday",
        disabled: true
    label: "",
    labelWidth: "20",
    type: 'title',
    prop: "title",
    span: 24,
    styles: {
        fontSize: '24px'
    }
},
{
    label: "所属保安公司",
    prop: "deptId",
    type: "tree",
    dicUrl: "/api/blade-system/dept/security_lazy-tree?parentId=1413470343230877697",
    // dicUrl: "/api/blade-system/dept/lazy-tree?parentId=0",
    props: {
        label: "title",
        value: "id",
    },
    disabled: true,
    span: 24,
},
{
    label: "登录账号",
    prop: "account",
    disabled: true
},
{
    label: "用户姓名",
    prop: "realName",
    disabled: true,
},
{
    label: "用户昵称",
    prop: "name",
    disabled: true
},
{
    label: "手机号码",
    prop: "phone",
    disabled: true
},
{
    label: "电子邮箱",
    prop: "email",
    disabled: true
},
{
    label: "身份证号",
    prop: "cardid",
    disabled: true
},
{
    label: "籍贯",
    prop: "nativeplace",
    disabled: true
},
{
    label: "民族",
    prop: "nation",
    disabled: true
},
{
    label: "是否持证",
    prop: "hold",
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=equipage",
    props: {
        label: "dictValue",
        value: "dictKey",
    },
    type: "select",
    disabled: true
},
{
    label: "保安员证编号",
    prop: "securitynumber",
    disabled: true
},
{
    label: "所属辖区",
    prop: "jurisdiction",
    // multiple: true,
    type: "tree",
    dicUrl: "/api/jurisdiction/lazy-tree?parentId=0",
    props: {
        label: "title",
        value: "id",
    },
    disabled: true
},
{
    label: "最高学历",
    prop: "education",
    type: "select",
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=educationType",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    dataType: "number",
    slot: true,
    disabled: true
},
{
    label: "政治面貌",
    prop: "politicaloutlook",
    disabled: true
},
{
    label: "身高",
    prop: "height",
    disabled: true
},
{
    label: "联系地址",
    prop: "address",
    disabled: true
},
{
    label: "户口所在地",
    prop: "registered",
    disabled: true
},
{
    label: "入职时间",
    prop: "rtime",
    type: 'date',
    format: "yyyy-MM-dd",
    valueFormat: "yyyy-MM-dd",
    disabled: true
},
{
    label: "用户性别",
    prop: "sex",
    type: "select",
    dicData: [{
        label: "男",
        value: 1
    },
    {
        label: "女",
        value: 2
    },
    {
        label: "未知",
        value: 3
    }
    ],
    disabled: true
},
{
    label: "用户生日",
    type: "date",
    prop: "birthday",
    disabled: true
}
]
export var securityBaseInfoColumns = [{
        label: "所属保安单位",
        prop: "tenantId",
        type: "tree",
        dicUrl: "/api/blade-system/tenant/select",
        props: {
            label: "tenantName",
            value: "tenantId"
        },
        disabled: true,
        span: 24,
    label: "所属保安单位",
    prop: "tenantId",
    type: "tree",
    dicUrl: "/api/blade-system/tenant/select",
    props: {
        label: "tenantName",
        value: "tenantId"
    },
    disabled: true,
    span: 24,
},
{
    label: "登录账号",
    prop: "account",
    disabled: true
},
{
    label: "用户姓名",
    prop: "realName",
    rules: [{
        required: true,
        message: "请输入用户姓名",
        trigger: "blur"
    }, {
        min: 2,
        max: 5,
        message: '姓名长度在2到5个字符'
    }]
},
{
    label: "用户昵称",
    prop: "name"
},
{
    label: "手机号码",
    prop: "phone",
    overHidden: true,
    rules: [{
        required: true,
        message: "请输入手机号",
        trigger: "blur"
    }]
},
{
    label: "电子邮箱",
    prop: "email",
    hide: true,
    overHidden: true
},
{
    label: "身份证号",
    prop: "cardid",
    hide: true,
    overHidden: true,
    rules: [{
        required: true,
        message: "请输入身份证号",
        trigger: "blur"
    }]
},
{
    label: "籍贯",
    prop: "nativeplace",
    hide: true,
    overHidden: true
},
{
    label: "民族",
    prop: "nation",
    hide: true,
    overHidden: true
},
{
    label: "最高学历",
    prop: "education",
    type: "select",
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=educationType",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    dataType: "number",
    slot: true,
    rules: [{
        required: true,
        message: "请选择学历",
        trigger: "blur"
    }]
},
{
    label: "政治面貌",
    prop: "politicaloutlook",
    hide: true,
    overHidden: true
},
{
    label: "身高",
    prop: "height",
    hide: true,
    overHidden: true
},
{
    label: "联系地址",
    prop: "address",
    hide: true,
    overHidden: true
},
{
    label: "户口所在地",
    prop: "registered",
    hide: true,
    overHidden: true
},
{
    label: "入职时间",
    prop: "rtime",
    type: 'date',
    format: "yyyy-MM-dd",
    valueFormat: "yyyy-MM-dd",
    hide: true,
    overHidden: true
},
{
    label: "用户性别",
    prop: "sex",
    type: "select",
    dicData: [{
        label: "男",
        value: 1
    },
    {
        label: "登录账号",
        prop: "account",
        disabled: true
        label: "女",
        value: 2
    },
    {
        label: "用户姓名",
        prop: "realName",
        rules: [{
            required: true,
            message: "请输入用户姓名",
            trigger: "blur"
        }, {
            min: 2,
            max: 5,
            message: '姓名长度在2到5个字符'
        }]
    },
    {
        label: "用户昵称",
        prop: "name"
    },
    {
        label: "手机号码",
        prop: "phone",
        overHidden: true,
        rules: [{
            required: true,
            message: "请输入手机号",
            trigger: "blur"
        }]
    },
    {
        label: "电子邮箱",
        prop: "email",
        hide: true,
        overHidden: true
    },
    {
        label: "身份证号",
        prop: "cardid",
        hide: true,
        overHidden: true,
        rules: [{
            required: true,
            message: "请输入身份证号",
            trigger: "blur"
        }]
    },
    {
        label: "籍贯",
        prop: "nativeplace",
        hide: true,
        overHidden: true
    },
    {
        label: "民族",
        prop: "nation",
        hide: true,
        overHidden: true
    },
    {
        label: "最高学历",
        prop: "education",
        type: "select",
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=educationType",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        dataType: "number",
        slot: true,
        rules: [{
            required: true,
            message: "请选择学历",
            trigger: "blur"
        }]
    },
    {
        label: "政治面貌",
        prop: "politicaloutlook",
        hide: true,
        overHidden: true
    },
    {
        label: "身高",
        prop: "height",
        hide: true,
        overHidden: true
    },
    {
        label: "联系地址",
        prop: "address",
        hide: true,
        overHidden: true
    },
    {
        label: "户口所在地",
        prop: "registered",
        hide: true,
        overHidden: true
    },
    {
        label: "入职时间",
        prop: "rtime",
        type: 'date',
        format: "yyyy-MM-dd",
        valueFormat: "yyyy-MM-dd",
        hide: true,
        overHidden: true
    },
    {
        label: "用户性别",
        prop: "sex",
        type: "select",
        dicData: [{
                label: "男",
                value: 1
            },
            {
                label: "女",
                value: 2
            },
            {
                label: "未知",
                value: 3
            }
        ],
        hide: true
    },
    {
        label: "用户生日",
        type: "date",
        prop: "birthday",
        hide: true
        label: "未知",
        value: 3
    }
    ],
    hide: true
},
{
    label: "用户生日",
    type: "date",
    prop: "birthday",
    hide: true
}
]
@@ -443,153 +443,153 @@
export var securityFormPageColumn = [{
        label: "姓名",
        prop: "realName",
        search: true,
        searchSpan: 4,
        display: false
    label: "姓名",
    prop: "realName",
    search: true,
    searchSpan: 4,
    display: false
},
{
    label: "性别",
    prop: "sex",
    type: "select",
    dicData: [{
        label: "男",
        value: 1,
    },
    {
        label: "性别",
        prop: "sex",
        type: "select",
        dicData: [{
                label: "男",
                value: 1,
            },
            {
                label: "女",
                value: 2,
            },
            {
                label: "未知",
                value: 3,
            },
        ],
        display: false
        label: "女",
        value: 2,
    },
    {
        label: "未知",
        value: 3,
    },
    ],
    display: false
},
    {
        label: "籍贯",
        prop: "nativeplace",
        display: false
{
    label: "籍贯",
    prop: "nativeplace",
    display: false
},
{
    label: "民族",
    prop: "nation",
    display: false
},
{
    label: "出生日期",
    prop: "birthday",
    type: "date",
    format: "yyyy-MM-dd",
    valueFormat: "yyyy-MM-dd",
    display: false
},
{
    label: "学历",
    prop: "education",
    display: false,
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=educationType",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    {
        label: "民族",
        prop: "nation",
        display: false
    type: "select",
    hide: true,
    rules: [{
        required: true,
        message: "请选择学历",
        trigger: "blur"
    }],
},
{
    label: "联系电话",
    prop: "phone",
    display: false
},
{
    label: "邮箱",
    prop: "email",
    display: false,
    width: 150
},
{
    label: "入职时间",
    prop: "rtime",
    display: false
},
{
    label: "保安公司名称",
    searchLabelWidth: "110",
    // prop: "deptName",
    prop: "deptId",
    type: "tree",
    dicUrl: "/api/blade-system/dept/security_lazy-tree?parentId=1413470343230877697",
    props: {
        label: "title",
        value: "id",
    },
    {
        label: "出生日期",
        prop: "birthday",
        type: "date",
        format: "yyyy-MM-dd",
        valueFormat: "yyyy-MM-dd",
        display: false
    slot: true,
    searchSpan: 6,
    display: false,
    search: true,
    width: 260
},
{
    label: "是否持证",
    prop: "hold",
    slot: true,
    display: false,
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=equipage",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    {
        label: "学历",
        prop: "education",
        display: false,
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=educationType",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        type: "select",
        hide: true,
        rules: [{
            required: true,
            message: "请选择学历",
            trigger: "blur"
        }],
    type: "select",
    rules: [{
        required: true,
        message: "请选择",
        trigger: "blur"
    }],
},
// {
//     label: "入职时间",
//     prop: "rtime",
//     type: "datetime",
//     format: "yyyy-MM-dd",
//     valueFormat: "yyyy-MM-dd",
//     searchRange: true,
//     searchSpan: 6,
//     hide: true,
//     addDisplay: false,
//     editDisplay: false,
//     viewDisplay: false,
//     search: true,
//     rules: [{
//         required: true,
//         message: "请输入时间",
//         trigger: "blur"
//     }]
// },
{
    label: "在职状态",
    prop: "status",
    type: "select",
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=workerState",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    {
        label: "联系电话",
        prop: "phone",
        display: false
    },
    {
        label: "邮箱",
        prop: "email",
        display: false,
        width: 150
    },
    {
        label: "入职时间",
        prop: "rtime",
        display: false
    },
    {
        label: "保安公司名称",
        searchLabelWidth: "110",
        // prop: "deptName",
        prop: "deptId",
        type: "tree",
        dicUrl: "/api/blade-system/dept/security_lazy-tree?parentId=1413470343230877697",
        props: {
            label: "title",
            value: "id",
        },
        slot: true,
        searchSpan: 5,
        display: false,
        search: true,
        width: 260
    },
    {
        label: "是否持证",
        prop: "hold",
        slot: true,
        display: false,
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=equipage",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        type: "select",
        rules: [{
            required: true,
            message: "请选择",
            trigger: "blur"
        }],
    },
    // {
    //     label: "入职时间",
    //     prop: "rtime",
    //     type: "datetime",
    //     format: "yyyy-MM-dd",
    //     valueFormat: "yyyy-MM-dd",
    //     searchRange: true,
    //     searchSpan: 6,
    //     hide: true,
    //     addDisplay: false,
    //     editDisplay: false,
    //     viewDisplay: false,
    //     search: true,
    //     rules: [{
    //         required: true,
    //         message: "请输入时间",
    //         trigger: "blur"
    //     }]
    // },
    {
        label: "在职状态",
        prop: "status",
        type: "select",
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=workerState",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        dataType: "number",
        display: false,
        searchSpan: 3,
        search: true,
        rules: [{
            required: true,
            message: "请选择在职状态",
            trigger: "blur"
        }]
    },
    dataType: "number",
    display: false,
    searchSpan: 4,
    search: true,
    rules: [{
        required: true,
        message: "请选择在职状态",
        trigger: "blur"
    }]
},
]
src/views/securityGuard/securityGuard.vue
@@ -1,5 +1,5 @@
<template>
  <el-row>
  <el-row class="securityGuard">
    <el-col :span="0" style="display: none">
      <div class="box">
        <el-scrollbar>
@@ -322,11 +322,12 @@
        searchMenuSpan: 6,
        border: false,
        stripe: true,
        align: "center",
        index: true,
        delBtnText: "注销",
        selection: true,
        viewBtn: true,
        defaultExpandAll:true,
        defaultExpandAll: true,
        //dialogType: 'drawer',
        dialogClickModal: false,
        column: securityFormPageColumn,
src/views/securityUnit/data.js
@@ -21,6 +21,8 @@
        prop: "creditcode",
        width: 140,
        hide: true,
        labelWidth: 160,
        // hide: true,
        // editDisplay: false,
        // addDisplay: false
@@ -55,12 +57,15 @@
        label: "企业名称",
        prop: "enterprisename",
        search: true,
        searchSpan: 6,
        labelWidth: 160,
        // width: 130,
    },
    {
        label: "企业类型",
        prop: "stats",
        type: "tree",
        labelWidth: 160,
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=stats",
        props: {
            label: "dictValue",
@@ -77,10 +82,11 @@
    },
    {
        label: "法定代表人",
        labelWidth: 160,
        prop: "representative",
        width: 80,
        search: true,
        searchSpan: 5,
        searchSpan: 6,
        searchLabelWidth: 100
    },
    // {
@@ -106,6 +112,7 @@
    {
        label: "成立日期",
        prop: "establishtime",
        labelWidth: 160,
        width: 130,
        overHidden: true,
        type: "date",
@@ -131,6 +138,7 @@
    {
        label: "注册资本(万元人民币)",
        prop: "registeredcapital",
        labelWidth: 160,
        // search: true,
        width: 140,
        // overHidden: true
@@ -138,6 +146,7 @@
    {
        label: "实缴资本(万元人民币)",
        prop: "capital",
        labelWidth: 160,
        // width: 85,
        hide: true,
        // search: true,
@@ -146,6 +155,7 @@
    },
    {
        label: "组织机构代码",
        labelWidth: 160,
        prop: "organizationcode",
        // width: 110,
        // search: true,
@@ -154,6 +164,7 @@
    {
        label: "工商注册号",
        prop: "registrationnumber",
        labelWidth: 160,
        width: 120,
        // search: true,
        // searchSpan: 4,
@@ -161,6 +172,7 @@
    {
        label: "纳税人识别号",
        prop: "identificationnumber",
        labelWidth: 160,
        width: 140,
        // addDisplay: true,
        // editDisplay: true,
@@ -203,6 +215,7 @@
    {
        label: "注册地址",
        prop: "address",
        labelWidth: 160,
        // search: true,
        hide: true,
    },
@@ -210,6 +223,7 @@
        label: "经营范围",
        prop: "business",
        // search: true,
        labelWidth: 160,
        hide: true,
        // width: 110,
        overHidden: true
@@ -217,6 +231,7 @@
    {
        label: "所属地区",
        prop: "region",
        labelWidth: 160,
        // width: 110,
        // search: true,
        overHidden: true
@@ -225,6 +240,7 @@
        label: "登记机关",
        prop: "registration",
        // search: true,
        labelWidth: 160,
        // width: 88,
        overHidden: true,
        hide: true,
@@ -233,6 +249,7 @@
    {
        label: "所属行业",
        prop: "industry",
        labelWidth: 160,
        hide: true,
        // search: true,
        // width: 88,
@@ -280,7 +297,7 @@
    },
    {
        label: "辖区",
        prop: "departmentid",
        prop: "jurisdiction",
        // type: "tree",
        // disabled: true,
        type: "tree",
src/views/securityUnit/index.vue
@@ -212,12 +212,13 @@
      query: {},
      data: [],
      option: {
        index: true,
        addBtn: false,
        // card: true,
        tip: false,
        searchSize: "mini",
        searchMenuSpan: 6,
        height: 623,
        height: 693,
        menuWidth: 160,
        align: "center",
        selection: true,
@@ -421,7 +422,7 @@
          }
        }
      }
      // console.log(d);
      console.log(d);
      for (var k in d) {
        if (d[k] == "" || d[k] == undefined) {
          console.log(k);
src/views/singleperformance/index.vue
New file
@@ -0,0 +1,398 @@
/*
 * @Author: Morpheus
 * @Date: 2021-07-05 16:31:54
 * @Last Modified by: Morpheus
 * @Last Modified time: 2021-07-18 21:02:10
 * menu-name 成绩管理
 */
<template>
    <el-row class="morpheus-box">
        <el-col :span="24">
            <el-card>
                <div class="exam-card-body">
                    <avue-crud v-model="obj"
                               class="company-box"
                               :option="questionBankOption"
                               :search.sync="questionBankSearch"
                               :table-loading="questionBankLoading"
                               :data="questionBankData"
                               ref="questionBankCrud"
                               :page.sync="questionBankPage"
                               @on-load="questionBankOnLoad"
                               @selection-change="questionBankSelectionChange"
                               @search-change="questionBankSearchChange"
                               @search-reset="questionBankSearchReset"
                               @current-change="questionBankCurrentChange"
                               @size-change="questionBankSizeChange"
                               @row-update="questionBankRowUpdate">
                        <template slot-scope="{ row }"
                                  slot="learnGrade">
                            {{ row.learnGrade == -1 ? "暂未录入" : row.learnGrade }}
                        </template>
                        <!-- 自定义按钮 -->
                        <!-- <template slot="menuLeft">
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">新增
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">删除
                            </el-button>
                            <el-button type="danger"
                                       size="mini"
                                       icon="el-icon-delete"
                                       plain
                                       @click="handleDelete">导出
                            </el-button>
                        </template> -->
                    </avue-crud>
                </div>
            </el-card>
        </el-col>
    </el-row>
</template>
<script>
import {
    getList,
    update
} from "@/api/examapi/performance";
export default {
    data () {
        var validatePass = (rule, value, callback) => {
            console.log(value)
            if (value == undefined || value == '') {
                callback(new Error('请输入实操成绩'));
                return;
            } else if (value !== '' && isNaN(value) == true) {
                callback(new Error('请输入数字'));
            } else if (value <= 0) {
                callback(new Error('分数设置请大于0'));
            } else if (value > 100) {
                callback(new Error('分数设置请小于100'));
            } else {
                callback();
            }
        };
        return {
            obj: {
                name: '张三',
            },
            questionBankOption: {
                // 操作栏多余按钮去除
                delBtn: false,
                editBtn: true,
                addBtn: false,
                selection: false,
                // 导出按钮
                excelBtn: true,
                excelBtnText: '成绩导出',
                viewBtn: true,
                title: '成绩',
                align: 'center',
                height: 'auto',
                calcHeight: 80,
                tip: false,
                searchShow: true,
                searchMenuSpan: 4,
                index: true,
                indexLabel: '序号',
                //dialogType: 'drawer',
                dialogClickModal: false,
                // 操作栏宽度
                menu: false,
                menuWidth: 136,
                labelWidth: 120,
                column: [
                    {
                        label: "试卷名称",
                        prop: "examName",
                        search: true,
                        searchSpan: 4,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入试卷名称",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "保安姓名",
                        prop: "securityName",
                        search: true,
                        searchSpan: 4,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入保安姓名",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "所属公司",
                        prop: "company",
                        search: true,
                        searchSpan: 4,
                        dicUrl: '/api/blade-system/dept/tree',
                        props: {
                            label: "title",
                            value: "id",
                        },
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入所属公司",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "考试时间",
                        prop: "examTime",
                        type: "datetime",
                        // span: 24,
                        format: 'yyyy-MM-dd HH:mm:ss',
                        valueFormat: 'yyyy-MM-dd HH:mm:ss',
                        width: 250,
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                    },
                    {
                        label: "理论成绩",
                        prop: "theoryGrade",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                    },
                    {
                        label: "实操成绩",
                        prop: "learnGrade",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: false,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{ validator: validatePass, required: true, trigger: 'blur' }],
                    },
                    {
                        label: "总成绩",
                        prop: "allGrade",
                        slot: true,
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入考试名称",
                            trigger: "blur"
                        }]
                    },
                    {
                        label: "是否合格",
                        prop: "qualified",
                        type: 'select',
                        slot: true,
                        search: true,
                        searchSpan: 4,
                        dicData: [{
                            label: '合格',
                            value: 0
                        }, {
                            label: '不合格',
                            value: 1,
                        }, {
                            label: '暂未录实操成绩',
                            value: 2,
                        }],
                        // 表单新增时是否禁止
                        addDisabled: false,
                        // 表单新增时是否可见
                        addDisplay: true,
                        // 表单新增时是否为查看模式
                        addDetail: false,
                        // 表单编辑时是否禁止
                        editDisabled: true,
                        // 表单编辑时是否可见
                        editDisplay: true,
                        // 表单编辑时是否为查看模式
                        editDetail: false,
                        rules: [{
                            required: true,
                            message: "请输入考试名称",
                            trigger: "blur"
                        }]
                    },
                ]
            },
            questionBankSearch: {},
            questionBankLoading: true,
            questionBankData: [
            ],
            questionBankPage: {
                pageSize: 10,
                currentPage: 1,
                total: 16
            },
            questionBankQuery: {},
            questionBankSelectionList: [],
        }
    },
    created () {
    },
    mounted () {
    },
    methods: {
        questionBankOnLoad (page, params = {}) {
            this.questionBankLoading = false;
            getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
                const data = res.data.data;
                this.questionBankPage.total = data.total;
                this.questionBankData = data.records;
                this.questionBankLoading = false;
                this.questionBankSelectionClear();
            });
        },
        questionBankSelectionClear () {
            this.questionBankSelectionList = [];
            this.$refs.questionBankCrud.toggleSelection();
        },
        questionBankSelectionChange (list) {
            this.questionBankSelectionList = list;
        },
        questionBankSearchChange (params, done) {
            this.questionBankQuery = params;
            this.questionBankPage.currentPage = 1;
            this.questionBankOnLoad(this.questionBankPage, params);
            done();
        },
        questionBankSearchReset () {
            this.questionBankQuery = {};
            this.questionBankOnLoad(this.questionBankPage);
        },
        questionBankCurrentChange (currentPage) {
            this.questionBankPage.currentPage = currentPage;
        },
        questionBankSizeChange (pageSize) {
            this.questionBankPage.pageSize = pageSize;
        },
        questionBankRowUpdate (row, index, done, loading) {
            update({ theoryGrade: row.theoryGrade, learnGrade: row.learnGrade, id: row.id }).then(() => {
                this.questionBankOnLoad(this.questionBankPage);
                this.$message({
                    type: "success",
                    message: "操作成功!"
                });
                done();
            }, error => {
                window.console.log(error);
                loading();
            });
        },
    }
}
</script>
<style lang="scss" scoped>
</style>
src/views/startexam/index.vue
New file
@@ -0,0 +1,663 @@
<template>
    <el-row class="morpheus-box">
        <el-col :span="24">
            <el-card>
                <div class="exam-card-body">
                    <div class="subject-box">
                        <el-row :gutter="30">
                            <el-col :span="5">
                                <div class="tool-bar">
                                    <div class="time-remain">
                                        剩余时间:
                                        <div class="time">
                                            <count-down v-on:start_callback="countDownS_cb(1)"
                                                        v-on:end_callback="countDownE_cb(1)"
                                                        :current-time="currentTime"
                                                        :start-time="startTime"
                                                        :end-time="endTime"
                                                        :tip-text="'距离考试开始'"
                                                        :tip-text-end="'距离考试结束'"
                                                        :end-text="'考试结束'"
                                                        :hourTxt="':'"
                                                        :minutesTxt="':'"
                                                        :secondsTxt="''">
                                            </count-down>
                                        </div>
                                    </div>
                                    <div class="current-progress">
                                        当前进度: {{subjectIndex}}/{{subjectIds.length}}
                                    </div>
                                    <div class="answer-card">
                                        <el-button type="text"
                                                   icon="el-icon-date"
                                                   @click="answerCard">答题卡</el-button>
                                    </div>
                                    <el-button type="success"
                                               icon="el-icon-date"
                                               @click="submitExam"
                                               v-bind:disabled="disableSubmit">提交</el-button>
                                </div>
                            </el-col>
                            <el-col :span="18">
                                <div class="subject-box-card">
                                    <div class="subject-exam-title">{{exam.examinationName}}(共{{subjectIds.length}}题,合计{{exam.totalScore}}分)</div>
                                    <!-- 题目内容 -->
                                    <choices ref="choices"
                                             v-show="this.query.type === 0" />
                                    <multiple-choices ref="multipleChoices"
                                                      v-show="this.query.type === 1" />
                                    <judgement ref="judgement"
                                               v-show="this.query.type === 2" />
                                    <practical-operation ref="practicalOperation"
                                                         v-show="this.query.type === 3" />
                                    <short-answer ref="shortAnswer"
                                                  v-show="this.query.type === 4" />
                                    <div class="subject-buttons"
                                         v-if="query.subjectId !== ''">
                                        <el-button plain
                                                   @click="last"
                                                   :loading="loadingLast">上一题</el-button>
                                        <el-button plain
                                                   @click="next"
                                                   :loading="loadingNext">下一题</el-button>
                                        <el-button type="success"
                                                   @click="submitExam"
                                                   v-bind:disabled="disableSubmit">提交</el-button>
                                    </div>
                                </div>
                            </el-col>
                        </el-row>
                        <el-dialog title="答题卡"
                                   :visible.sync="dialogVisible"
                                   width="50%"
                                   top="10vh"
                                   :modal='false'
                                   center>
                            <div class="answer-card-title">{{exam.examinationName}}(共{{subjectIds.length}}题,合计{{exam.totalScore}}分)</div>
                            <div class="answer-card-split"></div>
                            <el-row class="answer-card-content">
                                <el-button :class="{ 'answered': subjectIds[index].answered }"
                                           circle
                                           v-for="(value, index) in subjectIds"
                                           :key="index"
                                           @click="toSubject(value.everyID, value.type, index)">&nbsp;{{index + 1}}&nbsp;</el-button>
                            </el-row>
                        </el-dialog>
                    </div>
                </div>
            </el-card>
        </el-col>
    </el-row>
</template>
<script>
import { mapState } from 'vuex'
import CountDown from 'vue2-countdown'
import { saveAndNext } from '@/api/exam/answer'
import { getSubjectIds } from '@/api/exam/exam'
import { getCurrentTime } from '@/api/exam/examRecord'
import { getSubjectAnswer } from '@/api/exam/subject'
import moment from 'moment'
import { messageSuccess, messageFail, messageWarn, isNotEmpty } from '@/util/util'
import Tinymce from '@/components/Tinymce'
import Choices from '@/components/Subjects/Choices'
import MultipleChoices from '@/components/Subjects/MultipleChoices'
import PracticalOperation from '@/components/Subjects/PracticalOperation'
// import ShortAnswer from '@/components/Subjects/ShortAnswer'
import Judgement from '@/components/Subjects/Judgement'
import { nextSubjectType } from '@/const/constant'
export default {
    components: {
        CountDown,
        Tinymce,
        Choices,
        MultipleChoices,
        PracticalOperation,
        Judgement,
        // ShortAnswer,
    },
    data () {
        return {
            loadingLast: false,
            loadingNext: false,
            currentTime: 0,
            startTime: 0,
            endTime: 0,
            disableSubmit: true,
            subjectIndex: 1,
            query: {
                examinationId: undefined,
                examRecordId: undefined,
                subjectId: undefined,
                userId: undefined,
                type: 0
            },
            subject: {},
            answer: '',
            dialogVisible: false,
            subjectIds: [],
            subjectStartTime: undefined,
            exam: {
                id: '590969316204220416',
                creator: 'admin',
                createDate: 1560939664000,
                modifier: 'preview',
                modifyDate: 1609835214000,
                delFlag: 0,
                examinationName: '',
                startTime: null,
                endTime: null,
                totalScore: 50,
                status: 0,
                remark: '全国计算机统考练习题10道',
                newRecord: false
            },
            firstFlag: true
        }
    },
    computed: {
        ...mapState({
            userInfo: state => state.user.userInfo
        })
    },
    created () {
        const examInfo = this.$route.params.id
        if (isNotEmpty(examInfo)) {
            // 试卷ID
            this.query.examinationId = this.$route.params.id
            // 考场ID
            this.query.examRecordId = this.userInfo.user_id
            this.query.userId = this.userInfo.user_id
            this.exam.id = this.userInfo.user_id + '' + this.$route.params.id
            this.exam.examinationName = this.$route.query.examName
            this.exam.startTime = this.$route.query.startTime
            this.exam.endTime = this.$route.query.endTime
            this.exam.totalScore = this.$route.query.totalScore
            this.exam.status = this.$route.query.examStatus
            this.exam.remark = this.$route.query.remark
            this.validateExamTime()
        }
    },
    methods: {
        countDownS_cb: function () {
            messageSuccess(this, '考试开始')
        },
        validateExamTime () {
            getCurrentTime().then(response => {
                const currentTime = moment(response.data.data)
                if (currentTime.isAfter(this.exam.endTime)) {
                    messageWarn(this, '考试已结束')
                } else if (currentTime.isBefore(this.exam.startTime)) {
                    messageWarn(this, '考试未开始')
                } else {
                    this.startExam()
                    const current = currentTime.valueOf()
                    this.currentTime = current
                    this.startTime = current
                    this.subjectStartTime = current
                    this.endTime = moment(this.exam.endTime).valueOf()
                    this.disableSubmit = false
                }
            }).catch(() => {
                messageFail(this, '开始考试失败!15')
            })
        },
        startExam () {
            // 获取题目ID列表
            getSubjectIds({ id: this.query.examinationId }).then(subjectResponse => {
                const subjectData = subjectResponse.data.data.examExaminationSubjects
                if (subjectData.length > 0) {
                    for (let i = 0; i < subjectData.length; i++) {
                        const { examSubjectChoices } = subjectData[i]
                        this.subjectIds.push({
                            subjectId: subjectResponse.data.data.id,
                            everyID: examSubjectChoices.id,
                            type: examSubjectChoices.choicesType,
                            index: i + 1,
                            answered: false,
                            answer: examSubjectChoices.answer,
                            score: examSubjectChoices.score
                        })
                    }
                    this.query.type = parseInt(this.subjectIds[0].type)
                    // 准考证号
                    this.query.subjectId = this.subjectIds[0].everyID
                    this.updateSubjectIndex()
                    // 获取当前题目信息
                    getSubjectAnswer({
                        id: this.subjectIds[0].everyID,
                    }).then(response => {
                        if (isNotEmpty(response.data.data)) {
                            this.setSubjectInfo(response.data.data)
                        }
                    }).catch(() => {
                        messageFail(this, '获取题目失败!')
                    })
                }
            }).catch(() => {
                messageFail(this, '开始考试失败!4646549888*8*')
            })
        },
        countDownE_cb: function () {
            messageWarn(this, '考试结束')
            this.disableSubmit = true
        },
        last () {
            for (let i = 0; i < this.subjectIds.length; i++) {
                if (this.subjectIds[i].everyID == this.query.subjectId) {
                    this.subjectIds[i].answer = this.getAnswer()
                    this.markAnswered(this.subjectIds[i].answer, i)
                    if (i === 0) {
                        messageSuccess(this, '已经是第一题了')
                        break
                    }
                    let { everyID, type, index } = this.subjectIds[--i]
                    this.subjectIndex = index
                    this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.last, everyID, type)
                    break
                }
            }
        },
        next () {
            for (let i = 0; i < this.subjectIds.length; i++) {
                if (this.subjectIds[i].everyID == this.query.subjectId) {
                    this.subjectIds[i].answer = this.getAnswer()
                    this.markAnswered(this.subjectIds[i].answer, i)
                    if (i === this.subjectIds.length - 1) {
                        messageSuccess(this, '已经是最后一题了')
                        break
                    }
                    let { everyID, index } = this.subjectIds[++i]
                    this.subjectIndex = index
                    this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.next, everyID)
                    break
                }
            }
        },
        // 保存当前题目,同时根据序号加载下一题
        saveCurrentSubjectAndGetNextSubject (nextType, nextSubjectId) {
            this.startLoading(nextType)
            getSubjectAnswer({ id: nextSubjectId }).then(response => {
                if (response.data.data !== null) {
                    // 保存成功后更新答题卡状态
                    const subject = response.data.data
                    const { id, choicesType } = subject
                    this.query.subjectId = id
                    this.query.type = choicesType
                    for (let i = 0; i < this.subjectIds.length; i++) {
                        if (this.subjectIds[i].everyID == nextSubjectId) {
                            subject.answer = this.subjectIds[i].answer
                            break
                        }
                    }
                    this.setSubjectInfo(subject)
                    // store.dispatch('SetSubjectInfo', subject).then(() => { })
                }
                // 更新时间
                getCurrentTime().then(response => {
                    this.subjectStartTime = moment(response.data.data)
                })
                this.endLoading(nextType)
            }).catch((error) => {
                console.log(error)
                messageFail(this, '获取题目失败')
                this.endLoading(nextType)
            })
        },
        markAnswered (answer, index) {
            if (answer && answer !== null) {
                this.subjectIds[index].answered = true
            }
        },
        // 答题卡
        answerCard () {
            this.dialogVisible = true
        },
        // 跳转题目
        toSubject (everyID, type, index) {
            var ind = this.subjectIndex;
            if (this.firstFlag == false) {
                ind = this.subjectIndex;
            } else {
                ind = this.subjectIndex - 1;
            }
            this.subjectIds[ind].answer = this.getAnswer()
            this.markAnswered(this.subjectIds[ind].answer, ind)
            this.subjectIndex = index + 1
            this.firstFlag = true;
            // 保存当前题目,同时加载下一题
            this.saveCurrentSubjectAndGetNextSubject(nextSubjectType.next, everyID, type)
            this.dialogVisible = false
        },
        // 提交
        submitExam () {
            var ind = this.subjectIndex;
            if (this.firstFlag == false) {
                ind = this.subjectIndex;
            } else {
                ind = this.subjectIndex - 1;
            }
            this.subjectIds[ind].answer = this.getAnswer()
            this.markAnswered(this.subjectIds[ind].answer, ind)
            this.$confirm('确定要提交吗?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                this.disableSubmit = true
                this.doSubmitExam()
            }).catch(() => {
            })
        },
        doSubmitExam () {
            var obj = {
                examName: this.$route.query.examName,
                securityName: this.userInfo.user_name,
                securityId: this.userInfo.user_id,
                allScore: this.$route.query.totalScore,
                company: this.userInfo.dept_id,
                examTime: this.$route.query.startTime,
                papersId: this.$route.query.id,
                examEndTime: this.$route.query.endTime,
                examResultVOS: null
            }
            var arr = []
            this.subjectIds.forEach((item) => {
                if (item.type == 3) {
                    var str = ''
                    if (item.answer.length > 0) {
                        item.answer.forEach(it => {
                            if (it.value != '') {
                                str += it.value + ','
                            }
                        })
                        var a = str.substr(0, str.length - 1);
                        arr.push(
                            {
                                "subjectChoicesId": item.everyID,
                                "value": a,
                                "grade": item.score
                            }
                        )
                    }
                } else {
                    arr.push(
                        {
                            "subjectChoicesId": item.everyID,
                            "value": item.answer,
                            "grade": item.score
                        }
                    )
                }
            })
            obj.examResultVOS = arr
            saveAndNext(obj).then(response => {
                messageSuccess(this, '提交成功')
                if (response) {
                    this.$store.commit("DEL_TAG", this.$store.state.tags.tag);
                    this.$router.push({
                        path: `/singleperformance/index`,
                    });
                }
            }).catch(() => {
                this.disableSubmit = false
                messageFail(this, '提交题目失败')
            })
        },
        // 选中选项
        toggleOption (answer) {
            this.answer = answer
        },
        // 根据题目类型返回填写的答案
        getAnswer () {
            const ref = this.getSubjectRef()
            if (isNotEmpty(ref)) {
                const answer = ref.getAnswer()
                this.answer = answer
                return answer
                // {
                //     id: answerId,
                //     userId: this.userInfo.id,
                //     examinationId: this.query.examinationId,
                //     examRecordId: this.query.examRecordId,
                //     subjectId: this.query.subjectId,
                //     answer: answer,
                //     type: this.query.type,
                //     startTime: this.subjectStartTime
                // }
            }
            return {}
        },
        // 获取题目索引
        getSubjectIndex (targetId) {
            for (let subject of this.subjectIds) {
                let { subjectId, index } = subject
                if (subjectId === targetId) {
                    return index
                }
            }
            return 1
        },
        // 更新题目索引
        updateSubjectIndex () {
            this.subjectIndex = this.getSubjectIndex(this.query.subjectId)
        },
        startLoading (nextType) {
            if (nextType === nextSubjectType.next) {
                this.loadingNext = true
            } else if (nextType === nextSubjectType.last) {
                this.loadingLast = true
            } else {
                this.loadingNext = true
            }
        },
        endLoading (nextType) {
            if (nextType === nextSubjectType.next) {
                this.loadingNext = false
            } else if (nextType === nextSubjectType.last) {
                this.loadingLast = false
            } else {
                this.loadingNext = false
            }
        },
        getSubjectRef () {
            let ref
            switch (this.query.type) {
                case 0:
                    ref = this.$refs.choices
                    break
                case 1:
                    ref = this.$refs.multipleChoices
                    break
                case 2:
                    ref = this.$refs.judgement
                    break
                case 3:
                    ref = this.$refs.practicalOperation
                    break
                case 4:
                    ref = this.$refs.shortAnswer
                    break
            }
            return ref
        },
        setSubjectInfo (subject) {
            const ref = this.getSubjectRef()
            if (isNotEmpty(ref)) {
                try {
                    ref.setSubjectInfo(subject, this.subjectIds.length, this.subjectIndex)
                } catch (error) {
                    console.error(error)
                }
            }
        }
    }
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" rel="stylesheet/scss" scoped>
.subject-box {
    margin-top: 50px;
    margin-left: 20px;
}
.subject-box-card {
    width: 80%;
    margin-bottom: 30px;
    min-height: 400px;
}
.subject-buttons {
    text-align: right;
}
.tool-bar {
    margin-left: 20px;
}
.time-remain .time {
    display: inline-block;
    font-size: 18px;
    line-height: 22px;
    color: #ff0000;
    font-weight: 400;
}
/* 答题卡 */
.answer-card-title {
    font-size: 13px;
    color: #3a3e51;
    line-height: 17px;
    padding: 10px 0;
}
.answer-card-split {
    width: 100%;
    border-bottom: 1px solid #e6e6e6;
}
.answer-card-content {
    padding-bottom: 10px;
    font-size: 0;
    margin-right: -15px;
    > button {
        margin-top: 5px;
    }
}
.answered {
    background-color: greenyellow;
}
</style>
src/views/system/client.vue
@@ -1,30 +1,34 @@
<template>
  <basic-container>
    <avue-crud :option="option"
               :table-loading="loading"
               :data="data"
               :page.sync="page"
               @row-del="rowDel"
               v-model="form"
               ref="crud"
               :permission="permissionList"
               @row-update="rowUpdate"
               @row-save="rowSave"
               :before-open="beforeOpen"
               @search-change="searchChange"
               @search-reset="searchReset"
               @selection-change="selectionChange"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad">
  <basic-container class="hasButOne">
    <avue-crud
      :option="option"
      :table-loading="loading"
      :data="data"
      :page.sync="page"
      @row-del="rowDel"
      v-model="form"
      ref="crud"
      :permission="permissionList"
      @row-update="rowUpdate"
      @row-save="rowSave"
      :before-open="beforeOpen"
      @search-change="searchChange"
      @search-reset="searchReset"
      @selection-change="selectionChange"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
      @on-load="onLoad"
    >
      <template slot="menuLeft">
        <el-button type="danger"
                   size="small"
                   icon="el-icon-delete"
                   plain
                   v-if="permission.client_delete"
                   @click="handleDelete">删 除
        <el-button
          type="danger"
          size="small"
          icon="el-icon-delete"
          plain
          v-if="permission.client_delete"
          @click="handleDelete"
          >删 除
        </el-button>
      </template>
    </avue-crud>
@@ -32,301 +36,333 @@
</template>
<script>
  import {getList, getDetail, add, update, remove} from "@/api/system/client";
  import {mapGetters} from "vuex";
import { getList, getDetail, add, update, remove } from "@/api/system/client";
import { mapGetters } from "vuex";
  export default {
    data() {
      return {
        form: {},
        query: {},
        loading: true,
        page: {
          pageSize: 10,
          currentPage: 1,
          total: 0
        },
        selectionList: [],
        option: {
          height: 'auto',
          calcHeight: 30,
          tip: false,
          searchShow: true,
          searchMenuSpan: 6,
          border: true,
          index: true,
          viewBtn: true,
          selection: true,
          dialogClickModal: false,
          column: [
            {
              label: "应用id",
              prop: "clientId",
              search: true,
              rules: [{
export default {
  data() {
    return {
      form: {},
      query: {},
      loading: true,
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
      },
      selectionList: [],
      option: {
        height: "auto",
        calcHeight: 30,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        border: true,
        index: true,
        viewBtn: true,
        selection: true,
        dialogClickModal: false,
        column: [
          {
            label: "应用id",
            prop: "clientId",
            search: true,
            rules: [
              {
                required: true,
                message: "请输入客户端id",
                trigger: "blur"
              }]
            },
            {
              label: "应用密钥",
              prop: "clientSecret",
              search: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "应用密钥",
            prop: "clientSecret",
            search: true,
            rules: [
              {
                required: true,
                message: "请输入客户端密钥",
                trigger: "blur"
              }]
            },
            {
              label: "授权类型",
              prop: "authorizedGrantTypes",
              type: "checkbox",
              value: "refresh_token,password,authorization_code",
              dicData: [
                {
                  label: "refresh_token",
                  value: "refresh_token"
                },
                {
                  label: "password",
                  value: "password"
                },
                {
                  label: "authorization_code",
                  value: "authorization_code"
                },
                {
                  label: "captcha",
                  value: "captcha"
                },
                {
                  label: "social",
                  value: "social"
                }
              ],
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "授权类型",
            prop: "authorizedGrantTypes",
            type: "checkbox",
            value: "refresh_token,password,authorization_code",
            dicData: [
              {
                label: "refresh_token",
                value: "refresh_token",
              },
              {
                label: "password",
                value: "password",
              },
              {
                label: "authorization_code",
                value: "authorization_code",
              },
              {
                label: "captcha",
                value: "captcha",
              },
              {
                label: "social",
                value: "social",
              },
            ],
            rules: [
              {
                required: true,
                message: "请输入授权类型",
                trigger: "blur"
              }]
            },
            {
              label: "授权范围",
              prop: "scope",
              value: "all",
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "授权范围",
            prop: "scope",
            value: "all",
            rules: [
              {
                required: true,
                message: "请输入授权范围",
                trigger: "blur"
              }]
            },
            {
              label: "令牌秒数",
              prop: "accessTokenValidity",
              type: "number",
              value: 3600,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "令牌秒数",
            prop: "accessTokenValidity",
            type: "number",
            value: 3600,
            rules: [
              {
                required: true,
                message: "请输入令牌过期秒数",
                trigger: "blur"
              }]
            },
            {
              label: "刷新秒数",
              prop: "refreshTokenValidity",
              type: "number",
              value: 604800,
              hide: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "刷新秒数",
            prop: "refreshTokenValidity",
            type: "number",
            value: 604800,
            hide: true,
            rules: [
              {
                required: true,
                message: "请输入刷新令牌过期秒数",
                trigger: "blur"
              }]
            },
            {
              label: "回调地址",
              prop: "webServerRedirectUri",
              hide: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "回调地址",
            prop: "webServerRedirectUri",
            hide: true,
            rules: [
              {
                required: true,
                message: "请输入回调地址",
                trigger: "blur"
              }]
            },
            {
              label: "资源集合",
              prop: "resourceIds",
              hide: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "资源集合",
            prop: "resourceIds",
            hide: true,
            rules: [
              {
                message: "请输入资源集合",
                trigger: "blur"
              }]
            },
            {
              label: "权限",
              prop: "authorities",
              hide: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "权限",
            prop: "authorities",
            hide: true,
            rules: [
              {
                message: "请输入权限",
                trigger: "blur"
              }]
            },
            {
              label: "自动授权",
              prop: "autoapprove",
              hide: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "自动授权",
            prop: "autoapprove",
            hide: true,
            rules: [
              {
                message: "请输入自动授权",
                trigger: "blur"
              }]
            },
            {
              label: "附加说明",
              hide: true,
              prop: "additionalInformation",
              span: 24,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "附加说明",
            hide: true,
            prop: "additionalInformation",
            span: 24,
            rules: [
              {
                message: "请输入附加说明",
                trigger: "blur"
              }]
            },
          ]
        },
        data: []
                trigger: "blur",
              },
            ],
          },
        ],
      },
      data: [],
    };
  },
  computed: {
    ...mapGetters(["permission"]),
    permissionList() {
      return {
        addBtn: this.vaildData(this.permission.client_add),
        viewBtn: this.vaildData(this.permission.client_view),
        delBtn: this.vaildData(this.permission.client_delete),
        editBtn: this.vaildData(this.permission.client_edit),
      };
    },
    computed: {
      ...mapGetters(["permission"]),
      permissionList() {
        return {
          addBtn: this.vaildData(this.permission.client_add),
          viewBtn: this.vaildData(this.permission.client_view),
          delBtn: this.vaildData(this.permission.client_delete),
          editBtn: this.vaildData(this.permission.client_edit)
        };
      },
      ids() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids.join(",");
      }
    ids() {
      let ids = [];
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids.join(",");
    },
    methods: {
      rowSave(row, done, loading) {
        add(row).then(() => {
  },
  methods: {
    rowSave(row, done, loading) {
      add(row).then(
        () => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          done();
        }, error => {
        },
        (error) => {
          window.console.log(error);
          loading();
        });
      },
      rowUpdate(row, index, done, loading) {
        update(row).then(() => {
        }
      );
    },
    rowUpdate(row, index, done, loading) {
      update(row).then(
        () => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          done();
        }, error => {
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
        });
      },
      rowDel(row) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
    },
    searchReset() {
      this.query = {};
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      this.query = params;
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      this.$refs.crud.toggleSelection();
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
        return;
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
        })
          .then(() => {
            return remove(row.id);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
      },
      searchReset() {
        this.query = {};
        this.onLoad(this.page);
      },
      searchChange(params, done) {
        this.query = params;
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
      },
      selectionChange(list) {
        this.selectionList = list;
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(this.ids);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
      },
      beforeOpen(done, type) {
        if (["edit", "view"].includes(type)) {
          getDetail(this.form.id).then(res => {
            this.form = res.data.data;
          });
        }
        done();
      },
      currentChange(currentPage) {
        this.page.currentPage = currentPage;
      },
      sizeChange(pageSize) {
        this.page.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
      },
      onLoad(page, params = {}) {
        this.loading = true;
        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.loading = false;
          this.selectionClear();
          this.$refs.crud.toggleSelection();
        });
    },
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDetail(this.form.id).then((res) => {
          this.form = res.data.data;
        });
      }
    }
  };
      done();
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.query);
    },
    onLoad(page, params = {}) {
      this.loading = true;
      getList(
        page.currentPage,
        page.pageSize,
        Object.assign(params, this.query)
      ).then((res) => {
        const data = res.data.data;
        this.page.total = data.total;
        this.data = data.records;
        this.loading = false;
        this.selectionClear();
      });
    },
  },
};
</script>
<style>
src/views/system/dept.vue
@@ -1,5 +1,5 @@
<template>
  <basic-container>
  <basic-container class="hasButTwo">
    <avue-crud
      :option="option"
      :table-loading="loading"
src/views/system/dict.vue
@@ -1,5 +1,5 @@
<template>
  <basic-container>
  <basic-container class="hasButTwo">
    <avue-crud
      :option="optionParent"
      :table-loading="loading"
@@ -29,7 +29,7 @@
          v-if="permission.dict_delete"
          plain
          @click="handleDelete"
        >删 除
          >删 除
        </el-button>
      </template>
      <template slot-scope="scope" slot="menu">
@@ -39,20 +39,24 @@
          size="small"
          @click.stop="handleRowClick(scope.row)"
          v-if="userInfo.role_name.includes('admin')"
        >字典配置
          >字典配置
        </el-button>
      </template>
      <template slot-scope="{row}" slot="code">
        <el-tag @click="handleRowClick(row)" style="cursor:pointer">{{ row.code }}</el-tag>
      <template slot-scope="{ row }" slot="code">
        <el-tag @click="handleRowClick(row)" style="cursor: pointer">{{
          row.code
        }}</el-tag>
      </template>
      <template slot-scope="{row}" slot="isSealed">
        <el-tag>{{ row.isSealed === 0 ? '否' : '是' }}</el-tag>
      <template slot-scope="{ row }" slot="isSealed">
        <el-tag>{{ row.isSealed === 0 ? "否" : "是" }}</el-tag>
      </template>
    </avue-crud>
    <el-dialog :title="`[${dictValue}]字典配置`"
               append-to-body
               :visible.sync="box"
               width="1000px">
    <el-dialog
      :title="`[${dictValue}]字典配置`"
      append-to-body
      :visible.sync="box"
      width="1000px"
    >
      <avue-crud
        :option="optionChild"
        :table-loading="loadingChild"
@@ -81,7 +85,7 @@
            v-if="permission.dict_delete"
            plain
            @click="handleDelete"
          >删 除
            >删 除
          </el-button>
        </template>
        <template slot-scope="scope" slot="menu">
@@ -89,13 +93,13 @@
            type="text"
            icon="el-icon-circle-plus-outline"
            size="small"
            @click.stop="handleAdd(scope.row,scope.index)"
            @click.stop="handleAdd(scope.row, scope.index)"
            v-if="userInfo.role_name.includes('admin')"
          >新增子项
            >新增子项
          </el-button>
        </template>
        <template slot-scope="{row}" slot="isSealed">
          <el-tag>{{ row.isSealed === 0 ? '否' : '是' }}</el-tag>
        <template slot-scope="{ row }" slot="isSealed">
          <el-tag>{{ row.isSealed === 0 ? "否" : "是" }}</el-tag>
        </template>
      </avue-crud>
    </el-dialog>
@@ -110,15 +114,15 @@
  update,
  add,
  getDict,
  getDictTree
  getDictTree,
} from "@/api/system/dict";
import {optionParent, optionChild} from "@/option/system/dict";
import {mapGetters} from "vuex";
import { optionParent, optionChild } from "@/option/system/dict";
import { mapGetters } from "vuex";
export default {
  data() {
    return {
      dictValue: '暂无',
      dictValue: "暂无",
      parentId: -1,
      formParent: {},
      formChild: {},
@@ -131,13 +135,13 @@
        pageSize: 10,
        pageSizes: [10, 30, 50, 100, 200],
        currentPage: 1,
        total: 0
        total: 0,
      },
      pageChild: {
        pageSize: 10,
        pageSizes: [10, 30, 50, 100, 200],
        currentPage: 1,
        total: 0
        total: 0,
      },
      dataParent: [],
      dataChild: [],
@@ -157,18 +161,18 @@
    },
    ids() {
      let ids = [];
      this.selectionList.forEach(ele => {
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids.join(",");
    }
    },
  },
  mounted() {
    this.initData();
  },
  methods: {
    initData() {
      getDictTree().then(res => {
      getDictTree().then((res) => {
        const column = this.findObject(this.optionChild.column, "parentId");
        column.dicData = res.data.data;
      });
@@ -187,37 +191,43 @@
        ...row,
        dictKey: -1,
      };
      add(form).then(() => {
        this.onLoadParent(this.pageParent);
        this.$message({
          type: "success",
          message: "操作成功!"
        });
        done();
      }, error => {
        window.console.log(error);
        loading();
      });
      add(form).then(
        () => {
          this.onLoadParent(this.pageParent);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowUpdate(row, index, done, loading) {
      update(row).then(() => {
        this.onLoadParent(this.pageParent);
        this.$message({
          type: "success",
          message: "操作成功!"
        });
        this.onLoadChild(this.pageChild);
        done();
      }, error => {
        window.console.log(error);
        loading();
      });
      update(row).then(
        () => {
          this.onLoadParent(this.pageParent);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          this.onLoadChild(this.pageChild);
          done();
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
@@ -226,7 +236,7 @@
          this.onLoadParent(this.pageParent);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
        });
    },
@@ -268,7 +278,7 @@
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
@@ -277,14 +287,14 @@
          this.onLoadParent(this.pageParent);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          this.$refs.crud.toggleSelection();
        });
    },
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDict(this.formParent.id).then(res => {
        getDict(this.formParent.id).then((res) => {
          this.formParent = res.data.data;
        });
      }
@@ -300,36 +310,42 @@
      this.onLoadParent(this.pageParent, this.query);
    },
    rowSaveChild(row, done, loading) {
      add(row).then(() => {
        this.onLoadChild(this.pageChild);
        this.$message({
          type: "success",
          message: "操作成功!"
        });
        done();
      }, error => {
        window.console.log(error);
        loading();
      });
      add(row).then(
        () => {
          this.onLoadChild(this.pageChild);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowUpdateChild(row, index, done, loading) {
      update(row).then(() => {
        this.onLoadChild(this.pageChild);
        this.$message({
          type: "success",
          message: "操作成功!"
        });
        done();
      }, error => {
        window.console.log(error);
        loading();
      });
      update(row).then(
        () => {
          this.onLoadChild(this.pageChild);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowDelChild(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
@@ -338,7 +354,7 @@
          this.onLoadChild(this.pageChild);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
        });
    },
@@ -367,7 +383,7 @@
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
@@ -376,7 +392,7 @@
          this.onLoadChild(this.pageChild);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          this.$refs.crudChild.toggleSelection();
        });
@@ -386,7 +402,7 @@
        this.initData();
      }
      if (["edit", "view"].includes(type)) {
        getDict(this.formChild.id).then(res => {
        getDict(this.formChild.id).then((res) => {
          this.formChild = res.data.data;
        });
      }
@@ -394,7 +410,7 @@
    },
    beforeCloseChild(done) {
      this.$refs.crudChild.value.parentId = this.parentId;
      this.$refs.crudChild.option.column.filter(item => {
      this.$refs.crudChild.option.column.filter((item) => {
        if (item.prop === "parentId") {
          item.value = this.parentId;
        }
@@ -416,7 +432,7 @@
        page.currentPage,
        page.pageSize,
        Object.assign(params, this.query)
      ).then(res => {
      ).then((res) => {
        const data = res.data.data;
        this.pageParent.total = data.total;
        this.dataParent = data.records;
@@ -431,13 +447,13 @@
        page.pageSize,
        this.parentId,
        Object.assign(params, this.query)
      ).then(res => {
      ).then((res) => {
        this.dataChild = res.data.data;
        this.loadingChild = false;
        this.selectionClear();
      });
    }
  }
    },
  },
};
</script>
src/views/system/dictbiz.vue
@@ -1,5 +1,5 @@
<template>
  <basic-container>
  <basic-container class="hasButTwo">
    <avue-crud
      :option="optionParent"
      :table-loading="loading"
@@ -29,7 +29,7 @@
          v-if="permission.dictbiz_delete"
          plain
          @click="handleDelete"
        >删 除
          >删 除
        </el-button>
      </template>
      <template slot-scope="scope" slot="menu">
@@ -39,20 +39,24 @@
          size="small"
          @click.stop="handleRowClick(scope.row)"
          v-if="userInfo.role_name.includes('admin')"
        >字典配置
          >字典配置
        </el-button>
      </template>
      <template slot-scope="{row}" slot="code">
        <el-tag @click="handleRowClick(row)" style="cursor:pointer">{{ row.code }}</el-tag>
      <template slot-scope="{ row }" slot="code">
        <el-tag @click="handleRowClick(row)" style="cursor: pointer">{{
          row.code
        }}</el-tag>
      </template>
      <template slot-scope="{row}" slot="isSealed">
        <el-tag>{{ row.isSealed === 0 ? '否' : '是' }}</el-tag>
      <template slot-scope="{ row }" slot="isSealed">
        <el-tag>{{ row.isSealed === 0 ? "否" : "是" }}</el-tag>
      </template>
    </avue-crud>
    <el-dialog :title="`[${dictValue}]字典配置`"
               append-to-body
               :visible.sync="box"
               width="1000px">
    <el-dialog
      :title="`[${dictValue}]字典配置`"
      append-to-body
      :visible.sync="box"
      width="1000px"
    >
      <avue-crud
        :option="optionChild"
        :table-loading="loadingChild"
@@ -81,7 +85,7 @@
            v-if="permission.dict_delete"
            plain
            @click="handleDelete"
          >删 除
            >删 除
          </el-button>
        </template>
        <template slot-scope="scope" slot="menu">
@@ -89,13 +93,13 @@
            type="text"
            icon="el-icon-circle-plus-outline"
            size="small"
            @click.stop="handleAdd(scope.row,scope.index)"
            @click.stop="handleAdd(scope.row, scope.index)"
            v-if="userInfo.role_name.includes('admin')"
          >新增子项
            >新增子项
          </el-button>
        </template>
        <template slot-scope="{row}" slot="isSealed">
          <el-tag>{{ row.isSealed === 0 ? '否' : '是' }}</el-tag>
        <template slot-scope="{ row }" slot="isSealed">
          <el-tag>{{ row.isSealed === 0 ? "否" : "是" }}</el-tag>
        </template>
      </avue-crud>
    </el-dialog>
@@ -103,340 +107,352 @@
</template>
<script>
  import {
    getParentList,
    getChildList,
    remove,
    update,
    add,
    getDict,
    getDictTree
  } from "@/api/system/dictbiz";
  import {optionParent, optionChild} from "@/option/system/dictbiz";
  import {mapGetters} from "vuex";
import {
  getParentList,
  getChildList,
  remove,
  update,
  add,
  getDict,
  getDictTree,
} from "@/api/system/dictbiz";
import { optionParent, optionChild } from "@/option/system/dictbiz";
import { mapGetters } from "vuex";
  export default {
    data() {
export default {
  data() {
    return {
      dictValue: "暂无",
      parentId: -1,
      formParent: {},
      formChild: {},
      selectionList: [],
      query: {},
      box: false,
      loading: true,
      loadingChild: true,
      pageParent: {
        pageSize: 10,
        pageSizes: [10, 30, 50, 100, 200],
        currentPage: 1,
        total: 0,
      },
      pageChild: {
        pageSize: 10,
        pageSizes: [10, 30, 50, 100, 200],
        currentPage: 1,
        total: 0,
      },
      dataParent: [],
      dataChild: [],
      optionParent: optionParent,
      optionChild: optionChild,
    };
  },
  computed: {
    ...mapGetters(["userInfo", "permission"]),
    permissionList() {
      return {
        dictValue: '暂无',
        parentId: -1,
        formParent: {},
        formChild: {},
        selectionList: [],
        query: {},
        box: false,
        loading: true,
        loadingChild: true,
        pageParent: {
          pageSize: 10,
          pageSizes: [10, 30, 50, 100, 200],
          currentPage: 1,
          total: 0
        },
        pageChild: {
          pageSize: 10,
          pageSizes: [10, 30, 50, 100, 200],
          currentPage: 1,
          total: 0
        },
        dataParent: [],
        dataChild: [],
        optionParent: optionParent,
        optionChild: optionChild,
        addBtn: this.vaildData(this.permission.dictbiz_add, false),
        delBtn: this.vaildData(this.permission.dictbiz_delete, false),
        editBtn: this.vaildData(this.permission.dictbiz_edit, false),
        viewBtn: false,
      };
    },
    computed: {
      ...mapGetters(["userInfo", "permission"]),
      permissionList() {
        return {
          addBtn: this.vaildData(this.permission.dictbiz_add, false),
          delBtn: this.vaildData(this.permission.dictbiz_delete, false),
          editBtn: this.vaildData(this.permission.dictbiz_edit, false),
          viewBtn: false,
        };
      },
      ids() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids.join(",");
      }
    ids() {
      let ids = [];
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids.join(",");
    },
    mounted() {
      this.initData();
  },
  mounted() {
    this.initData();
  },
  methods: {
    initData() {
      getDictTree().then((res) => {
        const column = this.findObject(this.optionChild.column, "parentId");
        column.dicData = res.data.data;
      });
    },
    methods: {
      initData() {
        getDictTree().then(res => {
          const column = this.findObject(this.optionChild.column, "parentId");
          column.dicData = res.data.data;
        });
      },
      handleAdd(row) {
        this.formChild.dictValue = "";
        this.formChild.dictKey = "";
        this.formChild.sort = 0;
        this.formChild.isSealed = 0;
        this.formChild.remark = "";
        this.formChild.parentId = row.id;
        this.$refs.crudChild.rowAdd();
      },
      rowSave(row, done, loading) {
        const form = {
          ...row,
          dictKey: -1,
        };
        add(form).then(() => {
    handleAdd(row) {
      this.formChild.dictValue = "";
      this.formChild.dictKey = "";
      this.formChild.sort = 0;
      this.formChild.isSealed = 0;
      this.formChild.remark = "";
      this.formChild.parentId = row.id;
      this.$refs.crudChild.rowAdd();
    },
    rowSave(row, done, loading) {
      const form = {
        ...row,
        dictKey: -1,
      };
      add(form).then(
        () => {
          this.onLoadParent(this.pageParent);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          done();
        }, error => {
        },
        (error) => {
          window.console.log(error);
          loading();
        });
      },
      rowUpdate(row, index, done, loading) {
        update(row).then(() => {
        }
      );
    },
    rowUpdate(row, index, done, loading) {
      update(row).then(
        () => {
          this.onLoadParent(this.pageParent);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          this.onLoadChild(this.pageChild);
          done();
        }, error => {
        },
        (error) => {
          window.console.log(error);
          loading();
        });
      },
      rowDel(row) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(row.id);
          })
          .then(() => {
            this.onLoadParent(this.pageParent);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      handleRowClick(row) {
        this.query = {};
        this.parentId = row.id;
        this.dictValue = row.dictValue;
        const code = this.findObject(this.optionChild.column, "code");
        code.value = row.code;
        const parentId = this.findObject(this.optionChild.column, "parentId");
        parentId.value = row.id;
        this.box = true;
        this.onLoadChild(this.pageChild);
      },
      searchReset() {
        this.query = {};
        this.onLoadParent(this.pageParent);
      },
      searchChange(params, done) {
        this.query = params;
        this.pageParent.currentPage = 1;
        this.onLoadParent(this.pageParent, params);
        done();
      },
      selectionChange(list) {
        this.selectionList = list;
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
      );
    },
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
        })
          .then(() => {
            return remove(this.ids);
          })
          .then(() => {
            this.onLoadParent(this.pageParent);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
      },
      beforeOpen(done, type) {
        if (["edit", "view"].includes(type)) {
          getDict(this.formParent.id).then(res => {
            this.formParent = res.data.data;
          });
        }
        done();
      },
      currentChange(currentPage) {
        this.pageParent.currentPage = currentPage;
      },
      sizeChange(pageSize) {
        this.pageParent.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoadParent(this.pageParent, this.query);
      },
      rowSaveChild(row, done, loading) {
        add(row).then(() => {
          this.onLoadChild(this.pageChild);
        .then(() => {
          this.onLoadParent(this.pageParent);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          done();
        }, error => {
          window.console.log(error);
          loading();
        });
      },
      rowUpdateChild(row, index, done, loading) {
        update(row).then(() => {
          this.onLoadChild(this.pageChild);
    },
    handleRowClick(row) {
      this.query = {};
      this.parentId = row.id;
      this.dictValue = row.dictValue;
      const code = this.findObject(this.optionChild.column, "code");
      code.value = row.code;
      const parentId = this.findObject(this.optionChild.column, "parentId");
      parentId.value = row.id;
      this.box = true;
      this.onLoadChild(this.pageChild);
    },
    searchReset() {
      this.query = {};
      this.onLoadParent(this.pageParent);
    },
    searchChange(params, done) {
      this.query = params;
      this.pageParent.currentPage = 1;
      this.onLoadParent(this.pageParent, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      this.$refs.crud.toggleSelection();
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
        return;
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
        })
        .then(() => {
          this.onLoadParent(this.pageParent);
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          done();
        }, error => {
          window.console.log(error);
          loading();
          this.$refs.crud.toggleSelection();
        });
      },
      rowDelChild(row) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(row.id);
          })
          .then(() => {
            this.onLoadChild(this.pageChild);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      searchResetChild() {
        this.query = {};
        this.onLoadChild(this.pageChild);
      },
      searchChangeChild(params, done) {
        this.query = params;
        this.pageChild.currentPage = 1;
        this.onLoadChild(this.pageChild, params);
        done();
      },
      selectionChangeChild(list) {
        this.selectionList = list;
      },
      selectionClearChild() {
        this.selectionList = [];
        this.$refs.crudChild.toggleSelection();
      },
      handleDeleteChild() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(this.ids);
          })
          .then(() => {
            this.onLoadChild(this.pageChild);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crudChild.toggleSelection();
          });
      },
      beforeOpenChild(done, type) {
        if (["add", "edit"].includes(type)) {
          this.initData();
        }
        if (["edit", "view"].includes(type)) {
          getDict(this.formChild.id).then(res => {
            this.formChild = res.data.data;
          });
        }
        done();
      },
      beforeCloseChild(done) {
        this.$refs.crudChild.value.parentId = this.parentId;
        this.$refs.crudChild.option.column.filter(item => {
          if (item.prop === "parentId") {
            item.value = this.parentId;
          }
        });
        done();
      },
      currentChangeChild(currentPage) {
        this.pageChild.currentPage = currentPage;
      },
      sizeChangeChild(pageSize) {
        this.pageChild.pageSize = pageSize;
      },
      refreshChangeChild() {
        this.onLoadChild(this.pageChild, this.query);
      },
      onLoadParent(page, params = {}) {
        this.loading = true;
        getParentList(
          page.currentPage,
          page.pageSize,
          Object.assign(params, this.query)
        ).then(res => {
          const data = res.data.data;
          this.pageParent.total = data.total;
          this.dataParent = data.records;
          this.loading = false;
          this.selectionClear();
        });
      },
      onLoadChild(page, params = {}) {
        this.loadingChild = true;
        getChildList(
          page.currentPage,
          page.pageSize,
          this.parentId,
          Object.assign(params, this.query)
        ).then(res => {
          this.dataChild = res.data.data;
          this.loadingChild = false;
          this.selectionClear();
    },
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDict(this.formParent.id).then((res) => {
          this.formParent = res.data.data;
        });
      }
    }
  };
      done();
    },
    currentChange(currentPage) {
      this.pageParent.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.pageParent.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoadParent(this.pageParent, this.query);
    },
    rowSaveChild(row, done, loading) {
      add(row).then(
        () => {
          this.onLoadChild(this.pageChild);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowUpdateChild(row, index, done, loading) {
      update(row).then(
        () => {
          this.onLoadChild(this.pageChild);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowDelChild(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
        })
        .then(() => {
          this.onLoadChild(this.pageChild);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
        });
    },
    searchResetChild() {
      this.query = {};
      this.onLoadChild(this.pageChild);
    },
    searchChangeChild(params, done) {
      this.query = params;
      this.pageChild.currentPage = 1;
      this.onLoadChild(this.pageChild, params);
      done();
    },
    selectionChangeChild(list) {
      this.selectionList = list;
    },
    selectionClearChild() {
      this.selectionList = [];
      this.$refs.crudChild.toggleSelection();
    },
    handleDeleteChild() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
        return;
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
        })
        .then(() => {
          this.onLoadChild(this.pageChild);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          this.$refs.crudChild.toggleSelection();
        });
    },
    beforeOpenChild(done, type) {
      if (["add", "edit"].includes(type)) {
        this.initData();
      }
      if (["edit", "view"].includes(type)) {
        getDict(this.formChild.id).then((res) => {
          this.formChild = res.data.data;
        });
      }
      done();
    },
    beforeCloseChild(done) {
      this.$refs.crudChild.value.parentId = this.parentId;
      this.$refs.crudChild.option.column.filter((item) => {
        if (item.prop === "parentId") {
          item.value = this.parentId;
        }
      });
      done();
    },
    currentChangeChild(currentPage) {
      this.pageChild.currentPage = currentPage;
    },
    sizeChangeChild(pageSize) {
      this.pageChild.pageSize = pageSize;
    },
    refreshChangeChild() {
      this.onLoadChild(this.pageChild, this.query);
    },
    onLoadParent(page, params = {}) {
      this.loading = true;
      getParentList(
        page.currentPage,
        page.pageSize,
        Object.assign(params, this.query)
      ).then((res) => {
        const data = res.data.data;
        this.pageParent.total = data.total;
        this.dataParent = data.records;
        this.loading = false;
        this.selectionClear();
      });
    },
    onLoadChild(page, params = {}) {
      this.loadingChild = true;
      getChildList(
        page.currentPage,
        page.pageSize,
        this.parentId,
        Object.assign(params, this.query)
      ).then((res) => {
        this.dataChild = res.data.data;
        this.loadingChild = false;
        this.selectionClear();
      });
    },
  },
};
</script>
src/views/system/menu.vue
@@ -1,31 +1,35 @@
<template>
  <basic-container>
    <avue-crud :option="option"
               :table-loading="loading"
               :data="data"
               ref="crud"
               v-model="form"
               :permission="permissionList"
               :before-open="beforeOpen"
               :before-close="beforeClose"
               @row-del="rowDel"
               @row-update="rowUpdate"
               @row-save="rowSave"
               @search-change="searchChange"
               @search-reset="searchReset"
               @selection-change="selectionChange"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad"
               @tree-load="treeLoad">
  <basic-container class="hasButTwo">
    <avue-crud
      :option="option"
      :table-loading="loading"
      :data="data"
      ref="crud"
      v-model="form"
      :permission="permissionList"
      :before-open="beforeOpen"
      :before-close="beforeClose"
      @row-del="rowDel"
      @row-update="rowUpdate"
      @row-save="rowSave"
      @search-change="searchChange"
      @search-reset="searchReset"
      @selection-change="selectionChange"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
      @on-load="onLoad"
      @tree-load="treeLoad"
    >
      <template slot="menuLeft">
        <el-button type="danger"
                   size="small"
                   icon="el-icon-delete"
                   v-if="permission.menu_delete"
                   plain
                   @click="handleDelete">删 除
        <el-button
          type="danger"
          size="small"
          icon="el-icon-delete"
          v-if="permission.menu_delete"
          plain
          @click="handleDelete"
          >删 除
        </el-button>
      </template>
      <template slot-scope="scope" slot="menu">
@@ -33,15 +37,16 @@
          type="text"
          icon="el-icon-circle-plus-outline"
          size="small"
          @click.stop="handleAdd(scope.row,scope.index)"
          v-if="userInfo.role_name.includes('admin') && scope.row.category === 1"
        >新增子项
          @click.stop="handleAdd(scope.row, scope.index)"
          v-if="
            userInfo.role_name.includes('admin') && scope.row.category === 1
          "
          >新增子项
        </el-button>
      </template>
      <template slot-scope="{row}"
                slot="source">
        <div style="text-align:center">
          <i :class="row.source"/>
      <template slot-scope="{ row }" slot="source">
        <div style="text-align: center">
          <i :class="row.source" />
        </div>
      </template>
    </avue-crud>
@@ -49,374 +54,382 @@
</template>
<script>
  import {getLazyList, remove, update, add, getMenu} from "@/api/system/menu";
  import {mapGetters} from "vuex";
  import iconList from "@/config/iconList";
  import func from "@/util/func";
  import {getMenuTree} from "@/api/system/menu";
import { getLazyList, remove, update, add, getMenu } from "@/api/system/menu";
import { mapGetters } from "vuex";
import iconList from "@/config/iconList";
import func from "@/util/func";
import { getMenuTree } from "@/api/system/menu";
  export default {
    data() {
      return {
        form: {},
        query: {},
        loading: true,
        selectionList: [],
        parentId: 0,
        page: {
          pageSize: 10,
          currentPage: 1,
          total: 0,
        },
        option: {
          lazy: true,
          tip: false,
          simplePage: true,
          searchShow: true,
          searchMenuSpan: 6,
          dialogWidth: "60%",
          tree: true,
          border: true,
          index: true,
          selection: true,
          viewBtn: true,
          menuWidth: 300,
          dialogClickModal: false,
          column: [
            {
              label: "菜单名称",
              prop: "name",
              search: true,
              rules: [
                {
                  required: true,
                  message: "请输入菜单名称",
                  trigger: "blur"
                }
              ]
            },
            {
              label: "路由地址",
              prop: "path",
              rules: [
                {
                  required: true,
                  message: "请输入路由地址",
                  trigger: "blur"
                }
              ]
            },
            {
              label: "上级菜单",
              prop: "parentId",
              type: "tree",
              dicData: [],
              hide: true,
              addDisabled: false,
              props: {
                label: "title"
export default {
  data() {
    return {
      form: {},
      query: {},
      loading: true,
      selectionList: [],
      parentId: 0,
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
      },
      option: {
        lazy: true,
        tip: false,
        simplePage: true,
        searchShow: true,
        searchMenuSpan: 6,
        dialogWidth: "60%",
        tree: true,
        border: true,
        index: true,
        selection: true,
        viewBtn: true,
        menuWidth: 300,
        dialogClickModal: false,
        column: [
          {
            label: "菜单名称",
            prop: "name",
            search: true,
            rules: [
              {
                required: true,
                message: "请输入菜单名称",
                trigger: "blur",
              },
              rules: [
                {
                  required: false,
                  message: "请选择上级菜单",
                  trigger: "click"
                }
              ]
            ],
          },
          {
            label: "路由地址",
            prop: "path",
            rules: [
              {
                required: true,
                message: "请输入路由地址",
                trigger: "blur",
              },
            ],
          },
          {
            label: "上级菜单",
            prop: "parentId",
            type: "tree",
            dicData: [],
            hide: true,
            addDisabled: false,
            props: {
              label: "title",
            },
            {
              label: "菜单图标",
              prop: "source",
              type: "icon",
              slot: true,
              iconList: iconList,
              rules: [
                {
                  required: true,
                  message: "请输入菜单图标",
                  trigger: "click"
                }
              ]
            },
            {
              label: "菜单编号",
              prop: "code",
              search: true,
              rules: [
                {
                  required: true,
                  message: "请输入菜单编号",
                  trigger: "blur"
                }
              ]
            },
            {
              label: "菜单类型",
              prop: "category",
              type: "radio",
              dicData: [
                {
                  label: "菜单",
                  value: 1
                },
                {
                  label: "按钮",
                  value: 2
                }
              ],
              hide: true,
              rules: [
                {
                  required: true,
                  message: "请选择菜单类型",
                  trigger: "blur"
                }
              ]
            },
            {
              label: "菜单别名",
              prop: "alias",
              search: true,
              rules: [
                {
                  required: true,
                  message: "请输入菜单别名",
                  trigger: "blur"
                }
              ]
            },
            {
              label: "新窗口",
              prop: "isOpen",
              type: "radio",
              disabled: false,
              dicData: [
                {
                  label: "否",
                  value: 1
                },
                {
                  label: "是",
                  value: 2
                }
              ],
              value: 1,
              rules: [
                {
                  required: true,
                  message: "请选择新窗口打开",
                  trigger: "blur"
                }
              ]
            },
            {
              label: "菜单排序",
              prop: "sort",
              type: "number",
              row: true,
              span: 24,
              rules: [
                {
                  required: true,
                  message: "请输入菜单排序",
                  trigger: "blur"
                }
              ]
            },
            {
              label: "菜单备注",
              prop: "remark",
              type: "textarea",
              span: 24,
              minRows: 2,
              hide: true
            }
          ]
        },
        data: []
            rules: [
              {
                required: false,
                message: "请选择上级菜单",
                trigger: "click",
              },
            ],
          },
          {
            label: "菜单图标",
            prop: "source",
            type: "icon",
            slot: true,
            iconList: iconList,
            rules: [
              {
                required: true,
                message: "请输入菜单图标",
                trigger: "click",
              },
            ],
          },
          {
            label: "菜单编号",
            prop: "code",
            search: true,
            rules: [
              {
                required: true,
                message: "请输入菜单编号",
                trigger: "blur",
              },
            ],
          },
          {
            label: "菜单类型",
            prop: "category",
            type: "radio",
            dicData: [
              {
                label: "菜单",
                value: 1,
              },
              {
                label: "按钮",
                value: 2,
              },
            ],
            hide: true,
            rules: [
              {
                required: true,
                message: "请选择菜单类型",
                trigger: "blur",
              },
            ],
          },
          {
            label: "菜单别名",
            prop: "alias",
            search: true,
            rules: [
              {
                required: true,
                message: "请输入菜单别名",
                trigger: "blur",
              },
            ],
          },
          {
            label: "新窗口",
            prop: "isOpen",
            type: "radio",
            disabled: false,
            dicData: [
              {
                label: "否",
                value: 1,
              },
              {
                label: "是",
                value: 2,
              },
            ],
            value: 1,
            rules: [
              {
                required: true,
                message: "请选择新窗口打开",
                trigger: "blur",
              },
            ],
          },
          {
            label: "菜单排序",
            prop: "sort",
            type: "number",
            row: true,
            span: 24,
            rules: [
              {
                required: true,
                message: "请输入菜单排序",
                trigger: "blur",
              },
            ],
          },
          {
            label: "菜单备注",
            prop: "remark",
            type: "textarea",
            span: 24,
            minRows: 2,
            hide: true,
          },
        ],
      },
      data: [],
    };
  },
  watch: {
    "form.category"() {
      const category = func.toInt(this.form.category);
      this.$refs.crud.option.column.filter((item) => {
        if (item.prop === "path") {
          item.rules[0].required = category === 1;
        }
        if (item.prop === "isOpen") {
          item.disabled = category === 2;
        }
      });
    },
  },
  computed: {
    ...mapGetters(["userInfo", "permission"]),
    permissionList() {
      return {
        addBtn: this.vaildData(this.permission.menu_add, false),
        viewBtn: this.vaildData(this.permission.menu_view, false),
        delBtn: this.vaildData(this.permission.menu_delete, false),
        editBtn: this.vaildData(this.permission.menu_edit, false),
      };
    },
    watch: {
      'form.category'() {
        const category = func.toInt(this.form.category);
        this.$refs.crud.option.column.filter(item => {
          if (item.prop === "path") {
            item.rules[0].required = category === 1;
          }
          if (item.prop === 'isOpen') {
            item.disabled = category === 2;
          }
        });
      },
    ids() {
      let ids = [];
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids.join(",");
    },
    computed: {
      ...mapGetters(["userInfo", "permission"]),
      permissionList() {
        return {
          addBtn: this.vaildData(this.permission.menu_add, false),
          viewBtn: this.vaildData(this.permission.menu_view, false),
          delBtn: this.vaildData(this.permission.menu_delete, false),
          editBtn: this.vaildData(this.permission.menu_edit, false)
        };
      },
      ids() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids.join(",");
      }
    },
    methods: {
      initData() {
        getMenuTree().then(res => {
          const column = this.findObject(this.option.column, "parentId");
          column.dicData = res.data.data;
        });
      },
      handleAdd(row) {
        this.parentId = row.id;
  },
  methods: {
    initData() {
      getMenuTree().then((res) => {
        const column = this.findObject(this.option.column, "parentId");
        column.value = row.id;
        column.addDisabled = true;
        this.$refs.crud.rowAdd();
      },
      rowSave(row, done, loading) {
        add(row).then((res) => {
        column.dicData = res.data.data;
      });
    },
    handleAdd(row) {
      this.parentId = row.id;
      const column = this.findObject(this.option.column, "parentId");
      column.value = row.id;
      column.addDisabled = true;
      this.$refs.crud.rowAdd();
    },
    rowSave(row, done, loading) {
      add(row).then(
        (res) => {
          // 获取新增数据的相关字段
          const data = res.data.data;
          row.id = data.id;
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          // 数据回调进行刷新
          done(row);
        }, error => {
        },
        (error) => {
          window.console.log(error);
          loading();
        });
      },
      rowUpdate(row, index, done, loading) {
        update(row).then(() => {
        }
      );
    },
    rowUpdate(row, index, done, loading) {
      update(row).then(
        () => {
          this.$message({
            type: "success",
            message: "操作成功!"
            message: "操作成功!",
          });
          // 数据回调进行刷新
          done(row);
        }, error => {
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowDel(row, index, done) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
        })
        .then(() => {
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          // 数据回调进行刷新
          done(row);
        });
      },
      rowDel(row, index, done) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
        return;
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
        })
          .then(() => {
            return remove(row.id);
          })
          .then(() => {
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            // 数据回调进行刷新
            done(row);
        .then(() => {
          // 刷新表格数据并重载
          this.data = [];
          this.parentId = 0;
          this.$refs.crud.refreshTable();
          this.$refs.crud.toggleSelection();
          // 表格数据重载
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(this.ids);
          })
          .then(() => {
            // 刷新表格数据并重载
            this.data = [];
            this.parentId = 0;
            this.$refs.crud.refreshTable();
            this.$refs.crud.toggleSelection();
            // 表格数据重载
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      searchReset() {
        this.query = {};
        this.parentId = 0;
        this.onLoad(this.page);
      },
      searchChange(params, done) {
        this.query = params;
        this.parentId = '';
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
      },
      selectionChange(list) {
        this.selectionList = list;
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
      },
      beforeOpen(done, type) {
        if (["add", "edit"].includes(type)) {
          this.initData();
        }
        if (["edit", "view"].includes(type)) {
          getMenu(this.form.id).then(res => {
            this.form = res.data.data;
          });
        }
        done();
      },
      beforeClose(done) {
        this.parentId = "";
        const column = this.findObject(this.option.column, "parentId");
        column.value = "";
        column.addDisabled = false;
        done();
      },
      currentChange(currentPage) {
        this.page.currentPage = currentPage;
      },
      sizeChange(pageSize) {
        this.page.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
      },
      onLoad(page, params = {}) {
        this.loading = true;
        getLazyList(this.parentId, Object.assign(params, this.query)).then(res => {
        });
    },
    searchReset() {
      this.query = {};
      this.parentId = 0;
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      this.query = params;
      this.parentId = "";
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      this.$refs.crud.toggleSelection();
    },
    beforeOpen(done, type) {
      if (["add", "edit"].includes(type)) {
        this.initData();
      }
      if (["edit", "view"].includes(type)) {
        getMenu(this.form.id).then((res) => {
          this.form = res.data.data;
        });
      }
      done();
    },
    beforeClose(done) {
      this.parentId = "";
      const column = this.findObject(this.option.column, "parentId");
      column.value = "";
      column.addDisabled = false;
      done();
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.query);
    },
    onLoad(page, params = {}) {
      this.loading = true;
      getLazyList(this.parentId, Object.assign(params, this.query)).then(
        (res) => {
          this.data = res.data.data;
          this.loading = false;
          this.selectionClear();
        });
      },
      treeLoad(tree, treeNode, resolve) {
        const parentId = tree.id;
        getLazyList(parentId).then(res => {
          resolve(res.data.data);
        });
      }
    }
  };
        }
      );
    },
    treeLoad(tree, treeNode, resolve) {
      const parentId = tree.id;
      getLazyList(parentId).then((res) => {
        resolve(res.data.data);
      });
    },
  },
};
</script>
<style>
src/views/system/topmenu.vue
@@ -1,332 +1,371 @@
<template>
  <basic-container>
    <avue-crud :option="option"
               :table-loading="loading"
               :data="data"
               :page.sync="page"
               :permission="permissionList"
               :before-open="beforeOpen"
               v-model="form"
               ref="crud"
               @row-update="rowUpdate"
               @row-save="rowSave"
               @row-del="rowDel"
               @search-change="searchChange"
               @search-reset="searchReset"
               @selection-change="selectionChange"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad">
  <basic-container class="topmenu">
    <avue-crud
      :option="option"
      :table-loading="loading"
      :data="data"
      :page.sync="page"
      :permission="permissionList"
      :before-open="beforeOpen"
      v-model="form"
      ref="crud"
      @row-update="rowUpdate"
      @row-save="rowSave"
      @row-del="rowDel"
      @search-change="searchChange"
      @search-reset="searchReset"
      @selection-change="selectionChange"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
      @on-load="onLoad"
    >
      <template slot="menuLeft">
        <el-button type="danger"
                   size="small"
                   icon="el-icon-delete"
                   plain
                   v-if="permission.topmenu_delete"
                   @click="handleDelete">删 除
        <el-button
          type="danger"
          size="small"
          icon="el-icon-delete"
          plain
          v-if="permission.topmenu_delete"
          @click="handleDelete"
          >删 除
        </el-button>
        <el-button size="small"
                   icon="el-icon-delete"
                   @click="handleMenuSetting"
                   v-if="permission.topmenu_setting"
                   plain>菜单配置
        <el-button
          size="small"
          icon="el-icon-delete"
          @click="handleMenuSetting"
          v-if="permission.topmenu_setting"
          plain
          >菜单配置
        </el-button>
      </template>
      <template slot-scope="{row}" slot="source">
        <div style="text-align:center">
      <template slot-scope="{ row }" slot="source">
        <div style="text-align: center">
          <i :class="row.source"></i>
        </div>
      </template>
      <template slot="sort" slot-scope="{row}" >
        <el-input-number v-model="row.sort" @change="sortChange(row)" :min="1" :max="100"></el-input-number>
      <template slot="sort" slot-scope="{ row }">
        <el-input-number
          v-model="row.sort"
          @change="sortChange(row)"
          :min="1"
          :max="100"
        ></el-input-number>
      </template>
    </avue-crud>
    <el-dialog title="下级菜单配置"
               append-to-body
               :visible.sync="box"
               width="345px">
      <el-tree :data="menuGrantList"
               show-checkbox
               node-key="id"
               ref="treeMenu"
               :default-checked-keys="menuTreeObj"
               :props="props">
    <el-dialog
      title="下级菜单配置"
      append-to-body
      :visible.sync="box"
      width="345px"
    >
      <el-tree
        :data="menuGrantList"
        show-checkbox
        node-key="id"
        ref="treeMenu"
        :default-checked-keys="menuTreeObj"
        :props="props"
      >
      </el-tree>
      <span slot="footer"
            class="dialog-footer">
      <span slot="footer" class="dialog-footer">
        <el-button @click="box = false">取 消</el-button>
        <el-button type="primary"
                   @click="submit">确 定</el-button>
        <el-button type="primary" @click="submit">确 定</el-button>
      </span>
    </el-dialog>
  </basic-container>
</template>
<script>
  import {getList, getDetail, add, update, remove, grant, grantTree, getTopTree} from "@/api/system/topmenu";
  import {mapGetters} from "vuex";
  import iconList from "@/config/iconList";
import {
  getList,
  getDetail,
  add,
  update,
  remove,
  grant,
  grantTree,
  getTopTree,
} from "@/api/system/topmenu";
import { mapGetters } from "vuex";
import iconList from "@/config/iconList";
  export default {
    data() {
      return {
        form: {},
        box: false,
        query: {},
        loading: true,
        props: {
          label: "title",
          value: "key"
        },
        page: {
          pageSize: 10,
          currentPage: 1,
          total: 0
        },
        selectionList: [],
        menuGrantList: [],
        menuTreeObj: [],
        option: {
          height: 'auto',
          calcHeight: 30,
          tip: false,
          searchShow: true,
          searchMenuSpan: 6,
          border: true,
          index: true,
          viewBtn: true,
          selection: true,
          dialogWidth: 900,
          dialogClickModal: false,
          column: [
            {
              label: "菜单名",
              prop: "name",
              search: true,
              rules: [{
export default {
  data() {
    return {
      form: {},
      box: false,
      query: {},
      loading: true,
      props: {
        label: "title",
        value: "key",
      },
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
      },
      selectionList: [],
      menuGrantList: [],
      menuTreeObj: [],
      option: {
        height: "auto",
        calcHeight: 30,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        border: true,
        index: true,
        viewBtn: true,
        selection: true,
        dialogWidth: 900,
        dialogClickModal: false,
        column: [
          {
            label: "菜单名",
            prop: "name",
            search: true,
            rules: [
              {
                required: true,
                message: "请输入菜单名",
                trigger: "blur"
              }]
            },
            {
              label: "菜单图标",
              prop: "source",
              type: "icon",
              slot: true,
              iconList: iconList,
              rules: [
                {
                  required: true,
                  message: "请输入菜单图标",
                  trigger: "click"
                }
              ]
            },
            {
              label: "菜单编号",
              prop: "code",
              search: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "菜单图标",
            prop: "source",
            type: "icon",
            slot: true,
            iconList: iconList,
            rules: [
              {
                required: true,
                message: "请输入菜单图标",
                trigger: "click",
              },
            ],
          },
          {
            label: "菜单编号",
            prop: "code",
            search: true,
            rules: [
              {
                required: true,
                message: "请输入菜单编号",
                trigger: "blur"
              }]
            },
            {
              label: "菜单排序",
              prop: "sort",
              type: "number",
              slot: true,
              rules: [{
                trigger: "blur",
              },
            ],
          },
          {
            label: "菜单排序",
            prop: "sort",
            type: "number",
            slot: true,
            rules: [
              {
                required: true,
                message: "请输入菜单排序",
                trigger: "blur"
              }]
            },
          ]
        },
        data: []
                trigger: "blur",
              },
            ],
          },
        ],
      },
      data: [],
    };
  },
  computed: {
    ...mapGetters(["permission"]),
    permissionList() {
      return {
        addBtn: this.vaildData(this.permission.topmenu_add, false),
        viewBtn: this.vaildData(this.permission.topmenu_view, false),
        delBtn: this.vaildData(this.permission.topmenu_delete, false),
        editBtn: this.vaildData(this.permission.topmenu_edit, false),
      };
    },
    computed: {
      ...mapGetters(["permission"]),
      permissionList() {
        return {
          addBtn: this.vaildData(this.permission.topmenu_add, false),
          viewBtn: this.vaildData(this.permission.topmenu_view, false),
          delBtn: this.vaildData(this.permission.topmenu_delete, false),
          editBtn: this.vaildData(this.permission.topmenu_edit, false)
        };
      },
      ids() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids.join(",");
      },
      idsArray() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids;
      }
    ids() {
      let ids = [];
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids.join(",");
    },
    methods: {
      submit() {
        const menuList = this.$refs.treeMenu.getCheckedKeys();
        grant(this.idsArray, menuList).then(() => {
          this.box = false;
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          this.onLoad(this.page);
    idsArray() {
      let ids = [];
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids;
    },
  },
  methods: {
    submit() {
      const menuList = this.$refs.treeMenu.getCheckedKeys();
      grant(this.idsArray, menuList).then(() => {
        this.box = false;
        this.$message({
          type: "success",
          message: "操作成功!",
        });
      },
      rowSave(row, done, loading) {
        add(row).then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          window.console.log(error);
          loading();
        });
      },
      rowUpdate(row, index, done, loading) {
        update(row).then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          window.console.log(error);
          loading();
        });
      },
      rowDel(row) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(row.id);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(this.ids);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
      },
      handleMenuSetting() {
        if (this.selectionList.length !== 1) {
          this.$message.warning("只能选择一条数据");
          return;
        }
        this.menuTreeObj = [];
        grantTree()
          .then(res => {
            this.menuGrantList = res.data.data.menu;
            getTopTree(this.ids).then(res => {
              this.menuTreeObj = res.data.data.menu;
              this.box = true;
            });
          });
      },
      beforeOpen(done, type) {
        if (["edit", "view"].includes(type)) {
          getDetail(this.form.id).then(res => {
            this.form = res.data.data;
          });
        }
        done();
      },
      sortChange(row) {
        update(row).then(() => {
          this.onLoad(this.page);
        }, error => {
          window.console.log(error);
        });
      },
      searchReset() {
        this.query = {};
        this.onLoad(this.page);
      },
      searchChange(params, done) {
        this.query = params;
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
      },
      selectionChange(list) {
        this.selectionList = list;
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
      },
      currentChange(currentPage) {
        this.page.currentPage = currentPage;
      },
      sizeChange(pageSize) {
        this.page.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
      },
      onLoad(page, params = {}) {
        this.loading = true;
        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.loading = false;
          this.selectionClear();
      });
    },
    rowSave(row, done, loading) {
      add(row).then(
        () => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowUpdate(row, index, done, loading) {
      update(row).then(
        () => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          window.console.log(error);
          loading();
        }
      );
    },
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
        });
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
        return;
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          this.$refs.crud.toggleSelection();
        });
    },
    handleMenuSetting() {
      if (this.selectionList.length !== 1) {
        this.$message.warning("只能选择一条数据");
        return;
      }
      this.menuTreeObj = [];
      grantTree().then((res) => {
        this.menuGrantList = res.data.data.menu;
        getTopTree(this.ids).then((res) => {
          this.menuTreeObj = res.data.data.menu;
          this.box = true;
        });
      });
    },
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDetail(this.form.id).then((res) => {
          this.form = res.data.data;
        });
      }
    }
  };
      done();
    },
    sortChange(row) {
      update(row).then(
        () => {
          this.onLoad(this.page);
        },
        (error) => {
          window.console.log(error);
        }
      );
    },
    searchReset() {
      this.query = {};
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      this.query = params;
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      this.$refs.crud.toggleSelection();
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.query);
    },
    onLoad(page, params = {}) {
      this.loading = true;
      getList(
        page.currentPage,
        page.pageSize,
        Object.assign(params, this.query)
      ).then((res) => {
        const data = res.data.data;
        this.page.total = data.total;
        this.data = data.records;
        this.loading = false;
        this.selectionClear();
      });
    },
  },
};
</script>
<style>
  .none-border {
    border: 0;
    background-color: transparent !important;
  }
.none-border {
  border: 0;
  background-color: transparent !important;
}
</style>
src/views/system/user.vue
@@ -1,5 +1,5 @@
<template>
  <el-row>
  <el-row class="user">
    <el-col :span="5">
      <div class="box">
        <el-scrollbar>
src/views/trainingRegistration/index.vue
@@ -64,12 +64,13 @@
        tip: false,
        searchSize: "mini",
        searchMenuSpan: 6,
        height: 627,
        height: 693,
        index: true,
        menuWidth: 290,
        align: "center",
        selection: true,
        column: column,
        delBtn: false
        delBtn: false,
      },
    };
  },
src/views/workreport/data.js
@@ -1,230 +1,230 @@
//已发送列表信息
export var workreportColumn = [{
        label: "汇报时间",
        prop: "reportTime",
        type: "datetime",
        format: "yyyy-MM-dd HH:mm:ss",
        valueFormat: "yyyy-MM-dd HH:mm:ss",
        searchRange: true,
        searchSpan: 6,
        hide: false,
        addDisplay: false,
        editDisplay: false,
        // viewDisplay: false,
        search: false,
        rules: [{
            required: true,
            message: "请输入时间",
            trigger: "blur"
        }]
    }, {
        label: "汇报类别",
        prop: "category",
        type: "select",
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=workReportCategory",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        dataType: "number",
        searchSpan: 4,
        search: true,
        rules: [{
            required: true,
            message: "请选择汇报类别",
            trigger: "blur"
        }]
    }, {
        label: "汇报类型",
        prop: "type",
        type: "select",
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=workReportType",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        dataType: "number",
        searchSpan: 4,
        search: true,
        rules: [{
            required: true,
            message: "请选择汇报类型",
            trigger: "blur"
        }]
    label: "汇报时间",
    prop: "reportTime",
    type: "datetime",
    format: "yyyy-MM-dd HH:mm:ss",
    valueFormat: "yyyy-MM-dd HH:mm:ss",
    searchRange: true,
    searchSpan: 6,
    hide: false,
    addDisplay: false,
    editDisplay: false,
    // viewDisplay: false,
    search: false,
    rules: [{
        required: true,
        message: "请输入时间",
        trigger: "blur"
    }]
}, {
    label: "汇报类别",
    prop: "category",
    type: "select",
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=workReportCategory",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    {
        label: "汇报人身份证号",
        prop: "idCardNo",
        hide: true,
        addDisplay: false,
        editDisplay: false,
        viewDisplay: false,
    dataType: "number",
    searchSpan: 5,
    search: true,
    rules: [{
        required: true,
        message: "请选择汇报类别",
        trigger: "blur"
    }]
}, {
    label: "汇报类型",
    prop: "type",
    type: "select",
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=workReportType",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    {
        label: "汇报内容",
        prop: "content",
        type: "textarea",
        span: 24,
        rules: [{
            required: true,
            message: "请输入汇报内容",
            trigger: "blur"
        }]
    dataType: "number",
    searchSpan: 5,
    search: true,
    rules: [{
        required: true,
        message: "请选择汇报类型",
        trigger: "blur"
    }]
},
{
    label: "汇报人身份证号",
    prop: "idCardNo",
    hide: true,
    addDisplay: false,
    editDisplay: false,
    viewDisplay: false,
},
{
    label: "汇报内容",
    prop: "content",
    type: "textarea",
    span: 24,
    rules: [{
        required: true,
        message: "请输入汇报内容",
        trigger: "blur"
    }]
},
{
    label: "接收人",
    prop: "receivedIds",
    span: 24,
    type: "tree",
    dicUrl: "/api/blade-system/dept/lazy-tree-user",
    hide: true,
    props: {
        label: "title",
        value: "id",
    },
    {
        label: "接收人",
        prop: "receivedIds",
        span: 24,
        type: "tree",
        dicUrl: "/api/blade-system/dept/lazy-tree-user",
        hide: true,
        props: {
            label: "title",
            value: "id",
        },
        multiple: true,
        // dataType: "number",
        rules: [{
            required: true,
            message: "请选择接收人",
            trigger: "blur"
        }]
    },
    {
        label: "接收人",
        prop: "replyRealName",
        addDisplay: false,
        editDisplay: false,
        viewDisplay: false,
    },
    {
        label: "接收人单位",
        prop: "replyDeptName",
        addDisplay: false,
        editDisplay: false,
        // viewDisplay: false,
    },
    {
        label: "回复内容",
        prop: "replyContent",
        type: "textarea",
        span: 24,
        addDisplay: false,
        editDisplay: false,
        rules: [{
            required: true,
            message: "请输入回复内容",
            trigger: "blur"
        }]
    }
    multiple: true,
    // dataType: "number",
    rules: [{
        required: true,
        message: "请选择接收人",
        trigger: "blur"
    }]
},
{
    label: "接收人",
    prop: "replyRealName",
    addDisplay: false,
    editDisplay: false,
    viewDisplay: false,
},
{
    label: "接收人单位",
    prop: "replyDeptName",
    addDisplay: false,
    editDisplay: false,
    // viewDisplay: false,
},
{
    label: "回复内容",
    prop: "replyContent",
    type: "textarea",
    span: 24,
    addDisplay: false,
    editDisplay: false,
    rules: [{
        required: true,
        message: "请输入回复内容",
        trigger: "blur"
    }]
}
]
//接收人列信息
export var workreplyColumn = [{
        label: "汇报人",
        prop: "realName",
        disabled: true,
        span: 24,
        rules: [{
            required: true,
            message: "请选择接收人",
            trigger: "blur"
        }]
    label: "汇报人",
    prop: "realName",
    disabled: true,
    span: 24,
    rules: [{
        required: true,
        message: "请选择接收人",
        trigger: "blur"
    }]
},
{
    label: "汇报人单位",
    prop: "deptName",
    addDisplay: false,
    editDisplay: false,
    // viewDisplay: false,
}, {
    label: "汇报时间",
    prop: "reportTime",
    type: "datetime",
    format: "yyyy-MM-dd HH:mm:ss",
    valueFormat: "yyyy-MM-dd HH:mm:ss",
    searchRange: true,
    searchSpan: 6,
    hide: false,
    addDisplay: false,
    editDisplay: false,
    // viewDisplay: false,
    search: false,
    rules: [{
        required: true,
        message: "请输入时间",
        trigger: "blur"
    }]
}, {
    label: "汇报类别",
    prop: "category",
    type: "select",
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=workReportCategory",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    {
        label: "汇报人单位",
        prop: "deptName",
        addDisplay: false,
        editDisplay: false,
        // viewDisplay: false,
    }, {
        label: "汇报时间",
        prop: "reportTime",
        type: "datetime",
        format: "yyyy-MM-dd HH:mm:ss",
        valueFormat: "yyyy-MM-dd HH:mm:ss",
        searchRange: true,
        searchSpan: 6,
        hide: false,
        addDisplay: false,
        editDisplay: false,
        // viewDisplay: false,
        search: false,
        rules: [{
            required: true,
            message: "请输入时间",
            trigger: "blur"
        }]
    }, {
        label: "汇报类别",
        prop: "category",
        type: "select",
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=workReportCategory",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        dataType: "number",
        searchSpan: 4,
        search: true,
        hide: true,
        editDisplay: false,
        rules: [{
            required: true,
            message: "请选择汇报类别",
            trigger: "blur"
        }]
    }, {
        label: "汇报类型",
        prop: "type",
        type: "select",
        dicUrl: "/api/blade-system/dict-biz/dictionary?code=workReportType",
        props: {
            label: "dictValue",
            value: "dictKey"
        },
        dataType: "number",
        searchSpan: 4,
        search: true,
        disabled: true,
        rules: [{
            required: true,
            message: "请选择汇报类型",
            trigger: "blur"
        }]
    dataType: "number",
    searchSpan: 4,
    search: true,
    hide: true,
    editDisplay: false,
    rules: [{
        required: true,
        message: "请选择汇报类别",
        trigger: "blur"
    }]
}, {
    label: "汇报类型",
    prop: "type",
    type: "select",
    dicUrl: "/api/blade-system/dict-biz/dictionary?code=workReportType",
    props: {
        label: "dictValue",
        value: "dictKey"
    },
    // {
    //     label: "汇报人身份证号",
    //     prop: "idCardNo",
    //     hide: true,
    //     addDisplay: false,
    //     editDisplay: false,
    //     viewDisplay: false,
    // },
    {
        label: "汇报内容",
        prop: "content",
        type: "textarea",
        // editDisplay: false,
        disabled: true,
        span: 24,
        rules: [{
            required: true,
            message: "请输入汇报内容",
            trigger: "blur"
        }]
    },
    {
        label: "回复内容",
        prop: "replyContent",
        type: "textarea",
        span: 24,
        rules: [{
            required: true,
            message: "请输入回复内容",
            trigger: "blur"
        }]
    }
    dataType: "number",
    searchSpan: 4,
    search: true,
    disabled: true,
    rules: [{
        required: true,
        message: "请选择汇报类型",
        trigger: "blur"
    }]
},
// {
//     label: "汇报人身份证号",
//     prop: "idCardNo",
//     hide: true,
//     addDisplay: false,
//     editDisplay: false,
//     viewDisplay: false,
// },
{
    label: "汇报内容",
    prop: "content",
    type: "textarea",
    // editDisplay: false,
    disabled: true,
    span: 24,
    rules: [{
        required: true,
        message: "请输入汇报内容",
        trigger: "blur"
    }]
},
{
    label: "回复内容",
    prop: "replyContent",
    type: "textarea",
    span: 24,
    rules: [{
        required: true,
        message: "请输入回复内容",
        trigger: "blur"
    }]
}
]
src/views/workreport/workreport.vue
@@ -1,5 +1,5 @@
<template>
  <basic-container>
  <basic-container class="workreply">
    <avue-crud
      :option="option"
      :table-loading="loading"
@@ -271,4 +271,8 @@
</script>
<style>
.workreply .el-card.is-never-shadow.avue-crud__search {
  width: calc(100% - 380px) !important;
  left: 200px !important;
}
</style>