<template>
|
<div class="app-container">
|
|
<!-- 规章制度管理-->
|
<el-card class="box-card">
|
<template #header>
|
<div class="card-header">
|
<span>规章制度发布</span>
|
</div>
|
</template>
|
<div class="tab-content">
|
<el-row :gutter="20" class="mb-20">
|
<span class="ml-10">制度标题:</span>
|
<el-col :span="6">
|
<el-input v-model="regulationSearchForm.title" placeholder="请输入制度标题" clearable />
|
</el-col>
|
<span class="search_title">制度分类:</span>
|
<el-col :span="4">
|
<el-select v-model="regulationSearchForm.category" placeholder="制度分类" clearable>
|
<el-option label="人事制度" value="hr" />
|
<el-option label="财务制度" value="finance" />
|
<el-option label="安全制度" value="safety" />
|
<el-option label="技术制度" value="tech" />
|
</el-select>
|
</el-col>
|
<el-col :span="8">
|
<el-button type="primary" @click="searchRegulations">搜索</el-button>
|
<el-button @click="resetRegulationSearch">重置</el-button>
|
<el-button @click="handleExport">导出</el-button>
|
<el-button type="success" @click="handleAdd">
|
发布制度
|
</el-button>
|
</el-col>
|
</el-row>
|
|
<el-table :data="regulations" border v-loading="tableLoading" style="width: 100%">
|
<el-table-column prop="regulationNum" label="制度编号" width="120" />
|
<el-table-column prop="title" label="制度标题" min-width="150" />
|
<el-table-column prop="category" label="分类" width="120">
|
<template #default="scope">
|
<el-tag>{{ getCategoryText(scope.row.category) }}</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="version" label="版本" width="120" />
|
<el-table-column prop="createUserName" label="发布人" width="120" />
|
<el-table-column prop="createTime" label="发布时间" width="180" />
|
<el-table-column prop="status" label="状态" width="100">
|
<template #default="scope">
|
<el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
|
{{ scope.row.status === 'active' ? '生效中' : '已废止' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="readCount" label="已读人数" width="100" />
|
<el-table-column label="操作" width="320" fixed="right">
|
<template #default="scope">
|
<el-button link @click="viewRegulation(scope.row)">查看</el-button>
|
<el-button link type="primary" @click="handleEdit(scope.row)">编辑</el-button>
|
<el-button link type="danger" @click="repealEdit(scope.row)">废弃</el-button>
|
<el-button link type="success" @click="viewVersionHistory(scope.row)">版本历史</el-button>
|
<el-button link type="warning" @click="viewReadStatus(scope.row)">阅读状态</el-button>
|
<el-button link type="primary" @click="openFileDialog(scope.row)">附件</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</el-card>
|
|
<!-- 用印申请对话框(已移除) -->
|
|
<!-- 规章制度发布对话框 -->
|
<el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '发布制度' : '编辑制度'" width="800px">
|
<el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px">
|
<el-form-item label="制度编号" prop="regulationNum">
|
<el-input v-model="regulationForm.regulationNum" placeholder="请输入制度编号" />
|
</el-form-item>
|
<el-form-item label="制度标题" prop="title">
|
<el-input v-model="regulationForm.title" placeholder="请输入制度标题" />
|
</el-form-item>
|
<el-form-item label="制度分类" prop="category">
|
<el-select v-model="regulationForm.category" placeholder="请选择制度分类" style="width: 100%">
|
<el-option label="人事制度" value="hr" />
|
<el-option label="财务制度" value="finance" />
|
<el-option label="安全制度" value="safety" />
|
<el-option label="技术制度" value="tech" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="制度内容" prop="content">
|
<el-input v-model="regulationForm.content" type="textarea" :rows="10" placeholder="请输入制度详细内容" />
|
</el-form-item>
|
<el-form-item label="制度版本" prop="version">
|
<el-input v-model="regulationForm.version" placeholder="请输入制度版本" />
|
</el-form-item>
|
<el-form-item label="生效时间" prop="effectiveTime">
|
<el-date-picker v-model="regulationForm.effectiveTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
|
value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择生效时间" style="width: 100%" />
|
</el-form-item>
|
<el-form-item label="适用范围" prop="scope">
|
<el-checkbox-group v-model="regulationForm.scope">
|
<el-checkbox label="all">全体员工</el-checkbox>
|
<el-checkbox label="manager">管理层</el-checkbox>
|
<el-checkbox label="hr">人事部门</el-checkbox>
|
<el-checkbox label="finance">财务部门</el-checkbox>
|
<el-checkbox label="tech">技术部门</el-checkbox>
|
</el-checkbox-group>
|
</el-form-item>
|
<el-form-item label="是否需要确认" prop="requireConfirm">
|
<el-switch v-model="regulationForm.requireConfirm" />
|
<span class="ml-10">开启后员工需要阅读确认</span>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button @click="showRegulationDialog = false">取消</el-button>
|
<el-button type="primary" @click="submitRegulation">发布制度</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
|
<!-- 用印详情对话框(已移除) -->
|
|
<!-- 规章制度详情对话框 -->
|
<el-dialog v-model="showRegulationDetailDialog" title="规章制度详情" width="800px">
|
<div v-if="currentRegulationDetail">
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="制度编号">{{ currentRegulationDetail.id }}</el-descriptions-item>
|
<el-descriptions-item label="制度标题">{{ currentRegulationDetail.title }}</el-descriptions-item>
|
<el-descriptions-item label="分类">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item>
|
<el-descriptions-item label="版本">{{ currentRegulationDetail.version }}</el-descriptions-item>
|
<el-descriptions-item label="发布人">{{ currentRegulationDetail.createUserName }}</el-descriptions-item>
|
<el-descriptions-item label="发布时间">{{ currentRegulationDetail.createTime }}</el-descriptions-item>
|
</el-descriptions>
|
<div class="mt-20">
|
<h4>制度内容</h4>
|
<div class="regulation-content">{{ currentRegulationDetail.content }}</div>
|
</div>
|
<!-- 如果tableData>0 显示 -->
|
<div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" >
|
<el-button type="success" @click="resetForm(currentRegulationDetail)">确认查看</el-button>
|
</div>
|
</div>
|
</el-dialog>
|
|
<!-- 版本历史对话框 -->
|
<el-dialog v-model="showVersionHistoryDialog" title="版本历史" width="800px">
|
<el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px">
|
<el-table-column prop="version" label="版本号" width="100" />
|
<el-table-column prop="updateTime" label="更新时间" width="180" />
|
<el-table-column prop="createUserName" label="更新人" width="120" />
|
<el-table-column prop="changeLog" label="变更说明">
|
<template #default="scope">
|
<el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
|
{{ scope.row.status === 'active' ? '生效中' : '已废止' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-dialog>
|
|
<!-- 阅读状态对话框 -->
|
<el-dialog v-model="showReadStatusDialog" title="阅读状态" width="800px">
|
<el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px">
|
<el-table-column prop="employee" label="员工姓名" width="120" />
|
<el-table-column prop="department" label="所属部门" width="150" />
|
<el-table-column prop="createTime" label="阅读时间" width="180" />
|
<el-table-column prop="confirmTime" label="确认时间" width="180" />
|
<el-table-column prop="status" label="状态" width="100">
|
<template #default="scope">
|
<el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'">
|
{{ scope.row.status === 'confirmed' ? '已确认' : '未确认' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-dialog>
|
|
<FileListDialog
|
ref="fileListDialogRef"
|
v-model="fileDialogVisible"
|
:show-upload-button="true"
|
:show-delete-button="true"
|
:delete-method="handleAttachmentDelete"
|
:rules-regulations-management-id="currentFileRuleId"
|
:name-column-label="'附件名称'"
|
@upload="handleAttachmentUpload"
|
/>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,addReadingStatus,updateReadingStatus } from '@/api/collaborativeApproval/sealManagement.js'
|
import FileListDialog from '@/components/Dialog/FileListDialog.vue'
|
import { listRuleFiles, delRuleFile, addRuleFile } from '@/api/collaborativeApproval/rulesRegulationsManagementFile.js'
|
|
// 响应式数据
|
const operationType = ref('add')
|
const tableData = ref([])
|
const tableLoading = ref(false)
|
// 分页参数
|
const page = reactive({
|
current: 1,
|
size: 10,
|
total: 0
|
})
|
// 附件弹窗
|
const fileDialogVisible = ref(false)
|
const fileListDialogRef = ref(null)
|
const currentFileRuleId = ref(null)
|
const filePage = reactive({
|
current: 1,
|
size: 10,
|
total: 0
|
})
|
// 规章制度相关
|
const showRegulationDialog = ref(false)
|
const showRegulationDetailDialog = ref(false)
|
const showVersionHistoryDialog = ref(false)
|
const showReadStatusDialog = ref(false)
|
const currentRegulationDetail = ref(null)
|
const regulationFormRef = ref()
|
const regulationForm = reactive({
|
id: '',
|
regulationNum: '',
|
title: '',
|
category: '',
|
content: '',
|
version: '',
|
status: 'active',
|
readCount: 0,
|
effectiveTime: '',
|
scope: [],
|
requireConfirm: false
|
})
|
|
const readStatus = ref({
|
id: '',
|
ruleId: '',
|
employee: '',
|
department: '',
|
createTime: '',
|
confirmTime: '',
|
status: 'unconfirmed'
|
})
|
|
const regulationRules = {
|
title: [{ required: true, message: '请输入制度标题', trigger: 'blur' }],
|
category: [{ required: true, message: '请选择制度分类', trigger: 'change' }],
|
content: [{ required: true, message: '请输入制度内容', trigger: 'blur' }],
|
effectiveTime: [{ required: true, message: '请选择生效时间', trigger: 'change' }],
|
scope: [{ required: true, message: '请选择适用范围', trigger: 'change' }]
|
}
|
|
const regulationSearchForm = reactive({
|
title: '',
|
category: ''
|
})
|
|
const regulations = ref([])
|
|
const versionHistory = ref([])
|
|
const readStatusList = ref([])
|
// { employee: '陈志强', department: '销售部', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' },
|
// { employee: '刘雅婷', department: '技术部', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' },
|
// { employee: '王建国', department: '财务部', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' }
|
|
// 制度分类
|
const getCategoryText = (category) => {
|
const categoryMap = {
|
hr: '人事制度',
|
finance: '财务制度',
|
safety: '安全制度',
|
tech: '技术制度'
|
}
|
return categoryMap[category] || '未知'
|
}
|
// 搜索制度
|
const searchRegulations = () => {
|
page.current=1
|
getRegulationList()
|
}
|
// 重置制度搜索
|
const resetRegulationSearch = () => {
|
regulationSearchForm.title = ''
|
regulationSearchForm.category = ''
|
searchRegulations()
|
}
|
// 新增
|
const handleAdd = () => {
|
operationType.value = 'add'
|
resetRegulationForm()
|
showRegulationDialog.value = true
|
}
|
|
// 编辑
|
const handleEdit = (row) => {
|
operationType.value = 'edit'
|
Object.assign(regulationForm, row)
|
showRegulationDialog.value = true
|
}
|
// 废弃
|
const repealEdit = (row) => {
|
operationType.value = 'edit'
|
Object.assign(regulationForm, row)
|
regulationForm.status = 'repealed'
|
ElMessageBox.confirm('确认废弃该制度?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
updateRuleManagement(regulationForm).then(res => {
|
if(res.code == 200){
|
ElMessage.success('制度废弃成功')
|
// showRegulationDialog.value = false
|
getRegulationList()
|
resetRegulationForm()
|
}
|
})
|
}).catch(() => {
|
ElMessage({
|
type: 'info',
|
message: '已取消废弃'
|
})
|
})
|
}
|
// 发布制度
|
const submitRegulation = async () => {
|
try {
|
await regulationFormRef.value.validate()
|
if(operationType.value == 'add'){
|
addRuleManagement(regulationForm).then(res => {
|
if(res.code == 200){
|
ElMessage.success('制度发布成功')
|
showRegulationDialog.value = false
|
getRegulationList()
|
resetRegulationForm()
|
}
|
})
|
}else{
|
updateRuleManagement(regulationForm).then(res => {
|
if(res.code == 200){
|
ElMessage.success('制度编辑成功')
|
showRegulationDialog.value = false
|
resetRegulationForm()
|
getRegulationList()
|
}})}
|
}catch(err){
|
ElMessage.error(err.msg)
|
}
|
}
|
//重置制度表单
|
const resetRegulationForm = () => {
|
Object.assign(regulationForm, {
|
id: '',
|
regulationNum: '',
|
title: '',
|
category: '',
|
content: '',
|
version: '',
|
status: 'active',
|
readCount: 0,
|
effectiveTime: '',
|
scope: [],
|
requireConfirm: false
|
})
|
}
|
|
|
// 查看制度版本历史
|
const viewVersionHistory = (row) => {
|
showVersionHistoryDialog.value = true
|
const params = {
|
|
category: row.category
|
}
|
listRuleManagement(page,params).then(res => {
|
if(res.code == 200){
|
versionHistory.value = res.data.records
|
}
|
})
|
}
|
// 查看制度详情
|
const viewRegulation = (row) => {
|
currentRegulationDetail.value = row
|
showRegulationDetailDialog.value = true
|
getReadingStatusByRuleId(row.id).then(res => {
|
if(res.code == 200){
|
readStatusList.value = res.data
|
if(readStatusList.value.length==0 && tableData.value.length>0){
|
const params = {
|
ruleId: row.id,
|
employee: tableData.value[0].staffName,
|
department: tableData.value[0].postJob,
|
status: 'unconfirmed'
|
}
|
addReadingStatus(params).then(res => {
|
if(res.code == 200){
|
ElMessage.success('制度阅读成功')
|
}
|
})
|
}
|
}
|
})
|
|
}
|
// 查看制度阅读状态
|
const viewReadStatus = (row) => {
|
showReadStatusDialog.value = true
|
//查看阅读状态列表
|
getReadingStatusByRuleId(row.id).then(res => {
|
if(res.code == 200){
|
readStatusList.value = res.data
|
}
|
})
|
}
|
|
//确认查看
|
const resetForm = (row) => {
|
console.log("row",row)
|
row.readCount = row.readCount + 1
|
|
updateRuleManagement(row).then(res => {
|
if(res.code == 200){
|
ElMessage.success('查看数量修改成功')
|
//修改阅读状态
|
//根据制度id和当前登录的员工得到阅读状态
|
// let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName )
|
// if(item.length>0){
|
// item[0].status = 'confirmed',
|
// item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
|
// }
|
// 筛选当前员工对应该制度的阅读状态记录
|
let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id);
|
|
if (statusItem) {
|
// 如果找到记录,更新状态和确认时间
|
statusItem.status = 'confirmed';
|
// 格式化时间为"YYYY-MM-DD HH:mm:ss"格式
|
const now = new Date();
|
statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
|
// statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0];
|
|
updateReadingStatus(statusItem).then(res => {
|
if(res.code == 200){
|
ElMessage.success('制度阅读状态修改成功')
|
}
|
})
|
}
|
|
}
|
})
|
}
|
|
// 导出规章制度
|
const { proxy } = getCurrentInstance()
|
const handleExport = () => {
|
proxy.download('/rulesRegulationsManagement/export', { ...regulationSearchForm }, '规章制度.xlsx')
|
}
|
|
// 附件:查询
|
const fetchRuleFiles = async (rulesRegulationsManagementId) => {
|
const params = {
|
current: filePage.current,
|
size: filePage.size,
|
rulesRegulationsManagementId
|
}
|
const res = await listRuleFiles(params)
|
const records = res?.data?.records || []
|
filePage.total = res?.data?.total || records.length
|
const mapped = records.map(item => ({
|
id: item.id,
|
name: item.fileName || item.name,
|
url: item.fileUrl || item.url,
|
raw: item
|
}))
|
fileListDialogRef.value?.setList(mapped)
|
}
|
|
// 打开附件弹窗
|
const openFileDialog = async (row) => {
|
currentFileRuleId.value = row.id
|
fileDialogVisible.value = true
|
await fetchRuleFiles(row.id)
|
}
|
|
// 刷新附件列表
|
const refreshFileList = async () => {
|
if (!currentFileRuleId.value) return
|
await fetchRuleFiles(currentFileRuleId.value)
|
}
|
|
// 上传附件(由子组件触发)
|
const handleAttachmentUpload = async (filePayload) => {
|
if (!currentFileRuleId.value) return
|
const payload = {
|
name: filePayload?.fileName || filePayload?.name,
|
url: filePayload?.fileUrl || filePayload?.url,
|
rulesRegulationsManagementId: currentFileRuleId.value
|
}
|
await addRuleFile(payload)
|
ElMessage.success('文件上传成功')
|
await refreshFileList()
|
}
|
|
// 删除附件
|
const handleAttachmentDelete = async (row) => {
|
if (!row?.id) return false
|
try {
|
await ElMessageBox.confirm('确认删除该附件?', '提示', { type: 'warning' })
|
} catch {
|
return false
|
}
|
await delRuleFile([row.id])
|
ElMessage.success('删除成功')
|
await refreshFileList()
|
}
|
|
// 获取规章制度列表数据
|
const getRegulationList = async () => {
|
tableLoading.value = true
|
listRuleManagement(page,regulationSearchForm)
|
.then(res => {
|
|
regulations.value = res.data.records
|
// 过滤掉已废弃的制度
|
// regulations.value = res.data.records.filter(item => item.status !== 'repealed')
|
page.value.total = res.data.total;
|
tableLoading.value = false;
|
|
}).catch(err => {
|
tableLoading.value = false;
|
})
|
}
|
|
onMounted(() => {
|
// 初始化
|
getRegulationList()
|
})
|
</script>
|
|
<style scoped>
|
.app-container {
|
padding: 20px;
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.tab-content {
|
padding: 20px 0;
|
}
|
|
.mb-20 {
|
margin-bottom: 20px;
|
}
|
|
.mt-20 {
|
margin-top: 20px;
|
}
|
|
.ml-10 {
|
margin-left: 10px;
|
}
|
|
.regulation-content {
|
background-color: #f5f5f5;
|
padding: 15px;
|
border-radius: 4px;
|
line-height: 1.6;
|
white-space: pre-wrap;
|
height: 200px;
|
}
|
|
.dialog-footer {
|
display: flex;
|
justify-content: flex-end;
|
gap: 10px;
|
}
|
</style>
|