专家通道

chengdu
yujialong 4 years ago
parent 5d835b0989
commit 705965b5b3
  1. BIN
      src/assets/img/bg.jpg
  2. BIN
      src/assets/img/button.png
  3. 573
      src/components/page/ClientLogin.vue
  4. 644
      src/components/page/Login.vue
  5. 468
      src/components/page/ProjectIntro.vue
  6. 476
      src/components/page/ProjectPattern.vue
  7. 5
      src/router/index.js
  8. 1
      src/utils/api.js

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

@ -0,0 +1,573 @@
<template>
<div class="wrap">
<div class="left">
<img src="../../assets/img/logo.png" alt="">
<div class="text">
<p>欢迎使用</p>
<p>期货期权交易虚拟仿真实验</p>
</div>
</div>
<div class="right">
<div class="back" v-show="isReg" @click="toReg(false)">
<i class="el-icon-back"></i>
</div>
<div v-if="!isReg" class="ms-login">
<el-tabs v-model="activeName">
<el-tab-pane label="账号登录" name="0">
<el-form :model="loginForm" :rules="loginRules" ref="loginForm" style="margin-top: 20px">
<el-form-item label="用户名" prop="username">
<el-input v-model="loginForm.username" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
placeholder="请输入密码"
v-model="loginForm.password"
@keyup.enter.native="getSchool('loginForm')"
>
</el-input>
</el-form-item>
<el-button class="submit" type="primary" @click="getSchool('loginForm')">登录</el-button>
</el-form>
</el-tab-pane>
<el-tab-pane label="手机号/邮箱登录" name="1">
<el-form :model="phoneParam" :rules="phoneRules" ref="phoneParam" style="margin-top: 20px">
<el-form-item label="手机号/邮箱" prop="userphone">
<el-input v-model="phoneParam.userphone" placeholder="请输入手机号/邮箱"></el-input>
</el-form-item>
<el-form-item label="密码" prop="phonePassword">
<el-input
type="password"
placeholder="请输入密码"
v-model="phoneParam.phonePassword"
@keyup.enter.native="getSchool('phoneParam')"
>
</el-input>
</el-form-item>
<el-button class="submit" type="primary" @click="getSchool('phoneParam')">登录</el-button>
</el-form>
</el-tab-pane>
</el-tabs>
<div class="links flex-between">
<el-button type="text" class="ques" @click="toReg(true)">前往注册</el-button>
<el-button type="text" class="forget" @click="forget">忘记密码</el-button>
</div>
<!-- <h2>密码登录</h2>
<el-form :model="loginForm" :rules="loginRules" ref="login" label-width="0px">
<el-form-item prop="username">
<p class="label">用户名</p>
<el-input v-model="loginForm.username" placeholder="请输入账号/手机号" @keyup.enter.native="submitForm()"></el-input>
</el-form-item>
<el-form-item prop="password">
<p class="label">密码</p>
<el-input
type="password"
placeholder="请输入密码"
v-model="loginForm.password"
@keyup.enter.native="getSchool()"
>
</el-input>
</el-form-item>
<el-button class="submit" type="primary" @click="getSchool">登录</el-button>
<div class="links flex-between">
<el-button type="text" class="ques" @click="toReg(true)">前往注册</el-button>
<el-button type="text" class="forget" @click="forget">忘记密码</el-button>
</div>
</el-form> -->
</div>
<register v-else :isReg.sync="isReg" @updateInfo="updateInfo"></register>
</div>
<!-- 选择角色 -->
<el-dialog title="选择角色" :visible.sync="roleDialog" width="24%" center :close-on-click-modal="false">
<div>
<el-select v-model="roleId" placeholder="请选择角色">
<el-option v-for="(item,index) in roleList" :key="index" :label="item.roleName" :value="item.roleId"></el-option>
</el-select>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="cancleRoleDia"> </el-button>
<el-button v-if="activeName == '0'" type="primary" @click="roleSure('loginForm')"> </el-button>
<el-button v-else type="primary" @click="roleSure('phoneParam')"> </el-button>
</span>
</el-dialog>
<el-dialog :title="phoneReset ? '手机重置密码' : '邮箱重置密码'" :visible.sync="forgetVisible" :close-on-click-modal="false" @close="closeForget" width="30%">
<template v-if="phoneReset">
<el-form ref="form" label-width="60px">
<el-form-item label="手机号">
<el-input placeholder="请输入手机号" v-model.number="phone" maxlength="11"></el-input>
</el-form-item>
<el-form-item label="验证码">
<div class="flex-between">
<el-input v-model.number="phoneCode" placeholder="请输入验证码" maxlength="6"></el-input>
<el-button style="margin-left: 10px" type="text" @click="sendPhoneCode" :disabled="phoneDisabled">{{phoneBtnText}}</el-button>
</div>
</el-form-item>
<el-form-item label="新密码">
<el-input type="password" placeholder="请输入新密码" v-model="newPassword"></el-input>
</el-form-item>
</el-form>
<div class="switch" @click="switchType(false)"><span>邮箱重置密码</span></div>
<span slot="footer" class="dialog-footer">
<el-button @click="phoneVisible = false"> </el-button>
<el-button type="primary" @click="updatePassword(1)"> </el-button>
</span>
</template>
<template v-else>
<el-form ref="form" label-width="60px">
<el-form-item label="邮箱">
<el-input placeholder="请输入邮箱" v-model="email"></el-input>
</el-form-item>
<el-form-item label="验证码">
<div class="flex-between">
<el-input v-model.number="emailCode" placeholder="请输入验证码" maxlength="6"></el-input>
<el-button style="margin-left: 10px" type="text" @click="sendEmailCode" :disabled="emailDisabled">{{emailBtnText}}</el-button>
</div>
</el-form-item>
<el-form-item label="新密码">
<el-input type="password" placeholder="请输入新密码" v-model="newPassword"></el-input>
</el-form-item>
</el-form>
<div class="switch" @click="switchType(true)"><span>手机重置密码</span></div>
<span slot="footer" class="dialog-footer">
<el-button @click="emailVisible = false"> </el-button>
<el-button type="primary" @click="updatePassword"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
import register from './RegisterForm';
export default {
data: function() {
return {
activeName: '0',
isReg: false,
loginForm: {
username: '15794146134',
password: '111aaa',
},
loginRules: {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
},
phoneParam: {
userphone: '',
phonePassword: ''
},
phoneRules: {
userphone: [{ required: true, message: '请输入手机号/邮箱', trigger: 'blur' }],
phonePassword: [{ required: true, message: '请输入密码', trigger: 'blur' }],
},
roleDialog: false,
userId: '',
schoolId: '',
roleId: '',
roleList: [],
studentId: '',
forgetVisible: false,
phoneReset: true,
email: '',
emailBtnText: '发送验证码',
emailCode: '',
emailDisabled: false,
emailTimer: null,
phone: '',
phoneBtnText: '发送验证码',
phoneCode: '',
phoneDisabled: false,
phoneTimer: null,
newPassword: '',
emailOpener: '',
phoneOpener: ''
};
},
components: {
register
},
mounted(){
this.$once('hook:beforeDestroy', function () {
clearInterval(this.phoneTimer)
this.phoneTimer = null
clearInterval(this.emailTimer)
this.emailTimer = null
})
},
methods: {
getSchool(form) {
this.$refs[form].validate(valid => {
if (valid) {
let data = {
account: this.activeName == '0' ? this.loginForm.username : this.phoneParam.userphone,
password: this.activeName == '0' ? this.loginForm.password : this.phoneParam.phonePassword,
schoolId: 2105,
source: this.activeName
};
this.$get(this.api.loginSchool, data)
.then(res => {
if(res.status == 200){
this.schoolList = [...res.message.staffList,...res.message.studentList]
let indexs = {}
this.schoolList = this.schoolList.reduce((cur,next) => {
indexs[next.schoolId] ? '' : indexs[next.schoolId] = true && cur.push(next)
return cur
},[])
if(this.schoolList.length >= 1) {
this.schoolId = this.schoolList[0].schoolId
this.userId = this.schoolList[0].userId
this.studentId = this.schoolList[0].studentId
// this.getRole()
this.roleId = 4
this.submitForm(form)
}else{
this.$message.error('账号不存在')
}
}else{
this.$message.error(res.errmessage);
}
})
.catch(res => {});
} else {
this.$message.error('请输入账号和密码');
return false;
}
});
},
getRole(form) {
// this.userId = this.schoolList.find((n,k) => {
// return n.schoolId == this.schoolId
// }).userId
let data = {
userId: this.userId,
schoolId: this.schoolId
};
this.$get(this.api.loginRole, data)
.then(res => {
this.roleList = [...res.message.staffList,...res.message.studentList]
let indexs = {}
this.roleList = this.roleList.reduce((cur,next) => {
indexs[next.roleId] ? '' : indexs[next.roleId] = true && cur.push(next)
return cur
},[])
this.roleList.forEach((n,k) => {
switch(n.roleId){
case 2:
n.roleName = '管理员'
break
case 3:
n.roleName = '老师'
break
case 4:
n.roleName = '学生'
break
}
})
if(this.roleList.length > 1) {
this.roleDialog = true
}else{
this.roleId = this.roleList[0].roleId
this.submitForm(form)
}
})
.catch(res => {});
},
updateInfo(data){
this.loginForm.username = data.username
this.loginForm.password = data.password
},
roleSure(form){
if(this.roleId){
this.submitForm(form)
}else{
this.$message.error('请选择角色!');
}
},
submitForm(form) {
this.$refs[form].validate(valid => {
if (valid) {
let data = {
roleId: this.roleId,
userId: this.userId,
schoolId: this.schoolId
}
this.$get(this.api.logins,data).then(res => {
this.$post(this.api.updateLogInNumber,{userId: this.userId}).then(res => {}).catch(res => {});
this.$message.success('登录成功');
sessionStorage.setItem('kd_client_username', this.activeName == '0' ? this.loginForm.username : this.phoneParam.userphone);
this.$store.commit("userLoginData", { userId : this.userId,accountRole: this.roleId,studentId : this.studentId,schoolId: this.schoolId,token: res.message.user.token});
res.message.user.userAvatars && this.$store.commit("userPhoto", { avatar : res.message.user.userAvatars});
this.$store.commit("userName", { userName : res.message.user.userName});
this.$store.commit("dataTime", { dataTime : res.message.user.dataTime});
let redirect = decodeURIComponent(this.$route.query.redirect || '/dashboard')
this.$router.replace(redirect)
}).catch(res => {});
} else {
// this.$message.error('');
return false;
}
});
},
cancleRoleDia() {
this.roleId = ''
this.roleDialog = false
},
toReg(status) {
this.isReg = status
},
forget(){
this.forgetVisible = true
},
emailCountdown(){
let count = 60
if(!this.emailTimer){
this.emailDisabled = true
this.emailTimer = setInterval(() => {
if(count > 0){
count--
this.emailBtnText = `${count}秒后重试`
}else{
this.emailDisabled = false
clearInterval(this.emailTimer)
this.emailTimer = null
this.emailBtnText = `发送验证码`
}
},1000)
}
},
phoneCountdown(){
let count = 60
if(!this.phoneTimer){
this.phoneDisabled = true
this.phoneTimer = setInterval(() => {
if(count > 0){
count--
this.phoneBtnText = `${count}秒后重试`
}else{
this.phoneDisabled = false
clearInterval(this.phoneTimer)
this.phoneTimer = null
this.phoneBtnText = `发送验证码`
}
},1000)
}
},
closeForget(){
this.phoneCode = ''
this.emailCode = ''
this.userId = ''
this.newPassword = ''
},
sendEmailCode(){
if(!this.email) return this.$message.warning('请输入邮箱')
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return this.$message.warning('请输入正确的邮箱')
let data = {
email: this.email
}
this.$get(this.api.findPasswordByEmail,data).then(res => {
if(res.errmessage == 'success'){
this.$message.success('发送成功')
this.emailCountdown()
this.userId = res.data.userId
this.emailOpener = res.data.opener
}
}).catch(res => {});
},
sendPhoneCode(){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
let data = {
phone: this.phone
}
this.$get(this.api.findPasswordByPhone,data).then(res => {
if(res.errmessage == 'success'){
this.$message.success('发送成功')
this.phoneCountdown()
this.userId = res.data.userId
this.phoneOpener = res.data.opener
}
}).catch(res => {});
},
async updatePassword(type){
if(type == 1){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
if(!this.phoneCode) return this.$message.warning('请输入验证码')
}else{
if(!this.email) return this.$message.warning('请输入邮箱')
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return this.$message.warning('请输入正确的邮箱')
if(!this.emailCode) return this.$message.warning('请输入验证码')
}
if(!this.newPassword) return this.$message.warning('请输入新密码')
let checkData = {
code: type == 1 ? this.phoneCode : this.emailCode,
opener: type == 1 ? this.phoneOpener : this.emailOpener
}
let checkRes = await this.$post(this.api.checkCode,checkData)
if(checkRes.errmessage == 'success'){
let resetData = {
userId: this.userId,
password: this.newPassword
}
let resetRes = await this.$post(this.api.resetPassword,resetData)
if(resetRes.errmessage == 'success'){
this.$message.success('重置成功')
this.forgetVisible = false
}
}
},
switchType(type){
this.phoneReset = type
}
},
};
</script>
<style scoped lang="scss">
.wrap {
position: relative;
width: 100%;
height: 100%;
background: url(../../assets/img/login_bg.png) 0 0/100% 100% no-repeat;
overflow: hidden;
.logo{
position: absolute;
top: 20px;
left: 72px;
width: 240px;
}
.left{
position: absolute;
top: 50%;
left: 221px;
transform: translateY(-60%);
img{
width: 447px;;
margin-bottom: 30px;
}
.text{
font-size: 47px;
color: #fff;
p{
margin-bottom: 15px;
&:last-child{
margin-bottom: 0;
}
}
}
}
.right{
position: absolute;
top: 50%;
right: 100px;
transform: translateY(-50%);
width: 700px;
padding: 50px 90px 20px;
background-color: #fff;
box-sizing: border-box;
box-shadow: 0 1px 20px rgba(0,0,0,0.16);
.back{
position: absolute;
top: 20px;
left: 20px;
font-size: 24px;
color: #105cb2;
cursor: pointer;
&:hover{
opacity: .8;
}
}
h2{
padding-bottom: 10px;
font-size: 24px;
font-weight: 400;
color: #303d4c;
text-align: center;
border-bottom: 1px solid #E5E5E5;
}
/deep/.el-form{
margin-top: 30px;
.label{
margin-bottom: 10px;
color: #105CB2;
}
/deep/.el-input__inner{
height: 46px;
padding: 0 23px;
line-height: 46px;
border: 1px solid #AFB5BB;
border-radius: 23px !important;
}
/deep/.el-form-item__error{
top: 105%;
left: auto;
right: 0;
color: #FFA94E;
}
.submit{
width: 100%;
height: 48px;
margin-top: 60px;
line-height: 48px;
padding: 0;
font-size: 20px;
background-color: #105cb2;
border-radius: 23px;
border: 0;
}
.login-tips{
margin-bottom: 20px;
font-size: 16px;
color: #105CB2;
text-align: center;
}
.thirdParty{
.item{
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
padding: 10px 0;
color: #AFB5BB;
font-size: 16px;
background-color: #eff0f1;
border-radius: 36px;
cursor: pointer;
img{
width: 40px;
margin-right: 10px;
}
}
}
}
}
}
.switch{
span{
cursor: pointer;
color: #9076FF;
}
}
.links{
margin: 20px 0 20px;
}
.ques{
color: #105cb2;
font-size: 14px;
}
.forget{
color: #ffa94e;
font-size: 14px;
}
</style>

