<template> <div> <el-affix postion="top" :offset="95" v-if="!isDetail"> <div class="flex justify-between mb-4 bg-white"> <b class="text-20px">{{ form.meetingId ? '修改会议' : '新增会议' }}</b> <el-button type="success" @click="submit()">保存</el-button> </div> </el-affix> <el-form :model="form" ref="formRef" :rules="rules" label-width="120px" v-loading="loading" :disabled="!!isDetail" > <el-row :gutter="20"> <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24"> <el-form-item label="会议主题" prop="meetingSubject"> <el-input v-model="form.meetingSubject" placeholder="请输入会议主题" clearable /> </el-form-item> </el-col> <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24"> <el-form-item label="okr节点" prop="nodeId"> <el-tree-select v-model="form.nodeId" :data="peroidList" :props="defaultProps" :render-after-expand="false" :default-expand-all="false" check-strictly clearable placeholder="选择OKR节点" style="width: 100%" /> </el-form-item> </el-col> <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> <el-form-item label="会议时间" prop="startTime"> <el-date-picker v-model="form.startTime" type="datetime" format="YYYY-MM-DD HH:mm" value-format="YYYY-MM-DD HH:mm" placeholder="请选择会议开始时间" /> </el-form-item> </el-col> <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> <el-form-item label="预计结束时间" prop="expectEndTime"> <el-date-picker v-model="form.expectEndTime" type="datetime" format="YYYY-MM-DD HH:mm" value-format="YYYY-MM-DD HH:mm" placeholder="请选择预计结束时间" /> </el-form-item> </el-col> <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> <el-form-item label="会议地点" prop="meetingRoom"> <el-input v-model="form.meetingRoom" placeholder="请输入会议地点" clearable /> </el-form-item> </el-col> <el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24"> <el-form-item label="会议状态" prop="status"> <el-select v-model="form.status" placeholder="请选择会议状态" style="width: 100%"> <el-option label="未开始" value="1" /> <el-option label="已结束" value="2" /> <el-option label="已取消" value="3" disabled /> </el-select> </el-form-item> </el-col> <el-col :span="24" :offset="0"> <el-form-item label="预约参会人员" prop="expectUsers"> <el-select v-model="form.expectUsers" placeholder="选择参会人员" clearable filterable style="width: 100%" multiple @change="handleUserChange" > <el-option v-for="item in userOptions" :key="item.id" :label="item.name" :value="item.id" :disabled="item.status == 1" /> </el-select> </el-form-item> </el-col> <el-col :span="24" :offset="0" v-if="form.meetingId"> <el-form-item label="实际参会人员" prop="actualUsers"> <el-checkbox-group v-model="form.actualUsers"> <el-checkbox v-for="item in expectUserOptions" :key="item.id" :label="item.name" :value="item.id" > {{ item.name }} </el-checkbox> </el-checkbox-group> </el-form-item> </el-col> <el-col :span="24" :offset="0" v-if="!isAllActived"> <el-form-item label="缺席原因" prop="absentReason"> <el-input v-model="form.absentReason" placeholder="请输入缺席原因" /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24"> <el-form-item label="会议内容:" prop="meetingContent"> <div v-if="!!isDetail" v-dompurify-html="form.meetingContent" class="w-full"></div> <Editor v-else v-model="form.meetingContent" height="500px" /> </el-form-item> </el-col> <el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" v-if="!!form.meetingId"> <el-form-item label="会议纪要:" prop="meetingSummary"> <div v-if="!!isDetail" v-dompurify-html="form.meetingSummary" class="w-full"></div> <Editor v-else v-model="form.meetingSummary" height="500px" /> </el-form-item> </el-col> </el-row> </el-form> </div> </template> <script setup name="MeetingInfo"> import { listToTree } from '@/utils/tree' import { getAllNodeTree } from '@/api/okr/okr' import * as MeetingApi from '@/api/okr/meeting' import { formatDate } from '@/utils/formatTime' import { getEmployeeSimpleList } from '@/api/pers/employee' import { useTagsViewStore } from '@/store/modules/tagsView' const route = useRoute() const message = useMessage() const tagsViewStore = useTagsViewStore() const defaultProps = { value: 'nodeId', label: 'nodeName', children: 'children' } const isDetail = route.query.isDetail onMounted(async () => { await getOptions() if (route.params.id && route.params.id != 0) { // 这里可以调用API获取会议详情数据 getMeetingInfo(route.params.id) } else { console.error('会议不存在') } }) const peroidList = ref([]) function getOptions() { return Promise.all([getAllNodeTree(), getEmployeeSimpleList()]) .then(([okrResp, employeeResp]) => { peroidList.value = listToTree(okrResp?.tree || [], { id: 'nodeId', pid: 'parentId', children: 'children' }) userOptions.value = employeeResp.map((it) => ({ ...it, id: it.id + '' })) // handleUserChange() }) .catch((error) => { console.error('获取数据失败:', error) }) // // 获取OKR节点数据 // getAllNodeTree().then((resp) => { // peroidList.value = listToTree(resp?.tree || [], { // id: 'nodeId', // pid: 'parentId', // children: 'children' // }) // }) // // 获取人员数据 // getEmployeeSimpleList().then((data) => { // userOptions.value = data.map((it) => ({ ...it, id: it.id + '' })) // }) } const form = ref({ meetingId: undefined, meetingSubject: '', startTime: '', meetingRoom: '', expectEndTime: '', expectUsers: [], actualUsers: [], okrNodeName: '', status: '1', meetingContent: '', meetingSummary: '', absentReason: '' }) const rules = { meetingSubject: [{ required: true, message: '请输入会议主题', trigger: 'blur' }], startTime: [{ required: true, message: '请选择会议开始时间', trigger: 'change' }], expectEndTime: [{ required: true, message: '请选择预计结束时间', trigger: 'change' }], meetingRoom: [{ required: true, message: '请输入会议地点', trigger: 'blur' }], expectUsers: [{ required: true, message: '请选择参会人员', trigger: 'change' }] } const formRef = ref(null) const userOptions = ref([]) const expectUserOptions = ref([]) const isAllActived = computed(() => { // 判断实际参会人员是否包含所有预约参会人员 return form.value.expectUsers.every((item) => form.value.actualUsers.includes(item)) }) const loading = ref(false) // 获取详情 const getMeetingInfo = async (meetingId) => { try { loading.value = true // 调用API获取会议详情 const resp = await MeetingApi.getMeetingDetail({ meetingId }) loading.value = false if (resp) { form.value = { ...form.value, ...resp, startTime: formatDate(resp.startTime, 'YYYY-MM-DD HH:mm'), expectEndTime: formatDate(resp.expectEndTime, 'YYYY-MM-DD HH:mm'), expectUsers: resp.expectUsers || [], actualUsers: resp.actualUsers || [] } handleUserChange() } } catch (error) { loading.value = false console.error('获取会议详情失败:', error) } } function handleUserChange() { // 当预约参会人员变化时,更新实际参会人员选项 expectUserOptions.value = userOptions.value.filter((user) => form.value.expectUsers.some((it) => it == user.id) ) form.value.actualUsers = [...form.value.expectUsers] } const router = useRouter() async function submit() { // 校验表单 if (!formRef.value) return const valid = await formRef.value.validate() if (!valid) return try { // 提交表单数据 if (form.value.meetingId) { if (form.value.status == 2 && !form.value.meetingSummary) { message.error('会议结束时,会议纪要不能为空') return } // 更新会议 await MeetingApi.updateMeeting(form.value) message.success('会议更新成功') } else { if (form.value.status == 1 && !form.value.meetingContent) { message.error('预约会议时,会议内容不能为空') return } form.value.actualUsers = [] // 新增会议 await MeetingApi.createMeeting(form.value) message.success('会议创建成功') } tagsViewStore.delView(route) const visitedViews = tagsViewStore.getVisitedViews const latestView = visitedViews.slice(-1)[0] router.push(latestView) } catch (error) { console.error('保存会议数据失败:', error) } } </script> <style lang="scss" scoped></style>