|
@@ -1,6 +1,5 @@
|
|
|
<template>
|
|
|
<div class="app-container">
|
|
|
- <!-- 搜索栏 -->
|
|
|
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
|
|
<el-form-item label="状态" prop="status">
|
|
|
<el-radio-group v-model="queryParams.status">
|
|
@@ -46,320 +45,219 @@
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
|
|
|
- <!-- 状态筛选 -->
|
|
|
- <div class="status-filter">
|
|
|
- <el-tag type="success" size="small">可用</el-tag>
|
|
|
- <el-tag type="warning" size="small">占用</el-tag>
|
|
|
- <el-tag type="info" size="small">禁用</el-tag>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 会议室列表 -->
|
|
|
- <div class="meeting-list">
|
|
|
- <div v-for="meeting in waringList" :key="meeting.id" class="meeting-card">
|
|
|
- <div class="card-header">
|
|
|
- <img :src="getImageUrl(meeting.images)" alt="会议室图片" class="meeting-image"/>
|
|
|
- <div class="meeting-info">
|
|
|
- <h3>{{ meeting.name }}</h3>
|
|
|
- <p>
|
|
|
- {{ meeting.seats === 0 ? '无限制' : meeting.seats }}人 |
|
|
|
- {{ meeting.room_type_name[0] }}
|
|
|
- </p>
|
|
|
- <div v-if="meeting.device_name_arr.length > 0">
|
|
|
- <el-tag v-for="device in meeting.device_name_arr" :key="device" size="small">{{ device }}</el-tag>
|
|
|
- </div>
|
|
|
- <div v-else>暂无设备信息</div>
|
|
|
- <p></p>
|
|
|
- <div v-if="meeting.usage && meeting.usage.appointTime && meeting.usage.appointTime.length > 0">
|
|
|
- 已预订时间段:
|
|
|
- <span v-for="(appointment, index) in [...meeting.usage.appointTime].reverse()">
|
|
|
- {{ appointment.start_time }} - {{ appointment.end_time }}<span v-if="index < meeting.usage.appointTime.length - 1"> | </span>
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- <div v-else>
|
|
|
- <span>暂无预订时间段</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <!-- <el-button type="primary" size="small" @click="handleReserve(meeting)">预定</el-button>-->
|
|
|
- </div>
|
|
|
- <div class="time-slots">
|
|
|
- <div class="slot-container">
|
|
|
- <div v-for="(slot, index) in timeSlots" :key="index"
|
|
|
- :class="['slot', {
|
|
|
- current: isCurrent(slot),
|
|
|
- booked: isBookedBetween(meeting, slot, timeSlots[index+1])
|
|
|
- }]">
|
|
|
- {{ slot }}
|
|
|
- </div>
|
|
|
+ <el-row :gutter="10" class="mb8">
|
|
|
+
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-table v-loading="loading" :data="waringList" @selection-change="handleSelectionChange">
|
|
|
+ <el-table-column label="会议名称" align="center" prop="name" />
|
|
|
+ <el-table-column label="会议类型" align="center" prop="room_type_name" />
|
|
|
+ <el-table-column label="容纳人数" align="center" prop="seats">
|
|
|
+ <template #default="scope">
|
|
|
+ <span>{{ scope.row.seats === 0 ? '无限制' : scope.row.seats }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="预定时间段" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <div v-if="scope.row.usage.appointTime.length > 0">
|
|
|
+ <span v-for="(time, index) in scope.row.usage.appointTime" :key="index">
|
|
|
+ {{ time.start_time }} - {{ time.end_time }}
|
|
|
+ <br v-if="index < scope.row.usage.appointTime.length - 1" />
|
|
|
+ </span>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <span v-else>无预定</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="设备" align="center" prop="device_names" />
|
|
|
+ <el-table-column label="创建时间" align="center" prop="created_at" width="180">
|
|
|
+ <template #default="scope">
|
|
|
+ <span>{{ parseTime(scope.row.created_at, '{y}-{m}-{d} {h}:{i}') }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <pagination
|
|
|
+ v-show="total>0"
|
|
|
+ :total="total"
|
|
|
+ v-model:page="queryParams.pageNum"
|
|
|
+ v-model:limit="queryParams.pageSize"
|
|
|
+ @pagination="getList"
|
|
|
+ />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup name="Waring">
|
|
|
-import {listMeeting} from "@/api/meeting/meeting";
|
|
|
-import {ElMessage} from "element-plus";
|
|
|
-import {ref, reactive, toRefs, onMounted, nextTick} from 'vue';
|
|
|
+import { listMeeting } from "@/api/meeting/meeting";
|
|
|
+import { ElMessage } from "element-plus";
|
|
|
+
|
|
|
+const { proxy } = getCurrentInstance();
|
|
|
+const {alarm_level} = proxy.useDict('alarm_level');
|
|
|
|
|
|
const waringList = ref([]);
|
|
|
+const open = ref(false);
|
|
|
const loading = ref(true);
|
|
|
const showSearch = ref(true);
|
|
|
+const ids = ref([]);
|
|
|
+const single = ref(true);
|
|
|
+const multiple = ref(true);
|
|
|
const total = ref(0);
|
|
|
-const url_str = "";
|
|
|
+const title = ref("");
|
|
|
|
|
|
-// 获取当前时间
|
|
|
-const currentTime = getCurrentHour(); // 当前整点时间
|
|
|
const data = reactive({
|
|
|
form: {},
|
|
|
queryParams: {
|
|
|
pageNum: 1,
|
|
|
- pageSize: 10000,
|
|
|
+ pageSize: 10,
|
|
|
status: '', // 默认选中"全部"
|
|
|
date: new Date().toISOString().split('T')[0], // 格式化为YYYY-MM-DD
|
|
|
appoint_time: "", // 重置为空
|
|
|
start_time: "",
|
|
|
end_time: "",
|
|
|
- interfaceName:"会议",
|
|
|
+ interfaceName:"会议预订",
|
|
|
search: '' // 搜索文本默认为空
|
|
|
},
|
|
|
- timeSlots: generateTimeSlots(), // 动态生成时间轴
|
|
|
-});
|
|
|
|
|
|
-const {queryParams, timeSlots} = toRefs(data);
|
|
|
+});
|
|
|
|
|
|
-// 动态生成时间轴,从 00:00 到 23:00
|
|
|
-function generateTimeSlots() {
|
|
|
- const slots = [];
|
|
|
- for (let i = 0; i <= 23; i++) {
|
|
|
- slots.push(`${i.toString().padStart(2, '0')}:00`);
|
|
|
+const { queryParams, form, rules } = toRefs(data);
|
|
|
+watch(() => queryParams.value.status, (newStatus) => {
|
|
|
+ if(newStatus === "1") { // 当前可用
|
|
|
+ queryParams.value.appoint_time = getCurrentTimeRange();
|
|
|
+ } else if(newStatus === "2") { // 一小时后可用
|
|
|
+ queryParams.value.appoint_time = getCurrentTimeRange(1, true);
|
|
|
+ } else {
|
|
|
+ queryParams.value.appoint_time = ""; // 选择"全部"时清空
|
|
|
}
|
|
|
- return slots;
|
|
|
-}
|
|
|
-
|
|
|
-// 获取当前整点时间
|
|
|
-function getCurrentHour() {
|
|
|
- const now = new Date();
|
|
|
- const hour = now.getHours();
|
|
|
- return `${hour.toString().padStart(2, '0')}:00`;
|
|
|
-}
|
|
|
-
|
|
|
-// 获取会议室列表
|
|
|
-function getList() {
|
|
|
- loading.value = true;
|
|
|
- listMeeting(queryParams.value).then(response => {
|
|
|
- console.log(response);
|
|
|
- waringList.value = response.data.list;
|
|
|
- total.value = response.data.total;
|
|
|
- loading.value = false;
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-// 更新预约时间
|
|
|
+});
|
|
|
function updateAppointTime() {
|
|
|
- if (queryParams.value.start_time && queryParams.value.end_time) {
|
|
|
+ if(queryParams.value.start_time && queryParams.value.end_time) {
|
|
|
queryParams.value.appoint_time = `${queryParams.value.start_time}~${queryParams.value.end_time}`;
|
|
|
}
|
|
|
}
|
|
|
+/** 查询设备告警列表 */
|
|
|
+const getList = async () => {
|
|
|
+ try {
|
|
|
+ loading.value = true;
|
|
|
+ listMeeting(queryParams.value).then(response => {
|
|
|
+ waringList.value = response.data.list;
|
|
|
+ total.value = response.data.total;
|
|
|
+ loading.value = false;
|
|
|
+ });
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取数据失败:', error);
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
-// 判断某个时间段区间是否被预订
|
|
|
-function isBookedBetween(meeting, startTime, endTime) {
|
|
|
- if (!endTime) endTime = '24:00'; // 处理最后一个时间段
|
|
|
|
|
|
- const appointments = meeting.usage?.appointTime || [];
|
|
|
- return appointments.some(appointment => {
|
|
|
- return (
|
|
|
- (appointment.start_time < endTime) &&
|
|
|
- (appointment.end_time > startTime)
|
|
|
- );
|
|
|
- });
|
|
|
+// 表单重置
|
|
|
+function reset() {
|
|
|
+ form.value = {
|
|
|
+ status: '', // 默认选中"全部"
|
|
|
+ date: new Date(), // 默认当天
|
|
|
+ appoint_time: '', // 时间默认为空
|
|
|
+ search: '' // 搜索文本默认为空
|
|
|
+ };
|
|
|
+ proxy.resetForm("waringRef");
|
|
|
}
|
|
|
+function getCurrentTimeRange(hoursLater = 0, fullHour = false) {
|
|
|
+ const now = new Date();
|
|
|
+ now.setHours(now.getHours() + hoursLater);
|
|
|
+
|
|
|
+ const startHours = now.getHours().toString().padStart(2, '0');
|
|
|
+ const startMinutes = now.getMinutes().toString().padStart(2, '0');
|
|
|
+
|
|
|
+ let endHours, endMinutes;
|
|
|
+ if(fullHour) {
|
|
|
+ // 计算一小时后的时间
|
|
|
+ const endTime = new Date(now.getTime() + 60 * 60 * 1000);
|
|
|
+ endHours = endTime.getHours().toString().padStart(2, '0');
|
|
|
+ endMinutes = endTime.getMinutes().toString().padStart(2, '0');
|
|
|
+ } else {
|
|
|
+ // 只增加一分钟
|
|
|
+ endHours = startHours;
|
|
|
+ endMinutes = (now.getMinutes() + 1).toString().padStart(2, '0');
|
|
|
+ }
|
|
|
|
|
|
-// 搜索按钮操作
|
|
|
+ return `${startHours}:${startMinutes}~${endHours}:${endMinutes}`;
|
|
|
+}
|
|
|
+
|
|
|
+/** 搜索按钮操作 */
|
|
|
function handleQuery() {
|
|
|
queryParams.value.pageNum = 1;
|
|
|
getList();
|
|
|
}
|
|
|
|
|
|
-// 重置按钮操作
|
|
|
+/** 重置按钮操作 */
|
|
|
function resetQuery() {
|
|
|
- queryParams.value = {
|
|
|
- pageNum: 1,
|
|
|
- pageSize: 10000,
|
|
|
- status: '',
|
|
|
- date: new Date().toISOString().split('T')[0],
|
|
|
- appoint_time: "",
|
|
|
- interfaceName:"会议",
|
|
|
- start_time: "",
|
|
|
- end_time: "",
|
|
|
- search: ''
|
|
|
- };
|
|
|
+ proxy.resetForm("queryRef");
|
|
|
handleQuery();
|
|
|
}
|
|
|
|
|
|
-// 判断某个时间段是否被预订
|
|
|
-function isBooked(meeting, timeSlot) {
|
|
|
- const appointments = meeting.usage?.appointTime || [];
|
|
|
- return appointments.some(appointment => {
|
|
|
- return appointment.start_time <= timeSlot && appointment.end_time >= timeSlot;
|
|
|
- });
|
|
|
+// 多选框选中数据
|
|
|
+function handleSelectionChange(selection) {
|
|
|
+ ids.value = selection.map(item => item.id);
|
|
|
+ single.value = selection.length != 1;
|
|
|
+ multiple.value = !selection.length;
|
|
|
}
|
|
|
|
|
|
-// 判断是否是当前时间
|
|
|
-function isCurrent(timeSlot) {
|
|
|
- return timeSlot === currentTime;
|
|
|
+/** 新增按钮操作 */
|
|
|
+function handleAdd() {
|
|
|
+ reset();
|
|
|
+ open.value = true;
|
|
|
+ title.value = "添加设备告警";
|
|
|
}
|
|
|
|
|
|
-// 预定按钮操作
|
|
|
-function handleReserve(meeting) {
|
|
|
- proxy.$modal.confirm('是否确认预定会议室 "' + meeting.name + '"?').then(() => {
|
|
|
- // 这里可以添加预定逻辑
|
|
|
- ElMessage.success('预定成功');
|
|
|
- }).catch(() => {
|
|
|
+/** 修改按钮操作 */
|
|
|
+function handleUpdate(row) {
|
|
|
+ reset();
|
|
|
+ const _id = row.id || ids.value
|
|
|
+ getWaring(_id).then(response => {
|
|
|
+ form.value = response.data;
|
|
|
+ open.value = true;
|
|
|
+ title.value = "修改设备告警";
|
|
|
});
|
|
|
}
|
|
|
|
|
|
-// 处理图片URL
|
|
|
-function getImageUrl(url) {
|
|
|
- if (!url || url.length === 0) {
|
|
|
- return 'http://183.129.224.253:9998/assets/defRoomIng.3e28e55b.png';
|
|
|
- }
|
|
|
- return `http://183.129.224.253:9998${url}`;
|
|
|
-}
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- getList();
|
|
|
-
|
|
|
- const checkReady = () => {
|
|
|
- if (waringList.value.length > 0) {
|
|
|
- // 添加双重延迟确保DOM完全渲染
|
|
|
- setTimeout(() => {
|
|
|
- scrollToCurrentTime();
|
|
|
- // 二次检查确保滚动执行
|
|
|
- //setTimeout(scrollToCurrentTime, 300);
|
|
|
- }, 100);
|
|
|
- } else {
|
|
|
- setTimeout(checkReady, 200);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- checkReady();
|
|
|
-});
|
|
|
-
|
|
|
-// 滚动到当前时间
|
|
|
-function scrollToCurrentTime() {
|
|
|
- const currentSlots = document.querySelectorAll('.slot.current');
|
|
|
- currentSlots.forEach(slot => {
|
|
|
- const container = slot.closest('.time-slots');
|
|
|
- if (container) {
|
|
|
- const slotRect = slot.getBoundingClientRect();
|
|
|
- const containerRect = container.getBoundingClientRect();
|
|
|
- container.scrollLeft = slotRect.left - containerRect.left;// - (container.clientWidth) + (slotRect.width);
|
|
|
+/** 提交按钮 */
|
|
|
+function submitForm() {
|
|
|
+ proxy.$refs["waringRef"].validate(valid => {
|
|
|
+ if (valid) {
|
|
|
+ if (form.value.id != null) {
|
|
|
+ updateWaring(form.value).then(response => {
|
|
|
+ proxy.$modal.msgSuccess("修改成功");
|
|
|
+ open.value = false;
|
|
|
+ getList();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ addWaring(form.value).then(response => {
|
|
|
+ proxy.$modal.msgSuccess("新增成功");
|
|
|
+ open.value = false;
|
|
|
+ getList();
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.time-slots {
|
|
|
- overflow-x: auto;
|
|
|
- width: 100%;
|
|
|
- max-width: none;
|
|
|
- margin-top: 10px;
|
|
|
-}
|
|
|
-
|
|
|
-.slot-container {
|
|
|
- display: inline-flex;
|
|
|
- /* min-width: calc(64px * 24 + 4px * 23); 24个时间槽+间隙 */
|
|
|
- padding: 5px 0;
|
|
|
- gap: 4px;
|
|
|
-}
|
|
|
-
|
|
|
-.app-container {
|
|
|
- padding: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-.status-filter {
|
|
|
- margin-bottom: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-.meeting-list {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
|
|
|
- gap: 20px;
|
|
|
-}
|
|
|
-
|
|
|
-@media (max-width: 768px) {
|
|
|
- .meeting-list {
|
|
|
- grid-template-columns: 1fr;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.meeting-card {
|
|
|
- background-color: #fff;
|
|
|
- border-radius: 8px;
|
|
|
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
- padding: 16px;
|
|
|
-}
|
|
|
|
|
|
-.card-header {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 16px;
|
|
|
+/** 删除按钮操作 */
|
|
|
+function handleDelete(row) {
|
|
|
+ const _ids = row.id || ids.value;
|
|
|
+ proxy.$modal.confirm('是否确认删除设备告警编号为"' + _ids + '"的数据项?').then(function() {
|
|
|
+ return delWaring(_ids);
|
|
|
+ }).then(() => {
|
|
|
+ getList();
|
|
|
+ proxy.$modal.msgSuccess("删除成功");
|
|
|
+ }).catch(() => {});
|
|
|
}
|
|
|
|
|
|
-.meeting-image {
|
|
|
- width: 100px;
|
|
|
- height: 100px;
|
|
|
- object-fit: cover;
|
|
|
- border-radius: 8px;
|
|
|
+/** 导出按钮操作 */
|
|
|
+function handleExport() {
|
|
|
+ proxy.download('waring/waring/export', {
|
|
|
+ ...queryParams.value
|
|
|
+ }, `waring_${new Date().getTime()}.xlsx`)
|
|
|
}
|
|
|
|
|
|
-.meeting-info {
|
|
|
- flex: 1;
|
|
|
- margin-left: 16px;
|
|
|
-}
|
|
|
-
|
|
|
-.time-slots {
|
|
|
- overflow-x: auto; /* 添加水平滚动条 */
|
|
|
- white-space: nowrap;
|
|
|
- margin-top: 10px;
|
|
|
-
|
|
|
- @media (max-width: 768px) {
|
|
|
- max-width: 300px; /* 小屏幕宽度 */
|
|
|
- }
|
|
|
-
|
|
|
- @media (min-width: 769px) and (max-width: 1024px) {
|
|
|
- max-width: 400px; /* 中等屏幕宽度 */
|
|
|
- }
|
|
|
-
|
|
|
- @media (min-width: 1025px) {
|
|
|
- max-width: 900px; /* 大屏幕宽度 */
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.slot-container {
|
|
|
- display: inline-flex;
|
|
|
- gap: 4px;
|
|
|
-}
|
|
|
-
|
|
|
-.slot {
|
|
|
- width: 60px;
|
|
|
- height: 20px;
|
|
|
- background-color: #f0f0f0;
|
|
|
- text-align: center;
|
|
|
- line-height: 20px;
|
|
|
- border-radius: 4px;
|
|
|
- cursor: pointer;
|
|
|
-}
|
|
|
-
|
|
|
-.slot.current {
|
|
|
- background-color: #409EFF; /* 当前时间高亮 */
|
|
|
- color: #fff;
|
|
|
-}
|
|
|
-
|
|
|
-.slot.booked {
|
|
|
- background-color: #ff9900; /* 占用状态 */
|
|
|
-}
|
|
|
-</style>
|
|
|
+getList();
|
|
|
+</script>
|