【新增】反馈管理

This commit is contained in:
2025-11-04 10:06:20 +08:00
parent 80a60e37af
commit 73dda8b648
9 changed files with 302 additions and 45 deletions

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.corewing.app.mapper.FeedbackMapper">
<!-- 结果映射 -->
<resultMap id="VOResultMap" type="com.corewing.app.entity.Feedback">
<id column="id" property="id"/>
<result column="feedback_type" property="feedbackType"/>
<result column="title" property="title"/>
<result column="content" property="content"/>
<result column="contact" property="contact"/>
<result column="status" property="status"/>
<result column="nick_name" property="nickName"/>
<result column="username" property="username"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<!-- 基础查询SQL片段 -->
<sql id="selectVOSql">
select f.*,u.nick_name, u.username
from app_feedback f
left join app_user u on f.user_id = u.id
</sql>
<!-- 分页查询 -->
<select id="page" resultMap="VOResultMap">
<include refid="selectVOSql"/>
<where>
<if test="feedback.status != null">
AND f.status = #{feedback.status}
</if>
<if test="feedback.title != null and feedback.title != ''">
AND f.title like CONCAT('%', #{feedback.title}, '%')
</if>
<if test="feedback.feedbackType != null and feedback.feedbackType != ''">
AND f.feedbackType like CONCAT('%', #{feedback.feedbackType}, '%')
</if>
</where>
</select>
</mapper>

View File

@@ -42,8 +42,10 @@
@change="fetchData()"
>
<option value="">全部</option>
<option value="1">显示</option>
<option value="2">隐藏</option>
<option value="0">待处理</option>
<option value="1">处理中</option>
<option value="2">已完成</option>
<option value="3">已关闭</option>
</select>
</div>
</div>
@@ -77,8 +79,11 @@
@change="toggleSelectAll()"
>
</th>
<th>名称</th>
<th>是否显示</th>
<th>反馈问题</th>
<th>反馈详情</th>
<th>反馈用户</th>
<th>联系方式</th>
<th>流程</th>
<th>创建时间</th>
<th style="width: 120px;">操作</th>
</tr>
@@ -120,9 +125,12 @@
>
</td>
<td>{{ item.title }}</td>
<td class="ellipsis-single">{{ item.content }}</td>
<td>{{ item.nickName }}</td>
<td>{{ item.contact }}</td>
<td>
<span class="badge" :class="item.status === 0 ? 'bg-warning' : 'bg-success'">
{{ item.status === 0 ? '待处理' : '已处理' }}
<span class="badge" :class="item.status === 0 ? 'bg-warning' : (item.status === 2 ? 'bg-success': (item.status === 3 ? 'bg-dark':'bg-info'))">
{{ item.statusName }}
</span>
</td>
<td>{{ formatTime(item.createTime) }}</td>
@@ -208,35 +216,44 @@
<div class="modal-body">
<form>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label">名称</label>
<label class="col-sm-3 col-form-label">反馈标题</label>
<div class="col-sm-9">
<input type="text" class="form-control" v-model="addOrEditDto.title"
placeholder="请输入名称">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label">内容</label>
<label class="col-sm-3 col-form-label">联系方式</label>
<div class="col-sm-9">
<!-- 富文本编辑器容器 -->
<div id="contentEditor" style="border: 1px solid #dee2e6; border-radius: 0.375rem;"></div>
<!-- 错误提示 -->
<div class="invalid-feedback" id="contentError" style="display: none; margin-top: 0.25rem;"></div>
<input type="text" class="form-control" v-model="addOrEditDto.contact"
placeholder="请输入联系方式">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label">反馈内容</label>
<div class="col-sm-9">
<!-- &lt;!&ndash; 富文本编辑器容器 &ndash;&gt;-->
<!-- <div id="contentEditor" style="border: 1px solid #dee2e6; border-radius: 0.375rem;"></div>-->
<!-- &lt;!&ndash; 错误提示 &ndash;&gt;-->
<!-- <div class="invalid-feedback" id="contentError" style="display: none; margin-top: 0.25rem;"></div>-->
<textarea class="form-control" v-model="addOrEditDto.content"></textarea>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label">流程</label>
<div class="col-sm-9">
<select class="form-control" v-model="addOrEditDto.status">
<option value=1>显示</option>
<option value=2>隐藏</option>
<option value="0">待处理</option>
<option value="1">处理中</option>
<option value="2">已完成</option>
<option value="3">已关闭</option>
</select>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label">序号</label>
<label class="col-sm-3 col-form-label">反馈用户</label>
<div class="col-sm-9">
<input type="number" class="form-control" v-model="addOrEditDto.sort"
placeholder="请输入序号">
<input type="text" class="form-control" readonly v-model="addOrEditDto.nickName">
</div>
</div>
</form>
@@ -283,19 +300,14 @@
batchAction: '', // 批量操作选择
pageRange: 5,
modalInstances: {},
resetPasswordDto: {
userId: null,
nickName: null,
username: null,
password: null,
},
addOrEditTitle: '',
addOrEditDto: {
id: null,
title: null,
content: null,
visible: 1,
sort: 99
contact: null,
status: 0,
nickName: 0,
},
editor: null, // WangEditor 实例
}
@@ -430,7 +442,7 @@
content: `确定要删除选中的 ${this.selectedIds.length} 条数据吗?`,
onConfirm: async () => {
try {
const response = await request.post('/biz/privacy_policy/batchDelete', {ids: this.selectedIds});
const response = await request.post('/biz/feedback/batchDelete', {ids: this.selectedIds});
if (response.code === 200) {
$message.success("删除成功");
this.fetchData();
@@ -450,7 +462,7 @@
content: '确定要删除这条数据吗?',
onConfirm: async () => {
try {
const response = await request.delete('/biz/privacy_policy/delete', {id});
const response = await request.delete('/biz/feedback/delete', {id});
if (response.code === 200) {
$message.success("删除成功");
this.fetchData(); // 重新加载数据
@@ -480,17 +492,18 @@
this.modalInstances['addOrEditModel'].show();
},
saveEntity() {
let url = (this.addOrEditDto === null || this.addOrEditDto.id === null) ? '/biz/privacy_policy/save' : '/biz/privacy_policy/update';
let url = (this.addOrEditDto === null || this.addOrEditDto.id === null) ? '/biz/feedback/save' : '/biz/feedback/update';
request.post(url, this.addOrEditDto)
.then((res) => {
if (res.code === 200) {
$message.success('保存成功!', 500);
this.fetchData();
this.clearForm();
this.modalInstances['addOrEditModel'].hide();
} else {
$message.error('保存失败!', 500);
}
this.clearForm();
}).catch(() => {
@@ -502,8 +515,9 @@
id: null,
title: null,
content: null,
visible: 1,
sort: 99
contact: null,
status: 0,
nickName: 0,
};
},
// 初始化 WangEditor
@@ -558,20 +572,20 @@
}
});
// 初始化 WangEditor延迟初始化确保DOM加载完成
setTimeout(() => {
this.initWangEditor();
}, 500);
// 监听模态框关闭事件,避免内存泄漏
const modal = document.getElementById('addOrEditModel');
modal.addEventListener('hidden.bs.modal', () => {
if (this.editor) {
this.editor.txt.clear(); // 清空内容
document.getElementById('contentEditor').style.borderColor = '#dee2e6';
document.getElementById('contentError').style.display = 'none';
}
});
// // 初始化 WangEditor延迟初始化确保DOM加载完成
// setTimeout(() => {
// this.initWangEditor();
// }, 500);
//
// // 监听模态框关闭事件,避免内存泄漏
// const modal = document.getElementById('addOrEditModel');
// modal.addEventListener('hidden.bs.modal', () => {
// if (this.editor) {
// this.editor.txt.clear(); // 清空内容
// document.getElementById('contentEditor').style.borderColor = '#dee2e6';
// document.getElementById('contentError').style.display = 'none';
// }
// });
}
}).mount('#app');
</script>