mirror of https://github.com/halo-dev/halo-admin
refactor: install page. (#296)
* refactor: install page. * refactor: install page. * refactor: install page. * refactor: install page.pull/300/head
parent
3799afcdd3
commit
acbbb19347
|
@ -1351,9 +1351,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": {
|
"core-js": {
|
||||||
"version": "3.8.2",
|
"version": "3.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.0.tgz",
|
||||||
"integrity": "sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A=="
|
"integrity": "sha512-PyFBJaLq93FlyYdsndE5VaueA9K5cNB7CGzeCj191YYLhkQM0gdZR2SKihM70oF0wdqKSKClv/tEBOpoRmdOVQ=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3113,9 +3113,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ant-design-vue": {
|
"ant-design-vue": {
|
||||||
"version": "1.7.2",
|
"version": "1.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-1.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-1.7.3.tgz",
|
||||||
"integrity": "sha512-iVskTSG62OSiptyGQkvyhoeLlLMiqKtAOTcWZ7MmsMrj38h0TCpGtqSYS4/fwq4yYgyzloYSteBo8U8TrV99RA==",
|
"integrity": "sha512-OuJBZmpcy32OvdvP7iW1EqdqU6l/dta1zcQ/U0fep7EGksPviVK7ssifI5QMZFQDDsti0dYQhCEOZWUG0Y/xxQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/icons": "^2.1.1",
|
"@ant-design/icons": "^2.1.1",
|
||||||
"@ant-design/icons-vue": "^2.0.0",
|
"@ant-design/icons-vue": "^2.0.0",
|
||||||
|
@ -5382,7 +5382,7 @@
|
||||||
},
|
},
|
||||||
"component-classes": {
|
"component-classes": {
|
||||||
"version": "1.2.6",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npm.taobao.org/component-classes/download/component-classes-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz",
|
||||||
"integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=",
|
"integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"component-indexof": "0.0.3"
|
"component-indexof": "0.0.3"
|
||||||
|
@ -5396,7 +5396,7 @@
|
||||||
},
|
},
|
||||||
"component-indexof": {
|
"component-indexof": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npm.taobao.org/component-indexof/download/component-indexof-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz",
|
||||||
"integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ="
|
"integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ="
|
||||||
},
|
},
|
||||||
"compressible": {
|
"compressible": {
|
||||||
|
@ -6519,7 +6519,7 @@
|
||||||
},
|
},
|
||||||
"dom-closest": {
|
"dom-closest": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/dom-closest/download/dom-closest-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz",
|
||||||
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
|
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"dom-matches": ">=1.0.1"
|
"dom-matches": ">=1.0.1"
|
||||||
|
@ -6542,7 +6542,7 @@
|
||||||
},
|
},
|
||||||
"dom-matches": {
|
"dom-matches": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/dom-matches/download/dom-matches-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz",
|
||||||
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
|
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
|
||||||
},
|
},
|
||||||
"dom-scroll-into-view": {
|
"dom-scroll-into-view": {
|
||||||
|
@ -7844,6 +7844,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/filepond/-/filepond-4.25.1.tgz",
|
"resolved": "https://registry.npmjs.org/filepond/-/filepond-4.25.1.tgz",
|
||||||
"integrity": "sha512-8UPPTzfpHZRUtJl3dEcGMLYOygg8taJZpYTv1WaEkvzeI+X0JX9+agMJ+5Lu1EKtdt9dGq/9Gud+EnNRBaGl1A=="
|
"integrity": "sha512-8UPPTzfpHZRUtJl3dEcGMLYOygg8taJZpYTv1WaEkvzeI+X0JX9+agMJ+5Lu1EKtdt9dGq/9Gud+EnNRBaGl1A=="
|
||||||
},
|
},
|
||||||
|
"filepond-plugin-file-validate-type": {
|
||||||
|
"version": "1.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/filepond-plugin-file-validate-type/-/filepond-plugin-file-validate-type-1.2.5.tgz",
|
||||||
|
"integrity": "sha512-SsdYD6N+PDnetrPrBHfl13ZC9jRv5BuGdai5cORfANhuE/N32OwU/IclCNQ4qlpIa88hzqBg9dj6IINkiW+4HA=="
|
||||||
|
},
|
||||||
"filepond-plugin-image-preview": {
|
"filepond-plugin-image-preview": {
|
||||||
"version": "4.6.4",
|
"version": "4.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/filepond-plugin-image-preview/-/filepond-plugin-image-preview-4.6.4.tgz",
|
"resolved": "https://registry.npmjs.org/filepond-plugin-image-preview/-/filepond-plugin-image-preview-4.6.4.tgz",
|
||||||
|
@ -9135,7 +9140,7 @@
|
||||||
},
|
},
|
||||||
"intersperse": {
|
"intersperse": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/intersperse/download/intersperse-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/intersperse/-/intersperse-1.0.0.tgz",
|
||||||
"integrity": "sha1-8lYfsc/vn1J3zDNHoiiGtDUaUYE="
|
"integrity": "sha1-8lYfsc/vn1J3zDNHoiiGtDUaUYE="
|
||||||
},
|
},
|
||||||
"invariant": {
|
"invariant": {
|
||||||
|
@ -10444,7 +10449,7 @@
|
||||||
},
|
},
|
||||||
"json2mq": {
|
"json2mq": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/json2mq/download/json2mq-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
|
||||||
"integrity": "sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=",
|
"integrity": "sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"string-convert": "^0.2.0"
|
"string-convert": "^0.2.0"
|
||||||
|
@ -14935,7 +14940,7 @@
|
||||||
},
|
},
|
||||||
"string-convert": {
|
"string-convert": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/string-convert/download/string-convert-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
|
||||||
"integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c="
|
"integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c="
|
||||||
},
|
},
|
||||||
"string-length": {
|
"string-length": {
|
||||||
|
|
|
@ -20,11 +20,12 @@
|
||||||
"test:unit": "vue-cli-service test:unit"
|
"test:unit": "vue-cli-service test:unit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^1.7.2",
|
"ant-design-vue": "^1.7.3",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"dayjs": "^1.10.4",
|
"dayjs": "^1.10.4",
|
||||||
"enquire.js": "^2.1.6",
|
"enquire.js": "^2.1.6",
|
||||||
"filepond": "^4.25.1",
|
"filepond": "^4.25.1",
|
||||||
|
"filepond-plugin-file-validate-type": "^1.2.5",
|
||||||
"filepond-plugin-image-preview": "^4.6.4",
|
"filepond-plugin-image-preview": "^4.6.4",
|
||||||
"flv.js": "^1.5.0",
|
"flv.js": "^1.5.0",
|
||||||
"halo-editor": "^2.8.2",
|
"halo-editor": "^2.8.2",
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
:icon="computedIcon"
|
:icon="computedIcon"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
|
:size="size"
|
||||||
|
:block="block"
|
||||||
>{{ computedText }}</a-button>
|
>{{ computedText }}</a-button>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
@ -18,6 +20,14 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: 'default',
|
||||||
|
},
|
||||||
|
block: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
loading: {
|
loading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
:name="name"
|
:name="name"
|
||||||
:allow-multiple="multiple"
|
:allow-multiple="multiple"
|
||||||
:allowRevert="false"
|
:allowRevert="false"
|
||||||
:accepted-file-types="accept"
|
:accepted-file-types="accepts"
|
||||||
:maxParallelUploads="maxParallelUploads"
|
:maxParallelUploads="maxParallelUploads"
|
||||||
:allowImagePreview="allowImagePreview"
|
:allowImagePreview="allowImagePreview"
|
||||||
:maxFiles="maxFiles"
|
:maxFiles="maxFiles"
|
||||||
|
@ -16,6 +16,8 @@
|
||||||
labelFileProcessingError="上传错误"
|
labelFileProcessingError="上传错误"
|
||||||
labelTapToCancel="点击取消"
|
labelTapToCancel="点击取消"
|
||||||
labelTapToRetry="点击重试"
|
labelTapToRetry="点击重试"
|
||||||
|
labelFileTypeNotAllowed="不支持当前文件格式"
|
||||||
|
fileValidateTypeLabelExpectedTypes="请选择 {allTypes} 格式的文件"
|
||||||
:files="fileList"
|
:files="fileList"
|
||||||
:server="server"
|
:server="server"
|
||||||
@init="handleFilePondInit"
|
@init="handleFilePondInit"
|
||||||
|
@ -33,49 +35,52 @@ import 'filepond/dist/filepond.min.css'
|
||||||
// Plugins
|
// Plugins
|
||||||
import FilePondPluginImagePreview from 'filepond-plugin-image-preview'
|
import FilePondPluginImagePreview from 'filepond-plugin-image-preview'
|
||||||
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css'
|
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css'
|
||||||
|
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type'
|
||||||
|
|
||||||
// Create component and regist plugins
|
// Create component and regist plugins
|
||||||
const FilePond = vueFilePond(FilePondPluginImagePreview)
|
const FilePond = vueFilePond(FilePondPluginImagePreview, FilePondPluginFileValidateType)
|
||||||
export default {
|
export default {
|
||||||
name: 'FilePondUpload',
|
name: 'FilePondUpload',
|
||||||
components: {
|
components: {
|
||||||
FilePond
|
FilePond,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: 'file'
|
default: 'file',
|
||||||
},
|
},
|
||||||
filed: {
|
filed: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: ''
|
default: '',
|
||||||
},
|
},
|
||||||
multiple: {
|
multiple: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
default: true
|
default: true,
|
||||||
},
|
},
|
||||||
accept: {
|
accepts: {
|
||||||
type: String,
|
type: Array,
|
||||||
required: false,
|
required: false,
|
||||||
default: ''
|
default: () => {
|
||||||
|
return []
|
||||||
|
},
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: '点击选择文件或将文件拖拽到此处'
|
default: '点击选择文件或将文件拖拽到此处',
|
||||||
},
|
},
|
||||||
uploadHandler: {
|
uploadHandler: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
loadOptions: {
|
loadOptions: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
default: true
|
default: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['options']),
|
...mapGetters(['options']),
|
||||||
|
@ -96,7 +101,7 @@ export default {
|
||||||
return this.options.attachment_upload_max_files
|
return this.options.attachment_upload_max_files
|
||||||
}
|
}
|
||||||
return 1
|
return 1
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
|
@ -134,11 +139,11 @@ export default {
|
||||||
abort()
|
abort()
|
||||||
this.$log.debug('Upload operation aborted by the user')
|
this.$log.debug('Upload operation aborted by the user')
|
||||||
source.cancel('Upload operation canceled by the user.')
|
source.cancel('Upload operation canceled by the user.')
|
||||||
}
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fileList: []
|
},
|
||||||
|
fileList: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -147,7 +152,7 @@ export default {
|
||||||
},
|
},
|
||||||
handleClearFileList() {
|
handleClearFileList() {
|
||||||
this.$refs.pond.removeFiles()
|
this.$refs.pond.removeFiles()
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -74,6 +74,20 @@
|
||||||
animation-name: fadeInUp;
|
animation-name: fadeInUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fadeIn {
|
||||||
|
animation-name: fadeIn;
|
||||||
|
}
|
||||||
|
|
||||||
.animated {
|
.animated {
|
||||||
-webkit-animation-duration: 1s;
|
-webkit-animation-duration: 1s;
|
||||||
animation-duration: 1s;
|
animation-duration: 1s;
|
||||||
|
|
|
@ -10,6 +10,13 @@
|
||||||
padding: 18px 28px 28px 28px;
|
padding: 18px 28px 28px 28px;
|
||||||
box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1);
|
box-shadow: -4px 7px 46px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.halo-logo {
|
.halo-logo {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -31,10 +38,3 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tip {
|
|
||||||
cursor: pointer;
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -149,7 +149,7 @@
|
||||||
<FilePondUpload
|
<FilePondUpload
|
||||||
ref="upload"
|
ref="upload"
|
||||||
name="file"
|
name="file"
|
||||||
accept="application/zip"
|
:accepts="['application/zip']"
|
||||||
label="点击选择主题包或将主题包拖拽到此处<br>仅支持 ZIP 格式的文件"
|
label="点击选择主题包或将主题包拖拽到此处<br>仅支持 ZIP 格式的文件"
|
||||||
:uploadHandler="installModal.local.uploadHandler"
|
:uploadHandler="installModal.local.uploadHandler"
|
||||||
@success="handleUploadSucceed"
|
@success="handleUploadSucceed"
|
||||||
|
@ -223,7 +223,7 @@
|
||||||
<FilePondUpload
|
<FilePondUpload
|
||||||
ref="updateByupload"
|
ref="updateByupload"
|
||||||
name="file"
|
name="file"
|
||||||
accept="application/zip"
|
:accepts="['application/zip']"
|
||||||
label="点击选择主题更新包或将主题更新包拖拽到此处<br>仅支持 ZIP 格式的文件"
|
label="点击选择主题更新包或将主题更新包拖拽到此处<br>仅支持 ZIP 格式的文件"
|
||||||
:uploadHandler="localUpdateModel.uploadHandler"
|
:uploadHandler="localUpdateModel.uploadHandler"
|
||||||
:filed="localUpdateModel.selected.id"
|
:filed="localUpdateModel.selected.id"
|
||||||
|
|
|
@ -7,41 +7,56 @@
|
||||||
class="h-screen"
|
class="h-screen"
|
||||||
>
|
>
|
||||||
<a-col
|
<a-col
|
||||||
:xl="8"
|
:xxl="8"
|
||||||
:md="12"
|
:xl="12"
|
||||||
|
:lg="16"
|
||||||
|
:md="20"
|
||||||
:sm="20"
|
:sm="20"
|
||||||
:xs="24"
|
:xs="23"
|
||||||
>
|
>
|
||||||
<div class="card-container">
|
<div class="card-container animated fadeIn">
|
||||||
<a-card
|
<a-card
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
title="Halo 安装向导"
|
style="box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;"
|
||||||
style="box-shadow: 0px 10px 20px 0px rgba(236, 236, 236, 0.86);"
|
|
||||||
>
|
>
|
||||||
|
<div class="halo-logo">
|
||||||
<a-steps :current="stepCurrent">
|
<span>Halo
|
||||||
<a-step title="博主信息">
|
<small>安装向导</small>
|
||||||
</a-step>
|
</span>
|
||||||
<a-step title="博客信息">
|
</div>
|
||||||
</a-step>
|
<a-alert
|
||||||
<a-step title="数据导入">
|
:message="`欢迎使用 Halo,您正在安装的是 Halo ${VERSION}。`"
|
||||||
</a-step>
|
type="success"
|
||||||
</a-steps>
|
show-icon
|
||||||
<a-divider dashed />
|
/>
|
||||||
<!-- Blogger info -->
|
<!-- Blogger info -->
|
||||||
|
<div class="mt-5 mb-5">
|
||||||
|
<a-radio-group v-model="installationMode">
|
||||||
|
<a-radio-button value="new">
|
||||||
|
全新安装
|
||||||
|
</a-radio-button>
|
||||||
|
<a-radio-button value="import">
|
||||||
|
数据导入
|
||||||
|
</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</div>
|
||||||
<a-form-model
|
<a-form-model
|
||||||
ref="generalForm"
|
class="installationForm animated fadeIn"
|
||||||
:model="installation"
|
ref="installationForm"
|
||||||
:rules="generalRules"
|
:model="form.model"
|
||||||
|
:rules="form.rules"
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
v-show="stepCurrent == 0"
|
v-show="isInstallMode"
|
||||||
>
|
>
|
||||||
<a-form-model-item
|
<a-divider
|
||||||
class="animated fadeInUp"
|
orientation="left"
|
||||||
prop="username"
|
dashed
|
||||||
>
|
>
|
||||||
|
管理员信息
|
||||||
|
</a-divider>
|
||||||
|
<a-form-model-item prop="username">
|
||||||
<a-input
|
<a-input
|
||||||
v-model="installation.username"
|
v-model="form.model.username"
|
||||||
placeholder="用户名"
|
placeholder="用户名"
|
||||||
>
|
>
|
||||||
<a-icon
|
<a-icon
|
||||||
|
@ -51,29 +66,21 @@
|
||||||
/>
|
/>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item
|
<a-form-model-item prop="username">
|
||||||
class="animated fadeInUp"
|
|
||||||
:style="{'animation-delay': '0.1s'}"
|
|
||||||
prop="nickname"
|
|
||||||
>
|
|
||||||
<a-input
|
<a-input
|
||||||
v-model="installation.nickname"
|
v-model="form.model.nickname"
|
||||||
placeholder="用户昵称"
|
placeholder="用户昵称"
|
||||||
>
|
>
|
||||||
<a-icon
|
<a-icon
|
||||||
slot="prefix"
|
slot="prefix"
|
||||||
type="smile"
|
type="user"
|
||||||
style="color: rgba(0,0,0,.25)"
|
style="color: rgba(0,0,0,.25)"
|
||||||
/>
|
/>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item
|
<a-form-model-item prop="email">
|
||||||
class="animated fadeInUp"
|
|
||||||
:style="{'animation-delay': '0.2s'}"
|
|
||||||
prop="email"
|
|
||||||
>
|
|
||||||
<a-input
|
<a-input
|
||||||
v-model="installation.email"
|
v-model="form.model.email"
|
||||||
placeholder="用户邮箱"
|
placeholder="用户邮箱"
|
||||||
>
|
>
|
||||||
<a-icon
|
<a-icon
|
||||||
|
@ -83,15 +90,11 @@
|
||||||
/>
|
/>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item
|
<a-form-model-item prop="password">
|
||||||
class="animated fadeInUp"
|
|
||||||
:style="{'animation-delay': '0.3s'}"
|
|
||||||
prop="password"
|
|
||||||
>
|
|
||||||
<a-input
|
<a-input
|
||||||
v-model="installation.password"
|
v-model="form.model.password"
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="用户密码(8-100位)"
|
placeholder="登录密码(8-100位)"
|
||||||
>
|
>
|
||||||
<a-icon
|
<a-icon
|
||||||
slot="prefix"
|
slot="prefix"
|
||||||
|
@ -100,15 +103,11 @@
|
||||||
/>
|
/>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item
|
<a-form-model-item prop="confirmPassword">
|
||||||
class="animated fadeInUp"
|
|
||||||
:style="{'animation-delay': '0.4s'}"
|
|
||||||
prop="confirmPassword"
|
|
||||||
>
|
|
||||||
<a-input
|
<a-input
|
||||||
v-model="installation.confirmPassword"
|
v-model="form.model.confirmPassword"
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="确认密码"
|
placeholder="确认登录密码"
|
||||||
>
|
>
|
||||||
<a-icon
|
<a-icon
|
||||||
slot="prefix"
|
slot="prefix"
|
||||||
|
@ -117,23 +116,15 @@
|
||||||
/>
|
/>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-form-model>
|
<a-divider
|
||||||
|
orientation="left"
|
||||||
<!-- Blog info -->
|
dashed
|
||||||
|
|
||||||
<a-form-model
|
|
||||||
layout="horizontal"
|
|
||||||
v-show="stepCurrent == 1"
|
|
||||||
ref="blogForm"
|
|
||||||
:model="installation"
|
|
||||||
:rules="blogRules"
|
|
||||||
>
|
|
||||||
<a-form-model-item
|
|
||||||
class="animated fadeInUp"
|
|
||||||
prop="url"
|
|
||||||
>
|
>
|
||||||
|
站点信息
|
||||||
|
</a-divider>
|
||||||
|
<a-form-model-item prop="url">
|
||||||
<a-input
|
<a-input
|
||||||
v-model="installation.url"
|
v-model="form.model.url"
|
||||||
placeholder="博客地址"
|
placeholder="博客地址"
|
||||||
>
|
>
|
||||||
<a-icon
|
<a-icon
|
||||||
|
@ -143,13 +134,9 @@
|
||||||
/>
|
/>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item
|
<a-form-model-item prop="title">
|
||||||
class="animated fadeInUp"
|
|
||||||
:style="{'animation-delay': '0.2s'}"
|
|
||||||
prop="title"
|
|
||||||
>
|
|
||||||
<a-input
|
<a-input
|
||||||
v-model="installation.title"
|
v-model="form.model.title"
|
||||||
placeholder="博客标题"
|
placeholder="博客标题"
|
||||||
>
|
>
|
||||||
<a-icon
|
<a-icon
|
||||||
|
@ -162,50 +149,51 @@
|
||||||
</a-form-model>
|
</a-form-model>
|
||||||
|
|
||||||
<!-- Data migration -->
|
<!-- Data migration -->
|
||||||
<div v-show="stepCurrent == 2">
|
<div
|
||||||
<a-alert
|
class="animated fadeIn"
|
||||||
style="margin-bottom: 1rem"
|
v-show="isImportMode"
|
||||||
message="如果有数据导入需求,请点击并选择之前导出的文件。需要注意的是,并不是所有数据都会导入,该初始化表单的数据会覆盖你导入的数据。"
|
>
|
||||||
type="info"
|
|
||||||
/>
|
|
||||||
<FilePondUpload
|
<FilePondUpload
|
||||||
ref="upload"
|
ref="upload"
|
||||||
name="file"
|
name="file"
|
||||||
accept="application/json"
|
:accepts="['application/json']"
|
||||||
label="拖拽或点击选择数据文件,请确认是否为 Halo 后台导出的文件。"
|
label="拖拽或点击选择数据文件<br>请确认是否为 Halo 后台导出的文件。"
|
||||||
:multiple="false"
|
:multiple="false"
|
||||||
:uploadHandler="handleMigrationUpload"
|
:uploadHandler="onImportUpload"
|
||||||
:loadOptions="false"
|
:loadOptions="false"
|
||||||
></FilePondUpload>
|
></FilePondUpload>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-row
|
<div class="mt-8">
|
||||||
class="install-action"
|
<ReactiveButton
|
||||||
type="flex"
|
v-if="isInstallMode"
|
||||||
justify="space-between"
|
icon="check"
|
||||||
style="margin-top: 1rem;"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<a-button
|
|
||||||
class="previus-button"
|
|
||||||
v-if="stepCurrent != 0"
|
|
||||||
@click="stepCurrent--"
|
|
||||||
style="margin-right: 1rem;"
|
|
||||||
>上一步</a-button>
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
type="primary"
|
||||||
v-if="stepCurrent != 2"
|
block
|
||||||
@click="handleNextStep"
|
size="large"
|
||||||
>下一步</a-button>
|
|
||||||
</div>
|
|
||||||
<a-button
|
|
||||||
v-if="stepCurrent == 2"
|
|
||||||
type="primary"
|
|
||||||
icon="upload"
|
|
||||||
@click="handleInstall"
|
@click="handleInstall"
|
||||||
:loading="installing"
|
@callback="handleInstallCallback"
|
||||||
>安装</a-button>
|
:loading="form.installing"
|
||||||
</a-row>
|
:errored="form.installErrored"
|
||||||
|
text="安装"
|
||||||
|
loadedText="安装成功"
|
||||||
|
erroredText="安装失败"
|
||||||
|
></ReactiveButton>
|
||||||
|
<ReactiveButton
|
||||||
|
v-if="isImportMode"
|
||||||
|
icon="import"
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
size="large"
|
||||||
|
@click="handleImport"
|
||||||
|
@callback="handleImportCallback"
|
||||||
|
:loading="form.importing"
|
||||||
|
:errored="form.importErrored"
|
||||||
|
text="导入"
|
||||||
|
loadedText="导入成功"
|
||||||
|
erroredText="导入失败"
|
||||||
|
></ReactiveButton>
|
||||||
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
@ -221,26 +209,24 @@ import { mapActions } from 'vuex'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
const confirmPasswordValidate = (rule, value, callback) => {
|
const confirmPasswordValidate = (rule, value, callback) => {
|
||||||
if (value !== this.installation.password) {
|
if (value !== this.form.model.password) {
|
||||||
callback(new Error('确认密码与所输入的密码不一致'))
|
callback(new Error('确认密码与所输入的密码不一致'))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
installation: {},
|
installationMode: 'new', // new or import
|
||||||
stepCurrent: 0,
|
form: {
|
||||||
migrationData: null,
|
model: {},
|
||||||
installing: false,
|
rules: {
|
||||||
|
|
||||||
generalRules: {
|
|
||||||
username: [
|
username: [
|
||||||
{ required: true, message: '* 用户名不能为空', trigger: ['change'] },
|
{ required: true, message: '* 用户名不能为空', trigger: ['change'] },
|
||||||
{ max: 50, message: '* 用户名的字符长度不能超过 50', trigger: ['change'] }
|
{ max: 50, message: '* 用户名的字符长度不能超过 50', trigger: ['change'] },
|
||||||
],
|
],
|
||||||
nickname: [
|
nickname: [
|
||||||
{ required: true, message: '* 用户昵称不能为空', trigger: ['change'] },
|
{ required: true, message: '* 用户昵称不能为空', trigger: ['change'] },
|
||||||
{ max: 255, message: '* 用户昵称的字符长度不能超过 255', trigger: ['change'] }
|
{ max: 255, message: '* 用户昵称的字符长度不能超过 255', trigger: ['change'] },
|
||||||
],
|
],
|
||||||
email: [
|
email: [
|
||||||
{ required: true, message: '* 电子邮件地址不能为空', trigger: ['change'] },
|
{ required: true, message: '* 电子邮件地址不能为空', trigger: ['change'] },
|
||||||
|
@ -248,97 +234,124 @@ export default {
|
||||||
{
|
{
|
||||||
pattern: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/g,
|
pattern: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/g,
|
||||||
message: '* 电子邮件地址的格式不正确',
|
message: '* 电子邮件地址的格式不正确',
|
||||||
trigger: ['change']
|
trigger: ['change'],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
password: [
|
password: [
|
||||||
{ required: true, message: '* 密码不能为空', trigger: ['change'] },
|
{ required: true, message: '* 密码不能为空', trigger: ['change'] },
|
||||||
{ min: 8, max: 100, message: '* 密码的字符长度必须在 8 - 100 之间', trigger: ['change'] }
|
{ min: 8, max: 100, message: '* 密码的字符长度必须在 8 - 100 之间', trigger: ['change'] },
|
||||||
],
|
],
|
||||||
confirmPassword: [
|
confirmPassword: [
|
||||||
{ required: true, message: '* 确认密码不能为空', trigger: ['change'] },
|
{ required: true, message: '* 确认密码不能为空', trigger: ['change'] },
|
||||||
{ validator: confirmPasswordValidate, trigger: ['change'] }
|
{ validator: confirmPasswordValidate, trigger: ['change'] },
|
||||||
]
|
],
|
||||||
},
|
|
||||||
blogRules: {
|
|
||||||
url: [{ required: true, message: '* 博客地址不能为空', trigger: ['change'] }],
|
url: [{ required: true, message: '* 博客地址不能为空', trigger: ['change'] }],
|
||||||
title: [{ required: true, message: '* 博客标题不能为空', trigger: ['change'] }]
|
title: [{ required: true, message: '* 博客标题不能为空', trigger: ['change'] }],
|
||||||
}
|
},
|
||||||
|
installing: false,
|
||||||
|
installErrored: false,
|
||||||
|
|
||||||
|
importing: false,
|
||||||
|
importErrored: false,
|
||||||
|
importData: null,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
this.handleVerifyIsInstall()
|
this.handleVerifyIsInstall()
|
||||||
this.$set(this.installation, 'url', window.location.protocol + '//' + window.location.host)
|
this.$set(this.form.model, 'url', window.location.protocol + '//' + window.location.host)
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isInstallMode() {
|
||||||
|
return this.installationMode === 'new'
|
||||||
|
},
|
||||||
|
isImportMode() {
|
||||||
|
return this.installationMode === 'import'
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(['installCleanToken']),
|
...mapActions(['installCleanToken']),
|
||||||
async handleVerifyIsInstall() {
|
async handleVerifyIsInstall() {
|
||||||
await adminApi.isInstalled().then((response) => {
|
const response = await adminApi.isInstalled()
|
||||||
if (response.data.data) {
|
if (response.data.data) {
|
||||||
this.$router.push({ name: 'Login' })
|
this.$router.push({ name: 'Login' })
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
handleInstall() {
|
||||||
|
this.$refs.installationForm.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.form.installing = true
|
||||||
|
this.installCleanToken(this.form.model)
|
||||||
|
.then((response) => {
|
||||||
|
this.$log.debug('Installation response', response)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.form.installErrored = true
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.form.installing = false
|
||||||
|
}, 400)
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleNextStep() {
|
handleInstallCallback() {
|
||||||
if (this.stepCurrent === 0) {
|
if (this.form.installErrored) {
|
||||||
this.$refs.generalForm.validate((valid) => {
|
this.form.installErrored = false
|
||||||
if (valid) {
|
|
||||||
this.stepCurrent++
|
|
||||||
} else {
|
} else {
|
||||||
return false
|
this.$message.success('安装成功!')
|
||||||
}
|
this.$router.push({ name: 'Login' })
|
||||||
})
|
|
||||||
} else if (this.stepCurrent === 1) {
|
|
||||||
this.$refs.blogForm.validate((valid) => {
|
|
||||||
if (valid) {
|
|
||||||
this.stepCurrent++
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleMigrationUpload(data) {
|
onImportUpload(data) {
|
||||||
this.$log.debug('Selected data', data)
|
this.$log.debug('Selected data', data)
|
||||||
this.migrationData = data
|
this.form.importData = data
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.$log.debug('Handle uploading')
|
this.$log.debug('Handle uploading')
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
install() {
|
handleImport() {
|
||||||
this.installCleanToken(this.installation)
|
if (!this.form.importData) {
|
||||||
|
this.$message.warning('请先上传数据文件!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.form.importing = true
|
||||||
|
migrateApi
|
||||||
|
.migrate(this.form.importData)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.$log.debug('Installation response', response)
|
this.$log.debug('Migrated successfullly')
|
||||||
this.$message.success('安装成功!')
|
})
|
||||||
setTimeout(() => {
|
.catch(() => {
|
||||||
this.$router.push({ name: 'Login' })
|
this.form.importErrored = true
|
||||||
}, 200)
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.installing = false
|
this.form.importing = false
|
||||||
}, 400)
|
}, 400)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleInstall() {
|
handleImportCallback() {
|
||||||
this.installing = true
|
if (this.form.importErrored) {
|
||||||
if (this.migrationData) {
|
this.form.importErrored = false
|
||||||
const hide = this.$message.loading('数据导入中...', 0)
|
|
||||||
migrateApi
|
|
||||||
.migrate(this.migrationData)
|
|
||||||
.then((response) => {
|
|
||||||
this.$log.debug('Migrated successfullly')
|
|
||||||
this.$message.success('数据导入成功!')
|
|
||||||
this.install()
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
hide()
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
this.install()
|
this.$message.success('导入成功!')
|
||||||
}
|
this.$router.push({ name: 'Login' })
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
::v-deep .installationForm {
|
||||||
|
.ant-divider {
|
||||||
|
.ant-divider-inner-text {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
&::before {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -103,7 +103,7 @@
|
||||||
<FilePondUpload
|
<FilePondUpload
|
||||||
ref="upload"
|
ref="upload"
|
||||||
name="file"
|
name="file"
|
||||||
accept="text/markdown"
|
:accepts="['text/markdown']"
|
||||||
label="拖拽或点击选择 Markdown 文件到此处"
|
label="拖拽或点击选择 Markdown 文件到此处"
|
||||||
:uploadHandler="uploadHandler"
|
:uploadHandler="uploadHandler"
|
||||||
></FilePondUpload>
|
></FilePondUpload>
|
||||||
|
|
|
@ -97,19 +97,19 @@ import { mapActions, mapGetters, mapMutations } from 'vuex'
|
||||||
import LoginForm from '@/components/Login/LoginForm'
|
import LoginForm from '@/components/Login/LoginForm'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
LoginForm
|
LoginForm,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
resetPasswordButtonVisible: false,
|
resetPasswordButtonVisible: false,
|
||||||
apiForm: {
|
apiForm: {
|
||||||
apiUrl: window.location.host,
|
apiUrl: window.location.host,
|
||||||
visible: false
|
visible: false,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({ defaultApiUrl: 'apiUrl' })
|
...mapGetters({ defaultApiUrl: 'apiUrl' }),
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
const _this = this
|
const _this = this
|
||||||
|
@ -124,14 +124,13 @@ export default {
|
||||||
...mapActions(['refreshUserCache', 'refreshOptionsCache']),
|
...mapActions(['refreshUserCache', 'refreshOptionsCache']),
|
||||||
...mapMutations({
|
...mapMutations({
|
||||||
setApiUrl: 'SET_API_URL',
|
setApiUrl: 'SET_API_URL',
|
||||||
restoreApiUrl: 'RESTORE_API_URL'
|
restoreApiUrl: 'RESTORE_API_URL',
|
||||||
}),
|
}),
|
||||||
handleVerifyIsInstall() {
|
async handleVerifyIsInstall() {
|
||||||
adminApi.isInstalled().then((response) => {
|
const response = await adminApi.isInstalled()
|
||||||
if (!response.data.data) {
|
if (!response.data.data) {
|
||||||
this.$router.push({ name: 'Install' })
|
this.$router.push({ name: 'Install' })
|
||||||
}
|
}
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onLoginSucceed() {
|
onLoginSucceed() {
|
||||||
// Refresh the user info
|
// Refresh the user info
|
||||||
|
@ -156,7 +155,7 @@ export default {
|
||||||
if (this.apiForm.visible) {
|
if (this.apiForm.visible) {
|
||||||
this.apiForm.apiUrl = this.defaultApiUrl
|
this.apiForm.apiUrl = this.defaultApiUrl
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue