huminmin
2026-06-01 a563ea879ef5fb6897e76d2df661e465dce2ab9b
src/views/collaborativeApproval/notificationManagement/meetDraft/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,495 @@
<template>
  <div>
    <!-- é¡µé¢æ ‡é¢˜ -->
    <div class="page-header">
      <h2>会议草稿</h2>
      <el-button type="primary" @click="handleAdd">
        <el-icon><Plus /></el-icon>
        æ–°å»ºè‰ç¨¿
      </el-button>
    </div>
    <!-- æœç´¢åŒºåŸŸ -->
    <el-card class="search-card">
      <el-form :model="searchForm" label-width="100px" inline>
        <el-form-item label="会议主题">
          <el-input v-model="searchForm.title" placeholder="请输入会议主题" clearable />
        </el-form-item>
        <el-form-item label="会议日期">
          <el-date-picker
            v-model="searchForm.meetingDate"
            type="date"
            placeholder="请选择会议日期"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            style="width: 100%"
          />
        </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="draftList" border>
        <el-table-column prop="title" label="会议主题" align="center" min-width="200" show-overflow-tooltip />
        <el-table-column prop="room" 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="participants" label="参会人数" align="center" width="100">
          <template #default="scope">
            {{ scope.row.participants }}人
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="创建时间" align="center" width="180" />
        <el-table-column label="操作" align="center" width="200" fixed="right">
          <template #default="scope">
            <el-button type="primary" link @click="viewDraft(scope.row)">查看</el-button>
            <el-button type="primary" link @click="editDraft(scope.row)">编辑</el-button>
            <el-button type="danger" link @click="deleteDraft(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="currentDraft">
        <el-descriptions :column="2" border>
          <el-descriptions-item label="会议主题">{{ currentDraft.title }}</el-descriptions-item>
          <el-descriptions-item label="会议编号">{{ currentDraft.meetingId }}</el-descriptions-item>
          <el-descriptions-item label="会议室">{{ currentDraft.room }}</el-descriptions-item>
          <el-descriptions-item label="主持人">{{ currentDraft.host }}</el-descriptions-item>
          <el-descriptions-item label="会议时间" :span="2">
            {{ formatDateTime(currentDraft.meetingTime) }}
          </el-descriptions-item>
          <el-descriptions-item label="创建时间">{{ currentDraft.createTime }}</el-descriptions-item>
        </el-descriptions>
        <div class="content-section mt-20">
          <h4>参会人员</h4>
          <div class="participants-list">
            {{ currentDraft.participantList }}
          </div>
        </div>
        <div class="content-section mt-20">
          <h4>会议说明</h4>
          <div class="meeting-description">{{ currentDraft.description }}</div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="detailDialogVisible = false">关 é—­</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- æ–°å»º/编辑草稿对话框 -->
    <el-dialog
      :title="dialogTitle"
      v-model="editDialogVisible"
      width="700px"
    >
      <el-form :model="meetingForm" :rules="rules" ref="meetingFormRef" label-width="100px">
        <el-form-item label="会议主题" prop="title">
          <el-input v-model="meetingForm.title" placeholder="请输入会议主题" />
        </el-form-item>
        <el-form-item label="会议室" prop="room">
          <el-select v-model="meetingForm.roomId" placeholder="请选择会议室" style="width: 100%">
            <el-option v-for="(v,k) in roomList" :label="v.name" :value="v.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="主持人" prop="host">
          <el-input v-model="meetingForm.host" placeholder="请输入主持人" />
        </el-form-item>
        <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>
          </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 timeOptions"
                  :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 timeOptions"
                  :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-input
              v-model="meetingForm.participants"
              type="number"
              placeholder="请输入参会人数"
          />
        </el-form-item>
        <el-form-item label="参会人员" prop="participants">
          <el-input
            v-model="meetingForm.participantList"
            type="textarea"
            :rows="3"
            placeholder="请输入参会人员,用逗号分隔"
          />
        </el-form-item>
        <el-form-item label="会议说明">
          <el-input
            v-model="meetingForm.description"
            type="textarea"
            :rows="4"
            placeholder="请输入会议说明"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="editDialogVisible = false">取 æ¶ˆ</el-button>
          <el-button type="primary" @click="submitForm">保 å­˜</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import Pagination from '@/components/Pagination/index.vue'
import {getRoomEnum,getDraftList,saveDraft,delDraft} from '@/api/collaborativeApproval/meeting.js'
import dayjs from "dayjs";
// æ•°æ®åˆ—表加载状态
const loading = ref(false)
// æ€»æ¡æ•°
const total = ref(0)
// è‰ç¨¿åˆ—表数据
const draftList = ref([])
// æŸ¥è¯¢å‚æ•°
const queryParams = reactive({
  current: 1,
  size: 10
})
// æœç´¢è¡¨å•
const searchForm = reactive({
  title: '',
  meetingDate: ''
})
// æ˜¯å¦æ˜¾ç¤ºå¯¹è¯æ¡†
const detailDialogVisible = ref(false)
const editDialogVisible = ref(false)
const roomList = ref([])
// å¯¹è¯æ¡†æ ‡é¢˜
const dialogTitle = ref('')
// å½“前查看的草稿
const currentDraft = ref(null)
// è¡¨å•引用
const meetingFormRef = ref(null)
// æ—¶é—´é€‰é¡¹ï¼ˆä»¥åŠå°æ—¶ä¸ºé—´éš”,工作时间8:00-18:00)
const timeOptions = ref([])
// è¡¨å•数据
const meetingForm = reactive({
  id: '',
  meetingId: '',
  title: '',
  roomId: '',
  host: '',
  meetingDate: '',
  startTime: '',
  endTime: '',
  participants: 0,
  participantList: '',
  description: '',
  createTime: ''
})
// è¡¨å•校验规则
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' }],
  endTime: [{ required: true, message: '请选择结束时间', trigger: 'change' }]
}
// åˆå§‹åŒ–时间选项(以半小时为间隔,工作时间8:00-18:00)
const initTimeOptions = () => {
  const options = []
  for (let hour = 8; hour <= 18; hour++) {
    // æ¯ä¸ªå°æ—¶æ·»åŠ ä¸¤ä¸ªé€‰é¡¹ï¼šæ•´ç‚¹å’ŒåŠç‚¹
    options.push({
      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
}
// ç¦ç”¨æ—¥æœŸï¼ˆç¦ç”¨ä»Šå¤©ä¹‹å‰çš„æ—¥æœŸï¼‰
const disabledDate = (time) => {
  // ç¦ç”¨ä»Šå¤©ä¹‹å‰çš„æ—¥æœŸ
  return time.getTime() < Date.now() - 86400000
}
// æŸ¥è¯¢æ•°æ®
const getList = async () => {
  loading.value = true
  let resp = await getDraftList({...queryParams,...searchForm})
  queryParams.current = resp.data.current
  draftList.value = resp.data.records.map(it=>{
    it.room = roomList.value.find(room=>it.roomId===room.id).name ?? ""
    it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format("HH:mm")} ~ ${dayjs(it.endTime).format("HH:mm")}`
    return it
  })
  loading.value = false
}
// æœç´¢æŒ‰é’®æ“ä½œ
const handleSearch = () => {
  queryParams.pageNum = 1
  getList()
}
// é‡ç½®æœç´¢è¡¨å•
const resetSearch = () => {
  Object.assign(searchForm, {
    title: '',
    createTime: []
  })
  handleSearch()
}
// æ·»åŠ æŒ‰é’®æ“ä½œ
const handleAdd = () => {
  dialogTitle.value = '新建草稿'
  resetForm()
  editDialogVisible.value = true
}
// æŸ¥çœ‹è‰ç¨¿è¯¦æƒ…
const viewDraft = (row) => {
  currentDraft.value = row
  detailDialogVisible.value = true
}
// ç¼–辑草稿
const editDraft = (row) => {
  dialogTitle.value = '编辑草稿'
  Object.assign(meetingForm, {
    id: row.id,
    meetingId: row.meetingId,
    title: row.title,
    room: row.room,
    roomId: row.id,
    host: row.host,
    meetingDate: row.meetingTime.split(' ')[0],
    startTime: row.meetingTime.split(' ')[1],
    endTime: row.meetingTime.split(' ')[3],
    participants: row.participants,
    participantList: row.participantList,
    description: row.description,
    createTime: row.createTime
  })
  editDialogVisible.value = true
}
// åˆ é™¤è‰ç¨¿
const deleteDraft = (row) => {
  ElMessageBox.confirm(
    `确认删除会议草稿 "${row.title}"?`,
    '删除草稿',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    delDraft(row.id).then(resp=>{
      ElMessage.success('草稿删除成功')
      getList()
    })
  }).catch(() => {})
}
// é‡ç½®è¡¨å•
const resetForm = () => {
  Object.assign(meetingForm, {
    id: '',
    meetingId: '',
    title: '',
    room: '',
    host: '',
    meetingDate: '',
    startTime: '',
    endTime: '',
    participants: 0,
    participantList: '',
    description: '',
    createTime: ''
  })
}
// æäº¤è¡¨å•
const submitForm = () => {
  meetingFormRef.value.validate((valid) => {
    if (valid) {
      let formData = {...meetingForm}
      formData.startTime = dayjs(meetingForm.meetingDate + ' ' + meetingForm.startTime).format("YYYY-MM-DD HH:mm:ss")
      formData.endTime = dayjs(meetingForm.meetingDate + ' ' + meetingForm.endTime).format("YYYY-MM-DD HH:mm:ss")
      saveDraft(formData).then(()=>{
        ElMessage.success('保存成功')
        editDialogVisible.value = false
        getList()
      })
    }
  })
}
// æ ¼å¼åŒ–日期时间
const formatDateTime = (dateTime) => {
  if (!dateTime) return ''
  return dateTime.replace(' ', '\n')
}
// é¡µé¢åŠ è½½æ—¶èŽ·å–æ•°æ®
onMounted(() => {
  initTimeOptions()
  getList()
  getRoomEnum().then((res) => {
    roomList.value = res.data
  })
})
</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;
}
.meeting-description {
  padding: 15px;
  border-radius: 4px;
  line-height: 1.6;
  white-space: pre-wrap;
}
</style>