Commit c2ef6744 by @xu-tengbo

a

parent 16a8956b
# 页面标题
VUE_APP_TITLE = 艺考报名系统
# 开发环境配置
ENV = 'development'
# 智慧校园/开发环境
VUE_APP_BASE_API = '/dev-api'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true
# 页面标题
VUE_APP_TITLE = 艺考报名系统
# 生产环境配置
ENV = 'production'
# 智慧校园/生产环境
VUE_APP_BASE_API = '/prod-api'
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
2222 # art-exam-web
\ No newline at end of file
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "art-exam-web",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"axios": "^1.3.5",
"core-js": "^3.8.3",
"element-ui": "^2.15.13",
"js-cookie": "^3.0.4",
"nprogress": "^0.2.0",
"print-js": "^1.6.0",
"vue": "^2.6.14",
"vue-axios": "^3.5.2",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"less": "^4.0.0",
"less-loader": "^8.0.0",
"mockjs": "^1.1.0",
"vue-template-compiler": "^2.6.14"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
</body>
</html>
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
created () {
// 在页面加载时读取sessionStorage里的状态信息
if (sessionStorage.getItem('store')) {
this.$store.replaceState(
Object.assign(
{},
this.$store.state,
JSON.parse(sessionStorage.getItem('store'))
)
)
} // 在页面刷新时将vuex里的信息保存到sessionStorage里 // beforeunload事件在页面刷新时先触发
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('store', JSON.stringify(this.$store.state))
})
},
}
</script>
import request from '@/utils/request';
// 登录
export function login(idCard, phoneNumber, password) {
const data = {
idCard,
phoneNumber,
password,
}
return request({
url: '/web/artStudent/login',
headers: {
isToken: false
},
method: 'post',
data: data
})
}
// 注册
export function register(data) {
return request({
url: '/web/artStudent/register',
method: 'post',
data:data
})
}
// 获取信息
export function getInfo() {
return request({
url: '/web/artStudent/getInfo',
method: 'get'
})
}
// 退出登录
export function logout() {
return request({
url: '/web/artStudent/logout',
method: 'get'
})
}
\ No newline at end of file
import request from '@/utils/request';
// 获取考试列表
export function getList(studentId) {
return request({
url: '/web/artStudent/list/' + studentId,
method: 'get'
})
}
// 是否能进入
export function isEnter(testId,studentId) {
return request({
url: '/web/artStudent/enterBtn/' + testId + '/' + studentId,
method: 'get'
})
}
// 判断页面
export function allInfo(testId,studentId) {
return request({
url: '/web/artStudent/enter/all/' + testId + '/' + studentId,
method: 'get'
})
}
export function getAvatar(data) {
return request({
url: '/web/artStudent/avatar',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
})
}
// 报名暂存
export function webSave(data,testId) {
return request({
url: '/web/artStudent/webSave/' + testId,
method: 'put',
data: data
})
}
// 报名提交
export function webSubmit(data,testId) {
return request({
url: '/web/artStudent/webSubmit/' + testId,
method: 'put',
data: data
})
}
// 打印准考证
export function printCard(testId,studentId) {
return request({
url: '/web/artStudent/enterPrint/' + testId + '/' + studentId,
method: 'get'
})
}
// 考试成绩查询
export function scoreView(testId,studentId) {
return request({
url: '/web/artStudent/enterScore/' + testId + '/' + studentId,
method: 'get'
})
}
// 测试项目
export function getProject(testId) {
return request({
url: '/web/artStudent/getProjectList/' + testId,
method: 'get'
})
}
// 初中学校
export function getSchoolList() {
return request({
url: '/web/artStudent/schoolList',
method: 'get'
})
}
\ No newline at end of file
<template>
<div class="box1">
<div class="web-icon">
<el-image @click="returnIndex" :src="logo" alt="加载失败了"></el-image>
</div>
<span class="web-title" @click="returnIndex">艺考报名网</span>
<div class="drawer">
<el-dropdown>
<div class="el-dropdown-link">
<el-image :src="pic"
style="vertical-align: middle; border-radius: 50%; width: 45px; height: 45px"
alt="头像">
</el-image>&emsp;
{{ name }}<i class="el-icon-arrow-down el-icon--right"></i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>
<el-button type="text" @click="handleLogout">退出登录</el-button>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import logo from '@/assets/logo.png'
import defaultPhoto from '@/assets/image/photo.png'
export default {
name: 'HeadInfo',
props: ['name'],
computed: {
pic: {
get() {
if (this.$store.state.user.photo) {
return this.$store.state.user.photoData
} else {
return defaultPhoto
}
}
}
},
data() {
return {
logo,
baseUrl: 'http://localhost:8848',//前缀
}
},
methods: {
returnIndex() {
this.$router.push({
path: "/"
})
},
handleLogout() {
this.$alert('是否确认退出登录?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
}).then(() => {
this.$store.dispatch('LogOut').then(res => {
this.$router.push({
path: '/login'
}).catch(() => {
});
})
})
}
}
}
</script>
<style scoped lang="less">
.box1 {
margin-top: 10px;
height: 120px;
}
.web-icon {
width: 70px;
height: 70px;
display: inline-block;
//&:hover {
// background: white;
//}
}
.web-title {
margin-left: 40px;
color: white;
font-size: 28px;
display: inline-block;
width: 5em;
height: 80px;
vertical-align: bottom;
line-height: 80px;
font-weight: bold;
}
.drawer {
width: 160px;
text-align: center;
height: 80px;
line-height: 80px;
display: inline-block;
float: right;
}
.photo-icon {
float: left;
width: 27px;
height: 27px;
background-image: url(../assets/image/photo.png);
}
</style>
<style scoped>
.el-dropdown-link {
font-size: 18px;
cursor: pointer;
color: #ffffff;
}
.el-icon-arrow-down {
font-size: 12px;
}
</style>
\ No newline at end of file
<template>
<div class="print">
<div style="margin-top: 10px;">
<div style=" display: inline-block; margin-left: 10px; margin-right: 10px; width: 8px; height: 30px; background: #2a7eec"></div>
<b style="line-height: 30px; vertical-align: top">打印准考证</b>
<el-divider></el-divider>
</div>
<!-- 打印 -->
<div class="pic" v-if="!hasAdmissionCard">
<div style="font-weight: 700">暂无准考证信息</div>
</div>
<div v-else>
<el-button type="primary" style="display:block; font-weight: bold; margin: auto"
@click="print">打印准考证
</el-button>
<el-card style="width: 940px; margin: auto">
<!-- <div id="printArea" style="background: gold; margin: auto; width: 900px; height: 100%">-->
<br/>
<div id="printArea" class="main">
<br/>
<div class="title">东营市第二中学{{
todayYear
}}特色招生专业测试
</div>
<div class="titleSub">
准考证
</div>
<br/><br/><br/>
<div>
<div class="left">
<ul style="margin-left: 40px">
<li>
<b>姓名:</b>{{ examForm.studentName }}<br/><br/>
</li>
<li>
<b>准考证号:</b>{{ examForm.examNumber }}<br/><br/>
</li>
<li>
<b>测试项目:</b>{{ examForm.project }}<br/><br/>
</li>
<li>
<b>组别(座号):</b>{{ examForm.inGroup }}<br/><br/>
</li>
<li>
<b>联系电话:</b>{{ examForm.phoneNumber }}<br/><br/>
</li>
<li>
<b>毕业学校:</b>{{ examForm.schoolName }}<br/><br/>
</li>
</ul>
</div>
<div class="right">
<el-image :src="examForm.photoData"
style="width: 180px; height: 220px;"></el-image>
</div>
</div>
<table border="1">
<tr>
<th style="width: 35%;height: 30px;text-align: center;">考试时间({{
todayYear
}}年)
</th>
<th style="width: 30%;height: 30px;text-align: center;">考试时间</th>
<th style="width: 35%;height: 30px;text-align: center;">考试地点</th>
</tr>
<tr>
<th style="height: 30px;text-align: center;">{{ examForm.examDate }}</th>
<th style="height: 30px;text-align: center;">{{ examForm.examTime }}</th>
<th style="height: 30px;text-align: center;">{{ examForm.examAddress }}</th>
</tr>
</table>
<br/>
<div style="width: 800px;height:600px; margin: auto">
<b style="font-size: 16px; line-height: 30px">注意事项:</b>
<p v-html="examForm.notice" style="line-height: 22px; font-size: 14px"></p>
</div>
</div><!-- main的结束div-->
<!-- </div>-->
</el-card>
<br/> <br/> <br/> <br/>
</div>
</div>
</template>
<script>
import printJS from 'print-js'
import {allInfo, printCard} from '@/api/student'
export default {
name: 'Print',
props: ['PropTestId', 'PropStudentId'],
created() {
this.studentId = this.$store.state.user.studentId
//获取表单数据
this.getAllInfo()
},
computed: {
todayYear() {
const time = new Date()
return time.getFullYear()
}
},
data() {
return {
studentId: undefined,
baseUrl: 'http://localhost:8848',//前缀
examForm: {},
hasAdmissionCard: undefined,
}
},
methods: {
getAllInfo() {
allInfo(this.PropTestId, this.studentId).then(res => {
if (res.node == 4) {
this.$emit("changeTab", 3, "成绩查询")
} else if (res.node == 3) {
/** 允许打印准考证 */
this.examForm = res.data
this.hasAdmissionCard = true
} else {
this.hasAdmissionCard = false
}
})
},
print() {
// 重置表单
printJS({
printable: 'printArea',
targetStyles: ['*'],
type: "html",
})
},
}
}
</script>
<style scoped lang="less">
.print {
width: 100%;
//background:firebrick ;
height: 780px;
overflow-y: auto;
}
.title {
font-size: 32px;
font-weight: bolder;
text-align: center;
letter-spacing: 5px
}
.titleSub {
text-align: center;
font-weight: bold;
font-size: 30px;
margin-top: 15px;
letter-spacing: 10px
}
.pic {
width: 210px;
height: 199px;
margin: 110px auto;
background-image: url(../assets/image/nocard.png);
}
.main {
width: 95%;
// width: 840px;
//background: greenyellow;
height: 1200px;
margin: auto;
border: 1px solid rgb(101, 98, 98);
}
.notice {
width: 700px;
margin: auto;
}
.left {
width: 65%;
height: 260px;
display: inline-block;
vertical-align: top;
//background: red;
ul li {
list-style: none;
}
}
.right {
display: inline-block;
width: 25%;
//background: yellow;
}
table {
//background: #8c939d;
border-color: rgb(101, 98, 98);
border-collapse: collapse;
width: 100%;
height: 120px;
//margin: auto;
//border: 1px solid black;
}
.el-divider--horizontal {
margin: 15px 0;
}
</style>
\ No newline at end of file
<template>
<div>
<el-card style="width: 80%; margin: auto; height: 600px">
<div style="margin-top: 10px;">
<div style=" display: inline-block; margin-left: 10px; margin-right: 10px; width: 8px; height: 30px; background: #2a7eec"></div>
<b style="line-height: 30px; vertical-align: top">成绩查询</b>
<el-divider></el-divider>
</div>
<div v-if="!haveScore">
<el-image :src="noScore" style="width: 200px; height: 180px" alt="图片加载失败"/>
</div>
<div v-else style="width: 850px; margin: auto">
<br/> <br/>
<h1 style="text-align: center;color: #416af1; letter-spacing: 5px">
{{ todayYear }}{{ form.examName }}考试成绩查询结果
</h1>
<br/><br/>
<el-form :model="form" label-width="130px" style="margin: auto;">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="姓名:">
<el-input v-model="form.studentName"></el-input>
</el-form-item>
<el-form-item label="学籍号:">
<el-input v-model="form.studentNumber"></el-input>
</el-form-item>
<el-form-item label="准考证号:">
<el-input v-model="form.examNumber"></el-input>
</el-form-item>
<el-form-item label="证件号:">
<el-input v-model="form.idCard"></el-input>
</el-form-item>
<el-form-item label="考试类别:">
<el-input v-model="form.examSort"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="考试项目:">
<el-input v-model="form.examProject"></el-input>
</el-form-item>
<el-form-item label="成绩:">
<el-input v-model="form.score"></el-input>
</el-form-item>
<el-form-item label="专业测试结果:">
<el-input v-model="form.examNumber"></el-input>
</el-form-item>
<el-form-item label="专业录取资格线:">
<el-input v-model="form.passScore"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- <el-button type="primary" @click="handleReturn">返 回</el-button>-->
</div>
</el-card>
</div>
</template>
<script>
import {allInfo, scoreView} from '@/api/student';
import noScore from '@/assets/image/noScore.png';
export default {
name: 'Score',
props: ['PropTestId'],
computed: {
todayYear() {
const time = new Date()
return time.getFullYear()
}
},
created() {
this.studentId = this.$store.state.user.studentId
this.getAllInfo()
},
data() {
return {
studentId: undefined,
noScore: undefined,
haveScore: undefined,
form: [],
isView: true,// 是否可查看
}
},
methods: {
getAllInfo() {
allInfo(this.PropTestId, this.studentId).then(res => {
if (res.node == 4) {
/** 允许查看成绩 */
this.form = res.data
this.haveScore = true
} else {
this.haveScore = false
}
})
},
getScore() {
scoreView().then(res => {
})
},
handleReturn() {
this.$router.push({
path: '/entry'
})
}
}
}
</script>
<style scoped lang="less">
* {
margin: 0;
padding: 0;
}
.el-divider--horizontal {
margin: 15px 0;
}
.el-form-item {
margin: 10px;
}
</style>
\ No newline at end of file
<template>
<div class="s-canvas">
<canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
</div>
</template>
<script>
export default {
name: 'Validate',
props: {
identifyCode: {
type: String,
default: '1234'
},
fontSizeMin: {
type: Number,
default: 16
},
fontSizeMax: {
type: Number,
default: 40
},
backgroundColorMin: {
type: Number,
default: 180
},
backgroundColorMax: {
type: Number,
default: 240
},
colorMin: {
type: Number,
default: 50
},
colorMax: {
type: Number,
default: 160
},
lineColorMin: {
type: Number,
default: 40
},
lineColorMax: {
type: Number,
default: 180
},
dotColorMin: {
type: Number,
default: 0
},
dotColorMax: {
type: Number,
default: 255
},
contentWidth: {
type: Number,
default: 111
},
contentHeight: {
type: Number,
default: 38
}
},
methods: {
// 生成一个随机数
randomNum(min, max) {
return Math.floor(Math.random() * (max - min) + min)
},
// 生成一个随机的颜色
randomColor(min, max) {
let r = this.randomNum(min, max)
let g = this.randomNum(min, max)
let b = this.randomNum(min, max)
return 'rgb(' + r + ',' + g + ',' + b + ')'
},
drawPic() {
let canvas = document.getElementById('s-canvas')
let ctx = canvas.getContext('2d')
ctx.textBaseline = 'bottom'
// 绘制背景
ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax)
ctx.fillRect(0, 0, this.contentWidth, this.contentHeight)
// 绘制文字
for (let i = 0; i < this.identifyCode.length; i++) {
this.drawText(ctx, this.identifyCode[i], i)
}
this.drawLine(ctx)
this.drawDot(ctx)
},
drawText(ctx, txt, i) {
ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax)
ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei'
let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))
let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)
var deg = this.randomNum(-45, 45)
// 修改坐标原点和旋转角度
ctx.translate(x, y)
ctx.rotate(deg * Math.PI / 180)
ctx.fillText(txt, 0, 0)
// 恢复坐标原点和旋转角度
ctx.rotate(-deg * Math.PI / 180)
ctx.translate(-x, -y)
},
drawLine(ctx) {
// 绘制干扰线
for (let i = 0; i < 8; i++) {
ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax)
ctx.beginPath()
ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
ctx.stroke()
}
},
drawDot(ctx) {
// 绘制干扰点
for (let i = 0; i < 100; i++) {
ctx.fillStyle = this.randomColor(0, 255)
ctx.beginPath()
ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI)
ctx.fill()
}
}
},
watch: {
identifyCode() {
this.drawPic()
}
},
mounted() {
this.drawPic()
}
}
</script>
<style lang="less" scoped>
.s-canvas {
height: 38px;
canvas{
margin-top: 5px;
}
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import './permission'
Vue.use(ElementUI);
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
import router from './router'
import store from './store'
import {Message} from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
// auth文件主要依赖js-cookie模块,getToken,setToken,removeToken
import {getToken} from '@/utils/auth'
// 显示又上方螺旋加载提示
NProgress.configure({showSpinner: false})
// 路由白名单列表,把路由添加到这个数组中,不用登陆也可以访问
const whiteList = ['/login', '/register']
router.beforeEach((to, from, next) => {
// 请求路由时进度条开始
NProgress.start()
if (getToken()) {
// 如果用户存在令牌的情况下还请求登录页面,就让用户跳转到首页,避免重复登录的情况
if (to.path === '/login') {
next({path: '/entry'})
NProgress.done()
} else {
if (store.state.user.studentName === '') {
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => {
next()
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
next({path: '/login'})
}).catch(err => {
next({path: '/login'})
})
})
} else {
next()
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
} else {
next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done()
})
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../views/Login.vue'
import Register from '../views/Register.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect: '/entry'
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/register',
name: 'Register',
component: Register
},
{
path: '/entry',
name: 'Entry',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/Entry.vue')
},
{
path: '/instruction',
name: 'Instruction',
component: () => import(/* webpackChunkName: "about" */ '../views/Instruction.vue')
},
{
path: '/applyProcess',
name: 'ApplyProcess',
component: () => import(/* webpackChunkName: "about" */ '../views/ApplyProcess.vue')
},
// {
// path: '/print',
// name: 'Print',
// component: () => import(/* webpackChunkName: "about" */ '../views/Print.vue')
// },
]
const router = new VueRouter({
routes
})
export default router
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
getters: {
},
modules: {
user
}
})
import {login, logout, getInfo} from '@/api/login'
import {getToken, setToken, removeToken} from '@/utils/auth'
const user = {
state: {
token: getToken(),
studentName: '',
studentId: '',
idCard: '',
phoneNumber: '',
photo: '',
photoData: '',
temPhotoData: '',
active: 0,
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, studentName) => {
state.studentName = studentName
},
SET_ID: (state, studentId) => {
state.studentId = studentId
},
SET_IDCARD: (state, idCard) => {
state.idCard = idCard
},
SET_PHONENUMBER: (state, phoneNumber) => {
state.phoneNumber = phoneNumber
},
SET_PHOTO: (state, photo) => {
state.photo = photo
},
SET_PHOTODATA: (state, photoData) => {
state.photoData = photoData
},
SET_TEMPHOTODATA: (state, temPhotoData) => {
state.temPhotoData = temPhotoData
},
SET_ACTIVE: (state, active) => {
state.active = Number(active)
console.log('SET_ACTIVE', state.active)
},
},
actions: {
// 登录
Login({commit}, userInfo) {
const idCard = userInfo.idCard
const phoneNumber = userInfo.phoneNumber
const password = userInfo.password
return new Promise((resolve, reject) => {
login(idCard, phoneNumber, password).then(res => {
setToken(res.token)
commit('SET_TOKEN', res.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
// 获取用户信息
GetInfo({commit}, state) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
// console.log(getInfo)
const user = res.info
commit('SET_NAME', user.studentName)
commit('SET_IDCARD', user.idCard)
commit('SET_PHONENUMBER', user.phoneNumber)
commit('SET_PHOTO', user.photo)
commit('SET_PHOTODATA', user.photoData)
commit('SET_ID', user.id)
resolve(res)
}).catch(error => {
reject(error)
})
})
},
// 退出系统
LogOut({commit}, state) {
return new Promise((resolve, reject) => {
logout().then(() => {
commit('SET_TOKEN', '')
commit('SET_NAME', '')
commit('studentId', '')
commit('idCard', '')
commit('phoneNumber', '')
commit('photo', '')
commit('photoData', '')
removeToken()
resolve()
}).catch(error => {
removeToken()
reject(error)
})
})
},
// 前端 登出
FedLogOut({commit}) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
removeToken()
resolve()
})
}
}
}
export default user
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
\ No newline at end of file
/**** request.js ****/
// 导入axios
import axios from 'axios'
// 使用element-ui Message做消息提醒
import {Notification, Message, MessageBox} from 'element-ui'
import {getToken} from '@/utils/auth'
import store from "@/store";
// 是否显示重新登录
export let isRelogin = {show: false};
//1. 创建新的axios实例,
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
const service = axios.create({
// 公共接口
// baseURL: "http://localhost:8080",
baseURL: process.env.VUE_APP_BASE_API,
// 超时时间 单位是ms,这里设置了3s的超时时间
timeout: 120 * 1000
})
// 2.请求拦截器
service.interceptors.request.use(config => {
const isToken = (config.headers || {}).isToken === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config
}, error => {
Promise.reject(error)
})
// 3.响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || res.data.status || 200;
// 获取错误信息
const msg = res.data.msg
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
isRelogin.show = false;
store.dispatch('LogOut').then(() => {
location.href = '/login';
})
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
Message({
dangerouslyUseHTMLString: true,//重点代码
message: msg,
type: 'error'
})
return Promise.reject(new Error(msg))
} else if (code !== 200) {
Notification.error({
title: msg
})
return Promise.reject('error')
} else {
return res.data
}
}, error => {
let {message} = error;
if (message == "Network Error") {
message = "后端接口连接异常";
} else if (message.includes("timeout")) {
message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
Message({
message: message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
})
export default service
/**
* @description 封装公共校验规则
* */
// 校验身份证
export function checkIdcard(rule, idCard, callback) {
if (idCard && idCard.length == 18) {
var idCard_string = JSON.stringify(idCard);
var spstr = idCard_string.split("");
var x = spstr[spstr.length - 2];
if (x === "x") {
return callback(new Error("身份证号最后一位X为大写"));
}
var reg = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/);
var arrSplit = idCard.match(reg); //检查生日日期是否正确,value就是身份证号
if (!arrSplit) {
return callback(new Error("身份证号格式有问题,请重新输入"));
}
var dtmBirth = new Date(arrSplit[2] + "/" + arrSplit[3] + "/" + arrSplit[4]);
var bGoodDay;
bGoodDay = dtmBirth.getFullYear() == Number(arrSplit[2]) && dtmBirth.getMonth() + 1 == Number(arrSplit[3]) &&
dtmBirth.getDate() == Number(arrSplit[4]);
if (!bGoodDay) {
return callback(new Error("输入的身份证号里出生日期不对!"));
} else {
//检验18位身份证的校验码是否正确。 //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
var valnum;
var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
var nTemp = 0,
i;
for (i = 0; i < 17; i++) {
nTemp += idCard.substr(i, 1) * arrInt[i];
}
valnum = arrCh[nTemp % 11];
if (valnum != idCard.substr(17, 1)) {
return callback(new Error("末位校验码应该为:" + valnum));
}
return callback();
}
} else {
return callback(new Error("输入的身份证号不满足18位!"));
}
}
// 电话号码校验
export function validatePhone(rule, value, callback) {
let phone = value.replace(/\s/g, "")
let regs = /^1(3|4|5|7|8|9)\d{9}$/;
if (value.length != 0) {
if (!regs.test(phone)) {
callback([new Error("手机号输入不合法")])
} else {
callback()
}
}
}
<template>
<div class="box">
<div class="container">
<div class="head">
<head-info :name="studentName"></head-info>
</div>
<div class="main">
<div class="step">
<div class="stepChild">
<el-steps :active="active" finish-status="success" align-center>
<el-step title="报名"></el-step>
<el-step title="审核"></el-step>
<el-step title="打印准考证"></el-step>
<el-step title="成绩查询"></el-step>
</el-steps>
</div>
</div>
<component :is="tabs[active]" :PropTestId="testId" @changeTab="changeStep"></component>
</div>
<div style="width: 100%; height: 60px; text-align: center; color: white; font-size: 16px; font-weight: bold; padding-top: 30px; letter-spacing: 2px">
山东省东营市第二中学
</div>
</div>
</div>
</template>
<script>
import Score from '@/components/Score.vue'
import Print from '@/components/Print.vue'
import SignUp from '@/components/SignUp.vue'
import Check from '@/components/Check.vue'
import HeadInfo from '@/components/HeadInfo.vue'
export default {
name: 'ApplyProcess',
components: {
Score,
Print,
SignUp,
Check,
HeadInfo
},
computed: {
active() {
console.log('active', this.$store.state.user.active)
return this.$store.state.user.active
}
},
data() {
return {
tabs: ["signUp", 'check', 'print', 'score'],
titles: ['报名', '审核', '打印准考证', '成绩查询'],
studentName: '',
testId: '',
studentId: '',
};
},
created() {
this.studentName = this.$store.state.user.studentName
/** 点击暂存,进入Entry页面,点击进入按钮,路由传带的参数*/
this.testId = this.$route?.query?.testId
this.studentId = this.$route?.query?.studentId
},
methods: {
changeStep(index, title) {
this.$store.commit('SET_ACTIVE', index)
},
}
}
</script>
<style scoped lang="less">
.box {
display: flex;
justify-content: center;
background-image: url("../assets/image/background.png");
}
.container {
width: 80%;
height: 100%;
}
.head {
width: 100%;
height: 90px;
}
.main {
border-radius: 10px;
background: #fdfdfe;
width: 100%;
height: 890px;
}
.step {
width: 100%;
height: 65px;
padding-top: 20px;
padding-bottom: 10px;
background: #f5f8fb;
border-radius: 10px;
}
.stepChild {
width: 80%;
margin: auto;
}
</style>
\ No newline at end of file
<template>
<div class="box">
<div class="container">
<div class="head">
<head-info :name="studentName"></head-info>
</div>
<div class="entry-card-container">
<div class="entry-top">
<span>&emsp;&nbsp;考试报名</span>
</div>
<el-table
:data="testList"
:header-cell-style="{'text-align':'center', 'color':'#416af2'}"
:cell-style="{'text-align':'center', 'color': '#000000'}"
class="table"
border
v-loading="loading"
height="750"
style="width:100%; ">
<el-table-column prop="date" label="序号" type="index" width="100"/>
<el-table-column prop="examName" label="考试名称" min-width="180"/>
<el-table-column prop="deadline" label="报名截止日期" min-width="180"/>
<el-table-column prop="currentState" label="当前状态" min-width="180">
<template slot-scope="scope">
{{ getState(scope.row.currentState) }}
</template>
</el-table-column>
<el-table-column label="操作" min-width="120">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-d-arrow-right"
@click="handleSignUp(scope.row)"
>进入
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div style="width: 100%; height: 60px; text-align: center; color: white; font-size: 16px; font-weight: bold; padding-top: 30px; letter-spacing: 2px">
山东省东营市第二中学
</div>
</div>
</div>
</template>
<script>
import HeadInfo from '@/components/HeadInfo.vue';
import {getList, isEnter, allInfo} from '@/api/student'
export default {
name: 'Entry',
components: {
HeadInfo
},
data() {
return {
loading: true,// 遮罩层
testList: [], // 考试列表
studentName: '',// 学生姓名
studentId: '',// 学生ID
}
},
created() {
this.studentName = this.$store.state.user.studentName
this.studentId = this.$store.state.user.studentId
this.getTestList()
},
methods: {
getTestList() {
getList(this.studentId).then(res => {
this.testList = res.rows
this.loading = false
})
},
handleSignUp(row) {
//查询能否进入
isEnter(row.id, this.studentId).then(res => {
if (res.data == 1) {
/** 如果为1则有权限进入,为0则无权进入 */
//查询进入页面显示的阶段
allInfo(row.id, this.studentId).then(res => {
let node = res?.node
if (node === "0") {
//考试须知阶段
this.$router.push({
path: '/Instruction',
query: {
testId: row.id,
}
})
} else {
this.$store.commit("SET_ACTIVE", res?.node - 1)
//其他阶段,大页面
this.$router.push({
path: '/ApplyProcess',
query: {
testId: row.id,
studentId: this.studentId
}
})
}
})
} else {
/** 为0则无权进入 */
this.$message({
message: '暂时无法进入',
type: 'warning'
});
}
}).catch(err => {
})
},
},
computed: {
getState() {
return function (cur) {
let state = ''
switch (cur) {
case '0':
state = '待报名'
break
case '1':
state = '待审核'
break
case '2':
state = '通过'
break
case '3':
state = '驳回'
break
case '4':
state = '信息修改'
break
case '5':
state = '准考证打印'
break
case '6':
state = '成绩查询'
break
case '7':
state = '审核中'
}
return state
}
}
}
}
</script>
<style>
.box {
display: flex;
justify-content: center;
background-image: url("../assets/image/background.png");
}
.container {
width: 70%;
height: 100%;
/*background: red;*/
}
.head {
width: 100%;
height: 100px;
}
.entry-card-container {
width: 100%;
height: 845px;
/*margin: 25px auto 105px;*/
/* border: 2px solid black; */
border-radius: 12px;
background-color: #fff;
}
.entry-top {
background-color: rgb(245, 248, 251);
height: 80px;
border-radius: 12px 12px 0 0;
line-height: 80px;
font-size: 18px;
font-weight: 700;
}
</style>
\ No newline at end of file
<template>
<div class="instruction">
<div class="instruction-card-container">
<div class="title">
东营市第二中学艺考报名
</div>
<h3 class="instruction-title">报考须知</h3>
<br/>
<div class="content-card">
<div class="content">
<p v-html="notice"></p>
<p v-html="examArrange"></p>
</div>
</div>
<br/>
<div class="buttonGroup">
<el-button :disabled="disable" style="width: 150px" type="primary" @click="onContinue">已阅读并知晓<span
v-show="timerCount>0">({{ timerCount }})</span></el-button>
&emsp;
<el-button style="width: 150px" @click="onReturn">返 回</el-button>
</div>
</div>
</div>
</template>
<script>
import {allInfo} from "@/api/student";
export default {
name: 'Instruction',
data() {
return {
propStudentId: undefined,
disable: true,
testId: '',// 考试ID
timerCount: 10,
studentId: '',// 学生ID
examArrange: '',// 考试安排
notice: '',// 考试注意事项
}
},
created() {
this.testId = this.$route.query.testId
this.studentId = this.$store.state.user.studentId
this.getInfo()
},
methods: {
getInfo() {
allInfo(this.testId, this.studentId).then(res => {
this.notice = res.data.notice,
this.examArrange = res.data.examArrange
})
},
onContinue() {
this.$store.commit('SET_ACTIVE', 0)
this.$router.push({
path: '/ApplyProcess',
query: {
title: '报名',
index: 0,
testId: this.testId,
studentId: this.studentId,
}
})
},
onReturn() {
this.$router.back()
}
},
watch: {
timerCount: {
handler(value) {
if (value > 0) {
setTimeout(() => {
this.timerCount--;
}, 1000);
} else {
this.disable = false
}
},
immediate: true
}
}
}
</script>
<style scoped>
.instruction {
background-image: url("../assets/image/background.png");
height: 100vh;
display: flex;
justify-content: center;
}
.instruction-card-container {
width: 680px;
height: 625px;
background-color: #ffffff;
border-radius: 20px;
align-self: center;
position: relative;
}
.title {
width: 310px;
height: 56px;
line-height: 56px;
position: absolute;
left: 185px;
top: -28px;
text-align: center;
justify-content: center;
color: #ffffff;
font-size: 18px;
font-weight: 900;
background-size: cover;
background-image: url("../assets/image/title.png");
}
.instruction-title {
text-align: center;
margin-top: 40px;
font-size: 20px;
}
.content-card {
width: 640px;
height: 457px;
background: #f4f4f4;
margin: 0 auto;
}
.buttonGroup {
width: 300px;
height: 40px;
margin: auto;
/*background: red;*/
display: flex;
justify-content: center
}
.content {
height: 420px;
padding: 20px;
overflow-y: auto;
/*font-weight: bold;*/
line-height: 25px;
}
</style>
\ No newline at end of file
<template>
<div class="login">
<div class="login-card-container">
<div class="title">
艺考报名网页
</div>
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
@submit.prevent
>
<h3 class="login-title">考生登录</h3>
<el-form-item prop="idCard">
<el-input
v-model="loginForm.idCard"
type="text"
auto-complete="off"
placeholder="请输入身份证号">
</el-input>
</el-form-item>
<el-form-item prop="phoneNumber">
<el-input
v-model="loginForm.phoneNumber"
type="text"
auto-complete="off"
placeholder="请输入手机号">
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="text"
style="text-security:disc; -webkit-text-security:disc;"
auto-complete="off"
placeholder="请输入密码"
@keyup.enter.native="handleLogin">
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<div class="login-code-main">
<div class="login-code-sub">
<el-input
v-model="loginForm.code"
auto-complete="off"
placeholder="请输入验证码"
@keyup.enter.native="handleLogin"
style="width:100%;"
>
</el-input>
</div>
<div style="border: none; margin-left: 50px" @click="refreshCode">
<Validate :identifyCode="identifyCode"></Validate>
</div>
</div>
</el-form-item>
<!-- <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 20px;">记住密码</el-checkbox> -->
<el-form-item style="width:100%;" label-width="0">
<el-button :loading="loading" size="medium" type="primary" class="login-button"
@click="handleLogin">
<span v-if="!loading">登 录</span>
<span v-else>登 录 中...</span>
</el-button>
<div>
<div v-if="register">
<router-link class="link-type" :to="'/register'">新用户注册</router-link>
</div>
</div>
</el-form-item>
</el-form>
</div>
<!-- 底部 -->
<div class="el-login-footer">
<span></span>
</div>
</div>
</template>
<script>
import {checkIdcard, validatePhone} from "@/utils/validate/index"
import Validate from '@/components/validate.vue'
export default {
name: "Login",
components: {
Validate
},
mounted() {
const that = this
that.identifyCode = "";
that.makeCode(this.identifyCodes, 4);
},
created() {
this.refreshCode();
},
data() {
const validateCode = (rule, value, callback) => {
if (this.identifyCode !== value) {
this.loginForm.code = ''
this.refreshCode()
callback(new Error('请输入正确的验证码'))
} else {
callback()
}
}
return {
identifyCode: '',//图形验证码
identifyCodes: '1234567890',
codeUrl: "",
loginForm: {
idCard: '',
phoneNumber: '',
password: "",
// rememberMe: false,
code: "",
},
loginRules: {
idCard: [
{required: true, trigger: "blur", message: "请输入您的身份证号"},
{required: true, validator: checkIdcard, trigger: "blur"}
],
phoneNumber: [
{required: true, trigger: "blur", message: "请输入您的手机号"},
{required: true, validator: validatePhone, trigger: "blur"}
],
password: [
{required: true, trigger: "blur", message: "请输入您的密码"},
{min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur'}
],
code: [{required: true, trigger: "change", message: "请输入验证码"},
{required: true, validator: validateCode, trigger: "blur"}
]
},
loading: false,
// 验证码开关
captchaEnabled: true,
// 注册开关
register: true,
};
},
methods: {
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (!valid) return;
const {idCard, phoneNumber, password} = this.loginForm
this.$store.dispatch('Login', {idCard, phoneNumber, password}).then(res => {
this.$router.push({
path: '/entry'
})
})
})
},
/** *********前端实现验证码功能开始************/
refreshCode() {
this.identifyCode = ''
this.makeCode(this.identifyCodes, 4)
},
makeCode(o, l) {
for (let i = 0; i < l; i++) {
this.identifyCode += this.identifyCodes[
this.randomNum(0, this.identifyCodes.length)
]
}
},
randomNum(min, max) {
return Math.floor(Math.random() * (max - min) + min)
},
/** *********前端实现验证码功能结束************/
}
}
</script>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<style lang="less" scoped>
.login-code-main {
display: flex;
flex-direction: row;
}
.login-container {
//transition: transform .5s ease-in;
.login-page {
//height: 100vh;
}
}
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-image: url("../assets/image/background.png");
// background-size: cover;
.login-card-container {
display: flex;
position: relative;
width: 520px;
height: 470px;
background-color: #ffffff;
border-radius: 6px;
//padding: 20px;
//justify-content: center;
//align-items: center;
}
}
.title {
width: 310px;
height: 56px;
line-height: 56px;
position: absolute;
left: 105px;
top: -28px;
text-align: center;
justify-content: center;
color: #ffffff;
font-size: 18px;
font-weight: 900;
background-size: cover;
background-image: url("../assets/image/title.png");
}
.login-title {
margin: 45px auto 20px;
text-align: center;
color: #000000;
font-weight: 900;
}
.login-form {
border-radius: 6px;
// border: 1px solid;
width: 413px;
// height: 411px;
margin: 0 auto;
// padding: 26px 85px 26px 50px;
/deep/ .el-input .el-input__inner {
height: 45px;
}
}
.login-button {
width: 413px;
height: 60px;
background: #416af2;
border-radius: 6px;
}
// 封面背景
// .login-cover {
// // background-image: url("");
// background-size: cover;
// }
// .login-top {
// background-color: rgb(240, 248, 255);
// position: fixed;
// top: 10px;
// padding-top: 15px;
// width: 95%;
// height: 45px;
// font-size: 18px;
// }
// 封面内容
// .cover-container {
// width: 1200px;
// margin: auto;
// height: 100%;
// display: flex;
// flex-direction: column;
// .cover-center {
// position: relative;
// .cover-center__left {
// position: absolute;
// left: 0;
// top: 0;
// display: flex;
// flex-direction: column;
// }
// .cover-center__right {
// position: absolute;
// width: 559px;
// height: 559px;
// right: 0;
// }
// }
// }
// 登录页
.el-login-footer {
height: 40px;
line-height: 40px;
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
//color: #fff;
color: #989797;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
</style>
<template>
<div class="register">
<div class="register-card-container">
<div class="title">
艺考报名网页
</div>
<el-form
ref="registerForm"
:model="registerForm"
:rules="registerRules"
class="register-form"
>
<h3 class="register-title">个人注册</h3>
<el-form-item prop="studentName">
<el-input v-model="registerForm.studentName" type="text" auto-complete="off"
placeholder="请输入姓名">
</el-input>
</el-form-item>
<el-form-item prop="idCard">
<el-input v-model="registerForm.idCard" type="text" auto-complete="off"
placeholder="请输入身份证号">
</el-input>
</el-form-item>
<el-form-item prop="phoneNumber">
<el-input v-model="registerForm.phoneNumber" type="text" auto-complete="off"
placeholder="请输入手机号">
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="registerForm.password"
type="text"
style="text-security:disc; -webkit-text-security:disc;"
auto-complete="off"
placeholder="请输入密码"
@keyup.enter.native="handleRegister"
>
</el-input>
</el-form-item>
<el-form-item prop="confirmPassword">
<el-input
v-model="registerForm.confirmPassword"
type="text"
style="text-security:disc; -webkit-text-security:disc;"
auto-complete="off"
placeholder="请再次输入密码确认"
@keyup.enter.native="handleRegister"
>
</el-input>
</el-form-item>
<!-- <el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="registerForm.code"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter.native="handleRegister"
>
</el-input>
<div class="register-code">
<img :src="codeUrl" @click="getCode" class="register-code-img"/>
</div>
</el-form-item> -->
<el-form-item style="width:100%;">
<el-button
:loading="loading"
size="medium"
type="primary"
class="register-button"
@click.native.prevent="handleRegister"
>
<span v-if="!loading">注 册</span>
<span v-else>注 册 中...</span>
</el-button>
<div style="float: right;">
<router-link class="link-type" :to="'/login'">使用已有账户登录</router-link>
</div>
</el-form-item>
</el-form>
</div>
<!-- 底部 -->
<div class="el-register-footer">
<span></span>
</div>
</div>
</template>
<script>
import {register} from "@/api/login";
import {checkIdcard, validatePhone} from "@/utils/validate/index"
export default {
name: "Register",
data() {
// 确认密码
const equalToPassword = (rule, value, callback) => {
if (this.registerForm.password !== value) {
callback(new Error("两次输入的密码不一致"));
} else {
callback();
}
};
return {
codeUrl: "",
confirmPassword: "", // 确认密码
registerForm: {
studentName: "", // 学生姓名
idCard: "", // 身份证
phoneNumber: "",
password: "", // 密码
// code: "",
// uuid: ""
},
registerRules: {
studentName: [
{required: true, trigger: "blur", message: "请输入您的姓名"},
],
idCard: [
{required: true, trigger: "blur", message: "请输入您的身份证号"},
{required: true, validator: checkIdcard, trigger: "blur"}
],
phoneNumber: [
{required: true, trigger: "blur", message: "请输入您的手机号"},
{required: true, validator: validatePhone, trigger: "blur"}
],
password: [
{required: true, trigger: "blur", message: "请输入您的密码"},
{min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur'}
],
confirmPassword: [
{required: true, trigger: "blur", message: "请再次输入您的密码"},
{required: true, validator: equalToPassword, trigger: "blur"}
],
// code: [{ required: true, trigger: "change", message: "请输入验证码" }]
},
loading: false,
captchaEnabled: true
};
},
created() {
// this.getCode();
},
methods: {
// getCode() {
// getCodeImg().then(res => {
// this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
// if (this.captchaEnabled) {
// this.codeUrl = "data:image/gif;base64," + res.img;
// this.registerForm.uuid = res.uuid;
// }
// });
// },
handleRegister() {
this.$refs.registerForm.validate(valid => {
if (valid) {
this.loading = true;
register(this.registerForm).then(res => {
this.$message({
type: 'success',
message: "注册成功"
});
this.$router.push({
path: '/login'
});
// const studentName = this.registerForm.studentName;
// this.$alert(
// "恭喜你,您的账号 " + studentName + " 注册成功!", '系统提示', {
// confirmButtonText: '确定',
// callback: action => {
// }
// }).then(() => {
// })
}).catch(() => {
this.loading = false;
if (this.captchaEnabled) {
this.getCode();
}
})
}
});
}
}
};
</script>
<style lang="less" scoped>
.register {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-image: url("../assets/image/background.png");
// background-size: cover;
.register-card-container {
display: flex;
position: relative;
width: 520px;
// height: 411px;
background-color: #ffffff;
border-radius: 6px;
//padding: 20px;
//justify-content: center;
//align-items: center;
}
}
.title {
width: 310px;
height: 56px;
line-height: 56px;
position: absolute;
left: 105px;
top: -28px;
text-align: center;
justify-content: center;
color: #ffffff;
font-size: 18px;
font-weight: 900;
background-size: cover;
background-image: url("../assets/image/title.png");
}
.register-title {
margin: 30px auto 30px;
text-align: center;
color: #000000;
font-weight: 900;
}
.register-form {
border-radius: 6px;
// border: 1px solid;
width: 413px;
// height: 411px;
margin: 0 auto;
// padding: 26px 85px 26px 50px;
/deep/ .el-input .el-input__inner {
height: 48px;
}
}
.register-button {
width: 413px;
height: 60px;
background: #416af2;
border-radius: 6px;
}
.register-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.register-code {
width: 33%;
height: 38px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
}
.el-register-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.register-code-img {
height: 38px;
}
</style>
const {defineConfig} = require('@vue/cli-service')
module.exports = defineConfig({
publicPath: '/',
outputDir: 'web_dist',
assetsDir: 'static',
transpileDependencies: true,
lintOnSave: process.env.NODE_ENV === 'development',
productionSourceMap: false,
devServer: {
open: true,
//proxy: 'http://localhost:8848'
//proxy: 'http://10.20.100.200:11324'
proxy: {
[process.env.VUE_APP_BASE_API]: {
//target:'http://10.20.100.200:11324',
target: 'http://localhost:8848',
//crossOrigin:true,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
},
}
}
}
})
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>art-exam-web</title><script defer="defer" src="/static/js/chunk-vendors.3ec8172f.js"></script><script defer="defer" src="/static/js/app.53de8550.js"></script><link href="/static/css/chunk-vendors.09a7ec0e.css" rel="stylesheet"><link href="/static/css/app.7e110e8b.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but art-exam-web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
\ No newline at end of file
.box1[data-v-6f96cfc9]{margin-top:10px;height:120px}.web-icon[data-v-6f96cfc9]{width:70px;height:70px;display:inline-block}.web-title[data-v-6f96cfc9]{margin-left:40px;color:#fff;font-size:28px;display:inline-block;width:5em;height:80px;vertical-align:bottom;line-height:80px;font-weight:700}.drawer[data-v-6f96cfc9]{width:160px;text-align:center;height:80px;line-height:80px;display:inline-block;float:right}.photo-icon[data-v-6f96cfc9]{float:left;width:27px;height:27px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAYAAACN1PRVAAAAAXNSR0IArs4c6QAAAvtJREFUSEu9lkvMXlMUhp9n0kFFRTTERGhd4h4pTUqTdkArbmGCUJcm2kmpUrRpIumocSuiTJC4FMEAEcSlA6LVpDTiHqIlJkKIIAxMXllxfjnf+c/5/68hXcnKyfed/Z537/2u/a4t+zHcj1xMS5ZkJnAxcHyTJzTPL4DPgXpWvqT+OdXkpyRLchpwPzAP+KSTJwPt3A2sUT8cIhwkS3I18ATwInCrumfoI0nmAncDlwDXqE/2je0lS/IqcB6wUn1kXF2TrAAeBl5Tz+/iJpEluRZ4DJit/jwu0cS4JIcAPwHL1cfb+BGyJAcA3wC39G1FUyzXA6cDHwAP9hVFI8E9wFHqHxOEXbKHmhVd1l1RkrOA7VV1wDPAFU2VLlR39Ix/rlaorhoi2wtcNQDeBWxTN7S2bBNwtjp/YHJb1TmTyJIcB3wGHKz+3gYnORT4Qe3TOMBh6o8dzIHAL8CJ6pf17l9wksuBDeopPbM8EtitlvgjkaSKaJ76bc+7j4FN6rNdsgcavUqLSZGkgHeqT7e28UpgXd8Ea0yS0rZ0W90lq8O7V107QLa0KYwt6sYkG4EbqlDUNwYwm4E5ah32kW1cUw6gLhoALgYubbKsq6zq+Ur17QHMO+VAalneCNkC4JUBXcp+jgWuUz9tbeNJwKPAV2rZW5+eF6g7u2QzquKAxepHrQ/+CixQy+F7I0l1gp3qQS3cqUCtuCr1rxGyRtCXgT3qTc3v14HSqLxyykhyIbBKPbfB3gfMVS+aAHYdZAlQYpeg5fKb1fpvrEiyDbgROKbpFkvVN3vJmhk9BZwJrK8iUG8fi+mfUt8CvAvcAbynLmtjh1pMuUKRViW9sA9kde5qG5f1uc0QWblILf974Db1rekIk5wD3AUcDixRywRGYrprwc2lW3M12Ap8rf7WqrhZwNFl3nUlANaq9w5NbJwLz8Jq9cAZQJXzd+U05QzAEUAdk/frCqFWCxqMacnayCSzgWonldVydqnVlceKfSIb64v/18r+K9nfI5g9KzVPStcAAAAASUVORK5CYII=)}.el-dropdown-link[data-v-6f96cfc9]{font-size:18px;cursor:pointer;color:#fff}.el-icon-arrow-down[data-v-6f96cfc9]{font-size:12px}.box{display:flex;justify-content:center;background-image:url(/static/img/background.743fea97.png)}.container{width:70%;height:100%}.head{width:100%;height:100px}.entry-card-container{width:100%;height:845px;border-radius:12px;background-color:#fff}.entry-top{background-color:#f5f8fb;height:80px;border-radius:12px 12px 0 0;line-height:80px;font-size:18px;font-weight:700}.instruction[data-v-58cea8fe]{background-image:url(/static/img/background.743fea97.png);height:100vh;display:flex;justify-content:center}.instruction-card-container[data-v-58cea8fe]{width:680px;height:625px;background-color:#fff;border-radius:20px;align-self:center;position:relative}.title[data-v-58cea8fe]{width:310px;height:56px;line-height:56px;position:absolute;left:185px;top:-28px;text-align:center;justify-content:center;color:#fff;font-size:18px;font-weight:900;background-size:cover;background-image:url(/static/img/title.b8ec70cd.png)}.instruction-title[data-v-58cea8fe]{text-align:center;margin-top:40px;font-size:20px}.content-card[data-v-58cea8fe]{width:640px;height:457px;background:#f4f4f4;margin:0 auto}.buttonGroup[data-v-58cea8fe]{width:300px;height:40px;margin:auto;display:flex;justify-content:center}.content[data-v-58cea8fe]{height:420px;padding:20px;overflow-y:auto;line-height:25px}[data-v-6d0ee9e4]{margin:0;padding:0}.el-divider--horizontal[data-v-6d0ee9e4]{margin:15px 0}.el-form-item[data-v-6d0ee9e4]{margin:10px}.print[data-v-2cb272e6]{width:100%;height:780px;overflow-y:auto}.title[data-v-2cb272e6]{font-size:32px;font-weight:bolder;text-align:center;letter-spacing:5px}.titleSub[data-v-2cb272e6]{text-align:center;font-weight:700;font-size:30px;margin-top:15px;letter-spacing:10px}.pic[data-v-2cb272e6]{width:210px;height:199px;margin:110px auto;background-image:url(/static/img/nocard.2e304309.png)}.main[data-v-2cb272e6]{width:95%;height:1200px;margin:auto;border:1px solid #656262}.notice[data-v-2cb272e6]{width:700px;margin:auto}.left[data-v-2cb272e6]{width:65%;height:260px;display:inline-block;vertical-align:top}.left ul li[data-v-2cb272e6]{list-style:none}.right[data-v-2cb272e6]{display:inline-block;width:25%}table[data-v-2cb272e6]{border-color:#656262;border-collapse:collapse;width:100%;height:120px}.el-divider--horizontal[data-v-2cb272e6]{margin:15px 0}.sign-up[data-v-da89fe16]{position:relative}.form[data-v-da89fe16]{width:1350px;overflow:hidden;position:absolute;left:0;right:0;top:50px}.avatar-uploader[data-v-da89fe16]{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden;width:180px;height:200px}.avatar-uploader .el-upload[data-v-da89fe16]:hover{border-color:#409eff}.avatar-uploader-icon[data-v-da89fe16]{font-size:30px;color:#8c939d;width:180px;height:200px;line-height:178px;text-align:center}.avatar[data-v-da89fe16]{width:180px;height:200px;display:block}.el-divider--horizontal[data-v-da89fe16]{margin:15px 0}.avatar-uploader[data-v-68cea98e]{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden;width:180px;height:200px}.avatar-uploader .el-upload[data-v-68cea98e]:hover{border-color:#409eff}.avatar-uploader-icon[data-v-68cea98e]{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avatar[data-v-68cea98e]{width:180px;height:200px;display:block}.check[data-v-68cea98e]{position:relative;width:100%}.shade[data-v-68cea98e]{width:100%;height:738px;position:absolute;z-index:9}.shadeImg[data-v-68cea98e]{position:absolute;z-index:9;left:40%;top:10%}.shadeBackGround[data-v-68cea98e]{position:absolute;width:100%;height:740px;background:#252424;opacity:.2}.value[data-v-68cea98e]{position:absolute;width:100%}.el-divider--horizontal[data-v-68cea98e]{margin-top:10px;margin-bottom:0}.box[data-v-5ff2a068]{display:flex;justify-content:center;background-image:url(/static/img/background.743fea97.png)}.container[data-v-5ff2a068]{width:80%;height:100%}.head[data-v-5ff2a068]{width:100%;height:90px}.main[data-v-5ff2a068]{border-radius:10px;background:#fdfdfe;width:100%;height:890px}.step[data-v-5ff2a068]{width:100%;height:65px;padding-top:20px;padding-bottom:10px;background:#f5f8fb;border-radius:10px}.stepChild[data-v-5ff2a068]{width:80%;margin:auto}
\ No newline at end of file
.s-canvas[data-v-17c9cb97]{height:38px}.s-canvas canvas[data-v-17c9cb97]{margin-top:5px}*{margin:0;padding:0}.login-code-main[data-v-504b1909]{display:flex;flex-direction:row}.login[data-v-504b1909]{display:flex;justify-content:center;align-items:center;height:100vh;background-image:url(/static/img/background.743fea97.png)}.login .login-card-container[data-v-504b1909]{display:flex;position:relative;width:520px;height:470px;background-color:#fff;border-radius:6px}.title[data-v-504b1909]{width:310px;height:56px;line-height:56px;position:absolute;left:105px;top:-28px;text-align:center;justify-content:center;color:#fff;font-size:18px;font-weight:900;background-size:cover;background-image:url(/static/img/title.b8ec70cd.png)}.login-title[data-v-504b1909]{margin:45px auto 20px;text-align:center;color:#000;font-weight:900}.login-form[data-v-504b1909]{border-radius:6px;width:413px;margin:0 auto}.login-form[data-v-504b1909] .el-input .el-input__inner{height:45px}.login-button[data-v-504b1909]{width:413px;height:60px;background:#416af2;border-radius:6px}.el-login-footer[data-v-504b1909]{height:40px;line-height:40px;position:absolute;bottom:0;width:100%;text-align:center;color:#989797;font-family:Arial;font-size:12px;letter-spacing:1px}.register[data-v-11b4b6c4]{display:flex;justify-content:center;align-items:center;height:100vh;background-image:url(/static/img/background.743fea97.png)}.register .register-card-container[data-v-11b4b6c4]{display:flex;position:relative;width:520px;background-color:#fff;border-radius:6px}.title[data-v-11b4b6c4]{width:310px;height:56px;line-height:56px;position:absolute;left:105px;top:-28px;text-align:center;justify-content:center;color:#fff;font-size:18px;font-weight:900;background-size:cover;background-image:url(/static/img/title.b8ec70cd.png)}.register-title[data-v-11b4b6c4]{margin:30px auto 30px;text-align:center;color:#000;font-weight:900}.register-form[data-v-11b4b6c4]{border-radius:6px;width:413px;margin:0 auto}.register-form[data-v-11b4b6c4] .el-input .el-input__inner{height:48px}.register-button[data-v-11b4b6c4]{width:413px;height:60px;background:#416af2;border-radius:6px}.register-tip[data-v-11b4b6c4]{font-size:13px;text-align:center;color:#bfbfbf}.register-code[data-v-11b4b6c4]{width:33%;height:38px;float:right}.register-code img[data-v-11b4b6c4]{cursor:pointer;vertical-align:middle}.el-register-footer[data-v-11b4b6c4]{height:40px;line-height:40px;position:fixed;bottom:0;width:100%;text-align:center;color:#fff;font-family:Arial;font-size:12px;letter-spacing:1px}.register-code-img[data-v-11b4b6c4]{height:38px}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment