feat(announcement): 新增首页弹窗公告功能并完成弹窗UI视觉重构

- 数据库与后端:announcements 表增加 is_popup 字段及迁移脚本,提供前台弹窗接口与多公告优先级选取,补全选优单测
- 管理后台:总后台与分销后台公告编辑新增「弹窗公告」开关与列表标签展示
- 前台交互:前台 PC/移动端首页引入 AnnouncementPopup,支持同一用户同一天同一公告仅弹一次的关闭记录
- 视觉优化:重构弹窗结构,顶栏镶嵌品牌橙流光细条与浅暖橙通知徽标,中间内嵌浅灰舒适阅读卡片,底部搭配大锤橙实心主操作按钮
- 验证方式:后端 announcement 单测通过,前端 npm run build 编译无报错,浏览器实机截图验证
This commit is contained in:
yml2213
2026-10-12 18:33:44 +08:00
parent 41d7ffd073
commit 4a9e5f9d66
20 changed files with 758 additions and 14 deletions
@@ -11,6 +11,8 @@ export interface CreateAnnouncementRequest {
priority?: number
is_pinned?: boolean
is_important?: boolean
/** 弹窗公告:前台首页弹出且需用户手动关闭,同一天只弹一次 */
is_popup?: boolean
}
export interface UpdateAnnouncementRequest {
@@ -20,6 +22,7 @@ export interface UpdateAnnouncementRequest {
priority?: number
is_pinned?: boolean
is_important?: boolean
is_popup?: boolean
}
export async function fetchAdminAnnouncements(params: {
@@ -55,6 +55,7 @@ const formData = ref<CreateAnnouncementRequest>({
priority: 0,
is_pinned: false,
is_important: false,
is_popup: false,
})
// 站点列表:0=主站(默认),其余为分站;公告归属站点只在新建时可选。
@@ -118,6 +119,7 @@ watch(
priority: props.announcement.priority,
is_pinned: props.announcement.is_pinned,
is_important: props.announcement.is_important,
is_popup: props.announcement.is_popup,
}
} else {
formData.value = {
@@ -128,6 +130,7 @@ watch(
priority: 0,
is_pinned: false,
is_important: false,
is_popup: false,
}
}
void loadDistributionSites()
@@ -390,6 +393,13 @@ function escapeMarkdownImageText(text: string) {
<el-form-item label="标记">
<el-checkbox v-model="formData.is_pinned">置顶</el-checkbox>
<el-checkbox v-model="formData.is_important" style="margin-left: 20px">重要</el-checkbox>
<el-checkbox v-model="formData.is_popup" style="margin-left: 20px">弹窗公告</el-checkbox>
</el-form-item>
<el-form-item v-if="formData.is_popup" label=" ">
<span class="popup-tip">
该公告会在对应站点首页弹出,用户必须手动点击「我知道了」才能关闭;同一天同一条只弹一次,次日重新弹出。多条弹窗公告同时启用时只弹优先级最高的一条。
</span>
</el-form-item>
</el-form>
@@ -502,6 +512,12 @@ function escapeMarkdownImageText(text: string) {
flex-wrap: wrap;
}
.popup-tip {
color: #909399;
font-size: 13px;
line-height: 1.6;
}
:deep(.el-textarea__inner) {
font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
font-size: 13px;
@@ -308,6 +308,9 @@ function getStatusType(status: string): '' | 'success' | 'info' | 'warning' {
<el-tag v-if="row.is_important" type="danger" size="small" effect="plain"
>重要</el-tag
>
<el-tag v-if="row.is_popup" type="primary" size="small" effect="plain"
>弹窗公告</el-tag
>
</div>
</div>
</template>