src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
@@ -1,18 +1,17 @@ <template> <div> <!-- 申请类型选择 --> <el-card class="type-card"> <div class="type-selector"> <div v-for="type in applicationTypes" :key="type.value" class="type-item" :class="{ active: currentType === type.value }" @click="changeType(type.value)" > <div v-for="type in applicationTypes" :key="type.value" class="type-item" :class="{ active: currentType === type.value }" @click="changeType(type.value)"> <div class="type-icon"> <el-icon :size="24"><component :is="type.icon"/></el-icon> <el-icon :size="24"> <component :is="type.icon" /> </el-icon> </div> <div class="type-info"> <div class="type-name">{{ type.name }}</div> @@ -21,491 +20,512 @@ </div> </div> </el-card> <!-- 会议申请表单 --> <el-card> <div class="form-header"> <h3>{{ getCurrentTypeName() }}申请</h3> </div> <el-form ref="meetingFormRef" :model="meetingForm" :rules="rules" label-width="100px" > <el-form ref="meetingFormRef" :model="meetingForm" :rules="rules" label-width="100px"> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="会议主题" prop="title"> <el-input v-model="meetingForm.title" placeholder="请输入会议主题"/> <el-form-item label="会议主题" prop="title"> <el-input v-model="meetingForm.title" placeholder="请输入会议主题" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="会议室" prop="roomId"> <el-select v-model="meetingForm.roomId" placeholder="请选择会议室" style="width: 100%"> <el-option v-for="room in meetingRooms" :key="room.id" :label="`${room.name} (${room.location})`" :value="room.id" /> <el-form-item label="会议室" prop="roomId"> <el-select v-model="meetingForm.roomId" placeholder="请选择会议室" style="width: 100%"> <el-option v-for="room in meetingRooms" :key="room.id" :label="`${room.name} (${room.location})`" :value="room.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="主持人" prop="host"> <el-input v-model="meetingForm.host" placeholder="请输入主持人姓名"/> <el-form-item label="主持人" prop="host"> <el-input v-model="meetingForm.host" placeholder="请输入主持人姓名" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="会议日期" prop="meetingDate"> <el-date-picker v-model="meetingForm.meetingDate" type="date" placeholder="请选择会议日期" value-format="YYYY-MM-DD" format="YYYY-MM-DD" :disabled-date="disabledDate" style="width: 100%" /> <el-form-item label="会议日期" prop="meetingDate"> <el-date-picker v-model="meetingForm.meetingDate" type="date" placeholder="请选择会议日期" value-format="YYYY-MM-DD" format="YYYY-MM-DD" :disabled-date="disabledDate" style="width: 100%" /> </el-form-item> </el-col> <el-col :span="12"> <!-- 空列,保持布局 --> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="12"> <el-form-item label="开始时间" prop="startTime"> <el-select v-model="meetingForm.startTime" placeholder="请选择开始时间" style="width: 100%" > <el-option v-for="time in startTimeOptions" :key="time.value" :label="time.label" :value="time.value" /> <el-form-item label="开始时间" prop="startTime"> <el-select v-model="meetingForm.startTime" placeholder="请选择开始时间" style="width: 100%"> <el-option v-for="time in startTimeOptions" :key="time.value" :label="time.label" :value="time.value" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="结束时间" prop="endTime"> <el-select v-model="meetingForm.endTime" placeholder="请选择结束时间" style="width: 100%" > <el-option v-for="time in endTimeOptions" :key="time.value" :label="time.label" :value="time.value" /> <el-form-item label="结束时间" prop="endTime"> <el-select v-model="meetingForm.endTime" placeholder="请选择结束时间" style="width: 100%"> <el-option v-for="time in endTimeOptions" :key="time.value" :label="time.label" :value="time.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-form-item label="参会人员" prop="participants"> <el-select v-model="meetingForm.participants" multiple filterable placeholder="请选择参会人员" style="width: 100%" > <el-option v-for="person in employees" :key="person.id" :label="`${person.staffName}${person.postName ? ` (${person.postName})` : ''}`" :value="person.id" /> <el-form-item label="参会人员" prop="participants"> <el-select v-model="meetingForm.participants" multiple filterable placeholder="请选择参会人员" style="width: 100%"> <el-option v-for="user in users" :key="user.userId" :label="user.deptNames ? `${user.nickName} (${user.deptNames})` : user.nickName" :value="user.userId" /> </el-select> </el-form-item> <el-form-item label="会议说明" prop="description"> <el-input v-model="meetingForm.description" type="textarea" :rows="4" placeholder="请输入会议说明" /> <el-form-item label="会议说明" prop="description"> <el-input v-model="meetingForm.description" type="textarea" :rows="4" placeholder="请输入会议说明" /> </el-form-item> </el-form> <div class="form-footer"> <el-button @click="resetForm">重置</el-button> <el-button type="primary" @click="submitForm">提交</el-button> <el-button type="primary" @click="submitForm">提交</el-button> </div> </el-card> </div> </template> <script setup> import {ref, reactive, onMounted, computed, watch} from 'vue' import {ElMessage} from 'element-plus' import {Plus, Document, Promotion, Bell} from '@element-plus/icons-vue' import {getRoomEnum, saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; import { ref, reactive, onMounted, computed, watch } from "vue"; import { ElMessage } from "element-plus"; import { Plus, Document, Promotion, Bell } from "@element-plus/icons-vue"; import { getRoomEnum, saveMeetingApplication, } from "@/api/collaborativeApproval/meeting.js"; import { userListNoPageByTenantId } from "@/api/system/user.js"; // 当前申请类型 const currentType = ref('department') // approval: 审批流程, department: 部门级, notification: 通知发布 // 当前申请类型 const currentType = ref("department"); // approval: 审批流程, department: 部门级, notification: 通知发布 // 申请类型选项 const applicationTypes = ref([ { value: 'approval', name: '审批流程会议', desc: '需要经过多级审批的会议申请', icon: Document }, { value: 'department', name: '部门级会议', desc: '部门内部会议申请流程', icon: Promotion }, { value: 'notification', name: '会议通知', desc: '无需审批直接发布的会议通知', icon: Bell } ]) // 申请类型选项 const applicationTypes = ref([ { value: "approval", name: "审批流程会议", desc: "需要经过多级审批的会议申请", icon: Document, }, { value: "department", name: "部门级会议", desc: "部门内部会议申请流程", icon: Promotion, }, { value: "notification", name: "会议通知", desc: "无需审批直接发布的会议通知", icon: Bell, }, ]); // 表单数据 const meetingForm = reactive({ title: '', type: '', roomId: '', host: '', meetingDate: '', startTime: '', endTime: '', participants: [], description: '' }) // 表单数据 const meetingForm = reactive({ title: "", type: "", roomId: "", host: "", meetingDate: "", startTime: "", endTime: "", participants: [], description: "", }); // 表单引用 const meetingFormRef = ref(null) // 表单引用 const meetingFormRef = ref(null); // 会议室列表 const meetingRooms = ref([]) // 会议室列表 const meetingRooms = ref([]); // 员工列表 const employees = ref([]) // 用户列表(系统管理-用户管理) const users = ref([]); // 时间选项(以半小时为间隔) const timeOptions = ref([]) // 时间选项(以半小时为间隔) const timeOptions = ref([]); const getTimeInMinutes = (time) => { if (!time) return -1 const [hour, minute] = time.split(':').map(Number) return hour * 60 + minute } const getTimeInMinutes = time => { if (!time) return -1; const [hour, minute] = time.split(":").map(Number); return hour * 60 + minute; }; const isToday = (dateText) => { if (!dateText) return false const [year, month, day] = dateText.split('-').map(Number) const now = new Date() return year === now.getFullYear() && month === now.getMonth() + 1 && day === now.getDate() } const isToday = dateText => { if (!dateText) return false; const [year, month, day] = dateText.split("-").map(Number); const now = new Date(); return ( year === now.getFullYear() && month === now.getMonth() + 1 && day === now.getDate() ); }; const validateStartTime = (_rule, value, callback) => { if (!value) { callback() return } if (isToday(meetingForm.meetingDate)) { const now = new Date() const currentMinutes = now.getHours() * 60 + now.getMinutes() if (getTimeInMinutes(value) > currentMinutes) { callback(new Error('当天开始时间不能晚于当前时间')) return const validateStartTime = (_rule, value, callback) => { if (!value) { callback(); return; } } callback() } const validateEndTime = (_rule, value, callback) => { if (!value || !meetingForm.startTime) { callback() return } if (getTimeInMinutes(value) <= getTimeInMinutes(meetingForm.startTime)) { callback(new Error('结束时间必须大于开始时间')) return } callback() } // 表单校验规则 const rules = { title: [{required: true, message: '请输入会议主题', trigger: 'blur'}], roomId: [{required: true, message: '请选择会议室', trigger: 'change'}], host: [{required: true, message: '请输入主持人', trigger: 'blur'}], meetingDate: [{required: true, message: '请选择会议日期', trigger: 'change'}], startTime: [ {required: true, message: '请选择开始时间', trigger: 'change'}, {validator: validateStartTime, trigger: 'change'} ], endTime: [ {required: true, message: '请选择结束时间', trigger: 'change'}, {validator: validateEndTime, trigger: 'change'} ], participants: [{required: true, message: '请选择参会人员', trigger: 'change'}] } const startTimeOptions = computed(() => { if (!isToday(meetingForm.meetingDate)) { return timeOptions.value } const now = new Date() const currentMinutes = now.getHours() * 60 + now.getMinutes() return timeOptions.value.filter(item => getTimeInMinutes(item.value) <= currentMinutes) }) const endTimeOptions = computed(() => { if (!meetingForm.startTime) { return timeOptions.value } const startMinutes = getTimeInMinutes(meetingForm.startTime) return timeOptions.value.filter(item => getTimeInMinutes(item.value) > startMinutes) }) // 初始化时间选项 const initTimeOptions = () => { const options = [] const now = new Date() const currentHour = now.getHours() const currentMinute = now.getMinutes() // meetingDate 是 "yyyy-MM-dd" const meetingDate = new Date(meetingForm.meetingDate) const isSameDay = now.getFullYear() === meetingDate.getFullYear() && now.getMonth() === meetingDate.getMonth() && now.getDate() === meetingDate.getDate() console.log('是否同一天:', isSameDay) for (let hour = 8; hour <= 18; hour++) { // 开始时间必须晚于当前时间 if (hour < currentHour && isSameDay) { continue if (isToday(meetingForm.meetingDate)) { const now = new Date(); const currentMinutes = now.getHours() * 60 + now.getMinutes(); if (getTimeInMinutes(value) > currentMinutes) { callback(new Error("当天开始时间不能晚于当前时间")); return; } } if (hour === currentHour && currentMinute > 30 && isSameDay) { continue } // 每个小时添加两个选项:整点和半点 options.push({ value: `${hour.toString().padStart(2, '0')}:00`, label: `${hour.toString().padStart(2, '0')}:00` }) if (hour < 18) { // 18:00之后没有半点选项 callback(); }; const validateEndTime = (_rule, value, callback) => { if (!value || !meetingForm.startTime) { callback(); return; } if (getTimeInMinutes(value) <= getTimeInMinutes(meetingForm.startTime)) { callback(new Error("结束时间必须大于开始时间")); return; } callback(); }; // 表单校验规则 const rules = { title: [{ required: true, message: "请输入会议主题", trigger: "blur" }], roomId: [{ required: true, message: "请选择会议室", trigger: "change" }], host: [{ required: true, message: "请输入主持人", trigger: "blur" }], meetingDate: [ { required: true, message: "请选择会议日期", trigger: "change" }, ], startTime: [ { required: true, message: "请选择开始时间", trigger: "change" }, { validator: validateStartTime, trigger: "change" }, ], endTime: [ { required: true, message: "请选择结束时间", trigger: "change" }, { validator: validateEndTime, trigger: "change" }, ], participants: [ { required: true, message: "请选择参会人员", trigger: "change" }, ], }; const startTimeOptions = computed(() => { if (!isToday(meetingForm.meetingDate)) { return timeOptions.value; } const now = new Date(); const currentMinutes = now.getHours() * 60 + now.getMinutes(); return timeOptions.value.filter( item => getTimeInMinutes(item.value) <= currentMinutes ); }); const endTimeOptions = computed(() => { if (!meetingForm.startTime) { return timeOptions.value; } const startMinutes = getTimeInMinutes(meetingForm.startTime); return timeOptions.value.filter( item => getTimeInMinutes(item.value) > startMinutes ); }); // 初始化时间选项 const initTimeOptions = () => { const options = []; const now = new Date(); const currentHour = now.getHours(); const currentMinute = now.getMinutes(); // meetingDate 是 "yyyy-MM-dd" const meetingDate = new Date(meetingForm.meetingDate); const isSameDay = now.getFullYear() === meetingDate.getFullYear() && now.getMonth() === meetingDate.getMonth() && now.getDate() === meetingDate.getDate(); console.log("是否同一天:", isSameDay); for (let hour = 8; hour <= 18; hour++) { // 开始时间必须晚于当前时间 if (hour < currentHour && isSameDay) { continue; } if (hour === currentHour && currentMinute > 30 && isSameDay) { continue; } // 每个小时添加两个选项:整点和半点 options.push({ value: `${hour.toString().padStart(2, '0')}:30`, label: `${hour.toString().padStart(2, '0')}:30` }) value: `${hour.toString().padStart(2, "0")}:00`, label: `${hour.toString().padStart(2, "0")}:00`, }); if (hour < 18) { // 18:00之后没有半点选项 options.push({ value: `${hour.toString().padStart(2, "0")}:30`, label: `${hour.toString().padStart(2, "0")}:30`, }); } } } timeOptions.value = options } timeOptions.value = options; }; watch(() => meetingForm.meetingDate, () => { if (meetingForm.startTime && !startTimeOptions.value.some(item => item.value === meetingForm.startTime)) { meetingForm.startTime = '' } if (meetingForm.endTime && !endTimeOptions.value.some(item => item.value === meetingForm.endTime)) { meetingForm.endTime = '' } if (meetingForm.startTime) { meetingFormRef.value?.validateField('startTime') } if (meetingForm.endTime) { meetingFormRef.value?.validateField('endTime') } initTimeOptions() }) watch(() => meetingForm.startTime, () => { if (meetingForm.endTime && getTimeInMinutes(meetingForm.endTime) <= getTimeInMinutes(meetingForm.startTime)) { meetingForm.endTime = '' } if (meetingForm.endTime) { meetingFormRef.value?.validateField('endTime') } }) // 禁用日期(禁用今天之前的日期) const disabledDate = (time) => { // 禁用今天之前的日期 return time.getTime() < Date.now() - 86400000 } // 切换申请类型 const changeType = (type) => { currentType.value = type } // 获取当前类型名称 const getCurrentTypeName = () => { const type = applicationTypes.value.find(t => t.value === currentType.value) return type ? type.name : '' } // 重置表单 const resetForm = () => { meetingFormRef.value?.resetFields() } // 提交表单 const submitForm = () => { meetingFormRef.value?.validate((valid) => { if (valid) { let formData = {...meetingForm} formData.applicationType = currentType.value formData.startTime = `${meetingForm.meetingDate} ${meetingForm.startTime}:00` formData.endTime = `${meetingForm.meetingDate} ${meetingForm.endTime}:00` formData.participants = JSON.stringify(formData.participants) console.log(formData) saveMeetingApplication(formData).then(() => { // 模拟提交操作 ElMessage.success(`${getCurrentTypeName()}提交成功`) // 根据不同类型执行不同操作 switch (currentType.value) { case 'approval': ElMessage.info('会议已提交审批流程') break case 'department': ElMessage.info('部门级会议申请已提交') break case 'notification': ElMessage.info('会议通知已发布') break } resetForm() }) watch( () => meetingForm.meetingDate, () => { if ( meetingForm.startTime && !startTimeOptions.value.some(item => item.value === meetingForm.startTime) ) { meetingForm.startTime = ""; } if ( meetingForm.endTime && !endTimeOptions.value.some(item => item.value === meetingForm.endTime) ) { meetingForm.endTime = ""; } if (meetingForm.startTime) { meetingFormRef.value?.validateField("startTime"); } if (meetingForm.endTime) { meetingFormRef.value?.validateField("endTime"); } initTimeOptions(); } }) } ); // 页面加载时初始化 onMounted(() => { initTimeOptions() getRoomEnum().then(res => { meetingRooms.value = res.data }) staffOnJobListPage({ current: -1, size: -1, staffState: 1 }).then(res => { employees.value = res.data.records.sort((a, b) => (a.postName || '').localeCompare(b.postName || '')) }) }) watch( () => meetingForm.startTime, () => { if ( meetingForm.endTime && getTimeInMinutes(meetingForm.endTime) <= getTimeInMinutes(meetingForm.startTime) ) { meetingForm.endTime = ""; } if (meetingForm.endTime) { meetingFormRef.value?.validateField("endTime"); } } ); // 禁用日期(禁用今天之前的日期) const disabledDate = time => { // 禁用今天之前的日期 return time.getTime() < Date.now() - 86400000; }; // 切换申请类型 const changeType = type => { currentType.value = type; }; // 获取当前类型名称 const getCurrentTypeName = () => { const type = applicationTypes.value.find(t => t.value === currentType.value); return type ? type.name : ""; }; // 重置表单 const resetForm = () => { meetingFormRef.value?.resetFields(); }; // 提交表单 const submitForm = () => { meetingFormRef.value?.validate(valid => { if (valid) { let formData = { ...meetingForm }; formData.applicationType = currentType.value; formData.startTime = `${meetingForm.meetingDate} ${meetingForm.startTime}:00`; formData.endTime = `${meetingForm.meetingDate} ${meetingForm.endTime}:00`; formData.participants = JSON.stringify(formData.participants); console.log(formData); saveMeetingApplication(formData).then(() => { // 模拟提交操作 ElMessage.success(`${getCurrentTypeName()}提交成功`); // 根据不同类型执行不同操作 switch (currentType.value) { case "approval": ElMessage.info("会议已提交审批流程"); break; case "department": ElMessage.info("部门级会议申请已提交"); break; case "notification": ElMessage.info("会议通知已发布"); break; } resetForm(); }); } }); }; // 页面加载时初始化 onMounted(() => { initTimeOptions(); getRoomEnum().then(res => { meetingRooms.value = res.data; }); userListNoPageByTenantId().then(res => { const list = Array.isArray(res?.data) ? res.data : []; users.value = list .map(item => ({ userId: item?.userId, nickName: item?.nickName || item?.userName || String(item?.userId ?? ""), deptNames: item?.deptNames || "", })) .filter( item => item.userId !== null && item.userId !== undefined && item.nickName ) .sort((a, b) => String(a.nickName).localeCompare(String(b.nickName))); }); }); </script> <style scoped> .app-container { padding: 20px; } .app-container { padding: 20px; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .page-header h2 { margin: 0; color: #303133; } .page-header h2 { margin: 0; color: #303133; } .type-card { margin-bottom: 20px; } .type-card { margin-bottom: 20px; } .type-selector { display: flex; gap: 20px; } .type-selector { display: flex; gap: 20px; } .type-item { flex: 1; display: flex; align-items: center; padding: 20px; border: 1px solid #ebeef5; border-radius: 8px; cursor: pointer; transition: all 0.3s; } .type-item { flex: 1; display: flex; align-items: center; padding: 20px; border: 1px solid #ebeef5; border-radius: 8px; cursor: pointer; transition: all 0.3s; } .type-item:hover { border-color: #409eff; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); } .type-item:hover { border-color: #409eff; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); } .type-item.active { border-color: #409eff; background-color: #ecf5ff; } .type-item.active { border-color: #409eff; background-color: #ecf5ff; } .type-icon { margin-right: 15px; color: #409eff; } .type-icon { margin-right: 15px; color: #409eff; } .type-name { font-size: 16px; font-weight: 500; color: #303133; margin-bottom: 5px; } .type-name { font-size: 16px; font-weight: 500; color: #303133; margin-bottom: 5px; } .type-desc { font-size: 14px; color: #909399; } .type-desc { font-size: 14px; color: #909399; } .form-header { margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #ebeef5; } .form-header { margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #ebeef5; } .form-header h3 { margin: 0; color: #303133; } .form-header h3 { margin: 0; color: #303133; } .form-footer { display: flex; justify-content: flex-end; gap: 10px; margin-top: 30px; padding-top: 20px; border-top: 1px solid #ebeef5; } .form-footer { display: flex; justify-content: flex-end; gap: 10px; margin-top: 30px; padding-top: 20px; border-top: 1px solid #ebeef5; } </style> src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
@@ -1,182 +1,219 @@ <template> <div> <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-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-table v-loading="loading" :data="approvalList" border :height="tableHeight"> <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"> <el-table v-loading="loading" :data="approvalList" border :height="tableHeight"> <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"> <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"> <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"> <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 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" /> <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" > <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">{{ <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">{{ <el-descriptions-item label="申请人" label-class-name="nowrap-label">{{ currentMeeting.applicant }}</el-descriptions-item> <el-descriptions-item label="主理人" label-class-name="nowrap-label">{{ <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"> <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">{{ <el-descriptions-item label="会议地点" label-class-name="nowrap-label">{{ currentMeeting.location }}</el-descriptions-item> <el-descriptions-item label="参会人数" label-class-name="nowrap-label">{{ <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-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">{{ <el-descriptions-item label="申请时间" label-class-name="nowrap-label">{{ currentMeeting.createTime }}</el-descriptions-item> <el-descriptions-item style="max-height: 400px" label="会议说明" :span="2" <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;" > <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" > <el-dialog title="会议审批" v-model="approvalDialogVisible"> <div v-if="currentMeeting"> <el-descriptions :column="2" border> <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"> <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;" > <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"> <div v-show="false" class="approval-opinion mt-20"> <h4>审批意见</h4> <el-input v-model="approvalOpinion" type="textarea" placeholder="请输入审批意见" :rows="4" /> <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> <el-button type="danger" @click="submitApproval('2')">不通过</el-button> <el-button type="primary" @click="submitApproval('1')">通 过</el-button> </div> </template> </el-dialog> @@ -184,231 +221,260 @@ </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 dayjs from "dayjs"; import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; 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 dayjs from "dayjs"; import { userListNoPageByTenantId } from "@/api/system/user.js"; // 数据列表加载状态 const loading = ref(false) // 数据列表加载状态 const loading = ref(false); // 总条数 const total = ref(0) // 总条数 const total = ref(0); // 表格高度(根据窗口高度自适应) const tableHeight = ref(window.innerHeight - 380) const roomEnum = ref([]) const staffList = ref([]) // 审批列表数据 const approvalList = ref([]) // 表格高度(根据窗口高度自适应) const tableHeight = ref(window.innerHeight - 380); const roomEnum = ref([]); const userList = ref([]); // 审批列表数据 const approvalList = ref([]); // 查询参数 const queryParams = reactive({ current: 1, size: 10 }) // 查询参数 const queryParams = reactive({ current: 1, size: 10, }); // 搜索表单 const searchForm = reactive({ title: '', applicant: '', status: '' }) // 搜索表单 const searchForm = reactive({ title: "", applicant: "", status: "", }); // 是否显示对话框 const detailDialogVisible = ref(false) const approvalDialogVisible = ref(false) // 是否显示对话框 const detailDialogVisible = ref(false); const approvalDialogVisible = ref(false); // 当前查看的会议 const currentMeeting = ref(null) // 当前查看的会议 const currentMeeting = ref(null); // 审批意见 const approvalOpinion = ref('') // 审批意见 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.postName ? ` (${staff.postName})` : ''}` // 查询数据 const getList = async () => { loading.value = true; let resp = await getExamineList({ ...searchForm, ...queryParams }); const userMap = new Map(userList.value.map(u => [String(u.userId), u])); approvalList.value = resp.data.records.map(it => { let room = roomEnum.value.find(room => it.roomId === room.id); it.location = `${room.name}(${room.location})`; let participantIds = []; try { participantIds = Array.isArray(it.participants) ? it.participants : JSON.parse(it.participants); } catch (_e) { participantIds = []; } }) if (!Array.isArray(participantIds)) participantIds = []; it.staffCount = participantIds.length; it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( "HH:mm:ss" )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`; it.participants = participantIds.map(id => { const user = userMap.get(String(id)); const nickName = user?.nickName || user?.userName || String(id ?? ""); const deptNames = user?.deptNames || ""; return { id, name: deptNames ? `${nickName} (${deptNames})` : nickName, }; }); return it; }); total.value = resp.data.total; loading.value = false; }; return it }) total.value = resp.data.total loading.value = false } // 搜索按钮操作 const handleSearch = () => { queryParams.pageNum = 1; getList(); }; // 搜索按钮操作 const handleSearch = () => { queryParams.pageNum = 1 getList() } // 重置搜索表单 const resetSearch = () => { Object.assign(searchForm, { title: "", applicant: "", status: "", }); handleSearch(); }; // 重置搜索表单 const resetSearch = () => { Object.assign(searchForm, { title: '', applicant: '', status: '' }) handleSearch() } // 查看详情 const viewDetail = row => { currentMeeting.value = row; detailDialogVisible.value = true; }; // 查看详情 const viewDetail = (row) => { currentMeeting.value = row detailDialogVisible.value = true } // 处理审批 const handleApproval = row => { currentMeeting.value = row; approvalOpinion.value = ""; approvalDialogVisible.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 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 getStatusText = (status) => { const statusMap = { '0': '待审批', '1': '已通过', '2': '未通过', '3': '已取消' } return statusMap[status] || '未知' } // 格式化日期时间 const formatDateTime = dateTime => { if (!dateTime) return ""; return dateTime.replace(" ", "\n"); }; // 格式化日期时间 const formatDateTime = (dateTime) => { if (!dateTime) return '' return dateTime.replace(' ', '\n') } // 提交审批 const submitApproval = status => { // if (status === 'approved' && !approvalOpinion.value.trim()) { // ElMessage.warning('请填写审批意见') // return // } // 提交审批 const submitApproval = (status) => { // if (status === 'approved' && !approvalOpinion.value.trim()) { // ElMessage.warning('请填写审批意见') // return // } ElMessageBox.confirm( `确认${status === '1' ? '通过' : '不通过'}该会议申请?`, '审批确认', ElMessageBox.confirm( `确认${status === "1" ? "通过" : "不通过"}该会议申请?`, "审批确认", { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", } ).then(() => { saveMeetingApplication({ id: currentMeeting.value.id, status: status }).then(resp=>{ // 更新会议状态 currentMeeting.value.status = status ) .then(() => { saveMeetingApplication({ id: currentMeeting.value.id, status: status, }).then(resp => { // 更新会议状态 currentMeeting.value.status = status; ElMessage.success('审批提交成功') approvalDialogVisible.value = false getList() }) ElMessage.success("审批提交成功"); approvalDialogVisible.value = false; getList(); }); }) .catch(() => {}); }; }).catch(() => { }) } // 页面加载时获取数据 onMounted(async () => { const [resp1, resp2] = await Promise.all([ getRoomEnum(), userListNoPageByTenantId(), ]); roomEnum.value = resp1.data; const list = Array.isArray(resp2?.data) ? resp2.data : []; userList.value = list .map(item => ({ userId: item?.userId, nickName: item?.nickName, userName: item?.userName, deptNames: item?.deptNames || (item?.dept?.deptName ? item.dept.deptName : ""), })) .filter(item => item.userId !== null && item.userId !== undefined); // 页面加载时获取数据 onMounted(async () => { const [resp1, resp2]= await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) roomEnum.value = resp1.data staffList.value = resp2.data.records await getList() }) await getList(); }); </script> <style scoped> .app-container { padding: 20px; } .app-container { padding: 20px; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .page-header h2 { margin: 0; color: #303133; } .page-header h2 { margin: 0; color: #303133; } .search-card { margin-bottom: 20px; } .search-card { margin-bottom: 20px; } .dialog-footer { display: flex; justify-content: flex-end; gap: 10px; } .dialog-footer { display: flex; justify-content: flex-end; gap: 10px; } .content-section h4 { margin: 0 0 15px 0; color: #303133; } .content-section h4 { margin: 0 0 15px 0; color: #303133; } .mt-20 { margin-top: 20px; } .mt-20 { margin-top: 20px; } .participants-list { min-height: 40px; padding: 15px; border-radius: 4px; line-height: 1.6; } .participants-list { min-height: 40px; padding: 15px; border-radius: 4px; line-height: 1.6; } .approval-opinion h4 { margin: 0 0 15px 0; color: #303133; } .approval-opinion h4 { margin: 0 0 15px 0; color: #303133; } .nowrap-label { white-space: nowrap !important; } .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; } .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> src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
@@ -1,180 +1,213 @@ <template> <div> <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-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-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-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-table v-loading="loading" :data="approvalList" border :height="tableHeight"> <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"> <el-table v-loading="loading" :data="approvalList" border :height="tableHeight"> <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"> <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"> <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"> <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 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" /> <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" > <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">{{ <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">{{ <el-descriptions-item label="申请人" label-class-name="nowrap-label">{{ currentMeeting.applicant }}</el-descriptions-item> <el-descriptions-item label="主理人" label-class-name="nowrap-label">{{ <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"> <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">{{ <el-descriptions-item label="会议地点" label-class-name="nowrap-label">{{ currentMeeting.location }}</el-descriptions-item> <el-descriptions-item label="参会人数" label-class-name="nowrap-label">{{ <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-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">{{ <el-descriptions-item label="申请时间" label-class-name="nowrap-label">{{ currentMeeting.createTime }}</el-descriptions-item> <el-descriptions-item style="max-height: 400px" label="会议说明" :span="2" <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;" > <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" > <el-dialog title="会议发布" v-model="approvalDialogVisible"> <div v-if="currentMeeting"> <el-descriptions :column="2" border> <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"> <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;" > <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 class="approval-opinion mt-20"> <h4>发布意见</h4> <el-input v-model="publishComment" type="textarea" placeholder="请输入发布意见" :rows="4" /> <el-input v-model="publishComment" 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> <!-- <el-button type="danger" @click="submitApproval('2')">不通过</el-button>--> <el-button type="primary" @click="submitApproval('1')">发 布</el-button> </div> </template> </el-dialog> @@ -182,231 +215,260 @@ </template> <script setup> import {ref, reactive, onMounted} from 'vue' import {ElMessage, ElMessageBox} from 'element-plus' import Pagination from '@/components/Pagination/index.vue' import {getRoomEnum, getMeetingPublish,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' import dayjs from "dayjs"; import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; import { ref, reactive, onMounted } from "vue"; import { ElMessage, ElMessageBox } from "element-plus"; import Pagination from "@/components/Pagination/index.vue"; import { getRoomEnum, getMeetingPublish, saveMeetingApplication, } from "@/api/collaborativeApproval/meeting.js"; import dayjs from "dayjs"; import { userListNoPageByTenantId } from "@/api/system/user.js"; // 数据列表加载状态 const loading = ref(false) // 数据列表加载状态 const loading = ref(false); // 总条数 const total = ref(0) // 总条数 const total = ref(0); // 表格高度(根据窗口高度自适应) const tableHeight = ref(window.innerHeight - 380) const roomEnum = ref([]) const staffList = ref([]) // 发布列表数据 const approvalList = ref([]) // 表格高度(根据窗口高度自适应) const tableHeight = ref(window.innerHeight - 380); const roomEnum = ref([]); const userList = ref([]); // 发布列表数据 const approvalList = ref([]); // 查询参数 const queryParams = reactive({ current: 1, size: 10 }) // 查询参数 const queryParams = reactive({ current: 1, size: 10, }); // 搜索表单 const searchForm = reactive({ title: '', applicant: '', status: '' }) // 搜索表单 const searchForm = reactive({ title: "", applicant: "", status: "", }); // 是否显示对话框 const detailDialogVisible = ref(false) const approvalDialogVisible = ref(false) // 是否显示对话框 const detailDialogVisible = ref(false); const approvalDialogVisible = ref(false); // 当前查看的会议 const currentMeeting = ref(null) // 当前查看的会议 const currentMeeting = ref(null); // 发布意见 const publishComment = ref('') // 发布意见 const publishComment = ref(""); // 查询数据 const getList = async () => { loading.value = true let resp = await getMeetingPublish({...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.status = it.publishStatus 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.postName ? ` (${staff.postName})` : ''}` // 查询数据 const getList = async () => { loading.value = true; let resp = await getMeetingPublish({ ...searchForm, ...queryParams }); const userMap = new Map(userList.value.map(u => [String(u.userId), u])); approvalList.value = resp.data.records.map(it => { let room = roomEnum.value.find(room => it.roomId === room.id); it.location = `${room.name}(${room.location})`; let participantIds = []; try { participantIds = Array.isArray(it.participants) ? it.participants : JSON.parse(it.participants); } catch (_e) { participantIds = []; } }) if (!Array.isArray(participantIds)) participantIds = []; it.staffCount = participantIds.length; it.status = it.publishStatus; it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( "HH:mm:ss" )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`; it.participants = participantIds.map(id => { const user = userMap.get(String(id)); const nickName = user?.nickName || user?.userName || String(id ?? ""); const deptNames = user?.deptNames || ""; return { id, name: deptNames ? `${nickName} (${deptNames})` : nickName, }; }); return it; }); total.value = resp.data.total; loading.value = false; }; return it }) total.value = resp.data.total loading.value = false } // 搜索按钮操作 const handleSearch = () => { queryParams.pageNum = 1; getList(); }; // 搜索按钮操作 const handleSearch = () => { queryParams.pageNum = 1 getList() } // 重置搜索表单 const resetSearch = () => { Object.assign(searchForm, { title: "", applicant: "", status: "", }); handleSearch(); }; // 重置搜索表单 const resetSearch = () => { Object.assign(searchForm, { title: '', applicant: '', status: '' }) handleSearch() } // 查看详情 const viewDetail = row => { currentMeeting.value = row; detailDialogVisible.value = true; }; // 查看详情 const viewDetail = (row) => { currentMeeting.value = row detailDialogVisible.value = true } // 处理发布 const handleApproval = row => { currentMeeting.value = row; publishComment.value = ""; approvalDialogVisible.value = true; }; // 处理发布 const handleApproval = (row) => { currentMeeting.value = row publishComment.value = '' approvalDialogVisible.value = true } // 获取状态类型 const getStatusType = status => { const statusMap = { 0: "info", // 待发布 1: "success", // 已通过 2: "danger", // 未通过 }; return statusMap[status] || "info"; }; // 获取状态类型 const getStatusType = (status) => { const statusMap = { '0': 'info', // 待发布 '1': 'success', // 已通过 '2': 'danger', // 未通过 } return statusMap[status] || 'info' } // 获取状态文本 const getStatusText = status => { const statusMap = { 0: "待发布", 1: "已发布", 2: "已取消", }; return statusMap[status] || "未知"; }; // 获取状态文本 const getStatusText = (status) => { const statusMap = { '0': '待发布', '1': '已发布', '2': '已取消', } return statusMap[status] || '未知' } // 格式化日期时间 const formatDateTime = dateTime => { if (!dateTime) return ""; return dateTime.replace(" ", "\n"); }; // 格式化日期时间 const formatDateTime = (dateTime) => { if (!dateTime) return '' return dateTime.replace(' ', '\n') } // 提交发布 const submitApproval = status => { // if (status === 'approved' && !publishComment.value.trim()) { // ElMessage.warning('请填写发布意见') // return // } // 提交发布 const submitApproval = (status) => { // if (status === 'approved' && !publishComment.value.trim()) { // ElMessage.warning('请填写发布意见') // return // } ElMessageBox.confirm( `确认${status === '1' ? '发布' : '取消'}该会议?`, '发布确认', ElMessageBox.confirm( `确认${status === "1" ? "发布" : "取消"}该会议?`, "发布确认", { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' confirmButtonText: "确定", cancelButtonText: "取消", type: "warning", } ).then(() => { saveMeetingApplication({ id: currentMeeting.value.id, publishStatus: status, publishComment: publishComment.value }).then(resp=>{ // 更新会议状态 currentMeeting.value.status = status ) .then(() => { saveMeetingApplication({ id: currentMeeting.value.id, publishStatus: status, publishComment: publishComment.value, }).then(resp => { // 更新会议状态 currentMeeting.value.status = status; ElMessage.success('发布提交成功') approvalDialogVisible.value = false getList() }) ElMessage.success("发布提交成功"); approvalDialogVisible.value = false; getList(); }); }) .catch(() => {}); }; }).catch(() => { }) } // 页面加载时获取数据 onMounted(async () => { const [resp1, resp2] = await Promise.all([ getRoomEnum(), userListNoPageByTenantId(), ]); roomEnum.value = resp1.data; const list = Array.isArray(resp2?.data) ? resp2.data : []; userList.value = list .map(item => ({ userId: item?.userId, nickName: item?.nickName, userName: item?.userName, deptNames: item?.deptNames || (item?.dept?.deptName ? item.dept.deptName : ""), })) .filter(item => item.userId !== null && item.userId !== undefined); // 页面加载时获取数据 onMounted(async () => { const [resp1, resp2]= await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) roomEnum.value = resp1.data staffList.value = resp2.data.records await getList() }) await getList(); }); </script> <style scoped> .app-container { padding: 20px; } .app-container { padding: 20px; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .page-header h2 { margin: 0; color: #303133; } .page-header h2 { margin: 0; color: #303133; } .search-card { margin-bottom: 20px; } .search-card { margin-bottom: 20px; } .dialog-footer { display: flex; justify-content: flex-end; gap: 10px; } .dialog-footer { display: flex; justify-content: flex-end; gap: 10px; } .content-section h4 { margin: 0 0 15px 0; color: #303133; } .content-section h4 { margin: 0 0 15px 0; color: #303133; } .mt-20 { margin-top: 20px; } .mt-20 { margin-top: 20px; } .participants-list { min-height: 40px; padding: 15px; border-radius: 4px; line-height: 1.6; } .participants-list { min-height: 40px; padding: 15px; border-radius: 4px; line-height: 1.6; } .approval-opinion h4 { margin: 0 0 15px 0; color: #303133; } .approval-opinion h4 { margin: 0 0 15px 0; color: #303133; } .nowrap-label { white-space: nowrap !important; } .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; } .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> src/views/collaborativeApproval/notificationManagement/summary/index.vue
@@ -1,153 +1,182 @@ <template> <div> <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-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-table v-loading="loading" :data="meetingList" border :height="tableHeight"> <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"> <el-table v-loading="loading" :data="meetingList" border :height="tableHeight"> <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"> <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"> <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 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" /> <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" > <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">{{ <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">{{ <el-descriptions-item label="申请人" label-class-name="nowrap-label">{{ currentMeeting.applicant }}</el-descriptions-item> <el-descriptions-item label="主持人" label-class-name="nowrap-label">{{ <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"> <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">{{ <el-descriptions-item label="会议地点" label-class-name="nowrap-label">{{ currentMeeting.location }}</el-descriptions-item> <el-descriptions-item label="参会人数" label-class-name="nowrap-label">{{ <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-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">{{ <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-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;" > <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" > <el-dialog title="添加会议纪要" v-model="minutesDialogVisible" width="80%" @close="handleCloseMinutesDialog"> <div v-if="currentMeeting"> <el-descriptions :column="2" border> <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"> <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" /> <Editor v-model="minutesContent" :min-height="400" /> </div> </div> </div> <template #footer> <div class="dialog-footer"> <el-button @click="minutesDialogVisible = false">取 消</el-button> <el-button type="primary" @click="submitMinutes">保 存</el-button> <el-button type="primary" @click="submitMinutes">保 存</el-button> </div> </template> </el-dialog> @@ -155,245 +184,278 @@ </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 dayjs from "dayjs" import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; 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 dayjs from "dayjs"; import { userListNoPageByTenantId } from "@/api/system/user.js"; // 数据列表加载状态 const loading = ref(false) // 数据列表加载状态 const loading = ref(false); // 总条数 const total = ref(0) // 总条数 const total = ref(0); // 表格高度(根据窗口高度自适应) const tableHeight = ref(window.innerHeight - 380) const roomEnum = ref([]) const staffList = ref([]) // 表格高度(根据窗口高度自适应) const tableHeight = ref(window.innerHeight - 380); const roomEnum = ref([]); const userList = ref([]); // 会议列表数据 const meetingList = ref([]) // 会议列表数据 const meetingList = ref([]); // 查询参数 const queryParams = reactive({ current: 1, size: 10 }) // 查询参数 const queryParams = reactive({ current: 1, size: 10, }); // 搜索表单 const searchForm = reactive({ title: '', applicant: '', // status: '1' // 默认只显示已通过审批的会议 }) // 搜索表单 const searchForm = reactive({ title: "", applicant: "", // status: '1' // 默认只显示已通过审批的会议 }); // 是否显示对话框 const detailDialogVisible = ref(false) const minutesDialogVisible = ref(false) // 是否显示对话框 const detailDialogVisible = ref(false); const minutesDialogVisible = ref(false); // 当前查看的会议 const currentMeeting = ref(null) // 当前查看的会议 const currentMeeting = ref(null); // 会议纪要内容 const minutesContent = ref('') const minutesContentId = ref('') // 会议纪要内容 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.postName ? ` (${staff.postName})` : ''}` } }) const parseParticipants = raw => { if (!raw) return []; if (Array.isArray(raw)) return raw; try { const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed : []; } catch (_e) { return []; } }; return it }) total.value = resp.data.total loading.value = false } // 查询数据 const getList = async () => { loading.value = true; let resp = await getMeetingPublish({ ...searchForm, ...queryParams }); const userMap = new Map(userList.value.map(u => [String(u.userId), u])); meetingList.value = resp.data.records.map(it => { let room = roomEnum.value.find(room => it.roomId === room.id); it.location = `${room.name}(${room.location})`; const participantIds = parseParticipants(it.participants); it.staffCount = participantIds.length; it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( "HH:mm:ss" )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`; it.participants = participantIds.map(id => { const user = userMap.get(String(id)); const nickName = user?.nickName || user?.userName || String(id ?? ""); const deptNames = user?.deptNames || ""; return { id, name: deptNames ? `${nickName} (${deptNames})` : nickName, }; }); // 搜索按钮操作 const handleSearch = () => { queryParams.current = 1 getList() } return it; }); total.value = resp.data.total; loading.value = false; }; // 重置搜索表单 const resetSearch = () => { Object.assign(searchForm, { title: '', applicant: '', // status: '1' }) handleSearch() } // 搜索按钮操作 const handleSearch = () => { queryParams.current = 1; getList(); }; // 查看详情 const viewDetail = (row) => { currentMeeting.value = row detailDialogVisible.value = true } // 重置搜索表单 const resetSearch = () => { Object.assign(searchForm, { title: "", applicant: "", // status: '1' }); handleSearch(); }; // 添加会议纪要 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>` } // 查看详情 const viewDetail = row => { currentMeeting.value = row; detailDialogVisible.value = true; }; minutesDialogVisible.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>`; } // 提交会议纪要 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 }) 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 handleCloseMinutesDialog = () => { minutesContent.value = ""; }; // 获取状态类型 const getStatusType = (status) => { const statusMap = { '0': 'info', // 待审批 '1': 'success', // 已通过 '2': 'warning', // 未通过 '3': 'danger' // 取消 } return statusMap[status] || 'info' } // 获取状态类型 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 getStatusText = status => { const statusMap = { 0: "待审批", 1: "已通过", 2: "未通过", 3: "已取消", }; return statusMap[status] || "未知"; }; // 格式化日期时间 const formatDateTime = (dateTime) => { if (!dateTime) return '' return dateTime.replace(' ', '\n') } // 格式化日期时间 const formatDateTime = dateTime => { if (!dateTime) return ""; return dateTime.replace(" ", "\n"); }; // 页面加载时获取数据 onMounted(async () => { const [resp1, resp2] = await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) roomEnum.value = resp1.data staffList.value = resp2.data.records // 页面加载时获取数据 onMounted(async () => { const [resp1, resp2] = await Promise.all([ getRoomEnum(), userListNoPageByTenantId(), ]); roomEnum.value = resp1.data; const list = Array.isArray(resp2?.data) ? resp2.data : []; userList.value = list .map(item => ({ userId: item?.userId, nickName: item?.nickName, userName: item?.userName, deptNames: item?.deptNames || (item?.dept?.deptName ? item.dept.deptName : ""), })) .filter(item => item.userId !== null && item.userId !== undefined); await getList() }) await getList(); }); </script> <style scoped> .app-container { padding: 20px; } .app-container { padding: 20px; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .page-header h2 { margin: 0; color: #303133; } .page-header h2 { margin: 0; color: #303133; } .search-card { margin-bottom: 20px; } .search-card { margin-bottom: 20px; } .dialog-footer { display: flex; justify-content: flex-end; gap: 10px; } .dialog-footer { display: flex; justify-content: flex-end; gap: 10px; } .content-section h4 { margin: 0 0 15px 0; color: #303133; } .content-section h4 { margin: 0 0 15px 0; color: #303133; } .mt-20 { margin-top: 20px; } .mt-20 { margin-top: 20px; } .participants-list { min-height: 40px; padding: 15px; border-radius: 4px; line-height: 1.6; } .participants-list { min-height: 40px; padding: 15px; border-radius: 4px; line-height: 1.6; } .nowrap-label { white-space: nowrap !important; } .nowrap-label { white-space: nowrap !important; } .editor-container { border: 1px solid #dcdfe6; border-radius: 4px; } .editor-container { border: 1px solid #dcdfe6; border-radius: 4px; } </style>