refactor: form verification. (halo-dev/console#250)

* refactor: form verification.

* refactor: form verification.

* refactor: form verification.
pull/3445/head
Ryan Wang 2020-09-23 00:20:47 +08:00 committed by GitHub
parent 37ca43ad78
commit ab0617251f
5 changed files with 544 additions and 395 deletions

View File

@ -845,7 +845,7 @@ body {
.journal-list-content,
.comment-drawer-content {
img {
width: 100%;
width: 50%;
}
}

View File

@ -15,7 +15,7 @@
>
<a-form-item label="关键词:">
<a-input
v-model="queryParam.keyword"
v-model="list.queryParam.keyword"
@keyup.enter="handleQuery()"
/>
</a-form-item>
@ -27,14 +27,14 @@
<a-form-item label="状态:">
<a-select
placeholder="请选择状态"
v-model="queryParam.type"
v-model="list.queryParam.type"
@change="handleQuery()"
>
<a-select-option
v-for="type in Object.keys(journalType)"
v-for="type in Object.keys(list.journalType)"
:key="type"
:value="type"
>{{ journalType[type].text }}</a-select-option>
>{{ list.journalType[type].text }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
@ -48,7 +48,7 @@
type="primary"
@click="handleQuery()"
>查询</a-button>
<a-button @click="resetParam()"></a-button>
<a-button @click="handleResetParam()"></a-button>
</a-space>
</span>
</a-col>
@ -59,18 +59,18 @@
<a-button
type="primary"
icon="plus"
@click="handleNew"
@click="handleOpenPublishModal"
>写日志</a-button>
</div>
<a-divider />
<div class="mt-4">
<a-empty v-if="!listLoading && journals.length==0" />
<a-empty v-if="!list.loading && list.data.length==0" />
<a-list
v-else
itemLayout="vertical"
:pagination="false"
:dataSource="journals"
:loading="listLoading"
:dataSource="list.data"
:loading="list.loading"
>
<a-list-item
slot="renderItem"
@ -87,7 +87,7 @@
<span>
<a
href="javascript:void(0);"
@click="handleShowJournalComments(item)"
@click="handleOpenJournalCommentsDrawer(item)"
>
<a-icon type="message" />
{{ item.commentCount }}
@ -110,7 +110,7 @@
<template slot="extra">
<a
href="javascript:void(0);"
@click="handleEdit(item)"
@click="handleOpenEditModal(item)"
>编辑</a>
<a-divider type="vertical" />
<a-popconfirm
@ -141,9 +141,9 @@
<div class="page-wrapper">
<a-pagination
class="pagination"
:current="pagination.page"
:total="pagination.total"
:defaultPageSize="pagination.size"
:current="list.pagination.page"
:total="list.pagination.total"
:defaultPageSize="list.pagination.size"
:pageSizeOptions="['1', '2', '5', '10', '20', '50', '100']"
showSizeChanger
@showSizeChange="handlePaginationChange"
@ -163,13 +163,13 @@
shape="circle"
icon="setting"
size="large"
@click="optionFormVisible=true"
@click="optionModal.visible=true"
></a-button>
</div>
<a-modal
v-model="optionFormVisible"
v-model="optionModal.visible"
title="页面设置"
:afterClose="() => optionFormVisible = false"
:afterClose="() => optionModal.visible = false"
>
<template slot="footer">
<a-button
@ -183,11 +183,11 @@
label="页面标题:"
help="* 需要主题进行适配"
>
<a-input v-model="options.journals_title" />
<a-input v-model="optionModal.options.journals_title" />
</a-form-item>
<a-form-item label="每页显示条数:">
<a-input-number
v-model="options.journals_page_size"
v-model="optionModal.options.journals_page_size"
style="width:100%"
/>
</a-form-item>
@ -195,9 +195,9 @@
</a-modal>
<!-- 编辑日志弹窗 -->
<a-modal v-model="visible">
<a-modal v-model="form.visible">
<template slot="title">
{{ title }}
{{ formTitle }}
<a-tooltip
slot="action"
title="只能输入250字"
@ -208,47 +208,52 @@
<template slot="footer">
<a-button
type="dashed"
@click="attachmentDrawerVisible = true"
@click="attachmentDrawer.visible = true"
>附件库</a-button>
<ReactiveButton
type="primary"
@click="createOrUpdateJournal"
@callback="handleSavedCallback"
:loading="saving"
:errored="errored"
@click="handleSaveOrUpdate"
@callback="handleSaveOrUpdateCallback"
:loading="form.saving"
:errored="form.saveErrored"
text="发布"
loadedText="发布成功"
erroredText="发布失败"
></ReactiveButton>
</template>
<a-form layout="vertical">
<a-form-item>
<a-form-model
ref="journalForm"
:model="form.model"
:rules="form.rules"
layout="vertical"
>
<a-form-model-item prop="sourceContent">
<a-input
type="textarea"
:autoSize="{ minRows: 8 }"
v-model="journal.sourceContent"
v-model="form.model.sourceContent"
/>
</a-form-item>
<a-form-item>
</a-form-model-item>
<a-form-model-item>
<a-switch
checkedChildren="公开"
unCheckedChildren="私密"
v-model="isPublic"
v-model="form.isPublic"
defaultChecked
/>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</a-modal>
<TargetCommentDrawer
:visible="journalCommentVisible"
:description="journal.content"
:visible="journalCommentDrawer.visible"
:description="list.selected.content"
:target="`journals`"
:id="journal.id"
@close="onJournalCommentsClose"
:id="list.selected.id"
@close="onJournalCommentsDrawerClose"
/>
<AttachmentDrawer v-model="attachmentDrawerVisible" />
<AttachmentDrawer v-model="attachmentDrawer.visible" />
</div>
</template>
@ -264,166 +269,172 @@ export default {
components: { TargetCommentDrawer, AttachmentDrawer },
data() {
return {
journalType: journalApi.journalType,
title: '发表',
listLoading: false,
visible: false,
journalCommentVisible: false,
attachmentDrawerVisible: false,
optionFormVisible: false,
pagination: {
page: 1,
size: 10,
sort: null,
total: 1
list: {
data: [],
loading: false,
pagination: {
page: 1,
size: 10,
sort: null,
total: 1,
},
queryParam: {
page: 0,
size: 10,
sort: null,
keyword: null,
type: null,
},
selected: {},
journalType: journalApi.journalType,
},
queryParam: {
page: 0,
size: 10,
sort: null,
keyword: null,
type: null
form: {
model: {},
rules: {
sourceContent: [{ required: true, message: '* 内容不能为空', trigger: ['change'] }],
},
visible: false,
saving: false,
saveErrored: false,
isPublic: true,
},
journalCommentDrawer: {
visible: false,
},
attachmentDrawer: {
visible: false,
},
optionModal: {
visible: false,
options: [],
},
journals: [],
comments: [],
journal: {},
isPublic: true,
replyComment: {},
options: [],
saving: false,
errored: false
}
},
created() {
beforeMount() {
this.hanldeListJournals()
this.hanldeListOptions()
},
computed: {
...mapGetters(['user'])
...mapGetters(['user']),
formTitle() {
return this.form.model.id ? '编辑' : '发表'
},
},
methods: {
...mapActions(['refreshOptionsCache']),
hanldeListJournals() {
this.listLoading = true
this.queryParam.page = this.pagination.page - 1
this.queryParam.size = this.pagination.size
this.queryParam.sort = this.pagination.sort
this.list.loading = true
this.list.queryParam.page = this.list.pagination.page - 1
this.list.queryParam.size = this.list.pagination.size
this.list.queryParam.sort = this.list.pagination.sort
journalApi
.query(this.queryParam)
.then(response => {
this.journals = response.data.data.content
this.pagination.total = response.data.data.total
.query(this.list.queryParam)
.then((response) => {
this.list.data = response.data.data.content
this.list.pagination.total = response.data.data.total
})
.finally(() => {
setTimeout(() => {
this.listLoading = false
this.list.loading = false
}, 200)
})
},
hanldeListOptions() {
optionApi.listAll().then(response => {
this.options = response.data.data
optionApi.listAll().then((response) => {
this.optionModal.options = response.data.data
})
},
handleQuery() {
this.handlePaginationChange(1, this.pagination.size)
this.handlePaginationChange(1, this.list.pagination.size)
},
handleNew() {
this.title = '新建'
this.visible = true
this.journal = {}
handleResetParam() {
this.list.queryParam.keyword = null
this.list.queryParam.type = null
this.handlePaginationChange(1, this.list.pagination.size)
},
handleEdit(item) {
this.title = '编辑'
this.journal = item
this.isPublic = item.type !== 'INTIMATE'
this.visible = true
handleOpenPublishModal() {
this.form.visible = true
this.form.model = {}
},
handleOpenEditModal(item) {
this.form.model = item
this.form.isPublic = item.type !== 'INTIMATE'
this.form.visible = true
},
handleDelete(id) {
journalApi
.delete(id)
.then(response => {
this.$message.success('删除成功!')
})
.finally(() => {
this.hanldeListJournals()
})
journalApi.delete(id).finally(() => {
this.hanldeListJournals()
})
},
handleShowJournalComments(journal) {
this.journal = journal
this.journalCommentVisible = true
handleOpenJournalCommentsDrawer(journal) {
this.list.selected = journal
this.journalCommentDrawer.visible = true
},
createOrUpdateJournal() {
this.journal.type = this.isPublic ? 'PUBLIC' : 'INTIMATE'
if (!this.journal.sourceContent) {
this.$notification['error']({
message: '提示',
description: '发布内容不能为空!'
})
return
}
this.saving = true
if (this.journal.id) {
journalApi
.update(this.journal.id, this.journal)
.catch(() => {
this.errored = true
})
.finally(() => {
setTimeout(() => {
this.saving = false
}, 400)
})
handleSaveOrUpdate() {
const _this = this
_this.$refs.journalForm.validate((valid) => {
if (valid) {
_this.form.model.type = _this.form.isPublic ? 'PUBLIC' : 'INTIMATE'
_this.form.saving = true
if (_this.form.model.id) {
journalApi
.update(_this.form.model.id, _this.form.model)
.catch(() => {
_this.form.saveErrored = true
})
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 400)
})
} else {
journalApi
.create(_this.form.model)
.catch(() => {
_this.form.saveErrored = true
})
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 400)
})
}
}
})
},
handleSaveOrUpdateCallback() {
if (this.form.saveErrored) {
this.form.saveErrored = false
} else {
journalApi
.create(this.journal)
.catch(() => {
this.errored = true
})
.finally(() => {
setTimeout(() => {
this.saving = false
}, 400)
})
}
},
handleSavedCallback() {
if (this.errored) {
this.errored = false
} else {
this.isPublic = true
this.visible = false
this.form.isPublic = true
this.form.visible = false
this.hanldeListJournals()
}
},
handlePaginationChange(page, pageSize) {
this.$log.debug(`Current: ${page}, PageSize: ${pageSize}`)
this.pagination.page = page
this.pagination.size = pageSize
this.list.pagination.page = page
this.list.pagination.size = pageSize
this.hanldeListJournals()
},
onJournalCommentsClose() {
this.journal = {}
this.journalCommentVisible = false
},
resetParam() {
this.queryParam.keyword = null
this.queryParam.type = null
this.handlePaginationChange(1, this.pagination.size)
onJournalCommentsDrawerClose() {
this.form.model = {}
this.journalCommentDrawer.visible = false
},
handleSaveOptions() {
optionApi
.save(this.options)
.then(response => {
.save(this.optionModal.options)
.then((response) => {
this.$message.success('保存成功!')
this.optionFormVisible = false
this.optionModal.visible = false
})
.finally(() => {
this.hanldeListOptions()
this.refreshOptionsCache()
})
}
}
},
},
}
</script>

View File

@ -59,7 +59,7 @@
<a-button
type="primary"
icon="plus"
@click="formVisible=true"
@click="form.visible=true"
>新增</a-button>
</div>
<div class="mt-4">
@ -134,35 +134,50 @@
</div>
</a-card>
<a-modal
v-model="formVisible"
v-model="form.visible"
:title="formTitle"
:afterClose="onFormClose"
>
<template slot="footer">
<a-button
key="submit"
type="primary"
@click="createOrUpdateOption()"
>保存</a-button>
<ReactiveButton
@click="handleSaveOrUpdate"
@callback="handleSaveOrUpdateCallback"
:loading="form.saving"
:errored="form.saveErrored"
text="保存"
loadedText="保存成功"
erroredText="保存失败"
></ReactiveButton>
</template>
<a-alert
v-if="optionToStage.type === optionType.INTERNAL.value"
v-if="form.model.type === optionType.INTERNAL.value"
message="注意:在不知道系统变量的具体用途时,请不要随意修改!"
banner
closable
/>
<a-form layout="vertical">
<a-form-item label="Key">
<a-input v-model="optionToStage.key" />
</a-form-item>
<a-form-item label="Value">
<a-form-model
ref="optionForm"
:model="form.model"
:rules="form.rules"
layout="vertical"
>
<a-form-model-item
prop="key"
label="Key"
>
<a-input v-model="form.model.key" />
</a-form-model-item>
<a-form-model-item
prop="value"
label="Value"
>
<a-input
type="textarea"
:autoSize="{ minRows: 5 }"
v-model="optionToStage.value"
v-model="form.model.value"
/>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
@ -174,38 +189,38 @@ const columns = [
title: 'Key',
dataIndex: 'key',
ellipsis: true,
scopedSlots: { customRender: 'key' }
scopedSlots: { customRender: 'key' },
},
{
title: 'Value',
dataIndex: 'value',
ellipsis: true,
scopedSlots: { customRender: 'value' }
scopedSlots: { customRender: 'value' },
},
{
title: '类型',
dataIndex: 'typeProperty',
width: '100px',
scopedSlots: { customRender: 'type' }
scopedSlots: { customRender: 'type' },
},
{
title: '创建时间',
dataIndex: 'createTime',
width: '200px',
scopedSlots: { customRender: 'createTime' }
scopedSlots: { customRender: 'createTime' },
},
{
title: '更新时间',
dataIndex: 'updateTime',
width: '200px',
scopedSlots: { customRender: 'updateTime' }
scopedSlots: { customRender: 'updateTime' },
},
{
title: '操作',
dataIndex: 'action',
width: '120px',
scopedSlots: { customRender: 'action' }
}
scopedSlots: { customRender: 'action' },
},
]
export default {
name: 'OptionsList',
@ -213,37 +228,46 @@ export default {
return {
optionType: optionApi.type,
columns: columns,
formVisible: false,
pagination: {
page: 1,
size: 10,
sort: null,
total: 1
total: 1,
},
queryParam: {
page: 0,
size: 10,
sort: null,
keyword: null,
type: null
type: null,
},
optionToStage: {},
loading: false,
options: []
options: [],
form: {
visible: false,
model: {},
rules: {
key: [{ required: true, message: '* Key 不能为空', trigger: ['change'] }],
value: [{ required: true, message: '* Value 不能为空', trigger: ['change'] }],
},
saving: false,
saveErrored: false,
},
}
},
computed: {
formattedDatas() {
return this.options.map(option => {
return this.options.map((option) => {
option.typeProperty = this.optionType[option.type]
return option
})
},
formTitle() {
return this.optionToStage.id ? '编辑' : '新增'
}
return this.form.model.id ? '编辑' : '新增'
},
},
created() {
beforeMount() {
this.hanldeListOptions()
},
methods: {
@ -255,7 +279,7 @@ export default {
this.queryParam.sort = this.pagination.sort
optionApi
.query(this.queryParam)
.then(response => {
.then((response) => {
this.options = response.data.data.content
this.pagination.total = response.data.data.total
})
@ -271,7 +295,7 @@ export default {
handleDeleteOption(id) {
optionApi
.delete(id)
.then(response => {
.then((response) => {
this.$message.success('删除成功!')
})
.finally(() => {
@ -280,8 +304,8 @@ export default {
})
},
handleEditOption(option) {
this.optionToStage = option
this.formVisible = true
this.form.model = option
this.form.visible = true
},
handlePaginationChange(page, pageSize) {
this.$log.debug(`Current: ${page}, PageSize: ${pageSize}`)
@ -295,51 +319,51 @@ export default {
this.handlePaginationChange(1, this.pagination.size)
},
onFormClose() {
this.formVisible = false
this.optionToStage = {}
this.form.visible = false
this.form.model = {}
},
createOrUpdateOption() {
if (!this.optionToStage.key) {
this.$notification['error']({
message: '提示',
description: 'Key 不能为空!'
})
return
}
if (!this.optionToStage.value) {
this.$notification['error']({
message: '提示',
description: 'Value 不能为空!'
})
return
}
if (this.optionToStage.id) {
optionApi
.update(this.optionToStage.id, this.optionToStage)
.then(response => {
this.$message.success('更新成功!')
this.optionToStage = {}
this.formVisible = false
})
.finally(() => {
this.hanldeListOptions()
this.refreshOptionsCache()
})
handleSaveOrUpdate() {
const _this = this
_this.$refs.optionForm.validate((valid) => {
if (valid) {
_this.form.saving = true
if (_this.form.model.id) {
optionApi
.update(_this.form.model.id, _this.form.model)
.catch(() => {
_this.form.saveErrored = true
})
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 400)
})
} else {
_this.form.model.type = _this.optionType.CUSTOM.value
optionApi
.create(_this.form.model)
.catch(() => {
_this.form.saveErrored = true
})
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 400)
})
}
}
})
},
handleSaveOrUpdateCallback() {
if (this.form.saveErrored) {
this.form.saveErrored = false
} else {
this.optionToStage.type = this.optionType.CUSTOM.value
optionApi
.create(this.optionToStage)
.then(response => {
this.$message.success('保存成功!')
this.optionToStage = {}
this.formVisible = false
})
.finally(() => {
this.hanldeListOptions()
this.refreshOptionsCache()
})
this.form.model = {}
this.form.visible = false
this.hanldeListOptions()
this.refreshOptionsCache()
}
}
}
},
},
}
</script>

View File

@ -24,10 +24,12 @@
<a-button
type="primary"
@click="handleLoadLogsLines()"
:loading="loading"
>刷新</a-button>
<a-button
type="dashed"
@click="handleDownloadLogFile()"
:loading="downloading"
>下载</a-button>
</a-space>
</a-form-item>
@ -41,7 +43,7 @@ import moment from 'moment'
export default {
name: 'RuntimeLogs',
components: {
codemirror
codemirror,
},
data() {
return {
@ -49,14 +51,15 @@ export default {
tabSize: 4,
mode: 'shell',
lineNumbers: true,
line: true
line: true,
},
logContent: '',
loading: false,
logLines: 200
logLines: 200,
downloading: false,
}
},
created() {
beforeMount() {
this.handleLoadLogsLines()
},
updated() {
@ -68,20 +71,21 @@ export default {
this.loading = true
adminApi
.getLogFiles(this.logLines)
.then(response => {
.then((response) => {
this.logContent = response.data.data
})
.finally(() => {
setTimeout(() => {
this.loading = false
}, 200)
}, 400)
})
},
handleDownloadLogFile() {
const hide = this.$message.loading('下载中...', 0)
this.downloading = true
adminApi
.getLogFiles(this.logLines)
.then(response => {
.then((response) => {
var blob = new Blob([response.data.data])
var downloadElement = document.createElement('a')
var href = window.URL.createObjectURL(blob)
@ -91,15 +95,17 @@ export default {
downloadElement.click()
document.body.removeChild(downloadElement)
window.URL.revokeObjectURL(href)
this.$message.success('下载成功!')
})
.catch(() => {
this.$message.error('下载失败!')
})
.finally(() => {
hide()
setTimeout(() => {
this.downloading = false
hide()
}, 400)
})
}
}
},
},
}
</script>

View File

@ -8,18 +8,18 @@
<a-button
type="primary"
icon="cloud-upload"
@click="() => (uploadVisible = true)"
@click="uploadModal.visible = true"
>上传</a-button>
<a-button
icon="plus"
@click="handleShowCreateFolderModal({})"
@click="handleOpenCreateDirectoryModal({})"
>
新建文件夹
</a-button>
<a-button
icon="sync"
@click="handleListStatics"
:loading="loading"
:loading="list.loading"
>
刷新
</a-button>
@ -27,11 +27,11 @@
<div class="mt-4">
<a-table
:rowKey="record => record.id"
:columns="columns"
:columns="list.columns"
:dataSource="sortedStatics"
:pagination="false"
size="middle"
:loading="loading"
:loading="list.loading"
>
<span
slot="name"
@ -55,7 +55,7 @@
slot-scope="text, record"
>
<a
href="javascript:;"
href="javascript:void(0);"
v-if="!record.isFile"
@click="handleUpload(record)"
>上传</a>
@ -76,8 +76,8 @@
v-if="!record.isFile"
>
<a
href="javascript:;"
@click="handleShowCreateFolderModal(record)"
href="javascript:void(0);"
@click="handleOpenCreateDirectoryModal(record)"
>创建文件夹</a>
</a-menu-item>
<a-menu-item key="2">
@ -87,13 +87,13 @@
cancelText="取消"
@confirm="handleDelete(record.relativePath)"
>
<a href="javascript:;">删除</a>
<a href="javascript:void(0);">删除</a>
</a-popconfirm>
</a-menu-item>
<a-menu-item key="3">
<a
href="javascript:;"
@click="handleShowRenameModal(record)"
href="javascript:void(0);"
@click="handleOpenRenameModal(record)"
>重命名</a>
</a-menu-item>
<a-menu-item
@ -101,8 +101,8 @@
v-if="record.isFile"
>
<a
href="javascript:;"
@click="handleShowEditModal(record)"
href="javascript:void(0);"
@click="handleOpenEditContentModal(record)"
>编辑</a>
</a-menu-item>
</a-menu>
@ -113,64 +113,88 @@
</a-card>
<a-modal
title="上传文件"
v-model="uploadVisible"
v-model="uploadModal.visible"
:footer="null"
:afterClose="onUploadClose"
:afterClose="onUploadModalClose"
destroyOnClose
>
<FilePondUpload
ref="upload"
name="file"
:uploadHandler="uploadHandler"
:filed="selectedFile.relativePath"
:uploadHandler="uploadModal.uploadHandler"
:filed="list.selected.relativePath"
></FilePondUpload>
</a-modal>
<a-modal
v-model="createFolderModal"
:afterClose="onCreateFolderClose"
v-model="directoryForm.visible"
:afterClose="onDirectoryFormModalClose"
title="创建文件夹"
>
<template slot="footer">
<a-button
key="submit"
type="primary"
@click="handleCreateFolder()"
>创建</a-button>
<ReactiveButton
@click="handleCreateDirectory"
@callback="handleCreateDirectoryCallback"
:loading="directoryForm.saving"
:errored="directoryForm.saveErrored"
text="创建"
loadedText="创建成功"
erroredText="创建失败"
></ReactiveButton>
</template>
<a-form layout="vertical">
<a-form-item label="文件夹名:">
<a-form-model
ref="directoryForm"
:model="directoryForm.model"
:rules="directoryForm.rules"
layout="vertical"
>
<a-form-model-item
prop="name"
label="文件夹名:"
>
<a-input
ref="createFoldeInput"
v-model="createFolderName"
@keyup.enter="handleCreateFolder"
ref="createDirectoryInput"
v-model="directoryForm.model.name"
@keyup.enter="handleCreateDirectory"
/>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</a-modal>
<a-modal
v-model="renameModal"
:afterClose="onRenameClose"
v-model="renameForm.visible"
:afterClose="onRenameModalClose"
title="重命名"
>
<template slot="footer">
<a-button
key="submit"
type="primary"
@click="handleRename()"
>重命名</a-button>
<ReactiveButton
@click="handleRenameDirectoryOrFile"
@callback="handleRenameDirectoryOrFileCallback"
:loading="renameForm.saving"
:errored="renameForm.saveErrored"
text="重命名"
loadedText="重命名成功"
erroredText="重命名失败"
></ReactiveButton>
</template>
<a-form layout="vertical">
<a-form-item :label="renameFile?'文件名:':'文件夹名:'">
<a-form-model
ref="renameForm"
:model="renameForm.model"
:rules="renameForm.rules"
layout="vertical"
>
<a-form-model-item
prop="name"
:label="list.selected.isFile?'文件名:':'文件夹名:'"
>
<a-input
ref="renameModalInput"
v-model="renameName"
@keyup.enter="handleRename"
v-model="renameForm.model.name"
@keyup.enter="handleRenameDirectoryOrFile"
/>
</a-form-item>
</a-form>
</a-form-model-item>
</a-form-model>
</a-modal>
<a-modal
v-model="editModal"
v-model="editContentForm.visible"
title="编辑文件"
width="80%"
style="max-width: 1000px"
@ -183,22 +207,26 @@
title="未保存的内容将会丢失,确定要退出吗?"
okText="确定"
cancelText="取消"
@confirm="handleEditClose"
@confirm="handleEditContentModalClose"
>
<a-button>取消</a-button>
</a-popconfirm>
<a-button
key="submit"
type="primary"
@click="handleEditSave()"
>保存</a-button>
<ReactiveButton
@click="handleContentEdit"
@callback="handleContentEditCallback"
:loading="editContentForm.saving"
:errored="editContentForm.saveErrored"
text="保存"
loadedText="保存成功"
erroredText="保存失败"
></ReactiveButton>
</template>
<a-form layout="vertical">
<a-form-item>
<codemirror
ref="editor"
:value="editContent"
:options="codemirrorOptions"
:value="editContentForm.model.content"
:options="editContentForm.codeMirror.options"
></codemirror>
</a-form-item>
</a-form>
@ -206,7 +234,6 @@
</div>
</template>
<script>
import Vue from 'vue'
import { mapGetters } from 'vuex'
import staticApi from '@/api/static'
import { codemirror } from 'vue-codemirror-lite'
@ -216,86 +243,119 @@ const columns = [
{
title: '文件名',
dataIndex: 'name',
scopedSlots: { customRender: 'name' }
scopedSlots: { customRender: 'name' },
},
{
title: '文件类型',
dataIndex: 'mimeType',
scopedSlots: { customRender: 'mimeType' }
scopedSlots: { customRender: 'mimeType' },
},
{
title: '上传时间',
dataIndex: 'createTime',
width: '200px',
scopedSlots: { customRender: 'createTime' }
scopedSlots: { customRender: 'createTime' },
},
{
title: '操作',
dataIndex: 'action',
width: '120px',
scopedSlots: { customRender: 'action' }
}
scopedSlots: { customRender: 'action' },
},
]
export default {
components: {
codemirror
codemirror,
},
name: 'StaticStorage',
data() {
return {
columns: columns,
statics: [],
loading: false,
uploadHandler: staticApi.upload,
uploadVisible: false,
selectedFile: {},
createFolderModal: false,
createFolderName: '',
renameModal: false,
renameName: '',
renameFile: false,
codemirrorOptions: {
tabSize: 4,
lineNumbers: true,
line: true
list: {
columns: columns,
data: [],
loading: false,
selected: {},
},
uploadModal: {
visible: false,
uploadHandler: staticApi.upload,
},
directoryForm: {
model: {
name: null,
},
visible: false,
saving: false,
saveErrored: false,
rules: {
name: [{ required: true, message: '* 文件夹名不能为空', trigger: ['change'] }],
},
},
renameForm: {
model: {
name: null,
},
visible: false,
saving: false,
saveErrored: false,
rules: {
name: [{ required: true, message: '* 文件夹名不能为空', trigger: ['change'] }],
},
},
editContentForm: {
model: {
content: null,
},
visible: false,
saving: false,
saveErrored: false,
codeMirror: {
instance: null,
options: {
tabSize: 4,
lineNumbers: true,
line: true,
},
},
},
editModal: false,
editContent: '',
CodeMirror: null
}
},
created() {
beforeMount() {
this.handleListStatics()
this.CodeMirror = require('codemirror')
this.CodeMirror.modeURL = 'codemirror/mode/%N/%N.js'
this.editContentForm.codeMirror.instance = require('codemirror')
this.editContentForm.codeMirror.instance.modeURL = 'codemirror/mode/%N/%N.js'
},
computed: {
...mapGetters(['options']),
sortedStatics() {
const data = this.statics.slice(0)
const data = this.list.data.slice(0)
return data.sort(function(a, b) {
return a.isFile - b.isFile
})
}
},
},
methods: {
handleListStatics() {
this.loading = true
this.list.loading = true
staticApi
.list()
.then(response => {
this.statics = response.data.data
.then((response) => {
this.list.data = response.data.data
})
.finally(() => {
setTimeout(() => {
this.loading = false
this.list.loading = false
}, 200)
})
},
handleDelete(path) {
staticApi
.delete(path)
.then(response => {
.then((response) => {
this.$message.success(`删除成功!`)
})
.finally(() => {
@ -303,25 +363,51 @@ export default {
})
},
handleUpload(file) {
this.selectedFile = file
this.uploadVisible = true
this.list.selected = file
this.uploadModal.visible = true
},
handleShowCreateFolderModal(file) {
this.selectedFile = file
this.createFolderModal = true
const that = this
Vue.nextTick().then(() => {
that.$refs.createFoldeInput.focus()
handleOpenCreateDirectoryModal(file) {
const _this = this
_this.list.selected = file
_this.directoryForm.visible = true
_this.$nextTick(() => {
_this.$refs.createDirectoryInput.focus()
})
},
handleShowRenameModal(file) {
this.selectedFile = file
this.renameName = file.name
this.renameFile = file.isFile
this.renameModal = true
const that = this
Vue.nextTick().then(() => {
const inputRef = that.$refs.renameModalInput
handleCreateDirectory() {
const _this = this
_this.$refs.directoryForm.validate((valid) => {
if (valid) {
this.directoryForm.saving = true
staticApi
.createFolder(_this.list.selected.relativePath, _this.directoryForm.model.name)
.catch(() => {
_this.directoryForm.saveErrored = true
})
.finally(() => {
setTimeout(() => {
this.directoryForm.saving = false
}, 400)
})
}
})
},
handleCreateDirectoryCallback() {
if (this.directoryForm.saveErrored) {
this.directoryForm.saveErrored = false
} else {
this.directoryForm.model = {}
this.directoryForm.visible = false
this.handleListStatics()
}
},
handleOpenRenameModal(file) {
const _this = this
_this.list.selected = file
_this.$set(_this.renameForm.model, 'name', file.name)
_this.renameForm.visible = true
_this.$nextTick(() => {
const inputRef = _this.$refs.renameModalInput
const tmp = inputRef.value.split('.')
inputRef.focus()
if (tmp.length <= 1) {
@ -331,71 +417,93 @@ export default {
}
})
},
handleShowEditModal(file) {
this.selectedFile = file
handleRenameDirectoryOrFile() {
const _this = this
_this.$refs.renameForm.validate((valid) => {
if (valid) {
this.renameForm.saving = true
staticApi
.rename(_this.list.selected.relativePath, _this.renameForm.model.name)
.catch(() => {
_this.renameForm.saveErrored = true
})
.finally(() => {
setTimeout(() => {
this.renameForm.saving = false
}, 400)
})
}
})
},
handleRenameDirectoryOrFileCallback() {
if (this.renameForm.saveErrored) {
this.renameForm.saveErrored = false
} else {
this.renameForm.model = {}
this.renameForm.visible = false
this.handleListStatics()
}
},
handleOpenEditContentModal(file) {
const _this = this
_this.list.selected = file
const arr = file.name.split('.')
const postfix = arr[arr.length - 1]
staticApi.getContent(this.options.blog_url + file.relativePath).then(response => {
this.editContent = response.data
const info = this.CodeMirror.findModeByExtension(postfix)
staticApi.getContent(_this.options.blog_url + file.relativePath).then((response) => {
_this.editContentForm.model.content = response.data
const info = _this.editContentForm.codeMirror.instance.findModeByExtension(postfix)
if (info === undefined) {
this.$message.error(`不支持编辑 "${postfix}" 类型的文件`)
_this.$message.error(`不支持编辑 "${postfix}" 类型的文件`)
} else {
this.editModal = true
Vue.nextTick().then(() => {
const editor = this.$refs.editor.editor
_this.editContentForm.visible = true
_this.$nextTick(() => {
const editor = _this.$refs.editor.editor
editor.setOption('mode', info.mime)
this.CodeMirror.autoLoadMode(editor, info.mode)
_this.editContentForm.codeMirror.instance.autoLoadMode(editor, info.mode)
})
}
})
},
handleCreateFolder() {
handleContentEdit() {
this.editContentForm.saving = true
staticApi
.createFolder(this.selectedFile.relativePath, this.createFolderName)
.then(response => {
this.$message.success(`创建文件夹成功!`)
this.createFolderModal = false
.save(this.list.selected.relativePath, this.$refs.editor.editor.getValue())
.catch(() => {
this.editContentForm.saveErrored = true
})
.finally(() => {
this.handleListStatics()
setTimeout(() => {
this.editContentForm.saving = false
}, 400)
})
},
handleRename() {
staticApi
.rename(this.selectedFile.relativePath, this.renameName)
.then(response => {
this.$message.success(`重命名成功!`)
this.renameModal = false
})
.finally(() => {
this.handleListStatics()
})
handleContentEditCallback() {
if (this.editContentForm.saveErrored) {
this.editContentForm.saveErrored = false
} else {
this.editContentForm.model = {}
this.editContentForm.visible = false
this.handleListStatics()
}
},
handleEditSave() {
staticApi.save(this.selectedFile.relativePath, this.$refs.editor.editor.getValue()).then(response => {
this.$message.success(`文件保存成功!`)
this.editModal = false
})
onDirectoryFormModalClose() {
this.list.selected = {}
this.$set(this.directoryForm.model, 'name', null)
},
onCreateFolderClose() {
this.selectedFile = {}
this.createFolderName = ''
onRenameModalClose() {
this.list.selected = {}
this.$set(this.renameForm.model, 'name', null)
},
onRenameClose() {
this.selectedFile = {}
this.renameName = ''
},
onUploadClose() {
onUploadModalClose() {
this.$refs.upload.handleClearFileList()
this.selectedFile = {}
this.list.selected = {}
this.handleListStatics()
},
handleEditClose() {
this.editModal = false
this.selectedFile = {}
this.editContent = ''
}
}
handleEditContentModalClose() {
this.editContentForm.visible = false
this.list.selected = {}
this.editContentForm.model.content = ''
},
},
}
</script>