467 lines
12 KiB
Vue
467 lines
12 KiB
Vue
<template>
|
|
<div class="system-regulation">
|
|
<a-card title="已公告制度确认" :bordered="false">
|
|
<!-- 搜索区域 -->
|
|
<div class="search-container">
|
|
<a-form layout="inline" :model="searchForm" class="search-form">
|
|
<a-form-item label="制度标题">
|
|
<a-input
|
|
v-model="searchForm.title"
|
|
placeholder="请输入制度标题"
|
|
allow-clear
|
|
style="width: 200px"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item label="公示人">
|
|
<a-input
|
|
v-model="searchForm.proposer"
|
|
placeholder="请输入公示人"
|
|
allow-clear
|
|
style="width: 150px"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item label="确认状态">
|
|
<a-select
|
|
v-model="searchForm.confirmStatus"
|
|
placeholder="请选择状态"
|
|
allow-clear
|
|
style="width: 150px"
|
|
>
|
|
<a-option value="">全部</a-option>
|
|
<a-option value="CONFIRMED">已确认</a-option>
|
|
<a-option value="PENDING">待确认</a-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<a-space>
|
|
<a-button type="primary" @click="search">
|
|
<template #icon><icon-search /></template>
|
|
搜索
|
|
</a-button>
|
|
<a-button @click="reset">
|
|
<template #icon><icon-refresh /></template>
|
|
重置
|
|
</a-button>
|
|
</a-space>
|
|
</a-form-item>
|
|
</a-form>
|
|
</div>
|
|
|
|
<a-table
|
|
:columns="columns"
|
|
:data="tableData"
|
|
:loading="loading"
|
|
:pagination="pagination"
|
|
@page-change="onPageChange"
|
|
@page-size-change="onPageSizeChange"
|
|
>
|
|
<template #toolbar-left>
|
|
<span class="search-result-info">
|
|
共找到 <strong>{{ pagination.total }}</strong> 条记录
|
|
</span>
|
|
</template>
|
|
<template #confirmStatus="{ record }">
|
|
<a-tag :color="record.confirmStatus === 'CONFIRMED' ? 'green' : 'orange'">
|
|
{{ record.confirmStatus === 'CONFIRMED' ? '已确认' : '待确认' }}
|
|
</a-tag>
|
|
</template>
|
|
|
|
<template #operations="{ record }">
|
|
<a-space>
|
|
<a-button type="text" size="small" @click="handleView(record)">
|
|
查看详情
|
|
</a-button>
|
|
<a-button type="text" size="small" @click="handleDownload(record)">
|
|
下载
|
|
</a-button>
|
|
</a-space>
|
|
</template>
|
|
</a-table>
|
|
</a-card>
|
|
|
|
<!-- 制度详情弹窗 -->
|
|
<a-modal
|
|
v-model:visible="detailModalVisible"
|
|
title="制度详情"
|
|
width="800px"
|
|
:footer="false"
|
|
>
|
|
<div class="regulation-detail" v-if="currentRegulation">
|
|
<div class="detail-header">
|
|
<h3>{{ currentRegulation.title }}</h3>
|
|
<div class="detail-meta">
|
|
<span>公示人: {{ currentRegulation.createByName }}</span>
|
|
<span>公示时间: {{ currentRegulation.publishTime }}</span>
|
|
<span>生效日期: {{ currentRegulation.effectiveTime }}</span>
|
|
<span>确认状态:
|
|
<a-tag :color="currentRegulation.confirmStatus === 'CONFIRMED' ? 'green' : 'orange'">
|
|
{{ currentRegulation.confirmStatus === 'CONFIRMED' ? '已确认' : '待确认' }}
|
|
</a-tag>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<a-divider />
|
|
|
|
<div class="detail-content">
|
|
<h4>制度内容</h4>
|
|
<div class="content-text">{{ currentRegulation.content }}</div>
|
|
|
|
<h4>适用范围</h4>
|
|
<div class="content-text">{{ currentRegulation.scope }}</div>
|
|
|
|
<h4>实施要求</h4>
|
|
<div class="content-text">{{ currentRegulation.requirements }}</div>
|
|
|
|
<h4>注意事项</h4>
|
|
<div class="content-text">{{ currentRegulation.notes }}</div>
|
|
</div>
|
|
|
|
<a-divider />
|
|
|
|
<div class="detail-footer">
|
|
<a-button
|
|
v-if="currentRegulation.confirmStatus !== 'CONFIRMED'"
|
|
type="primary"
|
|
@click="handleConfirm(currentRegulation)"
|
|
>
|
|
确认知晓并遵守
|
|
</a-button>
|
|
<a-button
|
|
v-else
|
|
type="primary"
|
|
disabled
|
|
>
|
|
已确认知晓
|
|
</a-button>
|
|
<a-button @click="handleDownload(currentRegulation)">
|
|
下载制度文件
|
|
</a-button>
|
|
</div>
|
|
</div>
|
|
</a-modal>
|
|
|
|
<!-- 确认承诺弹窗 -->
|
|
<a-modal
|
|
v-model:visible="confirmModalVisible"
|
|
title="制度确认承诺"
|
|
width="600px"
|
|
@ok="submitConfirm"
|
|
@cancel="confirmModalVisible = false"
|
|
>
|
|
<div class="confirm-content">
|
|
<p>我确认已仔细阅读并理解《{{ currentRegulation?.title }}》的全部内容,承诺:</p>
|
|
<ul>
|
|
<li>严格遵守该制度的各项规定</li>
|
|
<li>认真履行相关职责和义务</li>
|
|
<li>如有违反,愿意承担相应责任</li>
|
|
</ul>
|
|
|
|
<a-checkbox v-model="agreeTerms">
|
|
我已阅读并同意上述承诺
|
|
</a-checkbox>
|
|
</div>
|
|
</a-modal>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
import type { Regulation } from '@/apis/regulation/type'
|
|
import { Message } from '@arco-design/web-vue'
|
|
import { IconSearch, IconRefresh } from '@arco-design/web-vue/es/icon'
|
|
import { useRegulationStore } from '@/stores/modules/regulation'
|
|
import { regulationApi } from '@/apis/regulation'
|
|
import { PDFGenerator } from '@/utils/pdfGenerator'
|
|
|
|
defineOptions({ name: 'SystemRegulation' })
|
|
|
|
// 表格列定义
|
|
const columns = [
|
|
{ title: '制度名称', dataIndex: 'title', key: 'title' },
|
|
{ title: '制度类型', dataIndex: 'regulationType', key: 'regulationType' },
|
|
{ title: '公示人', dataIndex: 'createByName', key: 'createByName' },
|
|
{ title: '公示时间', dataIndex: 'publishTime', key: 'publishTime' },
|
|
{ title: '生效日期', dataIndex: 'effectiveTime', key: 'effectiveTime' },
|
|
{ title: '确认状态', dataIndex: 'confirmStatus', key: 'confirmStatus', slotName: 'confirmStatus' },
|
|
{ title: '操作', key: 'operations', slotName: 'operations', width: 250 }
|
|
]
|
|
|
|
// 表格数据
|
|
const tableData = ref<Regulation[]>([])
|
|
const loading = ref(false)
|
|
const pagination = reactive({
|
|
current: 1,
|
|
pageSize: 10,
|
|
total: 0,
|
|
showTotal: true,
|
|
showJumper: true,
|
|
showPageSize: true
|
|
})
|
|
|
|
// 搜索表单
|
|
const searchForm = reactive({
|
|
title: '',
|
|
proposer: '',
|
|
confirmStatus: ''
|
|
})
|
|
|
|
// 弹窗相关
|
|
const detailModalVisible = ref(false)
|
|
const confirmModalVisible = ref(false)
|
|
const currentRegulation = ref<Regulation | null>(null)
|
|
const agreeTerms = ref(false)
|
|
|
|
// 制度管理store
|
|
const regulationStore = useRegulationStore()
|
|
|
|
// 获取表格数据 - 使用后端搜索接口
|
|
const getTableData = async () => {
|
|
loading.value = true
|
|
try {
|
|
const response = await regulationApi.getRegulationList({
|
|
page: pagination.current,
|
|
size: pagination.pageSize,
|
|
status: "PUBLISHED",
|
|
title: searchForm.title || undefined,
|
|
proposer: searchForm.proposer || undefined,
|
|
confirmStatus: searchForm.confirmStatus || undefined
|
|
})
|
|
|
|
if (response.status === 200) {
|
|
|
|
|
|
// 确保每个记录都有 confirmStatus 字段
|
|
const records = response.data.records.map((record: any) => ({
|
|
...record,
|
|
confirmStatus: record.confirmStatus || 'PENDING'
|
|
}))
|
|
|
|
tableData.value = records
|
|
pagination.pageSize = response.data.size
|
|
pagination.current = response.data.current
|
|
pagination.total = response.data.total
|
|
|
|
|
|
} else {
|
|
Message.error('搜索失败')
|
|
}
|
|
} catch (error) {
|
|
console.error('搜索已公告制度失败:', error)
|
|
Message.error('搜索失败')
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 搜索
|
|
const search = () => {
|
|
pagination.current = 1
|
|
getTableData()
|
|
}
|
|
|
|
// 重置
|
|
const reset = () => {
|
|
Object.assign(searchForm, {
|
|
title: '',
|
|
proposer: '',
|
|
confirmStatus: ''
|
|
})
|
|
pagination.current = 1
|
|
getTableData()
|
|
}
|
|
|
|
// 分页事件
|
|
const onPageChange = (page: number) => {
|
|
pagination.current = page
|
|
getTableData()
|
|
}
|
|
|
|
const onPageSizeChange = (pageSize: number) => {
|
|
pagination.pageSize = pageSize
|
|
pagination.current = 1
|
|
getTableData()
|
|
}
|
|
|
|
// 查看详情
|
|
const handleView = (record: any) => {
|
|
currentRegulation.value = record
|
|
detailModalVisible.value = true
|
|
}
|
|
|
|
// 确认知晓
|
|
const handleConfirm = (record: any) => {
|
|
currentRegulation.value = record
|
|
confirmModalVisible.value = true
|
|
agreeTerms.value = false
|
|
}
|
|
|
|
// 下载
|
|
const handleDownload = async (record: any) => {
|
|
try {
|
|
const loadingMessage = Message.loading('正在生成PDF文件...', 0)
|
|
|
|
// 生成PDF
|
|
const pdfBlob = await PDFGenerator.generateRegulationPDF(record)
|
|
|
|
// 关闭加载提示
|
|
loadingMessage.close()
|
|
|
|
// 生成文件名
|
|
const filename = `${record.title}_${new Date().toISOString().split('T')[0]}.pdf`
|
|
|
|
// 下载PDF
|
|
PDFGenerator.downloadPDF(pdfBlob, filename)
|
|
|
|
Message.success('PDF文件下载成功')
|
|
} catch (error) {
|
|
Message.error('PDF生成失败')
|
|
console.error('PDF生成错误:', error)
|
|
}
|
|
}
|
|
|
|
// 提交确认
|
|
const submitConfirm = async () => {
|
|
if (!agreeTerms.value) {
|
|
Message.warning('请先同意承诺条款')
|
|
return
|
|
}
|
|
|
|
try {
|
|
if (currentRegulation.value) {
|
|
await regulationApi.confirmRegulation(currentRegulation.value.regulationId)
|
|
|
|
Message.success('确认成功,您已承诺遵守该制度')
|
|
confirmModalVisible.value = false
|
|
|
|
// 立即刷新数据,确保状态同步
|
|
await getTableData()
|
|
|
|
// 如果详情弹窗是打开的,也更新详情弹窗中的数据
|
|
if (detailModalVisible.value && currentRegulation.value) {
|
|
const updatedRecord = tableData.value.find(item => item.regulationId === currentRegulation.value.regulationId)
|
|
if (updatedRecord) {
|
|
currentRegulation.value = updatedRecord
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('确认失败:', error)
|
|
Message.error('确认失败')
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
getTableData()
|
|
})
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.system-regulation {
|
|
.arco-card {
|
|
margin-bottom: 16px;
|
|
}
|
|
}
|
|
|
|
.search-container {
|
|
padding: 16px;
|
|
background: var(--color-bg-2);
|
|
border-radius: 6px;
|
|
margin-bottom: 16px;
|
|
|
|
.search-form {
|
|
.arco-form-item {
|
|
margin-bottom: 0;
|
|
margin-right: 16px;
|
|
|
|
.arco-form-item-label {
|
|
font-weight: 500;
|
|
color: var(--color-text-1);
|
|
margin-right: 8px;
|
|
}
|
|
}
|
|
|
|
.arco-input,
|
|
.arco-select {
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.arco-btn {
|
|
border-radius: 4px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.search-result-info {
|
|
color: var(--color-text-2);
|
|
font-size: 14px;
|
|
|
|
strong {
|
|
color: var(--color-text-1);
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
|
|
.regulation-detail {
|
|
.detail-header {
|
|
margin-bottom: 16px;
|
|
|
|
h3 {
|
|
margin-bottom: 12px;
|
|
color: var(--color-text-1);
|
|
}
|
|
|
|
.detail-meta {
|
|
display: flex;
|
|
gap: 16px;
|
|
color: var(--color-text-3);
|
|
font-size: 14px;
|
|
}
|
|
}
|
|
|
|
.detail-content {
|
|
h4 {
|
|
margin: 16px 0 8px 0;
|
|
color: var(--color-text-1);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.content-text {
|
|
color: var(--color-text-2);
|
|
line-height: 1.6;
|
|
margin-bottom: 16px;
|
|
padding: 12px;
|
|
background: var(--color-fill-1);
|
|
border-radius: 6px;
|
|
}
|
|
}
|
|
|
|
.detail-footer {
|
|
display: flex;
|
|
gap: 12px;
|
|
justify-content: center;
|
|
}
|
|
}
|
|
|
|
.confirm-content {
|
|
p {
|
|
margin-bottom: 16px;
|
|
color: var(--color-text-1);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
ul {
|
|
margin-bottom: 20px;
|
|
padding-left: 20px;
|
|
|
|
li {
|
|
margin-bottom: 8px;
|
|
color: var(--color-text-2);
|
|
line-height: 1.5;
|
|
}
|
|
}
|
|
}
|
|
</style> |