山东大学项目实训Web实验室(WebLab)(四)界面
前言
项目仓库
本项目是为开发一套容器化的开发、运行、测试环境,用以支持Web开发、程序设计等课程的实验教学。
任务目标
设计并且编写主界面
主界面内容:
- 代码编写界面
- 代码显示界面
- 代码提交及刷结果按钮
- 导航条
代码
views/login-view.vue
<!--登录界面-->
<template>
<div class="login-wrap">
<el-form
ref="loginFormRef"
:model="loginForm"
:rules="loginRules"
class="login-container"
label-position="right"
label-width="80px"
>
<h1 class="title">登录</h1>
<el-form-item label="用户账号" prop="userid">
<el-input v-model="loginForm.userid" placeholder="请输入账号" />
</el-form-item>
<el-form-item label="用户密码" prop="pass">
<el-input v-model="loginForm.pass" type="password" placeholder="请输入密码" show-password />
</el-form-item>
<el-form-item label-width="0px">
<el-button type="primary" @click="doLogin()" style="width: 100%;">用户登录</el-button>
</el-form-item>
<el-row :gutter="20" style="text-align: center;">
<el-col :span="5">
<div class="grid-content"></div>
</el-col>
<el-col :span="6">
<el-link @click="gotoRegister()">用户注册</el-link>
</el-col>
<el-col :span="1">
<div class="grid-content"></div>
</el-col>
<el-col :span="6">
<el-link @click="gotoForget()">忘记密码</el-link>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script lang="ts">
import { ref, defineComponent, reactive, unref } from 'vue'
import { useRouter } from "vue-router";
import CharacterVerification from '../components/CharacterVerification.vue';
import { ElMessage } from 'element-plus';
import { useLoginStore } from '@/stores/store';
import { request } from "@/network/request";
export default defineComponent({
components: { CharacterVerification },
setup() {
const store = useLoginStore();
const router = useRouter();
const loginFormRef = ref();
const ver = ref();
//表单内容
const loginForm = reactive({
userid: '',
pass: '',
checkCode: ''
})
//自定义表单验证
const validatePass = (rule: any, value: any, callback: any) => {
//const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
if (!reg.test(value)) {
callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
}
callback();
}
// 定义校验规则
const loginRules = reactive({
userid: [
{ required: true, message: '用户账号不能为空', trigger: 'blur' },
],
pass: [
{ required: true, message: '密码不能为空', trigger: 'blur' },
{ min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
{ validator: validatePass, trigger: 'blur' }
],
checkCode: [
{ required: true, message: '验证码不能为空', trigger: 'blur' },
{ validator: validateVerificationCode, trigger: 'blur' }
]
})
function gotoForget() {
router.push({ path: '/forget_password' });
}
function gotoRegister() {
router.push({ path: '/register' });
}
const doLogin = async () => {
const form = unref(loginFormRef);
if (!form) return
try {
await form.validate();
const { userid, pass } = loginForm;
console.log(userid, pass);
//todo: 发送登录请求
let param = new FormData();
param.append('username ', userid);
param.append('password', pass);
request('/weblab/user/login', param)
.then(res => {
console.log(res.data);
if (res.status == 200) {
const token = res.data.pkg;
store.userLogin(userid, pass, token);
router.push('/login_home');
}
})
.catch(error => {
console.log(error);
})
} catch (error: any) {
ElMessage({
showClose: true,
message: '输入格式不正确',
type: 'error',
center: true,
grouping: true,
})
}
}
return {
ver,
loginFormRef,
loginForm,
loginRules,
gotoForget,
gotoRegister,
doLogin,
}
},
})
</script>
<style>
.login-wrap {
box-sizing: border-box;
width: 100%;
height: 100%;
padding-top: 10%;
}
.login-container {
border-radius: 10px;
margin: 0px auto;
width: 350px;
padding: 30px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
text-align: left;
box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1);
}
.title {
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
</style>
views/register-view.vue
<!--注册界面-->
<template>
<div class="login-wrap">
<el-form
ref="registerFormRef"
class="login-container"
:model="registerForm"
:rules="registerRules"
label-position="right"
label-width="80px"
>
<h1 class="title">注册</h1>
<el-form-item label="用户名称" prop="username">
<el-input type="text" placeholder="请输入名称" v-model="registerForm.username"></el-input>
</el-form-item>
<el-form-item label="用户邮箱" prop="useremail">
<el-input type="email" placeholder="请输入邮箱" v-model="registerForm.useremail" size="default"></el-input>
</el-form-item>
<el-form-item label="用户密码" prop="pass">
<el-tooltip content="<span>长度为8~15位,必须同时包含大小写字母及数字</span>" raw-content>
<el-input v-model="registerForm.pass" type="password" placeholder="请输入密码" show-password />
</el-tooltip>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input
v-model="registerForm.checkPass"
type="password"
placeholder="请再次输入密码"
show-password
/>
</el-form-item>
<el-form-item label="验证码">//(肖同学完成)
<el-input
v-model="registerForm.checkCode"
type="text"
placeholder="请输入验证码"
input="value=value.replace(/[^\d]/g,'')"
maxlength="6"
>
<template #append>
<el-button @click="getCheckCode" :disabled="checkBtnDisabled">{{ btnInfo }}</el-button>
</template>
</el-input>
</el-form-item>
<!-- <el-form-item label-width="100px">
<CharacterVerification ref="ver"></CharacterVerification>
</el-form-item>-->
<el-form-item label-width="0px">
<el-button
type="primary"
:disabled="registerBtnDisabled"
@click="registerUser()"
style="width: 48%;"
>用户注册</el-button>
<el-button style="width: 48%;" @click="gotoLogin()">返回登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script lang="ts">
import { useRouter } from "vue-router";
import { ref, defineComponent, reactive, unref } from 'vue';
import CharacterVerification from '../components/CharacterVerification.vue';
import { ElMessage } from "element-plus";
import { useLoginStore } from "@/stores/store";
import { request } from "@/network/request";
export default defineComponent({
components: { CharacterVerification },
setup() {
const registerBtnDisabled = ref(false);
const checkBtnDisabled = ref(false);
const store = useLoginStore();
const router = useRouter();
let waitTime = 60;
const btnInfo = ref('获取邮箱验证码');
//表单内容
const registerForm = reactive({
username: '',
useremail: '',
pass: '',
checkPass: '',
checkCode: ''
})
const registerFormRef = ref();
const ver = ref();
// 自定义验证规则(肖同学完成)
const validatePass = (rule: any, value: any, callback: any) => {
const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
if (!reg.test(value)) {
callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
}
if (registerForm.checkPass != null && registerForm.checkPass !== '') {
if (!registerFormRef.value) return
registerFormRef.value.validateField('checkPass', () => null)
}
callback();
}
const validateCheckPass = (rule: any, value: any, callback: any) => {
const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
if (value !== registerForm.pass) {
callback(new Error('输入密码不一致'));
}
if (!reg.test(value)) {
callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
}
callback();
}
// 定义校验规则
const registerRules = reactive({
username: [
{ required: true, message: '用户名称不能为空', trigger: 'blur' },
{ min: 2, max: 32, message: '名称长度只能在2~32之间', trigger: 'blur' }
],
useremail: [
{ required: true, message: '邮箱不能为空', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
],
pass: [
{ required: true, message: '密码不能为空', trigger: 'blur' },
{ min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ required: true, message: '密码不能为空', trigger: 'blur' },
{ min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
{ validator: validateCheckPass, trigger: 'blur' }
],
})
function timer() {
if (waitTime == 0) {
checkBtnDisabled.value = false;
btnInfo.value = '获取邮箱验证码'
waitTime = 60;
} else {
btnInfo.value = `${waitTime}秒后重试`;
waitTime--;
setTimeout(timer, 1000);
}
}
const getCheckCode = async () => {
const form = unref(registerFormRef);
if (!form) return
try {
await form.validate();
checkBtnDisabled.value = true;
timer();
registerForm.checkCode = '';
const { username, useremail, pass } = registerForm;
//发送注册请求(肖同学完成)
let param = new FormData();
param.append('email', useremail);
param.append('username', username);
param.append('password', pass);
request('/weblab/user/register', param)
.then((res) => {
console.log(res);
console.log(res.data);
console.log(res.status);
console.log(res.data.msg);
if (res.status == 200) {
console.log('发送注册请求...');
}
})
.catch(error => {
console.log(error);
})
} catch (error: any) {
ElMessage({
showClose: true,
message: '输入格式不正确',
type: 'error',
center: true,
grouping: true,
})
}
}
const registerUser = async () => {
const form = unref(registerFormRef);
if (!form) return
try {
await form.validate();
//发送验证码激活请求(肖同学完成)
const checkCode:string=registerForm.checkCode;
let param = new FormData();
param.append('code', checkCode);
console.log(typeof checkCode);
request('/weblab/user/activation', param)
.then((res) => {
console.log(res);
console.log(res.data);
console.log(res.status);
if (res.status == 200 && res.data.msg == 'success') {
registerBtnDisabled.value = true;
ElMessage({
showClose: true,
message: '注册成功',
type: 'success',
center: true,
grouping: true,
onClose: () => { router.push({ path: "/login" }); }
})
} else {
ElMessage({
showClose: true,
message: '验证码错误',
type: 'error',
center: true,
grouping: true,
})
}
})
.catch(error => {
console.log(error);
})
} catch (error: any) {
ElMessage({
showClose: true,
message: '输入格式不正确',
type: 'error',
center: true,
grouping: true,
})
}
}
function gotoLogin() {
router.push({ path: "/login" });
}
return {
registerBtnDisabled,
checkBtnDisabled,
ver,
btnInfo,
registerFormRef,
registerForm,
registerRules,
registerUser,
gotoLogin,
getCheckCode,
}
}
})
</script>
<style>
.login-wrap {
box-sizing: border-box;
width: 100%;
height: 100%;
padding-top: 10%;
}
.login-container {
border-radius: 10px;
margin: 0px auto;
width: 350px;
padding: 30px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
text-align: left;
box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1);
}
.title {
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
</style>