From 42a1a434f77154746038c476ef70ca9be0b8e4e0 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期一, 19 一月 2026 18:02:46 +0800
Subject: [PATCH] fix: 完成资金管理,财务对账

---
 src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue |  363 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 363 insertions(+), 0 deletions(-)

diff --git a/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue b/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue
new file mode 100644
index 0000000..9b5325f
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/meetIndex/index.vue
@@ -0,0 +1,363 @@
+<template>
+  <div>
+    <el-form :model="queryForm" label-width="80px" inline>
+        <el-form-item label="鏌ヨ鏃ユ湡">
+          <el-date-picker
+              v-model="queryForm.meetingDate"
+              type="date"
+              placeholder="璇烽�夋嫨鏃ユ湡"
+              value-format="YYYY-MM-DD"
+              format="YYYY-MM-DD"
+              :clearable="false"
+          />
+        </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 class="table-container" :loading="loading">
+      <div class="time-table">
+        <!-- 琛ㄥご -->
+        <div class="table-header">
+          <div class="header-cell room-header">浼氳瀹�</div>
+          <div
+              v-for="timeSlot in timeSlots"
+              :key="timeSlot.value"
+              class="header-cell time-header"
+          >
+            {{ timeSlot.label }}
+          </div>
+        </div>
+
+        <!-- 琛ㄦ牸鍐呭 -->
+        <div class="table-body">
+          <div
+              v-for="room in roomUsage"
+              :key="room.id"
+              class="table-row"
+          >
+            <div class="cell room-cell">{{ room.name }}</div>
+            <div class="cells-container">
+              <template v-for="(cell, index) in generateMeetingCells(room)" :key="index">
+                <div
+                    class="cell content-cell"
+                    :class="[cell.type, `status-${cell.meeting?.status || '0'}`]"
+                    :style="{ flex: cell.span-0.2 }"
+                    @click="viewMeetingDetails(cell)"
+                >
+                  <div v-if="cell.type === 'meeting'" class="meeting-content">
+                    <div class="meeting-title">{{ cell.meeting.title }}</div>
+                    <div class="meeting-time">{{ cell.startTime }}-{{ cell.endTime }}</div>
+                  </div>
+                  <div v-else class="free-content">
+                    绌洪棽
+                  </div>
+                </div>
+              </template>
+            </div>
+          </div>
+        </div>
+      </div>
+    </el-card>
+
+    <!-- 浼氳璇︽儏瀵硅瘽妗� -->
+    <el-dialog
+        title="浼氳璇︽儏"
+        v-model="detailDialogVisible"
+        width="800px"
+    >
+      <div v-if="currentMeeting">
+        <el-descriptions :column="1" border>
+          <el-descriptions-item label="浼氳涓婚">{{ currentMeeting.title }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳瀹�">{{ currentMeeting.room }}</el-descriptions-item>
+          <el-descriptions-item label="浼氳鏃堕棿">{{ currentMeeting.time }}</el-descriptions-item>
+          <el-descriptions-item label="涓绘寔浜�">{{ currentMeeting.host }}</el-descriptions-item>
+          <el-descriptions-item label="鍙備細浜烘暟">{{ currentMeeting.participants }}浜�</el-descriptions-item>
+          <el-descriptions-item label="浼氳璇存槑">{{ currentMeeting.description }}</el-descriptions-item>
+        </el-descriptions>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="detailDialogVisible = false">鍏� 闂�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref, reactive, onMounted} from 'vue'
+import {ElMessage} from 'element-plus'
+import {getMeetingUseList} from "@/api/collaborativeApproval/meeting.js"
+import dayjs from "dayjs";
+
+// 鏌ヨ琛ㄥ崟
+const queryForm = reactive({
+  meetingDate: dayjs().format('YYYY-MM-DD')
+})
+let loading = ref(false)
+// 鏃堕棿娈碉紙浠ュ崐灏忔椂涓洪棿闅旓級
+const timeSlots = ref([])
+
+// 浼氳瀹や娇鐢ㄦ儏鍐�
+const roomUsage = ref([])
+
+// 褰撳墠鏌ョ湅鐨勪細璁�
+const currentMeeting = ref(null)
+
+// 鏄惁鏄剧ず璇︽儏瀵硅瘽妗�
+const detailDialogVisible = ref(false)
+
+// 鍒濆鍖栨椂闂存Ы锛堜互鍗婂皬鏃朵负闂撮殧锛屼粠8:00鍒�18:00锛�
+const initTimeSlots = () => {
+  const slots = []
+  for (let hour = 8; hour < 18; hour++) {
+    // 姣忎釜灏忔椂娣诲姞涓や釜鏃堕棿娈碉細鏁寸偣鍜屽崐鐐�
+    slots.push({
+      label: `${hour.toString().padStart(2, '0')}:00`,
+      value: `${hour.toString().padStart(2, '0')}:00`
+    })
+
+    if (hour < 18) { // 鍒�17:30涓烘
+      slots.push({
+        label: `${hour.toString().padStart(2, '0')}:30`,
+        value: `${hour.toString().padStart(2, '0')}:30`
+      })
+    }
+  }
+  timeSlots.value = slots
+}
+
+// 鐢熸垚浼氳瀹ょ殑鏃堕棿鍗曞厓鏍�
+const generateMeetingCells = (room) => {
+  const cells = []
+  const meetings = room.meetings || []
+  const occupiedSlots = new Set()
+
+  // 澶勭悊姣忎釜浼氳
+  for (const meeting of meetings) {
+
+    const startIdx = timeSlots.value.findIndex(slot => slot.value === meeting.startTime)
+    let endIdx = timeSlots.value.findIndex(slot => slot.value === meeting.endTime)
+    if (endIdx === -1) {
+      endIdx = timeSlots.value.length
+    }
+    console.log('endIdx111', endIdx)
+    if (startIdx !== -1 && endIdx !== -1) {
+      // 鏍囪琚崰鐢ㄧ殑鏃堕棿娈�
+      for (let i = startIdx; i < endIdx; i++) {
+        occupiedSlots.add(timeSlots.value[i].value)
+      }
+
+      // 鍒涘缓浼氳鍗曞厓鏍�
+      cells.push({
+        type: 'meeting',
+        meeting: meeting,
+        span: endIdx - startIdx,
+        startTime: meeting.startTime,
+        endTime: meeting.endTime
+      })
+    }
+  }
+
+  // 澶勭悊绌洪棽鏃堕棿娈�
+  for (let i = 0; i < timeSlots.value.length; i++) {
+    const slot = timeSlots.value[i]
+    if (!occupiedSlots.has(slot.value)) {
+      // 鏌ユ壘杩炵画鐨勭┖闂叉椂闂存
+      let span = 1
+      while (i + span < timeSlots.value.length &&
+      !occupiedSlots.has(timeSlots.value[i + span].value)) {
+        occupiedSlots.add(timeSlots.value[i + span].value)
+        span++
+      }
+
+      cells.push({
+        type: 'free',
+        span: span,
+        time: slot.value
+      })
+    }
+  }
+
+  // 鎸夋椂闂存帓搴�
+  cells.sort((a, b) => {
+    const timeA = a.startTime || a.time
+    const timeB = b.startTime || b.time
+    return timeSlots.value.findIndex(s => s.value === timeA) -
+        timeSlots.value.findIndex(s => s.value === timeB)
+  })
+  console.log('cells', cells)
+  return cells
+}
+
+// 鏌ョ湅浼氳璇︽儏
+const viewMeetingDetails = (cell) => {
+  if (cell && cell.type === 'meeting') {
+    currentMeeting.value = cell.meeting
+    detailDialogVisible.value = true
+  } else {
+    ElMessage.info('璇ユ椂闂存浼氳瀹ょ┖闂�')
+  }
+}
+
+// 鏌ヨ鎸夐挳鎿嶄綔
+const handleSearch = async () => {
+  loading.value = true
+  let resp = await getMeetingUseList({...queryForm})
+  roomUsage.value = resp.data
+  loading.value = false
+}
+
+// 閲嶇疆鎼滅储琛ㄥ崟
+const resetSearch = () => {
+  queryForm.date = dayjs().format('YYYY-MM-DD')
+}
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栨暟鎹�
+onMounted(() => {
+  // 鍒濆鍖栨椂闂存Ы
+  initTimeSlots()
+
+  // 榛樿鏌ヨ浠婂ぉ鐨勬暟鎹�
+  const today = new Date()
+  queryForm.date = today.toISOString().split('T')[0]
+  handleSearch()
+})
+</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;
+}
+
+.table-container {
+  padding: 0;
+}
+
+.time-table {
+  width: 100%;
+  border-collapse: collapse;
+}
+
+.table-header {
+  display: flex;
+  border: 1px solid;
+}
+
+.table-row {
+  display: flex;
+  border: 1px solid #ebeef5;
+  border-top: none;
+}
+
+.header-cell {
+  padding: 12px 5px;
+  text-align: center;
+  font-weight: bold;
+  border-right: 1px solid;
+  min-height: 20px;
+}
+
+.room-header {
+  width: 120px;
+}
+
+.time-header {
+  flex: 1;
+}
+
+.cell {
+  padding: 15px 5px;
+  text-align: center;
+  border-right: 1px solid;
+  min-height: 20px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  word-break: break-word;
+  line-height: 1.2;
+}
+
+.room-cell {
+  width: 120px;
+  font-weight: bold;
+}
+
+.cells-container {
+  flex: 1;
+  display: flex;
+}
+
+.content-cell {
+  min-height: 60px;
+  cursor: pointer;
+  transition: all 0.3s;
+}
+
+.content-cell:hover {
+  opacity: 0.8;
+}
+
+.free {
+  color: #f56c6c;
+}
+
+.meeting {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+
+.status-1 {
+  background-color: #fef0f0;
+  color: #d14646;
+}
+
+.status-0 {
+  background-color: #c7ddc8;
+  color: rgba(230, 162, 60, 0.29);
+}
+
+.meeting-content {
+  width: 100%;
+}
+
+.meeting-title {
+  font-weight: bold;
+  margin-bottom: 5px;
+}
+
+.meeting-time {
+  font-size: 12px;
+}
+
+.free-content {
+  color: #909399;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+</style>

--
Gitblit v1.9.3