1
This commit is contained in:
261
Design/frontend_Design/FeedbackManagementPage_Design.md
Normal file
261
Design/frontend_Design/FeedbackManagementPage_Design.md
Normal file
@@ -0,0 +1,261 @@
|
||||
# 反馈管理页面设计文档
|
||||
|
||||
## 1. 页面概述
|
||||
|
||||
反馈管理页面是管理员和主管处理用户提交的环境问题报告、建议或其他反馈的核心平台。此页面旨在提供一个高效的工作流程,用于审查、分类、回复和跟踪所有用户反馈,确保问题得到及时响应和解决。
|
||||
|
||||
## 2. 页面布局
|
||||
|
||||

|
||||
|
||||
### 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. **集成测试**:
|
||||
- 测试筛选功能是否能正确过滤反馈列表。
|
||||
- 测试分页是否正常。
|
||||
- 测试点击"查看详情"按钮是否能打开对话框并加载正确的反馈信息。
|
||||
- 测试在详情对话框中提交处理意见后,列表中的反馈状态是否更新。
|
||||
Reference in New Issue
Block a user