@ -1,214 +1,76 @@
<template> <template>
<div class="wrap"> <div class="wrap">
<div class="left"> <!-- 顶部栏目 -->
<div class="bar flex-between">
<div class="icon_wrap">
<img src="../../assets/img/logo.png" alt=""> <img src="../../assets/img/logo.png" alt="">
<div class="text">
<p>欢迎使用</p>
<p>期货期权交易虚拟仿真实验</p>
</div> </div>
<div class="bar_name">经济与管理学院虚拟仿真实验教学中心</div>
</div> </div>
<div class="right"> <!-- 标题+实验入口 -->
<div class="back" v-show="isReg" @click="toReg(false)"> <div class="content">
<i class="el-icon-back"></i> <div class="content_title">
<div>欢迎使用</div>
<div>期货期权交易虚拟仿真实验</div>
</div> </div>
<div v-if="!isReg" class="ms-login"> <div class="content_button">
<el-tabs v-model="activeName"> <a @click="toClient"><div>学生端</div></a>
<el-tab-pane label="账号登录" name="0"> <a @click="toMang"><div>教师端(教学活动查看入口)</div></a>
<el-form :model="loginForm" :rules="loginRules" ref="loginForm" style="margin-top: 20px"> <a @click="toExpert"><div style="background:#CD3E6A">专家通道</div></a>
<el-form-item label="用户名" prop="username">
<el-input v-model="loginForm.username" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
placeholder="请输入密码"
v-model="loginForm.password"
@keyup.enter.native="getSchool('loginForm')"
>
</el-input>
</el-form-item>
<el-button class="submit" type="primary" @click="getSchool('loginForm')">登录</el-button>
</el-form>
</el-tab-pane>
<el-tab-pane label="手机号/邮箱登录" name="1">
<el-form :model="phoneParam" :rules="phoneRules" ref="phoneParam" style="margin-top: 20px">
<el-form-item label="手机号/邮箱" prop="userphone">
<el-input v-model="phoneParam.userphone" placeholder="请输入手机号/邮箱"></el-input>
</el-form-item>
<el-form-item label="密码" prop="phonePassword">
<el-input
type="password"
placeholder="请输入密码"
v-model="phoneParam.phonePassword"
@keyup.enter.native="getSchool('phoneParam')"
>
</el-input>
</el-form-item>
<el-button class="submit" type="primary" @click="getSchool('phoneParam')">登录</el-button>
</el-form>
</el-tab-pane>
</el-tabs>
<div class="links flex-between">
<el-button type="text" class="ques" @click="toReg(true)">前往注册</el-button>
<el-button type="text" class="forget" @click="forget">忘记密码</el-button>
</div>
<!-- <h2>密码登录</h2>
<el-form :model="loginForm" :rules="loginRules" ref="login" label-width="0px">
<el-form-item prop="username">
<p class="label">用户名</p>
<el-input v-model="loginForm.username" placeholder="请输入账号/手机号" @keyup.enter.native="submitForm()"></el-input>
</el-form-item>
<el-form-item prop="password">
<p class="label">密码</p>
<el-input
type="password"
placeholder="请输入密码"
v-model="loginForm.password"
@keyup.enter.native="getSchool()"
>
</el-input>
</el-form-item>
<el-button class="submit" type="primary" @click="getSchool">登录</el-button>
<div class="links flex-between">
<el-button type="text" class="ques" @click="toReg(true)">前往注册</el-button>
<el-button type="text" class="forget" @click="forget">忘记密码</el-button>
</div> </div>
</el-form> --> <div class="content_footer">
<div>建议使用谷歌浏览器进行实验</div>
<div>热线电话028-61831033 &nbsp;&nbsp;&nbsp;&nbsp;虚拟实验服务和支持QQ群459797943</div>
</div> </div>
<register v-else :isReg.sync="isReg" @updateInfo="updateInfo"></register>
</div> </div>
<!-- 访问人数 -->
<!-- 选择角色 --> <div class="count_wrap">
<el-dialog title="选择角色" :visible.sync="roleDialog" width="24%" center :close-on-click-modal="false"> <div class="count_title">访问统计</div>
<div> <div>
<el-select v-model="roleId" placeholder="请选择角色"> <div class="count_current">当前访问&nbsp;87</div>
<el-option v-for="(item,index) in roleList" :key="index" :label="item.roleName" :value="item.roleId"></el-option> <div class="count_history">历史访问&nbsp;468427</div>
</el-select> <div class="count_people">实验人数&nbsp;1059</div>
</div> </div>
<span slot="footer" class="dialog-footer">
<el-button @click="cancleRoleDia"> </el-button>
<el-button v-if="activeName == '0'" type="primary" @click="roleSure('loginForm')"> </el-button>
<el-button v-else type="primary" @click="roleSure('phoneParam')"> </el-button>
</span>
</el-dialog>
<el-dialog :title="phoneReset ? '手机重置密码' : '邮箱重置密码'" :visible.sync="forgetVisible" :close-on-click-modal="false" @close="closeForget" width="30%">
<template v-if="phoneReset">
<el-form ref="form" label-width="60px">
<el-form-item label="手机号">
<el-input placeholder="请输入手机号" v-model.number="phone" maxlength="11"></el-input>
</el-form-item>
<el-form-item label="验证码">
<div class="flex-between">
<el-input v-model.number="phoneCode" placeholder="请输入验证码" maxlength="6"></el-input>
<el-button style="margin-left: 10px" type="text" @click="sendPhoneCode" :disabled="phoneDisabled">{{phoneBtnText}}</el-button>
</div> </div>
</el-form-item>
<el-form-item label="新密码">
<el-input type="password" placeholder="请输入新密码" v-model="newPassword"></el-input>
</el-form-item>
</el-form>
<div class="switch" @click="switchType(false)"><span>邮箱重置密码</span></div>
<span slot="footer" class="dialog-footer">
<el-button @click="phoneVisible = false"> </el-button>
<el-button type="primary" @click="updatePassword(1)"> </el-button>
</span>
</template>
<template v-else>
<el-form ref="form" label-width="60px">
<el-form-item label="邮箱">
<el-input placeholder="请输入邮箱" v-model="email"></el-input>
</el-form-item>
<el-form-item label="验证码">
<div class="flex-between">
<el-input v-model.number="emailCode" placeholder="请输入验证码" maxlength="6"></el-input>
<el-button style="margin-left: 10px" type="text" @click="sendEmailCode" :disabled="emailDisabled">{{emailBtnText}}</el-button>
</div>
</el-form-item>
<el-form-item label="新密码">
<el-input type="password" placeholder="请输入新密码" v-model="newPassword"></el-input>
</el-form-item>
</el-form>
<div class="switch" @click="switchType(true)"><span>手机重置密码</span></div>
<span slot="footer" class="dialog-footer">
<el-button @click="emailVisible = false"> </el-button>
<el-button type="primary" @click="updatePassword"> </el-button>
</span>
</template>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import register from './RegisterForm'; import { Loading } from 'element-ui'
export default { export default {
data: function() { data() {
return { return {
activeName: '0',
isReg: false,
loginForm: {
username: '15794146134',
password: '111aaa',
},
loginRules: {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
},
phoneParam: {
userphone: '',
phonePassword: ''
},
phoneRules: {
userphone: [{ required: true, message: '请输入手机号/邮箱', trigger: 'blur' }],
phonePassword: [{ required: true, message: '请输入密码', trigger: 'blur' }],
},
roleDialog: false,
userId: '', userId: '',
schoolId: '',
roleId: '',
roleList: [],
studentId: '', studentId: '',
forgetVisible: false, schoolId: '',
phoneReset: true, studentIds: [1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513],
email: '', loadIns: null,
emailBtnText: '发送验证码', }
emailCode: '',
emailDisabled: false,
emailTimer: null,
phone: '',
phoneBtnText: '发送验证码',
phoneCode: '',
phoneDisabled: false,
phoneTimer: null,
newPassword: '',
emailOpener: '',
phoneOpener: ''
};
},
components: {
register
}, },
mounted(){ mounted(){
this.$once('hook:beforeDestroy', function () {
clearInterval(this.phoneTimer) },
this.phoneTimer = null methods:{
clearInterval(this.emailTimer) toClient(){
this.emailTimer = null location.href = location.host.includes('116.63.168.79') ? 'http://116.63.168.79/kdclient/#/login' : 'http://122.9.154.146/kdclient/#/login'
})
}, },
methods: { toMang(){
getSchool(form) { location.href = location.host.includes('116.63.168.79') ? 'http://116.63.168.79/kdserver/#/login' : 'http://122.9.154.146/kdserver/#/login'
this.$refs[form].validate(valid => { },
if (valid) { toExpert(){
this.loadIns = Loading.service({
background: 'rgba(255,255,255,.6)'
})
let studentId = this.studentIds[parseInt(Math.random()*10)]
this.$get(this.api.getAccountPassword,{studentId}).then(res => {
let account = res.data.account
let data = { let data = {
account: this.activeName == '0' ? this.loginForm.username : this.phoneParam.userphone, account: res.data.account,
password: this.activeName == '0' ? this.loginForm.password : this.phoneParam.phonePassword, password: res.data.password,
schoolId: 2105, schoolId: 2105,
source: this.activeName source: 0
}; };
this.$get(this.api.loginSchool, data) this.$get(this.api.loginSchool, data).then(res => {
.then(res => {
if(res.status == 200){ if(res.status == 200){
this.schoolList = [...res.message.staffList,...res.message.studentList] this.schoolList = [...res.message.staffList,...res.message.studentList]
let indexs = {} let indexs = {}
@ -220,354 +82,140 @@ export default {
this.schoolId = this.schoolList[0].schoolId this.schoolId = this.schoolList[0].schoolId
this.userId = this.schoolList[0].userId this.userId = this.schoolList[0].userId
this.studentId = this.schoolList[0].studentId this.studentId = this.schoolList[0].studentId
// this.getRole()
this.roleId = 4 this.roleId = 4
this.submitForm(form)
}else{
this.$message.error('账号不存在')
}
}else{
this.$message.error(res.errmessage);
}
})
.catch(res => {});
} else {
this.$message.error('请输入账号和密码');
return false;
}
});
},
getRole(form) {
// this.userId = this.schoolList.find((n,k) => {
// return n.schoolId == this.schoolId
// }).userId
let data = {
userId: this.userId,
schoolId: this.schoolId
};
this.$get(this.api.loginRole, data)
.then(res => {
this.roleList = [...res.message.staffList,...res.message.studentList]
let indexs = {}
this.roleList = this.roleList.reduce((cur,next) => {
indexs[next.roleId] ? '' : indexs[next.roleId] = true && cur.push(next)
return cur
},[])
this.roleList.forEach((n,k) => {
switch(n.roleId){
case 2:
n.roleName = '管理员'
break
case 3:
n.roleName = '老师'
break
case 4:
n.roleName = '学生'
break
}
})
if(this.roleList.length > 1) {
this.roleDialog = true
}else{
this.roleId = this.roleList[0].roleId
this.submitForm(form)
}
})
.catch(res => {});
},
updateInfo(data){
this.loginForm.username = data.username
this.loginForm.password = data.password
},
roleSure(form){
if(this.roleId){
this.submitForm(form)
}else{
this.$message.error('请选择角色!');
}
},
submitForm(form) {
this.$refs[form].validate(valid => {
if (valid) {
let data = { let data = {
roleId: this.roleId, roleId: 4,
userId: this.userId, userId: this.userId,
schoolId: this.schoolId schoolId: this.schoolId
} }
this.$get(this.api.logins,data).then(res => { this.$get(this.api.logins,data).then(res => {
this.$post(this.api.updateLogInNumber,{userId: this.userId}).then(res => {}).catch(res => {}); this.$post(this.api.updateLogInNumber,{userId: this.userId}).then(res => {}).catch(res => {});
this.$message.success('登录成功'); sessionStorage.setItem('kd_client_username',account);
sessionStorage.setItem('kd_client_username', this.activeName == '0' ? this.loginForm.username : this.phoneParam.userphone);
this.$store.commit("userLoginData", { userId : this.userId,accountRole: this.roleId,studentId : this.studentId,schoolId: this.schoolId,token: res.message.user.token}); this.$store.commit("userLoginData", { userId : this.userId,accountRole: this.roleId,studentId : this.studentId,schoolId: this.schoolId,token: res.message.user.token});
res.message.user.userAvatars && this.$store.commit("userPhoto", { avatar : res.message.user.userAvatars}); res.message.user.userAvatars && this.$store.commit("userPhoto", { avatar : res.message.user.userAvatars});
this.$store.commit("userName", { userName : res.message.user.userName}); this.$store.commit("userName", { userName : res.message.user.userName});
this.$store.commit("dataTime", { dataTime : res.message.user.dataTime}); this.$store.commit("dataTime", { dataTime : res.message.user.dataTime});
let redirect = decodeURIComponent(this.$route.query.redirect || '/dashboard') this.loadIns.close()
this.$router.replace(redirect) this.$router.replace('/dashboard')
}).catch(res => {}); }).catch(res => {})
} else {
// this.$message.error('');
return false;
}
});
},
cancleRoleDia() {
this.roleId = ''
this.roleDialog = false
},
toReg(status) {
this.isReg = status
},
forget(){
this.forgetVisible = true
},
emailCountdown(){
let count = 60
if(!this.emailTimer){
this.emailDisabled = true
this.emailTimer = setInterval(() => {
if(count > 0){
count--
this.emailBtnText = `${count}秒后重试`
}else{
this.emailDisabled = false
clearInterval(this.emailTimer)
this.emailTimer = null
this.emailBtnText = `发送验证码`
} }
},1000)
} }
}, }).catch(res => {})
phoneCountdown(){ }).catch(res => {})
let count = 60
if(!this.phoneTimer){
this.phoneDisabled = true
this.phoneTimer = setInterval(() => {
if(count > 0){
count--
this.phoneBtnText = `${count}秒后重试`
}else{
this.phoneDisabled = false
clearInterval(this.phoneTimer)
this.phoneTimer = null
this.phoneBtnText = `发送验证码`
}
},1000)
}
},
closeForget(){
this.phoneCode = ''
this.emailCode = ''
this.userId = ''
this.newPassword = ''
},
sendEmailCode(){
if(!this.email) return this.$message.warning('请输入邮箱')
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return this.$message.warning('请输入正确的邮箱')
let data = {
email: this.email
} }
this.$get(this.api.findPasswordByEmail,data).then(res => {
if(res.errmessage == 'success'){
this.$message.success('发送成功')
this.emailCountdown()
this.userId = res.data.userId
this.emailOpener = res.data.opener
} }
}).catch(res => {}); }
},
sendPhoneCode(){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
let data = {
phone: this.phone
}
this.$get(this.api.findPasswordByPhone,data).then(res => {
if(res.errmessage == 'success'){
this.$message.success('发送成功')
this.phoneCountdown()
this.userId = res.data.userId
this.phoneOpener = res.data.opener
}
}).catch(res => {});
},
async updatePassword(type){
if(type == 1){
if(!this.phone) return this.$message.warning('请输入手机号')
if(!/^1[3456789]\d{9}$/.test(this.phone)) return this.$message.warning('请输入正确的手机号')
if(!this.phoneCode) return this.$message.warning('请输入验证码')
}else{
if(!this.email) return this.$message.warning('请输入邮箱')
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return this.$message.warning('请输入正确的邮箱')
if(!this.emailCode) return this.$message.warning('请输入验证码')
}
if(!this.newPassword) return this.$message.warning('请输入新密码')
let checkData = {
code: type == 1 ? this.phoneCode : this.emailCode,
opener: type == 1 ? this.phoneOpener : this.emailOpener
}
let checkRes = await this.$post(this.api.checkCode,checkData)
if(checkRes.errmessage == 'success'){
let resetData = {
userId: this.userId,
password: this.newPassword
}
let resetRes = await this.$post(this.api.resetPassword,resetData)
if(resetRes.errmessage == 'success'){
this.$message.success('重置成功')
this.forgetVisible = false
}
}
},
switchType(type){
this.phoneReset = type
}
},
};
</script> </script>
<style scoped lang="scss"> <style lang="scss" scoped>
.wrap { .wrap{
position: relative; font-family: '微软雅黑';
width: 100%; width: 100%;
height: 100%; height: 100%;
background: url(../../assets/img/login_bg.png) 0 0/100% 100% no-repeat; position: fixed;
overflow: hidden; background: url('../../assets/img/bg.jpg');
background-size: 100% 100%;
.logo{ background-repeat: no-repeat;
position: absolute; .bar{
top: 20px; width: 100%;
left: 72px; height: 90px;
width: 240px; background: #004592;
} border-bottom: 2px solid #4d8ab6;
.left{ box-shadow: -3px 7px 5px -7px rgba(77,70,70,0.75);
position: absolute; -webkit-box-shadow: -3px 7px 5px -7px rgba(77,70,70,0.75);
top: 50%; -moz-box-shadow: -3px 7px 5px -7px rgba(77,70,70,0.75);
left: 221px; .icon_wrap{
transform: translateY(-60%); width: 12%;
height: 90px;
background: #CD3E6A;
display: flex;
justify-content: center;
align-items: center;
img{ img{
width: 447px;; height: 45px;
margin-bottom: 30px;
}
.text{
font-size: 47px;
color: #fff;
p{
margin-bottom: 15px;
&:last-child{
margin-bottom: 0;
}
}
} }
} }
.right{ .bar_name{
position: absolute; width:88%;
top: 50%;
right: 100px;
transform: translateY(-50%);
width: 700px;
padding: 50px 90px 20px;
background-color: #fff;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0 1px 20px rgba(0,0,0,0.16); padding-left: 100px;
font-size: 25px;
.back{ color: white;
position: absolute;
top: 20px;
left: 20px;
font-size: 24px;
color: #105cb2;
cursor: pointer;
&:hover{
opacity: .8;
} }
} }
.content{
h2{ .content_title{
padding-bottom: 10px; height: 400px;
font-size: 24px;
font-weight: 400;
color: #303d4c;
text-align: center;
border-bottom: 1px solid #E5E5E5;
}
/deep/.el-form{
margin-top: 30px;
.label{
margin-bottom: 10px;
color: #105CB2;
}
/deep/.el-input__inner{
height: 46px;
padding: 0 23px;
line-height: 46px;
border: 1px solid #AFB5BB;
border-radius: 23px !important;
}
/deep/.el-form-item__error{
top: 105%;
left: auto;
right: 0;
color: #FFA94E;
}
.submit{
width: 100%; width: 100%;
height: 48px;
margin-top: 60px;
line-height: 48px;
padding: 0;
font-size: 20px;
background-color: #105cb2;
border-radius: 23px;
border: 0;
}
.login-tips{
margin-bottom: 20px;
font-size: 16px;
color: #105CB2;
text-align: center; text-align: center;
} box-sizing: border-box;
.thirdParty{ padding: 100px 0px;
.item{ line-height: 100px;
font-size: 60px;
color: white;
letter-spacing:8px;
// background: red;
}
.content_button{
height: 280px;
// background: blue;
width: 100%;
display: flex; display: flex;
justify-content: center; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 20px; flex-flow: column;
padding: 10px 0; div{
color: #AFB5BB; width: 400px;
font-size: 16px; height: 70px;
background-color: #eff0f1; text-align: center;
border-radius: 36px; line-height: 70px;
cursor: pointer; font-size: 28px;
img{ color: white;
width: 40px; // background: green;
background: url('../../assets/img/button.png');
background-size: 400px 70px;
}
div:hover{
background: #FF5288;
border:2px solid white;
cursor:pointer
}
}
.content_footer{
margin-top: 50px;
height: 200px;
width: 100%;
text-align: center;
color: white;
font-size: 28px;
line-height: 50px;
font-family: '仿宋';
.icon-dianhuahaoma,.icon-a317{
font-size: 32px;
margin-right: 10px; margin-right: 10px;
} }
} }
} }
} }
.count_wrap{
position: fixed;
bottom: 30px;
width: 230px;
height: 200px;
// background: red;
left: 130px;
color: white;
.count_title{
font-size: 30px;
margin-bottom:25px ;
font-weight: 540;
} }
div{
font-size: 20px;
margin-bottom: 13px;
letter-spacing:2px;
font-weight: 50;
} }
.switch{
span{
cursor: pointer;
color: #9076FF;
}
}
.links{
margin: 20px 0 20px;
}
.ques{
color: #105cb2;
font-size: 14px;
}
.forget{
color: #ffa94e;
font-size: 14px;
} }
</style> </style>

