Browse Source

feat: "项目详情"

master
xuesinan 4 years ago
parent
commit
6dad31d920
  1. 18
      src/apis/index.js
  2. 252
      src/components/tall/center/ProjectDetail.vue
  3. 58
      src/components/tall/left/Index.vue
  4. 44
      src/components/tall/left/Projects.vue
  5. 8
      src/store/tall/task/index.js

18
src/apis/index.js

@ -5,6 +5,7 @@ import http from 'utils/axios';
const apiUrl = import.meta.env.VITE_API_URL;
const users = `${apiUrl}/gateway/tall3/v3.0/users`;
const tall = `${apiUrl}/gateway/tall3/v3.0`;
const experiment = `${apiUrl}/gateway/experiment`;
// 根据userId 获取token
// eslint-disable-next-line import/prefer-default-export
@ -17,11 +18,22 @@ export const signIn = params => http.post(`${users}/signin`, params);
export const getProjects = (startTime, endTime) => http.post(`${tall}/project/query`, { param: { startTime, endTime } });
// 根据项目id查找角色
export const findShowRole = param => http.post(`${tall}/role/show`, param);
export const findShowRole = projectId => http.post(`${experiment}/role/show`, { param: { projectId } });
// 根据项目id查找所有成员
export const queryChecker = param => http.post(`${tall}/deliver/queryChecker`, param);
export const getGlobal = params => http.post(`${tall}/task/global`, params);
// 查找带时间的日常任务
export const getGlobal = params => http.post(`${experiment}/task/global`, params);
export const getPermanent = params => http.post(`${tall}/task/permanent`, params);
// 查找永久日常任务
export const getPermanent = params => http.post(`${experiment}/task/permanent`, params);
// 查找定期任务
export const getRegularTask = params => http.post(`${experiment}/task/regular`, params);
// 添加任务
export const saveTask = params => http.post(`${experiment}/task/save`, params);
// 查询子任务
export const findSonTask = params => http.post(`${experiment}/task/findSonTask`, params);

252
src/components/tall/center/ProjectDetail.vue

