Files
education/frontend/node_modules/.cache/vue-loader/8df4df15c43e0b419d6819975cc2d84c.json
T

1 line
12 KiB
JSON

{"remainingRequest":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\index.js??vue-loader-options!C:\\Users\\Admin\\Desktop\\education\\frontend\\src\\layout\\components\\HeaderNotice\\index.vue?vue&type=style&index=0&id=02f62cf5&lang=scss&scoped=true","dependencies":[{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\src\\layout\\components\\HeaderNotice\\index.vue","mtime":1787567871537},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\css-loader\\dist\\cjs.js","mtime":1787309792478},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\loaders\\stylePostLoader.js","mtime":1787309794547},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\postcss-loader\\src\\index.js","mtime":1787309793084},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\sass-loader\\dist\\cjs.js","mtime":1787309791955},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\cache-loader\\dist\\cjs.js","mtime":1787309791955},{"path":"C:\\Users\\Admin\\Desktop\\education\\frontend\\node_modules\\vue-loader\\lib\\index.js","mtime":1787309793790}],"contextDependencies":[],"result":[{"type":"Buffer","data":"base64:CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoNCi5ub3RpY2UtdHJpZ2dlciB7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgZGlzcGxheTogaW5saW5lLWZsZXg7DQogIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICAvKiDoh6rouqvkuI3lvLrooYzpmZDliLblsLrlr7jvvIznlLHniLbnuqcgLmljb24tYnRuIOaOp+WItuWchuahhuWwuuWvuCAqLw0KICB3aWR0aDogMTAwJTsNCiAgaGVpZ2h0OiAxMDAlOw0KICAuc3ZnLWljb24geyB3aWR0aDogMThweDsgaGVpZ2h0OiAxOHB4OyBjb2xvcjogI2ZmZjsgfQ0KICAubm90aWNlLWJhZGdlIHsNCiAgICBwb3NpdGlvbjogYWJzb2x1dGU7DQogICAgdG9wOiAycHg7DQogICAgcmlnaHQ6IDJweDsNCiAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjZmY1ZTVlLCAjZjUyMjJkKTsNCiAgICBjb2xvcjogI2ZmZjsNCiAgICBib3JkZXItcmFkaXVzOiAxMHB4Ow0KICAgIGZvbnQtc2l6ZTogMTBweDsNCiAgICBoZWlnaHQ6IDE2cHg7DQogICAgbGluZS1oZWlnaHQ6IDE2cHg7DQogICAgcGFkZGluZzogMCA0cHg7DQogICAgbWluLXdpZHRoOiAxNnB4Ow0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgICB3aGl0ZS1zcGFjZTogbm93cmFwOw0KICAgIHBvaW50ZXItZXZlbnRzOiBub25lOw0KICAgIGZvbnQtd2VpZ2h0OiA2MDA7DQogICAgYm94LXNoYWRvdzogMCAycHggNnB4IHJnYmEoMjQ1LCAzNCwgNDUsIDAuNSk7DQogICAgYm9yZGVyOiAxLjVweCBzb2xpZCAjZmZmOw0KICAgIHRyYW5zZm9ybTogc2NhbGUoMC45Mik7DQogICAgdHJhbnNmb3JtLW9yaWdpbjogdG9wIHJpZ2h0Ow0KICB9DQp9DQoubm90aWNlLXBvcG92ZXIgew0KICBwYWRkaW5nOiAwICFpbXBvcnRhbnQ7DQp9DQoubm90aWNlLXBvcG92ZXIgLm5vdGljZS1oZWFkZXIgew0KICBkaXNwbGF5OiBmbGV4Ow0KICBhbGlnbi1pdGVtczogY2VudGVyOw0KICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47DQogIHBhZGRpbmc6IDEwcHggMTRweDsNCiAgYmFja2dyb3VuZDogI2Y3ZjlmYjsNCiAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNlZWU7DQogIGZvbnQtc2l6ZTogMTNweDsNCiAgZm9udC13ZWlnaHQ6IDYwMDsNCiAgY29sb3I6ICMzMzM7DQp9DQoubm90aWNlLXBvcG92ZXIgLm5vdGljZS1tYXJrLWFsbCB7DQogIGZvbnQtc2l6ZTogMTJweDsNCiAgY29sb3I6ICMwMDg3NUE7DQogIGZvbnQtd2VpZ2h0OiBub3JtYWw7DQogIGN1cnNvcjogcG9pbnRlcjsNCn0NCi5ub3RpY2UtcG9wb3ZlciAubm90aWNlLW1hcmstYWxsOmhvdmVyIHsgY29sb3I6ICMyYjdjYzE7IH0NCi5ub3RpY2UtcG9wb3ZlciAubm90aWNlLWxvYWRpbmcsDQoubm90aWNlLXBvcG92ZXIgLm5vdGljZS1lbXB0eSB7DQogIHBhZGRpbmc6IDI0cHg7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgY29sb3I6ICNiYmI7DQogIGZvbnQtc2l6ZTogMTJweDsNCiAgbGluZS1oZWlnaHQ6IDEuODsNCn0NCi5ub3RpY2UtcG9wb3ZlciAubm90aWNlLWl0ZW0gew0KICBkaXNwbGF5OiBmbGV4Ow0KICBhbGlnbi1pdGVtczogY2VudGVyOw0KICBnYXA6IDhweDsNCiAgcGFkZGluZzogMTBweCAxNHB4Ow0KICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI2Y1ZjVmNTsNCiAgY3Vyc29yOiBwb2ludGVyOw0KICB0cmFuc2l0aW9uOiBiYWNrZ3JvdW5kIDAuMTVzOw0KfQ0KLm5vdGljZS1wb3BvdmVyIC5ub3RpY2UtaXRlbTpsYXN0LWNoaWxkIHsgYm9yZGVyLWJvdHRvbTogbm9uZTsgfQ0KLm5vdGljZS1wb3BvdmVyIC5ub3RpY2UtaXRlbTpob3ZlciB7IGJhY2tncm91bmQ6ICNmN2Y5ZmI7IH0NCi5ub3RpY2UtcG9wb3ZlciAubm90aWNlLWl0ZW0uaXMtcmVhZCAubm90aWNlLXRhZywNCi5ub3RpY2UtcG9wb3ZlciAubm90aWNlLWl0ZW0uaXMtcmVhZCAubm90aWNlLWl0ZW0tdGl0bGUsDQoubm90aWNlLXBvcG92ZXIgLm5vdGljZS1pdGVtLmlzLXJlYWQgLm5vdGljZS1pdGVtLWRhdGUgeyBvcGFjaXR5OiAwLjQ1OyBmaWx0ZXI6IGdyYXlzY2FsZSgxKTsgY29sb3I6ICM5OTk7IH0NCi5ub3RpY2UtcG9wb3ZlciAubm90aWNlLXRhZyB7IGZsZXgtc2hyaW5rOiAwOyB9DQoubm90aWNlLXBvcG92ZXIgLm5vdGljZS1pdGVtLXRpdGxlIHsNCiAgZmxleDogMTsNCiAgZm9udC1zaXplOiAxMnB4Ow0KICBjb2xvcjogIzMzMzsNCiAgb3ZlcmZsb3c6IGhpZGRlbjsNCiAgd2hpdGUtc3BhY2U6IG5vd3JhcDsNCiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7DQp9DQoubm90aWNlLXBvcG92ZXIgLm5vdGljZS1pdGVtLWRhdGUgew0KICBmbGV4LXNocmluazogMDsNCiAgZm9udC1zaXplOiAxMXB4Ow0KICBjb2xvcjogI2JiYjsNCn0NCg=="},{"version":3,"sources":["index.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.vue","sourceRoot":"src/layout/components/HeaderNotice","sourcesContent":["<template>\r\n <div>\r\n <el-popover ref=\"noticePopover\" placement=\"bottom-end\" width=\"320\" trigger=\"manual\" :value=\"noticeVisible\" popper-class=\"notice-popover\">\r\n <div class=\"notice-header\">\r\n <span class=\"notice-title\">通知公告</span>\r\n <span class=\"notice-mark-all\" @click=\"markAllRead\">全部已读</span>\r\n </div>\r\n <div v-if=\"noticeLoading\" class=\"notice-loading\"><i class=\"el-icon-loading\"></i> 加载中...</div>\r\n <div v-else-if=\"noticeList.length === 0\" class=\"notice-empty\"><i class=\"el-icon-inbox\"></i><br>暂无公告</div>\r\n <div v-else>\r\n <div v-for=\"item in noticeList\" :key=\"item.noticeId\" class=\"notice-item\" :class=\"{ 'is-read': item.isRead }\" @click=\"previewNotice(item)\">\r\n <el-tag size=\"mini\" :type=\"item.noticeType === '1' ? 'warning' : 'success'\" class=\"notice-tag\">\r\n {{ item.noticeType === '1' ? '通知' : '公告' }}\r\n </el-tag>\r\n <span class=\"notice-item-title\">{{ item.noticeTitle }}</span>\r\n <span class=\"notice-item-date\">{{ item.createTime }}</span>\r\n </div>\r\n </div>\r\n </el-popover>\r\n\r\n <div v-popover:noticePopover class=\"right-menu-item hover-effect notice-trigger\" @mouseenter=\"onNoticeEnter\" @mouseleave=\"onNoticeLeave\">\r\n <svg-icon icon-class=\"bell\" />\r\n <span v-if=\"unreadCount > 0\" class=\"notice-badge\">{{ unreadCount }}</span>\r\n </div>\r\n\r\n <notice-detail-view ref=\"noticeViewRef\" />\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport NoticeDetailView from './DetailView'\r\nimport { listNoticeTop, markNoticeRead, markNoticeReadAll } from '@/api/system/notice'\r\n\r\nexport default {\r\n name: 'HeaderNotice',\r\n components: { NoticeDetailView },\r\n data() {\r\n return {\r\n noticeList: [], // 通知列表\r\n unreadCount: 0, // 未读数量\r\n noticeLoading: false, // 加载状态\r\n noticeVisible: false, // 弹出层显示状态\r\n noticeLeaveTimer: null // 鼠标离开计时器\r\n }\r\n },\r\n mounted() {\r\n this.loadNoticeTop()\r\n },\r\n methods: {\r\n // 鼠标移入铃铛区域\r\n onNoticeEnter() {\r\n clearTimeout(this.noticeLeaveTimer)\r\n this.noticeVisible = true\r\n this.$nextTick(() => {\r\n const popper = this.$refs.noticePopover.$refs.popper\r\n if (popper && !popper._noticeBound) {\r\n popper._noticeBound = true\r\n popper.addEventListener('mouseenter', () => clearTimeout(this.noticeLeaveTimer))\r\n popper.addEventListener('mouseleave', () => {\r\n this.noticeLeaveTimer = setTimeout(() => { this.noticeVisible = false }, 100)\r\n })\r\n }\r\n })\r\n },\r\n // 鼠标离开铃铛区域\r\n onNoticeLeave() {\r\n this.noticeLeaveTimer = setTimeout(() => { this.noticeVisible = false }, 150)\r\n },\r\n // 加载顶部公告列表\r\n loadNoticeTop() {\r\n this.noticeLoading = true\r\n listNoticeTop().then(res => {\r\n this.noticeList = res.data || []\r\n this.unreadCount = res.unreadCount !== undefined ? res.unreadCount : this.noticeList.filter(n => !n.isRead).length\r\n }).finally(() => {\r\n this.noticeLoading = false\r\n })\r\n },\r\n // 预览公告详情\r\n previewNotice(item) {\r\n if (!item.isRead) {\r\n markNoticeRead(item.noticeId).catch(() => {})\r\n item.isRead = true\r\n const idx = this.noticeList.indexOf(item)\r\n if (idx !== -1) this.$set(this.noticeList, idx, { ...item, isRead: true })\r\n this.unreadCount = Math.max(0, this.unreadCount - 1)\r\n }\r\n this.$refs.noticeViewRef.open(item.noticeId)\r\n },\r\n // 全部已读\r\n markAllRead() {\r\n const ids = this.noticeList.map(n => n.noticeId).join(',')\r\n if (!ids) return\r\n markNoticeReadAll(ids).catch(() => {})\r\n this.noticeList = this.noticeList.map(n => ({ ...n, isRead: true }))\r\n this.unreadCount = 0\r\n }\r\n }\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.notice-trigger {\r\n position: relative;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n /* 自身不强行限制尺寸,由父级 .icon-btn 控制圆框尺寸 */\r\n width: 100%;\r\n height: 100%;\r\n .svg-icon { width: 18px; height: 18px; color: #fff; }\r\n .notice-badge {\r\n position: absolute;\r\n top: 2px;\r\n right: 2px;\r\n background: linear-gradient(135deg, #ff5e5e, #f5222d);\r\n color: #fff;\r\n border-radius: 10px;\r\n font-size: 10px;\r\n height: 16px;\r\n line-height: 16px;\r\n padding: 0 4px;\r\n min-width: 16px;\r\n text-align: center;\r\n white-space: nowrap;\r\n pointer-events: none;\r\n font-weight: 600;\r\n box-shadow: 0 2px 6px rgba(245, 34, 45, 0.5);\r\n border: 1.5px solid #fff;\r\n transform: scale(0.92);\r\n transform-origin: top right;\r\n }\r\n}\r\n.notice-popover {\r\n padding: 0 !important;\r\n}\r\n.notice-popover .notice-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 10px 14px;\r\n background: #f7f9fb;\r\n border-bottom: 1px solid #eee;\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n.notice-popover .notice-mark-all {\r\n font-size: 12px;\r\n color: #00875A;\r\n font-weight: normal;\r\n cursor: pointer;\r\n}\r\n.notice-popover .notice-mark-all:hover { color: #2b7cc1; }\r\n.notice-popover .notice-loading,\r\n.notice-popover .notice-empty {\r\n padding: 24px;\r\n text-align: center;\r\n color: #bbb;\r\n font-size: 12px;\r\n line-height: 1.8;\r\n}\r\n.notice-popover .notice-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 10px 14px;\r\n border-bottom: 1px solid #f5f5f5;\r\n cursor: pointer;\r\n transition: background 0.15s;\r\n}\r\n.notice-popover .notice-item:last-child { border-bottom: none; }\r\n.notice-popover .notice-item:hover { background: #f7f9fb; }\r\n.notice-popover .notice-item.is-read .notice-tag,\r\n.notice-popover .notice-item.is-read .notice-item-title,\r\n.notice-popover .notice-item.is-read .notice-item-date { opacity: 0.45; filter: grayscale(1); color: #999; }\r\n.notice-popover .notice-tag { flex-shrink: 0; }\r\n.notice-popover .notice-item-title {\r\n flex: 1;\r\n font-size: 12px;\r\n color: #333;\r\n overflow: hidden;\r\n white-space: nowrap;\r\n text-overflow: ellipsis;\r\n}\r\n.notice-popover .notice-item-date {\r\n flex-shrink: 0;\r\n font-size: 11px;\r\n color: #bbb;\r\n}\r\n</style>\r\n"]}]}