项目周报界面完善

dev
lh 2 months ago
parent e047db3cbd
commit e3c3c9bc9d

@ -137,6 +137,16 @@
<!-- 项目周报具体信息表格 -->
<div style="margin-bottom: 16px">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-if="routeParams.type === 'view'"
v-hasPermi="['oa/erp:projectReportDetail:remove']"
>删除</el-button
>
<el-button
type="warning"
plain
@ -147,7 +157,14 @@
>导出</el-button
>
</div>
<el-table v-loading="buttonLoading" border :data="projectReportDetailList" v-if="routeParams.type !== 'add' && routeParams.type !== 'approval'">
<el-table
v-loading="buttonLoading"
border
:data="projectReportDetailList"
v-if="routeParams.type !== 'add' && routeParams.type !== 'approval'"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目周报明细ID" align="center" prop="reportDetailId" v-if="columns[0].visible" />
<el-table-column label="项目周报ID" align="center" prop="reportId" v-if="columns[1].visible" />
<el-table-column label="项目ID" align="center" prop="projectId" v-if="columns[2].visible" />
@ -188,6 +205,13 @@
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0 && routeParams.type === 'view'"
:total="total"
v-model:page="projectReportFormQuery.pageNum"
v-model:limit="projectReportFormQuery.pageSize"
@pagination="getProjectDetail"
/>
<el-form
ref="projectReportDetailFormRef"
:model="projectReportForm"
@ -236,36 +260,6 @@
<el-input v-model="projectReportForm.secondaryPhase" placeholder="请输入二级进度阶段" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="本周完成工作" prop="tasksCompleted">
<el-input v-model="projectReportForm.tasksCompleted" placeholder="请输入本周完成工作" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="下周计划" prop="nextPlan">
<el-input v-model="projectReportForm.nextPlan" placeholder="请输入下周计划" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="风险及解决措施" prop="riskResolution">
<el-input v-model="projectReportForm.riskResolution" placeholder="请输入风险及解决措施" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划完成率" prop="plannedCompletionRate">
<el-input v-model="projectReportForm.plannedCompletionRate" placeholder="请输入计划完成率" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="周报情况说明" prop="informationNote">
<el-input v-model="projectReportForm.informationNote" placeholder="请输入周报情况说明" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序号" prop="sortOrder">
<el-input v-model="projectReportForm.sortOrder" placeholder="请输入排序号" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目状态" prop="scheduleStatus">
<el-select v-model="projectReportForm.scheduleStatus" placeholder="请选择项目状态" clearable>
@ -273,12 +267,53 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划完成率" prop="plannedCompletionRate">
<el-input
v-model="projectReportForm.plannedCompletionRate"
placeholder="请输入0-1之间的数字"
clearable
type="number"
:min="0"
:max="1"
:step="0.01"
@input="validatePlannedCompletionRate"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="本周完成工作" prop="tasksCompleted">
<el-input v-model="projectReportForm.tasksCompleted" type="textarea" placeholder="请输入本周完成工作" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="下周计划" prop="nextPlan">
<el-input v-model="projectReportForm.nextPlan" type="textarea" placeholder="请输入下周计划" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="风险及解决措施" prop="riskResolution">
<el-input v-model="projectReportForm.riskResolution" type="textarea" placeholder="请输入风险及解决措施" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="周报情况说明" prop="informationNote">
<el-input v-model="projectReportForm.informationNote" type="textarea" placeholder="请输入周报情况说明" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="排序号" prop="sortOrder">
<el-input v-model="projectReportForm.sortOrder" placeholder="请输入排序号" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="合同ID" prop="contractId">
<el-input v-model="projectReportForm.contractId" placeholder="请输入合同ID" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="12" v-show="false">
<el-form-item label="附件ID" prop="ossId">
<el-input v-model="projectReportForm.ossId" placeholder="请输入附件ID" clearable />
</el-form-item>
@ -385,7 +420,7 @@
</div>
</template>
<script setup name="ContractInfoEdit" lang="ts">
<script setup name="ProjectReportEdit" lang="ts">
import { ContractMaterialVO, ContractprojectReportForm } from '@/api/oa/erp/contractMaterial/types';
import { getBaseUnitInfoList } from '@/api/oa/base/unitInfo';
import { getRuleGenerateCode } from '@/api/system/codeRule';
@ -416,7 +451,7 @@ import {
ProjectReportDetailForm,
ProjectReportDetailFormEx
} from '@/api/oa/erp/projectReportDetail/types';
import { fa } from 'element-plus/es/locale/index.mjs';
import { fa, tr } from 'element-plus/es/locale/index.mjs';
import ProjectSelect from '@/components/ProjectSelect/index.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -532,7 +567,6 @@ const getList = async () => {
// loading.value = true;
const res = await listProjectReport(queryParams.value);
projectReportList.value = res.rows;
total.value = res.total;
// loading.value = false;
};
//
@ -591,7 +625,15 @@ const ReportDialog = reactive<DialogOption>({
const projectReportDetailFormRef = ref<ElFormInstance>();
const projectReportDetailList = ref<ProjectReportDetailVO[]>([]);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectReportDetailVO[]) => {
ids.value = selection.map((item) => item.reportDetailId);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
//
const hasReportDetails = computed(() => {
return (
@ -699,15 +741,82 @@ const projectReportFormQuery = ref<ProjectReportDetailQuery>({
const reportRules = {
tasksCompleted: [{ required: true, message: '本周完成工作不能为空', trigger: 'blur' }],
nextPlan: [{ required: true, message: '下周计划不能为空', trigger: 'blur' }],
secondaryPhase: [{ required: true, message: '二级进度阶段不能为空', trigger: 'blur' }]
secondaryPhase: [{ required: true, message: '二级进度阶段不能为空', trigger: 'blur' }],
plannedCompletionRate: [
{ required: false, message: '请填写计划完成率', trigger: 'blur' },
{
validator: (rule: any, value: any, callback: any) => {
if (value === null || value === undefined || value === '') {
callback();
return;
}
//
const numValue = Number(value);
//
if (isNaN(numValue)) {
callback(new Error('请输入有效的数字'));
return;
}
// 0-1
if (numValue < 0 || numValue > 1) {
callback(new Error('请输入0-1之间的数字'));
return;
}
//
const decimalPlaces = value.toString().split('.')[1];
if (decimalPlaces && decimalPlaces.length > 2) {
callback(new Error('最多支持两位小数'));
return;
}
callback();
},
trigger: 'blur'
}
]
};
//
const validatePlannedCompletionRate = (value: string) => {
if (!value) return;
//
const numValue = Number(value);
//
if (isNaN(numValue)) {
projectReportForm.value.plannedCompletionRate = '';
return;
}
// 0-1
if (numValue < 0) {
projectReportForm.value.plannedCompletionRate = 0;
} else if (numValue > 1) {
projectReportForm.value.plannedCompletionRate = 1;
} else {
//
const decimalPlaces = value.split('.')[1];
if (decimalPlaces && decimalPlaces.length > 2) {
projectReportForm.value.plannedCompletionRate = parseFloat(numValue.toFixed(2));
}
}
};
//
const formattedPlannedCompletionRate = computed(() => {
if (projectReportForm.value.plannedCompletionRate === null || projectReportForm.value.plannedCompletionRate === undefined) {
return '';
}
//
const handleAddReport = () => {
resetProjectReportForm();
projectReportForm.value.contractId = form.value.contractId;
ReportDialog.visible = true;
ReportDialog.title = '新增周报明细';
const value = Number(projectReportForm.value.plannedCompletionRate);
if (isNaN(value)) return '';
// 2
return `${(value * 100).toFixed(2)}%`;
});
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectReportDetailVO) => {
const _reportDetailIds = row?.reportDetailId || ids.value;
await proxy?.$modal.confirm('是否确认删除项目周报明细编号为"' + _reportDetailIds + '"的数据项?').finally(() => (buttonLoading.value = false));
await delProjectReportDetail(_reportDetailIds);
proxy?.$modal.msgSuccess('删除成功');
await getProjectDetail();
};
//
@ -824,53 +933,54 @@ const getWorkWeek = (dateString) => {
//
const initDefaultDate = () => {
if (routeParams.value.type === 'add') {
//
const cachedFormData = proxy?.$cache.local.getJSON(CACHE_KEYS.PROJECT_REPORT_DRAFT);
const cachedDetailData = proxy?.$cache.local.getJSON(CACHE_KEYS.PROJECT_REPORT_DETAIL_DRAFT);
// reportData使
if (!routeParams.value.reportData) {
//
const cachedFormData = proxy?.$cache.local.getJSON(CACHE_KEYS.PROJECT_REPORT_DRAFT);
const cachedDetailData = proxy?.$cache.local.getJSON(CACHE_KEYS.PROJECT_REPORT_DETAIL_DRAFT);
if (cachedFormData) {
//
Object.assign(form.value, cachedFormData);
}
if (cachedDetailData) {
//
Object.assign(projectReportForm.value, cachedDetailData);
// fillTime
if (projectReportForm.value.fillTime) {
const [date] = projectReportForm.value.fillTime.split(' ');
if (date) {
datePart.value = date;
//
projectReportForm.value.currentWorkWeek = getWorkWeek(date);
}
if (cachedFormData) {
//
Object.assign(form.value, cachedFormData);
}
} else {
//
const now = new Date();
// YYYY-MM-DD
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const dateStr = `${year}-${month}-${day}`;
// HH:mm:ss
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
const timeStr = `${hours}:${minutes}:${seconds}`;
//
datePart.value = dateStr;
//
projectReportForm.value.fillTime = `${dateStr} ${timeStr}`;
//
projectReportForm.value.currentWorkWeek = getWorkWeek(dateStr);
if (cachedDetailData) {
//
Object.assign(projectReportForm.value, cachedDetailData);
}
}
// fillTime
const now = new Date();
// YYYY-MM-DD
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const dateStr = `${year}-${month}-${day}`;
// HH:mm:ss
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
const timeStr = `${hours}:${minutes}:${seconds}`;
//
datePart.value = dateStr;
//
// fillTime使
if (!projectReportForm.value.fillTime) {
projectReportForm.value.fillTime = `${dateStr} ${timeStr}`;
} else {
// fillTime DateTime
if (projectReportForm.value.fillTime && !projectReportForm.value.fillTime.includes(' ')) {
projectReportForm.value.fillTime = `${projectReportForm.value.fillTime} ${timeStr}`;
}
}
//
projectReportForm.value.currentWorkWeek = getWorkWeek(dateStr);
}
};
@ -1019,6 +1129,13 @@ const handleClearDraft = () => {
datePart.value = '';
initDefaultDate();
};
const getProjectDetail = async () => {
const res = await listProjectReportDetail(projectReportFormQuery.value);
buttonLoading.value = true;
projectReportDetailList.value = res.rows;
total.value = res.total;
buttonLoading.value = false;
};
/** 提交按钮 */
const submitForm = async (status: string, mode: boolean) => {
try {
@ -1125,14 +1242,16 @@ onMounted(async () => {
const reportData = JSON.parse(decodeURIComponent(reportDataStr));
Object.assign(form.value, reportData);
if (routeParams.value.type === 'add') {
initDefaultDate();
Object.assign(projectReportForm.value, reportData);
projectReportForm.value.informationNote = '';
} else if (routeParams.value.type === 'view') {
Object.assign(projectReportFormQuery.value, reportData);
Object.assign(projectReportFormQuery.value, reportData.reportId);
const res = await listProjectReportDetail(projectReportFormQuery.value);
console.log()
buttonLoading.value = true;
projectReportDetailList.value = res.rows;
console.log(projectReportDetailList.value);
total.value = res.total;
buttonLoading.value = false;
}
proxy?.$modal.closeLoading();
} else if (routeParams.value.type === 'add') {

@ -4,47 +4,45 @@
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
<el-row :gutter="10" class="form-row">
<el-col :span="12">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery">
<!-- <template #suffix>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery">
<!-- <template #suffix>
<el-icon style="cursor: pointer; margin-right: 4px; font-size: 14px" @click="openProjectSelect">
<Search />
</el-icon>
</template> -->
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
</el-input>
</el-form-item>
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目经理" prop="managerName">
<el-input v-model="queryParams.managerName" placeholder="请输入项目经理" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="当前里程碑" prop="milestonePlan">
<el-input v-model="queryParams.milestonePlan" placeholder="请输入当前里程碑" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="部门名称" prop="deptName">
<el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="部门负责人" prop="chargeName">
<el-input v-model="queryParams.chargeName" placeholder="请输入部门负责人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
<el-row :gutter="10" class="form-row">
<el-col :span="12"> </el-col>
<el-col :span="12"> </el-col>
</el-row>
<el-row :gutter="10" class="form-row">
<el-col :span="12">
<el-form-item label="项目经理" prop="managerName">
<el-input v-model="queryParams.managerName" placeholder="请输入项目经理" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="当前里程碑" prop="milestonePlan">
<el-input v-model="queryParams.milestonePlan" placeholder="请输入当前里程碑" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="12"> </el-col>
<el-col :span="12"> </el-col>
</el-row>
<el-row :gutter="10" class="form-row">
<el-col :span="12">
<el-form-item label="部门名称" prop="deptName">
<el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="部门负责人" prop="chargeName">
<el-input v-model="queryParams.chargeName" placeholder="请输入部门负责人" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-col>
<el-col :span="12"> </el-col>
<el-col :span="12"> </el-col>
<el-col :span="12" v-show="false">
<el-form-item label="周报ID" prop="reportId">
<el-input v-model="queryParams.reportId" placeholder="请点击右侧图标选择项目" />
@ -102,12 +100,7 @@
</el-col>
</el-row>
<el-row :gutter="10" class="form-row">
<el-col :span="24">
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-col>
<el-col :span="24"> </el-col>
</el-row>
</el-form>
</el-card>
@ -165,7 +158,7 @@
<el-tooltip content="查看详情" placement="top">
<el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip content="修改" placement="top">
<!-- <el-tooltip content="修改" placement="top">
<el-button
link
type="primary"
@ -173,7 +166,7 @@
@click="handleUpdateReport(scope.row)"
v-hasPermi="['oa/erp:projectReport:edit']"
></el-button>
</el-tooltip>
</el-tooltip> -->
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/erp:projectReport:remove']"></el-button>
</el-tooltip>
@ -220,7 +213,6 @@
placeholder="请选择项目经理"
clearable
filterable
:loading="loadingManagers"
:disabled="!form.deptId"
@change="handleManagerChange"
>
@ -235,7 +227,6 @@
placeholder="请选择部门负责人"
clearable
filterable
:loading="loadingCharges"
:disabled="!form.deptId"
@change="handleChargeChange"
>
@ -252,7 +243,6 @@
placeholder="请选择分管副总"
clearable
filterable
:loading="loadingDeputies"
:disabled="!form.deptId"
@change="handleDeputyChange"
>
@ -426,10 +416,8 @@ const deptList = ref<any[]>([]);
const managerList = ref<any[]>([]);
const chargeList = ref<any[]>([]);
const deputyList = ref<any[]>([]);
const loadingManagers = ref(false);
const loadingCharges = ref(false);
const loadingDeputies = ref(false);
const loadingUsers = ref(false);
//
const getDeptList = async () => {
try {
@ -440,57 +428,8 @@ const getDeptList = async () => {
deptList.value = [];
}
};
//
const getManagers = async (deptId: number | string) => {
try {
loadingManagers.value = true;
const res = await listUserByDeptAndRole({
deptId: deptId,
roleName: ''
});
managerList.value = res.data || [];
} catch (error) {
console.error('获取项目经理列表失败:', error);
managerList.value = [];
} finally {
loadingManagers.value = false;
}
};
//
const getCharges = async (deptId: number | string) => {
try {
loadingCharges.value = true;
const res = await listUserByDeptAndRole({
deptId: deptId,
roleName: ''
});
chargeList.value = res.data || [];
} catch (error) {
console.error('获取部门负责人列表失败:', error);
chargeList.value = [];
} finally {
loadingCharges.value = false;
}
};
//
const getDeputies = async (deptId: number | string) => {
try {
loadingDeputies.value = true;
const res = await listUserByDeptAndRole({
deptId: deptId,
roleName: ''
});
deputyList.value = res.data || [];
} catch (error) {
console.error('获取分管副总列表失败:', error);
deputyList.value = [];
} finally {
loadingDeputies.value = false;
}
};
// ID
// ID
const getUsersByDept = async (deptId: number | string) => {
if (!deptId) {
managerList.value = [];
@ -500,10 +439,38 @@ const getUsersByDept = async (deptId: number | string) => {
}
try {
//
await Promise.all([getManagers(deptId), getCharges(deptId), getDeputies(deptId)]);
loadingUsers.value = true;
//
const currentDeptUsers = await listUserByDeptId(deptId);
// ID
const currentDept = deptList.value.find((dept) => String(dept.deptId) === String(deptId));
if (currentDept) {
//
managerList.value = currentDeptUsers.data || [];
chargeList.value = currentDeptUsers.data || [];
//
if (currentDept.parentId && currentDept.parentId !== '0') {
const parentDeptUsers = await listUserByDeptId(currentDept.parentId);
deputyList.value = parentDeptUsers.data || [];
} else {
//
deputyList.value = currentDeptUsers.data || [];
}
//
form.value.deptName = currentDept.deptName || currentDept.label;
}
} catch (error) {
console.error('获取用户列表失败:', error);
managerList.value = [];
chargeList.value = [];
deputyList.value = [];
} finally {
loadingUsers.value = false;
}
};
//
@ -516,19 +483,14 @@ const handleDeptChange = async (deptId: number | string) => {
form.value.chargeName = undefined;
form.value.deputyName = undefined;
//
//
managerList.value = [];
chargeList.value = [];
deputyList.value = [];
//
await getUsersByDept(deptId);
//
const selectedDept = deptList.value.find((dept) => {
// ID
return String(dept.deptId) === String(deptId) || String(dept.id) === String(deptId);
});
if (selectedDept) {
form.value.deptName = selectedDept.deptName || selectedDept.label;
}
};
//
const handleManagerChange = (userId: number | string) => {
const selectedUser = managerList.value.find((user) => String(user.userId) === String(userId));
@ -690,8 +652,6 @@ const handleUpdate = async (row?: ProjectReportVO) => {
form.value = { ...initFormData };
Object.assign(form.value, res.data);
console.log('编辑获取的数据:', res.data);
//
if (form.value.deptId) {
await getUsersByDept(form.value.deptId);
@ -701,12 +661,6 @@ const handleUpdate = async (row?: ProjectReportVO) => {
console.log('项目经理列表:', managerList.value);
console.log('部门负责人列表:', chargeList.value);
console.log('分管副总列表:', deputyList.value);
//
// IDlabel
// managerName
//
}
dialog.visible = true;

Loading…
Cancel
Save