<template> <div class="project-progress-container"> <!-- 左侧项目信息表单 --> <div class="left-section"> <h2 class="mb20 ml10 textC">项目人员表</h2> <el-form :model="projectInfo" label-width="120px" class="project-info-form" > <el-form-item label="选择项目"> <el-select v-model="selectedProject" placeholder="请选择项目" @change="handleProjectChange" filterable > <el-option v-for="project in projectList" :key="project.projectId" :label="project.projectName" :value="project.projectId" ></el-option> </el-select> </el-form-item> <el-form-item label="项目名称"> <span>{{ projectInfo.projectName }}</span> </el-form-item> <el-form-item label="项目编码"> <span>{{ projectInfo.projectCode }}</span> </el-form-item> <el-form-item label="预计工时"> <span>{{ projectInfo.budgetDate }} 天</span> </el-form-item> <el-form-item label="项目开始时间"> <span>{{ projectInfo.startDate }}</span> </el-form-item> <el-form-item label="项目结束时间"> <span>{{ projectInfo.endDate }}</span> </el-form-item> </el-form> </div> <!-- 右侧滚动列表格 --> <div class="right-section"> <div class="date-range-container mb20"> <span class="date-range-label">统计时间:</span> <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" @change="handleDateRangeChange" format="yyyy-MM-dd" value-format="yyyy-MM-dd" /> </div> <CustomTable :columns="scrollableColumns" :tableData="executionData" :showPagination="false" :border="true" tableHeight="600" ></CustomTable> </div> </div> </template> <script> import CustomTable from "@/components/CustomTable.vue"; import { projectBank, projectApi } from "@/utils/api"; export default { name: "ProjectUser", components: { CustomTable, }, data() { return { timeRange: [], dateRange: this.getDefaultDateRange(), selectedProject: null, projectInfo: { projectName: "", projectCode: "", budgetDate: "", startDate: "", endDate: "", }, projectList: [], scrollableColumns: [], executionData: [], }; }, methods: { getDefaultDateRange() { const startOfMonth = this.moment().startOf("month").format("YYYY-MM-DD"); const endOfMonth = this.moment().endOf("month").format("YYYY-MM-DD"); this.timeRange = [startOfMonth, endOfMonth]; return [startOfMonth, endOfMonth]; }, handleDateRangeChange() { this.timeRange = [ this.dateRange[0] + " 00:00:00", this.dateRange[1] + " 23:59:59", ]; this.getProjectUser(); }, async getProjectList() { const res = await projectBank.porjectProgress({ startDate: this.dateRange[0] + " 00:00:00", endDate: this.dateRange[1] + " 23:59:59", }); this.projectList = res.data.map((ele) => ({ projectName: ele.projectName, projectId: ele.projectId, })); if (this.projectList.length) { if (this.$route.query.projectId) { this.dateRange = [ this.$route.query.startDate, this.$route.query.endDate, ]; this.validateDateRange(); this.selectedProject = Number(this.$route.query.projectId); this.handleProjectChange(this.$route.query.projectId, 1); } else { this.selectedProject = this.projectList[0].projectId; this.handleProjectChange(this.projectList[0].projectId); } } }, validateDateRange() { const startDate = new Date(this.dateRange[0]); const endDate = new Date(this.dateRange[1]); // 计算日期范围的差值(以毫秒为单位) const timeDiff = endDate - startDate; // 计算三个月的毫秒数 const threeMonthsInMs = 3 * 30 * 24 * 60 * 60 * 1000; // 约为三个月 // 检查日期范围是否超过三个月 if (timeDiff > threeMonthsInMs) { // 如果超过三个月,将结束日期设置为开始日期加三个月 const newEndDate = new Date(startDate); newEndDate.setMonth(startDate.getMonth() + 3); this.dateRange[1] = newEndDate.toISOString().split("T")[0]; // 格式化为 YYYY-MM-DD } }, async handleProjectChange(projectId, time) { const res = await projectApi.getProjectDetail(projectId); this.projectInfo = res.data; if (!time) this.dateRange = [ this.projectInfo.startDate.split(" ")[0], this.projectInfo.endDate.split(" ")[0], ]; this.validateDateRange(); this.handleDateRangeChange(); }, async getProjectUser() { const res = await projectBank.projectUser({ startDate: this.dateRange[0] + " 00:00:00", endDate: this.dateRange[1] + " 23:59:59", projectId: this.projectInfo.projectId, }); console.log(123, this.dateRange); const start = new Date(this.timeRange[0]); const end = new Date(this.timeRange[1]); let index = 0; this.executionData = [{}]; for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) { const dateStr = `${d.getMonth() + 1}/${d.getDate()}`; index++; this.executionData[0][dateStr] = res.data.detailList[index - 1]; } }, goToDetail(row) { this.$router.push({ path: "/", query: { userId: row.userId, projectId: this.projectInfo.projectId, nickName: row.userName, }, }); }, }, watch: { timeRange: { deep: true, handler(newVal) { const days = []; if (newVal && newVal.length === 2) { const start = new Date(this.timeRange[0]); const end = new Date(this.timeRange[1]); for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) { const dayOfWeek = [ "周日", "周一", "周二", "周三", "周四", "周五", "周六", ][d.getDay()]; const dateStr = `${d.getMonth() + 1}/${d.getDate()}`; days.push({ prop: dateStr, label: `${dayOfWeek}\n${dateStr}`, minWidth: 100, type: "multiButton", callback: (data, row) => { return data.userName + `(${data.workTime}天)`; }, Event: (data, row) => { if (data) { this.goToDetail(data); } }, }); } } this.scrollableColumns = days; }, }, }, mounted() { this.getProjectList(); }, }; </script> <style lang="scss" scoped> .project-progress-container { display: flex; height: 88vh; background-color: white; } .left-section, .right-section { display: flex; flex-direction: column; height: 100%; } .left-section { width: 400px; /* 根据固定列的总宽度调整 */ padding-top: 34px; padding-bottom: 20px; box-shadow: 2px 0 10px rgba(0, 0, 0, 0.5); /* 添加右侧阴影 */ z-index: 1; /* 确保左侧在右侧之上 */ margin-right: 5px; position: relative; } .right-section { flex: 1; overflow-x: auto; padding: 20px; padding-left: 0; /* 移除左侧内边距,与左侧部分紧密相连 */ } .date-range-container { display: flex; align-items: center; width: 500px; margin-left: 20px; } .date-range-label { white-space: nowrap; margin-right: 10px; } ::v-deep .el-table { height: 100% !important; } ::v-deep .el-table__header th { background-color: #4a4a4a; color: white; text-align: center; } ::v-deep .el-table__body td { text-align: center; } ::v-deep .el-table__footer td { background-color: #f5f7fa; font-weight: bold; text-align: center; /* 确保合计行内容居中 */ } ::v-deep .el-table__header .cell, ::v-deep .el-table__body .cell, ::v-deep .el-table__footer .cell { white-space: pre-wrap; line-height: 1.2; padding: 8px 0; } ::v-deep .el-table__body-wrapper { overflow: auto; // height: 88%; } /* 确保两个表格的高度一致 */ .left-section ::v-deep .el-table, .right-section ::v-deep .el-table { height: 100% !important; } /* 调整日期选择器样式 */ ::v-deep .el-date-editor { width: 100%; } /* 调整表格内容的字体大小 */ ::v-deep .el-table { font-size: 14px; } /* 调整表头的样式 */ ::v-deep .el-table__header-wrapper { background-color: #f5f7fa; } ::v-deep .el-table__header th { background-color: #f5f7fa; color: #606266; font-weight: bold; } /* 调整合计行的样式 */ ::v-deep .el-table__footer-wrapper { background-color: #606266; } ::v-deep .el-table__footer td { background-color: #f5f7fa !important; font-weight: bold; color: #606266; } .project-name { cursor: pointer; color: #409eff; } .project-name:hover { text-decoration: underline; } .user-select-container { position: absolute; top: 25px; right: 10px; width: 220px; z-index: 2; display: flex; align-items: center; flex-direction: row; gap: 10px; span { width: 100px; } } ::v-deep .el-table__body{ height: 100%; } ::v-deep td.el-table__cell{ border-bottom: none; border-top: none; vertical-align: top; } ::v-deep tr.el-table__row.current-row .el-table__cell { background-color: #fff !important; } </style>