<template>
|
<div class="app-container">
|
<!-- 页面标题 -->
|
<div class="page-header">
|
<h2>会议审批</h2>
|
</div>
|
|
<!-- 搜索区域 -->
|
<el-card class="search-card">
|
<el-form :model="searchForm" inline>
|
<el-form-item label="会议主题">
|
<el-input v-model="searchForm.title" placeholder="请输入会议主题" clearable/>
|
</el-form-item>
|
<el-form-item label="申请人">
|
<el-input v-model="searchForm.applicant" placeholder="请输入申请人" clearable/>
|
</el-form-item>
|
<el-form-item label="审批状态">
|
<el-select style="width: 100px" v-model="searchForm.status" placeholder="请选择审批状态" clearable>
|
<el-option label="待审批" value="0"/>
|
<el-option label="已通过" value="1"/>
|
<el-option label="未审批" value="2"/>
|
<el-option label="已取消" value="3"/>
|
</el-select>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
<el-button @click="resetSearch">重置</el-button>
|
</el-form-item>
|
</el-form>
|
</el-card>
|
|
<!-- 会议审批列表 -->
|
<el-card>
|
<el-table v-loading="loading" :data="approvalList" border>
|
<el-table-column prop="title" label="会议主题" align="center" min-width="200" show-overflow-tooltip/>
|
<el-table-column prop="applicant" label="申请人" align="center" width="120"/>
|
<el-table-column prop="host" label="主理人" align="center" width="120"/>
|
<el-table-column prop="meetingTime" label="会议时间" align="center" width="180">
|
<template #default="scope">
|
{{ formatDateTime(scope.row.meetingTime) }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="location" label="会议地点" align="center" width="150"/>
|
<el-table-column prop="participants" label="参会人数" align="center" width="100">
|
<template #default="scope">
|
{{ scope.row.participants.length }}人
|
</template>
|
</el-table-column>
|
<el-table-column prop="status" label="审批状态" align="center" width="120">
|
<template #default="scope">
|
<el-tag :type="getStatusType(scope.row.status)">
|
{{ getStatusText(scope.row.status) }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" align="center" width="200" fixed="right">
|
<template #default="scope">
|
<el-button type="primary" link @click="viewDetail(scope.row)">查看</el-button>
|
<el-button
|
v-if="scope.row.status == '0'"
|
type="primary"
|
link
|
@click="handleApproval(scope.row)"
|
>
|
审批
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<!-- 分页 -->
|
<pagination
|
v-show="total > 0"
|
:total="total"
|
v-model:page="queryParams.current"
|
v-model:limit="queryParams.size"
|
@pagination="getList"
|
/>
|
</el-card>
|
|
<!-- 会议详情对话框 -->
|
<el-dialog
|
title="会议详情"
|
v-model="detailDialogVisible"
|
width="800px"
|
>
|
<div v-if="currentMeeting">
|
<el-descriptions label-width="100px" class="meeting-desc" :column="2" border>
|
<el-descriptions-item label="会议主题" label-class-name="nowrap-label">{{
|
currentMeeting.title
|
}}</el-descriptions-item>
|
<el-descriptions-item label="申请人" label-class-name="nowrap-label">{{
|
currentMeeting.applicant
|
}}</el-descriptions-item>
|
<el-descriptions-item label="主理人" label-class-name="nowrap-label">{{
|
currentMeeting.host
|
}}</el-descriptions-item>
|
<el-descriptions-item label="会议时间" :span="2" label-class-name="nowrap-label">
|
{{ formatDateTime(currentMeeting.meetingTime) }}
|
</el-descriptions-item>
|
<el-descriptions-item label="会议地点" label-class-name="nowrap-label">{{
|
currentMeeting.location
|
}}</el-descriptions-item>
|
<el-descriptions-item label="参会人数" label-class-name="nowrap-label">{{
|
currentMeeting.participants.length
|
}}人</el-descriptions-item>
|
<el-descriptions-item label="审批状态" label-class-name="nowrap-label">
|
<el-tag :type="getStatusType(currentMeeting.status)">
|
{{ getStatusText(currentMeeting.status) }}
|
</el-tag>
|
</el-descriptions-item>
|
<el-descriptions-item label="申请时间" label-class-name="nowrap-label">{{
|
currentMeeting.createTime
|
}}</el-descriptions-item>
|
<el-descriptions-item style="max-height: 400px" label="会议说明" :span="2"
|
label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item>
|
</el-descriptions>
|
|
|
<div class="content-section mt-20">
|
<h4>参会人员</h4>
|
<div class="participants-list">
|
<el-tag
|
v-for="participant in currentMeeting.participants"
|
:key="participant.id"
|
style="margin-right: 10px; margin-bottom: 10px;"
|
>
|
{{ participant.name }}
|
</el-tag>
|
</div>
|
</div>
|
</div>
|
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
|
<!-- 会议审批对话框 -->
|
<el-dialog
|
title="会议审批"
|
v-model="approvalDialogVisible"
|
>
|
<div v-if="currentMeeting">
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="会议主题">{{ currentMeeting.title }}</el-descriptions-item>
|
<el-descriptions-item label="申请人">{{ currentMeeting.applicant }}</el-descriptions-item>
|
<el-descriptions-item label="主理人">{{ currentMeeting.host }}</el-descriptions-item>
|
<el-descriptions-item label="会议时间" :span="2">
|
{{ formatDateTime(currentMeeting.meetingTime) }}
|
</el-descriptions-item>
|
<el-descriptions-item label="会议地点">{{ currentMeeting.location }}</el-descriptions-item>
|
<el-descriptions-item label="参会人数">{{ currentMeeting.participants.length }}人</el-descriptions-item>
|
</el-descriptions>
|
|
<div class="content-section mt-20">
|
<h4>参会人员</h4>
|
<div class="participants-list">
|
<el-tag
|
v-for="participant in currentMeeting.participants"
|
:key="participant.id"
|
style="margin-right: 10px; margin-bottom: 10px;"
|
>
|
{{ participant.name }}
|
</el-tag>
|
</div>
|
</div>
|
|
<div v-show="false" class="approval-opinion mt-20">
|
<h4>审批意见</h4>
|
<el-input
|
v-model="approvalOpinion"
|
type="textarea"
|
placeholder="请输入审批意见"
|
:rows="4"
|
/>
|
</div>
|
</div>
|
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button @click="approvalDialogVisible = false">取 消</el-button>
|
<el-button type="danger" @click="submitApproval('2')">不通过</el-button>
|
<el-button type="primary" @click="submitApproval('1')">通 过</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import {ref, reactive, onMounted} from 'vue'
|
import {ElMessage, ElMessageBox} from 'element-plus'
|
import Pagination from '@/components/Pagination/index.vue'
|
import {getRoomEnum, getExamineList,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js'
|
import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
|
import dayjs from "dayjs";
|
|
// 数据列表加载状态
|
const loading = ref(false)
|
|
// 总条数
|
const total = ref(0)
|
const roomEnum = ref([])
|
const staffList = ref([])
|
// 审批列表数据
|
const approvalList = ref([])
|
|
// 查询参数
|
const queryParams = reactive({
|
current: 1,
|
size: 10
|
})
|
|
// 搜索表单
|
const searchForm = reactive({
|
title: '',
|
applicant: '',
|
status: ''
|
})
|
|
// 是否显示对话框
|
const detailDialogVisible = ref(false)
|
const approvalDialogVisible = ref(false)
|
|
// 当前查看的会议
|
const currentMeeting = ref(null)
|
|
// 审批意见
|
const approvalOpinion = ref('')
|
|
// 查询数据
|
const getList = async () => {
|
loading.value = true
|
let resp = await getExamineList({...searchForm, ...queryParams})
|
approvalList.value = resp.data.records.map(it => {
|
let room = roomEnum.value.find(room => it.roomId === room.id)
|
it.location = `${room.name}(${room.location})`
|
let staffs = JSON.parse(it.participants)
|
it.staffCount = staffs.size
|
it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}`
|
it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => {
|
return {
|
id: staff.id,
|
name: `${staff.staffName}(${staff.postJob})`
|
}
|
})
|
|
|
return it
|
})
|
total.value = resp.data.total
|
loading.value = false
|
}
|
|
// 搜索按钮操作
|
const handleSearch = () => {
|
queryParams.pageNum = 1
|
getList()
|
}
|
|
// 重置搜索表单
|
const resetSearch = () => {
|
Object.assign(searchForm, {
|
title: '',
|
applicant: '',
|
status: ''
|
})
|
handleSearch()
|
}
|
|
// 查看详情
|
const viewDetail = (row) => {
|
currentMeeting.value = row
|
detailDialogVisible.value = true
|
}
|
|
// 处理审批
|
const handleApproval = (row) => {
|
currentMeeting.value = row
|
approvalOpinion.value = ''
|
approvalDialogVisible.value = true
|
}
|
|
// 获取状态类型
|
const getStatusType = (status) => {
|
const statusMap = {
|
'0': 'info', // 待审批
|
'1': 'success', // 已通过
|
'2': 'warning', // 未通过
|
'3': 'danger' // 取消
|
}
|
return statusMap[status] || 'info'
|
}
|
|
// 获取状态文本
|
const getStatusText = (status) => {
|
const statusMap = {
|
'0': '待审批',
|
'1': '已通过',
|
'2': '未通过',
|
'3': '已取消'
|
}
|
return statusMap[status] || '未知'
|
}
|
|
// 格式化日期时间
|
const formatDateTime = (dateTime) => {
|
if (!dateTime) return ''
|
return dateTime.replace(' ', '\n')
|
}
|
|
// 提交审批
|
const submitApproval = (status) => {
|
// if (status === 'approved' && !approvalOpinion.value.trim()) {
|
// ElMessage.warning('请填写审批意见')
|
// return
|
// }
|
|
ElMessageBox.confirm(
|
`确认${status === '1' ? '通过' : '不通过'}该会议申请?`,
|
'审批确认',
|
{
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}
|
).then(() => {
|
saveMeetingApplication({
|
id: currentMeeting.value.id,
|
status: status
|
}).then(resp=>{
|
// 更新会议状态
|
currentMeeting.value.status = status
|
|
ElMessage.success('审批提交成功')
|
approvalDialogVisible.value = false
|
getList()
|
})
|
|
}).catch(() => {
|
})
|
}
|
|
// 页面加载时获取数据
|
onMounted(async () => {
|
const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()])
|
roomEnum.value = resp1.data
|
staffList.value = resp2.data
|
|
await getList()
|
})
|
</script>
|
|
<style scoped>
|
.app-container {
|
padding: 20px;
|
}
|
|
.page-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 20px;
|
}
|
|
.page-header h2 {
|
margin: 0;
|
color: #303133;
|
}
|
|
.search-card {
|
margin-bottom: 20px;
|
}
|
|
.dialog-footer {
|
display: flex;
|
justify-content: flex-end;
|
gap: 10px;
|
}
|
|
.content-section h4 {
|
margin: 0 0 15px 0;
|
color: #303133;
|
}
|
|
.mt-20 {
|
margin-top: 20px;
|
}
|
|
.participants-list {
|
min-height: 40px;
|
padding: 15px;
|
border-radius: 4px;
|
line-height: 1.6;
|
}
|
|
.approval-opinion h4 {
|
margin: 0 0 15px 0;
|
color: #303133;
|
}
|
|
.nowrap-label {
|
white-space: nowrap !important;
|
}
|
|
.description-content {
|
white-space: pre-wrap;
|
word-wrap: break-word;
|
line-height: 1.6;
|
padding: 10px;
|
background-color: #f5f7fa;
|
border-radius: 4px;
|
min-height: 60px;
|
}
|
</style>
|