387 lines
9.7 KiB
Vue
387 lines
9.7 KiB
Vue
<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>
|