shinnosuke
2026-09-18 c2f0ec3b3891bc177bdc58c2a111ab9c4fea911d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<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 { getAdminPolicyDetail, updateAdminPolicy, uploadAdminImage } from '../api/admin'
import AdminRichTextEditor from '../components/AdminRichTextEditor.vue'
 
const route = useRoute(); const router = useRouter(); const loading = ref(false)
const formRef = ref<FormInstance>()
const form = reactive({ title: '', subtitle: '', author: '', source: '', content: '', coverUrl: '', isTop: false, sortNo: 0, status: 1 })
const stripHtml = (value: string) => value.replace(/<[^>]*>/g, '').replace(/&nbsp;/g, '').trim()
const rules: FormRules = {
  title: [{ required: true, message: '请输入政策标题', trigger: 'blur' }],
  subtitle: [{ 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' }],
  sortNo: [{
    required: true,
    trigger: ['blur', 'change'],
    validator: (_rule, value: number, callback) => {
      if (!Number.isInteger(value) || value < 0) callback(new Error('请输入有效的排序值'))
      else callback()
    },
  }],
}
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 validateContent() { void formRef.value?.validateField('content') }
function formatTime(value?: string) { return value ? value.replace('T', ' ').slice(0, 19) : '-' }
// 发布人取创建该政策的管理员,修改人取最近一次保存的管理员;历史数据回落为发布人字段。
const publisher = ref('-'); const editor = ref('-'); const createdAt = ref('-'); const updatedAt = ref('-')
async function load() { loading.value = true; try { const item = await getAdminPolicyDetail(String(route.params.id)); form.title = item.title; form.subtitle = item.subtitle || ''; form.author = item.author || ''; form.source = item.source || ''; form.content = item.content || ''; form.coverUrl = item.coverUrl || ''; form.isTop = Boolean(item.isTop); form.sortNo = Number(item.sortNo || 0); form.status = Number(item.status ?? 0); publisher.value = item.createdByName || item.author || '-'; editor.value = item.updatedByName || item.author || '-'; createdAt.value = formatTime(item.createdAt); updatedAt.value = formatTime(item.updatedAt) } finally { loading.value = false } }
async function save() { const valid = await formRef.value?.validate().catch(() => false); if (!valid) return; await updateAdminPolicy(String(route.params.id), { ...form, title: form.title.trim(), subtitle: form.subtitle.trim(), author: form.author.trim(), source: form.source.trim(), coverUrl: form.coverUrl.trim() }); ElMessage.success('政策已保存'); router.push('/talent-policy-management') }
onMounted(() => void load())
</script>
<template>
  <div class="policy-edit-page" v-loading="loading"><section class="news-meta-panel"><h3>发布信息</h3><div class="news-meta-grid"><div><span>发布人</span><strong>{{ publisher }}</strong></div><div><span>发布时间</span><strong>{{ createdAt }}</strong></div><div><span>修改人</span><strong>{{ editor }}</strong></div><div><span>修改时间</span><strong>{{ updatedAt }}</strong></div></div></section><section class="policy-publish-panel"><h3>政策内容</h3><el-form ref="formRef" class="policy-publish-form" :model="form" :rules="rules" label-width="88px">
    <el-form-item label="政策标题" prop="title"><el-input v-model="form.title" /></el-form-item><el-form-item label="政策标签" prop="subtitle"><el-input v-model="form.subtitle" placeholder="请输入政策标签" /></el-form-item><el-form-item class="news-editor-form-item" label="政策内容" prop="content"><AdminRichTextEditor v-model="form.content" @update:model-value="validateContent" /></el-form-item><el-form-item label="封面图" prop="coverUrl"><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">推荐尺寸 750 × 320 px(小程序政策详情页顶部大图)</div></el-form-item><el-form-item label="是否置顶"><el-switch v-model="form.isTop" /></el-form-item><el-form-item label="排序" prop="sortNo"><el-input v-model.number="form.sortNo" type="number" placeholder="请输入非负整数" /></el-form-item><el-form-item><el-button type="primary" @click="save">保存</el-button></el-form-item>
  </el-form></section></div>
</template>