置顶公告视觉增强 + 请假销假页接入公告条
ci/woodpecker/tag/build Pipeline was successful

1. 公告条美化(PinnedNotice.vue)
   - 增加左侧琥珀色渐变强调条,提升顶部存在感
   - 增加 hover 态阴影过渡,点击反馈更明确
   - 卡片背景改为更通透的柠檬暖色玻璃

2. 请假/销假页接入置顶公告(LeaveView.vue)
   - 引入 PinnedNotice 与 announceApi
   - onMounted 中异步拉取置顶公告,失败静默降级为空列表
     (不阻塞页面主体加载)
   - 公告条置于页面最顶部,与打卡页位置和交互一致
     (翻页、长文本横向滚动、点击查看全部)

npm run build 与 vue-tsc 均通过。
This commit is contained in:
becomer
2026-10-21 13:26:22 +08:00
parent fab756a1ef
commit 608dee697f
2 changed files with 35 additions and 1 deletions
+17 -1
View File
@@ -194,11 +194,27 @@ onUnmounted(() => {
<style scoped> <style scoped>
/* 卡片:柠檬暖色玻璃(亮)/ 暗金半透明(暗),与品牌薄荷色区分开,表达「提醒」语义 */ /* 卡片:柠檬暖色玻璃(亮)/ 暗金半透明(暗),与品牌薄荷色区分开,表达「提醒」语义 */
.notice-card { .notice-card {
background: linear-gradient(135deg, rgb(255 246 214 / 0.92), rgb(255 250 235 / 0.86)); position: relative;
background: linear-gradient(135deg, rgb(255 246 214 / 0.95), rgb(255 250 235 / 0.9));
border: 1px solid rgb(245 189 46 / 0.32); border: 1px solid rgb(245 189 46 / 0.32);
box-shadow: 0 1px 2px rgb(138 90 0 / 0.06), 0 6px 16px rgb(227 160 8 / 0.1); box-shadow: 0 1px 2px rgb(138 90 0 / 0.06), 0 6px 16px rgb(227 160 8 / 0.1);
-webkit-backdrop-filter: blur(12px) saturate(160%); -webkit-backdrop-filter: blur(12px) saturate(160%);
backdrop-filter: blur(12px) saturate(160%); backdrop-filter: blur(12px) saturate(160%);
transition: box-shadow 0.25s ease, transform 0.15s ease;
}
/* 左侧琥珀色强调条:让公告在页面顶部更有存在感 */
.notice-card::before {
content: '';
position: absolute;
left: 0;
top: 20%;
bottom: 20%;
width: 3px;
border-radius: 9999px;
background: linear-gradient(180deg, #ffd166, #f5a623);
}
.notice-card:hover {
box-shadow: 0 2px 4px rgb(138 90 0 / 0.08), 0 10px 24px rgb(227 160 8 / 0.16);
} }
.notice-icon { .notice-icon {
color: #8a5a00; color: #8a5a00;
+18
View File
@@ -2,6 +2,9 @@
<!-- 请/销假页:上方请假+销假按钮(左右平分),下方请假/销假日志列表。 <!-- 请/销假页:上方请假+销假按钮(左右平分),下方请假/销假日志列表。
两者均为同步执行:请假 → 填表提交;销假 → 选请假单 → 填位置 → 立即销假。 --> 两者均为同步执行:请假 → 填表提交;销假 → 选请假单 → 填位置 → 立即销假。 -->
<div class="p-4 space-y-4"> <div class="p-4 space-y-4">
<!-- 置顶公告:与打卡页一致的顶部轮播条(见 PinnedNotice) -->
<PinnedNotice v-if="pinnedAnnouncements.length" :items="pinnedAnnouncements" class="rise-in" />
<!-- 入口卡片:请假 / 销假 按钮并排左右平分(珊瑚渐变头卡) --> <!-- 入口卡片:请假 / 销假 按钮并排左右平分(珊瑚渐变头卡) -->
<div class="relative overflow-hidden hero-clip rounded-3xl p-5 text-white shadow-lg shadow-rose-500/25 leave-hero rise-in"> <div class="relative overflow-hidden hero-clip rounded-3xl p-5 text-white shadow-lg shadow-rose-500/25 leave-hero rise-in">
<div class="pointer-events-none absolute -right-10 -top-12 w-40 h-40 rounded-full bg-white/15" /> <div class="pointer-events-none absolute -right-10 -top-12 w-40 h-40 rounded-full bg-white/15" />
@@ -800,6 +803,8 @@ import { CalendarCheck, CalendarPlus, CalendarClock, LoaderCircle, Trash2, X, Ma
import { resolveUploadFileName } from '@/utils/obsUpload' import { resolveUploadFileName } from '@/utils/obsUpload'
import * as leaveApi from '@/api/leave' import * as leaveApi from '@/api/leave'
import * as authApi from '@/api/auth' import * as authApi from '@/api/auth'
import * as announceApi from '@/api/announcement'
import PinnedNotice from '@/components/PinnedNotice.vue'
import type { LeaveItem, LeaveReportPlace, LeaveType } from '@/api/leave' import type { LeaveItem, LeaveReportPlace, LeaveType } from '@/api/leave'
import { useMessage } from '@/composables/useMessage' import { useMessage } from '@/composables/useMessage'
import { confirmDialog } from '@/composables/useConfirm' import { confirmDialog } from '@/composables/useConfirm'
@@ -815,6 +820,18 @@ function goTicket() {
} }
// ======== 销假日志 ======== // ======== 销假日志 ========
// ======== 置顶公告(顶部轮播条,与打卡页一致,渲染见 PinnedNotice) ========
const pinnedAnnouncements = ref<announceApi.PinnedAnnouncement[]>([])
async function loadPinnedAnnouncements() {
try {
const res = await announceApi.getPinnedAnnouncements()
pinnedAnnouncements.value = res.data.data || []
} catch {
pinnedAnnouncements.value = []
}
}
const loadingLogs = ref(false) const loadingLogs = ref(false)
const leaveLogs = ref<leaveApi.LeaveLog[]>([]) const leaveLogs = ref<leaveApi.LeaveLog[]>([])
@@ -1209,6 +1226,7 @@ const showBindDeviceDialog = ref(false)
onMounted(async () => { onMounted(async () => {
loadLogs() loadLogs()
void loadPinnedAnnouncements()
try { try {
const res = await authApi.getUserInfo() const res = await authApi.getUserInfo()
deviceCode.value = res.data.data?.mobileCode || '' deviceCode.value = res.data.data?.mobileCode || ''