├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ ├── bg.jpg │ ├── exam.png │ ├── jige.jpg │ └── logo.png ├── components │ ├── HelloWorld.vue │ ├── Pagination.vue │ ├── SlideVerification.vue │ └── TimeCountDown.vue ├── layout │ └── index.vue ├── main.js ├── plugins │ ├── axios.js │ └── element.js ├── router │ └── index.js ├── store │ └── index.js └── views │ ├── Answer.vue │ ├── Center.vue │ ├── Error.vue │ ├── Exam.vue │ ├── Grade.vue │ ├── Login.vue │ ├── Paper.vue │ ├── Password.vue │ ├── Practice.vue │ ├── Record.vue │ ├── Register.vue │ └── Score.vue └── vue.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # exam-online 2 | 3 | 后端代码:https://github.com/520118202/ExamOnline 4 | 5 | ## Project setup 6 | ``` 7 | npm install 8 | ``` 9 | 10 | ### Compiles and hot-reloads for development 11 | ``` 12 | npm run serve 13 | ``` 14 | 15 | ### Compiles and minifies for production 16 | ``` 17 | npm run build 18 | ``` 19 | 20 | ### Customize configuration 21 | See [Configuration Reference](https://cli.vuejs.org/config/). 22 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "exam-online", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "@babel/core": "^7.10.2", 11 | "@babel/preset-env": "^7.10.2", 12 | "core-js": "^3.6.4", 13 | "element-ui": "^2.4.5", 14 | "vue": "^2.6.11", 15 | "vue-router": "^3.1.5", 16 | "vuex": "^3.1.2" 17 | }, 18 | "devDependencies": { 19 | "@vue/cli-plugin-babel": "^4.2.0", 20 | "@vue/cli-plugin-router": "^4.2.0", 21 | "@vue/cli-plugin-vuex": "^4.2.0", 22 | "@vue/cli-service": "^4.2.0", 23 | "axios": "^0.18.0", 24 | "node-sass": "^4.12.0", 25 | "sass-loader": "^8.0.2", 26 | "vue-cli-plugin-axios": "0.0.4", 27 | "vue-cli-plugin-element": "^1.0.1", 28 | "vue-template-compiler": "^2.6.11" 29 | }, 30 | "browserslist": [ 31 | "> 1%", 32 | "last 2 versions" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/520118202/exam-online/e8bcf8ff64f99dd34bc3d96bdef03b8c552a83ed/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 24 | -------------------------------------------------------------------------------- /src/assets/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/520118202/exam-online/e8bcf8ff64f99dd34bc3d96bdef03b8c552a83ed/src/assets/bg.jpg -------------------------------------------------------------------------------- /src/assets/exam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/520118202/exam-online/e8bcf8ff64f99dd34bc3d96bdef03b8c552a83ed/src/assets/exam.png -------------------------------------------------------------------------------- /src/assets/jige.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/520118202/exam-online/e8bcf8ff64f99dd34bc3d96bdef03b8c552a83ed/src/assets/jige.jpg -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/520118202/exam-online/e8bcf8ff64f99dd34bc3d96bdef03b8c552a83ed/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 42 | 43 | 44 | 60 | -------------------------------------------------------------------------------- /src/components/Pagination.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 37 | 38 | 43 | -------------------------------------------------------------------------------- /src/components/SlideVerification.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 75 | 76 | 119 | -------------------------------------------------------------------------------- /src/components/TimeCountDown.vue: -------------------------------------------------------------------------------- 1 | 8 | 78 | -------------------------------------------------------------------------------- /src/layout/index.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 92 | 93 | 133 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import './plugins/axios.js' 6 | import './plugins/element.js' 7 | 8 | Vue.config.productionTip = false 9 | 10 | new Vue({ 11 | router, 12 | store, 13 | render: h => h(App) 14 | }).$mount('#app') 15 | -------------------------------------------------------------------------------- /src/plugins/axios.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import Vue from 'vue'; 4 | import axios from "axios"; 5 | 6 | // Full config: https://github.com/axios/axios#request-config 7 | // axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || ''; 8 | // axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; 9 | // axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 10 | 11 | let config = { 12 | // baseURL: process.env.baseURL || process.env.apiUrl || "" 13 | // timeout: 60 * 1000, // Timeout 14 | // withCredentials: true, // Check cross-site Access-Control 15 | }; 16 | 17 | const _axios = axios.create(config); 18 | 19 | _axios.interceptors.request.use( 20 | function(config) { 21 | // Do something before request is sent 22 | // 添加请求拦截器,在请求头中加token 23 | if (localStorage.getItem('Authorization')) { 24 | config.headers.Authorization = localStorage.getItem('Authorization'); 25 | } 26 | return config; 27 | }, 28 | function(error) { 29 | // Do something with request error 30 | return Promise.reject(error); 31 | } 32 | ); 33 | 34 | // Add a response interceptor 35 | _axios.interceptors.response.use( 36 | function(response) { 37 | // Do something with response data 38 | return response; 39 | }, 40 | function(error) { 41 | // Do something with response error 42 | return Promise.reject(error); 43 | } 44 | ); 45 | 46 | Plugin.install = function(Vue, options) { 47 | Vue.axios = _axios; 48 | window.axios = _axios; 49 | Object.defineProperties(Vue.prototype, { 50 | axios: { 51 | get() { 52 | return _axios; 53 | } 54 | }, 55 | $axios: { 56 | get() { 57 | return _axios; 58 | } 59 | }, 60 | }); 61 | }; 62 | 63 | Vue.use(Plugin) 64 | 65 | export default Plugin; 66 | -------------------------------------------------------------------------------- /src/plugins/element.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Element from 'element-ui' 3 | import 'element-ui/lib/theme-chalk/index.css' 4 | 5 | Vue.use(Element) 6 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | import Layout from '@/layout/index.vue' 4 | 5 | Vue.use(VueRouter) 6 | 7 | const routes = [{ 8 | path: '/', 9 | component: Layout, 10 | redirect: '/exam', 11 | children: [{ 12 | path: 'exam', 13 | component: () => import('../views/Exam.vue'), 14 | name: 'exam', 15 | meta: { 16 | title: '考试中心' 17 | } 18 | }, 19 | { 20 | path: 'practice', 21 | name: 'Practice', 22 | component: () => import('../views/Practice.vue'), 23 | meta: { 24 | title: '模拟练习' 25 | } 26 | }, 27 | { 28 | path: 'grade', 29 | name: 'Grade', 30 | component: () => import('../views/Grade.vue'), 31 | meta: { 32 | title: '查询成绩' 33 | } 34 | }, 35 | { 36 | path: 'center', 37 | name: 'Center', 38 | component: () => import('../views/Center.vue'), 39 | meta: { 40 | title: '个人中心' 41 | } 42 | }, 43 | { 44 | path: 'password', 45 | name: 'Password', 46 | component: () => import('../views/Password.vue'), 47 | meta: { 48 | title: '修改密码' 49 | } 50 | }, 51 | { 52 | path: 'paper', 53 | name: 'Paper', 54 | component: () => import('../views/Paper.vue'), 55 | meta: { 56 | title: '试卷详情' 57 | } 58 | }, 59 | { 60 | path: 'score', 61 | name: 'Score', 62 | component: () => import('../views/Score.vue'), 63 | meta: { 64 | title: '考试得分' 65 | } 66 | } 67 | ] 68 | }, 69 | { 70 | path: '/answer', 71 | name: 'Answer', 72 | component: () => import('../views/Answer.vue'), 73 | meta: { 74 | title: '答题界面' 75 | } 76 | }, 77 | { 78 | path: '/record', 79 | name: 'Record', 80 | component: () => import('../views/Record.vue'), 81 | meta: { 82 | title: '练习记录' 83 | } 84 | }, 85 | { 86 | path: '/login', 87 | name: 'Login', 88 | component: () => import('../views/Login.vue'), 89 | meta: { 90 | title: '登录界面' 91 | } 92 | }, 93 | { 94 | path: '/register', 95 | name: 'Register', 96 | component: () => import('../views/Register.vue'), 97 | meta: { 98 | title: '注册界面' 99 | } 100 | }, 101 | { 102 | path: '*', 103 | name: 'Error', 104 | component: () => import('../views/Error.vue'), 105 | meta: { 106 | title: '404错误界面' 107 | } 108 | } 109 | ] 110 | 111 | const router = new VueRouter({ 112 | mode: 'history', 113 | base: process.env.BASE_URL, 114 | routes 115 | }) 116 | 117 | // 导航守卫 118 | // 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆 119 | router.beforeEach((to, from, next) => { 120 | // 设置标题 121 | if (to.meta.title) { 122 | document.title = to.meta.title 123 | } 124 | 125 | if (to.path === '/login' || to.path === '/register') { 126 | next(); 127 | } else { 128 | let token = sessionStorage.getItem('Authorization'); 129 | if (token === null || token === '') { 130 | next('/login'); 131 | } else { 132 | next(); 133 | } 134 | } 135 | }); 136 | export default router 137 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | export default new Vuex.Store({ 7 | state: { 8 | user: sessionStorage.getItem('user') ? JSON.parse(sessionStorage.getItem('user')) : {}, 9 | student: sessionStorage.getItem('student') ? JSON.parse(sessionStorage.getItem('student')) : {}, 10 | Authorization: sessionStorage.getItem('Authorization') ? sessionStorage.getItem('Authorization') : '', 11 | isPractice: sessionStorage.getItem('isPractice') ? sessionStorage.getItem('isPractice') : false 12 | }, 13 | mutations: { 14 | setUser(state, value) { 15 | state.user = value; 16 | sessionStorage.setItem("user", JSON.stringify(value)); 17 | }, 18 | setStudent(state, value) { 19 | state.student = value; 20 | sessionStorage.setItem("student", JSON.stringify(value)); 21 | }, 22 | setAuthorization(state, value) { 23 | state.Authorization = value; 24 | sessionStorage.setItem("Authorization", value); 25 | }, 26 | setIsPractice(state, value) { 27 | state.isPractice = value; 28 | sessionStorage.setItem("isPractice", value) 29 | } 30 | }, 31 | actions: { 32 | }, 33 | modules: { 34 | } 35 | }) 36 | -------------------------------------------------------------------------------- /src/views/Answer.vue: -------------------------------------------------------------------------------- 1 | 142 | 143 | 484 | 485 | 570 | -------------------------------------------------------------------------------- /src/views/Center.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 150 | 151 | 165 | -------------------------------------------------------------------------------- /src/views/Error.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 10 | 11 | 13 | -------------------------------------------------------------------------------- /src/views/Exam.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 129 | 157 | -------------------------------------------------------------------------------- /src/views/Grade.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 115 | 116 | 119 | -------------------------------------------------------------------------------- /src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 104 | 105 | 144 | -------------------------------------------------------------------------------- /src/views/Paper.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /src/views/Password.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 135 | 136 | 150 | -------------------------------------------------------------------------------- /src/views/Practice.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 140 | 141 | 174 | -------------------------------------------------------------------------------- /src/views/Record.vue: -------------------------------------------------------------------------------- 1 | 92 | 93 | 173 | 174 | 193 | -------------------------------------------------------------------------------- /src/views/Register.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 177 | 178 | 212 | -------------------------------------------------------------------------------- /src/views/Score.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | devServer: { 3 | proxy: { 4 | '/api': { 5 | target: 'http://127.0.0.1:8000', 6 | changeOrigin: true, 7 | pathRewrite: { 8 | '^/api': '/' 9 | } 10 | } 11 | } 12 | } 13 | } --------------------------------------------------------------------------------