更新vue版本,完成注册页面

This commit is contained in:
zemal 2017-08-19 17:27:43 +08:00
parent b636447353
commit e2a491fea1
9 changed files with 229 additions and 143 deletions

53
oj/package-lock.json generated
View File

@ -1736,9 +1736,9 @@
"dev": true
},
"cosmiconfig": {
"version": "2.1.3",
"resolved": "http://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-2.1.3.tgz",
"integrity": "sha1-lSdx6w3dwcs/ovb75RpSLpOz7go=",
"version": "2.2.2",
"resolved": "http://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-2.2.2.tgz",
"integrity": "sha1-YXPOvVb6wELB9DkO33r2wHx8uJI=",
"dev": true,
"requires": {
"is-directory": "0.3.1",
@ -2195,14 +2195,15 @@
}
},
"editorconfig": {
"version": "0.13.2",
"resolved": "http://registry.npm.taobao.org/editorconfig/download/editorconfig-0.13.2.tgz",
"integrity": "sha1-jleSbZ7mmrbLmZ8CfCFxRnrM6zU=",
"version": "0.13.3",
"resolved": "http://registry.npm.taobao.org/editorconfig/download/editorconfig-0.13.3.tgz",
"integrity": "sha1-5SGeWHlR1glY/ZTqmpoAjN7/GzQ=",
"dev": true,
"requires": {
"bluebird": "3.5.0",
"commander": "2.9.0",
"lru-cache": "3.2.0",
"semver": "5.3.0",
"sigmund": "1.0.1"
},
"dependencies": {
@ -4650,7 +4651,7 @@
"dev": true,
"requires": {
"config-chain": "1.1.11",
"editorconfig": "0.13.2",
"editorconfig": "0.13.3",
"mkdirp": "0.5.1",
"nopt": "3.0.6"
}
@ -5743,7 +5744,7 @@
"integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=",
"dev": true,
"requires": {
"cosmiconfig": "2.1.3",
"cosmiconfig": "2.2.2",
"object-assign": "4.1.1",
"postcss-load-options": "1.2.0",
"postcss-load-plugins": "2.3.0"
@ -5755,7 +5756,7 @@
"integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=",
"dev": true,
"requires": {
"cosmiconfig": "2.1.3",
"cosmiconfig": "2.2.2",
"object-assign": "4.1.1"
}
},
@ -5765,7 +5766,7 @@
"integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=",
"dev": true,
"requires": {
"cosmiconfig": "2.1.3",
"cosmiconfig": "2.2.2",
"object-assign": "4.1.1"
}
},
@ -7402,9 +7403,9 @@
}
},
"vue": {
"version": "2.3.4",
"resolved": "http://registry.npm.taobao.org/vue/download/vue-2.3.4.tgz",
"integrity": "sha1-XsO4ehkdqAkLvvVrfPq9QVgDgXE="
"version": "2.4.2",
"resolved": "http://registry.npm.taobao.org/vue/download/vue-2.4.2.tgz",
"integrity": "sha1-qYVSYfGRyXjMDcEVBTG40IFJtYw="
},
"vue-codemirror": {
"version": "3.0.8",
@ -7438,9 +7439,9 @@
"dev": true
},
"vue-loader": {
"version": "12.2.1",
"resolved": "http://registry.npm.taobao.org/vue-loader/download/vue-loader-12.2.1.tgz",
"integrity": "sha1-U/J8CXPThnaPWnUVb0Epte/GulU=",
"version": "12.2.2",
"resolved": "http://registry.npm.taobao.org/vue-loader/download/vue-loader-12.2.2.tgz",
"integrity": "sha1-Kzp2TycBj5dbx4y4sfVRN1SO4tc=",
"dev": true,
"requires": {
"consolidate": "0.14.5",
@ -7455,13 +7456,13 @@
"source-map": "0.5.6",
"vue-hot-reload-api": "2.1.0",
"vue-style-loader": "3.0.1",
"vue-template-es2015-compiler": "1.5.2"
"vue-template-es2015-compiler": "1.5.3"
}
},
"vue-router": {
"version": "2.6.0",
"resolved": "http://registry.npm.taobao.org/vue-router/download/vue-router-2.6.0.tgz",
"integrity": "sha1-d7Jx9uCsbVfo5VbaWMZYL84KtxI="
"version": "2.7.0",
"resolved": "http://registry.npm.taobao.org/vue-router/download/vue-router-2.7.0.tgz",
"integrity": "sha1-FtQkSTqlHDyMzot8chDqTDqJr/E="
},
"vue-style-loader": {
"version": "3.0.1",
@ -7474,9 +7475,9 @@
}
},
"vue-template-compiler": {
"version": "2.3.4",
"resolved": "http://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.3.4.tgz",
"integrity": "sha1-WoisLF5NXWIY5qqA5+Ih+35niUw=",
"version": "2.4.2",
"resolved": "http://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.4.2.tgz",
"integrity": "sha1-WkXYQ/FIsJj2wdHjWsIMSVbTCtE=",
"dev": true,
"requires": {
"de-indent": "1.0.2",
@ -7484,9 +7485,9 @@
}
},
"vue-template-es2015-compiler": {
"version": "1.5.2",
"resolved": "http://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.5.2.tgz",
"integrity": "sha1-oKbFDJQdKkq9qWPy9CwzesRQ7pU=",
"version": "1.5.3",
"resolved": "http://registry.npm.taobao.org/vue-template-es2015-compiler/download/vue-template-es2015-compiler-1.5.3.tgz",
"integrity": "sha1-Inh95ON+vZM5t0IjvEZ9Gt7jBUU=",
"dev": true
},
"watchpack": {

View File

@ -16,11 +16,11 @@
"font-awesome": "^4.7.0",
"iview": "^2.0.0-rc.17",
"moment": "^2.18.1",
"vue": "^2.3.3",
"vue": "^2.4.2",
"vue-codemirror": "^3.0.8",
"vue-echarts": "^2.4.0",
"vue-highlightjs": "^1.3.3",
"vue-router": "^2.6.0"
"vue-router": "^2.7.0"
},
"devDependencies": {
"autoprefixer": "^6.7.2",
@ -58,9 +58,9 @@
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"url-loader": "^0.5.8",
"vue-loader": "^12.1.0",
"vue-loader": "^12.2.2",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.3.3",
"vue-template-compiler": "^2.4.2",
"webpack": "^2.6.1",
"webpack-bundle-analyzer": "^2.2.1",
"webpack-dev-middleware": "^1.10.0",

View File

@ -50,14 +50,14 @@
margin: 0;
padding: 0;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
overflow: auto;
-webkit-font-smoothing: antialiased;
background-color: #eee;;
overflow-y: scroll;
}
.content-app {
padding: 80px 15px 0 15px;
margin-top: 80px;
padding: 0 15px 0 15px;
overflow-y: scroll;
}
.footer {

View File

@ -24,20 +24,26 @@ export default {
}
})
},
// 注册
register(username, email, password, captcha) {
return ajax('register', 'post', {
checkUsernameOrEmail(username, email) {
return ajax('check_username_or_email', 'post', {
data: {
username,
email,
password,
captcha
email
}
})
},
// 注册
register(data) {
return ajax('register', 'post', {
data
})
},
logout() {
return ajax('logout', 'get')
},
getCaptcha() {
return ajax('captcha', 'get')
},
// 获取自身信息
getUserInfo(username = undefined) {
return ajax('account/profile', 'get', {
@ -207,9 +213,9 @@ function ajax(url, method, options) {
// }
} else {
resolve(res)
if (method !== 'get') {
Vue.prototype.$success('Success')
}
// if (method !== 'get') {
// Vue.prototype.$success('Success')
// }
}
}, res => {
// API请求异常一般为Server error 或 network error

View File

@ -11,7 +11,7 @@
<template v-if="!isAuthed">
<div class="btn-menu">
<Button type="ghost" shape="circle" @click="handleRoute('/login')">Login</Button>
<Button type="ghost" shape="circle" @click="handleRoute('/register')" style="margin-left: 5px;">Register
<Button type="ghost" shape="circle" @click="registerModalVisible = true" style="margin-left: 5px;">Register
</Button>
</div>
</template>
@ -29,7 +29,7 @@
</Dropdown>
</template>
</Menu>
<Register :visible.sync="registerModalVisible"></Register>
</div>
</template>
@ -39,9 +39,15 @@
import api from '@/api'
import auth from '../utils/authHelper'
import Register from '@/views/user/Register'
export default {
components: {
Register
},
data() {
return {
registerModalVisible: false,
isAuthed: false,
username: ''
}

View File

@ -1,6 +1,9 @@
// all routes here.
import Test from '../views/test'
import {ProblemList, Logout, ContestList, ContestDetails, ContestProblemList, ContestAnnouncement} from '../views'
import {
ProblemList, ContestList, ContestDetails, ContestProblemList, ContestAnnouncement,
Logout, Register
} from '../views'
export default [
{
@ -62,6 +65,11 @@ export default [
path: '/contest/:contestID/problem/:problemID',
component: () => import('@/views/problem/Problem.vue')
},
{
name: 'register',
path: '/register',
component: Register
},
{
name: 'logout',
path: '/logout',

View File

@ -4,8 +4,8 @@ import ContestDetails from './contest/ContestDetail.vue'
import ContestProblemList from './contest/children/ContestProblemList.vue'
import ContestAnnouncement from './contest/children/ContestAnnouncement.vue'
import Logout from './user/Logout.vue'
//
export {ProblemList, Logout, ContestList, ContestDetails, ContestProblemList, ContestAnnouncement}
import Register from './user/Register.vue'
export {ProblemList, ContestList, ContestDetails, ContestProblemList, ContestAnnouncement, Register, Logout}
/* , Login, Logout,
* 在对应的route内加载

View File

@ -153,7 +153,6 @@
contest_id: this.contestID
}
api.getSubmissionList(offset, limit, params).then((res) => {
console.log(res.data.data.results)
this.submissions = res.data.data.results
this.total = res.data.data.total
})

View File

@ -1,114 +1,180 @@
<template>
<div class="center">
<el-card class="box-card" id="login-card">
<div slot="header" class="clearfix" id="login-title">
<span style="line-height: 36px;">用户注册</span>
<Modal :value="visible" @on-cancel="$emit('update:visible', false)" :width="500">
<div slot="header">
<span>Welcome to register!</span>
</div>
<Form ref="formRegister" :model="formRegister" :rules="ruleRegister">
<Form-item prop="username">
<Input type="text" v-model="formRegister.username" placeholder="Username" size="large">
<Icon type="ios-person-outline" slot="prepend"></Icon>
</Input>
</Form-item>
<Form-item prop="email">
<Input v-model="formRegister.email" placeholder="Email Address" size="large">
<Icon type="ios-email-outline" slot="prepend"></Icon>
</Input>
</Form-item>
<Form-item prop="password">
<Input type="password" v-model="formRegister.password" placeholder="Password" size="large">
<Icon type="ios-locked-outline" slot="prepend"></Icon>
</Input>
</Form-item>
<Form-item prop="passwordAgain">
<Input type="password" v-model="formRegister.passwordAgain" placeholder="Password Again" size="large">
<Icon type="ios-locked-outline" slot="prepend"></Icon>
</Input>
</Form-item>
<Form-item prop="captcha">
<div id="captcha">
<div id="captchaCode">
<Input v-model="formRegister.captcha" placeholder="Capacha" size="large">
<Icon type="ios-lightbulb-outline" slot="prepend"></Icon>
</Input>
</div>
<div id="captchaImg">
<Tooltip content="Click to refresh" placement="top">
<img :src="captchaSrc" @click="getCaptchaSrc"/>
</Tooltip>
</div>
</div>
</Form-item>
<el-form :label-position="labelPosition" :rules="rules" label-width="80px" :model="formLabelAlign">
<el-form-item label="账号" prop="username">
<el-input v-model="formLabelAlign.username"></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="formLabelAlign.email" type="email"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="formLabelAlign.password" type="password"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPassword">
<el-input v-model="formLabelAlign.checkPassword" type="password"></el-input>
</el-form-item>
<el-form-item label="验证码">
<el-input v-model="formLabelAlign.captcha"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">提交</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</Form>
<div slot="footer">
<Button type="ghost" @click="handleReset('formRegister')">reset</Button>
<Button type="primary" @click="handleSubmit('formRegister')">submit</Button>
</div>
</Modal>
</template>
<script>
import api from '../../api.js'
import api from '@/api'
export default {
data() {
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else {
if (this.formLabelAlign.checkPassword !== '') {
this.$refs.formLabelAlign.validateField('checkPassword')
export default {
data() {
const validateUsername = (rule, value, callback) => {
if (value !== '') {
api.checkUsernameOrEmail(value, undefined).then(res => {
if (res.data.data.username === false) {
callback(new Error('username already exists.'))
} else {
callback()
}
}, _ => {})
} else {
callback()
}
}
const validateEmail = (rule, value, callback) => {
if (value !== '') {
api.checkUsernameOrEmail(undefined, value).then(res => {
if (res.data.data.email === false) {
callback(new Error('email already exists'))
} else {
callback()
}
}, _ => {})
} else {
callback()
}
}
const validatePass = (rule, value, callback) => {
if (this.formRegister.passwdCheck !== '') {
//
this.$refs.formRegister.validateField('passwordAgain')
}
callback()
}
}
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.formLabelAlign.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
const validatePassCheck = (rule, value, callback) => {
if (value !== this.formRegister.password) {
callback(new Error('password does not match'))
} else {
callback()
}
}
}
return {
labelPosition: 'top',
formLabelAlign: {
username: '',
password: '',
email: '',
captcha: ''
},
rules: {
username: [{
required: true,
message: '请输入用户名',
trigger: 'blur'
}],
email: [{
required: true,
message: '请输入邮箱',
trigger: 'blur'
}],
password: [{
validator: validatePass,
trigger: 'blur'
}],
checkPassword: [{
validator: validatePass2,
trigger: 'blur'
}]
return {
captchaSrc: '',
formRegister: {
username: 'zemal',
password: '123555',
passwordAgain: '123555',
email: '213@zemal.com',
captcha: ''
},
ruleRegister: {
username: [
{required: true, trigger: 'blur'},
{validator: validateUsername, trigger: 'blur'}
],
email: [
{required: true, type: 'email', trigger: 'blur'},
{validator: validateEmail, trigger: 'blur'}
],
password: [
{required: true, trigger: 'blur', min: 6, max: 20},
{validator: validatePass, trigger: 'blur'}
],
passwordAgain: [
{required: true, validator: validatePassCheck, trigger: 'change'}
],
captcha: [
{required: true, trigger: 'blur', min: 1, max: 10}
]
}
}
}
},
methods: {
onSubmit() {
console.log('submit!')
api.register(this.formLabelAlign.username, this.formLabelAlign.email,
this.formLabelAlign.password, this.formLabelAlign.captcha).then(function(res) {
// problems
},
props: {
visible: {
required: true,
type: Boolean,
default: false
}
},
methods: {
handleSubmit(name) {
this.$refs[name].validate((valid) => {
if (!valid) {
this.$error('please validate the error fields')
} else {
let formData = Object.assign({}, this.formRegister)
delete formData['passwordAgain']
api.register(formData).then(res => {
console.log(res.data.data)
}, res => {
console.log(res)
})
}
})
},
handleReset(name) {
this.$refs[name].resetFields()
},
getCaptchaSrc() {
api.getCaptcha().then(res => {
console.log(res.data.data)
this.captchaSrc = res.data.data
})
}
},
mounted() {
this.getCaptchaSrc()
}
}
}
</script>
<style lang="css" scoped>
.center{
margin-top: 50px;
}
#login-card{
max-width: 400px;
margin: auto;
}
#login-title{
text-align: center;
font-size: 20px;
}
<style scoped lang="less">
#captcha {
display: inline-flex;
justify-content: space-between;
width: 100%;
#captchaCode {
flex: auto;
}
#captchaImg {
margin-left: 10px;
padding: 3px;
flex: initial;
}
}
</style>