Files
Environment-Monitoring-System/Design/frontend_Design/FeedbackManagementPage_Design.md
ChuXun 4ce487588a 1
2025-10-19 20:31:01 +08:00

261 lines
7.8 KiB
Markdown
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.
# 反馈管理页面设计文档
## 1. 页面概述
反馈管理页面是管理员和主管处理用户提交的环境问题报告、建议或其他反馈的核心平台。此页面旨在提供一个高效的工作流程,用于审查、分类、回复和跟踪所有用户反馈,确保问题得到及时响应和解决。
## 2. 页面布局
![反馈管理页面布局示意图](https://placeholder-for-feedback-page-mockup.png)
### 2.1 布局结构
页面布局与任务管理页面类似,遵循标准的后台管理界面设计:
- **顶部**: 筛选区域,允许管理员按反馈状态(待处理、已处理)、反馈类型或提交时间进行过滤。
- **中部**: 反馈列表,以表格或卡片列表的形式展示反馈信息。
- **底部**: 分页控件。
### 2.2 响应式设计
- **桌面端**: 使用多列数据表格,清晰展示反馈的各项信息。
- **移动端**: 转换为卡片式列表,每张卡片突出显示反馈标题、提交人和状态,并提供点击查看详情的入口。
## 3. 组件结构
```vue
<template>
<div class="feedback-management-page">
<el-page-header title="反馈管理" content="用户反馈列表" />
<el-card class="page-container">
<!-- 筛选区域 -->
<div class="filter-container">
<el-form :model="filters" inline>
<el-form-item label="处理状态">
<el-select v-model="filters.status" placeholder="请选择状态" clearable>
<el-option label="待处理" value="PENDING" />
<el-option label="已处理" value="RESOLVED" />
</el-select>
</el-form-item>
<el-form-item label="提交人">
<el-input v-model="filters.submitter" placeholder="输入提交人姓名/ID" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</div>
<!-- 反馈表格 -->
<el-table :data="feedbackList" v-loading="loading" stripe>
<el-table-column prop="title" label="反馈标题" min-width="200" />
<el-table-column prop="submitterName" label="提交人" width="120" />
<el-table-column prop="createdAt" label="提交时间" width="180" sortable />
<el-table-column prop="status" label="状态" width="100">
<template #default="{ row }">
<el-tag :type="row.status === 'PENDING' ? 'warning' : 'success'">
{{ row.status === 'PENDING' ? '待处理' : '已处理' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="handleViewDetails(row)">查看详情</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
v-if="total > 0"
class="pagination-container"
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
<!-- 反馈详情对话框 -->
<FeedbackDetailDialog
v-model="dialogVisible"
:feedback-id="selectedFeedbackId"
@processed="handleProcessed"
/>
</div>
</template>
```
## 4. 数据结构
```typescript
// 反馈筛选条件
interface FeedbackFilters {
status?: 'PENDING' | 'RESOLVED';
submitter?: string;
}
// 反馈列表项
interface FeedbackListItem {
id: number;
title: string;
submitterName: string;
createdAt: string;
status: 'PENDING' | 'RESOLVED';
}
// 反馈详情 (用于对话框)
interface FeedbackDetail extends FeedbackListItem {
content: string;
images: string[]; // 图片 URL 列表
location: string;
contact: string;
handlerNotes?: string; // 处理备注
}
```
## 5. 状态管理
```typescript
// 组件内状态
const filters = ref<FeedbackFilters>({});
const pagination = ref({ page: 1, pageSize: 10 });
const dialogVisible = ref(false);
const selectedFeedbackId = ref<number | null>(null);
// 全局状态 (Pinia Store)
const feedbackStore = useFeedbackStore();
const { feedbackList, total, loading } = storeToRefs(feedbackStore);
```
## 6. 交互逻辑
### 6.1 数据获取与筛选
```typescript
const fetchFeedback = () => {
feedbackStore.fetchFeedbackList({ ...filters.value, ...pagination.value });
};
onMounted(fetchFeedback);
const handleSearch = () => {
pagination.value.page = 1;
fetchFeedback();
};
// 分页逻辑 (handleSizeChange, handleCurrentChange) 与任务管理页面类似
```
### 6.2 查看详情与处理
```typescript
const handleViewDetails = (feedback: FeedbackListItem) => {
selectedFeedbackId.value = feedback.id;
dialogVisible.value = true;
};
// 当详情对话框中完成处理后被调用
const handleProcessed = () => {
dialogVisible.value = false;
fetchFeedback(); // 刷新列表以更新状态
};
```
## 7. API 调用
### 7.1 反馈管理 API
```typescript
// api/feedback.ts
export const feedbackApi = {
getFeedbackList: (params) => apiClient.get('/management/feedback', { params }),
getFeedbackDetail: (id: number) => apiClient.get(`/management/feedback/${id}`),
processFeedback: (id: number, data: { notes: string }) => apiClient.post(`/management/feedback/${id}/process`, data),
};
```
### 7.2 Pinia Store
```typescript
// stores/feedback.ts
export const useFeedbackStore = defineStore('feedback', {
state: () => ({
feedbackList: [] as FeedbackListItem[],
total: 0,
loading: false,
currentFeedbackDetail: null as FeedbackDetail | null,
}),
actions: {
async fetchFeedbackList(params) {
this.loading = true;
try {
const { data } = await feedbackApi.getFeedbackList(params);
this.feedbackList = data.items;
this.total = data.total;
} finally {
this.loading = false;
}
},
async fetchFeedbackDetail(id: number) {
const { data } = await feedbackApi.getFeedbackDetail(id);
this.currentFeedbackDetail = data;
},
async processFeedback(payload: { id: number; notes: string }) {
await feedbackApi.processFeedback(payload.id, { notes: payload.notes });
}
}
});
```
## 8. 样式设计
```scss
.feedback-management-page {
padding: 24px;
.page-container {
margin-top: 24px;
padding: 24px;
border-radius: 8px;
border: none;
}
.filter-container {
margin-bottom: 20px;
}
.pagination-container {
margin-top: 24px;
display: flex;
justify-content: flex-end;
}
}
```
## 9. 关联组件
### `FeedbackDetailDialog.vue`
这是一个关键的子组件,用于显示反馈的完整信息,并提供处理功能。
- **Props**: `modelValue` (for v-model), `feedbackId`
- **功能**:
- 接收 `feedbackId`,在对话框打开时调用 store action 获取反馈详情。
- 展示反馈的文本内容、联系方式、地理位置和图片(图片可点击放大预览)。
- 提供一个文本域供管理员填写处理备注。
- 提供一个"标记为已处理"的按钮,点击后调用 store action 提交处理结果。
- 操作成功后emit 一个 `processed` 事件通知父组件刷新列表。
## 10. 测试用例
1. **单元测试**:
- 测试 Pinia store 的各个 action 是否能正常工作。
- 测试 `FeedbackDetailDialog` 组件在接收到 `feedbackId` 后是否能正确加载和显示数据。
2. **集成测试**:
- 测试筛选功能是否能正确过滤反馈列表。
- 测试分页是否正常。
- 测试点击"查看详情"按钮是否能打开对话框并加载正确的反馈信息。
- 测试在详情对话框中提交处理意见后,列表中的反馈状态是否更新。