@ -1,6 +1,6 @@
<template>
<div class="navbar flex items-center justify-between">
<div class="project-name">项目名称</div>
<div class="project-name">{{ projectObj.obj.pname }}</div>
<div class="project-action">
<img />
<img @click="toShowMask" />
@ -8,26 +8,25 @@
</div>
<div class="role-list flex items-center">
<div class="role-box relative">
<div class="role-name">角色名称</div>
<div class="line-box absolute flex justify-center"><div class="line"></div></div>
<div class="role-box relative" v-for="(item, index) in roles.arr" :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">
<div class="global-task">任务1</div>
<div class="global-task">任务1</div>
<div class="global-task">任务1</div>
<div class="global-task">任务1</div>
<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)">
{{ item.name }}
</div>
</div>
<div class="task-list">
<div class="task-box">
</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">
<img />
<span>10 09:00</span>
<span>{{ dayjs(item.planStart).format('D日 HH:mm') }}</span>
</div>
<div class="task-action"></div>
</div>
@ -35,45 +34,16 @@
<div class="task-info">
<div>
<div class="task-card">
<div class="task-name">任务名</div>
<div class="task-con">
<div>
<a-checkbox><span class="child-project-name">子课题负责人1 穿戴式运动捕获单元</span></a-checkbox>
</div>
<div>
<a-checkbox><span class="child-project-name">子课题负责人1 穿戴式运动捕获单元</span></a-checkbox>
</div>
<div>
<a-checkbox><span class="child-project-name">子课题负责人1 穿戴式运动捕获单元</span></a-checkbox>
</div>
<div>
<a-checkbox><span class="child-project-name">子课题负责人1 穿戴式运动捕获单元</span></a-checkbox>
</div>
<div>
<a-checkbox><span class="child-project-name">子课题负责人1 穿戴式运动捕获单元</span></a-checkbox>
</div>
</div>
<div class="open-icon" @click="openCard">
<img />
</div>
</div>
</div>
<div class="task-name cursor-pointer" @click="toDetail(item)">{{ item.name }}</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 @change="handleChange">{{ val.name }}</a-checkbox>
</div>
</div>
<div class="task-box">
<div class="task-time flex items-center justify-between">
<div class="flex items-center">
<div class="open-icon" v-if="item.sonList" @click="openCard">
<img />
<span>10 09:00</span>
</div>
<div class="task-action"></div>
</div>
<div class="task-info">
<div>
<div class="task-card">
<div class="task-name">任务名</div>
</div>
</div>
</div>
@ -82,67 +52,132 @@
</template>
<script setup>
import { computed, watch } from 'vue';
import { computed, watch, reactive, ref } from 'vue';
import { useStore } from 'vuex';
// import { findShowRole } from 'apis';
import dayjs from 'dayjs';
import { findShowRole, getRegularTask, findSonTask } from 'apis';
const store = useStore();
// const project = ref(0)
const project = computed(() => store.state.projects.project);
watch(project, (newVal, oldVal) => {
console.log(newVal.p, oldVal.p);
// clearTasksData();
// getGlobalData(); //
// initPlanTasks(); //
const projectObj = reactive({ obj: { u: '', p: '', pname: '', url: '' } });
const project = computed(() => store.state.projects.project); //
const currRoleId = computed(() => store.state.role.roleId); //
const roles = reactive({
//
arr: [
{ id: 1, name: '项目经理', mine: 1, pm: 1, sequence: 1 },
{ id: 2, name: '运维', mine: 0, pm: 0, sequence: 2 },
],
});
console.log('project', project.value.p);
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); //
//
// const setInitialRoleId = visibleList => {
// if (!visibleList || !visibleList.length) return;
// const index = visibleList.findIndex(item => +item.mine === 1);
// const currentRole = index > 0 ? visibleList[index] : visibleList[0];
// // const storageRoleId = uni.getStorageSync('roleId');
const setInitialRoleId = visibleList => {
if (!visibleList || !visibleList.length) return;
roles.arr = [];
visibleList.forEach(item => {
roles.arr.push(item);
});
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 : '';
// store.commit('role/setRoleId', currentRoleId);
// // storage
// // uni.setStorageSync('roleId', '');
// }
// /**
// * id
// * @param {string} projectId
// * @param {object} params
// */
// const getRoles = async params => {
// try {
// let 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 clearTasksData() {
// //
// // setPermanents([]);
// // setDailyTasks([]);
// // //
// // clearTasks();
// //
// //
// // clearEndFlag();
// }
// //
// function getGlobalData() {
// const { roleId, timeNode, timeUnit, projectId } = this;
// const param = { roleId, timeNode, timeUnit, projectId };
// store.dispatch('task/getGlobal', param);
// }
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 提交的参数
*/
const getRoles = async projectId => {
try {
const data = await findShowRole(projectId);
store.commit('role/setInvisibleRoles', data ? data.invisibleList : []);
store.commit('role/setVisibleRoles', data ? data.visibleList : []);
setInitialRoleId(data ? data.visibleList : []);
} catch (error) {
throw new Error(error);
}
};
//
const getPermanentData = async 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
const getSonTask = async 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向下查找(默认) 下查包含自己上查不包含
*/
const getTasks = async query => {
const params = { param: query };
try {
const data = await getRegularTask(params);
taskObj.tasks = data;
data.forEach(item => {
getSonTask(item.detailId);
});
store.commit('task/setUpTasks', data);
} catch (error) {
throw new Error(error);
}
};
//
watch(project, async newVal => {
projectObj.obj = newVal;
store.commit('projects/setProject', newVal);
permanentObj.permanentList = permanents.value;
taskObj.tasks = tasks.value;
await getRoles(projectObj.obj.p); // id
await getPermanentData(currRoleId.value); //
await getTasks({ roleId: currRoleId.value });
});
function toDetail(item) {
store.commit('task/setTaskDetail', item);
}
</script>
<style scoped>
@ -164,12 +199,17 @@ console.log('project', project.value.p);
}
.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;
}
@ -197,10 +237,12 @@ console.log('project', project.value.p);
.global-task {
padding: 8px 0;
line-height: 22px;
}
.task-list {
padding: 0 16px;
padding: 0 16px 50px;
overflow-y: auto;
}
.task-box {
@ -247,7 +289,11 @@ console.log('project', project.value.p);
height: 30px;
}
.child-project-name {
::v-deep .ant-checkbox + span {
color: #607d8b;
}
::-webkit-scrollbar {
width: 0 !important;
}
</style>

58
src/components/tall/left/Index.vue

@ -4,47 +4,47 @@
</template>
<script setup>
import { reactive } from 'vue';
import { useStore } from 'vuex';
import dayjs from 'dayjs';
import { getProjects } from 'apis';
// import { reactive } from 'vue';
// import { useStore } from 'vuex';
// import dayjs from 'dayjs';
// import { getProjects } from 'apis';
import Calendar from './Calendar.vue';
import Projects from './Projects.vue';
const store = useStore();
const projects = reactive([]);
// const store = useStore();
// const projects = reactive([]);
//
const getProjectsList = async (startTime, endTime) => {
try {
const data = await getProjects(startTime, endTime);
// const getProjectsList = async (startTime, endTime) => {
// try {
// const data = await getProjects(startTime, endTime);
data.forEach(item => {
item.show = false;
});
// data.forEach(item => {
// item.show = false;
// });
data.forEach(item => {
item.show = false;
// data.forEach(item => {
// item.show = false;
if (item.sonsonProjectList) {
item.sonsonProjectList.forEach(sonItem => {
sonItem.show = false;
});
}
// if (item.sonsonProjectList) {
// item.sonsonProjectList.forEach(sonItem => {
// sonItem.show = false;
// });
// }
projects.push(item);
});
// projects.push(item);
// });
store.commit('projects/setProjects', projects);
} catch (error) {
console.log(error);
}
};
// store.commit('projects/setProjects', projects);
// } catch (error) {
// console.log(error);
// }
// };
getProjectsList(dayjs().startOf('day').format('x'), dayjs().endOf('day').format('x'));
// getProjectsList(dayjs().startOf('day').format('x'), dayjs().endOf('day').format('x'));
function changeTime(data) {
getProjectsList(data.startTime, data.endTime);
function changeTime() {
// getProjectsList(data.startTime, data.endTime);
}
</script>

44
src/components/tall/left/Projects.vue

@ -7,7 +7,7 @@
<div class="detail">
<div class="name-box flex items-center">
<div class="name truncate">{{ item.name }}</div>
<div class="precent">50%</div>
<div class="precent-num">50%</div>
</div>
<div class="time">{{ dayjs(item.startTime).format('HH:mm:ss') }} {{ dayjs(item.endTime).format('HH:mm:ss') }}</div>
@ -19,14 +19,14 @@
</div>
</div>
<div class="two-box" v-for="(sonItem, sonIndex) in item.sonProjectList" :key="sonIndex">
<div class="two-flex">
<div class="two-level h-70 cursor-pointer flex items-center" @click="toDetail()">
<div class="two-box">
<div class="two-flex" v-for="(sonItem, sonIndex) in item.sonProjectList" :key="sonIndex">
<div class="two-level h-70 cursor-pointer flex items-center" @click="toDetail(sonItem)">
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
<div class="detail">
<div class="name-box flex items-center">
<div class="name truncate">{{ sonItem.name }}</div>
<div class="precent">50%</div>
<div class="precent-num">50%</div>
</div>
<div class="time">{{ dayjs(sonItem.startTime).format('HH:mm:ss') }} {{ dayjs(sonItem.endTime).format('HH:mm:ss') }}</div>
@ -39,15 +39,22 @@
</div>
<div class="three-box">
<div class="three-level h-70 cursor-pointer flex items-center" @click="toDetail()">
<div
class="three-level h-70 cursor-pointer flex items-center"
v-for="(thirdItem, thirdIndex) in sonItem.sonProjectList"
:key="thirdIndex"
@click="toDetail(thirdItem)"
>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
<div class="detail">
<div class="name-box flex items-center">
<div class="name truncate">项目名称</div>
<div class="precent">50%</div>
<div class="name truncate">{{ thirdItem.name }}</div>
<div class="precent-num">50%</div>
</div>
<div class="time">11-21 00:00 11-21 23.59</div>
<div class="time">
{{ dayjs(thirdItem.startTime).format('HH:mm:ss') }} {{ dayjs(thirdItem.endTime).format('HH:mm:ss') }}
</div>
</div>
</div>
</div>
@ -66,9 +73,6 @@ import { RightOutlined, DownOutlined } from '@ant-design/icons-vue';
const store = useStore();
const projects = reactive([]);
// const projectList = computed(() => store.state.projects.projects);
// watch( projectList, ( newVal, oldVal ) => { console.log( newVal + ":===" + oldVal ) })
// console.log('projectList', projectList)
//
const getProjectsList = async (startTime, endTime) => {
@ -78,8 +82,8 @@ const getProjectsList = async (startTime, endTime) => {
data.forEach(item => {
item.show = false;
if (item.sonsonProjectList) {
item.sonsonProjectList.forEach(sonItem => {
if (item.sonProjectList) {
item.sonProjectList.forEach(sonItem => {
sonItem.show = false;
});
}
@ -96,16 +100,6 @@ const getProjectsList = async (startTime, endTime) => {
getProjectsList(dayjs().startOf('day').format('x'), dayjs().endOf('day').format('x'));
function toDetail(project) {
//
// const { name, id, url } = project;
// url && (uni.$t.domain = url);
// this.$u.route('pages/project-webview/project-webview', {
// u: this.userId,
// p: id,
// pname: name,
// url: encodeURIComponent(url),
// });
const obj = {
u: project.userId,
p: project.id,
@ -174,7 +168,7 @@ export default { name: 'Projects' };
color: #333333;
}
.precent {
.precent-num {
width: 48px;
height: 18px;
line-height: 18px;

8
src/store/tall/task/index.js

@ -25,6 +25,7 @@ export default {
showSkeleton: false, // 定期任务骨架屏
newProjectInfo: {},
showScrollTo: false, // 是否可以设置时间轴自动滚动的位置
taskDetail: {}, // 当前点击任务信息
},
getters: {
@ -284,6 +285,13 @@ export default {
setShowScrollTo(state, show) {
state.showScrollTo = show;
},
/**
* 设置当前点击的任务信息
*/
setTaskDetail(state, show) {
state.taskDetail = show;
},
},
actions: {

Loading…
Cancel
Save