pms-front/src/views/projectBank/userProject.vue

316 lines
7.9 KiB
Vue
Raw Normal View History

<template>
<div class="project-progress-container">
<!-- 左侧固定列表格 -->
<div class="content flex-col">
<div class="flex-row aic mb20">
<h2 class="textC">人员项目表</h2>
<div class="selectBox flex-row aic">
<span>选择人员</span>
<el-input
v-model="selectedUserName"
placeholder="请选择用户"
readonly
@click.native="openUserSelectDialog"
></el-input>
</div>
<div class="date-range-container">
<span class="date-range-label">统计时间</span>
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
:clearable="false"
/>
</div>
</div>
<div class="f1">
<CustomTable
:columns="fixedColumns"
:tableData="executionData"
:showPagination="false"
:showSummary="true"
:summaryMethod="getFixedColumnsSummaries"
2024-10-16 09:32:16 +00:00
:tableHeight="600"
></CustomTable>
</div>
</div>
<!-- 用户选择对话框 -->
<SelectUser
:dialogVisible="userSelectDialogVisible"
:multiSelect="false"
:currentSelectedUser="selectedUser ? [selectedUser] : []"
@confirm="handleUserSelect"
@close="handleUserClose"
/>
</div>
</template>
<script>
import CustomTable from "@/components/CustomTable.vue";
import SelectUser from "@/components/SelectUser.vue";
import { projectBank } from "@/utils/api";
export default {
components: {
CustomTable,
SelectUser,
},
data() {
return {
fixedColumns: [],
executionData: [],
dateRange: [],
selectedUserName: "超级管理员",
selectedUserId: 1,
selectedUser: {
userId: 1,
selectedUserName: "超级管理员",
},
userSelectDialogVisible: false,
};
},
methods: {
getDefaultDateRange() {
const startOfMonth = this.moment().startOf("month").format("YYYY-MM-DD");
const endOfMonth = this.moment().endOf("month").format("YYYY-MM-DD");
this.dateRange = [startOfMonth, endOfMonth];
},
openUserSelectDialog() {
this.userSelectDialogVisible = true;
},
async getUserProject() {
const res = await projectBank.porjectProgress({
startDate: this.dateRange[0] + " 00:00:00",
endDate: this.dateRange[1] + " 00:00:00",
userId: this.selectedUserId,
});
this.executionData = res.data;
},
getFixedColumnsSummaries(param) {
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = "合计工时(天)";
return;
}
const values =
column.property === "detailList"
? data.map((item) => Number(item[column.property][index - 2]))
: data.map((item) => Number(item[column.property]));
if (!values.every((value) => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
return !isNaN(value) ? prev + curr : prev;
}, 0);
sums[index] = Number(sums[index].toFixed(2));
} else {
sums[index] = "";
}
});
return sums;
},
handleUserSelect(users) {
if (users.length > 0) {
this.selectedUser = users[0];
this.selectedUserId = users[0].userId;
this.selectedUserName = users[0].nickName;
} else {
this.selectedUser = null;
this.selectedUserId = "";
this.selectedUserName = "";
}
this.userSelectDialogVisible = false;
this.getUserProject();
},
goToDetail(row) {
this.$router.push({
path: "/project/detail",
query: {
id: row.projectId,
},
});
},
handleUserClose() {
this.userSelectDialogVisible = false;
},
},
watch: {
dateRange: {
deep: true,
handler(newVal) {
const days = [];
if (newVal && newVal.length === 2) {
const start = new Date(this.dateRange[0]);
const end = new Date(this.dateRange[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()}`;
let index = days.length;
days.push({
prop: "detailList",
label: `${dayOfWeek}\n${dateStr}`,
minWidth: 100,
type: "array",
callback: (data, row) => {
return data[index];
},
});
}
}
this.fixedColumns = [
{
prop: "projectName",
label: "项目",
type: "button",
fixed: "left",
width: 160,
callback: (data, row) => {
return `<span style="color:#1686d8;cursor:pointer">${data}</span>`;
},
Event: (data, row) => {
this.goToDetail(row);
},
},
{
prop: "allWorkTime",
label: "统计工时\n",
width: 160,
fixed: "left",
},
...days,
];
this.$nextTick(this.getUserProject());
},
},
},
mounted() {
this.getDefaultDateRange();
},
beforeDestroy() {},
};
</script>
<style lang="scss" scoped>
.project-progress-container {
display: flex;
height: 88vh;
background-color: white;
padding: 30px;
}
.content {
width: 100%;
}
.placeholder-header {
height: 102px; /* 与左侧表格的标题和日期选择器高度一致 */
}
.date-range-container {
display: flex;
align-items: center;
width: 500px;
margin-left: 100px;
}
.date-range-label {
white-space: nowrap;
margin-right: 10px;
}
.selectBox {
width: 200px;
margin-left: 35px;
}
.selectBox span {
width: 120px;
}
::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;
}
::v-deep .el-table__body-wrapper ::-webkit-scrollbar {
}
/* 确保两个表格的高度一致 */
.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 td {
background-color: #c0c4cc !important;
font-weight: bold;
color: #606266;
}
.project-name {
cursor: pointer;
color: #409eff;
}
.project-name:hover {
text-decoration: underline;
}
::v-deep thead .el-table-fixed-column--left {
background: #d7d7d7 !important;
}
::v-deep .el-table__fixed {
box-shadow: 5px 20px 20px rgba(7, 7, 7, 0.5) !important;
}
.custom-table {
height: 100%;
}
::v-deep .el-table__footer-wrapper {
background-color: #f5f7fa;
bottom: 0;
position: absolute;
}
</style>