import { computed, nextTick } from 'vue'; import { useStore } from 'vuex'; import { flatten } from 'lodash'; import dayjs from 'dayjs'; export default function useGetTasks() { const store = useStore(); const tasks = computed(() => store.state.task.tasks); const roleId = computed(() => store.state.role.roleId); const timeNode = computed(() => store.state.task.timeNode); const timeUnit = computed(() => store.state.task.timeUnit); const projectId = computed(() => store.getters['project/projectId']); const timeGranularity = computed(() => store.getters['task/timeGranularity']); // 初始化 定期任务 async function initPlanTasks() { setPrevPlaceholderTasks(); // 向上加载空数据 setNextPlaceholderTasks(); // 向下加载空数据 await getInitTasks(); // 获取初始数据 } // 切换了 颗粒度 || 角色时候 获取初始定期任务 function getInitTasks() { // 预加载 上下的定期任务 function preloadFn(that) { const detailId = tasks.value.findIndex(task => task.detailId); const arr = []; tasks.value.forEach(task => { if (task.detailId) { arr.push(task); } }); if (detailId !== -1) { // 只要有1个真实的任务 就预加载上下周期的任务 const { pageCount } = uni.$task; nextTick(() => { // 向上拿数据 getTasks({ timeNode: +tasks.value[detailId].planStart, queryType: 0, queryNum: pageCount, }); // 向下拿数据 const nextQueryTime = +uni.$time.add(+arr[arr.length - 1].planStart, 1, timeGranularity.value); getTasks({ timeNode: nextQueryTime, queryType: 1, queryNum: pageCount, }); }); } else { // 没有任务 上下显示时间刻度 // 向上加载 setPrevPlaceholderTasks(); // // 向下加载 setNextPlaceholderTasks(); } } // 根据时间基准点和角色查找定期任务 getTasks({ queryType: 0, }); // 向上获取定期任务数据 // 根据项目id获取角色列表 // 向下获取定期任务数据 getTasks( { queryType: 1, }, preloadFn, ); } /** * 生成getTasks所用的参数 * @param {object} query getTasks传递的参数 */ function generateGetTaskParam(query) { return { roleId: roleId.value, timeNode: query.timeNode || timeNode.value, timeUnit: query.timeUnit || timeUnit.value, queryNum: query.queryNum || 3, queryType: query.queryType, projectId: projectId.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向下查找(默认) 下查包含自己,上查不包含 */ function getTasks(query, fn) { store.commit('task/setShowSkeleton', false); const params = generateGetTaskParam(query); uni.$catchReq.getRegularTask(params, (err, data) => { store.commit('task/setShowSkeleton', false); if (err) { // TODO: 提示错误 console.error('err: ', err); } else { store.commit('task/setShowScrollTo', true); // 有数据用数据替换刻度 // 没有数据 继续加载刻度 if (data && data.length) { replacePrevData(data, params.queryType); params.queryType === 0 ? store.commit('task/setTopEnd', false) : store.commit('task/setBottomEnd', false); } else { // TODO: 0 -> 向上 1 -> 向下 params.queryType === 0 ? setPrevPlaceholderTasks() : setNextPlaceholderTasks(); } if (tasks.value.length && fn) { fn(this); } } }); } /** * 用拿到的新数据 替换 时间刻度/旧数据 * 先对比 新旧数据的 始末时间 补齐刻度 * 再遍历对比 用任务替换刻度 * @param {array} data 服务端返回的新数据 上边已经处理过空值 * @param {number} type 0 -> 向上 1->向下 */ function replacePrevData(data, type) { const obj = { tasks: tasks.value, data, timeGranularity: timeGranularity.value }; let oldTasks = fillPlaceholderTask(obj); // 已经上下补齐时间刻度的 // 遍历对比 用任务替换刻度 // TODO: tasks越来越多 遍历越来越多 需要优化 oldTasks.forEach((taskItem, index) => { const arr = data.filter(dataItem => dayjs(+dataItem.planStart).isSame(+taskItem.planStart, timeGranularity.value)); if (arr && arr.length) { oldTasks.splice(index, 1, [...arr]); // 这里加入的数据是array类型的, [{},{},[],[],{}] } }); oldTasks = flatten(oldTasks); // 1维拍平 store.commit('task/clearTasks'); type === 0 ? store.commit('task/setUpTasks', oldTasks) : store.commit('task/setDownTasks', oldTasks); } /** * 超出旧数据上、下限 补齐时间刻度到新数据的起始时间颗粒度 */ function fillPlaceholderTask(obj) { const { prev, next } = uni.$task.computeFillPlaceholderTaskCount(obj); if (prev) { const newTasks = uni.$task.setPlaceholderTasks(+obj.tasks[0].planStart, true, obj.timeGranularity, prev); store.commit('task/setUpTasks', newTasks); } if (next) { const newTasks = uni.$task.setPlaceholderTasks(+obj.tasks[tasks.length - 1].planStart, false, obj.timeGranularity, next); store.commit('task/setDownTasks', newTasks); } return tasks.value; } // 设置时间轴向上的空数据 function setPrevPlaceholderTasks() { store.commit('task/setTopEnd', true); let startTime = ''; if (!tasks.value || !tasks.value.length) { startTime = Date.now(); // 没有任务就应该是时间基准点 } else { startTime = tasks.value[0].planStart - 0; // 有任务就是第一个任务的计划开始时间 } const placeholderTasks = uni.$task.setPlaceholderTasks(startTime, true, timeGranularity.value); store.commit('task/setUpTasks', placeholderTasks); } // 设置时间轴向下的空数据 function setNextPlaceholderTasks() { store.commit('task/setBottomEnd', true); let startTime = ''; if (!tasks.value || !tasks.value.length) { startTime = Date.now(); } else { startTime = +tasks.value[tasks.value.length - 1].planStart; } const initData = uni.$task.setPlaceholderTasks(startTime, false, timeGranularity.value); store.commit('task/setDownTasks', initData); } return { initPlanTasks, getTasks, }; }