<script setup lang="ts">
|
import { onMounted, reactive, ref } from 'vue'
|
import { useRoute, useRouter } from 'vue-router'
|
import { ElMessage } from 'element-plus'
|
import type { FormInstance, FormRules, UploadFile } from 'element-plus'
|
import { getAdminNewsDetail, updateAdminNews, uploadAdminImage } from '../api/admin'
|
import AdminRichTextEditor from '../components/AdminRichTextEditor.vue'
|
|
interface NewsForm {
|
title: string
|
summary: string
|
source: string
|
content: string
|
pinned: boolean
|
coverUrl: string
|
sortNo: number
|
status: number
|
}
|
|
const form = reactive<NewsForm>({
|
title: '',
|
summary: '',
|
source: '',
|
content: '',
|
pinned: false,
|
coverUrl: '',
|
sortNo: 0,
|
status: 1,
|
})
|
|
const route = useRoute()
|
const router = useRouter()
|
const formRef = ref<FormInstance>()
|
const createdAt = ref('-')
|
const updatedAt = ref('-')
|
const author = ref('-')
|
|
const stripHtml = (value: string) => value.replace(/<[^>]*>/g, '').replace(/ /g, '').trim()
|
const rules: FormRules = {
|
title: [{ required: true, message: '请输入资讯标题', trigger: 'blur' }],
|
summary: [{ required: true, message: '请输入资讯标签', trigger: 'blur' }],
|
content: [{
|
required: true,
|
trigger: 'change',
|
validator: (_rule, value: string, callback) => {
|
if (!stripHtml(value || '')) callback(new Error('请输入资讯内容'))
|
else callback()
|
},
|
}],
|
coverUrl: [{ required: true, message: '请上传封面图', trigger: 'change' }],
|
}
|
|
async function uploadCover(file: UploadFile) {
|
if (!file.raw) return
|
const result = await uploadAdminImage(file.raw)
|
form.coverUrl = result.url
|
await formRef.value?.validateField('coverUrl')
|
ElMessage.success('封面图上传成功')
|
}
|
|
function formatTime(value?: string) {
|
return value ? value.replace('T', ' ').slice(0, 19) : '-'
|
}
|
|
async function loadNews() {
|
const article = await getAdminNewsDetail(String(route.params.id))
|
form.title = article.title
|
form.summary = article.summary || ''
|
form.source = article.source || ''
|
form.content = article.content || ''
|
form.pinned = Boolean(article.isTop)
|
form.coverUrl = article.coverUrl || ''
|
form.sortNo = Number(article.sortNo || 0)
|
form.status = Number(article.status ?? 1)
|
author.value = article.author || '-'
|
createdAt.value = formatTime(article.createdAt)
|
updatedAt.value = formatTime(article.updatedAt)
|
}
|
|
function validateContent() {
|
void formRef.value?.validateField('content')
|
}
|
|
async function saveNews() {
|
const valid = await formRef.value?.validate().catch(() => false)
|
if (!valid) return
|
await updateAdminNews(String(route.params.id), {
|
title: form.title.trim(),
|
summary: form.summary.trim(),
|
source: form.source.trim(),
|
content: form.content,
|
coverUrl: form.coverUrl.trim(),
|
isTop: form.pinned,
|
sortNo: form.sortNo,
|
status: form.status,
|
})
|
ElMessage.success('资讯已保存')
|
router.push('/talent-news-management')
|
}
|
|
onMounted(() => void loadNews())
|
</script>
|
|
<template>
|
<div class="news-edit-page">
|
<section class="news-meta-panel">
|
<h3>发布信息</h3>
|
<div class="news-meta-grid">
|
<div>
|
<span>发布人</span>
|
<strong>{{ author }}</strong>
|
</div>
|
<div>
|
<span>发布时间</span>
|
<strong>{{ createdAt }}</strong>
|
</div>
|
<div>
|
<span>修改人</span>
|
<strong>{{ author }}</strong>
|
</div>
|
<div>
|
<span>修改时间</span>
|
<strong>{{ updatedAt }}</strong>
|
</div>
|
</div>
|
</section>
|
|
<section class="news-publish-panel">
|
<h3>资讯内容</h3>
|
|
<el-form ref="formRef" class="news-publish-form" :model="form" :rules="rules" label-width="96px" label-position="left">
|
<el-form-item label="资讯标题" prop="title" required>
|
<el-input v-model="form.title" placeholder="资讯标题" />
|
</el-form-item>
|
|
<el-form-item label="资讯标签" prop="summary" required>
|
<el-input v-model="form.summary" placeholder="资讯标签" />
|
</el-form-item>
|
|
<el-form-item class="news-editor-form-item" label="资讯内容" prop="content" required>
|
<AdminRichTextEditor v-model="form.content" placeholder="请输入资讯内容" @update:model-value="validateContent" />
|
</el-form-item>
|
|
<el-form-item label="是否置顶">
|
<el-switch v-model="form.pinned" />
|
</el-form-item>
|
|
<el-form-item label="封面图" prop="coverUrl" required>
|
<el-upload class="article-cover-upload" accept="image/*" :auto-upload="false" :show-file-list="false" :on-change="uploadCover">
|
<el-image v-if="form.coverUrl" class="article-cover-preview" :src="form.coverUrl" fit="cover" />
|
<div v-else class="article-cover-upload-card"><span>+</span><small>上传图片</small></div>
|
</el-upload>
|
<div class="admin-image-size-tip">推荐尺寸 236 × 168 px(小程序资讯列表缩略图;首页置顶大图会按 712 × 205 裁剪)</div>
|
</el-form-item>
|
|
<el-form-item>
|
<el-button type="primary" @click="saveNews">保存</el-button>
|
</el-form-item>
|
</el-form>
|
</section>
|
</div>
|
</template>
|