Browse Source

refactor: 重构时间刻度渲染任务

解决了时间刻度未替换的问题;解决重复渲染的问题
pull/1/head
wally 4 years ago
parent
commit
5cf7d08066
  1. 3
      CHANGELOG.md
  2. 2
      src/components/TimeLine/TimeLine.vue
  3. 1
      src/config/app.js
  4. 2
      src/config/task.js
  5. 331
      src/pages/project/project.vue
  6. 6
      src/store/task/mutations.js
  7. 24
      src/test/util/task.test.js
  8. 2
      src/utils/tall.js
  9. 34
      src/utils/task.js

3
CHANGELOG.md

@ -1,4 +1,4 @@
# 0.1.0 (2021-08-26)
# 0.1.0 (2021-08-27)
### 🌟 新功能
范围|描述|commitId
@ -142,6 +142,7 @@
- | 角色栏修改 | 19228d6
- | 解决时间轴报错 | da1eece
- | 设置时间轴自动滚动到当前位置 | a3474f8
- | 调试定期任务bug;不能合并使用 | d641312
- | 跳转详情页返回路径修改 | c5e17c0
- | 骨架屏替换 | e9fdd71

2
src/components/TimeLine/TimeLine.vue

@ -35,7 +35,7 @@ export default {
computed: {
...mapState('role', ['visibleRoles']),
...mapState('task', ['scrollTop', 'showTips', 'tasks', 'topEnd', 'bottomEnd', 'showSkeleton', 'timeNode', 'scrollToTaskId']),
...mapState('task', ['scrollTop', 'tasks', 'topEnd', 'bottomEnd', 'showSkeleton', 'timeNode', 'scrollToTaskId']),
...mapGetters('task', ['timeGranularity']),
},

1
src/config/app.js

@ -1,3 +1,4 @@
// TODO: 环境变量设置
const version = '3.0.0';
export default {

2
src/config/task.js

@ -0,0 +1,2 @@
// 每页加载颗粒度的个数
export default { pageCount: 10 };

331
src/pages/project/project.vue

@ -18,7 +18,8 @@
<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
import { setPlaceholderTasks } from '@/utils/task';
import { setPlaceholderTasks, computeFillPlaceholderTaskCount } from '@/utils/task';
import { flatten } from 'lodash';
export default {
data() {
@ -97,125 +98,45 @@ export default {
'setBottomEnd',
]),
/**
* 初始化
* @param {object | null} options
*/
init(options) {
if (!this.token) {
// tokenuserIdtoken
// token userId
if (!options || !options.u) {
this.$t.ui.showToast('缺少用户信息参数'); // u (userId)
} else {
this.getToken(options.u);
}
}
//
options && options.pname && this.setProjectName(options.pname);
if (!options || !options.p) {
this.$t.ui.showToast('缺少项目信息参数'); // id
} else {
this.getProjectById({ projectId: options.p }); // id
}
},
/**
* 通过项目id获取项目信息
* @param {object} params 提交的参数
*/
async getProjectById(params) {
try {
const data = await uni.$u.api.findProjectById(params);
this.setProject(data);
// id
this.getRoles(params);
} catch (error) {
console.log('error: ', error || '获取项目信息失败');
}
},
/**
* 通过项目id获取角色信息
* @param {string} projectId
* @param {object} params 提交的参数
*/
getRoles(params) {
this.$t.$q.findShowRole(params, (err, data) => {
if (err) {
console.error('err: ', err || '获取角色信息失败');
} else {
this.setInvisibleRoles(data ? data.invisibleList : []);
this.setVisibleRoles(data ? data.visibleList : []);
this.setInitialRoleId(data ? data.visibleList : []);
}
});
},
//
clearTasksData() {
//
this.setPermanents([]);
this.setDailyTasks([]);
//
this.clearTasks();
//
//
this.clearEndFlag();
},
//
//
async initPlanTasks() {
this.setPrevTasks(); //
this.setNextTasks(); //
this.setPrevPlaceholderTasks(); //
this.setNextPlaceholderTasks(); //
this.$nextTick(() => this.$refs.timeLine.setScrollPosition()); //
await this.getInitTasks();
await this.getInitTasks(); //
this.$nextTick(() => this.$refs.timeLine.setScrollPosition()); //
},
// ||
getInitTasks() {
//
function fn(that) {
function preloadFn(that) {
const detailId = that.tasks.findIndex(task => task.detailId);
console.log('detailId: ', detailId);
if (detailId !== -1) {
// 1
const { pageCount } = that.$t.task;
that.$nextTick(() => {
//
const { tasks, timeGranularity } = that;
that.getTasks({ timeNode: +tasks[0].planStart, queryType: 0, queryNum: 6 });
that.getTasks({ timeNode: +tasks[0].planStart, queryType: 0, queryNum: pageCount });
//
const nextQueryTime = +that.$t.time.add(+tasks[tasks.length - 1].planStart, 1, timeGranularity);
that.getTasks({ timeNode: nextQueryTime, queryType: 1, queryNum: 6 });
that.getTasks({ timeNode: nextQueryTime, queryType: 1, queryNum: pageCount });
});
} else {
//
//
// that.setPrevTasks();
// that.setPrevPlaceholderTasks();
// //
// that.setNextTasks();
// that.setNextPlaceholderTasks();
}
}
//
this.getTasks({ queryType: 0 }); //
// id
this.getTasks({ queryType: 1 }, fn); //
},
//
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 = this.$t.storage.getStorageSync('roleId');
const currentRoleId = storageRoleId ? storageRoleId : currentRole ? currentRole.id : '';
this.setRoleId(currentRoleId);
// storage
this.$t.storage.setStorageSync('roleId', '');
this.getTasks({ queryType: 1 }, preloadFn); //
},
/**
@ -225,19 +146,11 @@ export default {
* @param {string} query.timeNode 时间基准点 默认当前
* @param {string} query.timeUnit 时间颗粒度 默认天
* @param {string} query.queryNum 查找颗粒度数量 默认3个
* @param {string} query.queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
* @param {number} query.queryType 0向上查找 1向下查找(默认) 下查包含自己上查不包含
*/
getTasks(query, fn) {
this.setShowSkeleton(true);
const { roleId, timeNode, timeUnit, projectId } = this;
const params = {
roleId,
timeNode: query.timeNode || timeNode,
timeUnit: query.timeUnit || timeUnit,
queryNum: query.queryNum || 3,
queryType: query.queryType,
projectId,
};
const params = this.generateGetTaskParam(query);
this.$t.$q.getRegularTask(params, (err, data) => {
this.setShowSkeleton(false);
@ -245,14 +158,17 @@ export default {
// TODO:
console.error('err: ', err);
} else {
// 0 -> 1 ->
//
//
if (data && data.length) {
this.replacePrevData(data, params.queryType);
} else {
params.queryType === 0 ? this.setPrevTasks() : this.setNextTasks();
}
// else {
// TODO: 0 -> 1 ->
// params.queryType === 0 ? this.setPrevPlaceholderTasks() : this.setNextPlaceholderTasks();
// }
if (this.tasks.length && fn) {
fn(this);
}
@ -260,15 +176,24 @@ export default {
});
},
//
getGlobalData() {
/**
* 生成getTasks所用的参数
* @param {object} query getTasks传递的参数
*/
generateGetTaskParam(query) {
const { roleId, timeNode, timeUnit, projectId } = this;
const param = { roleId, timeNode, timeUnit, projectId };
this.getGlobal(param);
return {
roleId,
timeNode: query.timeNode || timeNode,
timeUnit: query.timeUnit || timeUnit,
queryNum: query.queryNum || 3,
queryType: query.queryType,
projectId,
};
},
//
setPrevTasks() {
setPrevPlaceholderTasks() {
this.setTopEnd(true);
let startTime = '';
const { tasks } = this;
@ -282,72 +207,146 @@ export default {
},
//
setNextTasks() {
setNextPlaceholderTasks() {
this.setBottomEnd(true);
let sTime = '';
let startTime = '';
if (!this.tasks || !this.tasks.length) {
sTime = +new Date().getTime();
startTime = Date.now();
} else {
sTime = +this.tasks[this.tasks.length - 1].planStart - 0;
startTime = +this.tasks[this.tasks.length - 1].planStart;
}
const initData = setPlaceholderTasks(sTime, false, this.timeGranularity);
const initData = setPlaceholderTasks(startTime, false, this.timeGranularity);
this.setDownTasks(initData);
},
//
/**
* 用拿到的新数据 替换 时间刻度/旧数据
* 先对比 新旧数据的 始末时间 补齐刻度
* 再遍历对比 用任务替换刻度
* @param {array} data 服务端返回的新数据 上边已经处理过空值
* @param {number} type 0 -> 向上 1->向下
*/
replacePrevData(data, type) {
let newTasks = [...this.tasks];
let newDate = this.$u.deepClone(data);
console.log('newDate: ', newDate);
if (newDate && newDate.length) {
for (let i = 0; i < newTasks.length; i++) {
// const task = newTasks[i];
let arr = [];
for (let j = 0; j < newDate.length; j++) {
const item = newDate[j];
if (newTasks[i].id === item.id) {
console.log('j', j, i);
newTasks[i] = item;
break;
}
//
if (+newTasks[0].planStart > +newDate[0].planStart) {
this.setPrevTasks();
newTasks = [...this.tasks];
i--;
break;
} else if (+newDate[newDate.length - 1].planStart > +newTasks[newTasks.length - 1].planStart) {
this.setNextTasks();
newTasks = [...this.tasks];
i--;
break;
} else {
//
const taskItem = this.$t.time.isSame(+newTasks[i].planStart, +item.planStart, this.timeGranularity);
if (taskItem) {
arr.push(item);
if (newTasks[i].detailId) {
newTasks.splice(i, 0, item);
} else {
if (arr.length === 1) {
newTasks.splice(i, 1, item);
}
if (arr.length > 1) {
newTasks.splice(i, 0, item);
}
}
i++;
}
}
}
const { timeGranularity } = this;
let oldTasks = this.fillPlaceholderTask({ tasks: this.tasks, data, timeGranularity }); //
//
// TODO: tasks
oldTasks.forEach((taskItem, index) => {
const arr = data.filter(dataItem => this.$moment(+dataItem.planStart).isSame(+taskItem.planStart, timeGranularity));
if (arr && arr.length) {
oldTasks.splice(index, 1, [...arr]); // array, [{},{},[],[],{}]
}
});
oldTasks = flatten(oldTasks); // 1
this.clearTasks(); // setUpTasks setUpTasks
type === 0 ? this.setUpTasks(oldTasks) : this.setUpTasks(oldTasks);
},
/**
* 超出旧数据上下限 补齐时间刻度到新数据的起始时间颗粒度
*/
fillPlaceholderTask({ tasks, data, timeGranularity }) {
const { prev, next } = computeFillPlaceholderTaskCount({ tasks, data, timeGranularity });
if (prev) {
const newTasks = setPlaceholderTasks(+tasks[0].planStart, true, timeGranularity, prev);
this.setUpTasks(newTasks);
}
if (next) {
const newTasks = setPlaceholderTasks(+tasks[tasks.length - 1].planStart, false, timeGranularity, next);
this.setDownTasks(newTasks);
}
return this.tasks;
},
/**
* 初始化
* @param {object | null} options
*/
init(options) {
if (!this.token) {
// tokenuserIdtoken
// token userId
if (!options || !options.u) {
this.$t.ui.showToast('缺少用户信息参数'); // u (userId)
} else {
this.getToken(options.u);
}
}
//
options && options.pname && this.setProjectName(options.pname);
if (!options || !options.p) {
this.$t.ui.showToast('缺少项目信息参数'); // id
} else {
this.getProjectById({ projectId: options.p }); // id
}
},
/**
* 通过项目id获取项目信息
* @param {object} params 提交的参数
*/
async getProjectById(params) {
try {
const data = await uni.$u.api.findProjectById(params);
this.setProject(data);
// id
this.getRoles(params);
} catch (error) {
console.log('error: ', error || '获取项目信息失败');
}
},
/**
* 通过项目id获取角色信息
* @param {string} projectId
* @param {object} params 提交的参数
*/
getRoles(params) {
this.$t.$q.findShowRole(params, (err, data) => {
if (err) {
console.error('err: ', err || '获取角色信息失败');
} else {
this.setInvisibleRoles(data ? data.invisibleList : []);
this.setVisibleRoles(data ? data.visibleList : []);
this.setInitialRoleId(data ? data.visibleList : []);
}
});
},
//
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 = this.$t.storage.getStorageSync('roleId');
const currentRoleId = storageRoleId ? storageRoleId : currentRole ? currentRole.id : '';
this.setRoleId(currentRoleId);
// storage
this.$t.storage.setStorageSync('roleId', '');
},
//
getGlobalData() {
const { roleId, timeNode, timeUnit, projectId } = this;
const param = { roleId, timeNode, timeUnit, projectId };
this.getGlobal(param);
},
//
clearTasksData() {
//
this.setPermanents([]);
this.setDailyTasks([]);
//
this.clearTasks();
type === 0 ? this.setUpTasks(newTasks) : this.setDownTasks(newTasks);
console.log('newTasks: ', newTasks.length);
console.log('end');
//
//
this.clearEndFlag();
},
},
};

6
src/store/task/mutations.js

@ -81,7 +81,8 @@ const mutations = {
if (!state.tasks.length) {
state.tasks = [...data]; // 原来没有数据
} else {
state.tasks = [...data.concat(state.tasks)];
state.tasks = [...data, ...state.tasks];
// state.tasks = [...data.concat(state.tasks)];
}
},
@ -94,7 +95,8 @@ const mutations = {
if (!state.tasks && !state.tasks.length) {
state.tasks = [...data];
} else {
state.tasks = [...state.tasks.concat(data)];
state.tasks = [...state.tasks, ...data];
// state.tasks = [...state.tasks.concat(data)];
}
},

24
src/test/util/task.test.js

@ -0,0 +1,24 @@
import { computeFillPlaceholderTaskCount } from '../../utils/task';
describe('computeFillPlaceholderTaskCount', () => {
// 2021/8/17 ~ 2021/8/21
const tasks = [
{ id: '99724910037144221455', panel: {}, plugins: [], process: 4, planStart: 1629169800242 },
{ id: '65053357415671253512', panel: {}, plugins: [], process: 4, planStart: 1629256200242 },
{ id: '38735454515347179194', panel: {}, plugins: [], process: 4, planStart: 1629342600242 },
{ id: '49602681534756706607', panel: {}, plugins: [], process: 4, planStart: 1629429000242 },
{ id: '98860265376222512018', panel: {}, plugins: [], process: 4, planStart: 1629515400242 },
{ id: '44419041575700334936', panel: {}, plugins: [], process: 4, planStart: 1629601800242 },
];
const timeGranularity = 'day';
it('超出上限 补齐', () => {
const data = [{ planStart: `${new Date('2021/8/10').getTime()}` }, { planStart: `${new Date('2021/8/11').getTime()}` }];
expect(computeFillPlaceholderTaskCount({ tasks, data, timeGranularity }).prev.toString()).toMatch(/(7|8)/);
});
it('超出下限 补齐', () => {
const data = [{ planStart: `${new Date('2021/8/10').getTime()}` }, { planStart: `${new Date('2021/8/22').getTime()}` }];
expect(computeFillPlaceholderTaskCount({ tasks, data, timeGranularity }).next.toString()).toMatch(/(1|2)/);
});
});

2
src/utils/tall.js

@ -9,6 +9,7 @@ import ui from '@/utils/ui.js';
import upload from '@/utils/upload.js';
import user from '@/config/user.js';
import zIndex from '@/config/zIndex.js';
import task from '@/config/task.js';
const gateway = process.env.VUE_APP_API_URL;
@ -25,6 +26,7 @@ const $t = {
cache, // 本地存储相关
$q: cacheAndRequest,
user, // 用户相关配置
task, // 任务相关配置
};
uni.$t = $t;

34
src/utils/task.js

@ -1,12 +1,16 @@
import dayjs from 'dayjs';
/**
* 设置时间轴空数据
* @param {number} startTime
* @param {boolean} isUp true 向上加载,false 向下加载
* @param {string} timeGranularity 颗粒度
* @param {number} pageCount 加载的颗粒度数量 默认值是10
*/
export const setPlaceholderTasks = (startTime, isUp, timeGranularity) => {
export const setPlaceholderTasks = (startTime, isUp, timeGranularity, pageCount) => {
let result = [];
for (let i = 0; i < 10; i++) {
pageCount = pageCount || uni.$t.task.pageCount;
for (let i = 0; i < pageCount; i++) {
const delta = isUp ? `-${i + 1}` - 0 : i + 1;
let item = {
id: uni.$u.guid(20, false, 10),
@ -21,3 +25,29 @@ export const setPlaceholderTasks = (startTime, isUp, timeGranularity) => {
}
return result;
};
/**
* 超出旧数据上下限 补齐时间刻度到新数据的起始时间颗粒度
* @param {object} option
* @param {array} option.tasks 旧的已有的任务书籍
* @param {array} option.data 新拿到的任务数据 空值已经过滤过了
* @param {string} option.timeGranularity 颗粒度
*/
export const computeFillPlaceholderTaskCount = ({ tasks, data, timeGranularity }) => {
const result = { prev: 0, next: 0 };
// 新数据的开始时间 < 旧数据的开始时间
// 超出了上限 补上限的时间刻度
// 补上 新数据开始时间 到 旧数据开始时间 的刻度
if (+data[0].planStart < +tasks[0].planStart) {
// 找出来需要补几组颗粒度
result.prev = dayjs(+tasks[0].planStart).diff(+data[0].planStart, timeGranularity) + 1;
}
// 新数据的结束时间 > 旧数据的结束时间
// 超出了下线 补下限的时间刻度
// 补上 旧数据截止时间 到 新数据截止时间 的刻度
if (+data[data.length - 1].planStart > +tasks[tasks.length - 1].planStart) {
result.next = dayjs(+data[data.length - 1].planStart).diff(+tasks[tasks.length - 1].planStart, timeGranularity) + 1;
}
return result;
};

Loading…
Cancel
Save