@ -15,15 +15,89 @@
</div> </div>
<!-- 选择期权模式基础+挑战 --> <!-- 选择期权模式基础+挑战 -->
<div class="select_wrap"> <div class="select_wrap">
<div class="select_item" @click="toNext(0)"> <div class="select_item" @click="toEvaluation(1,2)">
<div class="icon_one icon_wrap"><i class="iconfont icon-arrowRight"></i></div> <div class="icon_one icon_wrap"><i class="iconfont icon-arrowRight"></i></div>
<div class="select_title one_title">期权套期保值实验</div> <div class="select_title one_title">期权套期保值实验</div>
</div> </div>
<div class="select_item" @click="toNext(1)"> <div class="select_item" @click="toEvaluation(1,3)">
<div class="icon_two icon_wrap"><i class="iconfont icon-arrowRight"></i></div> <div class="icon_two icon_wrap"><i class="iconfont icon-arrowRight"></i></div>
<div class="select_title two_title">期权组合保险实验</div> <div class="select_title two_title">期权组合保险实验</div>
</div> </div>
</div> </div>
<!-- 答题弹框 -->
<el-dialog :visible.sync="evaluationVisible" width="30%" custom-class="evaluation_dialog" center :close-on-click-modal="false" :append-to-body="true">
<div class="title">能力测评</div>
<div class="content">
<p class="serial">{{question.currentQuestionSortNo}}/{{question.totalQuestionNum}}</p>
<p class="type">({{question.questionTypeName}})</p>
<div class="ques">{{question.questionStem}}</div>
<div class="countdown flex-center">
<img src="../../assets/img/hourglass.png" alt="">
<span>倒计时{{countdown}}</span>
</div>
<ul class="options" :class="{isDone}">
<li v-for="(item,key) in question.options" :key="key" :class="{active: selected.includes(key)}" @click="selectOption(key)"><em>{{key}}.</em><span>{{item}}</span></li>
</ul>
</div>
<div slot="footer" class="dialog-footer" v-if="!isDone">
<template v-if="lastOne">
<el-button @click="prevQues">上一题</el-button>
<el-button type="primary" @click="submitQues">提交</el-button>
</template>
<template v-else>
<el-button class="first" @click="prevQues">上一题</el-button>
<el-button class="second" type="primary" @click="nextQues">下一题</el-button>
</template>
<el-button class="pass" @click="passQues" v-if="passExam">跳过测评</el-button>
</div>
</el-dialog>
<!-- 提交成绩弹框 -->
<el-dialog :visible.sync="resultVisible" width="30%" custom-class="result_dialog" center :close-on-click-modal="false" :append-to-body="true">
<div class="result"><span>{{result.isPassed}}</span></div>
<div class="content">
<div class="point">
<span>{{result.totalScore}}</span>
</div>
<p class="tips">{{result.isPassed == '通过' ? '恭喜' : ''}}你答对{{result.correctQuestionNum}}正确率{{result.correctRate}}</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button class="first" @click="toEvaluation(0)">再试一次</el-button>
<el-button class="second" type="primary" @click="getDetail">成绩详情</el-button>
<el-button v-if="result.isPassed == '通过'" class="third" type="primary" @click="toSonSys">进入实训</el-button>
</div>
</el-dialog>
<!-- 成绩详情弹框 -->
<el-dialog :visible.sync="detailVisible" width="30%" custom-class="detail_dialog" center :close-on-click-modal="false" :append-to-body="true">
<div class="title">成绩详情</div>
<div style="min-height: 370px">
<el-table
:data="detailData"
height="340"
border
style="width: 100%">
<el-table-column type="index" label="序号" width="60" align="center"></el-table-column>
<el-table-column prop="date" label="正误" min-width="45" align="center">
<template slot-scope="scope">
<img v-if="scope.row.questionScore" width="15" src="../../assets/img/true.png" alt="">
<img v-else width="15" src="../../assets/img/false.png" alt="">
</template>
</el-table-column>
<el-table-column prop="questionScore" label="得分" min-width="45" align="center"></el-table-column>
<el-table-column prop="answer" label="正确答案" min-width="70" align="center"></el-table-column>
<el-table-column prop="userAnswer" label="你的答案" min-width="70" align="center"></el-table-column>
<el-table-column prop="answerAnalysis" label="解析" min-width="80"></el-table-column>
</el-table>
</div>
<p class="total">得分{{totalScore}}</p>
</el-dialog>
</div> </div>
</template> </template>
@ -32,11 +106,42 @@ export default {
data() { data() {
return { return {
title:'期权交易虚仿实验', title:'期权交易虚仿实验',
contentText:'本项目构建了面向实战的期权交易场景,让学生面对实际存在的农业生产相关问题,设计交易策略。分为期权套期保值实验和期权组合保险实验,期权套期保值实验为单一期权的实验,需利用一个期权合约对现货进行套期保值;期权组合保险实验为期货期权组合的实验,需利用多个期权的组合满足较为复杂的套期保值需求。' contentText:'本项目构建了面向实战的期权交易场景,让学生面对实际存在的农业生产相关问题,设计交易策略。分为期权套期保值实验和期权组合保险实验,期权套期保值实验为单一期权的实验,需利用一个期权合约对现货进行套期保值;期权组合保险实验为期货期权组合的实验,需利用多个期权的组合满足较为复杂的套期保值需求。',
passExam: [1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513].includes(this.$store.state.studentId),
userId: this.$store.state.userId,
evaluationVisible: false,
resultVisible: false,
detailVisible: false,
lastOne: false,
question: {
options: {}
},
countdown: '',
selected: '',
result: {},
detail: {},
timer: null,
totalScore: 0,
detailData: [],
isDone: false,
history: [],
btnType: 1,
showProject: false,
}; };
}, },
watch: {
question: {
handler(newVal,oldVal) {
for(let n in newVal.options) {
if(newVal.options[n] == '') delete(newVal.options[n])
}
},
deep: true
}
},
mounted(){ mounted(){
console.log(11,this.passExam)
}, },
methods: { methods: {
toIndex() { toIndex() {
@ -48,6 +153,167 @@ export default {
toNext(index) { toNext(index) {
this.$router.push(`ProjectPattern?pattern=${index}`) this.$router.push(`ProjectPattern?pattern=${index}`)
}, },
async toEvaluation(type,btn) {
clearInterval(this.timer)
this.lastOne = false
this.selected = ''
this.resultVisible = false
this.history = []
if(btn) this.btnType = btn
if(type && !this.passExam){
let res = await this.$get(this.api.openExerciseOrTeaching, { userId: this.userId })
if(res.errmessage == 'true'){
this.toNext(this.btnType == 2 ? 0 : 1)
}else{
this.$alert('请先完成能力测评并达到80分以上才可以进行实验', '提示', {
confirmButtonText: '进入测评',
callback: action => {
if(action == 'confirm') this.toEvaluation(0)
}
});
}
}else{
this.start()
this.getCountdown()
}
},
handleQues() {
this.question.options = {}
for(let n in this.question) {
if(n.includes('option') && n != 'options') {
this.question.options[n.replace('option','')] = this.question[n]
}
}
if(this.question.currentQuestionSortNo == this.question.totalQuestionNum){
this.lastOne = true
}else{
this.lastOne = false
}
},
async start() {
let res = await this.$get(this.api.experimentStart, { userId: this.userId,types: this.btnType })
if(res.data){
this.question = res.data
this.isDone = false
this.question.currentQuestionSortNo == 1 && this.$store.commit("answerHistoryData", { answerHistory : []})
this.handleQues()
this.evaluationVisible = true
}else{
this.$message.warning(res.message)
}
},
async getCountdown() {
let res = await this.$get(this.api.experimentRemaining, { userId: this.userId })
res.data && this.countDown(res.data)
// this.countDown('00:00:05')
},
countDown(time) {
this.countdown = time
this.timer = setInterval(() => {
let timeList = this.countdown.split(':')
let total = Number.parseInt(timeList[1] * 60) + Number.parseInt(timeList[2])
if(total > 0){
--total
let minutes = Math.floor(total / 60)
let seconds = Math.floor(total % 60)
this.countdown = `00:${this.core.formateTime(minutes)}:${this.core.formateTime(seconds)}`
}else{
this.isDone = true
this.$message.warning('测评时间结束');
clearInterval(this.timer)
}
},1000)
},
selectOption(option) {
if(!this.isDone) {
if(this.selected.includes(option)) {
this.selected = this.selected.replace(option,'')
}else{
if(this.question.questionType == 2) {
this.selected += option
}else{
this.selected = option
}
}
}
},
getHistory() {
this.history = this.$store.state.answerHistory
},
async nextQues() {
if(!this.selected) return this.$message.warning('请选择答案')
this.getHistory()
if(this.history.length > this.question.currentQuestionSortNo){
this.history[this.question.currentQuestionSortNo-1] = this.selected
}else if(this.history.length < this.question.currentQuestionSortNo){
this.history.push(this.selected)
}
this.$store.commit("answerHistoryData", { answerHistory : this.history})
let res = await this.$post(this.api.experimentNext, {
id: this.question.id,
currentQuestionSortNo: this.question.currentQuestionSortNo,
userAnswer: this.selected
})
if(res.data){
this.question = res.data
this.selected = ''
if(this.history.length >= this.question.currentQuestionSortNo){
this.selected = this.history[this.question.currentQuestionSortNo-1]
}else{
this.selected = ''
}
this.handleQues()
}
},
async prevQues() {
if(this.question.currentQuestionSortNo > 1){
this.getHistory()
let res = await this.$post(this.api.experimentPrevious, {
id: this.question.id,
currentQuestionSortNo: this.question.currentQuestionSortNo,
userAnswer: this.selected
})
if(res.data){
this.question = res.data
this.selected = this.history[this.question.currentQuestionSortNo-1]
this.handleQues()
}
}
},
async submitQues() {
if(!this.selected) return this.$message.warning('请选择答案');
let res = await this.$post(this.api.experimentSubmit, {
id: this.question.id,
currentQuestionSortNo: this.question.currentQuestionSortNo,
userAnswer: this.selected,
userId: this.userId,
types: this.btnType
})
if(res.data) {
this.result = res.data
this.evaluationVisible = false
this.resultVisible = true
}
},
async passQues(){
this.resultVisible = false
this.toNext(this.btnType == 2 ? 0 : 1)
},
async getDetail() {
let res = await this.$get(this.api.experimentDetail, {
evaluationRecordId: this.question.id
})
if(res.data){
this.totalScore = res.data.totalScore
this.detailData = res.data.evaluationDetailVOS
this.resultVisible = false
this.detailVisible = true
}
},
toSonSys() {
this.resultVisible = false
this.toNext(this.btnType == 2 ? 0 : 1)
}
}, },
}; };
</script> </script>
@ -177,4 +443,198 @@ export default {
color: white; color: white;
line-height: 60px; line-height: 60px;
} }
/deep/.el-tabs__item:focus{
outline: none;
box-shadow: none !important;
}
.back_index:hover{
opacity: 0.8;
cursor: pointer;
}
.back_index{
position: fixed;
right: 0px;
top: 48%;
width: 80px;
height: 80px;
background: white;
text-align: center;
z-index: 100;
}
.icon-home{
font-size: 50px;
color: #FF5288;
font-weight: 600;
line-height: 80px;
}
h3{
color: #328aff;
margin-bottom: 10px;
}
.mar0{
margin-top: 0;
}
/deep/.evaluation_dialog{
min-height: 700px;
background: url(../../assets/img/evaluation_bg1.png) 0 0/100% 100% no-repeat;
}
/deep/.evaluation_dialog .el-dialog__headerbtn,/deep/.evaluation_dialog .el-dialog__headerbtn,/deep/.detail_dialog .el-dialog__headerbtn{
font-size: 28px;
}
/deep/.evaluation_dialog .title,/deep/.detail_dialog .title{
margin-bottom: 45px;
text-align: center;
font-size: 24px
}
/deep/.evaluation_dialog .title{
margin-bottom: 55px;
}
/deep/.evaluation_dialog .serial{
font-size: 12px;
text-align: center;
}
/deep/.evaluation_dialog .content{
width: 80%;
margin: 0 auto;
}
/deep/.evaluation_dialog .type{
color: #666;
}
/deep/.evaluation_dialog .ques{
margin: 20px 0;
min-height: 145px;
color: #666;
font-size: 16px;
}
/deep/.evaluation_dialog .countdown{
margin-bottom: 20px;
justify-content: center;
text-align: center;
color: #DC3434;
font-size: 14px;
}
/deep/.evaluation_dialog .countdown img{
width: 15px !important;
margin-right: 10px;
}
/deep/.evaluation_dialog .options{
display: flex;
flex-direction: column;
min-height: 340px;
}
/deep/.evaluation_dialog .options.isDone{
min-height: 395px;
}
/deep/.evaluation_dialog .options li{
padding: 0 15px;
margin-bottom: 15px;
line-height: 40px;
border: 1px solid #9070FF;
border-radius: 20px;
color: #666;
cursor: pointer;
}
/deep/.evaluation_dialog .options li:hover{
color: #fff;
background-color: #b038bb;
border-color: #b038bb;
}
/deep/.evaluation_dialog .options li.active{
color: #fff;
background-color: #916CFF;
border-color: #916CFF;
}
/deep/.evaluation_dialog .options em{
margin-right: 10px;
font-weight: bold;
font-style: normal;
font-size: 16px;
}
/deep/.evaluation_dialog .options span{
font-size: 16px;
}
/deep/.evaluation_dialog .el-dialog__footer{
text-align: center;
}
/deep/.evaluation_dialog .first,/deep/.result_dialog .first{
color: #fff;
background-color: #9268FF;
border-color: #9268FF;
}
/deep/.evaluation_dialog .second,/deep/.result_dialog .second{
color: #fff;
background-color: #E371DA;
border-color: #E371DA;
}
/deep/.evaluation_dialog .pass,/deep/.result_dialog .pass{
color: #fff;
background-color: #e42c85;
border-color: #e42c85;
}
/deep/.result_dialog{
min-height: 500px;
background: url(../../assets/img/evaluation_bg2.png) 0 0/100% 100% no-repeat;
}
/deep/.result_dialog .el-dialog__headerbtn .el-dialog__close{
color: #5a5a5a;
font-size: 28px;
}
/deep/.result_dialog .result{
margin-top: 60px;
text-align: center;
color: #fff;
font-size: 24px;
}
/deep/.result_dialog .point{
margin: 30px 0 20px;
text-align: center;
font-size: 30px;
color: #666;
}
/deep/.result_dialog .point span{
font-size: 120px;
font-weight: bold;
}
/deep/.result_dialog .tips{
color: #666;
text-align: center;
font-size: 14px;
}
/deep/.result_dialog .third{
color: #fff;
background-color: #418cf5;
border-color: #418cf5;
}
/deep/.detail_dialog{
background: url(../../assets/img/evaluation_bg3.png) 0 0/100% 100% no-repeat;
}
/deep/.detail_dialog .title{
margin-top: -20px;
}
/deep/.detail_dialog .el-table__header th:nth-last-child(2){
text-align: center;
}
/deep/.detail_dialog .total{
margin-top: 20px;
text-align: center;
font-size: 30px;
color: #DC3434;
}
/deep/.evaluation_dialog{
margin:0 !important;
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
max-height:calc(100% - 30px);
max-width:calc(100% - 30px);
}
/deep/.evaluation_dialog .el-dialog__body{
flex:1;
overflow: auto;
}
</style> </style>

@ -25,11 +25,11 @@
</div> </div>
</div> </div>
<div class="pattern_wrap"> <div class="pattern_wrap">
<div class="img_wrap" @click="toEvaluation(1,2)"> <div class="img_wrap" @click="toPrac">
<div><img src="../../assets/img/buttonOne.png" alt=""></div> <div><img src="../../assets/img/buttonOne.png" alt=""></div>
<div>练习模式</div> <div>练习模式</div>
</div> </div>
<div class="img_wrap" @click="toEvaluation(1,3)"> <div class="img_wrap" @click="toNext(4)">
<div><img src="../../assets/img/buttonTwo.png" alt=""></div> <div><img src="../../assets/img/buttonTwo.png" alt=""></div>
<div>考核模式</div> <div>考核模式</div>
</div> </div>
@ -40,78 +40,6 @@
</div> </div>
</div> </div>
<div class="back_index" @click="toIndex"><i class="iconfont icon-home"></i></div> <div class="back_index" @click="toIndex"><i class="iconfont icon-home"></i></div>
<!-- 答题弹框 -->
<el-dialog :visible.sync="evaluationVisible" width="30%" custom-class="evaluation_dialog" center :close-on-click-modal="false">
<div class="title">能力测评</div>
<div class="content">
<p class="serial">{{question.currentQuestionSortNo}}/{{question.totalQuestionNum}}</p>
<p class="type">({{question.questionTypeName}})</p>
<div class="ques">{{question.questionStem}}</div>
<div class="countdown flex-center">
<img src="../../assets/img/hourglass.png" alt="">
<span>倒计时{{countdown}}</span>
</div>
<ul class="options" :class="{isDone}">
<li v-for="(item,key) in question.options" :key="key" :class="{active: selected.includes(key)}" @click="selectOption(key)"><em>{{key}}.</em><span>{{item}}</span></li>
</ul>
</div>
<div slot="footer" class="dialog-footer" v-if="!isDone">
<template v-if="lastOne">
<el-button @click="prevQues">上一题</el-button>
<el-button type="primary" @click="submitQues">提交</el-button>
</template>
<template v-else>
<el-button class="first" @click="prevQues">上一题</el-button>
<el-button class="second" type="primary" @click="nextQues">下一题</el-button>
</template>
</div>
</el-dialog>
<!-- 提交成绩弹框 -->
<el-dialog :visible.sync="resultVisible" width="30%" custom-class="result_dialog" center :close-on-click-modal="false">
<div class="result"><span>{{result.isPassed}}</span></div>
<div class="content">
<div class="point">
<span>{{result.totalScore}}</span>
</div>
<p class="tips">{{result.isPassed == '通过' ? '恭喜' : ''}}你答对{{result.correctQuestionNum}}正确率{{result.correctRate}}</p>
</div>
<div slot="footer" class="dialog-footer">
<el-button class="first" @click="toEvaluation(0)">再试一次</el-button>
<el-button class="second" type="primary" @click="getDetail">成绩详情</el-button>
<el-button v-if="result.isPassed == '通过'" class="third" type="primary" @click="toSonSys">进入实训</el-button>
</div>
</el-dialog>
<!-- 成绩详情弹框 -->
<el-dialog :visible.sync="detailVisible" width="30%" custom-class="detail_dialog" center :close-on-click-modal="false">
<div class="title">成绩详情</div>
<div style="min-height: 370px">
<el-table
:data="detailData"
height="340"
border
style="width: 100%">
<el-table-column type="index" label="序号" width="60" align="center"></el-table-column>
<el-table-column prop="date" label="正误" min-width="45" align="center">
<template slot-scope="scope">
<img v-if="scope.row.questionScore" width="15" src="../../assets/img/true.png" alt="">
<img v-else width="15" src="../../assets/img/false.png" alt="">
</template>
</el-table-column>
<el-table-column prop="questionScore" label="得分" min-width="45" align="center"></el-table-column>
<el-table-column prop="answer" label="正确答案" min-width="70" align="center"></el-table-column>
<el-table-column prop="userAnswer" label="你的答案" min-width="70" align="center"></el-table-column>
<el-table-column prop="answerAnalysis" label="解析" min-width="80"></el-table-column>
</el-table>
</div>
<p class="total">得分{{totalScore}}</p>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
@ -132,38 +60,8 @@ export default {
step:'1.关于delta动态调仓的实验背景;2.关于交叉对冲的实验背景;3.实验案例;4.最优对冲比率计算;5.合约选择;6.期权组合开仓;7.期权组合调仓;8.期权组合平仓;9.核算损益;10.填写实验报告;', step:'1.关于delta动态调仓的实验背景;2.关于交叉对冲的实验背景;3.实验案例;4.最优对冲比率计算;5.合约选择;6.期权组合开仓;7.期权组合调仓;8.期权组合平仓;9.核算损益;10.填写实验报告;',
prepare:'开始实验前,应了解期权定义、期权交易规则、希腊字母delta、交叉对冲和不同期权组合策略的盈亏图。' prepare:'开始实验前,应了解期权定义、期权交易规则、希腊字母delta、交叉对冲和不同期权组合策略的盈亏图。'
}], }],
userId: this.$store.state.userId,
evaluationVisible: false,
resultVisible: false,
detailVisible: false,
lastOne: false,
question: {
options: {}
},
countdown: '',
selected: '',
result: {},
detail: {},
timer: null,
totalScore: 0,
detailData: [],
isDone: false,
history: [],
btnType: 1,
showProject: false,
lastClick: '',
}; };
}, },
watch: {
question: {
handler(newVal,oldVal) {
for(let n in newVal.options) {
if(newVal.options[n] == '') delete(newVal.options[n])
}
},
deep: true
}
},
mounted(){ mounted(){
this.patternId = this.$route.query.type this.patternId = this.$route.query.type
}, },
@ -171,187 +69,14 @@ export default {
toIndex() { toIndex() {
this.$router.push('dashboard') this.$router.push('dashboard')
}, },
toPrac(){
this.core.toSubSystem('','','',this.pattern)
},
toNext(index) { toNext(index) {
sessionStorage.setItem('pattern',this.pattern) sessionStorage.setItem('pattern',this.pattern)
this.$router.push(`dashboard#${index}`) this.$router.push(`dashboard#${index}`)
}, },
async toEvaluation(type,btn) {
clearInterval(this.timer)
this.lastOne = false
this.selected = ''
this.resultVisible = false
this.history = []
if(btn) this.btnType = btn
if(type){
let res = null
if(btn == 2){
res = await this.$get(this.api.openExerciseOrTeaching, { userId: this.userId })
}else{
res = await this.$get(this.api.openExerciseOrTeaching, { userId: this.userId })
}
// return
if(res.errmessage == 'true'){
if(btn == 2){
this.core.toSubSystem('','','',this.pattern)
}
if(btn == 3){
this.toNext(4)
}
}else{
this.activeName = this.lastClick
this.$alert('请先完成能力测评并达到80分以上才可以进行实验', '提示', {
confirmButtonText: '进入测评',
callback: action => {
if(action == 'confirm'){
this.toEvaluation(0)
}else{
// this.activeName = btn == 2 ? 'second' : 'third'
}
}
});
}
}else{
this.start()
this.getCountdown()
}
},
handleQues() {
this.question.options = {}
for(let n in this.question) {
if(n.includes('option') && n != 'options') {
this.question.options[n.replace('option','')] = this.question[n]
}
}
if(this.question.currentQuestionSortNo == this.question.totalQuestionNum){
this.lastOne = true
}else{
this.lastOne = false
}
},
async start() {
let res = await this.$get(this.api.experimentStart, { userId: this.userId,types: this.btnType })
if(res.data){
this.question = res.data
this.isDone = false
this.question.currentQuestionSortNo == 1 && this.$store.commit("answerHistoryData", { answerHistory : []})
this.handleQues()
this.evaluationVisible = true
}else{
this.$message.warning(res.message)
}
},
async getCountdown() {
let res = await this.$get(this.api.experimentRemaining, { userId: this.userId })
res.data && this.countDown(res.data)
// this.countDown('00:00:05')
},
countDown(time) {
this.countdown = time
this.timer = setInterval(() => {
let timeList = this.countdown.split(':')
let total = Number.parseInt(timeList[1] * 60) + Number.parseInt(timeList[2])
if(total > 0){
--total
let minutes = Math.floor(total / 60)
let seconds = Math.floor(total % 60)
this.countdown = `00:${this.core.formateTime(minutes)}:${this.core.formateTime(seconds)}`
}else{
this.isDone = true
this.$message.warning('测评时间结束');
clearInterval(this.timer)
}
},1000)
},
selectOption(option) {
if(!this.isDone) {
if(this.selected.includes(option)) {
this.selected = this.selected.replace(option,'')
}else{
if(this.question.questionType == 2) {
this.selected += option
}else{
this.selected = option
}
}
}
},
getHistory() {
this.history = this.$store.state.answerHistory
},
async nextQues() {
if(!this.selected) return this.$message.warning('请选择答案')
this.getHistory()
if(this.history.length > this.question.currentQuestionSortNo){
this.history[this.question.currentQuestionSortNo-1] = this.selected
}else if(this.history.length < this.question.currentQuestionSortNo){
this.history.push(this.selected)
}
this.$store.commit("answerHistoryData", { answerHistory : this.history})
let res = await this.$post(this.api.experimentNext, {
id: this.question.id,
currentQuestionSortNo: this.question.currentQuestionSortNo,
userAnswer: this.selected
})
if(res.data){
this.question = res.data
this.selected = ''
if(this.history.length >= this.question.currentQuestionSortNo){
this.selected = this.history[this.question.currentQuestionSortNo-1]
}else{
this.selected = ''
}
this.handleQues()
}
},
async prevQues() {
if(this.question.currentQuestionSortNo > 1){
this.getHistory()
let res = await this.$post(this.api.experimentPrevious, {
id: this.question.id,
currentQuestionSortNo: this.question.currentQuestionSortNo,
userAnswer: this.selected
})
if(res.data){
this.question = res.data
this.selected = this.history[this.question.currentQuestionSortNo-1]
this.handleQues()
}
}
},
async submitQues() {
if(!this.selected) return this.$message.warning('请选择答案');
let res = await this.$post(this.api.experimentSubmit, {
id: this.question.id,
currentQuestionSortNo: this.question.currentQuestionSortNo,
userAnswer: this.selected,
userId: this.userId,
types: this.btnType
})
if(res.data) {
this.result = res.data
this.evaluationVisible = false
this.resultVisible = true
}
},
async getDetail() {
let res = await this.$get(this.api.experimentDetail, {
evaluationRecordId: this.question.id
})
if(res.data){
this.totalScore = res.data.totalScore
this.detailData = res.data.evaluationDetailVOS
this.resultVisible = false
this.detailVisible = true
}
},
toSonSys() {
if(this.btnType == 2){
this.core.toSubSystem('','','',this.pattern)
}else if(this.btnType == 3){
this.resultVisible = false
this.toNext(4)
}
}
}, },
}; };
</script> </script>
@ -463,193 +188,4 @@ export default {
height: 320px; height: 320px;
} }
} }
/deep/.el-tabs__item:focus{
outline: none;
box-shadow: none !important;
}
.back_index:hover{
opacity: 0.8;
cursor: pointer;
}
.back_index{
position: fixed;
right: 0px;
top: 48%;
width: 80px;
height: 80px;
background: white;
text-align: center;
z-index: 100;
}
.icon-home{
font-size: 50px;
color: #FF5288;
font-weight: 600;
line-height: 80px;
}
h3{
color: #328aff;
margin-bottom: 10px;
}
.mar0{
margin-top: 0;
}
/deep/.evaluation_dialog{
min-height: 700px;
background: url(../../assets/img/evaluation_bg1.png) 0 0/100% 100% no-repeat;
}
/deep/.evaluation_dialog .el-dialog__headerbtn,/deep/.evaluation_dialog .el-dialog__headerbtn,/deep/.detail_dialog .el-dialog__headerbtn{
font-size: 28px;
}
/deep/.evaluation_dialog .title,/deep/.detail_dialog .title{
margin-bottom: 45px;
text-align: center;
font-size: 24px
}
/deep/.evaluation_dialog .title{
margin-bottom: 55px;
}
/deep/.evaluation_dialog .serial{
font-size: 12px;
text-align: center;
}
/deep/.evaluation_dialog .content{
width: 80%;
margin: 0 auto;
}
/deep/.evaluation_dialog .type{
color: #666;
}
/deep/.evaluation_dialog .ques{
margin: 20px 0;
min-height: 145px;
color: #666;
font-size: 16px;
}
/deep/.evaluation_dialog .countdown{
margin-bottom: 20px;
justify-content: center;
text-align: center;
color: #DC3434;
font-size: 14px;
}
/deep/.evaluation_dialog .countdown img{
width: 15px !important;
margin-right: 10px;
}
/deep/.evaluation_dialog .options{
display: flex;
flex-direction: column;
min-height: 340px;
}
/deep/.evaluation_dialog .options.isDone{
min-height: 395px;
}
/deep/.evaluation_dialog .options li{
padding: 0 15px;
margin-bottom: 15px;
line-height: 40px;
border: 1px solid #9070FF;
border-radius: 20px;
color: #666;
cursor: pointer;
}
/deep/.evaluation_dialog .options li:hover{
color: #fff;
background-color: #b038bb;
border-color: #b038bb;
}
/deep/.evaluation_dialog .options li.active{
color: #fff;
background-color: #916CFF;
border-color: #916CFF;
}
/deep/.evaluation_dialog .options em{
margin-right: 10px;
font-weight: bold;
font-style: normal;
font-size: 16px;
}
/deep/.evaluation_dialog .options span{
font-size: 16px;
}
/deep/.evaluation_dialog .el-dialog__footer{
text-align: center;
}
/deep/.evaluation_dialog .first,/deep/.result_dialog .first{
color: #fff;
background-color: #9268FF;
border-color: #9268FF;
}
/deep/.evaluation_dialog .second,/deep/.result_dialog .second{
color: #fff;
background-color: #E371DA;
border-color: #E371DA;
}
/deep/.result_dialog{
min-height: 500px;
background: url(../../assets/img/evaluation_bg2.png) 0 0/100% 100% no-repeat;
}
/deep/.result_dialog .el-dialog__headerbtn .el-dialog__close{
color: #5a5a5a;
font-size: 28px;
}
/deep/.result_dialog .result{
margin-top: 60px;
text-align: center;
color: #fff;
font-size: 24px;
}
/deep/.result_dialog .point{
margin: 30px 0 20px;
text-align: center;
font-size: 30px;
color: #666;
}
/deep/.result_dialog .point span{
font-size: 120px;
font-weight: bold;
}
/deep/.result_dialog .tips{
color: #666;
text-align: center;
font-size: 14px;
}
/deep/.result_dialog .third{
color: #fff;
background-color: #418cf5;
border-color: #418cf5;
}
/deep/.detail_dialog{
background: url(../../assets/img/evaluation_bg3.png) 0 0/100% 100% no-repeat;
}
/deep/.detail_dialog .title{
margin-top: -20px;
}
/deep/.detail_dialog .el-table__header th:nth-last-child(2){
text-align: center;
}
/deep/.detail_dialog .total{
margin-top: 20px;
text-align: center;
font-size: 30px;
color: #DC3434;
}
/deep/.evaluation_dialog{
margin:0 !important;
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
max-height:calc(100% - 30px);
max-width:calc(100% - 30px);
}
/deep/.evaluation_dialog .el-dialog__body{
flex:1;
overflow: auto;
}
</style> </style>

