Files
medical-mall/pages/mall/consumer/message-detail.uvue

266 lines
5.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<scroll-view class="message-detail-page" scroll-y>
<view class="message-header">
<text class="message-title">{{ message.title }}</text>
<text class="message-time">{{ formatTime(message.created_at) }}</text>
</view>
<view class="message-content">
<text class="content-text">{{ message.content }}</text>
</view>
<view v-if="message.link_url" class="message-action" @click="goToLink">
<text class="action-text">查看详情</text>
<text class="action-arrow"></text>
</view>
<view v-if="message.icon_url" class="message-image">
<image :src="message.icon_url" mode="widthFix" class="icon-image" />
</view>
<view v-if="extraInfo.length > 0" class="extra-info">
<view v-for="(item, index) in extraInfo" :key="index" class="extra-item">
<text class="extra-label">{{ item.label }}</text>
<text class="extra-value">{{ item.value }}</text>
</view>
</view>
</scroll-view>
</template>
<script setup lang="uts">
import { ref, onMounted } from 'vue'
import { supabaseService } from '@/utils/supabaseService.uts'
type MessageType = {
id: string
type: string
title: string
content: string
icon_url: string | null
link_url: string | null
extra_data: any | null
created_at: string
}
type ExtraInfoItem = {
label: string
value: string
}
const message = ref<MessageType>({
id: '',
type: '',
title: '',
content: '',
icon_url: null,
link_url: null,
extra_data: null,
created_at: ''
})
const extraInfo = ref<ExtraInfoItem[]>([])
const loadMessage = async (id: string) => {
try {
const notifications = await supabaseService.getUserNotifications(null)
const found = notifications.find(n => n.id === id)
if (found != null) {
message.value = {
id: found.id,
type: found.type,
title: found.title,
content: found.content,
icon_url: found.icon_url,
link_url: found.link_url,
extra_data: found.extra_data,
created_at: found.created_at
}
// 解析extra_data
if (found.extra_data != null) {
parseExtraData(found.extra_data)
}
}
} catch (e) {
console.error('加载消息失败:', e)
}
}
const parseExtraData = (data: any) => {
extraInfo.value = []
if (data == null) return
try {
let dataObj: any = data
if (typeof data === 'string') {
dataObj = JSON.parse(data)
}
if (typeof dataObj === 'object') {
const keys = Object.keys(dataObj)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const value = dataObj[key]
if (value != null) {
extraInfo.value.push({
label: formatLabel(key),
value: String(value)
})
}
}
}
} catch (e) {
console.error('解析extra_data失败:', e)
}
}
const formatLabel = (key: string): string => {
const labelMap: Record<string, string> = {
'share_code': '分享码',
'product_name': '商品名称',
'reward_amount': '奖励金额',
'order_no': '订单号',
'buyer_name': '购买者',
'quantity': '数量'
}
return labelMap[key] ?? key
}
const formatTime = (timeStr: string): string => {
if (timeStr == null || timeStr === '') return ''
const date = new Date(timeStr)
const y = date.getFullYear()
const m = (date.getMonth() + 1).toString().padStart(2, '0')
const d = date.getDate().toString().padStart(2, '0')
const hh = date.getHours().toString().padStart(2, '0')
const mm = date.getMinutes().toString().padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}`
}
const goToLink = () => {
const url = message.value.link_url
if (url != null && url !== '') {
if (url.startsWith('/pages/')) {
uni.navigateTo({ url: url })
} else {
uni.setClipboardData({
data: url,
success: () => {
uni.showToast({ title: '链接已复制', icon: 'success' })
}
})
}
}
}
onMounted(() => {
const pages = getCurrentPages()
if (pages.length > 0) {
const currentPage = pages[pages.length - 1]
const options = (currentPage as any).options
if (options != null && options.id != null) {
loadMessage(options.id as string)
}
}
})
</script>
<style>
.message-detail-page {
flex: 1;
height: 100%;
background-color: #f5f5f5;
}
.message-header {
background-color: white;
padding: 20px 16px;
margin-bottom: 8px;
}
.message-title {
font-size: 18px;
font-weight: bold;
color: #333;
display: flex;
margin-bottom: 10px;
}
.message-time {
font-size: 13px;
color: #999;
}
.message-content {
background-color: white;
padding: 16px;
margin-bottom: 8px;
}
.content-text {
font-size: 15px;
color: #333;
line-height: 1.8;
}
.message-action {
background-color: white;
padding: 16px;
margin-bottom: 8px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.action-text {
font-size: 15px;
color: #ff6b35;
}
.action-arrow {
font-size: 18px;
color: #ccc;
}
.message-image {
background-color: white;
padding: 16px;
margin-bottom: 8px;
}
.icon-image {
width: 100%;
border-radius: 8px;
}
.extra-info {
background-color: white;
padding: 16px;
}
.extra-item {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 10px 0;
border-bottom: 1px solid #f5f5f5;
}
.extra-item:last-child {
border-bottom: none;
}
.extra-label {
font-size: 14px;
color: #666;
}
.extra-value {
font-size: 14px;
color: #333;
}
</style>