u
This commit is contained in:
1 parent
9aa4a72321
commit
9bf7c40b70
40 files changed
+918
-189
No files matched your search
@@ -1,10 +1,324 @@
|
||||
<script lang="ts" setup>
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import type { PostEditorForm } from '@/types/post'
|
||||
import type { PostTag } from '@/types/post/tag'
|
||||
import type { UploadImageResponse } from '@/utils/file'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import CustomLoading from '@/components/CustomLoading.vue'
|
||||
import ImageUploadCard from '@/components/ImageUploadCard.vue'
|
||||
import WangEditor from '@/components/wang-editor/index.vue'
|
||||
import { addPostApi } from '@/request/api/post'
|
||||
import { getPostTagApi } from '@/request/api/post/tag'
|
||||
import { uploadImage, uploadToAliyun } from '@/utils/file'
|
||||
|
||||
const wangEditorRef = ref<any>(null)
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const loading = reactive({
|
||||
init: true,
|
||||
confirm: false,
|
||||
})
|
||||
|
||||
const showPushDrawer = ref<boolean>(false)
|
||||
const imageUpload = ref<UploadImageResponse | null>(null)
|
||||
|
||||
const tagOptions = ref<PostTag[]>([])
|
||||
const statusOptions = [
|
||||
{
|
||||
label: '草稿',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '发布',
|
||||
value: 1,
|
||||
},
|
||||
]
|
||||
|
||||
const oldForm = ref<PostEditorForm>({
|
||||
id: 0,
|
||||
title: '',
|
||||
content: '',
|
||||
summary: '',
|
||||
cover: '',
|
||||
tags: [],
|
||||
publishTime: '',
|
||||
updateTime: '',
|
||||
status: 0,
|
||||
})
|
||||
|
||||
const form = ref<PostEditorForm>({
|
||||
id: 0,
|
||||
title: '',
|
||||
content: '',
|
||||
summary: '',
|
||||
cover: '',
|
||||
tags: [],
|
||||
publishTime: '',
|
||||
updateTime: '',
|
||||
status: 0,
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
title: [
|
||||
{ required: true, message: '文章标题不能为空', trigger: 'blur' },
|
||||
],
|
||||
summary: [
|
||||
{ required: true, message: '摘要不能为空', trigger: 'blur' },
|
||||
],
|
||||
status: [
|
||||
{ required: true, message: '状态不能为空', trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
|
||||
const isUpdate = computed(() => form.value.id !== 0)
|
||||
|
||||
onMounted(() => {
|
||||
loading.init = false
|
||||
|
||||
oldForm.value = JSON.parse(JSON.stringify(form.value))
|
||||
})
|
||||
|
||||
async function handleShowPushDrawer() {
|
||||
loading.init = true
|
||||
showPushDrawer.value = true
|
||||
|
||||
if (!isUpdate.value) {
|
||||
form.value.summary = (wangEditorRef.value.getText() || '').slice(0, 100)
|
||||
}
|
||||
|
||||
await getPostTagApi().then((res) => {
|
||||
if (res.isSuccess) {
|
||||
tagOptions.value = res.data
|
||||
}
|
||||
else {
|
||||
ElMessage.error(res.message || '获取帖子标签失败,请稍后再试')
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
ElMessage.error('获取帖子标签失败,请稍后再试')
|
||||
})
|
||||
|
||||
loading.init = false
|
||||
}
|
||||
|
||||
async function handleSave(formEl: FormInstance | undefined) {
|
||||
if (!formEl)
|
||||
return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (!valid)
|
||||
return
|
||||
|
||||
if (form.value.content === '') {
|
||||
ElMessage.warning('文章内容不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
loading.confirm = true
|
||||
|
||||
if (form.value.cover !== oldForm.value.cover) {
|
||||
if (form.value.cover && imageUpload.value !== null) {
|
||||
const aliyunRes = await uploadToAliyun(imageUpload.value.blob, imageUpload.value.name, imageUpload.value.size, false)
|
||||
form.value.cover = aliyunRes.url
|
||||
}
|
||||
}
|
||||
|
||||
addPostApi({
|
||||
title: form.value.title,
|
||||
content: form.value.content,
|
||||
summary: form.value.summary,
|
||||
status: form.value.status,
|
||||
cover: form.value.cover,
|
||||
tags: form.value.tags,
|
||||
}).then((res) => {
|
||||
if (res.isSuccess) {
|
||||
console.log(res)
|
||||
}
|
||||
else {
|
||||
ElMessage.error(res.message || '保存失败,请稍后再试')
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
ElMessage.error('保存失败,请稍后再试')
|
||||
}).finally(() => {
|
||||
loading.confirm = false
|
||||
|
||||
showPushDrawer.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="" />
|
||||
<div class="editor-container">
|
||||
<div class="toolbar">
|
||||
<input v-model="form.title" placeholder="输入标题" class="editor-title-input" maxlength="100">
|
||||
<div class="toolbar-extra">
|
||||
<div v-if="form.publishTime" class="time">
|
||||
更新于:{{ form.publishTime }}
|
||||
</div>
|
||||
<el-button type="primary" @click="handleShowPushDrawer()">
|
||||
发布
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<WangEditor ref="wangEditorRef" v-model="form.content" :show-direcotry="true" />
|
||||
</div>
|
||||
|
||||
<el-drawer v-model="showPushDrawer" title="发布文章">
|
||||
<CustomLoading v-if="loading.init" :in-container="true" />
|
||||
|
||||
<el-form
|
||||
v-else
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="formRules"
|
||||
label-width="auto"
|
||||
>
|
||||
<el-form-item label="文章标题" prop="title">
|
||||
<el-input
|
||||
v-model="form.title"
|
||||
placeholder="请输入文字标题"
|
||||
size="large"
|
||||
show-word-limit
|
||||
maxlength="100"
|
||||
type="textarea"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="标签" prop="tags">
|
||||
<el-select v-model="form.tags" placeholder="请选择标签">
|
||||
<el-option
|
||||
v-for="item in tagOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="文章封面 " prop="cover">
|
||||
<ImageUploadCard
|
||||
v-model="form.cover"
|
||||
@change="(data) => {
|
||||
imageUpload = data
|
||||
}"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="文章摘要" prop="summary">
|
||||
<el-input
|
||||
v-model="form.summary"
|
||||
placeholder="请输入文章摘要"
|
||||
size="large"
|
||||
show-word-limit
|
||||
maxlength="100"
|
||||
type="textarea"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="form.status" placeholder="请选择状态">
|
||||
<el-option
|
||||
v-for="item in statusOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div style="flex: auto">
|
||||
<el-button>
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" :loading="loading.confirm" @click="handleSave(formRef)">
|
||||
确认并发布
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
//
|
||||
.editor-container {
|
||||
padding: 16px 32px;
|
||||
.toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
.editor-title-input {
|
||||
width: 1000px;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
padding: 8px 0px;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
resize: none;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.toolbar-extra {
|
||||
.time {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-card {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #fafafa;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.3s ease;
|
||||
padding: 4px;
|
||||
&:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
&.loading {
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.upload-inner {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.upload-loading-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.upload-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-cover {
|
||||
height: 192px;
|
||||
width: 128px;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user