<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>
|
<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="meetingList"
|
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 label="操作"
|
align="center"
|
width="200"
|
fixed="right">
|
<template #default="scope">
|
<el-button type="primary"
|
link
|
@click="viewDetail(scope.row)">查看</el-button>
|
<el-button type="primary"
|
link
|
@click="addMinutes(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="minutesDialogVisible"
|
width="80%"
|
@close="handleCloseMinutesDialog">
|
<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="editor-container">
|
<Editor v-model="minutesContent"
|
:min-height="400" />
|
</div>
|
</div>
|
</div>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary"
|
@click="submitMinutes">保 存</el-button>
|
<el-button @click="minutesDialogVisible = false">取 消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted } from "vue";
|
import { ElMessage } from "element-plus";
|
import Pagination from "@/components/Pagination/index.vue";
|
import Editor from "@/components/Editor/index.vue";
|
import {
|
getRoomEnum,
|
getMeetingPublish,
|
getMeetingMinutesByMeetingId,
|
saveMeetingMinutes,
|
} 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 meetingList = ref([]);
|
|
// 查询参数
|
const queryParams = reactive({
|
current: 1,
|
size: 10,
|
});
|
|
// 搜索表单
|
const searchForm = reactive({
|
title: "",
|
applicant: "",
|
// status: '1' // 默认只显示已通过审批的会议
|
});
|
|
// 是否显示对话框
|
const detailDialogVisible = ref(false);
|
const minutesDialogVisible = ref(false);
|
|
// 当前查看的会议
|
const currentMeeting = ref(null);
|
|
// 会议纪要内容
|
const minutesContent = ref("");
|
const minutesContentId = ref("");
|
|
// 查询数据
|
const getList = async () => {
|
loading.value = true;
|
let resp = await getMeetingPublish({ ...searchForm, ...queryParams });
|
meetingList.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.current = 1;
|
getList();
|
};
|
|
// 重置搜索表单
|
const resetSearch = () => {
|
Object.assign(searchForm, {
|
title: "",
|
applicant: "",
|
// status: '1'
|
});
|
handleSearch();
|
};
|
|
// 查看详情
|
const viewDetail = row => {
|
currentMeeting.value = row;
|
detailDialogVisible.value = true;
|
};
|
|
// 添加会议纪要
|
const addMinutes = async row => {
|
let resp = await getMeetingMinutesByMeetingId(row.id);
|
currentMeeting.value = row;
|
if (resp.data) {
|
minutesContent.value = resp.data.content;
|
minutesContentId.value = resp.data.id;
|
} else {
|
minutesContent.value = `<h2>${row.title}会议纪要</h2>
|
<p><strong>会议时间:</strong>${row.meetingTime}</p>
|
<p><strong>会议地点:</strong>${row.location}</p>
|
<p><strong>主持人:</strong>${row.host}</p>
|
<p><strong>参会人员:</strong></p>
|
<ol>
|
${row.participants.map(p => `<li>${p.name}</li>`).join("")}
|
</ol>
|
<p><strong>会议内容:</strong></p>
|
<ol>
|
<li>议题一:
|
<ul>
|
<li>讨论内容:</li>
|
<li>决议事项:</li>
|
</ul>
|
</li>
|
<li>议题二:
|
<ul>
|
<li>讨论内容:</li>
|
<li>决议事项:</li>
|
</ul>
|
</li>
|
</ol>
|
<p><strong>备注:</strong></p>`;
|
}
|
|
minutesDialogVisible.value = true;
|
};
|
|
// 提交会议纪要
|
const submitMinutes = () => {
|
if (!minutesContent.value) {
|
ElMessage.warning("请输入会议纪要内容");
|
return;
|
}
|
saveMeetingMinutes({
|
id: minutesContentId.value,
|
content: minutesContent.value,
|
meetingId: currentMeeting.value.id,
|
title: currentMeeting.value.title,
|
}).then(resp => {
|
console.log("会议纪要内容:", minutesContent.value);
|
ElMessage.success("会议纪要保存成功");
|
minutesDialogVisible.value = false;
|
});
|
};
|
|
// 关闭会议纪要对话框
|
const handleCloseMinutesDialog = () => {
|
minutesContent.value = "";
|
};
|
|
// 获取状态类型
|
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");
|
};
|
|
// 页面加载时获取数据
|
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;
|
}
|
|
.nowrap-label {
|
white-space: nowrap !important;
|
}
|
|
.editor-container {
|
border: 1px solid #dcdfe6;
|
border-radius: 4px;
|
}
|
</style>
|