Commit 13b58a42000676c072cf9711491b5e6230dcb345

Authored by 梁保满
1 parent 65f592b6

备题组卷部分前端页面基本完成

@@ -136,13 +136,13 @@ @@ -136,13 +136,13 @@
136 { 136 {
137 path: "/", 137 path: "/",
138 iconCls: "fa fa-cog", 138 iconCls: "fa fa-cog",
139 - name: '学校管理', 139 + name: '学校设置',
140 component: Layout, 140 component: Layout,
141 children: [ 141 children: [
142 { 142 {
143 path: "/setUpSchool", 143 path: "/setUpSchool",
144 iconCls: "fa fa-calculator", 144 iconCls: "fa fa-calculator",
145 - name: '学校管理', 145 + name: '学校设置',
146 component: SetUpSchool, 146 component: SetUpSchool,
147 children: [] 147 children: []
148 }, 148 },
@@ -220,14 +220,14 @@ @@ -220,14 +220,14 @@
220 { 220 {
221 path: "/down", 221 path: "/down",
222 iconCls: "fa fa-download", // 图标样式class 222 iconCls: "fa fa-download", // 图标样式class
223 - name: "", 223 + name: "发卡软件",
224 component: Down, 224 component: Down,
225 children: [] 225 children: []
226 }, 226 },
227 { 227 {
228 path: "/downClient", 228 path: "/downClient",
229 iconCls: "", // 图标样式class 229 iconCls: "", // 图标样式class
230 - name: "", 230 + name: "授课端软件",
231 component: DownClient, 231 component: DownClient,
232 children: [] 232 children: []
233 } 233 }
src/api/apis/answerSheet.js
@@ -11,7 +11,7 @@ export default { @@ -11,7 +11,7 @@ export default {
11 data 11 data
12 }) 12 })
13 }, 13 },
14 - // 答题卡列表 14 + // 测验类型
15 fetchTypeNames(data) { 15 fetchTypeNames(data) {
16 return axios({ 16 return axios({
17 url: answerSheet.typeNames, 17 url: answerSheet.typeNames,
@@ -19,7 +19,7 @@ export default { @@ -19,7 +19,7 @@ export default {
19 data 19 data
20 }) 20 })
21 }, 21 },
22 - // 答题卡列表 22 + // 班级列表
23 fetchClassList(data) { 23 fetchClassList(data) {
24 return axios({ 24 return axios({
25 url: answerSheet.classList, 25 url: answerSheet.classList,
@@ -27,7 +27,7 @@ export default { @@ -27,7 +27,7 @@ export default {
27 data 27 data
28 }) 28 })
29 }, 29 },
30 - // 答题卡列表 30 + // 科目列表
31 fetchSubjectList(data) { 31 fetchSubjectList(data) {
32 return axios({ 32 return axios({
33 url: answerSheet.subjectList, 33 url: answerSheet.subjectList,
@@ -35,5 +35,53 @@ export default { @@ -35,5 +35,53 @@ export default {
35 data 35 data
36 }) 36 })
37 }, 37 },
  38 + // 年级列表
  39 + fetchGradeList(data) {
  40 + return axios({
  41 + url: answerSheet.gradeList,
  42 + method: 'POST',
  43 + data
  44 + })
  45 + },
  46 + // 添加测验类型
  47 + addAnswerTypeName(data) {
  48 + return axios({
  49 + url: answerSheet.addAnswerTypeName,
  50 + method: 'POST',
  51 + data
  52 + })
  53 + },
  54 + // 保存答题卡
  55 + saveAnswerSheet(data) {
  56 + return axios({
  57 + url: answerSheet.saveAnswerSheet,
  58 + method: 'POST',
  59 + data
  60 + })
  61 + },
  62 + // 删除答题卡
  63 + removeAnswerSheet(data) {
  64 + return axios({
  65 + url: answerSheet.removeAnswerSheet,
  66 + method: 'POST',
  67 + data
  68 + })
  69 + },
  70 + // 恢复答题卡
  71 + useAnswerSheet(data) {
  72 + return axios({
  73 + url: answerSheet.useAnswerSheet,
  74 + method: 'POST',
  75 + data
  76 + })
  77 + },
  78 + // 恢复答题卡
  79 + updateAnswerSheet(data) {
  80 + return axios({
  81 + url: answerSheet.updateAnswerSheet,
  82 + method: 'POST',
  83 + data
  84 + })
  85 + },
38 } 86 }
39 87
src/api/apis/login.js
@@ -4,7 +4,11 @@ import loginUrls from "../urls/login" @@ -4,7 +4,11 @@ import loginUrls from "../urls/login"
4 4
5 export default { 5 export default {
6 // 账号密码登陆 6 // 账号密码登陆
7 - fetchLogin (data) {  
8 - return axios.post(loginUrls.login, data)  
9 - } 7 + fetchLogin(data) {
  8 + return axios({
  9 + url: loginUrls.login,
  10 + method: 'POST',
  11 + data
  12 + })
  13 + },
10 } 14 }
src/api/axios.js
@@ -2,10 +2,12 @@ import axios from "axios" @@ -2,10 +2,12 @@ import axios from "axios"
2 import Cookies from "js-cookie" 2 import Cookies from "js-cookie"
3 import NProgress from "nprogress" 3 import NProgress from "nprogress"
4 import { Message } from "element-ui" 4 import { Message } from "element-ui"
5 -import config from "../config/index"; // 路径配置 5 +import router from "@/router/index"
  6 +import store from "@/store"
  7 +import conf from "../config/index"; // 路径配置
6 // axios默认配置 8 // axios默认配置
7 axios.defaults.timeout = 1000000000 // 超时时间 9 axios.defaults.timeout = 1000000000 // 超时时间
8 -axios.defaults.baseURL = config.baseURL 10 +axios.defaults.baseURL = conf.baseURL
9 11
10 // http request 拦截器 12 // http request 拦截器
11 axios.interceptors.request.use(config => { 13 axios.interceptors.request.use(config => {
@@ -27,38 +29,62 @@ axios.interceptors.request.use(config => { @@ -27,38 +29,62 @@ axios.interceptors.request.use(config => {
27 // http response 拦截器 29 // http response 拦截器
28 axios.interceptors.response.use( 30 axios.interceptors.response.use(
29 response => { 31 response => {
  32 + const res = respones.data;
30 NProgress.done() 33 NProgress.done()
31 if (respones.config.cancelToken) { 34 if (respones.config.cancelToken) {
32 store.commit('delTokenSources', respones.config.cancelToken) 35 store.commit('delTokenSources', respones.config.cancelToken)
33 } 36 }
34 - if (response.data.code === 11000) { 37 + if (respones.status == 200) {
35 Cookies.set("access_token", response.data.message, { expires: 1 / 12 }) 38 Cookies.set("access_token", response.data.message, { expires: 1 / 12 })
36 - return Promise.resolve()  
37 - } else if (response.data.code === 10000) { // 约定报错信息  
38 - Message({  
39 - message: response.data.message,  
40 - type: "warning"  
41 - })  
42 - return Promise.reject(response)  
43 - } else {  
44 - return Promise.resolve(response) 39 + // console.log(respones.status)
  40 + if (res.code == 999) {
  41 + if (!location.href.includes('localhost')) {
  42 + if (res.data) {
  43 + window.location.href = res.data
  44 + } else {
  45 + router.push({ path: '/login' })
  46 + if (res.message.includes('不存在')) {
  47 + Message({
  48 + message: res.message,
  49 + type: 'error',
  50 + duration: 3 * 1000
  51 + })
  52 + }
  53 + }
  54 + }
  55 + return
  56 + } else {
  57 + Cookies.set("access_token", response.data.message, { expires: 1 / 12 })
  58 + }
45 } 59 }
  60 + return Promise.resolve(response)
46 }, 61 },
47 error => { 62 error => {
48 - if (error.response.status === 404) { 63 + Message({
  64 + message: error.message,
  65 + type: 'error',
  66 + duration: 3 * 1000
  67 + })
  68 + if (error.response == undefined) {
  69 + return Promise.reject(error);
  70 + }
  71 + Message.closeAll()
  72 + const {
  73 + status
  74 + } = error.response
  75 + if (status === 403 || status === 401) {
49 Message({ 76 Message({
50 - message: "请求地址出错",  
51 - type: "warning" 77 + message: "未登录或登录超时,即将跳转到登录页面",
  78 + type: 'error',
  79 + duration: 3 * 1000
52 }) 80 })
53 - } else if (error.response.status === 401) {  
54 - Message({  
55 - message: error.response.data.message,  
56 - type: "warning" 81 + router.push({
  82 + path: '/login',
  83 + query: {
  84 + url: window.location.href
  85 + }
57 }) 86 })
58 - Cookies.remove("access_token")  
59 - setTimeout(() => {  
60 - location.reload()  
61 - }, 3000) 87 + return
62 } 88 }
63 return Promise.reject(error.response) // 返回接口返回的错误信息 89 return Promise.reject(error.response) // 返回接口返回的错误信息
64 }) 90 })
src/api/urls/answerSheet.js
1 export default { 1 export default {
2 // 答题卡列表 2 // 答题卡列表
3 answerList: "/apis/answerList", 3 answerList: "/apis/answerList",
4 - // 答题卡类型 4 + // 测验类型
5 typeNames: "/apis/typeNames", 5 typeNames: "/apis/typeNames",
  6 + // 查找年级
  7 + gradeList: "/apis/gradeList",
6 // 查找班级 8 // 查找班级
7 classList: "/apis/classList", 9 classList: "/apis/classList",
8 // 查找科目 10 // 查找科目
9 subjectList: "/apis/subjectList", 11 subjectList: "/apis/subjectList",
  12 + // 天假答题卡测验类型
  13 + addAnswerTypeName: "/apis/addAnswerTypeName",
  14 + // 保存答题卡
  15 + saveAnswerSheet: "/apis/saveAnswerSheet",
  16 + // 删除答题卡
  17 + removeAnswerSheet: "/apis/removeAnswerSheet",
  18 + // 恢复使用答题卡
  19 + useAnswerSheet: "/apis/useAnswerSheet",
  20 + // 更新答题卡
  21 + updateAnswerSheet: "/apis/updateAnswerSheet",
10 } 22 }
11 \ No newline at end of file 23 \ No newline at end of file
src/assets/css/base.css
@@ -21,18 +21,25 @@ a { @@ -21,18 +21,25 @@ a {
21 } 21 }
22 22
23 /* element-style */ 23 /* element-style */
24 -.el-button--default{ 24 +.el-button--default {
25 color: #667ffd; 25 color: #667ffd;
26 border-color: #667ffd; 26 border-color: #667ffd;
27 } 27 }
  28 +
28 .el-button--primary { 29 .el-button--primary {
29 background-color: #667ffd; 30 background-color: #667ffd;
30 border-color: #667ffd; 31 border-color: #667ffd;
31 } 32 }
32 -.el-radio__input.is-checked+.el-radio__label{ 33 +
  34 +.el-radio__input.is-checked+.el-radio__label {
33 color: #667ffd; 35 color: #667ffd;
34 } 36 }
35 -.el-radio__input.is-checked .el-radio__inner{ 37 +
  38 +.el-radio__input.is-checked .el-radio__inner {
36 border-color: #667ffd; 39 border-color: #667ffd;
37 - background: #667ffd;  
38 -}  
39 \ No newline at end of file 40 \ No newline at end of file
  41 + background: #667ffd;
  42 +}
  43 +
  44 +.el-message-box .el-button--default {
  45 + color: #fff
  46 +}
src/assets/css/index.scss 0 → 100644
  1 +.answer-header {
  2 + padding: 16px 40px 12px 20px;
  3 + display: flex;
  4 + justify-content: space-between;
  5 + align-items: center;
  6 + .btn-box {
  7 + display: flex;
  8 + }
  9 + .sel-box {
  10 + display: flex;
  11 + align-items: center;
  12 + flex-wrap: nowrap;
  13 + .sel {
  14 + width: 8%;
  15 + min-width: 90px;
  16 + margin-right: 20px;
  17 + }
  18 + .el-input__inner{
  19 + border-radius: 20px;
  20 + border: 1px solid #e2e2e2;
  21 + height: 36px;
  22 + line-height: 34px;
  23 + }
  24 + .el-input__icon {
  25 + line-height: 34px;
  26 + }
  27 + .el-date-editor.el-input,
  28 + .el-date-editor.el-input__inner {
  29 + width: 200px;
  30 + }
  31 + .input-with-select {
  32 + width: 200px;
  33 + height: 36px;
  34 + margin-right: 50px;
  35 + border-radius: 20px;
  36 + border: 1px solid #e2e2e2;
  37 + box-sizing: border-box;
  38 + .el-input__inner {
  39 + border-radius: 20px;
  40 + border: none;
  41 + height: 34px;
  42 + line-height: 34px;
  43 + }
  44 + .el-input-group__append, .el-input-group__prepend {
  45 + border: none;
  46 + background: transparent;
  47 + }
  48 + }
  49 + .d1 {
  50 + margin-left: 30px;
  51 + }
  52 + .p1 {
  53 + flex: 1;
  54 + .s1 {
  55 + margin-left: 36px;
  56 + cursor: pointer;
  57 + color: #7f7f7f;
  58 + &:hover {
  59 + color: #409eff;
  60 + }
  61 + &.active {
  62 + color: #667ffd;
  63 + }
  64 + }
  65 + }
  66 +}
  67 +}
0 \ No newline at end of file 68 \ No newline at end of file
src/main.js
@@ -18,6 +18,7 @@ import "element-ui/lib/theme-chalk/index.css" @@ -18,6 +18,7 @@ import "element-ui/lib/theme-chalk/index.css"
18 import "font-awesome/css/font-awesome.css" 18 import "font-awesome/css/font-awesome.css"
19 import "@/router/permission" 19 import "@/router/permission"
20 import "@/assets/css/base.css" 20 import "@/assets/css/base.css"
  21 +import "@/assets/css/index.scss"
21 22
22 Vue.config.productionTip = false 23 Vue.config.productionTip = false
23 Vue.use(ElementUI) 24 Vue.use(ElementUI)
src/router/index.js
@@ -5,8 +5,29 @@ import Login from "@/views/login/index" @@ -5,8 +5,29 @@ import Login from "@/views/login/index"
5 import Layout from "@/views/layout/layout" 5 import Layout from "@/views/layout/layout"
6 import HomeMain from "@/views/index/mainIndex" 6 import HomeMain from "@/views/index/mainIndex"
7 7
  8 +
8 // 不是必须加载的组件使用懒加载 9 // 不是必须加载的组件使用懒加载
9 const NotFound = () => import("@/views/page404") 10 const NotFound = () => import("@/views/page404")
  11 +const ExaminationPaper = () => import("@/views/examinationPaper/index")
  12 +const ExaminationPaperAdd = () => import("@/views/examinationPaper/add")
  13 +const ExaminationPaperEdit = () => import("@/views/examinationPaper/edit")
  14 +const ExaminationPaperRecycle = () => import("@/views/examinationPaper/recycle")
  15 +const Ask = () => import("@/views/ask/index")
  16 +const AskAnalysis = () => import("@/views/ask/analysis")
  17 +const Test = () => import("@/views/test/index")
  18 +const TestAnalysis = () => import("@/views/test/analysis")
  19 +const DataSync = () => import("@/views/dataSync/index")
  20 +const Portrait = () => import("@/views/portrait/index")
  21 +const Card = () => import("@/views/card/index")
  22 +const Analysis = () => import("@/views/analysis/index")
  23 +const Device = () => import("@/views/device/index")
  24 +const Down = () => import("@/views/down/index")
  25 +const DownClient = () => import("@/views/down/client")
  26 +const SetUpAccount = () => import("@/views/setUp/account")
  27 +const SetUpConglomerate = () => import("@/views/setUp/conglomerate")
  28 +const SetUpSchool = () => import("@/views/setUp/school")
  29 +const SetUpStudent = () => import("@/views/setUp/student")
  30 +const SetUpTeacher = () => import("@/views/setUp/teacher")
10 31
11 /** 32 /**
12 * 重写路由的push方法 33 * 重写路由的push方法
@@ -55,7 +76,266 @@ let defaultRouter = [ @@ -55,7 +76,266 @@ let defaultRouter = [
55 } 76 }
56 ] 77 ]
57 78
  79 +let addrouters = [ //测试用,后续后端获取
  80 + {
  81 + path: "/examinationPaper",
  82 + iconCls: "fa fa-file-text", // 图标样式class
  83 + name: "备题组卷",
  84 + component: Layout,
  85 + alone: true,
  86 + children: [
  87 + {
  88 + path: "/examinationPaper",
  89 + iconCls: "fa fa-file-text", // 图标样式class
  90 + name: "",
  91 + component: ExaminationPaper,
  92 + children: []
  93 + },
  94 + {
  95 + path: "/examinationPaperAdd",
  96 + iconCls: "", // 图标样式class
  97 + name: "添加答题卡",
  98 + component: ExaminationPaperAdd,
  99 + children: []
  100 + },
  101 + {
  102 + path: "/examinationPaperEdit",
  103 + iconCls: "", // 图标样式class
  104 + name: "修改答题卡",
  105 + component: ExaminationPaperEdit,
  106 + children: []
  107 + },
  108 + {
  109 + path: "/examinationPaperRecycle",
  110 + iconCls: "", // 图标样式class
  111 + name: "已归档答题卡",
  112 + component: ExaminationPaperRecycle,
  113 + children: []
  114 + },
  115 + ]
  116 + },
  117 + {
  118 + path: "/ask",
  119 + iconCls: "fa fa-bar-chart", // 图标样式class
  120 + name: "随堂问报表",
  121 + component: Layout,
  122 + alone: true,
  123 + children: [
  124 + {
  125 + path: "/ask",
  126 + iconCls: "fa fa-bar-chart", // 图标样式class
  127 + name: "",
  128 + component: Ask,
  129 + children: []
  130 +
  131 + },
  132 + {
  133 + path: "/askAnalysis",
  134 + iconCls: "", // 图标样式class
  135 + name: "随堂问报表分析",
  136 + component: AskAnalysis,
  137 + children: []
  138 + }
  139 + ]
  140 + },
  141 + {
  142 + path: "/test",
  143 + iconCls: "fa fa-pie-chart", // 图标样式class
  144 + name: "即时测报表",
  145 + component: Layout,
  146 + alone: true,
  147 + children: [
  148 + {
  149 + path: "/test",
  150 + iconCls: "fa fa-pie-chart", // 图标样式class
  151 + name: "",
  152 + component: Test,
  153 + children: []
  154 + },
  155 + {
  156 + path: "/testAnalysis",
  157 + iconCls: "", // 图标样式class
  158 + name: "即时测报表分析",
  159 + component: TestAnalysis,
  160 + children: []
  161 + }
  162 +
  163 + ]
  164 + },
  165 + {
  166 + path: "/portrait",
  167 + iconCls: "fa fa-users", // 图标样式class
  168 + name: "学生画像",
  169 + component: Layout,
  170 + alone: true,
  171 + children: [
  172 + {
  173 + path: "/portrait",
  174 + iconCls: "fa fa-users", // 图标样式class
  175 + name: "",
  176 + component: Portrait,
  177 + children: []
  178 + }
  179 + ]
  180 + },
  181 +
  182 + {
  183 + path: "/setUpConglomerate",
  184 + iconCls: "fa fa-building", // 图标样式class
  185 + name: "学校管理",
  186 + component: Layout,
  187 + alone: true,
  188 + children: [
  189 + {
  190 + path: "/setUpConglomerate",
  191 + iconCls: "fa fa-building",
  192 + name: '集团管理',
  193 + component: SetUpConglomerate,
  194 + children: []
  195 + },
  196 + ]
  197 + },
  198 + {
  199 + path: "/setUpAccount",
  200 + iconCls: "fa fa-id-card-o", // 图标样式class
  201 + name: "账号管理",
  202 + component: Layout,
  203 + alone: true,
  204 + children: [
  205 + {
  206 + path: "/setUpAccount",
  207 + iconCls: "fa fa-id-card-o",
  208 + name: '',
  209 + component: SetUpAccount,
  210 + children: []
  211 + },
  212 + ]
  213 + },
  214 + {
  215 + path: "/",
  216 + iconCls: "fa fa-cog",
  217 + name: '学校设置',
  218 + component: Layout,
  219 + children: [
  220 + {
  221 + path: "/setUpSchool",
  222 + iconCls: "fa fa-calculator",
  223 + name: '学校设置',
  224 + component: SetUpSchool,
  225 + children: []
  226 + },
  227 + {
  228 + path: "/setUpTeacher",
  229 + iconCls: "fa fa-male",
  230 + name: '教师管理',
  231 + component: SetUpTeacher,
  232 + children: []
  233 + },
  234 + {
  235 + path: "/setUpStudent",
  236 + iconCls: "fa fa-mortar-board",
  237 + name: '学生管理',
  238 + component: SetUpStudent,
  239 + children: []
  240 + },
  241 + ]
  242 + },
  243 + {
  244 + path: "/card",
  245 + iconCls: "fa fa-id-card", // 图标样式class
  246 + name: "发卡记录",
  247 + component: Layout,
  248 + alone: true,
  249 + children: [
  250 + {
  251 + path: "/card",
  252 + iconCls: "fa fa-id-card", // 图标样式class
  253 + name: "",
  254 + component: Card,
  255 + children: []
  256 + }
  257 + ]
  258 + },
  259 + {
  260 + path: "/device",
  261 + iconCls: "fa fa-dashboard", // 图标样式class
  262 + name: "设备状态",
  263 + component: Layout,
  264 + alone: true,
  265 + children: [
  266 + {
  267 + path: "/device",
  268 + iconCls: "fa fa-dashboard", // 图标样式class
  269 + name: "",
  270 + component: Device,
  271 + children: []
  272 + }
  273 + ]
  274 + },
  275 + {
  276 + path: "/analysis",
  277 + iconCls: "fa fa-area-chart", // 图标样式class
  278 + name: "使用分析",
  279 + component: Layout,
  280 + alone: true,
  281 + children: [
  282 + {
  283 + path: "/analysis",
  284 + iconCls: "fa fa-area-chart", // 图标样式class
  285 + name: "",
  286 + component: Analysis,
  287 + children: []
  288 + }
  289 + ]
  290 + },
  291 + {
  292 + path: "/down",
  293 + iconCls: "fa fa-download", // 图标样式class
  294 + name: "软件下载",
  295 + component: Layout,
  296 + alone: true,
  297 + children: [
  298 + {
  299 + path: "/down",
  300 + iconCls: "fa fa-download", // 图标样式class
  301 + name: "发卡软件",
  302 + component: Down,
  303 + children: []
  304 + },
  305 + {
  306 + path: "/downClient",
  307 + iconCls: "", // 图标样式class
  308 + name: "授课端软件",
  309 + component: DownClient,
  310 + children: []
  311 + }
  312 + ]
  313 + },
  314 + {
  315 + path: "/dataSync",
  316 + iconCls: "fa fa-random", // 图标样式class
  317 + name: "数据同步",
  318 + component: Layout,
  319 + alone: true,
  320 + children: [
  321 + {
  322 + path: "/dataSync",
  323 + iconCls: "fa fa-random", // 图标样式class
  324 + name: "",
  325 + component: DataSync,
  326 + children: []
  327 + }
  328 + ]
  329 + },
  330 + {
  331 + path: "*",
  332 + redirect: "/404",
  333 + hidden: true,
  334 + children: []
  335 + }
  336 +]
  337 +
58 export default new Router({ 338 export default new Router({
59 routes: defaultRouter 339 routes: defaultRouter
60 }) 340 })
61 -export {defaultRouter} 341 +export {defaultRouter,addrouters}
src/router/permission.js
1 import NProgress from "nprogress" 1 import NProgress from "nprogress"
2 -import en from "../i18n/lang/en"  
3 -import Layout from "@/views/layout/layout"  
4 -import CommerViews from "@/views/commerViews"  
5 import router from "./index" 2 import router from "./index"
6 import store from "../store" 3 import store from "../store"
7 -// let routeName = en.routeName  
8 -  
9 -const ExaminationPaper = () => import("@/views/examinationPaper/index")  
10 -const ExaminationPaperAdd = () => import("@/views/examinationPaper/add")  
11 -const ExaminationPaperEdit = () => import("@/views/examinationPaper/edit")  
12 -const ExaminationPaperRecycle = () => import("@/views/examinationPaper/recycle")  
13 -const Ask = () => import("@/views/ask/index")  
14 -const AskAnalysis = () => import("@/views/ask/analysis")  
15 -const Test = () => import("@/views/test/index")  
16 -const TestAnalysis = () => import("@/views/test/analysis")  
17 -const DataSync = () => import("@/views/dataSync/index")  
18 -const Portrait = () => import("@/views/portrait/index")  
19 -const Card = () => import("@/views/card/index")  
20 -const Analysis = () => import("@/views/analysis/index")  
21 -const Device = () => import("@/views/device/index")  
22 -const Down = () => import("@/views/down/index")  
23 -const DownClient = () => import("@/views/down/client")  
24 -const SetUpAccount = () => import("@/views/setUp/account")  
25 -const SetUpConglomerate = () => import("@/views/setUp/conglomerate")  
26 -const SetUpSchool = () => import("@/views/setUp/school")  
27 -const SetUpStudent = () => import("@/views/setUp/student")  
28 -const SetUpTeacher = () => import("@/views/setUp/teacher")  
29 -let addrouters = [ //测试用,后续后端获取  
30 - {  
31 - path: "/examinationPaper",  
32 - iconCls: "fa fa-file-text", // 图标样式class  
33 - name: "备题组卷",  
34 - component: Layout,  
35 - alone: true,  
36 - children: [  
37 - {  
38 - path: "/examinationPaper",  
39 - iconCls: "fa fa-file-text", // 图标样式class  
40 - name: "",  
41 - component: ExaminationPaper,  
42 - children: []  
43 - },  
44 - {  
45 - path: "/examinationPaperAdd",  
46 - iconCls: "", // 图标样式class  
47 - name: "添加答题卡",  
48 - component: ExaminationPaperAdd,  
49 - children: []  
50 - },  
51 - {  
52 - path: "/examinationPaperEdit",  
53 - iconCls: "", // 图标样式class  
54 - name: "修改答题卡",  
55 - component: ExaminationPaperEdit,  
56 - children: []  
57 - },  
58 - {  
59 - path: "/examinationPaperRecycle",  
60 - iconCls: "", // 图标样式class  
61 - name: "已归档答题卡",  
62 - component: ExaminationPaperRecycle,  
63 - children: []  
64 - },  
65 - ]  
66 - },  
67 - {  
68 - path: "/ask",  
69 - iconCls: "fa fa-bar-chart", // 图标样式class  
70 - name: "随堂问报表",  
71 - component: Layout,  
72 - alone: true,  
73 - children: [  
74 - {  
75 - path: "/ask",  
76 - iconCls: "fa fa-bar-chart", // 图标样式class  
77 - name: "",  
78 - component: Ask,  
79 - children: []  
80 -  
81 - },  
82 - {  
83 - path: "/askAnalysis",  
84 - iconCls: "", // 图标样式class  
85 - name: "随堂问报表分析",  
86 - component: AskAnalysis,  
87 - children: []  
88 - }  
89 - ]  
90 - },  
91 - {  
92 - path: "/test",  
93 - iconCls: "fa fa-pie-chart", // 图标样式class  
94 - name: "即时测报表",  
95 - component: Layout,  
96 - alone: true,  
97 - children: [  
98 - {  
99 - path: "/test",  
100 - iconCls: "fa fa-pie-chart", // 图标样式class  
101 - name: "",  
102 - component: Test,  
103 - children: []  
104 - },  
105 - {  
106 - path: "/testAnalysis",  
107 - iconCls: "", // 图标样式class  
108 - name: "即时测报表分析",  
109 - component: TestAnalysis,  
110 - children: []  
111 - }  
112 -  
113 - ]  
114 - },  
115 - {  
116 - path: "/portrait",  
117 - iconCls: "fa fa-users", // 图标样式class  
118 - name: "学生画像",  
119 - component: Layout,  
120 - alone: true,  
121 - children: [  
122 - {  
123 - path: "/portrait",  
124 - iconCls: "fa fa-users", // 图标样式class  
125 - name: "",  
126 - component: Portrait,  
127 - children: []  
128 - }  
129 - ]  
130 - },  
131 -  
132 - {  
133 - path: "/setUpConglomerate",  
134 - iconCls: "fa fa-building", // 图标样式class  
135 - name: "学校管理",  
136 - component: Layout,  
137 - alone: true,  
138 - children: [  
139 - {  
140 - path: "/setUpConglomerate",  
141 - iconCls: "fa fa-building",  
142 - name: '集团管理',  
143 - component: SetUpConglomerate,  
144 - children: []  
145 - },  
146 - ]  
147 - },  
148 - {  
149 - path: "/setUpAccount",  
150 - iconCls: "fa fa-id-card-o", // 图标样式class  
151 - name: "账号管理",  
152 - component: Layout,  
153 - alone: true,  
154 - children: [  
155 - {  
156 - path: "/setUpAccount",  
157 - iconCls: "fa fa-id-card-o",  
158 - name: '',  
159 - component: SetUpAccount,  
160 - children: []  
161 - },  
162 - ]  
163 - },  
164 - {  
165 - path: "/",  
166 - iconCls: "fa fa-cog",  
167 - name: '学校管理',  
168 - component: Layout,  
169 - children: [  
170 - {  
171 - path: "/setUpSchool",  
172 - iconCls: "fa fa-calculator",  
173 - name: '学校管理',  
174 - component: SetUpSchool,  
175 - children: []  
176 - },  
177 - {  
178 - path: "/setUpTeacher",  
179 - iconCls: "fa fa-male",  
180 - name: '教师管理',  
181 - component: SetUpTeacher,  
182 - children: []  
183 - },  
184 - {  
185 - path: "/setUpStudent",  
186 - iconCls: "fa fa-mortar-board",  
187 - name: '学生管理',  
188 - component: SetUpStudent,  
189 - children: []  
190 - },  
191 - ]  
192 - },  
193 - {  
194 - path: "/card",  
195 - iconCls: "fa fa-id-card", // 图标样式class  
196 - name: "发卡记录",  
197 - component: Layout,  
198 - alone: true,  
199 - children: [  
200 - {  
201 - path: "/card",  
202 - iconCls: "fa fa-id-card", // 图标样式class  
203 - name: "",  
204 - component: Card,  
205 - children: []  
206 - }  
207 - ]  
208 - },  
209 - {  
210 - path: "/device",  
211 - iconCls: "fa fa-dashboard", // 图标样式class  
212 - name: "设备状态",  
213 - component: Layout,  
214 - alone: true,  
215 - children: [  
216 - {  
217 - path: "/device",  
218 - iconCls: "fa fa-dashboard", // 图标样式class  
219 - name: "",  
220 - component: Device,  
221 - children: []  
222 - }  
223 - ]  
224 - },  
225 - {  
226 - path: "/analysis",  
227 - iconCls: "fa fa-area-chart", // 图标样式class  
228 - name: "使用分析",  
229 - component: Layout,  
230 - alone: true,  
231 - children: [  
232 - {  
233 - path: "/analysis",  
234 - iconCls: "fa fa-area-chart", // 图标样式class  
235 - name: "",  
236 - component: Analysis,  
237 - children: []  
238 - }  
239 - ]  
240 - },  
241 - {  
242 - path: "/down",  
243 - iconCls: "fa fa-download", // 图标样式class  
244 - name: "软件下载",  
245 - component: Layout,  
246 - alone: true,  
247 - children: [  
248 - {  
249 - path: "/down",  
250 - iconCls: "fa fa-download", // 图标样式class  
251 - name: "",  
252 - component: Down,  
253 - children: []  
254 - },  
255 - {  
256 - path: "/downClient",  
257 - iconCls: "", // 图标样式class  
258 - name: "",  
259 - component: DownClient,  
260 - children: []  
261 - }  
262 - ]  
263 - },  
264 - {  
265 - path: "/dataSync",  
266 - iconCls: "fa fa-random", // 图标样式class  
267 - name: "数据同步",  
268 - component: Layout,  
269 - alone: true,  
270 - children: [  
271 - {  
272 - path: "/dataSync",  
273 - iconCls: "fa fa-random", // 图标样式class  
274 - name: "",  
275 - component: DataSync,  
276 - children: []  
277 - }  
278 - ]  
279 - },  
280 - {  
281 - path: "*",  
282 - redirect: "/404",  
283 - hidden: true,  
284 - children: []  
285 - }  
286 -]  
287 - 4 +import {addrouters} from "./index"
288 5
289 // 获取角色信息,根据用户权限动态加载路由 6 // 获取角色信息,根据用户权限动态加载路由
290 router.beforeEach((to, from, next) => { 7 router.beforeEach((to, from, next) => {
@@ -314,7 +31,7 @@ router.beforeEach((to, from, next) => { @@ -314,7 +31,7 @@ router.beforeEach((to, from, next) => {
314 newAddRouters.forEach(res => { 31 newAddRouters.forEach(res => {
315 router.addRoute(res) 32 router.addRoute(res)
316 }) 33 })
317 - next({ path: to.path }) 34 + next({path: to.fullPath})
318 }()) 35 }())
319 } else { 36 } else {
320 next() 37 next()
src/store/index.js
@@ -3,291 +3,12 @@ import Vuex from "vuex" @@ -3,291 +3,12 @@ import Vuex from "vuex"
3 import Cookies from "js-cookie" 3 import Cookies from "js-cookie"
4 import layoutStore from "./modules/layout/index" 4 import layoutStore from "./modules/layout/index"
5 import { defaultRouter } from "@/router/index" 5 import { defaultRouter } from "@/router/index"
  6 +import { encryptLoginPassword } from "@/utils";
  7 +import { b64DecodeUnicode } from "@/utils";
6 8
7 import request from "@/api/index" 9 import request from "@/api/index"
8 import router from "@/router/index" 10 import router from "@/router/index"
9 -  
10 -import Layout from "@/views/layout/layout"  
11 -import CommerViews from "@/views/commerViews"  
12 -const ExaminationPaper = () => import("@/views/examinationPaper/index")  
13 -const ExaminationPaperAdd = () => import("@/views/examinationPaper/add")  
14 -const ExaminationPaperEdit = () => import("@/views/examinationPaper/edit")  
15 -const ExaminationPaperRecycle = () => import("@/views/examinationPaper/recycle")  
16 -const Ask = () => import("@/views/ask/index")  
17 -const AskAnalysis = () => import("@/views/ask/analysis")  
18 -const Test = () => import("@/views/test/index")  
19 -const TestAnalysis = () => import("@/views/test/analysis")  
20 -const DataSync = () => import("@/views/dataSync/index")  
21 -const Portrait = () => import("@/views/portrait/index")  
22 -const Card = () => import("@/views/card/index")  
23 -const Analysis = () => import("@/views/analysis/index")  
24 -const Device = () => import("@/views/device/index")  
25 -const Down = () => import("@/views/down/index")  
26 -const DownClient = () => import("@/views/down/client")  
27 -const SetUpAccount = () => import("@/views/setUp/account")  
28 -const SetUpConglomerate = () => import("@/views/setUp/conglomerate")  
29 -const SetUpSchool = () => import("@/views/setUp/school")  
30 -const SetUpStudent = () => import("@/views/setUp/student")  
31 -const SetUpTeacher = () => import("@/views/setUp/teacher")  
32 -let addrouters = [ //测试用,后续后端获取  
33 - {  
34 - path: "/examinationPaper",  
35 - iconCls: "fa fa-file-text", // 图标样式class  
36 - name: "备题组卷",  
37 - component: Layout,  
38 - alone: true,  
39 - children: [  
40 - {  
41 - path: "/examinationPaper",  
42 - iconCls: "fa fa-file-text", // 图标样式class  
43 - name: "",  
44 - component: ExaminationPaper,  
45 - children: []  
46 - },  
47 - {  
48 - path: "/examinationPaperAdd",  
49 - iconCls: "", // 图标样式class  
50 - name: "添加答题卡",  
51 - component: ExaminationPaperAdd,  
52 - children: []  
53 - },  
54 - {  
55 - path: "/examinationPaperEdit",  
56 - iconCls: "", // 图标样式class  
57 - name: "修改答题卡",  
58 - component: ExaminationPaperEdit,  
59 - children: []  
60 - },  
61 - {  
62 - path: "/examinationPaperRecycle",  
63 - iconCls: "", // 图标样式class  
64 - name: "已归档答题卡",  
65 - component: ExaminationPaperRecycle,  
66 - children: []  
67 - },  
68 - ]  
69 - },  
70 - {  
71 - path: "/ask",  
72 - iconCls: "fa fa-bar-chart", // 图标样式class  
73 - name: "随堂问报表",  
74 - component: Layout,  
75 - alone: true,  
76 - children: [  
77 - {  
78 - path: "/ask",  
79 - iconCls: "fa fa-bar-chart", // 图标样式class  
80 - name: "",  
81 - component: Ask,  
82 - children: []  
83 -  
84 - },  
85 - {  
86 - path: "/askAnalysis",  
87 - iconCls: "", // 图标样式class  
88 - name: "随堂问报表分析",  
89 - component: AskAnalysis,  
90 - children: []  
91 - }  
92 - ]  
93 - },  
94 - {  
95 - path: "/test",  
96 - iconCls: "fa fa-pie-chart", // 图标样式class  
97 - name: "即时测报表",  
98 - component: Layout,  
99 - alone: true,  
100 - children: [  
101 - {  
102 - path: "/test",  
103 - iconCls: "fa fa-pie-chart", // 图标样式class  
104 - name: "",  
105 - component: Test,  
106 - children: []  
107 - },  
108 - {  
109 - path: "/testAnalysis",  
110 - iconCls: "", // 图标样式class  
111 - name: "即时测报表分析",  
112 - component: TestAnalysis,  
113 - children: []  
114 - }  
115 -  
116 - ]  
117 - },  
118 - {  
119 - path: "/portrait",  
120 - iconCls: "fa fa-users", // 图标样式class  
121 - name: "学生画像",  
122 - component: Layout,  
123 - alone: true,  
124 - children: [  
125 - {  
126 - path: "/portrait",  
127 - iconCls: "fa fa-users", // 图标样式class  
128 - name: "",  
129 - component: Portrait,  
130 - children: []  
131 - }  
132 - ]  
133 - },  
134 -  
135 - {  
136 - path: "/setUpConglomerate",  
137 - iconCls: "fa fa-building", // 图标样式class  
138 - name: "学校管理",  
139 - component: Layout,  
140 - alone: true,  
141 - children: [  
142 - {  
143 - path: "/setUpConglomerate",  
144 - iconCls: "fa fa-building",  
145 - name: '集团管理',  
146 - component: SetUpConglomerate,  
147 - children: []  
148 - },  
149 - ]  
150 - },  
151 - {  
152 - path: "/setUpAccount",  
153 - iconCls: "fa fa-id-card-o", // 图标样式class  
154 - name: "账号管理",  
155 - component: Layout,  
156 - alone: true,  
157 - children: [  
158 - {  
159 - path: "/setUpAccount",  
160 - iconCls: "fa fa-id-card-o",  
161 - name: '',  
162 - component: SetUpAccount,  
163 - children: []  
164 - },  
165 - ]  
166 - },  
167 - {  
168 - path: "/",  
169 - iconCls: "fa fa-cog",  
170 - name: '学校设置',  
171 - component: Layout,  
172 - children: [  
173 - {  
174 - path: "/setUpSchool",  
175 - iconCls: "fa fa-calculator",  
176 - name: '学校设置',  
177 - component: SetUpSchool,  
178 - children: []  
179 - },  
180 - {  
181 - path: "/setUpTeacher",  
182 - iconCls: "fa fa-male",  
183 - name: '教师管理',  
184 - component: SetUpTeacher,  
185 - children: []  
186 - },  
187 - {  
188 - path: "/setUpStudent",  
189 - iconCls: "fa fa-mortar-board",  
190 - name: '学生管理',  
191 - component: SetUpStudent,  
192 - children: []  
193 - },  
194 - ]  
195 - },  
196 - {  
197 - path: "/card",  
198 - iconCls: "fa fa-id-card", // 图标样式class  
199 - name: "发卡记录",  
200 - component: Layout,  
201 - alone: true,  
202 - children: [  
203 - {  
204 - path: "/card",  
205 - iconCls: "fa fa-id-card", // 图标样式class  
206 - name: "",  
207 - component: Card,  
208 - children: []  
209 - }  
210 - ]  
211 - },  
212 - {  
213 - path: "/device",  
214 - iconCls: "fa fa-dashboard", // 图标样式class  
215 - name: "设备状态",  
216 - component: Layout,  
217 - alone: true,  
218 - children: [  
219 - {  
220 - path: "/device",  
221 - iconCls: "fa fa-dashboard", // 图标样式class  
222 - name: "",  
223 - component: Device,  
224 - children: []  
225 - }  
226 - ]  
227 - },  
228 - {  
229 - path: "/analysis",  
230 - iconCls: "fa fa-area-chart", // 图标样式class  
231 - name: "使用分析",  
232 - component: Layout,  
233 - alone: true,  
234 - children: [  
235 - {  
236 - path: "/analysis",  
237 - iconCls: "fa fa-area-chart", // 图标样式class  
238 - name: "",  
239 - component: Analysis,  
240 - children: []  
241 - }  
242 - ]  
243 - },  
244 - {  
245 - path: "/down",  
246 - iconCls: "fa fa-download", // 图标样式class  
247 - name: "软件下载",  
248 - component: Layout,  
249 - alone: true,  
250 - children: [  
251 - {  
252 - path: "/down",  
253 - iconCls: "fa fa-download", // 图标样式class  
254 - name: "发卡软件",  
255 - component: Down,  
256 - children: []  
257 - },  
258 - {  
259 - path: "/downClient",  
260 - iconCls: "", // 图标样式class  
261 - name: "授课端软件",  
262 - component: DownClient,  
263 - children: []  
264 - }  
265 - ]  
266 - },  
267 - {  
268 - path: "/dataSync",  
269 - iconCls: "fa fa-random", // 图标样式class  
270 - name: "数据同步",  
271 - component: Layout,  
272 - alone: true,  
273 - children: [  
274 - {  
275 - path: "/dataSync",  
276 - iconCls: "fa fa-random", // 图标样式class  
277 - name: "",  
278 - component: DataSync,  
279 - children: []  
280 - }  
281 - ]  
282 - },  
283 - {  
284 - path: "*",  
285 - redirect: "/404",  
286 - hidden: true,  
287 - children: []  
288 - }  
289 -]  
290 - 11 +import {addrouters} from "@/router/index"
291 Vue.use(Vuex) 12 Vue.use(Vuex)
292 13
293 const store = new Vuex.Store({ 14 const store = new Vuex.Store({
@@ -310,7 +31,7 @@ const store = new Vuex.Store({ @@ -310,7 +31,7 @@ const store = new Vuex.Store({
310 name: data.name, 31 name: data.name,
311 authorityRouter: data.authorityRouter, 32 authorityRouter: data.authorityRouter,
312 avatar: data.avatar ? data.avatar : "", 33 avatar: data.avatar ? data.avatar : "",
313 - uid: data.id 34 + uid: data.uid
314 } 35 }
315 localStorage.setItem("info", JSON.stringify(store.getters.info)) 36 localStorage.setItem("info", JSON.stringify(store.getters.info))
316 }, 37 },
@@ -330,9 +51,13 @@ const store = new Vuex.Store({ @@ -330,9 +51,13 @@ const store = new Vuex.Store({
330 }, 51 },
331 }, 52 },
332 actions: { 53 actions: {
333 - Login({ commit }, that) {  
334 - // request.fetchLogin(that.loginForm).then(res => { 54 + Login({ state,commit }, params) {
  55 + let loginForm={}
  56 + loginForm.username = params.username;
  57 + loginForm.password = encryptLoginPassword(params.password);
  58 + // request.fetchLogin(loginForm).then(res => {
335 // if (res.status == 200) { 59 // if (res.status == 200) {
  60 + // const dataJSON = JSON.parse(b64DecodeUnicode(res.data));
336 commit("setToken", "xxxx") 61 commit("setToken", "xxxx")
337 commit("setInfo", { 62 commit("setInfo", {
338 permissions: [ 63 permissions: [
@@ -347,14 +72,19 @@ const store = new Vuex.Store({ @@ -347,14 +72,19 @@ const store = new Vuex.Store({
347 // authorityRouter:[], 72 // authorityRouter:[],
348 }); 73 });
349 commit("setRouters", addrouters) 74 commit("setRouters", addrouters)
350 - addrouters.forEach((res) => {  
351 - that.$router.addRoute(res); 75 + state.addRouters.forEach((res) => {
  76 + router.addRoute(res);
352 }); 77 });
353 - that.$router.push({ path: "/" }) 78 + console.log()
  79 + if (params.url) {
  80 + window.location.href = params.url;
  81 + } else {
  82 + router.push({ path: "/" })
  83 + }
354 // } 84 // }
355 // }) 85 // })
356 }, 86 },
357 - permissions({ commit }, that) { 87 + permissions({ state,commit }, that) {
358 // request.fetchLogin(that.loginForm).then(res => { 88 // request.fetchLogin(that.loginForm).then(res => {
359 // if (res.status == 200) { 89 // if (res.status == 200) {
360 commit("setToken", "xxxx") 90 commit("setToken", "xxxx")
@@ -371,7 +101,7 @@ const store = new Vuex.Store({ @@ -371,7 +101,7 @@ const store = new Vuex.Store({
371 // authorityRouter:[], 101 // authorityRouter:[],
372 }); 102 });
373 commit("setRouters", addrouters) 103 commit("setRouters", addrouters)
374 - addrouters.forEach((res) => { 104 + state.addRouters.forEach((res) => {
375 that.$router.addRoute(res); 105 that.$router.addRoute(res);
376 }); 106 });
377 that.$router.push({ path: "/" }) 107 that.$router.push({ path: "/" })
src/utils/index.js
1 1
2 -import CryptoJS from "crypto-js" 2 +// import CryptoJS from "crypto-js"
  3 +import { JSEncrypt } from 'jsencrypt'
3 4
4 const encryptKey = "WfJTKO9S4eLkrPz2JKrAnzdb" 5 const encryptKey = "WfJTKO9S4eLkrPz2JKrAnzdb"
5 const encryptIV = "D076D35C" 6 const encryptIV = "D076D35C"
  7 +/**
  8 + * 登录密码加密,公钥直接写死在方法里
  9 + * @param data: 待加密数据
  10 + * @returns 加密结果
  11 + */
  12 +export function encryptLoginPassword(data){
  13 + const secret = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjh2ei17z5k2r4VzbqoSCE6RmYzWySJTgVQYulgfVM+vqcDoUE4cFB4XCFA2lHWjjpsuJP1EtwKlvUgxo5okr3x/a88o8eERxBynnVQZbEYpKteW5aqSEb/g1yPLWnKV88b/ED445ITYbZZuInRo5lkCvd6QEjL6d2Fch6mEo5awYXC4/S4BJf9YlYRhGzR7wpiXCLvyBHQ4iSIIDNpmrPBPQzGP0rx09aDu54kz/42CR6SX2OqXSi4ZoieqkPFl/iuX4RoD/NKKR+haDn1UzoD3k1WzHSTBFFs27rxRpxfBUZzfXQeskgKyw/Slcl3jUFizczsY4CLgTRrfey48Q6QIDAQAB';
  14 + // 新建JSEncrypt对象
  15 + let encryptor = new JSEncrypt();
  16 + // 设置公钥
  17 + encryptor.setPublicKey(secret);
  18 + // 加密数据
  19 + return encryptor.encrypt(data);
  20 +}
  21 +
  22 +/**
  23 +* 对称加密
  24 +* @param secret:加密公钥
  25 +* @param data: 待加密数据
  26 +* @returns 加密结果
  27 +*/
  28 +export function encryptData(secret, data){
  29 + // 新建JSEncrypt对象
  30 + let encryptor = new JSEncrypt();
  31 + // 设置公钥
  32 + encryptor.setPublicKey(secret);
  33 + // 加密数据
  34 + return encryptor.encrypt(data);
  35 +}
6 36
7 // 深度复制 37 // 深度复制
8 export function deepClone (obj) { 38 export function deepClone (obj) {
@@ -19,29 +49,29 @@ export function deepClone (obj) { @@ -19,29 +49,29 @@ export function deepClone (obj) {
19 return result 49 return result
20 } 50 }
21 51
22 -// 3DES加密  
23 -export function desEncrypt (str, key = encryptKey, iv = encryptIV) {  
24 - var cryptoKey = CryptoJS.enc.Utf8.parse(key)  
25 - var cryptoIv = CryptoJS.enc.Utf8.parse(iv.substr(0, 8))  
26 - var encodeStr = CryptoJS.TripleDES.encrypt(str, cryptoKey, {  
27 - iv: cryptoIv,  
28 - mode: CryptoJS.mode.CBC,  
29 - padding: CryptoJS.pad.Pkcs7  
30 - })  
31 - return encodeStr.toString()  
32 -} 52 +// // 3DES加密
  53 +// export function desEncrypt (str, key = encryptKey, iv = encryptIV) {
  54 +// var cryptoKey = CryptoJS.enc.Utf8.parse(key)
  55 +// var cryptoIv = CryptoJS.enc.Utf8.parse(iv.substr(0, 8))
  56 +// var encodeStr = CryptoJS.TripleDES.encrypt(str, cryptoKey, {
  57 +// iv: cryptoIv,
  58 +// mode: CryptoJS.mode.CBC,
  59 +// padding: CryptoJS.pad.Pkcs7
  60 +// })
  61 +// return encodeStr.toString()
  62 +// }
33 63
34 -// 3DES解密  
35 -export function desDecrypt (str, key = encryptKey, iv = encryptIV) {  
36 - var cryptoKey = CryptoJS.enc.Utf8.parse(key)  
37 - var cryptoIv = CryptoJS.enc.Utf8.parse(iv.substr(0, 8))  
38 - var decryptStr = CryptoJS.TripleDES.decrypt(str, cryptoKey, {  
39 - iv: cryptoIv,  
40 - mode: CryptoJS.mode.CBC,  
41 - padding: CryptoJS.pad.Pkcs7  
42 - })  
43 - return decryptStr.toString(CryptoJS.enc.Utf8)  
44 -} 64 +// // 3DES解密
  65 +// export function desDecrypt (str, key = encryptKey, iv = encryptIV) {
  66 +// var cryptoKey = CryptoJS.enc.Utf8.parse(key)
  67 +// var cryptoIv = CryptoJS.enc.Utf8.parse(iv.substr(0, 8))
  68 +// var decryptStr = CryptoJS.TripleDES.decrypt(str, cryptoKey, {
  69 +// iv: cryptoIv,
  70 +// mode: CryptoJS.mode.CBC,
  71 +// padding: CryptoJS.pad.Pkcs7
  72 +// })
  73 +// return decryptStr.toString(CryptoJS.enc.Utf8)
  74 +// }
45 75
46 // 随机生成由字母+数字的字符串 76 // 随机生成由字母+数字的字符串
47 export function randomWord (randomFlag, min, max) { 77 export function randomWord (randomFlag, min, max) {
@@ -86,6 +116,21 @@ export function getCookie (name, defaultValue) { @@ -86,6 +116,21 @@ export function getCookie (name, defaultValue) {
86 return result[0] === document.cookie.match(result[1]) ? unescape(result[0][2]) : defaultValue 116 return result[0] === document.cookie.match(result[1]) ? unescape(result[0][2]) : defaultValue
87 } 117 }
88 118
  119 +
  120 +/**
  121 + * base64转化unicode
  122 + */
  123 + export function b64DecodeUnicode(str) {
  124 + let uni;
  125 + try {
  126 + // atob 经过 base-64 编码的字符串进行解码
  127 + uni = decodeURIComponent(atob(str).split('').map(function (c) {
  128 + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
  129 + }).join(''));
  130 + } catch (e) {}
  131 + return uni;
  132 +}
  133 +
89 // base64ToFile 134 // base64ToFile
90 export function base64ToFile (base64Data, tempfilename, contentType) { 135 export function base64ToFile (base64Data, tempfilename, contentType) {
91 contentType = contentType || "" 136 contentType = contentType || ""
@@ -228,3 +273,28 @@ export function getNewTime (dayNum) { @@ -228,3 +273,28 @@ export function getNewTime (dayNum) {
228 var time = date.getTime() 273 var time = date.getTime()
229 return time 274 return time
230 } 275 }
  276 +
  277 +/*
  278 + * 获取URL参数
  279 + *
  280 + * */
  281 +export function getURLParams(variable) {
  282 + let str = window.location.href.split("?")[1];
  283 + if (!str) return null;
  284 + let ar = str.split("&");
  285 + let obj = {};
  286 + let data;
  287 + for (var i = 0; i < ar.length; i++) {
  288 + var pair = ar[i].split("=");
  289 + pair[1] = decodeURIComponent(pair[1])
  290 +
  291 + if (pair[0] == variable) {
  292 + data = pair[1]
  293 + return pair[1]
  294 + }
  295 + if (pair[0]) {
  296 + obj[pair[0]] = pair[1]
  297 + }
  298 + }
  299 + return variable ? data : obj
  300 +}
231 \ No newline at end of file 301 \ No newline at end of file
src/views/examinationPaper/add.vue
1 <template> 1 <template>
2 - <div>添加答题卡</div> 2 + <div>
  3 + <back-box>
  4 + <template slot="title">
  5 + <span>{{ "创建答题卡" }}</span>
  6 + </template>
  7 + </back-box>
  8 + <div class="content">
  9 + <el-steps
  10 + :active="step"
  11 + finish-status="success"
  12 + simple
  13 + style="margin: 20px 0"
  14 + >
  15 + <el-step title="基础信息" icon="el-icon-edit"></el-step>
  16 + <el-step title="题目编辑" icon="el-icon-tickets"></el-step>
  17 + <el-step title="设置答案" icon="el-icon-edit-outline"></el-step>
  18 + </el-steps>
  19 + <div v-show="step == 0">
  20 + <el-form
  21 + ref="forms"
  22 + :model="form"
  23 + :rules="formRules"
  24 + label-width="140px"
  25 + >
  26 + <el-form-item label="答题卡名称:" prop="title">
  27 + <el-col :span="10"
  28 + ><el-input
  29 + type="text"
  30 + placeholder="请输入答题卡名称"
  31 + v-model.trim="form.title"
  32 + maxlength="30"
  33 + size="45"
  34 + show-word-limit
  35 + >
  36 + </el-input
  37 + ></el-col>
  38 + </el-form-item>
  39 + <el-form-item label="测验类型:">
  40 + <el-select v-model="form.tag" placeholder="选择测验类型">
  41 + <el-option
  42 + v-for="item in answerTypeList"
  43 + :key="item.id"
  44 + :label="item.typeName"
  45 + :value="item.id"
  46 + >{{ item.typeName }}</el-option
  47 + >
  48 + </el-select>
  49 + <el-button
  50 + class="ml-20"
  51 + type="primary"
  52 + round
  53 + circle
  54 + icon="el-icon-plus"
  55 + @click="dialogVisible = true"
  56 + ></el-button>
  57 + </el-form-item>
  58 + <el-form-item label="年级:" prop="gradeName">
  59 + <el-select
  60 + class="sel"
  61 + v-model="form.gradeName"
  62 + placeholder=""
  63 + @change="changeGrade"
  64 + >
  65 + <el-option
  66 + v-for="item in gradeList"
  67 + :key="item"
  68 + :label="item"
  69 + :value="item"
  70 + >
  71 + </el-option>
  72 + </el-select>
  73 + </el-form-item>
  74 + <el-form-item label="科目:" prop="subjectId">
  75 + <el-select class="sel" v-model="form.subjectId" placeholder="">
  76 + <el-option
  77 + v-for="item in subjectList"
  78 + :key="item.value"
  79 + :label="item.label"
  80 + :value="item.value"
  81 + >
  82 + </el-option>
  83 + </el-select>
  84 + </el-form-item>
  85 + <el-form-item label="考试时长:" prop="examsDuration">
  86 + <el-input-number
  87 + size="medium"
  88 + :min="1"
  89 + :max="240"
  90 + v-model="form.examsDuration"
  91 + label="考试时长"
  92 + ></el-input-number>
  93 + </el-form-item>
  94 + <el-form-item label="分享范围:" prop="share">
  95 + <el-radio-group v-model="form.share">
  96 + <el-radio :label="1">任课班级分享</el-radio>
  97 + <el-radio :label="2">全年级分享</el-radio>
  98 + </el-radio-group>
  99 + </el-form-item>
  100 + </el-form>
  101 + <div class="btn-box">
  102 + <el-button type="danger" plain round @click="linkBack"
  103 + >取消</el-button
  104 + >
  105 + <el-button type="primary" round @click="setStep1">下一步</el-button>
  106 + </div>
  107 + <el-dialog
  108 + title="天假测验类型"
  109 + :visible.sync="dialogVisible"
  110 + width="500px"
  111 + >
  112 + <div class="dia-content">
  113 + <p class="add-type">
  114 + <el-input
  115 + type="text"
  116 + placeholder="请输入答题卡类型名称"
  117 + v-model.trim="answerTypeName"
  118 + maxlength="10"
  119 + show-word-limit
  120 + >
  121 + </el-input>
  122 + </p>
  123 + </div>
  124 + <div class="" slot="footer">
  125 + <el-button type="primary" @click="addAnswerTypeName"
  126 + >确 定</el-button
  127 + >
  128 + <el-button @click="dialogVisible = false">取 消</el-button>
  129 + </div>
  130 + </el-dialog>
  131 + </div>
  132 + <div v-show="step == 1">
  133 + <div v-for="(question, index) in form.questionList" :key="index">
  134 + <p class="question-title">
  135 + <span>{{ setBigNum(index) }}、</span>
  136 + <el-input
  137 + class="ipt"
  138 + v-model.trim="question.questionTitle"
  139 + placeholder="填写大题名称"
  140 + ></el-input>
  141 + <el-popconfirm
  142 + title="确定删除这道大题吗?"
  143 + @confirm="form.questionList.splice(index, 1)"
  144 + >
  145 + <el-button
  146 + slot="reference"
  147 + class="delete"
  148 + type="danger"
  149 + size="mini"
  150 + circle
  151 + icon="el-icon-delete"
  152 + ></el-button>
  153 + </el-popconfirm>
  154 +
  155 + <span>总分数:{{ setScore(question) }}分</span>
  156 + </p>
  157 + <ul class="questions-ul">
  158 + <li class="sub-questions">
  159 + <div class="qs-num">题号</div>
  160 + <div class="qs-type">题型</div>
  161 + <div class="qs-score">分数</div>
  162 + <div class="qs-partScore">部分分值</div>
  163 + <div class="qs-options">选项设置</div>
  164 + <div class="qs-set">操作</div>
  165 + </li>
  166 + <li
  167 + class="sub-questions"
  168 + v-for="(subQuestions, indexs) in question.subQuestions"
  169 + :key="indexs"
  170 + >
  171 + <div class="qs-num">{{ setNum(index, indexs) }}</div>
  172 + <div class="qs-type">
  173 + <el-select
  174 + v-model="subQuestions.questionType"
  175 + placeholder="选择答题卡类型"
  176 + @change="changeSubQuestions($event, subQuestions)"
  177 + >
  178 + <el-option label="单选题" :value="2"></el-option>
  179 + <el-option label="多选题" :value="3"></el-option>
  180 + <el-option label="判断题" :value="4"></el-option>
  181 + <el-option label="主观题" :value="5"></el-option>
  182 + </el-select>
  183 + </div>
  184 + <div class="qs-score">
  185 + <el-input-number
  186 + class="number-ipt"
  187 + size="medium"
  188 + :min="1"
  189 + :max="200"
  190 + :precision="2"
  191 + v-model="subQuestions.score"
  192 + label="单题分值"
  193 + ></el-input-number>
  194 + </div>
  195 + <div class="qs-partScore">
  196 + <p v-if="subQuestions.questionType != 3">--</p>
  197 + <el-input-number
  198 + class="number-ipt"
  199 + v-else
  200 + size="medium"
  201 + :min="0"
  202 + :precision="2"
  203 + :max="subQuestions.score"
  204 + :step="0.5"
  205 + v-model="subQuestions.partScore"
  206 + label="部分分值"
  207 + ></el-input-number>
  208 + </div>
  209 + <div class="qs-options">
  210 + <p v-if="subQuestions.questionType == 5">--</p>
  211 + <p
  212 + v-else-if="subQuestions.questionType == 4"
  213 + class="answer-box"
  214 + >
  215 + <span class="answer-s">✓</span>
  216 + <span class="answer-s">✗</span>
  217 + </p>
  218 + <p v-else class="answer-box">
  219 + <span
  220 + class="answer-s"
  221 + v-for="option in subQuestions.answerOptions"
  222 + :key="option"
  223 + >{{ option }}</span
  224 + >
  225 + <el-button
  226 + size="mini"
  227 + type="primary"
  228 + icon="el-icon-plus"
  229 + circle
  230 + @click="addOptions(subQuestions)"
  231 + ></el-button>
  232 + <el-button
  233 + size="mini"
  234 + type="primary"
  235 + icon="el-icon-minus"
  236 + round
  237 + circle
  238 + @click="removeOptions(subQuestions)"
  239 + ></el-button>
  240 + </p>
  241 + </div>
  242 + <div class="qs-set">
  243 + <el-popconfirm
  244 + title="确定删除这道题吗?"
  245 + @confirm="delTabData(indexs, index)"
  246 + >
  247 + <el-button
  248 + slot="reference"
  249 + class="delete"
  250 + type="danger"
  251 + size="mini"
  252 + circle
  253 + icon="el-icon-delete"
  254 + ></el-button>
  255 + </el-popconfirm>
  256 + </div>
  257 + </li>
  258 + <li class="sub-questions">
  259 + <div class="qs-num">添加</div>
  260 + <div class="qs-type">
  261 + <el-select
  262 + v-model="addSubQuestionsType"
  263 + placeholder="选择答题卡类型"
  264 + @change="changeAddSubQuestions($event, question)"
  265 + >
  266 + <el-option label="单选题" :value="2"></el-option>
  267 + <el-option label="多选题" :value="3"></el-option>
  268 + <el-option label="判断题" :value="4"></el-option>
  269 + <el-option label="主观题" :value="5"></el-option>
  270 + </el-select>
  271 + </div>
  272 + <div class="qs-score"></div>
  273 + <div class="qs-partScore"></div>
  274 + <div class="qs-options"></div>
  275 + <div class="qs-set"></div>
  276 + </li>
  277 + </ul>
  278 + </div>
  279 + <div class="add-box">
  280 + <p class="add-question" @click="openQuestion">
  281 + <el-button
  282 + size="mini"
  283 + type="primary"
  284 + icon="el-icon-plus"
  285 + circle
  286 + ></el-button>
  287 + <span class="s1">添加大题</span>
  288 + </p>
  289 + </div>
  290 + <div class="btn-box">
  291 + <el-button type="danger" plain round @click="linkBack"
  292 + >取消</el-button
  293 + >
  294 + <el-button round @click="step = 0">上一步</el-button>
  295 + <el-button type="primary" round @click="setStep2">下一步</el-button>
  296 + </div>
  297 + <el-dialog
  298 + title="添加大题"
  299 + :visible.sync="addQuestionVisible"
  300 + width="600px"
  301 + >
  302 + <div class="dia-content">
  303 + <el-form
  304 + ref="form"
  305 + :model="questionForm"
  306 + :rules="questionFormRules"
  307 + label-width="100px"
  308 + >
  309 + <el-form-item label="标题:" prop="questionTitle">
  310 + <el-col :span="12">
  311 + <el-input
  312 + v-model.trim="questionForm.questionTitle"
  313 + maxlength="30"
  314 + placeholder="输入大题名称"
  315 + ></el-input>
  316 + </el-col>
  317 + </el-form-item>
  318 + <el-form-item label="选择题型:">
  319 + <el-select v-model="questionForm.questionType" placeholder="">
  320 + <el-option
  321 + v-for="item in questionOptions"
  322 + :key="item.value"
  323 + :label="item.label"
  324 + :value="item.value"
  325 + >
  326 + </el-option>
  327 + </el-select>
  328 + </el-form-item>
  329 + <el-form-item label="默认题数:">
  330 + <el-input-number
  331 + v-model="questionForm.number"
  332 + :min="1"
  333 + :max="50"
  334 + label="label"
  335 + ></el-input-number>
  336 + </el-form-item>
  337 + </el-form>
  338 + </div>
  339 + <div class="dialog-footer" slot="footer">
  340 + <el-button type="primary" @click="addQuestion">确 定</el-button>
  341 + <el-button @click="addQuestionVisible = false">取 消</el-button>
  342 + </div>
  343 + </el-dialog>
  344 + </div>
  345 + <div v-show="step == 2">
  346 + <div v-for="(question, index) in form.questionList" :key="index">
  347 + <p class="question-title">
  348 + <span>{{ setBigNum(index) }}、</span>
  349 + <span class="title-txt">{{ question.questionTitle }}</span>
  350 + <span>共 {{ setScore(question) }} 分</span>
  351 + </p>
  352 + <ul class="questions-ul">
  353 + <li class="sub-questions">
  354 + <div class="qs-num">题号</div>
  355 + <div class="qs-score">分数</div>
  356 + <div class="qs-options qs-options2">选项设置</div>
  357 + </li>
  358 + <li
  359 + class="sub-questions"
  360 + v-for="(subQuestions, indexs) in question.subQuestions"
  361 + :key="indexs"
  362 + >
  363 + <div class="qs-num">{{ setNum(index, indexs) }}</div>
  364 + <div class="qs-type">
  365 + {{ setSubPro(subQuestions.questionType) }}
  366 + </div>
  367 + <div class="qs-score">
  368 + <el-input-number
  369 + class="number-ipt"
  370 + size="medium"
  371 + :min="1"
  372 + :max="200"
  373 + :precision="2"
  374 + v-model="subQuestions.score"
  375 + label="单题分值"
  376 + ></el-input-number>
  377 + </div>
  378 + <div class="qs-options qs-options2">
  379 + <p v-if="subQuestions.questionType == 5">--</p>
  380 + <p v-if="subQuestions.questionType == 4" class="answer-box">
  381 + <span
  382 + class="answer-s"
  383 + :class="subQuestions.correctAnswer == 1 ? 'active' : ''"
  384 + @click="subQuestions.correctAnswer = 1"
  385 + >✓</span
  386 + >
  387 + <span
  388 + class="answer-s"
  389 + :class="subQuestions.correctAnswer == 2 ? 'active' : ''"
  390 + @click="subQuestions.correctAnswer = 2"
  391 + >✗</span
  392 + >
  393 + </p>
  394 + <p v-if="subQuestions.questionType == 3" class="answer-box">
  395 + <span
  396 + class="answer-s"
  397 + v-for="option in subQuestions.answerOptions"
  398 + :class="
  399 + subQuestions.correctAnswer.includes(option)
  400 + ? 'active'
  401 + : ''
  402 + "
  403 + :key="option"
  404 + @click="changAnswer(subQuestions, option)"
  405 + >{{ option }}</span
  406 + >
  407 + </p>
  408 + <p v-if="subQuestions.questionType == 2" class="answer-box">
  409 + <span
  410 + class="answer-s"
  411 + v-for="option in subQuestions.answerOptions"
  412 + :class="
  413 + subQuestions.correctAnswer == option ? 'active' : ''
  414 + "
  415 + :key="option"
  416 + @click="subQuestions.correctAnswer = option"
  417 + >{{ option }}</span
  418 + >
  419 + </p>
  420 + </div>
  421 + </li>
  422 + </ul>
  423 + </div>
  424 + <div class="btn-box">
  425 + <el-button type="danger" plain round @click="linkBack"
  426 + >取消</el-button
  427 + >
  428 + <el-button round @click="step = 1">上一步</el-button>
  429 + <el-button type="primary" round @click="save">保存</el-button>
  430 + </div>
  431 + </div>
  432 + </div>
  433 + </div>
3 </template> 434 </template>
4 435
5 <script> 436 <script>
  437 +const questionForm = {
  438 + questionTitle: "",
  439 + questionType: 2,
  440 + number: 10,
  441 +};
  442 +const subQuesOptions = {
  443 + questionType: 2,
  444 + score: 1,
  445 + partScore: 0,
  446 + selectNum: 4,
  447 + answerOptions: ["A", "B", "C", "D"],
  448 + correctAnswer: "",
  449 +};
6 export default { 450 export default {
  451 + data() {
  452 + return {
  453 + type: 1, //1-创建,2-复制答题卡
  454 + dialogVisible: false, //测验类型设置弹窗
  455 + addQuestionVisible: false, //添加大题弹窗
  456 + questionForm: { ...questionForm },
  457 + questionFormRules: {
  458 + questionTitle: [
  459 + { required: true, message: "请输入答题卡名称", trigger: "blur" },
  460 + {
  461 + min: 1,
  462 + max: 30,
  463 + message: "长度在 1 到 30 个字符",
  464 + trigger: "blur",
  465 + },
  466 + ],
  467 + },
  468 + questionOptions: [
  469 + { label: "单选题", value: 2 },
  470 + { label: "多选题", value: 3 },
  471 + { label: "判断题", value: 4 },
  472 + { label: "主观题", value: 5 },
  473 + ],
  474 + rightOptions: ["A", "B", "C", "D", "E", "F", "G"],
  475 + addSubQuestionsType: "",
  476 + step: 0, //步骤
  477 + gradeList: [], //年级
  478 + subjectList: [], //科目
  479 + answerTypeList: [], //测验类型
  480 + answerTypeName: [], //测验类型名称
  481 + form: {
  482 + //答题卡详情
  483 + title: "",
  484 + tag: "",
  485 + subjectId: "",
  486 + examsDuration: 0,
  487 + gradeName: "",
  488 + share: 1,
  489 + questionList: [],
  490 + },
  491 + formRules: {
  492 + //答题卡验证
  493 + title: [
  494 + { required: true, message: "请输入答题卡名称", trigger: "blur" },
  495 + {
  496 + min: 1,
  497 + max: 30,
  498 + message: "长度在 1 到 30 个字符",
  499 + trigger: "blur",
  500 + },
  501 + ],
  502 + gradeName: [{ required: true, message: "请选择年级", trigger: "blur" }],
  503 + subjectId: [{ required: true, message: "请选择科目", trigger: "blur" }],
  504 + examsDuration: [
  505 + { required: true, message: "请设置考试时长", trigger: "blur" },
  506 + ],
  507 + },
  508 + };
  509 + },
  510 + created() {
  511 + this.type = this.$route.query.type ? this.$route.query.type : 1;
  512 + if (this.type == 2) {
  513 + this.form = this.$route.query.form && JSON.parse(this.$route.query.form);
  514 + console.log(this.form.examsDuration)
  515 + this.form.examsDuration = Number(this.form.examsDuration)/60
  516 + }
  517 + },
  518 + methods: {
  519 + linkBack() {
  520 + this.$confirm(
  521 + (this.type == 2 ? "修改复制的" : "组建的") +
  522 + "答题卡未保存,确认退出吗?",
  523 + "提示",
  524 + {
  525 + confirmButtonText: "取消",
  526 + cancelButtonText: "确定",
  527 + confirmButtonClass: "el-button--danger1",
  528 + cancelButtonClass: "el-button--primary",
  529 + showClose: false,
  530 + roundButton: true,
  531 + center: true,
  532 + type: "warning",
  533 + }
  534 + )
  535 + .then(() => {})
  536 + .catch(() => {
  537 + this.$router.push({
  538 + path: "/examinationPaper",
  539 + });
  540 + });
  541 + },
  542 + setSubPro(type) {
  543 + let tit;
  544 + switch (type) {
  545 + case 2:
  546 + tit = "单选题";
  547 + break;
  548 + case 3:
  549 + tit = "多选题";
  550 + break;
  551 + case 4:
  552 + tit = "判断题";
  553 + break;
  554 + case 5:
  555 + tit = "主观题";
  556 + break;
  557 + }
  558 + return tit;
  559 + },
  560 + setNum(index, indexs) {
  561 + let lengths = 0;
  562 + for (let i = 0; i < index; i++) {
  563 + lengths += this.form.questionList[i].subQuestions.length;
  564 + }
  565 + return lengths + indexs + 1;
  566 + },
  567 + setBigNum(num) {
  568 + let txt = "";
  569 + let bigNum = [
  570 + "一",
  571 + "二",
  572 + "三",
  573 + "四",
  574 + "五",
  575 + "六",
  576 + "七",
  577 + "八",
  578 + "九",
  579 + "十",
  580 + "十一",
  581 + "十二",
  582 + "十三",
  583 + "十四",
  584 + "十五",
  585 + "十六",
  586 + "十七",
  587 + "十八",
  588 + "十九",
  589 + "二十",
  590 + ];
  591 + txt = bigNum[num];
7 592
8 -}  
9 -</script> 593 + return txt;
  594 + },
  595 + setAddIndex(index) {},
  596 + setStep1() {
  597 + this.$refs["forms"].validate((valid) => {
  598 + // 验证通过:保存
  599 + if (valid) {
  600 + this.step = 1;
  601 + } else {
  602 + this.$message.error("数据有误,请检查!");
  603 + return false;
  604 + }
  605 + });
  606 + },
  607 + setStep2() {
  608 + let valid = true;
  609 + this.form.questionList.map((item) => {
  610 + if (!item.questionTitle) {
  611 + valid = false;
  612 + }
  613 + });
  614 + if (valid) {
  615 + this.step = 2;
  616 + } else {
  617 + this.$message.error("大题名称不能为空,请检查!");
  618 + }
  619 + },
  620 + openQuestion() {
  621 + this.questionForm = { ...questionForm };
  622 + this.addQuestionVisible = true;
  623 + },
  624 + addQuestion() {
  625 + let subQuestions = [];
  626 + let questionsOptions = {
  627 + ...subQuesOptions,
  628 + questionType: this.questionForm.questionType,
  629 + };
  630 + switch (questionsOptions.questionType) {
  631 + case 2:
  632 + questionsOptions.answerOptions = this.rightOptions.slice(
  633 + 0,
  634 + questionsOptions.selectNum
  635 + );
  636 + break;
  637 + case 3:
  638 + questionsOptions.answerOptions = this.rightOptions.slice(
  639 + 0,
  640 + questionsOptions.selectNum
  641 + );
  642 + questionsOptions.partScore = 0.5;
  643 + break;
  644 + case 4:
  645 + case 5:
  646 + questionsOptions.selectNum = 0;
  647 + break;
  648 + }
  649 + for (let i = 0; i < this.questionForm.number; i++) {
  650 + subQuestions.push({ ...questionsOptions });
  651 + }
  652 + this.form.questionList.push({
  653 + questionTitle: this.questionForm.questionTitle,
  654 + number: this.questionForm.number,
  655 + source: 10,
  656 + subQuestions: [...subQuestions],
  657 + });
  658 + this.addQuestionVisible = false;
  659 + },
  660 + delTabData(subIndex, index) {
  661 + //删除小题
  662 + console.log(subIndex);
  663 + console.log(index);
  664 + this.form.questionList[index].subQuestions.splice(subIndex, 1);
  665 + },
  666 + setScore(question) {
  667 + let score = question.subQuestions.reduce((a, b) => {
  668 + return a + b.score;
  669 + }, 0);
  670 + return score;
  671 + },
  672 + changeAddSubQuestions(val, question) {
  673 + if (val) {
  674 + let questionsOptions = {
  675 + ...subQuesOptions,
  676 + questionType: val,
  677 + };
  678 + switch (questionsOptions.questionType) {
  679 + case 2:
  680 + questionsOptions.answerOptions = this.rightOptions.slice(
  681 + 0,
  682 + questionsOptions.selectNum
  683 + );
  684 + break;
  685 + case 3:
  686 + questionsOptions.answerOptions = this.rightOptions.slice(
  687 + 0,
  688 + questionsOptions.selectNum
  689 + );
  690 + questionsOptions.partScore = 0.5;
  691 + break;
  692 + case 4:
  693 + case 5:
  694 + questionsOptions.selectNum = 0;
  695 + break;
  696 + }
  697 + question.subQuestions.push(questionsOptions);
  698 + this.addSubQuestionsType = "";
  699 + }
  700 + },
  701 + changeSubQuestions(val, subQuestions) {
  702 + //切换多题型-小题题型
  703 + const that = this;
  704 + subQuestions.score = 1;
  705 + subQuestions.partScore = 0;
  706 + subQuestions.correctAnswer = "";
  707 + subQuestions.selectNum = 4;
  708 + switch (val) {
  709 + case 2:
  710 + subQuestions.answerOptions = that.rightOptions.slice(
  711 + 0,
  712 + subQuestions.selectNum
  713 + );
  714 + break;
  715 + case 3:
  716 + subQuestions.answerOptions = that.rightOptions.slice(
  717 + 0,
  718 + subQuestions.selectNum
  719 + );
  720 + subQuestions.partScore = 0.5;
  721 + break;
  722 + case 4:
  723 + case 5:
  724 + subQuestions.selectNum = 0;
  725 + break;
  726 + }
  727 + },
  728 + addOptions(subQuestions) {
  729 + //添加选项
  730 + let length = subQuestions.answerOptions.length;
  731 + if (length > 6) return;
  732 + subQuestions.selectNum = length + 1;
  733 + subQuestions.answerOptions = this.rightOptions.slice(
  734 + 0,
  735 + subQuestions.selectNum
  736 + );
  737 + },
  738 + removeOptions(subQuestions) {
  739 + //删除选项
  740 + let length = subQuestions.answerOptions.length;
  741 + if (length < 2) return;
  742 + subQuestions.selectNum = length - 1;
  743 + subQuestions.answerOptions = this.rightOptions.slice(
  744 + 0,
  745 + subQuestions.selectNum
  746 + );
  747 + },
  748 + changAnswer(sub, option) {
  749 + //设置多选答案
  750 + let str = new RegExp(option, "g");
  751 + if (sub.correctAnswer?.includes(option)) {
  752 + sub.correctAnswer = sub.correctAnswer.replace(str, "");
  753 + } else {
  754 + let arrs = (sub.correctAnswer && sub.correctAnswer.split("")) || [];
  755 + arrs.push(option);
  756 + sub.correctAnswer = arrs.sort().join("");
  757 + }
  758 + },
  759 + async addAnswerTypeName() {
  760 + //保存测验类型
  761 + if (!this.answerTypeName) {
  762 + this.$message.error("请填写测验名称!");
  763 + return;
  764 + }
  765 + //添加测验类型
  766 + const { data, code, message } = await this.$request.addAnswerTypeName({
  767 + typeName: this.answerTypeName,
  768 + });
  769 + if (code == 0) {
  770 + this._CreatedTypeList();
  771 + this.dialogVisible = false;
  772 + this.answerTypeName = "";
  773 + this.$message.success("添加成功");
  774 + } else {
  775 + this.$message.error(message);
  776 + }
  777 + },
  778 + async save() {
  779 + if (this.saceLoading) return;
  780 + this.saceLoading = true;
  781 + const { data, code, message } = await this.$request.saveAnswerSheet({
  782 + ...this.form,
  783 + });
  784 + this.saceLoading = false;
  785 + if (code == 0) {
  786 + this.$router.push({
  787 + path:"/examinationPaper"
  788 + })
  789 + } else {
  790 + this.$message.error(message);
  791 + }
  792 + },
  793 + async changeGrade() {
  794 + //切换年级查询科目
  795 + this._QuerySubjectList(this.form.gradeName);
  796 + },
  797 + async _CreatedTypeList() {
  798 + //测验类型查询
  799 + const { data, code, message } = await this.$request.fetchTypeNames();
  800 + if (code == 0) {
  801 + this.answerTypeList = [...data.list] || [];
  802 + this.answerTypeList.unshift({
  803 + typeName: "--",
  804 + id: "",
  805 + });
  806 + if (this.type != 2) {
  807 + this.form.tag = this.answerTypeList[0].id || "";
  808 + }
  809 + } else {
  810 + this.$message.error(message);
  811 + }
  812 + },
  813 + async _GradeList() {
  814 + //查询年级列表
  815 + const { data, code, message } = await this.$request.fetchGradeList();
  816 + if (code == 0) {
  817 + this.gradeList = [...data.gradeNames] || [];
  818 + if (this.type != 2) {
  819 + this.form.gradeName = this.gradeList[0];
  820 + }
  821 + this._QuerySubjectList(this.gradeList[0]);
  822 + } else {
  823 + this.$message.error(message);
  824 + }
  825 + },
  826 + async _QuerySubjectList(grade, dont) {
  827 + //查询科目列表
  828 + let param = {};
  829 + if (grade) {
  830 + param.gradeName = grade;
  831 + }
  832 + const { data, code, message } = await this.$request.fetchSubjectList(
  833 + param
  834 + );
  835 + if (code === 0) {
  836 + this.subjectList = data.list.map((item) => {
  837 + return {
  838 + value: item.subjectId,
  839 + label: item.subjectName,
  840 + };
  841 + });
  842 + if (this.subjectList.length > 1) {
  843 + let isTeachingCourse = false;
  844 + this.subjectList.map((item) => {
  845 + if (item.isTeachingCourse) {
  846 + isTeachingCourse = true;
  847 + }
  848 + });
  849 + if (this.type != 2) {
  850 + !isTeachingCourse && !dont
  851 + ? (this.form.subjectId = this.subjectList[0].value)
  852 + : "";
  853 + }
  854 + }
  855 + if (this.subjectList.length > 0 && !dont) {
  856 + this.form.subjectId = this.subjectList[0].value;
  857 + }
  858 + } else {
  859 + this.$message.error(message);
  860 + }
  861 + },
10 862
11 -<style> 863 +
  864 + },
  865 +};
  866 +</script>
12 867
  868 +<style lang="scss" scoped>
  869 +.red {
  870 + color: #f30;
  871 +}
  872 +.content {
  873 + width: 100%;
  874 + box-sizing: border-box;
  875 + padding: 0 50px;
  876 + .ml-20 {
  877 + margin-left: 20px;
  878 + }
  879 + .btn-box {
  880 + text-align: right;
  881 + margin-left: 140px;
  882 + }
  883 +}
  884 +.dia-content {
  885 + .dia-tit {
  886 + font-size: 20px;
  887 + color: #333;
  888 + font-weight: 700;
  889 + text-align: center;
  890 + }
  891 + .add-type {
  892 + display: flex;
  893 + }
  894 + .add-btn {
  895 + margin-left: 20px;
  896 + }
  897 +}
  898 +.el-message-box {
  899 + :deep(.el-button--default) {
  900 + color: #fff;
  901 + }
  902 +}
  903 +.add-box {
  904 + display: flex;
  905 + justify-content: center;
  906 + align-items: center;
  907 + .add-question {
  908 + display: flex;
  909 + justify-content: center;
  910 + align-items: center;
  911 + font-size: 16px;
  912 + font-weight: bolder;
  913 + padding: 2px;
  914 + cursor: pointer;
  915 + .s1 {
  916 + margin-left: 6px;
  917 + }
  918 + :deep(.el-icon-plus) {
  919 + font-size: 24px;
  920 + font-weight: 900;
  921 + }
  922 + :deep(.el-button--mini.is-circle) {
  923 + padding: 3px;
  924 + }
  925 + }
  926 +}
  927 +.dialog-footer {
  928 + text-align: center;
  929 + :deep(.el-button) {
  930 + border-radius: 20px;
  931 + padding: 8px 20px 7px;
  932 + margin: 0 12px;
  933 + }
  934 +}
  935 +.question-title {
  936 + line-height: 40px;
  937 + .ipt {
  938 + width: 300px;
  939 + margin: 0 16px 0 10px;
  940 + :deep(.el-input__inner) {
  941 + border-radius: 20px;
  942 + border-color: #667ffd;
  943 + background: rgba($color: #667ffd, $alpha: 0.05);
  944 + }
  945 + }
  946 + .delete {
  947 + margin-right: 8px;
  948 + }
  949 + .title-txt {
  950 + margin-right: 20px;
  951 + font-size: 16px;
  952 + font-weight: 700;
  953 + }
  954 +}
  955 +.el-input-number {
  956 + width: 140px;
  957 +}
  958 +.answer-box {
  959 + .answer-s {
  960 + display: inline-block;
  961 + width: 30px;
  962 + height: 30px;
  963 + border: 1px solid #e2e2e2;
  964 + border-radius: 3px;
  965 + margin: 0 6px;
  966 + font-size: 16px;
  967 + color: #333;
  968 + text-align: center;
  969 + line-height: 30px;
  970 + &.active {
  971 + background: #5e78fa;
  972 + border-color: #5e78fa;
  973 + color: #fff;
  974 + }
  975 + }
  976 +}
  977 +.questions-ul {
  978 + border-left: 1px solid #e2e2e2;
  979 + border-top: 1px solid #e2e2e2;
  980 + margin: 12px 0;
  981 +}
  982 +.sub-questions {
  983 + width: 100%;
  984 + display: flex;
  985 + border-bottom: 1px solid #e2e2e2;
  986 + & > div {
  987 + min-height: 40px;
  988 + padding: 5px;
  989 + flex-shrink: 0;
  990 + border-right: 1px solid #e2e2e2;
  991 + display: flex;
  992 + justify-content: center;
  993 + align-items: center;
  994 + }
  995 + .qs-num {
  996 + width: 80px;
  997 + }
  998 + .qs-type {
  999 + width: 160px;
  1000 + }
  1001 + .qs-score,
  1002 + .qs-partScore {
  1003 + width: 160px;
  1004 + }
  1005 + .qs-options {
  1006 + flex: 1;
  1007 + }
  1008 + .qs-set {
  1009 + width: 80px;
  1010 + }
  1011 + .qs-options2 {
  1012 + text-align: left;
  1013 + justify-content: flex-start;
  1014 + padding-left: 20px;
  1015 + .answer-s {
  1016 + cursor: pointer;
  1017 + }
  1018 + }
  1019 + :deep(.el-select) {
  1020 + .el-input__inner {
  1021 + border-radius: 20px;
  1022 + border-color: #667ffd;
  1023 + width: 150px;
  1024 + height: 32px;
  1025 + line-height: 32px;
  1026 + background: rgba($color: #667ffd, $alpha: 0.05);
  1027 + }
  1028 + .el-input__icon {
  1029 + line-height: 32px;
  1030 + }
  1031 + }
  1032 +}
13 </style> 1033 </style>
14 \ No newline at end of file 1034 \ No newline at end of file
src/views/examinationPaper/edit.vue
@@ -5,12 +5,349 @@ @@ -5,12 +5,349 @@
5 <span>修改答案</span> 5 <span>修改答案</span>
6 </template> 6 </template>
7 </back-box> 7 </back-box>
  8 + <div class="content">
  9 + <p class="tips">
  10 + <i class="fa fa-bell-o"></i> 2022-11-24 14:30张老师修改了答案。
  11 + </p>
  12 + <div class="answer-title">
  13 + <p class="name">{{ form.title }}</p>
  14 + <p class="totals">卷面总分:{{ allScore }}分</p>
  15 + </div>
  16 + <div v-for="(question, index) in form.questionList" :key="index">
  17 + <p class="question-title">
  18 + <span>{{ setBigNum(index) }}、</span>
  19 + <el-input
  20 + class="ipt"
  21 + v-model.trim="question.questionTitle"
  22 + placeholder="填写大题名称"
  23 + ></el-input>
  24 + <span>共 {{ setScore(question) }} 分</span>
  25 + </p>
  26 + <ul class="questions-ul">
  27 + <li class="sub-questions">
  28 + <div class="qs-num">题号</div>
  29 + <div class="qs-score">分数</div>
  30 + <div class="qs-options qs-options2">选项设置</div>
  31 + </li>
  32 + <li
  33 + class="sub-questions"
  34 + v-for="(subQuestions, indexs) in question.subQuestions"
  35 + :key="indexs"
  36 + >
  37 + <div class="qs-num">{{ subQuestions.questionIndex }}</div>
  38 + <div class="qs-type">
  39 + {{ setSubPro(subQuestions.questionType) }}
  40 + </div>
  41 + <div class="qs-score">
  42 + <el-input-number
  43 + class="number-ipt"
  44 + size="medium"
  45 + :min="1"
  46 + :max="200"
  47 + :precision="2"
  48 + v-model="subQuestions.score"
  49 + label="单题分值"
  50 + ></el-input-number>
  51 + </div>
  52 + <div class="qs-options qs-options2">
  53 + <p v-if="subQuestions.questionType == 5">--</p>
  54 + <p v-if="subQuestions.questionType == 4" class="answer-box">
  55 + <span
  56 + class="answer-s"
  57 + :class="subQuestions.correctAnswer == 1 ? 'active' : ''"
  58 + @click="subQuestions.correctAnswer = 1"
  59 + >✓</span
  60 + >
  61 + <span
  62 + class="answer-s"
  63 + :class="subQuestions.correctAnswer == 2 ? 'active' : ''"
  64 + @click="subQuestions.correctAnswer = 2"
  65 + >✗</span
  66 + >
  67 + </p>
  68 + <p v-if="subQuestions.questionType == 3" class="answer-box">
  69 + <span
  70 + class="answer-s"
  71 + v-for="option in subQuestions.answerOptions"
  72 + :class="
  73 + subQuestions.correctAnswer.includes(option) ? 'active' : ''
  74 + "
  75 + :key="option"
  76 + @click="changAnswer(subQuestions, option)"
  77 + >{{ option }}</span
  78 + >
  79 + </p>
  80 + <p v-if="subQuestions.questionType == 2" class="answer-box">
  81 + <span
  82 + class="answer-s"
  83 + v-for="option in subQuestions.answerOptions"
  84 + :class="subQuestions.correctAnswer == option ? 'active' : ''"
  85 + :key="option"
  86 + @click="subQuestions.correctAnswer = option"
  87 + >{{ option }}</span
  88 + >
  89 + </p>
  90 + </div>
  91 + </li>
  92 + </ul>
  93 + </div>
  94 + <div class="btn-box">
  95 + <el-button type="danger" plain round @click="linkBack">取消</el-button>
  96 + <el-button type="primary" round @click="save">保存</el-button>
  97 + </div>
  98 + </div>
8 </div> 99 </div>
9 </template> 100 </template>
10 101
11 <script> 102 <script>
12 -export default {}; 103 +export default {
  104 + data() {
  105 + return {
  106 + form: {
  107 + //答题卡详情
  108 + title: "",
  109 + tag: "",
  110 + subjectId: "",
  111 + examsDuration: 90,
  112 + gradeName: "",
  113 + share: 1,
  114 + questionList: [],
  115 + },
  116 + };
  117 + },
  118 + computed: {
  119 + allScore: function () {
  120 + let score = 0;
  121 + this.form.questionList.map((item) => {
  122 + score += item.subQuestions.reduce((a, b) => {
  123 + return a + Number(b.score);
  124 + }, 0);
  125 + }, 0);
  126 + return Number(score).toFixed(2);
  127 + },
  128 + },
  129 + created() {
  130 + this.form = this.$route.query.form && JSON.parse(this.$route.query.form);
  131 + },
  132 + methods: {
  133 + linkBack() {
  134 + this.$router.push({
  135 + path: "/examinationPaper",
  136 + });
  137 + },
  138 + setSubPro(type) {
  139 + let tit;
  140 + switch (type) {
  141 + case 2:
  142 + tit = "单选题";
  143 + break;
  144 + case 3:
  145 + tit = "多选题";
  146 + break;
  147 + case 4:
  148 + tit = "判断题";
  149 + break;
  150 + case 5:
  151 + tit = "主观题";
  152 + break;
  153 + }
  154 + return tit;
  155 + },
  156 + setBigNum(num) {
  157 + let txt = "";
  158 + let bigNum = [
  159 + "一",
  160 + "二",
  161 + "三",
  162 + "四",
  163 + "五",
  164 + "六",
  165 + "七",
  166 + "八",
  167 + "九",
  168 + "十",
  169 + "十一",
  170 + "十二",
  171 + "十三",
  172 + "十四",
  173 + "十五",
  174 + "十六",
  175 + "十七",
  176 + "十八",
  177 + "十九",
  178 + "二十",
  179 + ];
  180 + txt = bigNum[num];
  181 +
  182 + return txt;
  183 + },
  184 + setScore(question) {
  185 + let score = question.subQuestions.reduce((a, b) => {
  186 + return a + b.score;
  187 + }, 0);
  188 + return score;
  189 + },
  190 + changAnswer(sub, option) {
  191 + //设置多选答案
  192 + let str = new RegExp(option, "g");
  193 + if (sub.correctAnswer?.includes(option)) {
  194 + sub.correctAnswer = sub.correctAnswer.replace(str, "");
  195 + } else {
  196 + let arrs = (sub.correctAnswer && sub.correctAnswer.split("")) || [];
  197 + arrs.push(option);
  198 + sub.correctAnswer = arrs.sort().join("");
  199 + }
  200 + },
  201 + save(){
  202 + //删除答题卡
  203 + // const { data, code, message } = await this.$request.updateAnswerSheet({...this.form});
  204 + // if (code == 0) {
  205 + this.$router.push({
  206 + path:"/examinationPaper"
  207 + })
  208 + // } else {
  209 + // this.$message.error(message);
  210 + // }
  211 + }
  212 + },
  213 +};
13 </script> 214 </script>
14 215
15 -<style> 216 +<style lang="scss" scoped>
  217 +.content {
  218 + width: 100%;
  219 + box-sizing: border-box;
  220 + padding: 0 50px;
  221 + .ml-20 {
  222 + margin-left: 20px;
  223 + }
  224 + .btn-box {
  225 + text-align: right;
  226 + margin-left: 140px;
  227 + }
  228 + .tips {
  229 + height: 48px;
  230 + line-height: 48px;
  231 + padding: 0 16px;
  232 + border: 1px solid #fac7cc;
  233 + background-color: #ffebec;
  234 + font-size: 14px;
  235 + color: #fd9795;
  236 + margin: 10px 0 20px 0;
  237 + .fa-bell-o {
  238 + font-size: 18px;
  239 + margin-right: 5px;
  240 + }
  241 + }
  242 +}
  243 +.answer-title {
  244 + text-align: center;
  245 + font-size: 20px;
  246 + color: #333;
  247 + font-weight: 700;
  248 + padding: 20px 0 0 0;
  249 + .totals {
  250 + font-size: 16px;
  251 + color: #888;
  252 + font-weight: normal;
  253 + }
  254 +}
  255 +.question-title {
  256 + line-height: 40px;
  257 + .ipt {
  258 + width: 300px;
  259 + margin: 0 16px 0 10px;
  260 + :deep(.el-input__inner) {
  261 + border-radius: 20px;
  262 + border-color: #667ffd;
  263 + background: rgba($color: #667ffd, $alpha: 0.05);
  264 + }
  265 + }
  266 + .delete {
  267 + margin-right: 8px;
  268 + }
  269 + .title-txt {
  270 + margin-right: 20px;
  271 + font-size: 16px;
  272 + font-weight: 700;
  273 + }
  274 +}
  275 +.el-input-number {
  276 + width: 140px;
  277 +}
  278 +.answer-box {
  279 + .answer-s {
  280 + display: inline-block;
  281 + width: 30px;
  282 + height: 30px;
  283 + border: 1px solid #e2e2e2;
  284 + border-radius: 3px;
  285 + margin: 0 6px;
  286 + font-size: 16px;
  287 + color: #333;
  288 + text-align: center;
  289 + line-height: 30px;
  290 + &.active {
  291 + background: #5e78fa;
  292 + border-color: #5e78fa;
  293 + color: #fff;
  294 + }
  295 + }
  296 +}
  297 +.questions-ul {
  298 + border-left: 1px solid #e2e2e2;
  299 + border-top: 1px solid #e2e2e2;
  300 + margin: 12px 0;
  301 +}
  302 +.sub-questions {
  303 + width: 100%;
  304 + display: flex;
  305 + border-bottom: 1px solid #e2e2e2;
  306 + & > div {
  307 + min-height: 40px;
  308 + padding: 5px;
  309 + flex-shrink: 0;
  310 + border-right: 1px solid #e2e2e2;
  311 + display: flex;
  312 + justify-content: center;
  313 + align-items: center;
  314 + }
  315 + .qs-num {
  316 + width: 80px;
  317 + }
  318 + .qs-type {
  319 + width: 160px;
  320 + }
  321 + .qs-score,
  322 + .qs-partScore {
  323 + width: 160px;
  324 + }
  325 + .qs-options {
  326 + flex: 1;
  327 + }
  328 + .qs-set {
  329 + width: 80px;
  330 + }
  331 + .qs-options2 {
  332 + text-align: left;
  333 + justify-content: flex-start;
  334 + padding-left: 20px;
  335 + .answer-s {
  336 + cursor: pointer;
  337 + }
  338 + }
  339 + :deep(.el-select) {
  340 + .el-input__inner {
  341 + border-radius: 20px;
  342 + border-color: #667ffd;
  343 + width: 150px;
  344 + height: 32px;
  345 + line-height: 32px;
  346 + background: rgba($color: #667ffd, $alpha: 0.05);
  347 + }
  348 + .el-input__icon {
  349 + line-height: 32px;
  350 + }
  351 + }
  352 +}
16 </style> 353 </style>
17 \ No newline at end of file 354 \ No newline at end of file
src/views/examinationPaper/index.vue
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 icon="el-icon-plus" 11 icon="el-icon-plus"
12 plain 12 plain
13 circle 13 circle
14 - @click="toAdd" 14 + @click="toAdd({})"
15 ></el-button> 15 ></el-button>
16 </el-tooltip> 16 </el-tooltip>
17 </template> 17 </template>
@@ -201,6 +201,27 @@ export default { @@ -201,6 +201,27 @@ export default {
201 teacher: "张老师", 201 teacher: "张老师",
202 date: "2022-11-04 18:09:49", 202 date: "2022-11-04 18:09:49",
203 share: 1, 203 share: 1,
  204 + score: 100,
  205 + gradeName:"二年级",
  206 + subjectId:1,
  207 + examsDuration:4800,
  208 + questionList: [
  209 + {
  210 + questionTitle: "f",
  211 + score: 1,
  212 + subQuestions: [
  213 + {
  214 + questionIndex: 1,
  215 + questionType: 2,
  216 + score: 1,
  217 + partScore: 0,
  218 + selectNum: 4,
  219 + answerOptions: ["A", "B", "C", "D"],
  220 + correctAnswer: "B",
  221 + },
  222 + ],
  223 + },
  224 + ],
204 }, 225 },
205 { 226 {
206 title: "数学样例试卷202211-4180949", 227 title: "数学样例试卷202211-4180949",
@@ -212,6 +233,27 @@ export default { @@ -212,6 +233,27 @@ export default {
212 teacher: "张老师", 233 teacher: "张老师",
213 date: "2022-11-04 18:09:49", 234 date: "2022-11-04 18:09:49",
214 share: 1, 235 share: 1,
  236 + score: 100,
  237 + gradeName:"二年级",
  238 + subjectId:1,
  239 + examsDuration:3000,
  240 + questionList: [
  241 + {
  242 + questionTitle: "f",
  243 + score: 1,
  244 + subQuestions: [
  245 + {
  246 + questionIndex: 2,
  247 + questionType: 3,
  248 + score: 1,
  249 + partScore: 0,
  250 + selectNum: 4,
  251 + answerOptions: ["A", "B", "C", "D"],
  252 + correctAnswer: "A,C",
  253 + },
  254 + ],
  255 + },
  256 + ],
215 }, 257 },
216 ], 258 ],
217 shareForm: { 259 shareForm: {
@@ -226,25 +268,27 @@ export default { @@ -226,25 +268,27 @@ export default {
226 }, 268 },
227 methods: { 269 methods: {
228 toAdd(query) { 270 toAdd(query) {
229 - this.$router.push({ 271 + let routerItem = {
230 path: "/examinationPaperAdd", 272 path: "/examinationPaperAdd",
231 - query:query&&{...query}  
232 - }); 273 + };
  274 + query ? (routerItem["query"] = { ...query }) : "";
  275 + this.$router.push(routerItem);
233 }, 276 },
234 toEdit(item) { 277 toEdit(item) {
235 this.$router.push({ 278 this.$router.push({
236 path: "/examinationPaperEdit", 279 path: "/examinationPaperEdit",
237 query: { 280 query: {
238 - id: item.id, 281 + form: JSON.stringify(item),
239 }, 282 },
240 }); 283 });
241 }, 284 },
242 - handleDropdownClick(value, item) {//更多 285 + handleDropdownClick(value, item) {
  286 + //更多
243 const that = this; 287 const that = this;
244 switch (value) { 288 switch (value) {
245 case 1: 289 case 1:
246 //授课端同步 290 //授课端同步
247 - that.syncMeg(item) 291 + that.syncMeg(item);
248 break; 292 break;
249 case 2: 293 case 2:
250 //修改分享范围 294 //修改分享范围
@@ -255,15 +299,16 @@ export default { @@ -255,15 +299,16 @@ export default {
255 break; 299 break;
256 case 3: 300 case 3:
257 //复制 301 //复制
258 - that.toAdd() 302 + that.toAdd({ type: 2, form: JSON.stringify(item), });
259 break; 303 break;
260 case 4: 304 case 4:
261 //归档 305 //归档
262 - that.recovery(item) 306 + that.recovery(item);
263 break; 307 break;
264 } 308 }
265 }, 309 },
266 - async syncMeg() {//同步 310 + async syncMeg() {
  311 + //同步
267 // const { data, code, message } = await this.$request.fetchAnswerList({ 312 // const { data, code, message } = await this.$request.fetchAnswerList({
268 // ...this.shareForm, 313 // ...this.shareForm,
269 // }); 314 // });
@@ -274,7 +319,8 @@ export default { @@ -274,7 +319,8 @@ export default {
274 // this.$message.error(message); 319 // this.$message.error(message);
275 // } 320 // }
276 }, 321 },
277 - async saveShare() {//修改分享范围 322 + async saveShare() {
  323 + //修改分享范围
278 // const { data, code, message } = await this.$request.fetchAnswerList({ 324 // const { data, code, message } = await this.$request.fetchAnswerList({
279 // ...this.shareForm, 325 // ...this.shareForm,
280 // }); 326 // });
@@ -288,20 +334,22 @@ export default { @@ -288,20 +334,22 @@ export default {
288 // this.$message.error(message); 334 // this.$message.error(message);
289 // } 335 // }
290 }, 336 },
291 - async recovery(item) {//归档 337 + async recovery(item) {
  338 + //归档
292 // const { data, code, message } = await this.$request.fetchAnswerList({ 339 // const { data, code, message } = await this.$request.fetchAnswerList({
293 // ...this.shareForm, 340 // ...this.shareForm,
294 // }); 341 // });
295 // if (code === 0) { 342 // if (code === 0) {
296 - this.tableData = this.tableData.filter(items=>{  
297 - return items.id != item.id  
298 - }) 343 + this.tableData = this.tableData.filter((items) => {
  344 + return items.id != item.id;
  345 + });
299 // } else { 346 // } else {
300 // this.$message.error(message); 347 // this.$message.error(message);
301 // } 348 // }
302 }, 349 },
303 350
304 - async changClazz() {//切换班级 351 + async changClazz() {
  352 + //切换班级
305 await this._QuerySubjectList(); 353 await this._QuerySubjectList();
306 this._QueryData(); 354 this._QueryData();
307 }, 355 },
@@ -348,7 +396,8 @@ export default { @@ -348,7 +396,8 @@ export default {
348 this.$message.error(message); 396 this.$message.error(message);
349 } 397 }
350 }, 398 },
351 - async _QueryData(type) {//获取答题卡列表 399 + async _QueryData(type) {
  400 + //获取答题卡列表
352 let query = {}; 401 let query = {};
353 if (!type) { 402 if (!type) {
354 this.query.title = ""; 403 this.query.title = "";
@@ -387,73 +436,6 @@ export default { @@ -387,73 +436,6 @@ export default {
387 </script> 436 </script>
388 437
389 <style scoped lang="scss"> 438 <style scoped lang="scss">
390 -.answer-header {  
391 - padding: 16px 40px 12px 20px;  
392 - display: flex;  
393 - justify-content: space-between;  
394 - align-items: center;  
395 - .btn-box {  
396 - display: flex;  
397 - }  
398 -}  
399 -.sel-box {  
400 - display: flex;  
401 - align-items: center;  
402 - flex-wrap: nowrap;  
403 - .sel {  
404 - width: 8%;  
405 - min-width: 90px;  
406 - margin-right: 20px;  
407 - }  
408 - :deep(.el-input__inner) {  
409 - border-radius: 20px;  
410 - border: 1px solid #e2e2e2;  
411 - height: 36px;  
412 - line-height: 34px;  
413 - }  
414 - :deep(.el-input__icon) {  
415 - line-height: 34px;  
416 - }  
417 - :deep(.el-date-editor.el-input),  
418 - :deep(.el-date-editor.el-input__inner) {  
419 - width: 200px;  
420 - }  
421 - .input-with-select {  
422 - width: 200px;  
423 - height: 36px;  
424 - margin-right: 50px;  
425 - border-radius: 20px;  
426 - border: 1px solid #e2e2e2;  
427 - box-sizing: border-box;  
428 - :deep(.el-input__inner) {  
429 - border-radius: 20px;  
430 - border: none;  
431 - height: 34px;  
432 - line-height: 34px;  
433 - }  
434 - :deep(.el-input-group__append, .el-input-group__prepend) {  
435 - border: none;  
436 - background: transparent;  
437 - }  
438 - }  
439 - .d1 {  
440 - margin-left: 30px;  
441 - }  
442 - .p1 {  
443 - flex: 1;  
444 - .s1 {  
445 - margin-left: 36px;  
446 - cursor: pointer;  
447 - color: #7f7f7f;  
448 - &:hover {  
449 - color: #409eff;  
450 - }  
451 - &.active {  
452 - color: #667ffd;  
453 - }  
454 - }  
455 - }  
456 -}  
457 .tips { 439 .tips {
458 display: flex; 440 display: flex;
459 padding-left: 30px; 441 padding-left: 30px;
src/views/examinationPaper/recycle.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <back-box> 3 + <back-box>
4 <template slot="title"> 4 <template slot="title">
5 - <span>归档</span> 5 + <span>已归档答题卡</span>
6 </template> 6 </template>
7 </back-box> 7 </back-box>
  8 + <div class="answer-header">
  9 + <div class="sel-box">
  10 + <el-select
  11 + class="sel"
  12 + v-model="query.gradeName"
  13 + placeholder=""
  14 + @change="changeGrade"
  15 + >
  16 + <el-option
  17 + v-for="item in gradeList"
  18 + :key="item"
  19 + :label="item"
  20 + :value="item"
  21 + >
  22 + </el-option>
  23 + </el-select>
  24 + <el-select
  25 + class="sel"
  26 + v-model="query.type"
  27 + placeholder="选择类型"
  28 + @change="_QueryData()"
  29 + >
  30 + <el-option label="全部" value=""></el-option>
  31 + <el-option
  32 + v-for="item in typeList"
  33 + :key="item.value"
  34 + :label="item.label"
  35 + :value="item.value"
  36 + >{{ item.label }}
  37 + </el-option>
  38 + </el-select>
  39 + <el-select
  40 + class="sel"
  41 + v-model="query.subjectId"
  42 + placeholder="选择科目"
  43 + @change="_QueryData()"
  44 + >
  45 + <el-option label="全部" value=""></el-option>
  46 + <el-option
  47 + v-for="item in subjectList"
  48 + :key="item.value"
  49 + :label="item.label"
  50 + :value="item.value"
  51 + >
  52 + </el-option>
  53 + </el-select>
  54 + <el-input
  55 + placeholder="输入试卷名称"
  56 + v-model="query.title"
  57 + class="input-with-select"
  58 + @keyup.enter.native="_QueryData(true)"
  59 + >
  60 + <el-button
  61 + slot="append"
  62 + icon="el-icon-search"
  63 + @click="_QueryData(true)"
  64 + ></el-button>
  65 + </el-input>
  66 + </div>
  67 + </div>
  68 + <ul class="content">
  69 + <li class="item" v-for="item in tableData" :key="item.id">
  70 + <div class="pic-box">
  71 + <p class="i-box"><i class="fa fa-map-o"></i></p>
  72 + <p class="ids">{{ item.id }}</p>
  73 + </div>
  74 + <div class="info">
  75 + <p class="title">
  76 + {{ item.title }} <span class="label">{{ item.typeName }}</span>
  77 + </p>
  78 + <p class="num">
  79 + {{ item.gradeName }}
  80 + <em class="s-line">|</em>
  81 + 总题数:{{ item.answerNum }}
  82 + <em class="s-line">|</em>
  83 + 预计时长:{{ item.time }}
  84 + <em class="s-line">|</em>
  85 + </p>
  86 + <p class="person">
  87 + {{ item.teacher }}<em class="s-line">|</em
  88 + ><span class="date">{{ item.date }}</span>
  89 + </p>
  90 + </div>
  91 + <div class="btn-box">
  92 + <el-tooltip effect="dark" content="使用" placement="bottom">
  93 + <el-button
  94 + class="edit"
  95 + type="info"
  96 + size="mini"
  97 + circle
  98 + icon="fa fa-mail-reply"
  99 + @click="have(item)"
  100 + ></el-button>
  101 + </el-tooltip>
  102 + <el-popconfirm title="确定删除这张答题卡吗?" @confirm="remove(item)">
  103 + <el-button
  104 + slot="reference"
  105 + class="delete"
  106 + type="info"
  107 + size="mini"
  108 + circle
  109 + icon="el-icon-delete"
  110 + ></el-button>
  111 + </el-popconfirm>
  112 + </div>
  113 + </li>
  114 + </ul>
8 </div> 115 </div>
9 </template> 116 </template>
10 117
11 <script> 118 <script>
12 export default { 119 export default {
13 -  
14 -} 120 + data() {
  121 + return {
  122 + query: {
  123 + gradeName: "二年级",
  124 + type: "",
  125 + subjectId: "",
  126 + title: "",
  127 + },
  128 + gradeList: ["二年级"],
  129 + typeList: [
  130 + { label: "随堂问", value: 1 },
  131 + { label: "即使测", value: 2 },
  132 + ],
  133 + subjectList: [],
  134 + tableData: [
  135 + {
  136 + title: "数学样例试卷202211-324654",
  137 + id: "1062837",
  138 + gradeName: "二年级",
  139 + typeName: "周测",
  140 + answerNum: 45,
  141 + time: 90,
  142 + aboutClazz: [203, 204],
  143 + teacher: "张老师",
  144 + date: "2022-11-04 18:09:49",
  145 + share: 1,
  146 + },
  147 + {
  148 + title: "数学样例试卷202211-4180949",
  149 + id: "1062838",
  150 + gradeName: "二年级",
  151 + typeName: "周测",
  152 + answerNum: 45,
  153 + time: 90,
  154 + aboutClazz: [203, 204],
  155 + teacher: "张老师",
  156 + date: "2022-11-04 18:09:49",
  157 + share: 1,
  158 + },
  159 + ],
  160 + total: 0,
  161 + };
  162 + },
  163 + methods: {
  164 + have(obj) {
  165 + //删除答题卡
  166 + // const { data, code, message } = await this.$request.useAnswerSheet();
  167 + // if (code == 0) {
  168 + this.tableData = this.tableData.filter(item=>{
  169 + return obj.if != item.id
  170 + })
  171 + // } else {
  172 + // this.$message.error(message);
  173 + // }
  174 + },
  175 + remove(obj) {
  176 + //删除答题卡
  177 + // const { data, code, message } = await this.$request.removeAnswerSheet();
  178 + // if (code == 0) {
  179 + this.tableData = this.tableData.filter(item=>{
  180 + return obj.if != item.id
  181 + })
  182 + // } else {
  183 + // this.$message.error(message);
  184 + // }
  185 + },
  186 + async _QueryData(type) {
  187 + //获取答题卡列表
  188 + let query = {};
  189 + if (!type) {
  190 + this.query.title = "";
  191 + query = { ...this.query };
  192 + } else {
  193 + query = { title: this.query.title };
  194 + this.query.type = "";
  195 + this.query.subjectId = "";
  196 + }
  197 + for (let key in query) {
  198 + if (!query[key]) {
  199 + query[key] = null;
  200 + }
  201 + }
  202 + this.loading = true;
  203 + const { data, code, message } = await this.$request.fetchAnswerList({
  204 + ...query,
  205 + });
  206 + this.loading = false;
  207 + if (code === 0) {
  208 + this.total = data.total;
  209 + this.tableData = (data.list && [...data.list]) || [];
  210 + } else {
  211 + this.$message.error(message);
  212 + }
  213 + },
  214 + async changeGrade() {
  215 + this._QueryData();
  216 + this._GradeList();
  217 + this._QuerySubjectList();
  218 + },
  219 + async _GradeList() {
  220 + //查询年级列表
  221 + const { data, code, message } = await this.$request.fetchGradeList();
  222 + if (code == 0) {
  223 + this.gradeList = [...data.gradeNames] || [];
  224 + this.query.gradeName = this.gradeList[0];
  225 + this._QuerySubjectList(this.gradeList[0]);
  226 + } else {
  227 + this.$message.error(message);
  228 + }
  229 + },
  230 + async _QuerySubjectList(grade, dont) {
  231 + //查询科目列表
  232 + let param = {};
  233 + if (grade) {
  234 + param.gradeName = grade;
  235 + }
  236 + const { data, code, message } = await this.$request.fetchSubjectList(
  237 + param
  238 + );
  239 + if (code === 0) {
  240 + this.subjectList = data.list.map((item) => {
  241 + return {
  242 + value: item.subjectId,
  243 + label: item.subjectName,
  244 + };
  245 + });
  246 + } else {
  247 + this.$message.error(message);
  248 + }
  249 + },
  250 + },
  251 +};
15 </script> 252 </script>
16 253
17 -<style>  
18 - 254 +<style lang="scss" scoped>
  255 +.answer-header {
  256 + .sel-box {
  257 + .sel {
  258 + min-width: 160px;
  259 + }
  260 + }
  261 +}
  262 +.content {
  263 + margin: 0 20px;
  264 + background: #f8f8f8;
  265 + padding: 12px;
  266 + border-radius: 20px;
  267 + .item {
  268 + display: flex;
  269 + align-items: center;
  270 + width: 100%;
  271 + overflow: hidden;
  272 + box-sizing: border-box;
  273 + padding: 12px;
  274 + border-radius: 20px;
  275 + background: #fff;
  276 + margin-bottom: 12px;
  277 + &:last-of-type {
  278 + margin-bottom: 0;
  279 + }
  280 + .pic-box {
  281 + width: 80px;
  282 + height: 80px;
  283 + border-radius: 10px;
  284 + margin-right: 10px;
  285 + flex-shrink: 0;
  286 + background: #d7d7d7;
  287 + text-align: center;
  288 + color: #fff;
  289 + font-weight: 500;
  290 + .i-box {
  291 + padding-top: 10px;
  292 + font-size: 32px;
  293 + margin-bottom: 3px;
  294 + }
  295 + }
  296 + .info {
  297 + height: 80px;
  298 + flex: 1;
  299 + overflow: hidden;
  300 + display: flex;
  301 + flex-direction: column;
  302 + justify-content: space-between;
  303 + .s-line {
  304 + padding: 0 5px;
  305 + color: #e2e2e2;
  306 + }
  307 + .title {
  308 + font-size: 16px;
  309 + color: #222;
  310 + font-weight: 500;
  311 + .label {
  312 + display: inline-block;
  313 + font-size: 12px;
  314 + color: #2e9afe;
  315 + line-height: 16px;
  316 + padding: 0 10px;
  317 + border: 1px solid #2e9afe;
  318 + border-radius: 10px;
  319 + transform: translateY(-2px);
  320 + }
  321 + }
  322 + .person {
  323 + color: #666;
  324 + }
  325 + }
  326 + .btn-box {
  327 + flex-shrink: 0;
  328 + .edit {
  329 + margin-right: 12px;
  330 + }
  331 + }
  332 + }
  333 +}
19 </style> 334 </style>
20 \ No newline at end of file 335 \ No newline at end of file
src/views/layout/header/header.vue
@@ -126,7 +126,6 @@ export default { @@ -126,7 +126,6 @@ export default {
126 }, 126 },
127 handleCommand(command) { 127 handleCommand(command) {
128 //刷新权限跳转首页 128 //刷新权限跳转首页
129 - this.$message("click on item " + command);  
130 this.$store.dispatch("permissions", this); 129 this.$store.dispatch("permissions", this);
131 }, 130 },
132 logOut() { 131 logOut() {
src/views/layout/layout.vue
@@ -22,6 +22,7 @@ import layoutAside from &quot;./aside/aside&quot;; @@ -22,6 +22,7 @@ import layoutAside from &quot;./aside/aside&quot;;
22 import layoutHeader from "./header/header"; 22 import layoutHeader from "./header/header";
23 import Bottom from "./Footer/bottom"; 23 import Bottom from "./Footer/bottom";
24 import langSelect from "../../components/lang/langSelect"; 24 import langSelect from "../../components/lang/langSelect";
  25 +import { getURLParams } from "@/utils";
25 26
26 export default { 27 export default {
27 name: "layout", 28 name: "layout",
@@ -31,6 +32,39 @@ export default { @@ -31,6 +32,39 @@ export default {
31 langSelect, 32 langSelect,
32 layoutAside, 33 layoutAside,
33 }, 34 },
  35 + data() {
  36 + return {
  37 + code: "",
  38 + };
  39 + },
  40 + created() {
  41 + this.code = getURLParams("code") || "";
  42 + if (this.code) {
  43 + localStorage.setItem("code",this.code)
  44 + this._LoginCheck();
  45 + }
  46 + },
  47 + methods: {
  48 + async _LoginCheck() {
  49 + let params = {};
  50 + if (this.code) {
  51 + params = {
  52 + code: this.code,
  53 + };
  54 + }
  55 + const { data = {}, message, code } = await loginCheck(params);
  56 + if (code === 0) {
  57 + if (data) {
  58 + this.school = data.schoolName;
  59 + this.user.name = data.realName;
  60 + this.user.id = data.id;
  61 + this.user.tx = data.smallHeaderImgPath;
  62 + }
  63 + } else {
  64 + this.$message.error(message);
  65 + }
  66 + },
  67 + },
34 }; 68 };
35 </script> 69 </script>
36 70
@@ -81,7 +115,7 @@ ul.el-menu { @@ -81,7 +115,7 @@ ul.el-menu {
81 115
82 #elmain { 116 #elmain {
83 background-color: #fff; 117 background-color: #fff;
84 - padding:0; 118 + padding: 0;
85 } 119 }
86 120
87 .avatar-uploader .el-upload { 121 .avatar-uploader .el-upload {
src/views/login/index.vue
@@ -101,8 +101,12 @@ export default { @@ -101,8 +101,12 @@ export default {
101 { required: true, message: "请输入账号密码",trigger: "blur" } 101 { required: true, message: "请输入账号密码",trigger: "blur" }
102 ] 102 ]
103 }, 103 },
  104 + url: "",
104 }; 105 };
105 }, 106 },
  107 + created() {
  108 + this.url = this.$route.query?.url || "";
  109 + },
106 methods: { 110 methods: {
107 showPwd() { 111 showPwd() {
108 if (this.passwordType === "password") { 112 if (this.passwordType === "password") {
@@ -115,7 +119,6 @@ export default { @@ -115,7 +119,6 @@ export default {
115 }); 119 });
116 }, 120 },
117 submitForm() { 121 submitForm() {
118 - let that = this;  
119 if (this.loginForm.username === "" || this.loginForm.password === "") { 122 if (this.loginForm.username === "" || this.loginForm.password === "") {
120 this.$message({ 123 this.$message({
121 showClose: true, 124 showClose: true,
@@ -124,7 +127,7 @@ export default { @@ -124,7 +127,7 @@ export default {
124 }); 127 });
125 return false; 128 return false;
126 } else { 129 } else {
127 - this.$store.dispatch("Login",this) 130 + this.$store.dispatch("Login",{...this.loginForm,url:this.url})
128 } 131 }
129 }, 132 },
130 }, 133 },