forked from TALL/tall3-pc-keti
13 changed files with 622 additions and 431 deletions
@ -0,0 +1,68 @@ |
|||||
|
<template> |
||||
|
<div class="global"> |
||||
|
<div class="global-box" v-if="permanents && permanents.length > 0"> |
||||
|
<div class="global-task cursor-pointer" v-for="(item, index) in permanents" :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> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { computed, watch } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import { getPermanent } from 'apis'; |
||||
|
|
||||
|
const store = useStore(); |
||||
|
const project = computed(() => store.state.projects.project); // 项目信息 |
||||
|
const roleId = computed(() => store.state.role.roleId); // 当前角色 |
||||
|
const permanents = computed(() => store.state.task.permanents); // 日常任务 |
||||
|
const sessionPermanents = sessionStorage.getItem('permanents'); // 日常任务缓存 |
||||
|
|
||||
|
if (sessionPermanents) { |
||||
|
const arr = JSON.parse(sessionPermanents); |
||||
|
store.commit('task/setPermanents', arr); |
||||
|
} |
||||
|
|
||||
|
watch([project, roleId], async () => { |
||||
|
if (roleId.value) { |
||||
|
await getPermanentData(roleId.value); // 根据角色查找永久的日常任务 |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 日常任务 |
||||
|
async function getPermanentData(id) { |
||||
|
const params = { param: { roleId: id } }; |
||||
|
try { |
||||
|
const data = await getPermanent(params); |
||||
|
store.commit('task/setPermanents', data); |
||||
|
const globalHeight = data.length * 38 + 26; |
||||
|
store.commit('task/setGlobalHeight', globalHeight); |
||||
|
} catch (error) { |
||||
|
throw new Error(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function toDetail(item) { |
||||
|
store.commit('task/setTaskDetail', item); |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.global { |
||||
|
padding: 16px; |
||||
|
} |
||||
|
|
||||
|
.global-box { |
||||
|
border: 1px solid #cccccc; |
||||
|
border-radius: 10px; |
||||
|
padding: 12px 16px; |
||||
|
} |
||||
|
|
||||
|
.global-task { |
||||
|
padding: 8px 0; |
||||
|
line-height: 22px; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,57 @@ |
|||||
|
<template> |
||||
|
<div> |
||||
|
<!-- 项目标题 --> |
||||
|
<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> |
||||
|
|
||||
|
<!-- 角色 --> |
||||
|
<Roles /> |
||||
|
|
||||
|
<!-- 日常任务 --> |
||||
|
<Global /> |
||||
|
|
||||
|
<!-- 定期任务 --> |
||||
|
<RegularTask /> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import { ReloadOutlined, MoreOutlined } from '@ant-design/icons-vue'; |
||||
|
import Roles from './Roles.vue'; // 角色 |
||||
|
import Global from './Global.vue'; // 日常任务面板 |
||||
|
import RegularTask from './RegularTask.vue'; // 定期任务 |
||||
|
|
||||
|
const store = useStore(); |
||||
|
const project = computed(() => store.state.projects.project); // 项目信息 |
||||
|
const sessionProject = sessionStorage.getItem('project'); // 项目信息 |
||||
|
|
||||
|
if (sessionProject) { |
||||
|
const projectInfo = JSON.parse(sessionProject); |
||||
|
store.commit('projects/setProject', projectInfo); |
||||
|
} |
||||
|
</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; |
||||
|
} |
||||
|
</style> |
@ -1,343 +0,0 @@ |
|||||
<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> |
|
@ -0,0 +1,186 @@ |
|||||
|
<template> |
||||
|
<div class="task-list" :style="{ height: 'calc(100vh - 160px - (' + globalHeight + 'px))' }"> |
||||
|
<div class="task-box" v-for="(item, index) in 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> --> |
||||
|
<span class="son-task-name cursor-pointer" @click.stop="toSonDetail(item, val.detailId)">{{ val.name }}</span> |
||||
|
</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 } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import dayjs from 'dayjs'; |
||||
|
import { PlayCircleOutlined } from '@ant-design/icons-vue'; |
||||
|
import { getRegularTask, findSonTask } from 'apis'; |
||||
|
|
||||
|
const store = useStore(); |
||||
|
const project = computed(() => store.state.projects.project); // 项目信息 |
||||
|
const roleId = computed(() => store.state.role.roleId); // 当前角色 |
||||
|
const globalHeight = computed(() => store.state.task.globalHeight); // 日常任务面板高度 |
||||
|
const sessionGlobalHeight = sessionStorage.getItem('globalHeight'); // 日常任务面板高度缓存 |
||||
|
const tasks = computed(() => store.state.task.tasks); // 定期任务 |
||||
|
const taskObj = reactive({ tasks: [] }); // 定期任务 |
||||
|
const sessionTasks = sessionStorage.getItem('tasks'); // 定期任务缓存 |
||||
|
const subProjectInfo = computed(() => store.state.task.subProjectInfo); // 子课题信息 |
||||
|
|
||||
|
if (sessionGlobalHeight) { |
||||
|
store.commit('task/setGlobalHeight', sessionGlobalHeight); |
||||
|
} |
||||
|
|
||||
|
if (sessionTasks) { |
||||
|
const arr = JSON.parse(sessionTasks); |
||||
|
store.commit('task/setUpTasks', arr); |
||||
|
} |
||||
|
|
||||
|
watch([project, roleId, subProjectInfo], async () => { |
||||
|
if (roleId.value) { |
||||
|
await getTasks({ roleId: roleId.value }); // 根据角色查找定期任务 |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
/** |
||||
|
* 根据时间基准点和角色查找定期任务 |
||||
|
* @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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 根据id获取子任务 |
||||
|
async function getSonTask(id) { |
||||
|
const params = { param: { detailId: id } }; |
||||
|
try { |
||||
|
const data = await findSonTask(params); |
||||
|
taskObj.tasks.forEach(item => { |
||||
|
if (item.detailId === id) { |
||||
|
item.sonList = data; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
store.commit('task/setUpTasks', taskObj.tasks); |
||||
|
} catch (error) { |
||||
|
throw new Error(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function toDetail(item) { |
||||
|
store.commit('task/setTaskDetail', item); |
||||
|
store.commit('task/sonDetailId', ''); |
||||
|
} |
||||
|
|
||||
|
function toSonDetail(item, id) { |
||||
|
store.commit('task/setTaskDetail', item); |
||||
|
store.commit('task/sonDetailId', id); |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.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; |
||||
|
padding-left: 16px; |
||||
|
} |
||||
|
|
||||
|
.task-con > div { |
||||
|
height: 30px; |
||||
|
} |
||||
|
|
||||
|
:deep(.ant-checkbox + span) { |
||||
|
color: #607d8b; |
||||
|
} |
||||
|
|
||||
|
.son-task-name { |
||||
|
color: #607d8b; |
||||
|
} |
||||
|
|
||||
|
.task-list::-webkit-scrollbar { |
||||
|
width: 0 !important; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,93 @@ |
|||||
|
<template> |
||||
|
<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 && roleId === item.id }">{{ item.name }}</div> |
||||
|
<div class="line-box absolute flex justify-center" v-if="item.mine === 1 && roleId === item.id"><div class="line"></div></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { computed, watch } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import { findShowRole } from 'apis'; |
||||
|
|
||||
|
const store = useStore(); |
||||
|
const roleId = computed(() => store.state.role.roleId); // 当前角色 |
||||
|
const sessionRoles = sessionStorage.getItem('roles'); // 角色缓存 |
||||
|
const roles = computed(() => store.state.role.visibleRoles); // 当前项目角色列表 |
||||
|
|
||||
|
const project = computed(() => store.state.projects.project); // 项目信息 |
||||
|
|
||||
|
if (sessionRoles) { |
||||
|
const roleArr = JSON.parse(sessionRoles); |
||||
|
store.commit('role/setVisibleRoles', roleArr); |
||||
|
setInitialRoleId(roleArr); |
||||
|
} |
||||
|
|
||||
|
watch(project, async () => { |
||||
|
if (project.value.id) { |
||||
|
await getRoles(project.value.id); // 通过项目id获取角色信息 |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
/** |
||||
|
* 通过项目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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 设置 初始显示角色信息 |
||||
|
function setInitialRoleId(visibleList) { |
||||
|
if (!visibleList || !visibleList.length) return; |
||||
|
const index = visibleList.findIndex(item => +item.mine === 1); |
||||
|
const currentRole = index > 0 ? visibleList[index] : visibleList[0]; |
||||
|
const currentRoleId = currentRole ? currentRole.id : ''; |
||||
|
store.commit('role/setRoleId', currentRoleId); |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.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; |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue