|
@@ -0,0 +1,797 @@
|
|
|
+<template>
|
|
|
+ <basic-container>
|
|
|
+ <avue-crud
|
|
|
+ :option="option"
|
|
|
+ :table-loading="loading"
|
|
|
+ :data="data"
|
|
|
+ :page="page"
|
|
|
+ ref="crud"
|
|
|
+ v-model="form"
|
|
|
+ :permission="permissionList"
|
|
|
+ @row-update="rowUpdate"
|
|
|
+ @row-save="rowSave"
|
|
|
+ @row-del="rowDel"
|
|
|
+ @search-change="searchChange"
|
|
|
+ @search-reset="searchReset"
|
|
|
+ @selection-change="selectionChange"
|
|
|
+ @current-change="currentChange"
|
|
|
+ @size-change="sizeChange"
|
|
|
+ @refresh-change="refreshChange"
|
|
|
+ @on-load="onLoad"
|
|
|
+ >
|
|
|
+ <template slot="menuLeft">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ icon="el-icon-plus"
|
|
|
+ v-if="permission.complaint_add"
|
|
|
+ @click="handleAdd"
|
|
|
+ >
|
|
|
+ 新增投诉
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="warning"
|
|
|
+ size="small"
|
|
|
+ icon="el-icon-edit"
|
|
|
+ :disabled="selectionList.length !== 1"
|
|
|
+ v-if="permission.complaint_edit"
|
|
|
+ @click="handleBatchStatus"
|
|
|
+ >
|
|
|
+ 批量处理
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template slot="status" slot-scope="{row}">
|
|
|
+ <el-tag
|
|
|
+ :type="getStatusType(row.status)"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ {{ getStatusText(row.status) }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template slot="replyStatus" slot-scope="{row}">
|
|
|
+ <el-tag
|
|
|
+ :type="row.replyStatus === 1 ? 'success' : 'info'"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ {{ row.replyStatus === 1 ? '已回复' : '未回复' }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template slot="complainantType" slot-scope="{row}">
|
|
|
+ <span>{{ getComplainantTypeText(row.complainantType) }}</span>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template slot="menu" slot-scope="{row}">
|
|
|
+ <el-button
|
|
|
+ type="text"
|
|
|
+ size="small"
|
|
|
+ icon="el-icon-view"
|
|
|
+ @click="handleDetail(row)"
|
|
|
+ >
|
|
|
+ 详情
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="text"
|
|
|
+ size="small"
|
|
|
+ icon="el-icon-edit"
|
|
|
+ v-if="permission.complaint_edit && row.status !== 4"
|
|
|
+ @click="handleEdit(row)"
|
|
|
+ >
|
|
|
+ 编辑
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="text"
|
|
|
+ size="small"
|
|
|
+ icon="el-icon-check"
|
|
|
+ v-if="permission.complaint_edit && row.status === 1"
|
|
|
+ @click="handleProcess(row)"
|
|
|
+ >
|
|
|
+ 处理
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="text"
|
|
|
+ size="small"
|
|
|
+ icon="el-icon-close"
|
|
|
+ v-if="permission.complaint_edit && row.status !== 4"
|
|
|
+ @click="handleClose(row)"
|
|
|
+ >
|
|
|
+ 关闭
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </avue-crud>
|
|
|
+
|
|
|
+ <!-- 投诉详情对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ title="投诉详情"
|
|
|
+ :visible.sync="detailVisible"
|
|
|
+ width="800px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :modal-append-to-body="false"
|
|
|
+ :append-to-body="true"
|
|
|
+ :destroy-on-close="true"
|
|
|
+ class="complaint-detail-dialog"
|
|
|
+ >
|
|
|
+ <div v-if="detailData" class="complaint-detail">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>投诉单号:</label>
|
|
|
+ <span>{{ detailData.complaintNo }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>投诉标题:</label>
|
|
|
+ <span>{{ detailData.title }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>投诉人类型:</label>
|
|
|
+ <span>{{ getComplainantTypeText(detailData.complainantType) }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>投诉类型:</label>
|
|
|
+ <span>{{ detailData.complaintType }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>联系人:</label>
|
|
|
+ <span>{{ detailData.contactName }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>联系电话:</label>
|
|
|
+ <span>{{ detailData.contactPhone }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="20" v-if="detailData.customerName">
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>客户名称:</label>
|
|
|
+ <span>{{ detailData.customerName }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>客户编码:</label>
|
|
|
+ <span>{{ detailData.customerCode }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>投诉状态:</label>
|
|
|
+ <el-tag :type="getStatusType(detailData.status)" size="small">
|
|
|
+ {{ getStatusText(detailData.status) }}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>回复状态:</label>
|
|
|
+ <el-tag :type="detailData.replyStatus === 1 ? 'success' : 'info'" size="small">
|
|
|
+ {{ detailData.replyStatus === 1 ? '已回复' : '未回复' }}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>投诉内容:</label>
|
|
|
+ <div class="content-text">{{ detailData.content }}</div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="20" v-if="detailData.closeReason">
|
|
|
+ <el-col :span="24">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>关闭原因:</label>
|
|
|
+ <div class="content-text">{{ detailData.closeReason }}</div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>提交时间:</label>
|
|
|
+ <span>{{ detailData.submitTime }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="detail-item">
|
|
|
+ <label>更新时间:</label>
|
|
|
+ <span>{{ detailData.updateTime }}</span>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="detailVisible = false">关闭</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 状态处理对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ :title="statusDialogTitle"
|
|
|
+ :visible.sync="statusVisible"
|
|
|
+ width="500px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ >
|
|
|
+ <el-form :model="statusForm" :rules="statusRules" ref="statusForm" label-width="100px">
|
|
|
+ <el-form-item label="新状态" prop="status">
|
|
|
+ <el-select v-model="statusForm.status" placeholder="请选择状态" style="width: 100%">
|
|
|
+ <el-option label="待处理" :value="1"></el-option>
|
|
|
+ <el-option label="处理中" :value="2"></el-option>
|
|
|
+ <el-option label="已完成" :value="3"></el-option>
|
|
|
+ <el-option label="已关闭" :value="4"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="关闭原因" prop="closeReason" v-if="statusForm.status === 4">
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ v-model="statusForm.closeReason"
|
|
|
+ placeholder="请输入关闭原因"
|
|
|
+ ></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="statusVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmStatusUpdate" :loading="statusLoading">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </basic-container>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getList, add, update, remove, getDetail, updateStatus, batchUpdateStatus } from '@/api/complaint'
|
|
|
+import { mapGetters } from 'vuex'
|
|
|
+
|
|
|
+/**
|
|
|
+ * 投诉查询参数类型定义
|
|
|
+ * @typedef {Object} ComplaintQueryParams
|
|
|
+ * @property {string} [complaintNo] - 投诉单号
|
|
|
+ * @property {string} [title] - 投诉标题
|
|
|
+ * @property {number} [complainantType] - 投诉人类型
|
|
|
+ * @property {string} [customerCode] - 客户编码
|
|
|
+ * @property {string} [customerName] - 客户名称
|
|
|
+ * @property {string} [contactName] - 联系人姓名
|
|
|
+ * @property {string} [contactPhone] - 联系人电话
|
|
|
+ * @property {string} [complaintType] - 投诉类型
|
|
|
+ * @property {number} [status] - 投诉状态
|
|
|
+ * @property {number} [replyStatus] - 回复状态
|
|
|
+ * @property {string} [submitTimeStart] - 提交时间开始
|
|
|
+ * @property {string} [submitTimeEnd] - 提交时间结束
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * 状态更新表单类型定义
|
|
|
+ * @typedef {Object} StatusForm
|
|
|
+ * @property {number} status - 新状态
|
|
|
+ * @property {string} [closeReason] - 关闭原因
|
|
|
+ */
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ /** @type {ComplaintRecord[]} */
|
|
|
+ data: [],
|
|
|
+ /** @type {ComplaintQueryParams} */
|
|
|
+ query: {},
|
|
|
+ loading: true,
|
|
|
+ /** @type {ComplaintForm} */
|
|
|
+ form: {},
|
|
|
+ /** @type {ComplaintRecord[]} */
|
|
|
+ selectionList: [],
|
|
|
+ /** @type {Object} */
|
|
|
+ page: {
|
|
|
+ pageSize: 10,
|
|
|
+ currentPage: 1,
|
|
|
+ total: 0
|
|
|
+ },
|
|
|
+ /** @type {ComplaintRecord|null} */
|
|
|
+ detailData: null,
|
|
|
+ detailVisible: false,
|
|
|
+ statusVisible: false,
|
|
|
+ statusDialogTitle: '',
|
|
|
+ /** @type {StatusForm} */
|
|
|
+ statusForm: {
|
|
|
+ status: 1,
|
|
|
+ closeReason: ''
|
|
|
+ },
|
|
|
+ statusLoading: false,
|
|
|
+ /** @type {string[]} */
|
|
|
+ currentIds: [],
|
|
|
+ statusRules: {
|
|
|
+ status: [
|
|
|
+ { required: true, message: '请选择状态', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ closeReason: [
|
|
|
+ { required: true, message: '请输入关闭原因', trigger: 'blur' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ option: {
|
|
|
+ height: 'auto',
|
|
|
+ calcHeight: 30,
|
|
|
+ tip: false,
|
|
|
+ searchShow: true,
|
|
|
+ searchMenuSpan: 6,
|
|
|
+ border: true,
|
|
|
+ index: true,
|
|
|
+ viewBtn: true,
|
|
|
+ selection: true,
|
|
|
+ dialogClickModal: false,
|
|
|
+ column: [
|
|
|
+ {
|
|
|
+ label: '投诉单号',
|
|
|
+ prop: 'complaintNo',
|
|
|
+ minWidth: 150,
|
|
|
+ search: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '投诉标题',
|
|
|
+ prop: 'title',
|
|
|
+ minWidth: 200,
|
|
|
+ search: true,
|
|
|
+ overHidden: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '投诉人类型',
|
|
|
+ prop: 'complainantType',
|
|
|
+ minWidth: 100,
|
|
|
+ slot: true,
|
|
|
+ search: true,
|
|
|
+ type: 'select',
|
|
|
+ dicData: [
|
|
|
+ { label: '消费者', value: 1 },
|
|
|
+ { label: '经销商', value: 2 },
|
|
|
+ { label: '分销商', value: 3 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '客户名称',
|
|
|
+ prop: 'customerName',
|
|
|
+ minWidth: 150,
|
|
|
+ search: true,
|
|
|
+ overHidden: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '联系人',
|
|
|
+ prop: 'contactName',
|
|
|
+ minWidth: 100,
|
|
|
+ search: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '联系电话',
|
|
|
+ prop: 'contactPhone',
|
|
|
+ minWidth: 120,
|
|
|
+ search: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '投诉类型',
|
|
|
+ prop: 'complaintType',
|
|
|
+ minWidth: 100,
|
|
|
+ search: true,
|
|
|
+ type: 'select',
|
|
|
+ dicData: [
|
|
|
+ { label: '质量', value: '质量' },
|
|
|
+ { label: '物流', value: '物流' },
|
|
|
+ { label: '服务', value: '服务' },
|
|
|
+ { label: '价格', value: '价格' },
|
|
|
+ { label: '其他', value: '其他' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '投诉状态',
|
|
|
+ prop: 'status',
|
|
|
+ minWidth: 100,
|
|
|
+ slot: true,
|
|
|
+ search: true,
|
|
|
+ type: 'select',
|
|
|
+ dicData: [
|
|
|
+ { label: '待处理', value: 1 },
|
|
|
+ { label: '处理中', value: 2 },
|
|
|
+ { label: '已完成', value: 3 },
|
|
|
+ { label: '已关闭', value: 4 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '回复状态',
|
|
|
+ prop: 'replyStatus',
|
|
|
+ minWidth: 100,
|
|
|
+ slot: true,
|
|
|
+ search: true,
|
|
|
+ type: 'select',
|
|
|
+ dicData: [
|
|
|
+ { label: '未回复', value: 0 },
|
|
|
+ { label: '已回复', value: 1 }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '提交时间',
|
|
|
+ prop: 'submitTime',
|
|
|
+ minWidth: 150,
|
|
|
+ type: 'datetime',
|
|
|
+ format: 'YYYY-MM-DD HH:mm:ss',
|
|
|
+ valueFormat: 'YYYY-MM-DD HH:mm:ss'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '更新时间',
|
|
|
+ prop: 'updateTime',
|
|
|
+ minWidth: 150,
|
|
|
+ type: 'datetime',
|
|
|
+ format: 'YYYY-MM-DD HH:mm:ss',
|
|
|
+ valueFormat: 'YYYY-MM-DD HH:mm:ss'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ ...mapGetters(['permission']),
|
|
|
+ permissionList() {
|
|
|
+ return {
|
|
|
+ addBtn: this.vaildData(this.permission.complaint_add, false),
|
|
|
+ viewBtn: this.vaildData(this.permission.complaint_view, false),
|
|
|
+ delBtn: this.vaildData(this.permission.complaint_delete, false),
|
|
|
+ editBtn: this.vaildData(this.permission.complaint_edit, false)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ids() {
|
|
|
+ /** @type {string[]} */
|
|
|
+ const ids = []
|
|
|
+ this.selectionList.forEach(ele => {
|
|
|
+ ids.push(ele.id)
|
|
|
+ })
|
|
|
+ return ids.join(',')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ /**
|
|
|
+ * 获取投诉状态文本
|
|
|
+ * @param {number} status - 状态值
|
|
|
+ * @returns {string} 状态文本
|
|
|
+ */
|
|
|
+ getStatusText(status) {
|
|
|
+ const statusMap = {
|
|
|
+ 1: '待处理',
|
|
|
+ 2: '处理中',
|
|
|
+ 3: '已完成',
|
|
|
+ 4: '已关闭'
|
|
|
+ }
|
|
|
+ return statusMap[status] || '未知'
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取投诉状态标签类型
|
|
|
+ * @param {number} status - 状态值
|
|
|
+ * @returns {string} 标签类型
|
|
|
+ */
|
|
|
+ getStatusType(status) {
|
|
|
+ const typeMap = {
|
|
|
+ 1: 'warning',
|
|
|
+ 2: 'primary',
|
|
|
+ 3: 'success',
|
|
|
+ 4: 'info'
|
|
|
+ }
|
|
|
+ return typeMap[status] || 'info'
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取投诉人类型文本
|
|
|
+ * @param {number} type - 类型值
|
|
|
+ * @returns {string} 类型文本
|
|
|
+ */
|
|
|
+ getComplainantTypeText(type) {
|
|
|
+ const typeMap = {
|
|
|
+ 1: '消费者',
|
|
|
+ 2: '经销商',
|
|
|
+ 3: '分销商'
|
|
|
+ }
|
|
|
+ return typeMap[type] || '未知'
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 行保存
|
|
|
+ * @param {ComplaintForm} row - 表单数据
|
|
|
+ * @param {boolean} done - 完成回调
|
|
|
+ * @param {boolean} loading - 加载状态回调
|
|
|
+ */
|
|
|
+ async rowSave(row, done, loading) {
|
|
|
+ try {
|
|
|
+ loading()
|
|
|
+ const res = await add(row)
|
|
|
+ if (res.data.success) {
|
|
|
+ this.$message.success('操作成功')
|
|
|
+ done()
|
|
|
+ this.onLoad(this.page)
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data.msg || '操作失败')
|
|
|
+ loading()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('新增投诉失败:', error)
|
|
|
+ this.$message.error('操作失败')
|
|
|
+ loading()
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 行更新
|
|
|
+ * @param {ComplaintForm} row - 表单数据
|
|
|
+ * @param {number} index - 行索引
|
|
|
+ * @param {boolean} done - 完成回调
|
|
|
+ * @param {boolean} loading - 加载状态回调
|
|
|
+ */
|
|
|
+ async rowUpdate(row, index, done, loading) {
|
|
|
+ try {
|
|
|
+ loading()
|
|
|
+ const res = await update(row)
|
|
|
+ if (res.data.success) {
|
|
|
+ this.$message.success('操作成功')
|
|
|
+ done()
|
|
|
+ this.onLoad(this.page)
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data.msg || '操作失败')
|
|
|
+ loading()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('修改投诉失败:', error)
|
|
|
+ this.$message.error('操作失败')
|
|
|
+ loading()
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 行删除
|
|
|
+ * @param {ComplaintRecord} row - 行数据
|
|
|
+ * @param {number} index - 行索引
|
|
|
+ */
|
|
|
+ async rowDel(row, index) {
|
|
|
+ try {
|
|
|
+ const res = await remove(row.id)
|
|
|
+ if (res.data.success) {
|
|
|
+ this.$message.success('操作成功')
|
|
|
+ this.onLoad(this.page)
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data.msg || '操作失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('删除投诉失败:', error)
|
|
|
+ this.$message.error('操作失败')
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 搜索变化
|
|
|
+ * @param {ComplaintQueryParams} params - 搜索参数
|
|
|
+ * @param {boolean} done - 完成回调
|
|
|
+ */
|
|
|
+ searchChange(params, done) {
|
|
|
+ this.query = params
|
|
|
+ this.onLoad(this.page, params)
|
|
|
+ done()
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 搜索重置
|
|
|
+ */
|
|
|
+ searchReset() {
|
|
|
+ this.query = {}
|
|
|
+ this.onLoad(this.page)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 选择变化
|
|
|
+ * @param {ComplaintRecord[]} val - 选中的行
|
|
|
+ */
|
|
|
+ selectionChange(val) {
|
|
|
+ this.selectionList = val
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当前页变化
|
|
|
+ * @param {number} currentPage - 当前页
|
|
|
+ */
|
|
|
+ currentChange(currentPage) {
|
|
|
+ this.page.currentPage = currentPage
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 页大小变化
|
|
|
+ * @param {number} pageSize - 页大小
|
|
|
+ */
|
|
|
+ sizeChange(pageSize) {
|
|
|
+ this.page.pageSize = pageSize
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 刷新变化
|
|
|
+ */
|
|
|
+ refreshChange() {
|
|
|
+ this.onLoad(this.page, this.query)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加载数据
|
|
|
+ * @param {Object} page - 分页信息
|
|
|
+ * @param {ComplaintQueryParams} [params={}] - 查询参数
|
|
|
+ */
|
|
|
+ async onLoad(page, params = {}) {
|
|
|
+ this.loading = true
|
|
|
+ try {
|
|
|
+ const res = await getList(page.currentPage, page.pageSize, Object.assign(params, this.query))
|
|
|
+ if (res.data.success) {
|
|
|
+ const data = res.data.data
|
|
|
+ this.data = data.records
|
|
|
+ this.page.total = data.total
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data.msg || '查询失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('查询投诉列表失败:', error)
|
|
|
+ this.$message.error('查询失败')
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增投诉
|
|
|
+ */
|
|
|
+ handleAdd() {
|
|
|
+ this.$refs.crud.rowAdd()
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 编辑投诉
|
|
|
+ * @param {ComplaintRecord} row - 行数据
|
|
|
+ */
|
|
|
+ handleEdit(row) {
|
|
|
+ this.$refs.crud.rowEdit(row, this.data.indexOf(row))
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查看详情
|
|
|
+ * @param {ComplaintRecord} row - 行数据
|
|
|
+ */
|
|
|
+ async handleDetail(row) {
|
|
|
+ try {
|
|
|
+ const res = await getDetail(row.id)
|
|
|
+ if (res.data.success) {
|
|
|
+ this.detailData = res.data.data
|
|
|
+ this.detailVisible = true
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data.msg || '获取详情失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取投诉详情失败:', error)
|
|
|
+ this.$message.error('获取详情失败')
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理投诉
|
|
|
+ * @param {ComplaintRecord} row - 行数据
|
|
|
+ */
|
|
|
+ handleProcess(row) {
|
|
|
+ this.statusDialogTitle = '处理投诉'
|
|
|
+ this.statusForm = {
|
|
|
+ status: 2,
|
|
|
+ closeReason: ''
|
|
|
+ }
|
|
|
+ this.currentIds = [row.id]
|
|
|
+ this.statusVisible = true
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭投诉
|
|
|
+ * @param {ComplaintRecord} row - 行数据
|
|
|
+ */
|
|
|
+ handleClose(row) {
|
|
|
+ this.statusDialogTitle = '关闭投诉'
|
|
|
+ this.statusForm = {
|
|
|
+ status: 4,
|
|
|
+ closeReason: ''
|
|
|
+ }
|
|
|
+ this.currentIds = [row.id]
|
|
|
+ this.statusVisible = true
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量状态处理
|
|
|
+ */
|
|
|
+ handleBatchStatus() {
|
|
|
+ if (this.selectionList.length === 0) {
|
|
|
+ this.$message.warning('请选择要处理的投诉')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.statusDialogTitle = '批量处理投诉'
|
|
|
+ this.statusForm = {
|
|
|
+ status: 2,
|
|
|
+ closeReason: ''
|
|
|
+ }
|
|
|
+ this.currentIds = this.selectionList.map(item => item.id)
|
|
|
+ this.statusVisible = true
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 确认状态更新
|
|
|
+ */
|
|
|
+ async confirmStatusUpdate() {
|
|
|
+ try {
|
|
|
+ await this.$refs.statusForm.validate()
|
|
|
+ this.statusLoading = true
|
|
|
+
|
|
|
+ let res
|
|
|
+ if (this.currentIds.length === 1) {
|
|
|
+ res = await updateStatus(this.currentIds[0], this.statusForm.status, this.statusForm.closeReason)
|
|
|
+ } else {
|
|
|
+ res = await batchUpdateStatus(this.currentIds, this.statusForm.status, this.statusForm.closeReason)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.data.success) {
|
|
|
+ this.$message.success('操作成功')
|
|
|
+ this.statusVisible = false
|
|
|
+ this.onLoad(this.page, this.query)
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data.msg || '操作失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ if (error.message) {
|
|
|
+ console.error('状态更新失败:', error)
|
|
|
+ this.$message.error('操作失败')
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ this.statusLoading = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.complaint-detail {
|
|
|
+ .detail-item {
|
|
|
+ margin-bottom: 15px;
|
|
|
+
|
|
|
+ label {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #606266;
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-text {
|
|
|
+ margin-top: 5px;
|
|
|
+ padding: 10px;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border-radius: 4px;
|
|
|
+ line-height: 1.6;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|