diff --git a/src/views/oa/erp/erpProjectPlan/gantt.vue b/src/views/oa/erp/erpProjectPlan/gantt.vue
index d7341f7..367c305 100644
--- a/src/views/oa/erp/erpProjectPlan/gantt.vue
+++ b/src/views/oa/erp/erpProjectPlan/gantt.vue
@@ -30,8 +30,8 @@
{{ taskList.length }}
-
- {{ formatDisplayDate(new Date()) }}
+
+ {{ lastPlanEndDate }}
@@ -129,6 +129,25 @@ const planStatusLabel = computed(() => {
return statusMap.value[planDetail.value.projectPlanStatus] || planDetail.value.projectPlanStatus;
});
+const lastPlanEndDate = computed(() => {
+ if (!taskList.value.length) {
+ return '-';
+ }
+ let maxTs: number | null = null;
+ taskList.value.forEach(task => {
+ const ts = toTimestamp(task.planEnd);
+ if (ts !== null) {
+ if (maxTs === null || ts > maxTs) {
+ maxTs = ts;
+ }
+ }
+ });
+ if (maxTs === null) {
+ return '-';
+ }
+ return formatDisplayDate(new Date(maxTs));
+});
+
const projectPlanId = computed(() => route.params.projectPlanId as string);
const renderGanttItem = (params: any, api: any) => {
@@ -180,41 +199,65 @@ const updateChart = () => {
let min = Number.POSITIVE_INFINITY;
let max = Number.NEGATIVE_INFINITY;
- const planData = taskList.value
- .map((task, index) => {
- const start = toTimestamp(task.planStart);
- const end = toTimestamp(task.planEnd);
- if (start === null || end === null || end < start) {
- return null;
- }
+ const planBarData: any[] = [];
+ const planPointData: any[] = [];
+
+ taskList.value.forEach((task, index) => {
+ const start = toTimestamp(task.planStart);
+ const end = toTimestamp(task.planEnd);
+ if (start === null || end === null) {
+ return;
+ }
+ // 同一天的任务使用散点展示,避免零宽度矩形不可见
+ if (end <= start) {
+ min = Math.min(min, start);
+ max = Math.max(max, start);
+ planPointData.push({
+ name: task.taskName,
+ value: [start, index],
+ task
+ });
+ } else {
min = Math.min(min, start);
max = Math.max(max, end);
- return {
+ planBarData.push({
name: task.taskName,
value: [index, start, end],
task
- };
- })
- .filter(Boolean) as Array<{ name: string; value: [number, number, number]; task: GanttTask }>;
+ });
+ }
+ });
- const actualData = showActual.value
- ? (taskList.value
- .map((task, index) => {
- const start = toTimestamp(task.realStart);
- const end = toTimestamp(task.realEnd);
- if (start === null || end === null || end < start) {
- return null;
- }
- min = Math.min(min, start);
- max = Math.max(max, end);
- return {
- name: `${task.taskName}-实际`,
- value: [index, start, end],
- task
- };
- })
- .filter(Boolean) as Array<{ name: string; value: [number, number, number]; task: GanttTask }>)
- : [];
+ const actualBarData: any[] = [];
+ const actualPointData: any[] = [];
+
+ if (showActual.value) {
+ taskList.value.forEach((task, index) => {
+ const start = toTimestamp(task.realStart);
+ const end = toTimestamp(task.realEnd);
+ if (start === null || end === null) {
+ return;
+ }
+ // 实际进度同一天也使用散点展示
+ if (end <= start) {
+ min = Math.min(min, start);
+ max = Math.max(max, start);
+ actualPointData.push({
+ name: `${task.taskName}-实际`,
+ value: [start, index],
+ task
+ });
+ } else {
+ min = Math.min(min, start);
+ max = Math.max(max, end);
+ actualBarData.push({
+ name: `${task.taskName}-实际`,
+ value: [index, start, end],
+ task
+ });
+ }
+ });
+ }
if (min === Number.POSITIVE_INFINITY || max === Number.NEGATIVE_INFINITY) {
const now = Date.now();
@@ -223,24 +266,42 @@ const updateChart = () => {
}
const series: any[] = [];
- if (planData.length) {
+ if (planBarData.length) {
series.push({
name: '计划进度',
type: 'custom',
renderItem: renderGanttItem,
itemStyle: { color: '#91cc75', opacity: 0.9 },
encode: { x: [1, 2], y: 0 },
- data: planData
+ data: planBarData
});
}
- if (actualData.length) {
+ if (planPointData.length) {
+ series.push({
+ name: '计划进度(单日)',
+ type: 'scatter',
+ symbolSize: 10,
+ itemStyle: { color: '#91cc75', opacity: 0.9 },
+ data: planPointData
+ });
+ }
+ if (actualBarData.length) {
series.push({
name: '实际进度',
type: 'custom',
renderItem: renderGanttItem,
itemStyle: { color: '#5470c6', opacity: 0.75 },
encode: { x: [1, 2], y: 0 },
- data: actualData
+ data: actualBarData
+ });
+ }
+ if (actualPointData.length) {
+ series.push({
+ name: '实际进度(单日)',
+ type: 'scatter',
+ symbolSize: 10,
+ itemStyle: { color: '#5470c6', opacity: 0.75 },
+ data: actualPointData
});
}