You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
450 lines
12 KiB
450 lines
12 KiB
<template>
|
|
<div class="notice-info-container">
|
|
<div class="search-panel">
|
|
<el-form :model="searchForm" inline>
|
|
<el-form-item label="公告内容:">
|
|
<el-input
|
|
v-model="searchForm.noticeContent"
|
|
placeholder="请输入关键字"
|
|
class="search-input"
|
|
clearable
|
|
@keyup.enter="handleSearch"
|
|
/>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="发布时间:">
|
|
<el-date-picker
|
|
v-model="searchForm.timeRange"
|
|
type="datetimerange"
|
|
range-separator="至"
|
|
start-placeholder="开始时间"
|
|
end-placeholder="结束时间"
|
|
class="date-picker publish-time-picker"
|
|
format="YYYY-MM-DD HH:mm:ss"
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
/>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="内容发布到:">
|
|
<el-select v-model="searchForm.targetPlatform" placeholder="请选择" class="search-select" clearable>
|
|
<el-option v-for="item in platformOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="状态:">
|
|
<el-select v-model="searchForm.status" placeholder="请选择" class="search-select" clearable>
|
|
<el-option label="在线" :value="2" />
|
|
<el-option label="下架" :value="3" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
<el-button type="primary" :icon="Search" @click="handleSearch" :loading="loading">搜索</el-button>
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
<el-button :icon="Refresh" @click="handleReset">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
|
|
<div class="action-bar">
|
|
<div class="action-left">
|
|
<el-button type="primary" :icon="Plus" @click="handleAdd">新增</el-button>
|
|
<el-button type="warning" @click="handleOpenDraft">草稿箱</el-button>
|
|
<el-button type="danger" :icon="Delete" @click="handleBatchDelete" :disabled="selectedRows.length === 0">
|
|
删除
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-container">
|
|
<el-table
|
|
v-loading="loading"
|
|
:data="tableData"
|
|
border
|
|
:header-cell-style="{ backgroundColor: '#f5f7fa', fontWeight: 'bold' }"
|
|
@selection-change="handleSelectionChange"
|
|
>
|
|
<el-table-column type="selection" width="55" />
|
|
<el-table-column prop="noticeContent" label="公告内容" min-width="250" show-overflow-tooltip />
|
|
<el-table-column prop="publishTime" label="发布时间" width="180" />
|
|
<el-table-column label="显示时长" width="100">
|
|
<template #default="scope">
|
|
{{ formatDisplayDays(scope.row.displayDays) }}
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="targetPlatformLabel" label="内容发布到" width="140" show-overflow-tooltip />
|
|
<el-table-column label="状态" width="100">
|
|
<template #default="scope">
|
|
<div class="status-badge">
|
|
<span :class="scope.row.status === 2 ? 'status-dot online' : 'status-dot offline'" />
|
|
{{ formatStatus(scope.row.status) }}
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" width="220" fixed="right">
|
|
<template #default="scope">
|
|
<el-button
|
|
size="small"
|
|
text type="primary"
|
|
:class="scope.row.status === 2 ? 'offline-btn' : 'online-btn'"
|
|
@click="handleStatusChange(scope.row)"
|
|
>
|
|
{{ scope.row.status === 2 ? '下架' : '上架' }}
|
|
</el-button>
|
|
<el-button size="small" text type="primary" @click="handleEdit(scope.row)">编辑</el-button>
|
|
<el-button size="small" text type="primary" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</div>
|
|
|
|
<div class="pagination-container">
|
|
<span class="total-text">共 {{ total }} 条数据</span>
|
|
<el-pagination
|
|
v-model:current-page="currentPage"
|
|
v-model:page-size="pageSize"
|
|
:total="total"
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
layout="prev, pager, next, jumper, ->, total, sizes"
|
|
@size-change="handleSizeChange"
|
|
@current-change="handleCurrentChange"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, onMounted, onActivated } from 'vue';
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
import { Plus, Delete, Search, Refresh } from '@element-plus/icons-vue';
|
|
import { useRouter } from 'vue-router';
|
|
import {
|
|
listNoticeInfo,
|
|
removeNoticeInfo,
|
|
editNoticeInfo,
|
|
type NoticeInfoVo
|
|
} from '@/api/supervision/noticeInfo';
|
|
|
|
const router = useRouter();
|
|
|
|
const loading = ref(false);
|
|
const tableData = ref<NoticeInfoVo[]>([]);
|
|
const total = ref(0);
|
|
const currentPage = ref(1);
|
|
const pageSize = ref(10);
|
|
const selectedRows = ref<NoticeInfoVo[]>([]);
|
|
|
|
const platformOptions = [
|
|
{ label: '企业端+执法端', value: 0 },
|
|
{ label: '企业端', value: 1 },
|
|
{ label: '执法端', value: 2 },
|
|
{ label: '监督端', value: 3 }
|
|
];
|
|
|
|
const searchForm = reactive({
|
|
noticeContent: '',
|
|
timeRange: [] as string[],
|
|
targetPlatform: undefined as number | undefined,
|
|
status: undefined as number | undefined
|
|
});
|
|
|
|
const formatDisplayDays = (value?: number) => {
|
|
if (value === undefined || value === null) return '-';
|
|
if (Number(value) === 0) return '永久';
|
|
return `${value}天`;
|
|
};
|
|
|
|
const formatStatus = (status?: number) => {
|
|
if (status === 2) return '在线';
|
|
if (status === 3) return '下架';
|
|
if (status === 1) return '待发布';
|
|
return '-';
|
|
};
|
|
|
|
const getList = async () => {
|
|
loading.value = true;
|
|
try {
|
|
const queryParams = {
|
|
noticeContent: searchForm.noticeContent || undefined,
|
|
targetPlatform: searchForm.targetPlatform,
|
|
status: searchForm.status,
|
|
startTime: searchForm.timeRange[0] || undefined,
|
|
endTime: searchForm.timeRange[1] || undefined,
|
|
pageNum: currentPage.value,
|
|
pageSize: pageSize.value
|
|
};
|
|
|
|
const res: any = await listNoticeInfo(queryParams);
|
|
if (res.code === 200) {
|
|
tableData.value = res.rows || [];
|
|
total.value = res.total || 0;
|
|
} else {
|
|
ElMessage.error(res.msg || '获取数据失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('获取列表数据失败:', error);
|
|
ElMessage.error('获取数据失败,请检查网络连接');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
const handleSearch = () => {
|
|
currentPage.value = 1;
|
|
getList();
|
|
};
|
|
|
|
const handleReset = () => {
|
|
searchForm.noticeContent = '';
|
|
searchForm.timeRange = [];
|
|
searchForm.targetPlatform = undefined;
|
|
searchForm.status = undefined;
|
|
currentPage.value = 1;
|
|
handleSearch();
|
|
ElMessage.info('已重置搜索条件');
|
|
};
|
|
|
|
const handleAdd = () => {
|
|
router.push('/supervision/noticeInfo/add');
|
|
};
|
|
|
|
const handleOpenDraft = () => {
|
|
router.push('/supervision/noticeInfo/draft');
|
|
};
|
|
|
|
const handleBatchDelete = () => {
|
|
if (selectedRows.value.length === 0) {
|
|
ElMessage.warning('请选择要删除的数据');
|
|
return;
|
|
}
|
|
ElMessageBox.confirm(`确定要删除选中的 ${selectedRows.value.length} 条数据吗?`, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消'
|
|
})
|
|
.then(async () => {
|
|
try {
|
|
const ids = selectedRows.value.map((row) => row.id);
|
|
const res: any = await removeNoticeInfo(ids);
|
|
if (res.code === 200) {
|
|
ElMessage.success('批量删除成功');
|
|
selectedRows.value = [];
|
|
getList();
|
|
} else {
|
|
ElMessage.error(res.msg || '批量删除失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('批量删除失败:', error);
|
|
ElMessage.error('批量删除失败,请重试');
|
|
}
|
|
})
|
|
.catch(() => {
|
|
ElMessage.info('已取消删除');
|
|
});
|
|
};
|
|
|
|
const handleSelectionChange = (selection: NoticeInfoVo[]) => {
|
|
selectedRows.value = selection;
|
|
};
|
|
|
|
const handleStatusChange = (row: NoticeInfoVo) => {
|
|
const newStatus = row.status === 2 ? 3 : 2;
|
|
const actionText = newStatus === 2 ? '上架' : '下架';
|
|
|
|
ElMessageBox.confirm(`确定要${actionText}公告吗?`, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消'
|
|
})
|
|
.then(async () => {
|
|
try {
|
|
const res: any = await editNoticeInfo({
|
|
id: row.id,
|
|
noticeContent: row.noticeContent,
|
|
targetPlatform: row.targetPlatform,
|
|
displayDays: row.displayDays,
|
|
publishTime: row.publishTime,
|
|
status: newStatus,
|
|
// isDelete: newStatus === 2 ? 0 : 1
|
|
});
|
|
if (res.code === 200) {
|
|
ElMessage.success(`${actionText}成功`);
|
|
getList();
|
|
} else {
|
|
ElMessage.error(res.msg || `${actionText}失败`);
|
|
}
|
|
} catch (error) {
|
|
console.error(`${actionText}失败:`, error);
|
|
ElMessage.error(`${actionText}失败,请重试`);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
ElMessage.info('已取消操作');
|
|
});
|
|
};
|
|
|
|
const handleEdit = (row: NoticeInfoVo) => {
|
|
router.push(`/supervision/noticeInfo/edit/${row.id}`);
|
|
};
|
|
|
|
const handleDelete = async (row: NoticeInfoVo) => {
|
|
try {
|
|
await ElMessageBox.confirm('确定要删除这条数据吗?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消'
|
|
});
|
|
|
|
const res: any = await removeNoticeInfo([row.id]);
|
|
if (res.code === 200) {
|
|
ElMessage.success('删除成功');
|
|
getList();
|
|
} else {
|
|
ElMessage.error(res.msg || '删除失败');
|
|
}
|
|
} catch (error: any) {
|
|
if (error !== 'cancel') {
|
|
console.error('删除失败:', error);
|
|
ElMessage.error('删除失败,请重试');
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleSizeChange = (val: number) => {
|
|
pageSize.value = val;
|
|
currentPage.value = 1;
|
|
getList();
|
|
};
|
|
|
|
const handleCurrentChange = (val: number) => {
|
|
currentPage.value = val;
|
|
getList();
|
|
};
|
|
|
|
onMounted(() => {
|
|
getList();
|
|
});
|
|
|
|
onActivated(() => {
|
|
getList();
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.notice-info-container {
|
|
padding: 20px;
|
|
background: #f5f7fa;
|
|
min-height: calc(100vh - 100px);
|
|
}
|
|
|
|
.search-panel {
|
|
background: #fff;
|
|
padding: 16px 20px;
|
|
border-radius: 8px;
|
|
margin-bottom: 16px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
:deep(.el-form-item__label) {
|
|
white-space: nowrap;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.search-input,
|
|
.date-picker,
|
|
.search-select {
|
|
width: 126px;
|
|
}
|
|
|
|
:deep(.publish-time-picker) {
|
|
width: 200px;
|
|
}
|
|
|
|
.action-bar {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
background: #fff;
|
|
padding: 12px 20px;
|
|
border-radius: 8px;
|
|
margin-bottom: 16px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.action-left {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.table-container {
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
padding: 16px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.status-badge {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.status-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.status-dot.online {
|
|
background: #67c23a;
|
|
}
|
|
|
|
.status-dot.offline {
|
|
background: #909399;
|
|
}
|
|
|
|
.pagination-container {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
background: #fff;
|
|
padding: 12px 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.total-text {
|
|
color: #909399;
|
|
}
|
|
|
|
:deep(.el-button--text) {
|
|
padding: 4px 8px;
|
|
}
|
|
|
|
:deep(.online-btn) {
|
|
color: #67c23a;
|
|
}
|
|
|
|
:deep(.online-btn:hover) {
|
|
color: #67c23a;
|
|
background: rgba(103, 194, 58, 0.1);
|
|
}
|
|
|
|
:deep(.offline-btn) {
|
|
color: #e6a23c;
|
|
}
|
|
|
|
:deep(.offline-btn:hover) {
|
|
color: #e6a23c;
|
|
background: rgba(230, 162, 60, 0.1);
|
|
}
|
|
|
|
:deep(.delete-btn) {
|
|
color: #f56c6c;
|
|
}
|
|
|
|
:deep(.delete-btn:hover) {
|
|
color: #f56c6c;
|
|
background: rgba(245, 108, 108, 0.1);
|
|
}
|
|
</style>
|
|
|