diff --git a/src/api/projectScreen/index.ts b/src/api/projectScreen/index.ts new file mode 100644 index 0000000..9e84e68 --- /dev/null +++ b/src/api/projectScreen/index.ts @@ -0,0 +1,66 @@ +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; + +// 查询生项目天气 +export const getScreenWeather = (projectId: number | string) => { + return request({ + url: '/project/big/screen/weather/' + projectId, + method: 'get', + }); +}; + +// 查询项目安全天数 +export const getScreenSafetyDay = (projectId: number | string) => { + return request({ + url: '/project/big/screen/safetyDay/' + projectId, + method: 'get', + }); +}; + +// 查询项目公告 +export const getScreenNews = (projectId: number | string) => { + return request({ + url: '/project/big/screen/news/' + projectId, + method: 'get', + }); +}; + +// 查询项目土地统计 +export const getScreenLand = (projectId: number | string) => { + return request({ + url: '/project/big/screen/' + projectId, + method: 'get', + }); +}; + +// 查询项目形象进度 +export const getScreenImgProcess = (projectId: number | string) => { + return request({ + url: '/project/big/screen/imageProgress/' + projectId, + method: 'get', + }); +}; + +// 查询项目人员情况 +export const getScreenPeople = (projectId: number | string) => { + return request({ + url: '/project/big/screen/people/' + projectId, + method: 'get', + }); +}; + +// 查询项目AI安全巡检 +export const getScreenSafetyInspection = (projectId: number | string) => { + return request({ + url: '/project/big/screen/safetyInspection/' + projectId, + method: 'get', + }); +}; + +// 查询项目概况 +export const getScreenGeneralize = (projectId: number | string) => { + return request({ + url: '/project/big/screen/generalize/' + projectId, + method: 'get', + }); +}; diff --git a/src/api/projectScreen/types.ts b/src/api/projectScreen/types.ts new file mode 100644 index 0000000..f6f3b57 --- /dev/null +++ b/src/api/projectScreen/types.ts @@ -0,0 +1,5 @@ +export interface TableQuery extends PageQuery { + tableName: string; + tableComment: string; + dataName: string; +} \ No newline at end of file diff --git a/src/assets/projectLarge/center.png b/src/assets/projectLarge/center.png new file mode 100644 index 0000000..c1ea62c Binary files /dev/null and b/src/assets/projectLarge/center.png differ diff --git a/src/assets/projectLarge/leftarrow.png b/src/assets/projectLarge/leftarrow.png deleted file mode 100644 index 55c4b79..0000000 Binary files a/src/assets/projectLarge/leftarrow.png and /dev/null differ diff --git a/src/assets/projectLarge/rightarrow.png b/src/assets/projectLarge/rightarrow.png deleted file mode 100644 index 723df81..0000000 Binary files a/src/assets/projectLarge/rightarrow.png and /dev/null differ diff --git a/src/assets/projectLarge/swiper.png b/src/assets/projectLarge/swiper.png deleted file mode 100644 index 32520bd..0000000 Binary files a/src/assets/projectLarge/swiper.png and /dev/null differ diff --git a/src/views/ProjectScreen/components/centerPage.vue b/src/views/ProjectScreen/components/centerPage.vue index 8c79dcf..21224b8 100644 --- a/src/views/ProjectScreen/components/centerPage.vue +++ b/src/views/ProjectScreen/components/centerPage.vue @@ -1,26 +1,27 @@ diff --git a/src/views/ProjectScreen/components/header.vue b/src/views/ProjectScreen/components/header.vue index 322f1d4..5450f69 100644 --- a/src/views/ProjectScreen/components/header.vue +++ b/src/views/ProjectScreen/components/header.vue @@ -6,7 +6,7 @@
安全生产天数:
- 1,235 + {{ safetyDay }}
@@ -14,16 +14,18 @@
XXX智慧工地管理平台
XXX Smart Construction Stic Management Dashboard
-
+
- 天气图标 - - - 多云 9°/18° - {{ week[date.week] }} ({{ date.ymd }}) - +
+
+ +
{{ item.weather }}{{ item.tempMin }}°/{{ item.tempMax }}°
+
{{ item.week }}({{ item.date }})
+
+
@@ -35,48 +37,155 @@ 设置图标 管理系统
+ +
+
+
+
+ +
+ + + + + + +
diff --git a/src/views/ProjectScreen/components/leftPage.vue b/src/views/ProjectScreen/components/leftPage.vue index 3be8ba0..3130984 100644 --- a/src/views/ProjectScreen/components/leftPage.vue +++ b/src/views/ProjectScreen/components/leftPage.vue @@ -2,30 +2,53 @@
- <div class="content"> - <div class="content_item" v-for="item in 6" :key="item"> - <div class="round"> - <div class="sub_round"></div> + <div class="content_item" v-for="item in news" :key="item.id"> + <img src="@/assets/projectLarge/round.svg" alt=""> + <div class="ellipsis"> + {{ item.title }} + <span @click="showNewsDetail(item)" style="color: rgba(138, 149, 165, 1);">{{ item.id === newId ? '关闭' : + '查看' }}</span> </div> - <div class="ellipsis">2025年6月23日 重庆市两江新区广场前期准备与审批完毕区广场前期准备与审批完毕前期准备与审批完毕区广场前期准备与审批完毕</div> </div> </div> </div> + + <div class="detailBox" :class="{'show': newId}"> + <!-- <div class="detail_title">{{ newDetail.title }}</div> --> + <div class="detail_content" v-html="newDetail.content"></div> + </div> + <div class="endPage"> <Title title="人员情况" /> - <div class="map"> <img src="@/assets/projectLarge/map.svg" alt=""> + <!-- <div ref="mapChartRef"></div> --> </div> <div class="attendance_tag"> - <div class="tag_item" v-for="(item, index) in tagList" :key="index"> + <div class="tag_item"> <img src="@/assets/projectLarge/people.svg" alt=""> - <div class="tag_title">{{ item.title }}</div> + <div class="tag_title">出勤人</div> <div class="tag_info"> - {{ item.number }} - <span style="font-size: 14px;">{{ index === 2 ? '%' : '人' }}</span> + {{ attendanceCount }} + <span style="font-size: 14px;">人</span> + </div> + </div> + <div class="tag_item"> + <img src="@/assets/projectLarge/people.svg" alt=""> + <div class="tag_title">在岗人</div> + <div class="tag_info"> + {{ peopleCount }} + <span style="font-size: 14px;">人</span> + </div> + </div> + <div class="tag_item"> + <img src="@/assets/projectLarge/people.svg" alt=""> + <div class="tag_title">出勤率</div> + <div class="tag_info"> + {{ attendanceRate }} + <span style="font-size: 14px;">%</span> </div> </div> </div> @@ -37,11 +60,11 @@ <div class="attendance_item_title">出勤率</div> <div class="attendance_item_title">出勤时间</div> </div> - <div v-for="item in list" :key="item.title" class="attendance_item"> - <div class="attendance_item_title">{{ item.title }}</div> - <div class="attendance_item_number">{{ item.number }} <span class="subfont">人/{{ item.number }}</span></div> + <div v-for="item in teamAttendanceList" :key="item.id" class="attendance_item"> + <div class="attendance_item_title">{{ item.teamName }}</div> + <div class="attendance_item_number">{{ item.attendanceNumber }} <span class="subfont">人/{{ item.allNumber }}</span></div> <div class="attendance_item_rate">{{ item.attendanceRate }} %</div> - <div class="attendance_item_date subfont">{{ item.date }}</div> + <div class="attendance_item_date subfont">{{ item.attendanceTime }}</div> </div> </div> </div> @@ -51,29 +74,101 @@ <script setup lang="ts"> import { ref } from "vue" import Title from './title.vue' +import { getScreenNews, getScreenPeople } from '@/api/projectScreen'; +import { mapOption } from './optionList' +import * as echarts from 'echarts'; -const list = ref([ - { title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' }, - { title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' }, - { title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' }, - { title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' }, - { title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' }, - { title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' }, +const props = defineProps({ + projectId: { + type: String, + default: '' + } +}) + +let mapChart = null +const mapChartRef = ref<HTMLDivElement | null>(null); +const news = ref([]) +const newDetail = ref({ + title: '', + content: '' +}) +const newId = ref('') +const attendanceCount = ref(0) +const attendanceRate = ref(0) +const peopleCount = ref(0) +const teamAttendanceList = ref([ + { id: "", teamName: "", attendanceNumber: 0, allNumber: 0, attendanceRate: 0, attendanceTime: "" }, ]) -const tagList = ref([ - { title: '出勤人数', number: 259 }, - { title: '在岗人数', number: 100 }, - { title: '出勤率', number: 100 }, -]) +/** + * 显示新闻详情 + */ +const showNewsDetail = (item: any) => { + if (newId.value === item.id) { + newId.value = '' + return + } + newDetail.value = item + newId.value = item.id +} + +/** + * 获取项目人员出勤数据 + */ +const getPeopleData = async () => { + const res = await getScreenPeople(props.projectId); + const { data, code } = res + if (code === 200) { + attendanceCount.value = data.attendanceCount + attendanceRate.value = data.attendanceRate + peopleCount.value = data.peopleCount + teamAttendanceList.value = data.teamAttendanceList + } +} + +/** + * 获取项目新闻数据 + */ +const getNewsData = async () => { + const res = await getScreenNews(props.projectId); + const { data, code } = res + if (code === 200) { + news.value = data + } +} + +/** + * 初始化地图 + */ +const initMapChart = () => { + if (!mapChartRef.value) { + return; + } + mapChart = echarts.init(mapChartRef.value); + mapChart.setOption(mapOption); +} + +onMounted(() => { + // nextTick(() => { + // initMapChart(); + // }); + getPeopleData() + getNewsData() +}) + +onUnmounted(() => { + // if (mapChart) { + // mapChart.dispose(); + // mapChart = null; + // } +}); + </script> <style scoped lang="scss"> .leftPage { display: flex; flex-direction: column; - width: calc(25vw - 30px); - margin: 0 15px; height: 100%; .topPage, @@ -115,11 +210,11 @@ const tagList = ref([ display: flex; align-items: flex-start; gap: 10px; - // position: relative; margin-bottom: 20px; font-size: 14px; font-weight: 400; color: rgba(230, 247, 255, 1); + cursor: pointer; .ellipsis { display: -webkit-box; @@ -134,21 +229,8 @@ const tagList = ref([ margin-bottom: 0; } - .round { - display: grid; - place-items: center; + img { margin-top: 3px; - width: 12px; - height: 12px; - border-radius: 50%; - background: rgba(29, 214, 255, 0.3); - - .sub_round { - width: 6px; - height: 6px; - border-radius: 50%; - background: #1DD6FF; - } } } } @@ -201,4 +283,45 @@ const tagList = ref([ .subfont { color: rgba(138, 149, 165, 1); } + +.detailBox { + position: absolute; + left: 20vw; + top: 0; + width: 300px; + height: 300px; + max-height: 500px; + overflow-y: auto; + padding: 0 15px; + box-sizing: border-box; + background: rgba(255, 255, 255, 0.2); + border-radius: 4px; + transition: all 0.3s ease; + opacity: 0; + z-index: -1; + + &.show { + left: 25vw; + opacity: 1; + z-index: 1; + } +} + +.detailBox::before { + content: ''; + /* 绝对定位相对于父元素 */ + position: absolute; + /* 定位到左侧中间位置 */ + left: -10px; + top: 50%; + /* 垂直居中 */ + transform: translateY(-50%); + /* 利用边框创建三角形 */ + border-width: 10px 10px 10px 0; + border-style: solid; + /* 三角形颜色与背景匹配,左侧边框透明 */ + border-color: transparent rgba(255, 255, 255, 0.2) transparent transparent; + /* 确保三角形在内容下方 */ + z-index: -1; +} </style> diff --git a/src/views/ProjectScreen/components/optionList.ts b/src/views/ProjectScreen/components/optionList.ts index e69de29..bcdf958 100644 --- a/src/views/ProjectScreen/components/optionList.ts +++ b/src/views/ProjectScreen/components/optionList.ts @@ -0,0 +1,153 @@ +export let pieOption = { + // 定义中心文字 + graphic: [ + { + type: 'text', + left: 'center', + top: '40%', + style: { + // 需要从接口替换 + text: '70%', + fontSize: 24, + fontWeight: 'bold', + fill: '#fff' + } + }, + { + type: 'text', + left: 'center', + top: '50%', + style: { + text: '总进度', + fontSize: 14, + fill: '#fff' + } + }, + ], + legend: { + show: true, + type: 'plain', + bottom: 20, + itemWidth: 12, + itemHeight: 12, + textStyle: { + color: '#fff' + } + }, + series: { + type: 'pie', + data: [], + radius: [50, 80], + center: ['50%', '45%'], + itemStyle: { + borderColor: '#fff', + borderWidth: 1 + }, + label: { + alignTo: 'edge', + formatter: '{name|{b}}\n{percent|{c} %}', + minMargin: 10, + edgeDistance: 20, + lineHeight: 15, + rich: { + name: { + fontSize: 12, + color: '#fff' + }, + percent: { + fontSize: 12, + color: '#fff' + } + } + }, + legend: { + top: 'bottom' + }, + } +}; + +export let barOption = { + legend: { + icon: 'rect', + itemWidth: 12, + itemHeight: 12, + // 调整文字与图标间距 + data: ['计划流转面积', '已流转面积'], + top: 0, + right: 20, + textStyle: { + color: '#fff', + } + }, + xAxis: { + type: 'category', + data: ['地块1', '地块2', '地块3', '地块4', '地块5', '地块6'], + axisLabel: { + color: '#fff' + }, + axisLine: { + show: false + }, + splitLine: { + show: false + } + }, + yAxis: { + name: '单位:m²', + type: 'value', + axisLabel: { + formatter: '{value}' + } + }, + grid: { + bottom: 0, // 距离容器底部的距离 + containLabel: true // 确保坐标轴标签不被裁剪 + }, + series: [ + { + name: '计划流转面积', + type: 'bar', + data: [], + barWidth: '20%', + itemStyle: { + color: 'rgb(29, 253, 253)' + }, + }, + { + name: '已流转面积', + type: 'bar', + data: [], + barWidth: '20%', + itemStyle: { + color: 'rgb(25, 181, 251)' + }, + } + ] +}; + +export let mapOption = { + geo: { + map: 'ch', + roam: true, + aspectScale: Math.cos((47 * Math.PI) / 180), + }, + series: [ + { + type: 'graph', + coordinateSystem: 'geo', + data: [ + { name: 'a', value: [7.667821250000001, 46.791734269956265] }, + { name: 'b', value: [7.404848750000001, 46.516308805996054] }, + { name: 'c', value: [7.376673125000001, 46.24728858538375] }, + { name: 'd', value: [8.015320625000001, 46.39460918238572] }, + { name: 'e', value: [8.616400625, 46.7020608630855] }, + { name: 'f', value: [8.869981250000002, 46.37539345234199] }, + { name: 'g', value: [9.546196250000001, 46.58676648282309] }, + { name: 'h', value: [9.311399375, 47.182454114178896] }, + { name: 'i', value: [9.085994375000002, 47.55395822835779] }, + { name: 'j', value: [8.653968125000002, 47.47709530818285] }, + { name: 'k', value: [8.203158125000002, 47.44506909144329] } + ], + } + ] +}; diff --git a/src/views/ProjectScreen/components/rightPage.vue b/src/views/ProjectScreen/components/rightPage.vue index 52d13b0..37aaec2 100644 --- a/src/views/ProjectScreen/components/rightPage.vue +++ b/src/views/ProjectScreen/components/rightPage.vue @@ -2,21 +2,14 @@ <div class="leftPage"> <div class="topPage"> <Title title="项目概况" /> - - <div class="content"> - <div class="content_item">项目名称:智慧生态工地社区开发项目</div> - <div class="content_item">项目位置:贵州省贵阳市乌当区(具体地块编号:01-123-11)</div> - <div class="content_item">占地面积:约10000亩</div> - <div class="content_item"> 土地性质:城镇住宅用地(兼容商业用地,容积率≤2.5)</div> - </div> + <div class="content" v-html="generalize"></div> </div> <div class="endPage"> - <!-- 饼图容器 --> <Title title="形象进度" /> - - <div ref="pieChartRef" class="echart" /> - <!-- 折线图容器 --> - <div ref="lineChartRef" class="echart" /> + <div class="chart_container"> + <div ref="pieChartRef" class="echart" /> + <div ref="lineChartRef" class="echart" /> + </div> </div> </div> </template> @@ -25,149 +18,45 @@ import { ref, onMounted, onUnmounted, nextTick } from "vue" import Title from './title.vue' import * as echarts from 'echarts'; +import { pieOption, barOption } from './optionList'; +import { getScreenLand, getScreenImgProcess, getScreenGeneralize } from '@/api/projectScreen'; +const props = defineProps({ + projectId: { + type: String, + default: 0 + } +}) + +const generalize = ref() // 饼图相关 const pieChartRef = ref<HTMLDivElement | null>(null); let pieChart: any = null; - +const totalPercent = ref(0) // 折线图相关 const lineChartRef = ref<HTMLDivElement | null>(null); let lineChart: any = null; - +// 土地数据 折线图 +const designAreaData = ref([]) +const transferAreaData = ref([]) // 饼图数据 const pieData = [ - { name: '桩点浇筑', value: 13 }, - { name: '水泥灌注', value: 7 }, - { name: '箱变安装', value: 40 }, - { name: '支架安装', value: 20 }, - { name: '组件安装', value: 20 }, + { label: 'areaPercentage', name: '厂区', value: 0 }, + { label: 'roadPercentage', name: '道路', value: 0 }, + { label: 'collectorLinePercentage', name: '集电线路', value: 0 }, + { label: 'exportLinePercentage', name: '送出线路', value: 0 }, + { label: 'substationPercentage', name: '升压站', value: 0 }, + { label: 'boxTransformerPercentage', name: '箱变', value: 0 }, ] -// 折线图数据 -const barData = { - xAxis: ['地块1', '地块2', '地块3', '地块4', '地块5', '地块6'], - series: [ - { - name: '计划流转面积', - data: [70, 25, 45, 115, 70, 85] - }, - { - name: '已流转面积', - data: [105, 30, 150, 65, 80, 200] - } - ] -} - -// 饼图配置 -const pieOption = { - series: { - type: 'pie', - data: pieData, - radius: [50, 80], - itemStyle: { - borderColor: '#fff', - borderWidth: 1 - }, - label: { - alignTo: 'edge', - formatter: '{name|{b}}\n{percent|{c} %}', - minMargin: 10, - edgeDistance: 20, - lineHeight: 15, - rich: { - name: { - fontSize: 12, - color: '#fff' - }, - percent: { - fontSize: 12, - color: '#fff' - } - } - }, - legend: { - top: 'bottom' - }, - } -}; - -// 柱状图配置 -const barOption = { - legend: { - data: ['计划流转面积', '已流转面积'], - top: 0 - }, - grid: { - left: '3%', - right: '4%', - bottom: '3%', - containLabel: true - }, - xAxis: { - type: 'category', - data: barData.xAxis - }, - yAxis: { - name: '单位:m²', - type: 'value', - axisLabel: { - formatter: '{value}' - } - }, - series: [ - { - type: 'bar', - data: [], // 空数据,仅用于承载markArea - markArea: { - silent: true, // 背景不响应交互 - data: (() => { - const groupCount = 3; // 共3组(6个月 ÷ 2) - const groupWidth = 1.8; // 每组背景宽度(覆盖2根柱子) - const bgData = []; - - for (let i = 0; i < groupCount; i++) { - const startX = i * 2 - 0.9; // 每组起始位置 - const endX = startX + groupWidth; // 每组结束位置 - bgData.push([ - { xAxis: startX, yAxis: 0 }, - { xAxis: endX, yAxis: 100 } - ]); - } - return bgData; - })(), - itemStyle: { - color: 'rgba(255, 255, 255, 0.05)', - borderRadius: 4 - } - } - }, - { - name: '计划流转面积', - type: 'bar', - data: barData.series[0].data, - barWidth: 15, // 柱形宽度 - itemStyle: { - color: 'rgb(29, 253, 253)' - }, - }, - { - name: '已流转面积', - type: 'bar', - data: barData.series[1].data, - barWidth: 15, - itemStyle: { - color: '#rgb(25, 181, 251)' - }, - } - ] -}; - // 初始化饼图 const initPieChart = () => { if (!pieChartRef.value) { console.error('未找到饼图容器元素'); return; } + pieOption.series.data = pieData + pieOption.graphic[0].style.text = totalPercent.value + '%' pieChart = echarts.init(pieChartRef.value, null, { renderer: 'canvas', useDirtyRect: false @@ -181,6 +70,8 @@ const initLineChart = () => { console.error('未找到折线图容器元素'); return; } + barOption.series[0].data = designAreaData.value + barOption.series[1].data = transferAreaData.value lineChart = echarts.init(lineChartRef.value, null, { renderer: 'canvas', useDirtyRect: false @@ -194,11 +85,52 @@ const handleResize = () => { if (lineChart) lineChart.resize(); }; +/** + * 获取项目土地统计数据 + */ +const getScreenLandData = async () => { + const res = await getScreenLand(props.projectId); + const { data, code } = res + if (code === 200) { + designAreaData.value = data.map((item: any) => Number(item.designArea)) + transferAreaData.value = data.map((item: any) => Number(item.transferArea)) + initLineChart(); + } +} + +/** + * 获取项目形象进度数据 + */ +const getScreenImgProcessData = async () => { + const res = await getScreenImgProcess(props.projectId); + const { data, code } = res + if (code === 200) { + totalPercent.value = data.totalPercentage + pieData.forEach((item: any) => { + item.value = data[item.label] + }) + initPieChart() + } +} + +/** + * 获取项目概况数据 + */ +const getScreenGeneralizeData = async () => { + const res = await getScreenGeneralize(props.projectId); + const { data, code } = res + if (code === 200) { + generalize.value = data + } +} + // 组件挂载时初始化图表 onMounted(() => { + getScreenLandData() + getScreenImgProcessData() + getScreenGeneralizeData() nextTick(() => { initPieChart(); - initLineChart(); window.addEventListener('resize', handleResize); }); }); @@ -221,8 +153,6 @@ onUnmounted(() => { .leftPage { display: flex; flex-direction: column; - width: calc(25vw - 30px); - margin: 0 15px; height: 100%; .topPage, @@ -240,15 +170,37 @@ onUnmounted(() => { flex: 1; margin-top: 23px; - .echart { + .chart_container { + display: flex; + flex-direction: column; width: 100%; height: 100%; } + + .echart { + height: 50%; + width: 100%; + } } } .content { - margin: 10px 35px; + max-height: 100px; + margin: 0 15px; + padding: 0 10px; + margin-top: 15px; + box-sizing: border-box; + overflow-y: auto; + + &::-webkit-scrollbar-track { + background: rgba(204, 204, 204, 0.1); + border-radius: 10px; + } + + &::-webkit-scrollbar-thumb { + background: rgba(29, 214, 255, 0.78); + border-radius: 10px; + } .content_item { font-size: 14px; @@ -262,12 +214,6 @@ onUnmounted(() => { } } -.ellipse { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - .subfont { color: rgba(138, 149, 165, 1); } diff --git a/src/views/ProjectScreen/components/title.vue b/src/views/ProjectScreen/components/title.vue index 04b607c..361f557 100644 --- a/src/views/ProjectScreen/components/title.vue +++ b/src/views/ProjectScreen/components/title.vue @@ -4,8 +4,8 @@ <img src="@/assets/projectLarge/section.svg" alt=""> <img src="@/assets/projectLarge/border.svg" alt=""> </div> - <div v-if="prefix"> - <img src="@/assets/projectLarge/robot.svg" alt="" style="width: 20px; height: 20px;margin-right: 5px;"> + <div> + <slot></slot> </div> <div>{{ title }}</div> </div> diff --git a/src/views/ProjectScreen/index.vue b/src/views/ProjectScreen/index.vue index 612dd7d..4c24540 100644 --- a/src/views/ProjectScreen/index.vue +++ b/src/views/ProjectScreen/index.vue @@ -1,45 +1,111 @@ <template> - <div class="large-screen"> - <Header /> + <div class="large_screen"> + <Header :projectId="projectId" :isFull="isFull" @changePage="handleChangePage" /> <div class="nav"> - <leftPage /> - <centerPage /> - <rightPage /> + <div class="nav_left" :style="{ left: isHideOther ? '-25vw' : '0' }"> + <leftPage :projectId="projectId" /> + </div> + <div class="nav_center" :style="{ width: isFull ? '100%' : 'calc(50vw - 30px)' }"> + <centerPage :projectId="projectId" :isHide="isFull" /> + </div> + <div class="nav_right" :style="{ right: isHideOther ? '-25vw' : '0' }"> + <rightPage :projectId="projectId" /> + </div> </div> </div> </template> <script setup lang="ts"> +import { ref } from 'vue'; import Header from './components/header.vue'; import leftPage from './components/leftPage.vue'; import centerPage from './components/centerPage.vue'; import rightPage from './components/rightPage.vue'; +<<<<<<< HEAD +======= +import { useUserStoreHook } from '@/store/modules/user'; + +const userStore = useUserStoreHook(); +const projectId = computed(() => userStore.selectedProject.id); +const isFull = ref(false) +const isHideOther = ref(false) + +/** + * 切换中心页面全屏 + */ +const handleChangePage = () => { + if (isFull.value) { + isFull.value = false; + setTimeout(() => { + isHideOther.value = false; + }, 500); + } else { + isFull.value = true; + isHideOther.value = true; + } +} +>>>>>>> 290fc16c320aeeee8ecb31af446b0ad7d555e954 </script> <style lang="scss" scoped> -.large-screen { +.large_screen { width: 100vw; height: 100vh; background: url('@/assets/large/bg.png') no-repeat; background-size: 100% 100%; + background-attachment: fixed; background-color: rgba(4, 7, 17, 1); + overflow: hidden; } .nav { - display: flex; - gap: 15rpx; - width: 100%; - height: calc(100vh - 100px); + position: relative; + display: grid; + place-items: center; + width: calc(100vw - 30px); + height: calc(100vh - 90px); + margin: 0 auto; box-sizing: border-box; color: #fff; } .nav_left, .nav_right { - margin: 0 15px 15px 15px; + position: absolute; + width: calc(25vw - 15px); + height: 100%; + transition: all 0.5s ease; +} + +.nav_left { + top: 0; + left: 0; +} + +.nav_right { + top: 0; + right: 0; } .nav_center { - margin-bottom: 15px; + height: 100%; + transition: all 0.5s ease; +} + +/* 中间面板全屏动画 */ +.full-width { + /* 取消flex增长,使用固定宽度 */ + width: calc(100vw - 30px); + flex: none; +} + +.slide_left { + left: -25vw; + opacity: 0; +} + +.slide_right { + right: -25vw; + opacity: 0; } </style>