Browse Source

add news

master
godo 9 months ago
parent
commit
6cbb5e3ec8
  1. 1
      frontend/components.d.ts
  2. 128
      frontend/src/components/taskbar/MessageCenterPop.vue
  3. 40
      frontend/src/stores/notify.ts
  4. 40
      frontend/src/system/notification/Notification.ts

1
frontend/components.d.ts

@ -54,6 +54,7 @@ declare module 'vue' {
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElLink: typeof import('element-plus/es')['ElLink'] ElLink: typeof import('element-plus/es')['ElLink']
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover'] ElPopover: typeof import('element-plus/es')['ElPopover']
ElProgress: typeof import('element-plus/es')['ElProgress'] ElProgress: typeof import('element-plus/es')['ElProgress']
ElRow: typeof import('element-plus/es')['ElRow'] ElRow: typeof import('element-plus/es')['ElRow']

128
frontend/src/components/taskbar/MessageCenterPop.vue

@ -3,44 +3,60 @@
<div v-if="isPopShow" class="message scroll-bar" @mousedown.stop=""> <div v-if="isPopShow" class="message scroll-bar" @mousedown.stop="">
<div class="notify-center"> <div class="notify-center">
<div class="message-title"> <div class="message-title">
{{ notifyGroup.length }}条提醒 {{ store.page.total }}条通知
<span @click="allClear" class="allclear">×</span>
</div> </div>
<div class="message-group scroll-bar"> <div class="message-group scroll-bar">
<div class="message-item" v-for="notify in notifyGroup" :key="notify.id"> <div class="message-item" v-for="notify in store.notifyList" :key="notify.id">
<div class="message-item-title"> <div class="message-item-title" @click="showDetail(notify)">
<span>{{ notify.title }}</span> <span>{{ notify.title }}</span>
</div> </div>
<div class="message-item-body">
<span>{{ notify.content }}</span>
</div>
</div> </div>
<el-row justify="center" style="margin-top: 15px" v-if="store.page.pages > 1">
<el-pagination background layout="prev, pager, next" v-model:current-page="store.page.current"
v-model:page-size="store.page.size" :total="store.page.total"
@current-change="(val: any) => store.pageClick(val)" />
</el-row>
</div> </div>
</div> </div>
</div> </div>
</Transition> </Transition>
<el-dialog v-model="showNews" :title="newsDetail.title" show-close="true" width="600">
<div class="new-content">
<div class="news-detail" v-html="newsDetail.content"></div>
<p class="new-time"><strong>发布时间:</strong> {{ newsDetail.showtime }}</p>
</div>
</el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useSystem } from '@/system'; import { useNotifyStore } from '@/stores/notify';
import { ref } from 'vue'; import { ref } from 'vue';
import { mountEvent } from '@/system/event'; import { mountEvent } from '@/system/event';
const rootState = useSystem()._rootState; const store = useNotifyStore()
const notifyGroup = rootState.message.notify;
// const systemGroup = rootState.message.system;
const isPopShow = ref(false); const isPopShow = ref(false);
const newsDetail: any = ref({})
const showNews = ref(false)
mountEvent('messagecenter.show', () => { mountEvent('messagecenter.show', () => {
isPopShow.value = !isPopShow.value; isPopShow.value = !isPopShow.value;
}); });
mountEvent('messagecenter.hidden', () => { mountEvent('messagecenter.hidden', () => {
isPopShow.value = false; isPopShow.value = false;
}); });
function allClear() { onMounted(async () => {
rootState.message.notify.splice(0, notifyGroup.length); // store.init();
isPopShow.value = false; await store.getList()
});
const showDetail = (notify: any) => {
const timestamp = notify.add_time * 1000; // 10 13
const date = new Date(timestamp);
notify.showtime = date.toLocaleString();
newsDetail.value = notify
showNews.value = true
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/assets/main.scss'; @import '@/assets/main.scss';
.message { .message {
position: absolute; position: absolute;
top: 0; top: 0;
@ -48,8 +64,10 @@ function allClear() {
width: 300px; width: 300px;
height: 100%; height: 100%;
z-index: 400; z-index: 400;
background-color: #F5F5F5; /* 更接近Win10的背景颜色 */ background-color: #F5F5F5;
border-left: 1px solid #E5E5E5; /* 边框颜色调整 */ /* 更接近Win10的背景颜色 */
border-left: 1px solid #E5E5E5;
/* 边框颜色调整 */
overflow-y: auto; overflow-y: auto;
user-select: none; user-select: none;
box-sizing: content-box; box-sizing: content-box;
@ -58,19 +76,25 @@ function allClear() {
.message-title { .message-title {
padding: 10px 20px; padding: 10px 20px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* 使用Win10默认字体 */ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 14px; /* 字体大小调整 */ /* 使用Win10默认字体 */
font-size: 14px;
/* 字体大小调整 */
font-weight: bold; font-weight: bold;
border-bottom: 1px solid #E5E5E5; /* 边框颜色调整 */ border-bottom: 1px solid #E5E5E5;
/* 边框颜色调整 */
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: flex-end; align-items: flex-end;
.allclear { .allclear {
font-size: 12px; /* 字体大小调整 */ font-size: 12px;
/* 字体大小调整 */
cursor: pointer; cursor: pointer;
&:hover { &:hover {
color: #0078D4; /* Win10主题蓝色 */ color: #0078D4;
/* Win10主题蓝色 */
} }
} }
} }
@ -88,16 +112,22 @@ function allClear() {
} }
.message-item { .message-item {
padding: 10px 16px; padding: 15px 16px;
background-color: #FFFFFF; /* 消息项背景色调整 */ background-color: #FFFFFF;
width: 100%; /* 设置为100%,以便内容自适应 */ /* 消息项背景色调整 */
width: 100%;
/* 设置为100%,以便内容自适应 */
overflow: hidden; overflow: hidden;
margin-bottom: 8px; /* 增加间距 */ margin-bottom: 8px;
border: 1px solid #E5E5E5; /* 边框颜色调整 */ /* 增加间距 */
border-radius: 4px; /* 添加圆角 */ border: 1px solid #E5E5E5;
/* 边框颜色调整 */
border-radius: 4px;
/* 添加圆角 */
transition: all 0.2s ease; transition: all 0.2s ease;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
/* 添加阴影效果 */
.message-item-title { .message-item-title {
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
@ -107,18 +137,21 @@ function allClear() {
} }
.message-item-body { .message-item-body {
font-size: 13px; /* 字体大小调整 */ font-size: 13px;
/* 字体大小调整 */
} }
&:hover { &:hover {
border-color: #C7C7C7; /* 鼠标悬停时边框颜色变淡 */ border-color: #C7C7C7;
/* 鼠标悬停时边框颜色变淡 */
} }
} }
} }
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: all 0.3s ease; /* 修改过渡效果 */ transition: all 0.3s ease;
/* 修改过渡效果 */
} }
.fade-enter-to, .fade-enter-to,
@ -132,4 +165,35 @@ function allClear() {
opacity: 0; opacity: 0;
transform: translateX(100%); transform: translateX(100%);
} }
.new-content {
padding: 20px;
background-color: #F5F5F5;
border: 1px solid #E5E5E5;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
.new-time {
margin-bottom: 10px;
font-size: 14px;
color: #666;
strong {
font-weight: bold;
color: #333;
}
}
.news-detail {
font-size: 16px;
line-height: 1.5;
color: #333;
white-space: pre-wrap;
}
.news-detail:deep(img){
max-width: 90%;
}
}
</style> </style>

40
frontend/src/stores/notify.ts

@ -0,0 +1,40 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { getSystemConfig,fetchGet } from "@/system/config";
export const useNotifyStore = defineStore('notifyStore', () => {
const config = getSystemConfig();
const notifyList:any = ref([]);
const page = ref({
current: 1,
size: 10,
total: 0,
pages: 0,
})
async function getList(){
if(config.userType == 'person'){
return
}
const complition = await fetchGet(config.userInfo.url + '/news/list?page=' + page.value.current + '&limit='+ page.value.size)
if(!complition.ok){
return;
}
const data = await complition.json();
if(data.success){
page.value.total = data.data.total;
notifyList.value = data.data.list;
page.value.pages = Math.ceil(page.value.total / page.value.size)
}
}
const pageClick = async (pageNum: any) => {
//console.log(pageNum)
page.value.current = pageNum
await getList()
}
return {
notifyList,
getList,
page,
pageClick
}
})

40
frontend/src/system/notification/Notification.ts

@ -20,27 +20,27 @@ export class Notify {
this.close(); this.close();
}, option.timeout || 5000); }, option.timeout || 5000);
// // 检查浏览器是否支持通知 // 检查浏览器是否支持通知
// if ('Notification' in window) { if ('Notification' in window) {
// // 请求通知权限 // 请求通知权限
// Notification.requestPermission().then(function (permission) { Notification.requestPermission().then(function (permission) {
// if (permission === 'granted') { if (permission === 'granted') {
// // 创建通知 // 创建通知
// const notification = new Notification(option.title, { const notification = new Notification(option.title, {
// body: option.content, body: option.content,
// }); });
// // 点击通知时触发的事件 // 点击通知时触发的事件
// notification.onclick = function () { notification.onclick = function () {
// // console.log('通知被点击了'); // console.log('通知被点击了');
// }; };
// } else { } else {
// // console.warn('用户拒绝了通知权限'); // console.warn('用户拒绝了通知权限');
// } }
// }); });
// } else { } else {
// // console.error('浏览器不支持通知'); // console.error('浏览器不支持通知');
// } }
} }
close() { close() {
const sys = useSystem(); const sys = useSystem();

Loading…
Cancel
Save