数字化大屏
This commit is contained in:
		
							
								
								
									
										329
									
								
								src/views/projectLarge/ProjectScreen/components/leftPage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										329
									
								
								src/views/projectLarge/ProjectScreen/components/leftPage.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,329 @@ | ||||
| <template> | ||||
|   <div class="leftPage"> | ||||
|     <div class="topPage"> | ||||
|       <Title title="项目公告" /> | ||||
|       <div class="content"> | ||||
|         <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> | ||||
|       </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"> | ||||
|           <img src="@/assets/projectLarge/people.svg" alt=""> | ||||
|           <div class="tag_title">出勤人</div> | ||||
|           <div class="tag_info"> | ||||
|             {{ 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> | ||||
|  | ||||
|       <div class="attendance_list"> | ||||
|         <div class="attendance_item subfont"> | ||||
|           <div class="attendance_item_title"></div> | ||||
|           <div class="attendance_item_title">在岗人数</div> | ||||
|           <div class="attendance_item_title">出勤率</div> | ||||
|           <div class="attendance_item_title">出勤时间</div> | ||||
|         </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.attendanceTime }}</div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <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 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 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; | ||||
|   height: 100%; | ||||
|  | ||||
|   .topPage, | ||||
|   .endPage { | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     align-items: center; | ||||
|     width: 100%; | ||||
|     padding: 15px 0; | ||||
|     border: 1px solid rgba(29, 214, 255, 0.1); | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
|  | ||||
|   .endPage { | ||||
|     flex: 1; | ||||
|     margin-top: 23px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .content { | ||||
|   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 { | ||||
|     display: flex; | ||||
|     align-items: flex-start; | ||||
|     gap: 10px; | ||||
|     margin-bottom: 20px; | ||||
|     font-size: 14px; | ||||
|     font-weight: 400; | ||||
|     color: rgba(230, 247, 255, 1); | ||||
|     cursor: pointer; | ||||
|  | ||||
|     .ellipsis { | ||||
|       display: -webkit-box; | ||||
|       -webkit-box-orient: vertical; | ||||
|       -webkit-line-clamp: 2; | ||||
|       overflow: hidden; | ||||
|       text-overflow: ellipsis; | ||||
|       line-height: 1.5; | ||||
|     } | ||||
|  | ||||
|     &:last-child { | ||||
|       margin-bottom: 0; | ||||
|     } | ||||
|  | ||||
|     img { | ||||
|       margin-top: 3px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .map { | ||||
|   margin-top: 15px; | ||||
| } | ||||
|  | ||||
| .attendance_tag { | ||||
|   width: 100%; | ||||
|   display: flex; | ||||
|   justify-content: space-between; | ||||
|   padding: 0 30px; | ||||
|   margin-top: 15px; | ||||
|  | ||||
|   .tag_item { | ||||
|     width: 28%; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     align-items: center; | ||||
|     gap: 10px; | ||||
|     border: 1px dashed rgba(29, 214, 255, 0.3); | ||||
|     padding: 10px; | ||||
|  | ||||
|     .tag_info { | ||||
|       font-size: 20px; | ||||
|       font-weight: 700; | ||||
|       color: rgba(230, 247, 255, 1); | ||||
|       text-shadow: 0px 1.24px 6.21px rgba(0, 190, 247, 1); | ||||
|     } | ||||
|  | ||||
|     .tag_title { | ||||
|       font-size: 14px; | ||||
|       font-weight: 400; | ||||
|       color: rgba(230, 247, 255, 1); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .attendance_list { | ||||
|   padding: 0px 30px; | ||||
|   font-size: 14px; | ||||
|  | ||||
|   .attendance_item { | ||||
|     display: grid; | ||||
|     grid-template-columns: 3fr 2fr 2fr 3fr; | ||||
|     margin-top: 20px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .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> | ||||
		Reference in New Issue
	
	Block a user