搭建完前端脚手架之后,让我们来安装一些必要的包和配置axios。
源码部分文件,百度云分享链接:
链接:https://pan.baidu.com/s/141k9nU3AfDTW3MW-7lziaw
提取码:9ycn
步骤1:删除脚手架初始化不必要的文件
删除components和路径下HelloWorld.vue
步骤2:安装vue-router、elementUI,axios
1-vue-router, npm install vue-router
2-elementUI,npm install element-ui
3-axios,npm install axios
步骤3:新增的以下部分内容。主要为styles和store,以及部分图片
步骤4:配置vue-router、elementUI,axios
配置vue-router:
src目录下新建router目录,目录内新建index.js
index.js源码
import Vue from 'vue'
import Router from 'vue-router'
import Register from '@/pages/auth/Register'
Vue.use(Router);
export default new Router({
mode:'history',
routes: [
{
path: '/register',
name: 'Register',
component: Register,
meta: {
title: '用户注册'
}
},
]
})
配置elementUI:
更新src同级目录下的main.js
main.js源码
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
import router from './router'
import './assets/styles/iconfont.css'
import './assets/styles/swagger.css'
import './assets/styles/tree.css'
import './assets/styles/home.css'
import './assets/styles/reports.css'
import * as api from './restful/api'
import store from './store'
Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.prototype.$api = api
Vue.filter('datetimeFormat', function (time, format = 'YY-MM-DD hh:mm:ss') {
let date = new Date(time);
let year = date.getFullYear(),
month = date.getMonth() + 1,
day = date.getDate(),
hour = date.getHours(),
min = date.getMinutes(),
sec = date.getSeconds();
let preArr = Array.apply(null, Array(10)).map(function (elem, index) {
return '0' + index;
});
let newTime = format.replace(/YY/g, year)
.replace(/MM/g, preArr[month] || month)
.replace(/DD/g, preArr[day] || day)
.replace(/hh/g, preArr[hour] || hour)
.replace(/mm/g, preArr[min] || min)
.replace(/ss/g, preArr[sec] || sec);
return newTime;
});
Vue.filter("timestampToTime", function (timestamp) {
let date = new Date(timestamp * 1000);
const Y = date.getFullYear() + '-';
const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
const D = date.getDate() + ' ';
const h = date.getHours() + ':';
const m = date.getMinutes() + ':';
const s = date.getSeconds();
return Y + M + D + h + m + s;
});
Vue.prototype.setLocalValue = function (name, value) {
if (window.localStorage) {
localStorage.setItem(name, value);
} else {
alert('This browser does NOT support localStorage');
}
};
Vue.prototype.getLocalValue = function (name) {
const value = localStorage.getItem(name);
if (value) {
return value;
} else {
return '';
}
};
router.beforeEach((to, from, next) => {
/* 路由发生变化修改页面title */
setTimeout((res) => {
if (to.meta.title) {
document.title = to.meta.title
}
if (to.meta.requireAuth) {
if (store.state.token !== '') {
next();
} else {
next({
name: 'Login',
})
}
} else {
next()
}
})
})
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: {App},
template: '<App/>',
created() {
if (this.getLocalValue("token") === null) {
this.setLocalValue("token", "");
}
if (this.getLocalValue("user") === null) {
this.setLocalValue("user", "");
}
if (this.getLocalValue("routerName") === null) {
this.setLocalValue("routerName", "ProjectList");
}
this.$store.commit("isLogin", this.getLocalValue("token"));
this.$store.commit("setUser", this.getLocalValue("user"));
this.$store.commit("setRouterName", this.getLocalValue("routerName"));
}
})
配置axios:
src目录下新建restful目录,目录内新建api.js
api.js源码。请注意解决跨域问题的关键要注释withCredentials ****
// axios.defaults.withCredentials = true; 或者改成
axios.defaults.withCredentials = false;
import axios from 'axios'
import store from '../store/state'
import router from '../router'
import {Message} from 'element-ui';
export const baseUrl = "http://127.0.0.1:7000";
// axios.defaults.withCredentials = true;
axios.defaults.baseURL = baseUrl;
axios.interceptors.request.use(function (config) {
if (config.url.indexOf("/api/aiotest/project/?cursor=") !== -1 ) {
}
else if (!config.url.startsWith("/api/user/")) {
config.url = config.url + "?token=" + store.token;
}
return config;
}, function (error) {
return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
return response;
}, function (error) {
try {
if (error.response.status === 401) {
router.replace({
name: 'Login'
})
}
if (error.response.status === 500) {
Message.error({
message: '服务器内部异常, 请检查',
duration: 1000
})
}
}
catch (e) {
Message.error({
message: '服务器连接超时,请重试',
duration: 1000
})
}
});
// user api
export const register = params => {
return axios.post('/api/user/register/', params).then(res => res.data)
};
步骤5:新增register组件和页面。
src目录下新建pages目录,pages下新建auth目录,分别在auth目录内部和auth同级内分别新增Register.vue和Register.vue
详情见下图:
此处请注意,目录可能无法正常创建。如遇到请关闭vscode打开win10前往目录auth目录,vscode新增首个目录可能有bug,无法多层创建并平行增加。
新增内部auth/Register.vue,源码
<template>
<el-container class="login">
<el-header>
<el-row>
<el-col
:span="4"
:offset="1"
>
<div>
</div>
</el-col>
</el-row>
</el-header>
<el-main style="padding: 0px">
<el-row>
<el-col :span="7">
<div class="bottom-left">
<img src="~@/assets/images/bottom-left.png">
</div>
</el-col>
<el-col :span="24">
<div>
<div id="form-title">接口测试平台</div>
<form id="submit-form">
<div id="form-content">
<div id="form-msg">注册账号</div>
<div id="form-inputs">
<div class="form-input-div">
<i class="iconfont"
style="position: absolute; bottom: 375px; padding-left: 10px"></i>
<input placeholder="用户名或邮箱" type="text" id="user"
v-model="registerForm.username">
<div class="err_msg" id="user_err" v-html="usernameInvalid"
@mouseover="usernameInvalid=''"></div>
</div>
<div class="form-input-div">
<i class="iconfont"
style="position: absolute; bottom: 312px; padding-left: 10px"></i>
<input placeholder="密码" type="password" id="pwd"
v-model="registerForm.password">
<div class="err_msg" id="pwd_err" v-html="passwordInvalid"
@mouseover="passwordInvalid= ''"></div>
</div>
<div class="form-input-div">
<i class="iconfont"
style="position: absolute; bottom: 250px; padding-left: 10px"></i>
<input placeholder="确认密码" type="password" id="repwd" v-model="registerForm.repwd">
<div class="err_msg" id="repwd_err" v-html="repwdInvalid"
@mouseover="repwdInvalid= ''"></div>
</div>
<div class="form-input-div">
<i class="iconfont"
style="position: absolute; bottom: 190px; padding-left: 10px"></i>
<input placeholder="邮箱" type="email" id="email" v-model="registerForm.email">
<div class="err_msg" id="email_err" v-html="emailInvalid"
@mouseover="emailInvalid= ''"></div>
</div>
<div class="form-submit">
<button type="button" class="btn btn-primary" id="submitBtn"
@click="submitForm">立即注册
</button>
</div>
</div>
<div class="form-foot">
<span>已有账户,<router-link to="/login">立即登陆</router-link></span>
</div>
</div>
</form>
</div>
</el-col>
<el-col :span="7">
<div class="bottom-right">
<img src="~@/assets/images/bottom-right.png">
</div>
</el-col>
</el-row>
</el-main>
</el-container>
</template>
<script>
export default {
name: "Register",
data() {
return {
registerForm: {
username: '',
password: '',
repwd: '',
email: ''
},
passwordInvalid: "",
usernameInvalid: '',
repwdInvalid: '',
emailInvalid: ''
};
},
methods: {
validateUser() {
const uPattern = /^[a-zA-Z0-9_-]{4,16}$/;
if (!uPattern.test(this.registerForm.username)) {
this.usernameInvalid = '用户名4到16位,只能是字母,数字,下划线,连字符';
return false
}
return true
},
validatePassword() {
const pPattern = /^[a-zA-Z\d_]{6,}$/;
if (!pPattern.test(this.registerForm.password)) {
this.passwordInvalid = "密码至少6位数";
return false
}
return true
},
validateRepwd() {
if (this.registerForm.password !== this.registerForm.repwd) {
this.repwdInvalid = '确认密码和密码不一致';
return false
}
return true
},
validateEmail() {
const ePattern = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
if (!ePattern.test(this.registerForm.email)) {
this.emailInvalid = "邮箱格式不正确";
return false
}
return true
},
handleRegisterSuccess(resp) {
if (resp['success']) {
this.$router.push('/stl/login')
} else {
this.$message.error({
message: resp["msg"],
duration: 2000,
center: true
})
}
}
,
submitForm(formName) {
if (this.validateUser() && this.validatePassword() && this.validateRepwd() && this.validateEmail()) {
this.$api.register(this.registerForm).then(resp => {
this.handleRegisterSuccess(resp)
})
}
}
}
}
</script>
<style scoped>
</style>
新增同级auth,Register.vue,源码
<template>
<el-container class="login">
<!-- <el-header>
<el-row>
<el-col :span="4" :offset="1">
<div></div>
</el-col>
</el-row>
</el-header> -->
<div id="rlogo">
<el-main style="padding: 0px">
<el-row>
<el-col :span="24">
<div>
<div id="form-title">自动化测试平台</div>
<form id="submit-form">
<div id="form-content">
<div id="form-msg">注册账号</div>
<div id="form-inputs">
<div class="form-input-div">
<i
class="iconfont"
style="
position: absolute;
bottom: 438px;
padding-left: 10px;
"
></i
>
<input
placeholder="用户名"
type="text"
id="user"
v-model="registerForm.username"
/>
<div
class="err_msg"
id="user_err"
v-html="usernameInvalid"
@mouseover="usernameInvalid = ''"
></div>
</div>
<div class="form-input-div">
<i
class="iconfont"
style="
position: absolute;
bottom: 375px;
padding-left: 10px;
"
>󱈴</i
>
<input
placeholder="真实姓名"
type="text"
id="real_name"
v-model="registerForm.real_name"
/>
<div
class="err_msg"
id="realname_err"
v-html="realnameInvalid"
@mouseover="realnameInvalid = ''"
></div>
</div>
<div class="form-input-div">
<i
class="iconfont"
style="
position: absolute;
bottom: 312px;
padding-left: 10px;
"
></i
>
<input
placeholder="密码"
type="password"
id="pwd"
v-model="registerForm.password"
/>
<div
class="err_msg"
id="pwd_err"
v-html="passwordInvalid"
@mouseover="passwordInvalid = ''"
></div>
</div>
<div class="form-input-div">
<i
class="iconfont"
style="
position: absolute;
bottom: 250px;
padding-left: 10px;
"
></i
>
<input
placeholder="确认密码"
type="password"
id="repwd"
v-model="registerForm.repwd"
/>
<div
class="err_msg"
id="repwd_err"
v-html="repwdInvalid"
@mouseover="repwdInvalid = ''"
></div>
</div>
<div class="form-input-div">
<i
class="iconfont"
style="
position: absolute;
bottom: 190px;
padding-left: 10px;
"
></i
>
<input
placeholder="邮箱"
type="email"
id="email"
v-model="registerForm.email"
/>
<div
class="err_msg"
id="email_err"
v-html="emailInvalid"
@mouseover="emailInvalid = ''"
></div>
</div>
<div class="form-submit">
<button
type="button"
class="btn btn-primary"
id="submitBtn"
@click="submitForm"
>
立即注册
</button>
</div>
</div>
<div class="form-foot">
<span
>已有账户,<router-link to="/login"
>立即登陆</router-link
></span
>
</div>
</div>
</form>
</div>
</el-col>
</el-row>
</el-main>
</div>
</el-container>
</template>
<script>
export default {
name: "Register",
data() {
return {
registerForm: {
username: "",
real_name: "",
password: "",
repwd: "",
email: "",
},
passwordInvalid: "",
usernameInvalid: "",
realnameInvalid: "",
repwdInvalid: "",
emailInvalid: "",
};
},
methods: {
validateUser() {
const uPattern = /^[a-zA-Z0-9_-]{4,16}$/;
if (!uPattern.test(this.registerForm.username)) {
this.usernameInvalid = "用户名4到16位,只能是字母,数字,下划线,连字符";
return false;
}
return true;
},
validateRealName() {
// const uPattern = /^[a-zA-Z0-9_-]{4,16}$/;
const uPattern = /^[\u4e00-\u9fa5]{0,}$/;
if (!uPattern.test(this.registerForm.real_name)) {
this.realnameInvalid = "只能输入汉字";
return false;
}
return true;
},
validatePassword() {
const pPattern = /^[a-zA-Z\d_]{6,}$/;
if (!pPattern.test(this.registerForm.password)) {
this.passwordInvalid = "密码至少6位数";
return false;
}
return true;
},
validateRepwd() {
if (this.registerForm.password !== this.registerForm.repwd) {
this.repwdInvalid = "确认密码和密码不一致";
return false;
}
return true;
},
validateEmail() {
const ePattern = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
if (!ePattern.test(this.registerForm.email)) {
this.emailInvalid = "邮箱格式不正确";
return false;
}
return true;
},
handleRegisterSuccess(resp) {
if (resp["success"]) {
this.$router.push("/login");
} else {
this.$message.error({
message: resp["msg"],
duration: 2000,
center: true,
});
}
},
submitForm(formName) {
if (
this.validateUser() &&
this.validateRealName() &&
this.validatePassword() &&
this.validateRepwd() &&
this.validateEmail()
) {
this.$api.register(this.registerForm).then((resp) => {
this.handleRegisterSuccess(resp);
});
}
},
},
};
</script>
<style scoped>
#rlogo {
background: url("~@/assets/images/b.png");
background-size: 100% 100%;
height: 4000px;
width: 7000px;
}
</style>
步骤6:启动服务
此时会抛出异常。
步骤7:修改build目录下webpack.base.conf.js 大概在43行
注释掉...(config.dev.useEslint ? [createLintingRule()] : []),改成
// ...(config.dev.useEslint ? [createLintingRule()] : []),
步骤8:再次运行
步骤9:
步骤10:发送前端请求: