投诉列表

This commit is contained in:
BabyBoy 2025-06-18 10:13:20 +08:00
parent e8326be198
commit 34b31007d0
8 changed files with 427 additions and 30 deletions

View File

@ -91,6 +91,7 @@ export interface CategoryVO {
likeCounts: number;
fansCounts: number;
reason: string;
fileId: string;
/**
*
*/

25
src/api/report/index.ts Normal file
View File

@ -0,0 +1,25 @@
import { paramOV, reQueryOV } from '@/api/report/types';
import { AxiosPromise } from 'axios';
import request from '@/utils/request';
/**
*
* @param query
* @returns {*}
*/
export const listCategory = (query?: reQueryOV): AxiosPromise<[]> => {
return request({
url: '/ums/feedback/list',
method: 'post',
data: query
});
};
export const posthandle = (query?: paramOV): AxiosPromise<[]> => {
return request({
url: '/ums/feedback/handle/handle',
method: 'post',
data: query
});
};

55
src/api/report/types.ts Normal file
View File

@ -0,0 +1,55 @@
export interface CategoryTreeVO {
id: number | string;
label: string;
parentId: number | string;
weight: number;
children: CategoryTreeVO[];
}
export interface Formaget {
vlogId: number | string;
reason: string;
status: number;
}
export interface fansListVO {
bothFriend: number;
createdTime: string;
face: string;
fanId: string;
friend: boolean;
nickname: string;
}
export interface reQueryOV {
current: number;
size: number;
aimId: string | number;
phone: string | number;
}
export interface vlogListVO {
aimId: string | number;
aimObject: null;
aimType: number;
category: number;
content: string;
createBy: number;
createTime: string;
handleStatus: string;
handleTime: string;
handlerId: number;
id: number;
images: string;
member: string;
memberId: string;
phone: string;
remark: string;
resultContent: string;
resultType: number;
type: number;
}
export interface paramOV {
id: string;
resultType: string;
remark: string;
status: number;
}

View File

@ -1,4 +1,4 @@
import { CategoryForm, CategoryQuery, CategoryTreeVO, CategoryVO, Formaget, QueryChildOV, QueryParamOV } from '@/api/workflow/category/types';
import { CategoryForm, CategoryQuery, CategoryTreeVO, CategoryVO, Formaget, QueryParamOV } from '@/api/workflow/category/types';
import { AxiosPromise } from 'axios';
import request from '@/utils/request';

View File

@ -233,11 +233,17 @@ export const dynamicRoutes: RouteRecordRaw[] = [
meta: { title: '视频评论', icon: 'dashboard', affix: true }
},
{
path: 'detail',
component: () => import('@/views/contentManage/videodetails/index.vue'),
name: 'Videodetails',
meta: { title: '视频详情', icon: 'dashboard', affix: true }
path: 'report',
component: () => import('@/views/contentManage/report/index.vue'),
name: 'report',
meta: { title: '举报', icon: 'dashboard', affix: true }
}
// {
// path: 'detail',
// component: () => import('@/views/contentManage/videodetails/index.vue'),
// name: 'Videodetails',
// meta: { title: '视频详情', icon: 'dashboard', affix: true }
// }
]
}
];

View File

@ -0,0 +1,242 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="search">
<el-form ref="queryFormRef" :model="queryParam" :inline="true">
<el-form-item label="手机号" prop="phone">
<el-input v-model="queryParam.phone" placeholder="请输入手机号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="被投诉对象id" prop="aimId" label-width="120px">
<el-input v-model="queryParam.aimId" placeholder="请输入被投诉对象id" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</div>
</transition>
<el-table
ref="categoryTableRef"
:data="vlogList"
row-key="categoryId"
border
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column label="申请人" prop="status" align="center" width="100">
<template #default="{ row }">
{{ row.member.nickname }}
</template>
</el-table-column>
<el-table-column label="申请原因" prop="reasonType" align="center" width="150">
<template #default="{ row }">
{{ getEmulistLabelById(row.reasonType, statusreasontype) }}
</template>
</el-table-column>
<el-table-column label="投诉类型" prop="type" align="center" width="150">
<template #default="{ row }">
{{ getEmulistLabelById(row.type, statustype) }}
</template>
</el-table-column>
<el-table-column label="被投诉对象" prop="aimType" align="center" width="150">
<template #default="{ row }">
{{ getEmulistLabelById(row.aimType, statusaimobject) }}
</template>
</el-table-column>
<el-table-column label="处理方案" prop="resulttype" align="center" width="150">
<template #default="{ row }">
{{ getEmulistLabelById(row.resultType, statusresulttype) }}
</template>
</el-table-column>
<el-table-column label="方案内容" align="center" prop="resultContent" width="200" />
<el-table-column label="状态" prop="status" align="center" width="100">
<template #default="{ row }">
{{ getEmulistLabelById(row.status, feedbackstatus) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="审核" placement="top">
<el-button link type="primary" @click="handleAdd(scope.row)" v-hasPermi="['workflow:video:add']">审核</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['workflow:video:remove']">删除</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<div class="block">
<pagination v-if="totalref > 0" :total="totalref" v-model:page="queryParam.current" v-model:limit="queryParam.size" @pagination="getList" />
</div>
<el-dialog v-model="showRefuteDialog" title="审核">
<el-form>
<el-form-item label="处理方案">
<el-select v-model="param.resultType" placeholder="处理方案">
<el-option v-for="(item, index) in statusresulttype" :label="item.label" :value="item.value" :key="index" />
</el-select>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="param.remark" type="textarea" :rows="4"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showRefuteDialog = false">取消</el-button>
<el-button type="primary" @click="subclick">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="Category" lang="ts">
import { reQueryOV, vlogListVO, paramOV } from '@/api/report/types';
import { listCategory, posthandle } from '@/api/report/index';
import { getDictionaryByKey } from '@/utils/dict';
import { getEmulistLabelById } from '@/utils';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const showSearch = ref(true);
const showRefuteDialog = ref(false);
const queryParam = ref<reQueryOV>({
current: 1,
size: 10,
aimId: undefined,
phone: undefined
});
const vlogList = ref<vlogListVO[]>([]);
const totalref = ref<number>(0);
const isExpandAll = ref(true);
//
const handleQuery = () => {
queryParam.value.current = 1;
getList();
};
const handleDelete = (row: any) => {};
//
const resetQuery = () => {
queryParam.value = {
current: 1,
size: 10,
aimId: undefined,
phone: undefined
};
getList();
};
//
const getList = async () => {
const res = await listCategory(queryParam.value);
const { records, total } = (res.data || {}) as { records: any[]; total: number };
if (res.code == 200) {
vlogList.value = records;
totalref.value = total;
}
};
const statustype = ref([]);
const statusresulttype = ref([]);
const statusreasontype = ref([]);
const statusaimobject = ref([]);
const feedbackstatus = ref([]);
const getByKey = async () => {
const orderStatustype = await getDictionaryByKey('ums_feedback_type');
statustype.value = orderStatustype;
const orderStatusresulttype = await getDictionaryByKey('ums_feedback_resulttype');
statusresulttype.value = orderStatusresulttype;
const orderStatusreasontype = await getDictionaryByKey('ums_feedback_reasontype');
statusreasontype.value = orderStatusreasontype;
const orderStatusaimobject = await getDictionaryByKey('ums_feedback_aimobject');
statusaimobject.value = orderStatusaimobject;
const orderStatusstatus = await getDictionaryByKey('ums_feedback_status');
feedbackstatus.value = orderStatusstatus;
};
const handObj = ref({});
const param = ref<paramOV>({
id: '',
resultType: '',
remark: '',
status: 1
});
const handleAdd = (row: any) => {
param.value = {
id: '',
resultType: '',
remark: '',
status: 1
};
handObj.value = row;
showRefuteDialog.value = true;
param.value.id = row.id;
};
const subclick = async () => {
const res = await posthandle(param.value);
console.log(res);
if (res.code === 200) {
getList();
showRefuteDialog.value = false;
}
};
onMounted(() => {
getList();
getByKey();
});
</script>
<style scoped lang="scss">
.video-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.video-container .video {
width: 100%;
height: 100%;
object-fit: cover;
}
.video-info {
width: 100%;
display: flex;
justify-content: space-around;
margin-top: 10px;
font-size: 20px;
font-weight: bold;
& > div {
cursor: pointer;
}
}
.comment-list {
width: 100%;
}
.comment-item {
display: flex;
width: 100%;
.comment-avatar {
padding: 10px;
}
.comment-content {
padding: 10px;
width: 100%;
.comment-header {
width: 100%;
display: flex;
justify-content: space-between;
.comment-name {
color: rgb(145, 145, 145);
}
}
.comment-text {
display: flex;
width: 100%;
justify-content: space-between;
.el-button {
width: 50px;
height: 20px;
}
}
}
}
</style>

View File

@ -35,11 +35,12 @@
<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>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<!-- <el-button icon="Refresh" @click="resetQuery">重置</el-button> -->
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</div>
@ -55,12 +56,12 @@
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column label="视频id" prop="vlogId" align="center" width="100" />
<el-table-column label="视频id" prop="fileId" align="center" width="100" />
<el-table-column label="名称" prop="nickname" align="center" width="100" />
<el-table-column label="手机号" prop="mobile" align="center" width="100" />
<el-table-column label="审核状态" prop="reason" align="center" width="100">
<template #default="{ row }">
{{ row.reason == 'Illegal' ? '不通过' : row.reason }}
{{ isfun(row.reason) }}
</template>
</el-table-column>
<el-table-column label="内容" prop="title" align="center" width="100" />
@ -86,7 +87,7 @@
</el-table-column>
</el-table>
<div class="block">
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.current" v-model:limit="queryParams.size" @pagination="getList" />
<pagination v-if="totalref > 0" :total="totalref" v-model:page="queryParams.current" v-model:limit="queryParams.size" @pagination="getList" />
</div>
</el-card>
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
@ -99,8 +100,8 @@
<template #footer>
<div class="dialog-footer">
<el-button v-if="object.reason != 'Illegal'" :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button v-if="object.reason != 'Illegal'" type="danger" @click="showRefuteDialog = true"> </el-button>
<el-button v-if="isfun1(object.reason)" :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button v-if="isfun1(object.reason)" type="danger" @click="showRefuteDialog = true"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
@ -143,7 +144,7 @@ const shouldShowVideo = ref(false);
const queryFormRef = ref<ElFormInstance>();
const categoryFormRef = ref<ElFormInstance>();
const categoryTableRef = ref<ElTableInstance>();
const total = ref<number>(0);
const totalref = ref<number>(0);
const isstates = ref<number>(1);
//
const showRefuteDialog = ref(false);
@ -157,7 +158,7 @@ const submitRefute = async () => {
console.log('提交的反驳原因:', refuteReason.value);
const data: Formaget = { vlogId: object.value.file_id, status: 2, reason: refuteReason.value };
const res = await updateaudit(data);
if (res.status === 200) {
if (res.code === 200) {
ElMessage({
message: '操作成功',
type: 'success'
@ -167,6 +168,56 @@ const submitRefute = async () => {
refuteReason.value = '';
}
};
const isfun = (status: string) => {
if (status == 'Terror') {
return '不通过';
}
if (status == 'Polity') {
return '不通过';
}
if (status == 'Illegal') {
return '不通过';
}
if (status == 'Abuse') {
return '不通过';
}
if (status == 'Moan') {
return '不通过';
}
if (status == 'Porn') {
return '不通过';
}
if (status == 'Ad') {
return '不通过';
} else {
return status;
}
};
const isfun1 = (status: string) => {
if (status == 'Terror') {
return false;
}
if (status == 'Polity') {
return false;
}
if (status == 'Illegal') {
return false;
}
if (status == 'Abuse') {
return false;
}
if (status == 'Moan') {
return false;
}
if (status == 'Porn') {
return false;
}
if (status == 'Ad') {
return false;
} else {
return true;
}
};
const dialog = reactive<DialogOption>({
visible: false,
title: ''
@ -199,14 +250,16 @@ const data = reactive<PageData<CategoryForm, CategoryQuery>>({
const { queryParams, form, rules } = toRefs(data);
/** 查询流程分类列表 */
/** 获取视频列表 */
const getList = async () => {
loading.value = true;
const res = await listCategory(queryParams.value);
// const {{}}
// const data = proxy?.handleTree<CategoryVO>(res.data, 'categoryId', 'parentId');
if (res.status == 200) {
categoryList.value = res.data.records;
total.value = res.data.total;
const { records, total } = (res.data || {}) as { records: any[]; total: number };
if (res.code == 200) {
categoryList.value = records;
totalref.value = total;
loading.value = false;
}
};
@ -245,13 +298,28 @@ const reset = () => {
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.current = 1; //
console.log(queryParams.value);
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
// debugger
// queryParams.value = {
// mobile: undefined,
// startTime: undefined,
// endTime: undefined,
// status: undefined,
// asc: undefined,
// column: undefined
// };
queryParams.value.mobile = undefined;
queryParams.value.startTime = undefined;
queryParams.value.endTime = undefined;
queryParams.value.status = undefined;
queryParams.value.asc = undefined;
queryParams.value.column = undefined;
dateRange.value = [];
// queryFormRef.value?.resetFields();
handleQuery();
};
//
@ -272,12 +340,12 @@ const handleAdd = async (row?: CategoryVO) => {
dialog.title = '视频查看';
});
});
const res = await gerdetail(row.fileId);
if (res.status == 200) {
comments.value = res.data.comments;
likedUsers.value = res.data.likedUsers;
fansList.value = res.data.fansList;
}
// const res = await gerdetail(row.fileId);
// if (res.code == 200) {
// comments.value = res.data.comments;
// likedUsers.value = res.data.likedUsers;
// fansList.value = res.data.fansList;
// }
};
//
const delshow = (id: string) => {
@ -287,7 +355,7 @@ const delshow = (id: string) => {
type: 'warning'
}).then(async () => {
const res = await deldetail(id);
if (res.status == 200) {
if (res.code == 200) {
cancel();
getList();
}
@ -333,7 +401,7 @@ const submitForm = () => {
.then(async () => {
const data: Formaget = { vlogId: object.value.fileId, status: 1, reason: refuteReason.value };
const res = await updateaudit(data);
if (res.status == 200) {
if (res.code == 200) {
ElMessage({
message: '操作成功',
type: 'success'
@ -361,7 +429,7 @@ const handleDelete = async (row: CategoryVO) => {
type: 'warning'
}).then(async () => {
const res = await updateaforbid(row.fileId);
if (res.status == 200) {
if (res.code == 200) {
ElMessage({
message: '删除成功',
type: 'success'

View File

@ -229,7 +229,7 @@ const handleDelete = async (row?: LomglistVO) => {
type: 'warning'
}).then(async () => {
const res = await deldetail(row.id);
if (res.status == 200) {
if (res.code == 200) {
getList();
dialog.visible = false;
ElMessage({
@ -252,7 +252,7 @@ const handledeloffline = async (row?: LomglistVO) => {
type: 'warning'
}).then(async () => {
const res = await deloffline(row.id);
if (res.status == 200) {
if (res.code == 200) {
getList();
ElMessage({
message: res.msg,