344 lines
11 KiB
Vue
344 lines
11 KiB
Vue
|
|
<template>
|
||
|
|
<AppLayout>
|
||
|
|
<view class="detail-content">
|
||
|
|
|
||
|
|
<scroll-view scroll-y class="detail-scroll">
|
||
|
|
<view class="scroll-body" v-if="message">
|
||
|
|
<view class="msg-card" :class="{ unread: message.isRead === '0' }">
|
||
|
|
<view class="card-row">
|
||
|
|
<view class="card-icon">
|
||
|
|
<image class="card-icon-img" v-if="message.title === '招聘会预约提醒'" src="/static/icon/msgtype.png"></image>
|
||
|
|
<image class="card-icon-img" v-else-if="message.title === '职位上新'" src="/static/icon/msgtype2.png"></image>
|
||
|
|
<image class="card-icon-img" v-else-if="message.title === '系统通知'" src="/static/icon/msgtype3.png"></image>
|
||
|
|
<image class="card-icon-img card-icon-default" v-else src="/static/icon/bell.png"></image>
|
||
|
|
</view>
|
||
|
|
<view class="card-info">
|
||
|
|
<view class="info-title-row">
|
||
|
|
<view class="unread-dot" v-if="message.isRead === '0'"></view>
|
||
|
|
<text class="info-title" :class="{ 'title-bold': message.isRead === '0' }">{{ message.title }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="info-meta">
|
||
|
|
<text class="info-time">{{ message.createTime || message.date }}</text>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="card-divider"></view>
|
||
|
|
|
||
|
|
<view class="card-subtitle" v-if="message.subTitle">
|
||
|
|
<text class="subtitle-label">摘要</text>
|
||
|
|
<text class="subtitle-text">{{ message.subTitle }}</text>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="card-content" v-if="message.noticeContent">
|
||
|
|
<text class="content-label">详情</text>
|
||
|
|
<text class="content-text">{{ message.noticeContent }}</text>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="card-footer" v-if="message.noticeType === '4'">
|
||
|
|
<text class="footer-hint" @click="handleMsgClick">点击查看详情</text>
|
||
|
|
<uni-icons color="#909090" type="right" size="14"></uni-icons>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<!-- <view class="info-card">
|
||
|
|
<view class="info-item">
|
||
|
|
<text class="info-item-label">消息类型</text>
|
||
|
|
<text class="info-item-value">{{ message.noticeType === '4' ? '职位相关' : message.title }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="info-item">
|
||
|
|
<text class="info-item-label">接收时间</text>
|
||
|
|
<text class="info-item-value">{{ message.createTime || message.date }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="info-item">
|
||
|
|
<text class="info-item-label">阅读状态</text>
|
||
|
|
<text class="info-item-value status-text" :class="{ unread: message.isRead === '0' }">{{ message.isRead === '0' ? '未读' : '已读' }}</text>
|
||
|
|
</view>
|
||
|
|
</view> -->
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="empty-state" v-else-if="!loading">
|
||
|
|
<image class="empty-icon" src="/static/icon/empty.png" mode="aspectFit"></image>
|
||
|
|
<text class="empty-text">消息不存在</text>
|
||
|
|
<text class="empty-desc">该消息可能已被删除</text>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="loading-state" v-if="loading">
|
||
|
|
<text class="loading-text">加载中...</text>
|
||
|
|
</view>
|
||
|
|
</scroll-view>
|
||
|
|
</view>
|
||
|
|
</AppLayout>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup>
|
||
|
|
import { inject, ref } from 'vue';
|
||
|
|
import { onLoad } from '@dcloudio/uni-app';
|
||
|
|
const { $api, navTo } = inject('globalFunction');
|
||
|
|
import { useReadMsg } from '@/stores/useReadMsg';
|
||
|
|
|
||
|
|
const message = ref(null);
|
||
|
|
const loading = ref(false);
|
||
|
|
const hasMarkedRead = ref(false);
|
||
|
|
|
||
|
|
onLoad(() => {
|
||
|
|
const item = uni.getStorageSync('currentMessageDetail');
|
||
|
|
if (item) {
|
||
|
|
message.value = item;
|
||
|
|
if (item.isRead === '0') {
|
||
|
|
markAsRead(item);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
loading.value = false;
|
||
|
|
});
|
||
|
|
|
||
|
|
function goBack() {
|
||
|
|
uni.navigateBack();
|
||
|
|
}
|
||
|
|
|
||
|
|
function markAsRead(item) {
|
||
|
|
if (!item.noticeId || hasMarkedRead.value) return;
|
||
|
|
hasMarkedRead.value = true;
|
||
|
|
$api.createRequest('/app/notice/read/noticeRead', { id: item.noticeId }, 'POST').then(() => {
|
||
|
|
message.value.isRead = '1';
|
||
|
|
useReadMsg().fetchMessages();
|
||
|
|
}).catch(err => {
|
||
|
|
console.error('标记已读失败:', err);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function handleMsgClick() {
|
||
|
|
const item = message.value;
|
||
|
|
if (!item) return;
|
||
|
|
|
||
|
|
if (item.noticeType === '4') {
|
||
|
|
if (item.bussinessIdEncrypt) {
|
||
|
|
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(item.bussinessId)}&encryptJobId=${encodeURIComponent(item.bussinessIdEncrypt)}`);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
// switch (item.title) {
|
||
|
|
// case '职位上新':
|
||
|
|
// navTo('/packageA/pages/newJobPosition/newJobPosition');
|
||
|
|
// break;
|
||
|
|
// case '招聘会预约提醒':
|
||
|
|
// navTo('/packageA/pages/reservation/reservation');
|
||
|
|
// break;
|
||
|
|
// case '系统通知':
|
||
|
|
// navTo('/packageA/pages/systemNotification/systemNotification');
|
||
|
|
// break;
|
||
|
|
// }
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style lang="stylus" scoped>
|
||
|
|
.detail-content
|
||
|
|
height: 100vh
|
||
|
|
display: flex
|
||
|
|
flex-direction: column
|
||
|
|
background: #F5F6FA
|
||
|
|
|
||
|
|
.detail-header
|
||
|
|
display: flex
|
||
|
|
align-items: center
|
||
|
|
justify-content: space-between
|
||
|
|
padding: 20rpx 28rpx
|
||
|
|
background: #FFFFFF
|
||
|
|
position: relative
|
||
|
|
.header-back
|
||
|
|
width: 60rpx
|
||
|
|
height: 60rpx
|
||
|
|
display: flex
|
||
|
|
align-items: center
|
||
|
|
justify-content: center
|
||
|
|
.header-title
|
||
|
|
font-size: 36rpx
|
||
|
|
font-weight: 600
|
||
|
|
color: #1A1A1A
|
||
|
|
position: absolute
|
||
|
|
left: 50%
|
||
|
|
transform: translateX(-50%)
|
||
|
|
.header-right
|
||
|
|
width: 60rpx
|
||
|
|
|
||
|
|
.detail-scroll
|
||
|
|
flex: 1
|
||
|
|
overflow: hidden
|
||
|
|
|
||
|
|
.scroll-body
|
||
|
|
padding: 28rpx
|
||
|
|
padding-bottom: 40rpx
|
||
|
|
|
||
|
|
.msg-card
|
||
|
|
background: #FFFFFF
|
||
|
|
border-radius: 20rpx
|
||
|
|
padding: 32rpx
|
||
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06)
|
||
|
|
transition: all 0.2s ease
|
||
|
|
&:active
|
||
|
|
transform: scale(0.99)
|
||
|
|
&.unread
|
||
|
|
border-left: 6rpx solid #FF4757
|
||
|
|
|
||
|
|
.card-row
|
||
|
|
display: flex
|
||
|
|
align-items: center
|
||
|
|
.card-icon
|
||
|
|
width: 88rpx
|
||
|
|
height: 88rpx
|
||
|
|
border-radius: 50%
|
||
|
|
display: flex
|
||
|
|
align-items: center
|
||
|
|
justify-content: center
|
||
|
|
margin-right: 24rpx
|
||
|
|
flex-shrink: 0
|
||
|
|
.card-icon-img
|
||
|
|
width: 100%
|
||
|
|
height: 100%
|
||
|
|
border-radius: 50%
|
||
|
|
.card-icon-default
|
||
|
|
width: 60%
|
||
|
|
height: 60%
|
||
|
|
.card-info
|
||
|
|
flex: 1
|
||
|
|
min-width: 0
|
||
|
|
.info-title-row
|
||
|
|
display: flex
|
||
|
|
align-items: center
|
||
|
|
margin-bottom: 12rpx
|
||
|
|
.unread-dot
|
||
|
|
width: 14rpx
|
||
|
|
height: 14rpx
|
||
|
|
background: #FF4757
|
||
|
|
border-radius: 50%
|
||
|
|
margin-right: 10rpx
|
||
|
|
flex-shrink: 0
|
||
|
|
.info-title
|
||
|
|
font-size: 34rpx
|
||
|
|
color: #1A1A1A
|
||
|
|
font-weight: 500
|
||
|
|
line-height: 1.3
|
||
|
|
&.title-bold
|
||
|
|
font-weight: 700
|
||
|
|
.info-meta
|
||
|
|
display: flex
|
||
|
|
align-items: center
|
||
|
|
.info-status
|
||
|
|
font-size: 24rpx
|
||
|
|
color: #FF4757
|
||
|
|
display: flex
|
||
|
|
align-items: center
|
||
|
|
margin-right: 20rpx
|
||
|
|
&.read
|
||
|
|
color: #BBBBBB
|
||
|
|
.status-dot
|
||
|
|
width: 10rpx
|
||
|
|
height: 10rpx
|
||
|
|
background: #FF4757
|
||
|
|
border-radius: 50%
|
||
|
|
margin-right: 6rpx
|
||
|
|
.info-time
|
||
|
|
font-size: 24rpx
|
||
|
|
color: #AAAAAA
|
||
|
|
|
||
|
|
.card-divider
|
||
|
|
height: 1rpx
|
||
|
|
background: #F0F0F0
|
||
|
|
margin: 28rpx 0
|
||
|
|
|
||
|
|
.card-subtitle
|
||
|
|
margin-bottom: 24rpx
|
||
|
|
.subtitle-label
|
||
|
|
display: inline-block
|
||
|
|
font-size: 22rpx
|
||
|
|
color: #FFFFFF
|
||
|
|
background: #256BFA
|
||
|
|
border-radius: 6rpx
|
||
|
|
padding: 2rpx 12rpx
|
||
|
|
margin-bottom: 12rpx
|
||
|
|
.subtitle-text
|
||
|
|
display: block
|
||
|
|
font-size: 28rpx
|
||
|
|
color: #333333
|
||
|
|
line-height: 1.5
|
||
|
|
|
||
|
|
.card-content
|
||
|
|
.content-label
|
||
|
|
display: inline-block
|
||
|
|
font-size: 22rpx
|
||
|
|
color: #FFFFFF
|
||
|
|
background: #9E74FD
|
||
|
|
border-radius: 6rpx
|
||
|
|
padding: 2rpx 12rpx
|
||
|
|
margin-bottom: 12rpx
|
||
|
|
.content-text
|
||
|
|
display: block
|
||
|
|
font-size: 28rpx
|
||
|
|
color: #555555
|
||
|
|
line-height: 1.7
|
||
|
|
|
||
|
|
.card-footer
|
||
|
|
margin-top: 32rpx
|
||
|
|
padding-top: 24rpx
|
||
|
|
border-top: 1rpx dashed #E8E8E8
|
||
|
|
display: flex
|
||
|
|
align-items: center
|
||
|
|
justify-content: center
|
||
|
|
.footer-hint
|
||
|
|
font-size: 26rpx
|
||
|
|
color: #256BFA
|
||
|
|
margin-right: 4rpx
|
||
|
|
|
||
|
|
.info-card
|
||
|
|
background: #FFFFFF
|
||
|
|
border-radius: 20rpx
|
||
|
|
padding: 24rpx 32rpx
|
||
|
|
margin-top: 24rpx
|
||
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06)
|
||
|
|
.info-item
|
||
|
|
display: flex
|
||
|
|
justify-content: space-between
|
||
|
|
align-items: center
|
||
|
|
padding: 20rpx 0
|
||
|
|
border-bottom: 1rpx solid #F5F5F5
|
||
|
|
&:last-child
|
||
|
|
border-bottom: none
|
||
|
|
.info-item-label
|
||
|
|
font-size: 26rpx
|
||
|
|
color: #999999
|
||
|
|
.info-item-value
|
||
|
|
font-size: 26rpx
|
||
|
|
color: #333333
|
||
|
|
font-weight: 500
|
||
|
|
&.status-text.unread
|
||
|
|
color: #FF4757
|
||
|
|
|
||
|
|
.empty-state
|
||
|
|
display: flex
|
||
|
|
flex-direction: column
|
||
|
|
align-items: center
|
||
|
|
justify-content: center
|
||
|
|
padding: 200rpx 40rpx
|
||
|
|
.empty-icon
|
||
|
|
width: 200rpx
|
||
|
|
height: 200rpx
|
||
|
|
margin-bottom: 32rpx
|
||
|
|
opacity: 0.5
|
||
|
|
.empty-text
|
||
|
|
font-size: 30rpx
|
||
|
|
color: #999999
|
||
|
|
font-weight: 500
|
||
|
|
margin-bottom: 12rpx
|
||
|
|
.empty-desc
|
||
|
|
font-size: 26rpx
|
||
|
|
color: #CCCCCC
|
||
|
|
|
||
|
|
.loading-state
|
||
|
|
display: flex
|
||
|
|
justify-content: center
|
||
|
|
padding: 200rpx 0
|
||
|
|
.loading-text
|
||
|
|
font-size: 28rpx
|
||
|
|
color: #BBBBBB
|
||
|
|
</style>
|