|
|
|
|
@@ -1,6 +1,545 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="gl-page-content">工作负载</div>
|
|
|
|
|
<div class="gl-page-content">
|
|
|
|
|
|
|
|
|
|
<div class="page-filter-box">
|
|
|
|
|
<el-form :model="filterFprmData" inline>
|
|
|
|
|
<el-form-item label="用户组:">
|
|
|
|
|
<el-select v-model="filterFprmData.userGroupId" class="mw200" @change="filterWorkLoadFn">
|
|
|
|
|
<el-option v-for="item in groupList" :key="item.id" :label="item.groupName" :value="item.id">
|
|
|
|
|
</el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="开始时间:">
|
|
|
|
|
<el-date-picker
|
|
|
|
|
v-model="filterFprmData.beginTime"
|
|
|
|
|
type="datetime"
|
|
|
|
|
placeholder="请选择开始时间"
|
|
|
|
|
format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
@change="filterWorkLoadFn"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="结束时间:">
|
|
|
|
|
<el-date-picker
|
|
|
|
|
v-model="filterFprmData.endTime"
|
|
|
|
|
type="datetime"
|
|
|
|
|
placeholder="请选择开始时间"
|
|
|
|
|
format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
@change="filterWorkLoadFn"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<el-radio-group v-model="filterFprmData.dateType" @change="changeDateTypeFn">
|
|
|
|
|
<el-radio value="month">月</el-radio>
|
|
|
|
|
<el-radio value="week">周</el-radio>
|
|
|
|
|
<el-radio value="day">日</el-radio>
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item class="mr0">
|
|
|
|
|
<el-button type="primary" @change="filterWorkLoadFn">查询</el-button>
|
|
|
|
|
<el-button type="" @click="clearParamFn">清空</el-button>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="page-content">
|
|
|
|
|
<div ref="ganttRef" class="gant-page" v-loading="loading"></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="page-footer">
|
|
|
|
|
<template v-for="(item, index) in colorList" :key="index">
|
|
|
|
|
<div class="color-item" v-if="index > 0">
|
|
|
|
|
<div :style="{ background: item }"></div>
|
|
|
|
|
<div>{{ index >= 5 ? '大于或等于5个任务' : index + '个任务' }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { ref, reactive, onMounted, nextTick, onBeforeUnmount } from 'vue';
|
|
|
|
|
import { gantt } from 'dhtmlx-gantt';
|
|
|
|
|
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css';
|
|
|
|
|
import dayjs from 'dayjs';
|
|
|
|
|
import isBetween from 'dayjs/plugin/isBetween';
|
|
|
|
|
import isoWeek from 'dayjs/plugin/isoWeek';
|
|
|
|
|
import weekOfYear from 'dayjs/plugin/weekOfYear';
|
|
|
|
|
import { userQueryGroupApi, userQueryGroupDetailApi } from '@/api/system/user';
|
|
|
|
|
import { getListUserWorkloadsApi } from '@/api/project/task';
|
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
|
import { isWorkday } from 'chinese-workday';
|
|
|
|
|
|
|
|
|
|
dayjs.extend(isBetween);
|
|
|
|
|
dayjs.extend(weekOfYear);
|
|
|
|
|
dayjs.extend(isoWeek);
|
|
|
|
|
let Gantt: any = gantt;
|
|
|
|
|
const ganttEvents = ref<any>([]);
|
|
|
|
|
const colorList: string[] = ['#ffffff', '#fff6e6', '#ffdca3', '#ff9729', '#ff7d00', '#d96200']; // 格子颜色
|
|
|
|
|
const taskOriginData = ref<any>([]); // 所有用户的任务数据
|
|
|
|
|
const loading = ref<boolean>(false);
|
|
|
|
|
const workDaysRange = ref<number>(0);
|
|
|
|
|
|
|
|
|
|
const filterFprmData = reactive<any>({
|
|
|
|
|
userGroupId: '',
|
|
|
|
|
userIds: [],
|
|
|
|
|
beginTime: '',
|
|
|
|
|
endTime: '',
|
|
|
|
|
dateType: 'week',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const ganttRef = ref();
|
|
|
|
|
|
|
|
|
|
const changeDateTypeFn = () => {
|
|
|
|
|
loading.value = true;
|
|
|
|
|
// 加载动画
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
setUserDayWork(filterFprmData.beginTime, filterFprmData.endTime);
|
|
|
|
|
Gantt.ext.zoom.setLevel(filterFprmData.dateType);
|
|
|
|
|
loading.value = false;
|
|
|
|
|
}, 200);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const groupList = ref<any>([]);
|
|
|
|
|
const getUserGroupFn = async () => {
|
|
|
|
|
const res: any = await userQueryGroupApi({
|
|
|
|
|
current: 1,
|
|
|
|
|
size: 999,
|
|
|
|
|
});
|
|
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
groupList.value = res.data.data;
|
|
|
|
|
if (groupList.value?.length) {
|
|
|
|
|
filterFprmData.userGroupId = groupList.value[0].id;
|
|
|
|
|
filterFprmData.userIds = await queryGroupUserListFn(filterFprmData.userGroupId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取用户组内成员
|
|
|
|
|
const queryGroupUserListFn = async (id: any) => {
|
|
|
|
|
const res: any = await userQueryGroupDetailApi({
|
|
|
|
|
id,
|
|
|
|
|
current: 1,
|
|
|
|
|
size: 999,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
const usrids = res.data.users.data.map((item: any) => {
|
|
|
|
|
return item.userId;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return usrids;
|
|
|
|
|
} else {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getWorkLoadDataFn = async () => {
|
|
|
|
|
if (!filterFprmData.userIds.length) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loading.value = true;
|
|
|
|
|
Gantt.clearAll();
|
|
|
|
|
taskOriginData.value = [];
|
|
|
|
|
|
|
|
|
|
const res: any = await getListUserWorkloadsApi({
|
|
|
|
|
...filterFprmData,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
taskOriginData.value = res.data;
|
|
|
|
|
|
|
|
|
|
Gantt.config.start_date = filterFprmData.beginTime;
|
|
|
|
|
Gantt.config.end_date = filterFprmData.endTime;
|
|
|
|
|
Gantt.ext.zoom.setLevel(filterFprmData.dateType);
|
|
|
|
|
if (res.data.length > 0) {
|
|
|
|
|
calculateWorkDay([filterFprmData.beginTime, filterFprmData.endTime]);
|
|
|
|
|
formatUserTask(res.data, [filterFprmData.beginTime, filterFprmData.endTime]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setUserDayWork(filterFprmData.beginTime, filterFprmData.endTime);
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
Gantt.render();
|
|
|
|
|
});
|
|
|
|
|
loading.value = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const formatUserTask = (data: any, time: any) => {
|
|
|
|
|
const ganttData = data.map((item: any, index: any) => {
|
|
|
|
|
let jobSaturation = 0;
|
|
|
|
|
if (item.taskList?.length > 0) {
|
|
|
|
|
item.taskList.forEach((item_1: any) => {
|
|
|
|
|
jobSaturation = jobSaturation + workDaysRange.value * item_1.workRate;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
id: index + 1,
|
|
|
|
|
userName: item.userName,
|
|
|
|
|
userId: item.userId,
|
|
|
|
|
taskNum: item.taskNum ? item.taskNum : 0,
|
|
|
|
|
jobSaturation: jobSaturation.toFixed(2),
|
|
|
|
|
start_date: time[0],
|
|
|
|
|
duration: dayjs(time[1]).diff(dayjs(time[0]), 'day'),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
Gantt.clearAll();
|
|
|
|
|
Gantt.parse({
|
|
|
|
|
data: ganttData,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取用户工作负载信息
|
|
|
|
|
const filterWorkLoadFn = async () => {
|
|
|
|
|
|
|
|
|
|
// 判断开始时间和截止时间
|
|
|
|
|
const begin = new Date(filterFprmData.beginTime).getTime();
|
|
|
|
|
const end = new Date(filterFprmData.endTime).getTime();
|
|
|
|
|
if (end < begin) {
|
|
|
|
|
ElMessage.warning('结束时间无法小于开始时间!');
|
|
|
|
|
filterFprmData.endTime = dayjs(new Date(filterFprmData.beginTime)).add(3, 'months').format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
|
}
|
|
|
|
|
filterFprmData.userIds = await queryGroupUserListFn(filterFprmData.userGroupId);
|
|
|
|
|
await refreshGanttFn();
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const clearParamFn = async () => {
|
|
|
|
|
await getUserGroupFn();
|
|
|
|
|
filterFprmData.beginTime = dayjs().subtract(3, 'month').format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
|
filterFprmData.endTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
|
await filterWorkLoadFn();
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 计算时间段中的工作日天数
|
|
|
|
|
const calculateWorkDay = ([startDate, endDate]: any) => {
|
|
|
|
|
|
|
|
|
|
let workdays = 0;
|
|
|
|
|
let currentDate = dayjs(startDate);
|
|
|
|
|
while (currentDate.isBefore(dayjs(endDate)) || currentDate.isSame(dayjs(endDate), 'day')) {
|
|
|
|
|
if (isWorkday(currentDate)) {
|
|
|
|
|
workdays++;
|
|
|
|
|
}
|
|
|
|
|
currentDate = currentDate.add(1, 'day');
|
|
|
|
|
}
|
|
|
|
|
workDaysRange.value = workdays;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 生成日期列表的函数
|
|
|
|
|
const generateDateList = (startDate: any, endDate: any, mode = 'day') => {
|
|
|
|
|
const result = [];
|
|
|
|
|
let formatStart = null;
|
|
|
|
|
let formatEnd = null;
|
|
|
|
|
if (mode === 'day') {
|
|
|
|
|
formatStart = dayjs(startDate);
|
|
|
|
|
formatEnd = dayjs(endDate);
|
|
|
|
|
} else if (mode === 'week') {
|
|
|
|
|
formatStart = dayjs(startDate).startOf('isoWeek');
|
|
|
|
|
formatEnd = dayjs(endDate).startOf('isoWeek');
|
|
|
|
|
} else if (mode === 'month') {
|
|
|
|
|
formatStart = dayjs(startDate).startOf('month');
|
|
|
|
|
formatEnd = dayjs(endDate).startOf('month');
|
|
|
|
|
}
|
|
|
|
|
if (!formatStart || !formatEnd) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
// 根据模式生成不同的日期列表
|
|
|
|
|
while (formatStart.isBefore(endDate) || formatStart.isSame(formatEnd)) {
|
|
|
|
|
result.push(formatStart.format('YYYY-MM-DD')); // 将日期加入结果列表
|
|
|
|
|
if (mode === 'day') {
|
|
|
|
|
formatStart = formatStart.add(1, 'day'); // 每天
|
|
|
|
|
} else if (mode === 'week') {
|
|
|
|
|
formatStart = formatStart.startOf('isoWeek').add(1, 'week'); // 每周第一天(星期一)
|
|
|
|
|
} else if (mode === 'month') {
|
|
|
|
|
formatStart = formatStart.startOf('month').add(1, 'month'); // 每月第一天
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 每个用户gantt单元格的任务
|
|
|
|
|
const userTimeItemWorkList: any = new Map();
|
|
|
|
|
const setUserDayWork: any = (startDate: any, endDate: any) => {
|
|
|
|
|
userTimeItemWorkList.clear();
|
|
|
|
|
const dateList = generateDateList(startDate, endDate, filterFprmData.dateType);
|
|
|
|
|
taskOriginData.value.forEach((item: any) => {
|
|
|
|
|
const dateWorkMap: any = new Map();
|
|
|
|
|
dateList.forEach((item_1: any) => {
|
|
|
|
|
const tasks = filterUserTask(item.taskList, item_1);
|
|
|
|
|
dateWorkMap.set(item_1, tasks);
|
|
|
|
|
});
|
|
|
|
|
userTimeItemWorkList.set(item.userName, dateWorkMap);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 筛选某一用户在某一周或者某月的任务
|
|
|
|
|
const filterUserTask = (taskList: any, date: any) => {
|
|
|
|
|
let filterTask: any = [];
|
|
|
|
|
filterTask = taskList
|
|
|
|
|
?.filter((item: any) => {
|
|
|
|
|
const startTime = dayjs(item.beginTime);
|
|
|
|
|
const endTime = startTime.add(item.days - 1, 'day');
|
|
|
|
|
const weekOrMonthStart = dayjs(date);
|
|
|
|
|
const addDays = filterFprmData.dateType === 'day' ? 0 : filterFprmData.dateType === 'week' ? 6 : weekOrMonthStart.daysInMonth() - 1;
|
|
|
|
|
const weekOrMonthEnd = weekOrMonthStart.add(addDays, 'day');
|
|
|
|
|
// 判断当前任务的时间段是否在这周
|
|
|
|
|
// 开始时间在这周||结束时间在这周||这周整个在任务的时间段中
|
|
|
|
|
return (
|
|
|
|
|
startTime.isBetween(weekOrMonthStart, weekOrMonthEnd, 'day', '[]') ||
|
|
|
|
|
endTime.isBetween(weekOrMonthStart, weekOrMonthEnd, 'day', '[]') ||
|
|
|
|
|
(weekOrMonthStart.isBetween(startTime, endTime, 'day', '[]') &&
|
|
|
|
|
weekOrMonthEnd.isBetween(startTime, endTime, 'day', '[]'))
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
?.map((item: any) => item.id);
|
|
|
|
|
return filterTask;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const initGantt = () => {
|
|
|
|
|
const zoomConfig: any = {
|
|
|
|
|
levels: [
|
|
|
|
|
{
|
|
|
|
|
name: 'day',
|
|
|
|
|
scales: [
|
|
|
|
|
{ unit: 'year', step: 1, format: '%Y' },
|
|
|
|
|
{ unit: 'month', step: 1, format: '%M' },
|
|
|
|
|
{ unit: 'week', step: 1, format: '%W周' },
|
|
|
|
|
{ unit: 'day', format: '%d' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'week',
|
|
|
|
|
min_column_width: 50,
|
|
|
|
|
scales: [
|
|
|
|
|
{ unit: 'year', step: 1, format: '%Y' },
|
|
|
|
|
{ unit: 'month', step: 1, format: '%M' },
|
|
|
|
|
{ unit: 'week', step: 1, format: '%W周' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'month',
|
|
|
|
|
scales: [
|
|
|
|
|
{ unit: 'year', step: 1, format: '%Y' },
|
|
|
|
|
{ unit: 'month', step: 1, format: '%M' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
Gantt.ext.zoom.init(zoomConfig);
|
|
|
|
|
Gantt.ext.zoom.setLevel('week');
|
|
|
|
|
Gantt.config.autosize = false;
|
|
|
|
|
Gantt.config.show_grid = true;
|
|
|
|
|
// 只读模式:打开后不可以操作甘特图
|
|
|
|
|
Gantt.config.readonly = true;
|
|
|
|
|
// 设置空数据
|
|
|
|
|
Gantt.config.show_empty_state = false;
|
|
|
|
|
Gantt.config.fit_tasks = true;
|
|
|
|
|
Gantt.config.min_column_width = 30;
|
|
|
|
|
Gantt.config.date_format = '%Y-%m-%d';
|
|
|
|
|
Gantt.config.scale_height = 28 * 3;
|
|
|
|
|
Gantt.config.select_task = false;
|
|
|
|
|
Gantt.i18n.setLocale('cn');
|
|
|
|
|
Gantt.config.columns = [
|
|
|
|
|
{
|
|
|
|
|
name: 'userName',
|
|
|
|
|
label: '姓名',
|
|
|
|
|
width: 200,
|
|
|
|
|
align: 'left',
|
|
|
|
|
onrender: (task: any, node: any) => {
|
|
|
|
|
console.log(node);
|
|
|
|
|
|
|
|
|
|
return `<img src="" style="width:15px;height:15px;margin-right:12px"></img>${task.userName}`;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'taskNum', label: '任务数量', align: 'left', width: 80,
|
|
|
|
|
onrender: (task: any, node: any) => {
|
|
|
|
|
console.log(node);
|
|
|
|
|
|
|
|
|
|
return `${task.taskNum}`;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
Gantt.templates.timeline_cell_content = function (task: any, date: any) {
|
|
|
|
|
|
|
|
|
|
let tasks: any = [];
|
|
|
|
|
if (task.userName && userTimeItemWorkList && userTimeItemWorkList.has(task.userName)) {
|
|
|
|
|
const currentNameMap = userTimeItemWorkList.get(task.userName);
|
|
|
|
|
const dateFormat = dayjs(date).format('YYYY-MM-DD');
|
|
|
|
|
if (currentNameMap && currentNameMap.has(dateFormat)) {
|
|
|
|
|
tasks = currentNameMap.get(dateFormat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return `<div class='${tasks?.length > 0 ? 'cell-style' : ''}' style='background:${colorList[tasks?.length >= 5 ? 5 : tasks?.length]
|
|
|
|
|
};cursor:${tasks?.length > 0 ? 'pointer' : 'default'}' userName=${task?.userName} userId=${task?.userId
|
|
|
|
|
} tasks=${JSON.stringify(tasks)} date=${dayjs(date).format('YYYY-MM-DD')}></div>`;
|
|
|
|
|
};
|
|
|
|
|
// gantt渲染结束添加监听单元格点击事件
|
|
|
|
|
const onGanttRender = Gantt.attachEvent('onGanttRender', function (e:any, date:any) {
|
|
|
|
|
|
|
|
|
|
console.log(e, 'e');
|
|
|
|
|
console.log(date, 'date');
|
|
|
|
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
monitorCellClickFn();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
ganttEvents.value.push(onGanttRender);
|
|
|
|
|
const onLoadStart = Gantt.attachEvent('onGanttScroll', function (e:any, date:any) {
|
|
|
|
|
console.log(e, 'e');
|
|
|
|
|
console.log(date, 'date');
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
monitorCellClickFn();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
ganttEvents.value.push(onLoadStart);
|
|
|
|
|
Gantt.init(ganttRef.value as HTMLElement);
|
|
|
|
|
Gantt.parse({
|
|
|
|
|
data: [],
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const monitorCellClickFn = () => {
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const refreshGanttFn = async () => {
|
|
|
|
|
Gantt.clearAll();
|
|
|
|
|
initGantt();
|
|
|
|
|
|
|
|
|
|
await getWorkLoadDataFn();
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
await getUserGroupFn();
|
|
|
|
|
filterFprmData.beginTime = dayjs().subtract(3, 'month').format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
|
filterFprmData.endTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
|
await refreshGanttFn();
|
|
|
|
|
console.log(filterFprmData, 'filterFprmData');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
ganttEvents.value?.forEach((item: any) => {
|
|
|
|
|
Gantt.detachEvent(item);
|
|
|
|
|
});
|
|
|
|
|
Gantt.templates.timeline_cell_content = function (task: any, date: any) {
|
|
|
|
|
console.log(task);
|
|
|
|
|
console.log(date);
|
|
|
|
|
|
|
|
|
|
return '';
|
|
|
|
|
};
|
|
|
|
|
Gantt.clearAll();
|
|
|
|
|
Gantt = null;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.gl-page-content {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
|
|
|
|
.page-filter-box {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 50px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
.mw200 {
|
|
|
|
|
width: 200px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-form {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.mr0 {
|
|
|
|
|
margin-right: 0px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.page-content {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: calc(100% - 80px);
|
|
|
|
|
|
|
|
|
|
.gant-page {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.page-footer {
|
|
|
|
|
height: 30px;
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
|
|
|
|
.color-item {
|
|
|
|
|
height: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
margin-left: 12px;
|
|
|
|
|
|
|
|
|
|
&>div:first-child {
|
|
|
|
|
height: 16px;
|
|
|
|
|
width: 16px;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
margin-right: 3px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.cell-style) {
|
|
|
|
|
height: 100%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
:deep(.gantt_links_area) {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.gantt_bars_area) {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.gantt_tree_icon.gantt_file) {
|
|
|
|
|
background-image: url('~@/assets/imgs/versionTree/user.svg') !important;
|
|
|
|
|
background-size: 60%;
|
|
|
|
|
}
|
|
|
|
|
:deep(
|
|
|
|
|
.gantt_grid_data .gantt_row.gantt_selected,
|
|
|
|
|
.gantt_grid_data .gantt_row.odd.gantt_selected,
|
|
|
|
|
.gantt_task_row.gantt_selected
|
|
|
|
|
) {
|
|
|
|
|
background-color: #96bdff;
|
|
|
|
|
&:hover {
|
|
|
|
|
background-color: #96bdff !important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
:deep(.gantt_grid_data .gantt_row.odd:hover, .gantt_grid_data .gantt_row:hover) {
|
|
|
|
|
background-color: #ecf7ff;
|
|
|
|
|
}
|
|
|
|
|
:deep(.gantt_grid_data .gantt_row:hover) {
|
|
|
|
|
background-color: #ecf7ff;
|
|
|
|
|
}
|
|
|
|
|
:deep(.task-table-container) {
|
|
|
|
|
height: 100%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
:deep(.gantt_row.gantt_row_task) {
|
|
|
|
|
position: none;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|