feat(反馈): 修改反馈详情页跳转链接并支持反馈类型

重构文章详情页以支持反馈类型,添加获取反馈详情和标记已读功能
This commit is contained in:
砂糖
2025-11-07 10:45:43 +08:00
parent 884b1bb311
commit 750f66441b
2 changed files with 262 additions and 198 deletions

View File

@@ -1,220 +1,284 @@
<template> <template>
<view class="article-container"> <view class="article-container">
<!-- 加载状态 --> <!-- 加载状态 -->
<view class="loading" v-if="loading"> <view class="loading" v-if="loading">
<uni-loading-icon size="24" color="#007aff"></uni-loading-icon> <uni-loading-icon size="24" color="#007aff"></uni-loading-icon>
<text class="loading-text">加载中...</text> <text class="loading-text">加载中...</text>
</view> </view>
<!-- 文章内容加载完成后显示 --> <!-- 文章内容加载完成后显示 -->
<view class="article-content" v-else-if="article"> <view class="article-content" v-else-if="article">
<!-- 帖子标题 --> <!-- 帖子标题 -->
<view class="post-title">{{ article.title || '无标题' }}</view> <view class="post-title">{{ article.title || '无标题' }}</view>
<!-- 用户信息 --> <!-- 用户信息 -->
<view class="user-info"> <view class="user-info">
<image v-if="article.avatar" class="user-avatar" :src="article.avatar || '/static/default-avatar.png'" mode="cover"></image> <image v-if="article.avatar" class="user-avatar" :src="article.avatar || '/static/default-avatar.png'"
<view class="user-meta"> mode="cover"></image>
<view class="user-name"> <view class="user-meta">
{{ article.author || '未知用户' }} <view class="user-name">
<!-- <view class="user-level">Lv.1</view> --> {{ article.author || '未知用户' }}
</view> <!-- <view class="user-level">Lv.1</view> -->
<view class="user-time-area"> </view>
<view class="user-time-area">
<text>{{ article.createTime || '未知时间' }}</text> <text>{{ article.createTime || '未知时间' }}</text>
<text v-if="article.area"> · {{ article.area || '未知地区' }}</text> <text v-if="article.area"> · {{ article.area || '未知地区' }}</text>
</view> </view>
</view> </view>
<!-- <view class="follow-btn">+关注</view> --> <!-- <view class="follow-btn">+关注</view> -->
</view> </view>
<!-- 富文本内容 --> <!-- 富文本内容 -->
<mp-html :content="article.content"></mp-html> <mp-html :content="article.content"></mp-html>
</view> </view>
<!-- 错误状态 --> <!-- 错误状态 -->
<view class="error" v-else> <view class="error" v-else>
<uni-icons type="warn" size="36" color="#ff4d4f"></uni-icons> <uni-icons type="warn" size="36" color="#ff4d4f"></uni-icons>
<text class="error-text">加载失败</text> <text class="error-text">加载失败</text>
<button class="retry-btn" @click="reload">重试</button> <button class="retry-btn" @click="reload">重试</button>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import { getNotice } from '@/api/oa/notice'; import {
getNotice
} from '@/api/oa/notice';
import {
getFeedback,
toRead
} from "@/api/oa/feedback";
export default { export default {
data() { data() {
return { return {
article: null, article: null,
loading: true, loading: true,
}; };
}, },
onLoad(options) { onLoad(options) {
const { type, id } = options; const {
if (!type || !id) { type,
uni.showToast({ title: '参数错误', icon: 'none' }); id
setTimeout(() => uni.navigateBack(), 1000); } = options;
return; if (!type || !id) {
} uni.showToast({
this.fetchData(type, id); title: '参数错误',
}, icon: 'none'
methods: { });
fetchData(type, id) { setTimeout(() => uni.navigateBack(), 1000);
this.loading = true; return;
switch (type) { }
case 'notice': this.fetchData(type, id);
getNotice(id) },
.then(res => { methods: {
this.article = { fetchData(type, id) {
...res.data, this.loading = true;
author: res.data.createBy, switch (type) {
title: res.data.noticeTitle, case 'notice':
content: res.data.noticeContent, getNotice(id)
}; .then(res => {
this.loading = false; this.article = {
}) ...res.data,
.catch(err => { author: res.data.createBy,
console.error('获取文章失败', err); title: res.data.noticeTitle,
this.article = null; content: res.data.noticeContent,
this.loading = false; };
uni.showToast({ title: '加载失败', icon: 'none' }); uni.setNavigationBarTitle({
}); title: '通知详情'
break; })
default: this.loading = false;
uni.showToast({ title: '未知类型', icon: 'none' }); })
setTimeout(() => uni.navigateBack(), 1000); .catch(err => {
break; console.error('获取文章失败', err);
} this.article = null;
}, this.loading = false;
reload() { uni.showToast({
const { type, id } = this.$options.onLoad.options; title: '加载失败',
this.fetchData(type, id); icon: 'none'
}, });
navigateBack() { });
uni.navigateBack(); break;
} case 'feedback':
} getFeedback(id)
}; .then(res => {
if (res.data) {
this.article = res.data;
uni.setNavigationBarTitle({
title: '反馈详情'
})
// 标记为已读
toRead(this.article);
} else {
uni.showToast({
title: '未找到消息',
icon: 'none'
});
}
})
.catch(err => {
uni.showToast({
title: err.message || '获取消息失败',
icon: 'none'
});
})
.finally(() => {
this.loading = false;
});
break;
default:
uni.showToast({
title: '未知类型',
icon: 'none'
});
setTimeout(() => uni.navigateBack(), 1000);
break;
}
},
reload() {
const {
type,
id
} = this.$options.onLoad.options;
this.fetchData(type, id);
},
navigateBack() {
uni.navigateBack();
}
}
};
</script> </script>
<style scoped> <style scoped>
.article-container { .article-container {
min-height: 100vh; min-height: 100vh;
background-color: #fff; background-color: #fff;
} }
.loading { .loading {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 50px 0; padding: 50px 0;
} }
.loading-text {
margin-top: 10px;
color: #666;
font-size: 14px;
}
.error { .loading-text {
display: flex; margin-top: 10px;
flex-direction: column; color: #666;
align-items: center; font-size: 14px;
padding: 50px 0; }
}
.error-text {
margin: 15px 0;
color: #ff4d4f;
font-size: 16px;
}
.retry-btn {
background-color: #007aff;
color: #fff;
border-radius: 4px;
padding: 8px 20px;
font-size: 14px;
}
.article-content { .error {
padding: 16px; display: flex;
} flex-direction: column;
align-items: center;
padding: 50px 0;
}
.post-title { .error-text {
font-size: 18px; margin: 15px 0;
font-weight: bold; color: #ff4d4f;
color: #333; font-size: 16px;
margin-bottom: 12px; }
line-height: 1.4;
}
.user-info { .retry-btn {
display: flex; background-color: #007aff;
align-items: center; color: #fff;
margin-bottom: 16px; border-radius: 4px;
} padding: 8px 20px;
.user-avatar { font-size: 14px;
width: 40px; }
height: 40px;
border-radius: 50%;
margin-right: 10px;
}
.user-meta {
flex: 1;
}
.user-name {
display: flex;
align-items: center;
font-size: 14px;
color: #333;
margin-bottom: 4px;
}
.user-level {
background-color: #dff0d8;
color: #5cb85c;
font-size: 10px;
padding: 1px 4px;
border-radius: 3px;
margin-left: 6px;
}
.user-time-area {
font-size: 12px;
color: #999;
}
.follow-btn {
font-size: 12px;
color: #5cb85c;
background-color: #e8f5e9;
padding: 4px 8px;
border-radius: 12px;
}
.mp-html { .article-content {
font-size: 15px; padding: 16px;
color: #333; }
line-height: 1.8;
}
.mp-html img {
max-width: 100%;
height: auto;
margin: 10px 0;
border-radius: 8px;
}
.interact-area { .post-title {
display: flex; font-size: 18px;
justify-content: space-around; font-weight: bold;
margin-top: 20px; color: #333;
padding: 10px 0; margin-bottom: 12px;
border-top: 1px solid #eee; line-height: 1.4;
} }
.interact-item {
display: flex; .user-info {
flex-direction: column; display: flex;
align-items: center; align-items: center;
font-size: 12px; margin-bottom: 16px;
color: #999; }
}
.interact-count { .user-avatar {
margin-top: 4px; width: 40px;
} height: 40px;
border-radius: 50%;
margin-right: 10px;
}
.user-meta {
flex: 1;
}
.user-name {
display: flex;
align-items: center;
font-size: 14px;
color: #333;
margin-bottom: 4px;
}
.user-level {
background-color: #dff0d8;
color: #5cb85c;
font-size: 10px;
padding: 1px 4px;
border-radius: 3px;
margin-left: 6px;
}
.user-time-area {
font-size: 12px;
color: #999;
}
.follow-btn {
font-size: 12px;
color: #5cb85c;
background-color: #e8f5e9;
padding: 4px 8px;
border-radius: 12px;
}
.mp-html {
font-size: 15px;
color: #333;
line-height: 1.8;
}
.mp-html img {
max-width: 100%;
height: auto;
margin: 10px 0;
border-radius: 8px;
}
.interact-area {
display: flex;
justify-content: space-around;
margin-top: 20px;
padding: 10px 0;
border-top: 1px solid #eee;
}
.interact-item {
display: flex;
flex-direction: column;
align-items: center;
font-size: 12px;
color: #999;
}
.interact-count {
margin-top: 4px;
}
</style> </style>

View File

@@ -219,7 +219,7 @@
// 跳转到详情页 // 跳转到详情页
navigateToDetail(msg) { navigateToDetail(msg) {
uni.navigateTo({ uni.navigateTo({
url: `/pages/workbench/feedback/detail?feedbackId=${msg.feedbackId}` url: `/pages/workbench/article/article?id=${msg.feedbackId}&type=feedback`
}); });
}, },