feat(oa/erp): 工时管理页面功能增强

- 在工时详情页增加项目号显示
- 扩大工时汇总对话框宽度以适应更多内容
- 将人员搜索改为下拉选择,支持按用户搜索
- 新增原项目号和原项目名搜索过滤功能
- 在汇总表格中分别显示原项目号和原项目名
- 优化调整项目列,支持按项目号和项目名分别选择
- 修改导出功能,支持按汇总ID导出
- 完善过滤逻辑,支持多条件组合筛选
dev
yangk 4 weeks ago
parent 8389314fce
commit 16bc122e92

@ -145,7 +145,8 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="项目" prop="originalProjectName" align="center" show-overflow-tooltip />
<el-table-column label="项目号" prop="originalProjectCode" align="center" show-overflow-tooltip />
<el-table-column label="项目名称" prop="originalProjectName" align="center" show-overflow-tooltip />
<el-table-column label="工时" prop="originalHours" align="center" />
</el-table>
</div>

@ -99,7 +99,7 @@
</el-card>
<!-- 调整汇总工时对话框 -->
<el-dialog :title="adjustDialog.title" v-model="adjustDialog.visible" width="1000px" append-to-body>
<el-dialog :title="adjustDialog.title" v-model="adjustDialog.visible" width="1200px" append-to-body>
<div v-if="adjustData" class="mt-4">
<el-descriptions title="汇总统计" :column="4" border class="mb-4">
<el-descriptions-item label="项目总工时">{{ adjustData.totalProjectHours }}</el-descriptions-item>
@ -109,9 +109,21 @@
<el-descriptions-item label="标准天数">{{ adjustData.standardDays }}</el-descriptions-item>
</el-descriptions>
<div class="mb-4 flex items-center">
<div class="mb-4 flex flex-wrap items-center">
<div class="mr-6 mb-2 flex items-center">
<span class="mr-2 text-sm font-medium">人员搜索:</span>
<el-input v-model="staffSearchName" placeholder="输入姓名搜索..." clearable style="width: 250px" prefix-icon="Search" />
<el-select v-model="staffSearchUserId" placeholder="输入人员搜索" clearable filterable style="width: 200px">
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
</el-select>
</div>
<div class="mr-6 mb-2 flex items-center">
<span class="mr-2 text-sm font-medium">原项目号:</span>
<el-input v-model="staffSearchProjectCode" placeholder="输入项目号搜索" clearable style="width: 200px" prefix-icon="Search" />
</div>
<div class="mr-6 mb-2 flex items-center">
<span class="mr-2 text-sm font-medium">原项目名:</span>
<el-input v-model="staffSearchProjectName" placeholder="输入项目名搜索" clearable style="width: 250px" prefix-icon="Search" />
</div>
</div>
<el-table :data="filteredDetailList" border max-height="400">
@ -124,15 +136,31 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="原始项目" prop="originalProjectName" align="center" show-overflow-tooltip />
<el-table-column label="原始工时" prop="originalHours" align="center" />
<el-table-column label="调整项目" align="center" width="200">
<el-table-column label="原项目号" prop="originalProjectCode" align="center" show-overflow-tooltip />
<el-table-column label="原项目名" prop="originalProjectName" align="center" show-overflow-tooltip />
<el-table-column label="原工时" prop="originalHours" align="center" />
<el-table-column label="调整项目号" align="center" width="200">
<template #default="scope">
<el-select
v-model="scope.row.adjustedProjectId"
filterable
clearable
placeholder="请选择项目"
placeholder="选择项目号"
v-if="scope.row.isProject === '1'"
@change="(val) => handleProjectChange(val, scope.row)"
>
<el-option v-for="item in projectList" :key="item.projectId" :label="item.projectCode" :value="item.projectId" />
</el-select>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="调整项目名" align="center" width="250">
<template #default="scope">
<el-select
v-model="scope.row.adjustedProjectId"
filterable
clearable
placeholder="选择项目名"
v-if="scope.row.isProject === '1'"
@change="(val) => handleProjectChange(val, scope.row)"
>
@ -228,6 +256,7 @@ import {
import { TimesheetSummaryVO, TimesheetSummaryQuery, TimesheetSummaryForm } from '@/api/oa/erp/timesheetSummary/types';
import { getErpProjectInfoList } from '@/api/oa/erp/projectInfo';
import { allListDept } from '@/api/system/dept';
import { listUser } from '@/api/system/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -249,6 +278,13 @@ const dialog = reactive<DialogOption>({
});
const deptList = ref<any[]>([]);
const userList = ref<any[]>([]);
/** 查询用户列表 */
const getUserList = async () => {
const res = await listUser({ pageNum: 1, pageSize: 1000 } as any);
userList.value = res.rows;
};
/** 查询部门列表 */
const getDeptList = async () => {
@ -262,8 +298,8 @@ const columns = ref<FieldOption[]>([
{ key: 1, label: `租户编号`, visible: true },
{ key: 2, label: `汇总编号`, visible: true },
{ key: 3, label: `月份编码(YYYYMM)`, visible: true },
{ key: 4, label: `部门ID`, visible: true },
{ key: 5, label: `汇总人(部门负责人)用户ID`, visible: true },
{ key: 4, label: `部门`, visible: true },
{ key: 5, label: `部门负责人`, visible: true },
{ key: 6, label: `关联月标准工时ID`, visible: false },
{ key: 7, label: `月标准工时天数(冗余,取自标准月表)`, visible: true },
{ key: 8, label: `项目工时合计(天)`, visible: true },
@ -409,7 +445,8 @@ const handleExport = () => {
proxy?.download(
'oa/erp/timesheetSummary/export',
{
...queryParams.value
...queryParams.value,
summaryIds: ids.value
},
`timesheetSummary_${new Date().getTime()}.xlsx`
);
@ -418,6 +455,7 @@ const handleExport = () => {
onMounted(() => {
getDeptList();
getList();
getUserList();
});
//
@ -427,14 +465,22 @@ const adjustDialog = reactive({
});
const adjustData = ref<TimesheetSummaryVO | null>(null);
const projectList = ref<any[]>([]);
const staffSearchName = ref('');
const staffSearchUserId = ref<string | number | undefined>(undefined);
const staffSearchProjectCode = ref('');
const staffSearchProjectName = ref('');
const filteredDetailList = computed(() => {
if (!adjustData.value || !adjustData.value.summaryDetailList) return [];
if (!staffSearchName.value) return adjustData.value.summaryDetailList;
return adjustData.value.summaryDetailList.filter(
(item) => item.staffName && item.staffName.toLowerCase().includes(staffSearchName.value.toLowerCase())
);
return adjustData.value.summaryDetailList.filter((item) => {
const matchUser = !staffSearchUserId.value || item.staffUserId === staffSearchUserId.value;
const matchProjCode =
!staffSearchProjectCode.value ||
(item.originalProjectCode && item.originalProjectCode.toLowerCase().includes(staffSearchProjectCode.value.toLowerCase()));
const matchProjName =
!staffSearchProjectName.value ||
(item.originalProjectName && item.originalProjectName.toLowerCase().includes(staffSearchProjectName.value.toLowerCase()));
return matchUser && matchProjCode && matchProjName;
});
});
const loadProjectList = async () => {
@ -451,7 +497,9 @@ const handleAdjust = async (row: TimesheetSummaryVO) => {
const summaryId = row.summaryId;
const res = await getTimesheetSummary(summaryId);
adjustData.value = res.data;
staffSearchName.value = '';
staffSearchUserId.value = undefined;
staffSearchProjectCode.value = '';
staffSearchProjectName.value = '';
await loadProjectList();

Loading…
Cancel
Save