feat: add validate for installation. (#169)

pull/166/head
Ryan Wang 2020-05-18 21:27:13 +08:00 committed by GitHub
parent c165cf8f56
commit d3e2bda04f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 1198 additions and 76 deletions

1033
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,11 +9,12 @@
"test:unit": "vue-cli-service test:unit" "test:unit": "vue-cli-service test:unit"
}, },
"dependencies": { "dependencies": {
"ant-design-vue": "^1.5.2", "ant-design-vue": "^1.5.5",
"axios": "^0.19.2", "axios": "^0.19.2",
"enquire.js": "^2.1.6", "enquire.js": "^2.1.6",
"filepond": "^4.13.0", "filepond": "^4.13.0",
"filepond-plugin-image-preview": "^4.6.1", "filepond-plugin-image-preview": "^4.6.1",
"flv.js": "^1.5.0",
"halo-editor": "^2.8.2", "halo-editor": "^2.8.2",
"marked": "^1.0.0", "marked": "^1.0.0",
"moment": "^2.24.0", "moment": "^2.24.0",
@ -27,8 +28,7 @@
"vue-ls": "^3.2.1", "vue-ls": "^3.2.1",
"vue-router": "^3.1.6", "vue-router": "^3.1.6",
"vuejs-logger": "^1.5.3", "vuejs-logger": "^1.5.3",
"vuex": "^3.1.1", "vuex": "^3.1.1"
"flv.js": "^1.5.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/polyfill": "^7.4.4", "@babel/polyfill": "^7.4.4",
@ -46,8 +46,10 @@
"eslint-plugin-html": "^6.0.2", "eslint-plugin-html": "^6.0.2",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"generate-asset-webpack-plugin": "^0.3.0", "generate-asset-webpack-plugin": "^0.3.0",
"husky": "^4.2.5",
"less": "^3.10.0", "less": "^3.10.0",
"less-loader": "^5.0.0", "less-loader": "^5.0.0",
"lint-staged": "^10.2.2",
"vue-svg-component-runtime": "^1.0.1", "vue-svg-component-runtime": "^1.0.1",
"vue-svg-icon-loader": "^2.1.1", "vue-svg-icon-loader": "^2.1.1",
"vue-template-compiler": "^2.6.11" "vue-template-compiler": "^2.6.11"
@ -117,6 +119,17 @@
] ]
} }
}, },
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
},
"postcss": { "postcss": {
"plugins": { "plugins": {
"autoprefixer": {} "autoprefixer": {}

View File

@ -15,6 +15,7 @@ import {
Divider, Divider,
Dropdown, Dropdown,
Form, Form,
FormModel,
Icon, Icon,
Input, Input,
InputNumber, InputNumber,
@ -67,6 +68,7 @@ Vue.use(Divider)
Vue.use(Drawer) Vue.use(Drawer)
Vue.use(Dropdown) Vue.use(Dropdown)
Vue.use(Form) Vue.use(Form)
Vue.use(FormModel)
Vue.use(Icon) Vue.use(Icon)
Vue.use(Input) Vue.use(Input)
Vue.use(InputNumber) Vue.use(InputNumber)

View File

@ -29,19 +29,20 @@
</a-steps> </a-steps>
<a-divider dashed /> <a-divider dashed />
<!-- Blogger info --> <!-- Blogger info -->
<a-form <a-form-model
ref="generalForm"
:model="installation"
:rules="generalRules"
layout="horizontal" layout="horizontal"
v-show="stepCurrent == 0" v-show="stepCurrent == 0"
:form="bloggerForm"
> >
<a-form-item class="animated fadeInUp"> <a-form-model-item
class="animated fadeInUp"
prop="username"
>
<a-input <a-input
v-model="installation.username" v-model="installation.username"
placeholder="用户名" placeholder="用户名"
v-decorator="[
'username',
{rules: [{ required: true, message: '请输入用户名' }]}
]"
> >
<a-icon <a-icon
slot="prefix" slot="prefix"
@ -49,10 +50,11 @@
style="color: rgba(0,0,0,.25)" style="color: rgba(0,0,0,.25)"
/> />
</a-input> </a-input>
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
class="animated fadeInUp" class="animated fadeInUp"
:style="{'animation-delay': '0.1s'}" :style="{'animation-delay': '0.1s'}"
prop="nickname"
> >
<a-input <a-input
v-model="installation.nickname" v-model="installation.nickname"
@ -64,18 +66,15 @@
style="color: rgba(0,0,0,.25)" style="color: rgba(0,0,0,.25)"
/> />
</a-input> </a-input>
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
class="animated fadeInUp" class="animated fadeInUp"
:style="{'animation-delay': '0.2s'}" :style="{'animation-delay': '0.2s'}"
prop="email"
> >
<a-input <a-input
v-model="installation.email" v-model="installation.email"
placeholder="用户邮箱" placeholder="用户邮箱"
v-decorator="[
'email',
{rules: [{ required: true, message: '请输入邮箱' }]}
]"
> >
<a-icon <a-icon
slot="prefix" slot="prefix"
@ -83,19 +82,16 @@
style="color: rgba(0,0,0,.25)" style="color: rgba(0,0,0,.25)"
/> />
</a-input> </a-input>
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
class="animated fadeInUp" class="animated fadeInUp"
:style="{'animation-delay': '0.3s'}" :style="{'animation-delay': '0.3s'}"
prop="password"
> >
<a-input <a-input
v-model="installation.password" v-model="installation.password"
type="password" type="password"
placeholder="用户密码8-100位" placeholder="用户密码8-100位"
v-decorator="[
'password',
{rules: [{ required: true, message: '请输入密码8-100位' },{ validator: handleValidatePassword }]}
]"
> >
<a-icon <a-icon
slot="prefix" slot="prefix"
@ -103,19 +99,16 @@
style="color: rgba(0,0,0,.25)" style="color: rgba(0,0,0,.25)"
/> />
</a-input> </a-input>
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
class="animated fadeInUp" class="animated fadeInUp"
:style="{'animation-delay': '0.4s'}" :style="{'animation-delay': '0.4s'}"
prop="confirmPassword"
> >
<a-input <a-input
v-model="installation.confirmPassword" v-model="installation.confirmPassword"
type="password" type="password"
placeholder="确认密码" placeholder="确认密码"
v-decorator="[
'confirmPassword',
{rules: [{ required: true, message: '请输入确认密码' },{ validator: handleValidateConfirmPassword }]}
]"
> >
<a-icon <a-icon
slot="prefix" slot="prefix"
@ -123,16 +116,22 @@
style="color: rgba(0,0,0,.25)" style="color: rgba(0,0,0,.25)"
/> />
</a-input> </a-input>
</a-form-item> </a-form-model-item>
</a-form> </a-form-model>
<!-- Blog info --> <!-- Blog info -->
<a-form <a-form-model
layout="horizontal" layout="horizontal"
v-show="stepCurrent == 1" v-show="stepCurrent == 1"
ref="blogForm"
:model="installation"
:rules="blogRules"
>
<a-form-model-item
class="animated fadeInUp"
prop="url"
> >
<a-form-item class="animated fadeInUp">
<a-input <a-input
v-model="installation.url" v-model="installation.url"
placeholder="博客地址" placeholder="博客地址"
@ -143,10 +142,11 @@
style="color: rgba(0,0,0,.25)" style="color: rgba(0,0,0,.25)"
/> />
</a-input> </a-input>
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
class="animated fadeInUp" class="animated fadeInUp"
:style="{'animation-delay': '0.2s'}" :style="{'animation-delay': '0.2s'}"
prop="title"
> >
<a-input <a-input
v-model="installation.title" v-model="installation.title"
@ -158,8 +158,8 @@
style="color: rgba(0,0,0,.25)" style="color: rgba(0,0,0,.25)"
/> />
</a-input> </a-input>
</a-form-item> </a-form-model-item>
</a-form> </a-form-model>
<!-- Data migration --> <!-- Data migration -->
<div v-show="stepCurrent == 2"> <div v-show="stepCurrent == 2">
@ -219,12 +219,102 @@ import migrateApi from '@/api/migrate'
export default { export default {
data() { data() {
const confirmPasswordValidate = (rule, value, callback) => {
if (value !== this.installation.password) {
callback(new Error('确认密码与所输入的密码不一致'))
} else {
callback()
}
}
return { return {
installation: {}, installation: {},
stepCurrent: 0, stepCurrent: 0,
migrationData: null, migrationData: null,
bloggerForm: this.$form.createForm(this), installing: false,
installing: false
generalRules: {
username: [
{
required: true,
message: '用户名不能为空',
trigger: 'change'
},
{
max: 50,
message: '用户名的字符长度不能超过 50',
trigger: 'change'
}
],
nickname: [
{
required: true,
message: '用户昵称不能为空',
trigger: 'change'
},
{
max: 255,
message: '用户昵称的字符长度不能超过 255',
trigger: 'change'
}
],
email: [
{
required: true,
message: '电子邮件地址不能为空',
trigger: 'change'
},
{
max: 127,
message: '电子邮件地址的字符长度不能超过 127',
trigger: 'change'
},
{
pattern: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/g,
message: '电子邮件地址的格式不正确',
trigger: 'change'
}
],
password: [
{
required: true,
message: '密码不能为空',
trigger: 'change'
},
{
min: 8,
max: 100,
message: '密码的字符长度必须在 8 - 100 之间',
trigger: 'change'
}
],
confirmPassword: [
{
required: true,
message: '确认密码不能为空',
trigger: 'change'
},
{
validator: confirmPasswordValidate,
trigger: 'change'
}
]
},
blogRules: {
url: [
{
required: true,
message: '博客地址不能为空',
trigger: 'change'
}
],
title: [
{
required: true,
message: '博客标题不能为空',
trigger: 'change'
}
]
}
} }
}, },
created() { created() {
@ -232,37 +322,31 @@ export default {
this.$set(this.installation, 'url', window.location.protocol + '//' + window.location.host) this.$set(this.installation, 'url', window.location.protocol + '//' + window.location.host)
}, },
methods: { methods: {
handleValidateConfirmPassword(rule, value, callback) { async verifyIsInstall() {
if (this.installation.confirmPassword && this.installation.password !== this.installation.confirmPassword) { await adminApi.isInstalled().then(response => {
// eslint-disable-next-line standard/no-callback-literal
callback('确认密码和密码不匹配')
}
callback()
},
handleValidatePassword(rule, value, callback) {
if (this.installation.password.length < 8) {
// eslint-disable-next-line standard/no-callback-literal
callback('密码不能低于 8 位')
}
callback()
},
verifyIsInstall() {
adminApi.isInstalled().then(response => {
if (response.data.data) { if (response.data.data) {
this.$router.push({ name: 'Login' }) this.$router.push({ name: 'Login' })
} }
}) })
}, },
handleNextStep(e) { handleNextStep() {
e.preventDefault() if (this.stepCurrent === 0) {
this.bloggerForm.validateFields((error, values) => { this.$refs.generalForm.validate(valid => {
this.$log.debug('error', error) if (valid) {
this.$log.debug('Received values of form: ', values)
if (error != null) {
} else {
this.stepCurrent++ this.stepCurrent++
} else {
return false
} }
}) })
} else if (this.stepCurrent === 1) {
this.$refs.blogForm.validate(valid => {
if (valid) {
this.stepCurrent++
} else {
return false
}
})
}
}, },
handleMigrationUpload(data) { handleMigrationUpload(data) {
this.$log.debug('Selected data', data) this.$log.debug('Selected data', data)
@ -287,16 +371,6 @@ export default {
}) })
}, },
handleInstall() { handleInstall() {
const password = this.installation.password
const confirmPassword = this.installation.confirmPassword
this.$log.debug('Password', password)
this.$log.debug('Confirm password', confirmPassword)
if (password !== confirmPassword) {
this.$message.error('确认密码和密码不匹配')
return
}
this.installing = true this.installing = true
if (this.migrationData) { if (this.migrationData) {
const hide = this.$message.loading('数据导入中...', 0) const hide = this.$message.loading('数据导入中...', 0)