@ -76,6 +76,11 @@ export default new Router({
component: () => import(/* webpackChunkName: "login" */ '../components/page/Login.vue'), component: () => import(/* webpackChunkName: "login" */ '../components/page/Login.vue'),
meta: { title: '登录' } meta: { title: '登录' }
}, },
{
path: '/clientLogin',
component: () => import(/* webpackChunkName: "login" */ '../components/page/ClientLogin.vue'),
meta: { title: '首页' }
},
{ {
path: '*', path: '*',
redirect: '/404' redirect: '/404'

@ -10,6 +10,7 @@ if(process.env.NODE_ENV === 'development'){
export default { export default {
logins: `${host}/liuwanr/userInfo/logins`, //登录  logins: `${host}/liuwanr/userInfo/logins`, //登录 
getAccountPassword: `${host}/evaluation/tms/userInfo/getAccountPassword`, //获取账号密码
queryToken: `${host}/liuwanr/userInfo/queryToken`, queryToken: `${host}/liuwanr/userInfo/queryToken`,
save: `${host}/evaluation/tms/userInfo/add`, //注册 save: `${host}/evaluation/tms/userInfo/add`, //注册
updateLogInNumber: `${host}/liuwanr/userInfo/updateLogInNumber`, //用户登录修改登录次数和登陆时间 updateLogInNumber: `${host}/liuwanr/userInfo/updateLogInNumber`, //用户登录修改登录次数和登陆时间

Loading…
Cancel
Save