|
|
@@ -1,23 +1,33 @@
|
|
|
<template>
|
|
|
- <div class="project-gantt">
|
|
|
+ <div class="project-gantt" :class="{ 'is-fullscreen': isFullscreen }">
|
|
|
<div class="view-switch">
|
|
|
+ <div class="view-switch-left">
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ :type="viewMode === 'gantt' ? 'primary' : 'default'"
|
|
|
+ @click="handleViewSwitch('gantt')"
|
|
|
+ >
|
|
|
+ 甘特图
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ :type="viewMode === 'calendar' ? 'primary' : 'default'"
|
|
|
+ @click="handleViewSwitch('calendar')"
|
|
|
+ >
|
|
|
+ 工作日历
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
<el-button
|
|
|
size="mini"
|
|
|
- :type="viewMode === 'gantt' ? 'primary' : 'default'"
|
|
|
- @click="handleViewSwitch('gantt')"
|
|
|
- >
|
|
|
- 甘特图
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- size="mini"
|
|
|
- :type="viewMode === 'calendar' ? 'primary' : 'default'"
|
|
|
- @click="handleViewSwitch('calendar')"
|
|
|
+ :icon="isFullscreen ? 'el-icon-close' : 'el-icon-full-screen'"
|
|
|
+ @click="toggleFullscreen"
|
|
|
>
|
|
|
- 工作日历
|
|
|
+ {{ isFullscreen ? '退出全屏' : '全屏显示' }}
|
|
|
</el-button>
|
|
|
</div>
|
|
|
<div class="project-gantt__body">
|
|
|
<resource-panel
|
|
|
+ :is-fullscreen="isFullscreen"
|
|
|
:resource-tabs="resourceTabs"
|
|
|
:active-tab="activeTab"
|
|
|
:keyword="keyword"
|
|
|
@@ -30,6 +40,7 @@
|
|
|
/>
|
|
|
<div v-show="viewMode === 'gantt'" class="gantt-view">
|
|
|
<gantt-filter-bar
|
|
|
+ v-show="!isFullscreen"
|
|
|
:query="ganttQuery"
|
|
|
@update:query="ganttQuery = $event"
|
|
|
@apply="applyGanttFilters"
|
|
|
@@ -41,6 +52,7 @@
|
|
|
</div>
|
|
|
<div v-show="viewMode === 'calendar'" class="calendar-view">
|
|
|
<gantt-filter-bar
|
|
|
+ v-show="!isFullscreen"
|
|
|
:query="calendarQuery"
|
|
|
@update:query="calendarQuery = $event"
|
|
|
@apply="applyCalendarFilters"
|
|
|
@@ -144,7 +156,8 @@
|
|
|
calendarQuery: createSearchQuery(),
|
|
|
calendarFilters: createSearchQuery(),
|
|
|
calendarExpand: true,
|
|
|
- hoverTooltip: createHoverTooltipState()
|
|
|
+ hoverTooltip: createHoverTooltipState(),
|
|
|
+ isFullscreen: false
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -472,6 +485,23 @@
|
|
|
this.initData(); // 数据format以及gantt reload
|
|
|
this.syncGanttVisibility();
|
|
|
this.bindGanttHoverTooltip();
|
|
|
+ // 监听全屏状态变化
|
|
|
+ document.addEventListener(
|
|
|
+ 'fullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ document.addEventListener(
|
|
|
+ 'webkitfullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ document.addEventListener(
|
|
|
+ 'mozfullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ document.addEventListener(
|
|
|
+ 'MSFullscreenChange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
@@ -745,6 +775,72 @@
|
|
|
}
|
|
|
this.viewMode = mode;
|
|
|
},
|
|
|
+ async toggleFullscreen() {
|
|
|
+ const element = this.$el;
|
|
|
+ if (!this.isFullscreen) {
|
|
|
+ // 进入全屏
|
|
|
+ try {
|
|
|
+ if (element.requestFullscreen) {
|
|
|
+ await element.requestFullscreen();
|
|
|
+ } else if (element.webkitRequestFullscreen) {
|
|
|
+ await element.webkitRequestFullscreen();
|
|
|
+ } else if (element.mozRequestFullScreen) {
|
|
|
+ await element.mozRequestFullScreen();
|
|
|
+ } else if (element.msRequestFullscreen) {
|
|
|
+ await element.msRequestFullscreen();
|
|
|
+ }
|
|
|
+ this.isFullscreen = true;
|
|
|
+ } catch (err) {
|
|
|
+ console.error('全屏请求失败:', err);
|
|
|
+ this.$message.warning('浏览器不支持全屏功能');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 退出全屏
|
|
|
+ try {
|
|
|
+ if (document.exitFullscreen) {
|
|
|
+ await document.exitFullscreen();
|
|
|
+ } else if (document.webkitExitFullscreen) {
|
|
|
+ await document.webkitExitFullscreen();
|
|
|
+ } else if (document.mozCancelFullScreen) {
|
|
|
+ await document.mozCancelFullScreen();
|
|
|
+ } else if (document.msExitFullscreen) {
|
|
|
+ await document.msExitFullscreen();
|
|
|
+ }
|
|
|
+ this.isFullscreen = false;
|
|
|
+ } catch (err) {
|
|
|
+ console.error('退出全屏失败:', err);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.viewMode === 'gantt') {
|
|
|
+ gantt.render();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleFullscreenChange() {
|
|
|
+ // 监听全屏状态变化(用户按ESC键退出全屏)
|
|
|
+ const isCurrentlyFullscreen = !!(
|
|
|
+ document.fullscreenElement ||
|
|
|
+ document.webkitFullscreenElement ||
|
|
|
+ document.mozFullScreenElement ||
|
|
|
+ document.msFullscreenElement
|
|
|
+ );
|
|
|
+
|
|
|
+ if (this.isFullscreen && !isCurrentlyFullscreen) {
|
|
|
+ this.isFullscreen = false;
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.viewMode === 'gantt') {
|
|
|
+ gantt.render();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleEscKey(event) {
|
|
|
+ if (event.key === 'Escape' && this.isFullscreen) {
|
|
|
+ this.toggleFullscreen();
|
|
|
+ }
|
|
|
+ },
|
|
|
initGantt() {
|
|
|
let _this = this;
|
|
|
gantt.config.readonly = true;
|
|
|
@@ -964,6 +1060,24 @@
|
|
|
this.hideHoverTooltip
|
|
|
);
|
|
|
}
|
|
|
+ document.removeEventListener('keydown', this.handleEscKey);
|
|
|
+ // 移除全屏状态监听
|
|
|
+ document.removeEventListener(
|
|
|
+ 'fullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ document.removeEventListener(
|
|
|
+ 'webkitfullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ document.removeEventListener(
|
|
|
+ 'mozfullscreenchange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ document.removeEventListener(
|
|
|
+ 'MSFullscreenChange',
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
@@ -975,8 +1089,28 @@
|
|
|
height: 100%;
|
|
|
min-height: 280px;
|
|
|
gap: 12px;
|
|
|
+
|
|
|
+ &.is-fullscreen {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ width: 100vw;
|
|
|
+ height: 100vh;
|
|
|
+ z-index: 9999;
|
|
|
+ background: #fff;
|
|
|
+ padding: 16px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
}
|
|
|
.view-switch {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+ .view-switch-left {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 8px;
|