You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
8.8 KiB
343 lines
8.8 KiB
<template>
|
|
<!-- 项目标题 -->
|
|
<div class="navbar flex items-center justify-between">
|
|
<div class="project-name">{{ project.name }}</div>
|
|
<div class="project-action">
|
|
<ReloadOutlined :style="{ fontSize: 20 + 'px' }" />
|
|
<MoreOutlined :style="{ fontSize: 20 + 'px' }" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 角色 -->
|
|
<div class="role-list flex items-center">
|
|
<div class="role-box relative" v-for="(item, index) in roles" :key="index">
|
|
<div class="role-name" :class="{ mine: item.mine === 1 && currRoleId === item.id }">{{ item.name }}</div>
|
|
<div class="line-box absolute flex justify-center" v-if="item.mine === 1 && currRoleId === item.id"><div class="line"></div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 日常任务 -->
|
|
<div class="global">
|
|
<div class="global-box" v-if="permanentObj.permanentList && permanentObj.permanentList.length > 0">
|
|
<div class="global-task cursor-pointer" v-for="(item, index) in permanentObj.permanentList" :key="index" @click="toDetail(item)">
|
|
<template v-for="v in item.plugins">
|
|
<template v-if="v[0].pluginId == 1">{{ item.name }}</template>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 定期任务 -->
|
|
<div class="task-list" :style="{ height: 'calc(100vh - 160px - (' + globalHeight + 'px))' }">
|
|
<div class="task-box" v-for="(item, index) in taskObj.tasks" :key="index">
|
|
<div class="task-time flex items-center justify-between">
|
|
<div class="flex items-center">
|
|
<PlayCircleOutlined style="font-size: 23px; color: #999999" />
|
|
<span>{{ dayjs(item.planStart).format('D日 HH:mm') }}</span>
|
|
</div>
|
|
<div class="task-action"></div>
|
|
</div>
|
|
|
|
<div class="task-info">
|
|
<div>
|
|
<div class="task-card">
|
|
<div class="task-name cursor-pointer" @click="toDetail(item)">
|
|
<template v-for="v in item.plugins">
|
|
<template v-if="v[0].pluginId == 1">{{ item.name }}</template>
|
|
</template>
|
|
</div>
|
|
|
|
<div class="task-con" v-if="item.sonList && item.sonList.length > 0">
|
|
<div v-for="(val, key) in item.sonList" :key="key">
|
|
<a-checkbox>{{ val.name }}</a-checkbox>
|
|
</div>
|
|
</div>
|
|
<div class="open-icon" v-if="item.sonList" @click="openCard">
|
|
<img />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, watch, reactive, ref } from 'vue';
|
|
import { useStore } from 'vuex';
|
|
import dayjs from 'dayjs';
|
|
import { findShowRole, getRegularTask, findSonTask, findProjectById } from 'apis';
|
|
import { ReloadOutlined, MoreOutlined, PlayCircleOutlined } from '@ant-design/icons-vue';
|
|
|
|
const store = useStore();
|
|
const projectId = sessionStorage.getItem('projectId');
|
|
const project = computed(() => store.state.projects.project); // 项目信息
|
|
const currRoleId = computed(() => store.state.role.roleId); // 当前角色
|
|
const roles = ref([
|
|
{ id: 1, name: '项目经理', mine: 1, pm: 1, sequence: 1 },
|
|
{ id: 2, name: '运维', mine: 0, pm: 0, sequence: 2 },
|
|
]);
|
|
|
|
const permanents = computed(() => store.state.role.permanents); // 日常任务
|
|
const permanentObj = reactive({ permanentList: [] }); // 日常任务
|
|
const tasks = computed(() => store.state.role.tasks); // 定期任务
|
|
const taskObj = reactive({ tasks: [] }); // 定期任务
|
|
const globalHeight = ref(0); // 日常任务面板高度
|
|
|
|
init();
|
|
|
|
// 监听项目信息
|
|
watch(project, async () => {
|
|
permanentObj.permanentList = permanents.value;
|
|
taskObj.tasks = tasks.value;
|
|
|
|
await getRoles(project.value.id); // 通过项目id获取角色信息
|
|
await getPermanentData(currRoleId.value); // 根据角色查找永久的日常任务
|
|
await getTasks({ roleId: currRoleId.value });
|
|
});
|
|
|
|
// 刷新页面判断是否有项目ID缓存,有则加载对应的项目信息、角色、任务
|
|
async function init() {
|
|
try {
|
|
if (projectId) {
|
|
permanentObj.permanentList = permanents.value;
|
|
taskObj.tasks = tasks.value;
|
|
|
|
await getFindProjectById(projectId);
|
|
await getRoles(projectId); // 通过项目id获取角色信息
|
|
await getPermanentData(currRoleId.value); // 根据角色查找永久的日常任务
|
|
await getTasks({ roleId: currRoleId.value });
|
|
}
|
|
} catch (error) {
|
|
console.log('error: ', error);
|
|
}
|
|
}
|
|
|
|
// 设置 初始显示角色信息
|
|
function setInitialRoleId(visibleList) {
|
|
if (!visibleList || !visibleList.length) return;
|
|
|
|
roles.value = [...visibleList];
|
|
|
|
const index = visibleList.findIndex(item => +item.mine === 1);
|
|
const currentRole = index > 0 ? visibleList[index] : visibleList[0];
|
|
// const storageRoleId = this.$t.storage.getStorageSync('roleId');
|
|
// const currentRoleId = storageRoleId ? storageRoleId : currentRole ? currentRole.id : '';
|
|
const currentRoleId = currentRole ? currentRole.id : '';
|
|
currRoleId.value = currentRoleId;
|
|
store.commit('role/setRoleId', currentRoleId);
|
|
// 清空storage
|
|
// this.$t.storage.setStorageSync('roleId', '');
|
|
}
|
|
|
|
/**
|
|
* 通过项目id获取项目信息
|
|
* @param {string} projectId
|
|
* @param {object} params 提交的参数
|
|
*/
|
|
async function getFindProjectById(params) {
|
|
try {
|
|
const data = await findProjectById(params);
|
|
store.commit('projects/setProject', data);
|
|
} catch (error) {
|
|
throw new Error(error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 通过项目id获取角色信息
|
|
* @param {string} projectId
|
|
* @param {object} params 提交的参数
|
|
*/
|
|
async function getRoles(params) {
|
|
try {
|
|
const data = await findShowRole(params);
|
|
store.commit('role/setInvisibleRoles', data ? data.invisibleList : []);
|
|
store.commit('role/setVisibleRoles', data ? data.visibleList : []);
|
|
setInitialRoleId(data ? data.visibleList : []);
|
|
} catch (error) {
|
|
throw new Error(error);
|
|
}
|
|
}
|
|
|
|
// 日常任务
|
|
async function getPermanentData(roleId) {
|
|
const params = { param: { roleId } };
|
|
try {
|
|
const data = await store.dispatch('task/getPermanent', params);
|
|
permanentObj.permanentList = data;
|
|
globalHeight.value = data.length * 38 + 26;
|
|
} catch (error) {
|
|
throw new Error(error);
|
|
}
|
|
}
|
|
|
|
// 根据id获取子任务
|
|
async function getSonTask(detailId) {
|
|
const params = { param: { detailId } };
|
|
try {
|
|
const data = await findSonTask(params);
|
|
taskObj.tasks.forEach(item => {
|
|
if (item.detailId === detailId) {
|
|
item.sonList = data;
|
|
}
|
|
});
|
|
} catch (error) {
|
|
throw new Error(error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 根据时间基准点和角色查找定期任务
|
|
* @param {object} query
|
|
* @param {string} query.roleId 角色id
|
|
* @param {string} query.timeNode 时间基准点 默认当前
|
|
* @param {string} query.timeUnit 时间颗粒度 默认天
|
|
* @param {string} query.queryNum 查找颗粒度数量 默认3个
|
|
* @param {number} query.queryType 0向上查找 1向下查找(默认) 下查包含自己,上查不包含
|
|
*/
|
|
async function getTasks(query) {
|
|
const params = { param: query };
|
|
try {
|
|
const data = await getRegularTask(params);
|
|
taskObj.tasks = data;
|
|
|
|
data.forEach(item => {
|
|
item.plugins.forEach(val => {
|
|
if (Number(val[0].pluginId) === 6) {
|
|
getSonTask(item.detailId);
|
|
}
|
|
});
|
|
});
|
|
|
|
store.commit('task/setUpTasks', data);
|
|
} catch (error) {
|
|
throw new Error(error);
|
|
}
|
|
}
|
|
|
|
function toDetail(item) {
|
|
store.commit('task/setTaskDetail', item);
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.navbar {
|
|
padding: 0 16px;
|
|
height: 44px;
|
|
}
|
|
|
|
.project-name {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #333;
|
|
}
|
|
|
|
.project-action .anticon {
|
|
margin-left: 16px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.role-list {
|
|
padding: 0 16px;
|
|
height: 36px;
|
|
border-bottom: 1px solid #cccccc;
|
|
}
|
|
|
|
.role-box {
|
|
margin-right: 16px;
|
|
height: 36px;
|
|
}
|
|
|
|
.role-name {
|
|
font-size: 14px;
|
|
line-height: 36px;
|
|
color: #333333;
|
|
}
|
|
|
|
.role-name.mine {
|
|
font-weight: 600;
|
|
color: #1890ff;
|
|
}
|
|
|
|
.role-box .line-box {
|
|
width: 100%;
|
|
bottom: 0;
|
|
}
|
|
|
|
.line-box .line {
|
|
width: 16px;
|
|
height: 2px;
|
|
background-color: #1890ff;
|
|
}
|
|
|
|
.global {
|
|
padding: 16px;
|
|
}
|
|
|
|
.global-box {
|
|
border: 1px solid #cccccc;
|
|
border-radius: 10px;
|
|
padding: 12px 16px;
|
|
}
|
|
|
|
.global-task {
|
|
padding: 8px 0;
|
|
line-height: 22px;
|
|
}
|
|
|
|
.task-list {
|
|
padding: 0 16px 50px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.task-box {
|
|
}
|
|
|
|
.task-time {
|
|
height: 32px;
|
|
}
|
|
|
|
.task-time .anticon {
|
|
margin-right: 16px;
|
|
}
|
|
|
|
.task-time span {
|
|
font-size: 14px;
|
|
color: #595959;
|
|
}
|
|
|
|
.task-info {
|
|
margin: 8px 0;
|
|
padding-left: 11px;
|
|
}
|
|
|
|
.task-info > div {
|
|
padding-left: 27px;
|
|
border-left: 1px solid #d2d2d2;
|
|
}
|
|
|
|
.task-info .task-card {
|
|
padding: 16px;
|
|
border-radius: 8px;
|
|
-moz-box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.12);
|
|
-webkit-box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.12);
|
|
box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.12);
|
|
}
|
|
|
|
.task-con {
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.task-con > div {
|
|
height: 30px;
|
|
}
|
|
|
|
:deep(.ant-checkbox + span) {
|
|
color: #607d8b;
|
|
}
|
|
|
|
.task-list::-webkit-scrollbar {
|
|
width: 0 !important;
|
|
}
|
|
</style>
|
|
|