Skip to main content

Custom Pages combined with calendar charts to implement task Kanban

1. Usage scenarios​

This example describes how to implement task dashboards for day View and week view on the YIDA custom page.

2. Implement functions​

2.1. Create page storage tasks and task executors​

2.1.1. Task entry​

On the process page, publish task details on the current page;

2.1.2. Task executor​

On the process page, enter the basic data of the task executor;

2.2. Create a custom page​

2.3. Configure data sources and variables​

2.3.1. Configure remote data sources​

Obtain the task/task Executor. The interface configuration is as follows:

`/dingtalk/web/${window.pageConfig.appType || window.g_config.appKey}/query/formProcInstData/getInstanceDatasLight.json`

[Task entry] Initiated. The interface configuration is as follows:

Reference documents:Process initiation

`/${window.pageConfig.appType || window.g_config.appKey}/v1/process/startInstance.json`

2.4. Configure variables​

2.4.1. Current view type​

2.4.2. Task executor data​

2.4.3. Task recipient query parameters​

2.4.4. Task query parameters​

2.4.5. Number of instances per page​

2.4.6. Current page number​

2.4.7. Loading status​

2.4.8. Header timeline (Monday to Sunday) data​

2.4.9. Day View task time cell data​

2.4.10. Day View task cell time scale​

2.4.11. Week view task cell time scale​

2.4.12. Week view task time cell data​

2.4.13. Task date query parameters​

2.4.14. Task cell time scale type​

2.4.15. Task details​

2.4.16. Calendar Chart data​

2.4.17. Select query parameters for the date in the calendar chart​

this.utils.formatter('date',Date.now(),'YYYY-M-D')

2.4.18. Calendar Chart Shows year​

2.4.19. The calendar chart shows the month​

2.5. Head switch panel configuration​

2.5.1. Use custom style classes to render the status of tasks into different color rendering descriptions​

The task is in progress and is bound to running 」;

The task is completed and is bound to finish 」;

Page properties-style, configure the style of the task in different states, as shown in the following figure:

2.5.2. View type switching, default [day view], binding callback events, rendering different types of task views​

By binding a custom style class, the selected status of the Task View is displayed;

state.boardType === 'day' ? 'boardTypeSelected' : ''

Select the status style configuration, as shown in the following figure:

state.boardType === 'week' ? 'boardTypeSelected' : ''

Click more to configure callback events;

// 切换面板显示类型
export function onBoardTypeChange() {
const { type } = this.params;
if (type === 'much') {
// 更多--跳转到【任务报表】查看任务数据
this.utils.router.push('/alibaba/web/APP_U3S2ETH1VNEUVT5H0IM8/report/vigoTopicview?isPreview=true&topicId=8770692&formUuid=REPORT-S9866D91J35FS450FVDK86VZULXJ232B6K6OLIQ', {}, true, true);
return;
}
const { boardType } = this.state;
if (type === boardType) {
return;
}
this.setState({
boardType: type,
});
this.getDateList();
this.onSubmit();//执行筛选框搜索
}

2.5.3. Switch time types to render different types of time cells​

Default time type: 8-22; By binding custom style classes, the rendering time type is selected;

state.dateType === '8-22' ? 'switchSelected' : ''

Configuration8-22 Time type parameters in the action panel

Time type-all day

state.dateType === '8-22' ? '' : 'switchSelected'

Time type switch binding callback event, as shown in the following figure:


// 切换日期类型
export function onDateTypeChange() {
const { type } = this.params;
const { dateType } = this.state;
if (type === dateType) {
return;
}
this.setState({
dateType: type,
});
this.getDateList();
}

2.6. Head Timeline rendering​

Page JS header timeline data acquisition

// 创建头部时间轴
export function getDateLine(startTimeCurrent = Date.now()) {
const dayCount = 7; // 显示 7 天
const dateLine = [];
const weekChinese = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
const startTimeWeekNum = new Date(startTimeCurrent).getDay() === 0 ? 7 : new Date(startTimeCurrent).getDay();
for (let i = 0; i < dayCount; i++) {
const timeCurrent = i <= startTimeWeekNum ? (startTimeCurrent - (startTimeWeekNum - (i + 1)) * 24 * 3600000) :
(startTimeCurrent + ((i + 1) - startTimeWeekNum) * 24 * 3600000);
dateLine.push({
isToday: this.utils.formatter('date', timeCurrent, 'YYYYMMDD') ===
this.utils.formatter('date', Date.now(), 'YYYYMMDD'),
isWeekend: new Date(timeCurrent).getDay() === 0 || new Date(timeCurrent).getDay() === 6,
year: new Date(timeCurrent).getFullYear(),
month: new Date(timeCurrent).getMonth() + 1,
day: new Date(timeCurrent).getDate(),
dateString: this.utils.formatter('date', timeCurrent, 'YYYY-MM-DD'),
weekNum: new Date(timeCurrent).getDay(),
weekString: weekChinese[(new Date(timeCurrent).getDay() === 0 ? 6 : new Date(timeCurrent).getDay() - 1)],
});
}
this.setState({
dateLine,
selectedDay: dateLine[startTimeWeekNum - 1],
});
}

The header timeline data source is bound, as shown in the following figure:

Rendering date

Bind a custom style class to the time frame with the date Saturday and Sunday to distinguish the style from the workday;

Configure the header timeline-date cell, callback event when clicking;

// 选择日期
export function onSelectDay() {
const { selectedDay, boardType } = this.state;
const { dateString } = this.item;
if (boardType === 'day') {
if (dateString === selectedDay.dateString) {
return;
}
this.setState({
selectedDay: this.item,
});
this.getDateList();
this.getViewMainData();
}
}

Determine whether the date in the Time box is the current date, and use custom style classes to distinguish the day;

Click more to display and load the calendar chart in the pop-up window of calendar;

// 更多日期
export function onClickMoreMonth() {
this.$('日历弹窗唯一标识').show(() => {
this.renderCalendar();
});
}
// 日历渲染
export function renderCalendar() {
const { year, month } = this.state;
const nowMonthStartDayWeekNum = new Date(year, month - 1, 1).getDay(); // 获取当前月第一天星期数
const nowMonthEndDayWeekNum = new Date(year, month, 0).getDay(); // 获取当前月最后一天星期数
const nowMonthEndDayNum = new Date(year, month, 0).getDate(); // 获取当前月最后一天天数
const lastMonthEndDayNum = new Date(year, month - 1, 0).getDate(); // 获取上个月最后一天天数
const lastMonthDateList = _.range(lastMonthEndDayNum - nowMonthStartDayWeekNum + 1, lastMonthEndDayNum + 1, 1).map((item) => {
return {
type: 'lastMonth',
isToday: false,
year: month - 1 > 0 ? year : year - 1,
month: month - 1 > 0 ? month - 1 : 12,
day: item,
dateString: `${month - 1 > 0 ? year : year - 1}-${month - 1 > 0 ? month - 1 : 12}-${item}`,
};
}); // 上月日期序列
const nowMonthDateList = _.range(1, nowMonthEndDayNum + 1, 1).map((item) => {
return {
type: 'nowMonth',
isToday: item === new Date().getDate() && month === new Date().getMonth() + 1 && year === new Date().getFullYear(),
year,
month,
day: item,
dateString: `${year}-${month}-${item}`,
};
}); // 本月日期序列
const nextMonthDateList = _.range(1, 7 - nowMonthEndDayWeekNum, 1).map((item) => {
return {
type: 'nextMonth',
isToday: false,
year: month - 1 < 13 ? year : +year + 1,
month: +month + 1 < 13 ? +month + 1 : 1,
day: item,
dateString: `${month - 1 < 13 ? year : +year + 1}-${+month + 1 < 13 ? +month + 1 : 1}-${item}`,
};
}); // 下月日期序列
this.setState({
calendarDateList: [...lastMonthDateList, ...nowMonthDateList, ...nextMonthDateList],
});
}

// 切换年月
export function changeYearOrMonth() {
const { type } = this.params;
const { year, month } = this.state;
switch (type) {
case 'lastYear':
this.setState({
year: year - 1,
});
break;
case 'nextYear':
this.setState({
year: +year + 1,
});
break;
case 'lastMonth':
this.setState({
month: month - 1 > 0 ? month - 1 : 12,
year: month - 1 > 0 ? year : year - 1,
});
break;
case 'nextMonth':
this.setState({
month: +month + 1 < 13 ? +month + 1 : 1,
year: +month + 1 < 13 ? year : +year + 1,
});
break;
case 'nowMonth':
this.setState({
month: new Date().getMonth() + 1,
year: new Date().getFullYear(),
clickValue: this.utils.formatter('date', Date.now(), 'YYYY-M-D'),
});
break;
default:
// console.log('无效的状态');
break;
}
this.renderCalendar();
}

Click the date in calendar to configure the callback event, as shown in the following figure:

// 点击日历
export function onCalendarCellClick() {
this.setState({
clickValue: this.item.dateString,
currentPage: 1,
});
this.getDateLine(new Date(`${this.item.year}/${this.item.month}/${this.item.day}`).getTime());
this.getDateList();
this.getViewMainData();//执行获取任务数据
this.$('日历弹窗唯一标识').hide();
}

2.7. Day View​

2.7.1. Time cell acquisition and rendering​

2.7.1.1. Time cell data acquisition​
// 日视图 - 获取单元格 cell
export function getDateDayList() {
const { dateType, selectedDay } = this.state;
const startHour = dateType === 'all' ? 0 : 8;
const endHour = dateType === 'all' ? 24 : 22;
const dayDateCellList = [];
const dateLabelList = [];
for (let i = startHour; i < endHour; i += 0.5) {
dayDateCellList.push({
hour: parseInt(i, 10),
minute: Number.isInteger(i) ? 0 : 30,
str: `${parseInt(i, 10)}:${Number.isInteger(i) ? '00' : '30'}`,
current: new Date(`${selectedDay.dateString} ${parseInt(i, 10)}:${Number.isInteger(i) ? '00' : '30'}`).getTime(),
});
}
for (let i = startHour; i <= endHour; i++) {
dateLabelList.push(i);
}
this.setState({
dateCellList: dayDateCellList,
dateLabelList,
});
}
// 合并函数 - 获取单元格 cell
export function getDateList() {
const { boardType } = this.state;
switch (boardType) {
case 'day':
this.getDateDayList();//获取日视图-单元格cell
break;
case 'week':
this.getDateWeekList();//获取周视图-单元格cell
break;
default:
break;
}
}
2.7.1.2. Time cell data source binding;​

The display position of the dynamic rendering time scale according to different time types;

// 日视图 - 时间刻度动态定位
export function renderDataLabel() {
const { dateLabelList } = this.state;
return (
dateLabelList.map((item, index) => {
return (
<div
className="date_label"
style={{
left: `${(100 / (dateLabelList.length - 1)) * index}%`,
}}
>
{item}
</div>
);
})
);
}

2.7.2. Task executor and task data acquisition and rendering​

Page JS didmount

Obtain task executors and task data;

export async function getDayViewData() {
const { pageSize, currentPage, selectedDay, userSearchQuery, taskSearchQuery } = this.state;
this.setState({
loading: true,
});
const userData = await this.dataSourceMap.getData.load({
formUuid: '任务执行人表单formUuid',//任务执行人formUuid
page: currentPage,
limit: pageSize,
pageSize,
currentPage,
searchField: JSON.stringify([...userSearchQuery]),
logicOperator: 'AND',
}).then((res) => {
const { values = [], currentPage, totalCount } = res;
const data = this.formatInstValue(values); // 格式化数据
const userList = data.map((item) => {
return {
formInstId: item.formInstanceId, // 实例 id
name: item.姓名唯一标识, // 执行人姓名
userId: item.userId唯一标识, // 执行人 userId
taskList: [], // 任务列表
};
});
return {
currentPage,
data: userList,
totalCount,
};
}).catch((error) => {
this.utils.toast({
title: error.message,
type: 'error',
});
return {
data: [],
currentPage: 1,
totalCount: 0,
};
});
this.setState({
userData,
loading: false,
});
if (!userData.totalCount) {
return;
}
const taskDataResult = {
data: [],
totalCount: 0,
};
await this.dataSourceMap.getData.load({
formUuid: '任务录入表单的formUuid',//任务录入表单formuuid
page: 1,
limit: 100,
currentPage: 1,
pageSize: 100,
searchField: JSON.stringify([...[
{
key: '开始时间唯一标识',
value: new Date(selectedDay.dateString).setHours(23, 59, 59, 999),
type: 'DOUBLE',
operator: 'le',
componentName: 'DateField',
}, {
key: '结束时间唯一标识',
value: new Date(selectedDay.dateString).setHours(0, 0, 0, 0),
type: 'DOUBLE',
operator: 'ge',
componentName: 'DateField',
}, {
key: '任务执行人唯一标识',
value: userData.data.map((item) => { return item.userId; }),
type: 'STRING',
operator: 'contains',
componentName: 'EmployeeField',
},
], ...taskSearchQuery]),
logicOperator: 'AND',
}).then((res) => {
// 处理每次返回的结果
const { values = [], totalCount } = res;
const taskData = this.formatInstValue(values); // 格式化数据
taskDataResult.data.push(...taskData);
taskDataResult.totalCount = totalCount;
}).catch((error) => {
this.utils.toast({
title: error.message,
type: 'error',
});
});
//接口返回数据超100条处理
if (taskDataResult.totalCount > 100) {
for (let i = 2; i < Math.ceil(taskDataResult.totalCount / 100) + 1; i++) {
const delay = i === 2 ? 0 : 100;
await new Promise((resolve) => {
setTimeout(async () => {
await this.dataSourceMap.getData.load({
formUuid: '任务录入页面formUuid',//任务录入页面formUuid
page: i,
currentPage: i,
limit: 100,
pageSize: 100,
searchField: JSON.stringify([...[
{
key: '开始时间唯一标识',
value: new Date(selectedDay.dateString).setHours(23, 59, 59, 999),
type: 'DOUBLE',
operator: 'le',
componentName: 'DateField',
}, {
key: '结束时间唯一标识',
value: new Date(selectedDay.dateString).setHours(0, 0, 0, 0),
type: 'DOUBLE',
operator: 'ge',
componentName: 'DateField',
}, {
key: '任务执行人唯一标识',
value: userData.data.map((item) => { return item.userId; }),
type: 'STRING',
operator: 'contains',
componentName: 'EmployeeField',
},
], ...taskSearchQuery]),
logicOperator: 'AND',
}).then((res) => {
const { values = [] } = res;
const taskData = this.formatInstValue(values); // 格式化数据
taskDataResult.data.push(...taskData);
});
resolve();
}, delay);
});
}
}
for (let i = 0; i < userData.data.length; i++) {
userData.data[i].taskList = taskDataResult.data.filter((item) => {
return item.textField_llc16ij6 === userData.data[i].userId;
});
}
this.setState({
userData,
});
}
// 合并函数 - 获取数据
export function getViewMainData() {
const { boardType } = this.state;
switch (boardType) {
case 'day':
this.getDayViewData();
break;
case 'week':
this.getWeekViewData();
break;
default:
break;
}
}
// 数据格式化
export function formatInstValue(values = []) {
return values.map((item) => {
const { formInstanceId, formUuid, processInstanceId, instValue = '' } = item;
const formData = {};
if (instValue) {
JSON.parse(instValue).forEach((_item) => {
switch (_item.componentName) {
case 'RadioField':
case 'SelectField':
formData[_item.fieldId] = _item.fieldData.text;
formData[`${_item.fieldId}_id`] = _item.fieldData.value;
break;
default:
formData[_item.fieldId] = _item.fieldData.value;
}
});
}
return {
formInstanceId,
formUuid,
processInstanceId,
...formData,
};
});
}

Bind the task executor data source

Name of the rendering task executor

2.7.3. Use the obtained task to pass parameters in a custom style class to render the cell status-in progress and completed​

// 日视图 - 单元格状态
export function dateCellStatus(taskList, currentTime) {
if (!taskList || !currentTime) {
return {
taskList: [],
cellClassName: '',
};
}
const filterResult = taskList.filter((f) => {
return currentTime >= f.dateField_llbm0xap && currentTime < f.dateField_llbm0xaq;
});
const taskStatusList = filterResult.map((i) => {
return i.radioField_llbm0xav_id;
});
if (!taskStatusList.length) {
return {
taskList: filterResult,
cellClassName: 'normal',
};
} else {
if (taskStatusList.indexOf('running') !== -1) {
return {
taskList: filterResult,
cellClassName: 'running',
};
}
return {
taskList: filterResult,
cellClassName: 'finish',
};
}
}

2.7.4. Configure task status cell click callback event​

Display different pop-up windows according to the status of the cell;

// 日视图 - 点击单元格
export function onDateCellClick() {
const { taskList, cellClassName } = this.dateCellStatus(this.item.taskList, this._item.current);
switch (cellClassName) {
case 'finish':
case 'running':
this.setState({
taskDetail: taskList,
});
this.$('任务详情的弹窗唯一标识').show();
break;
default:
this.$('任务指派的弹窗唯一标识').show(() => {
this.$('任务类型唯一标识').reset();
this.$('任务名称唯一标识').reset();
this.$('任务接受人唯一标识').setValue({
label: this.item.name,
value: this.item.userId,
});
});
}
}
2.7.4.1. Cell status-when running and completed, the task details pop-up window is displayed.​

Task details data source binding;

In the task details, the task number field is rendered, as shown in the following figure:

In the task details, the task name field is rendered, as shown in the following figure:

In task details, the content of the task category field is rendered, as shown in the following figure:

In the task details, the content of the start and end time field is rendered, as shown in the following figure:

`${utils.formatter('date', item.dateField_llbm0xap, 'YYYY-MM-DD hh:mm')} ~ ${utils.formatter('date', item.dateField_llbm0xaq, 'YYYY-MM-DD hh:mm')}`

In the task details, the task duration field is rendered, as shown in the following figure:

In task details, the task status field is rendered, as shown in the following figure:

In the task details, the task executor field is rendered, as shown in the following figure:

2.7.4.2. Cell status-when idle, task assignment appears in the pop-up window.​

The task assignment dialog box binds the following functions:

// 日视图 - 任务指派
export function onCreateTask() {
const fieldList = [
'任务类别唯一标识',
'任务名称唯一标识',
'任务接收人唯一标识',
];
// 调用表单校验函数
this.fieldsValidate(fieldList).then((errorList) => {
setTimeout(() => {
if (errorList.length > 0) {
// 表单校验未通过,可做一些数据错误提示
return;
}
this.$('任务指派弹窗唯一标识').set('confirmState', 'LOADING');
// 表单校验通过,你的后续业务逻辑由此往下写
this.dataSourceMap.startInstance.load({
processCode: '任务录入流程code',//TPROC--K0766T9165CFM3L5DZX5TBBRUUMJ27KB6K6OLQ8
formUuid: '任务录入表单formUuid',
formDataJson: JSON.stringify({
radioField_lldjbq09: '指派', // 提交方式
radioField_llbm0xaf: this.$('任务类别唯一标识').getValue(), // 任务类别
textField_llbm0xai: this.$('任务名称唯一标识').getValue(), // 任务名称
employeeField_llbm0xag: Array.isArray(this.$('任务接收人唯一标识').getValue()) ?
[this.$('任务接收人唯一标识').getValue()[0].value] :
[this.$('任务接收人唯一标识').getValue().value], // 任务接收人
textField_llc16ij5: Array.isArray(this.$('employeeField_llbm0xag').getValue()) ?
this.$('任务接收人唯一标识').getValue()[0].label :
this.$('任务接收人唯一标识').getValue().label, // 任务接收人姓名
textField_llc16ij6: Array.isArray(this.$('employeeField_llbm0xag').getValue()) ?
this.$('任务接收人唯一标识').getValue()[0].value :
this.$('任务接收人唯一标识').getValue().value, // 任务接收人 userId
radioField_llbm0xav: 'running', // 任务状态
}),
}).then(() => {
this.$('任务指派弹窗唯一标识').set('confirmState', 'NORMAL');
this.utils.toast({
title: '任务指派成功',
type: 'success',
});
this.$('任务指派弹窗唯一标识').hide();
}).catch((error) => {
this.$('任务指派弹窗唯一标识').set('confirmState', 'NORMAL');
this.utils.toast({
title: error.message,
type: 'error',
});
});
i});
}, 0);
}
// fieldList:Array,需要校验组件的唯一标识集合
export async function fieldsValidate(fieldList = []) {
const result = [];
for (let i = 0; i < fieldList.length; i++) {
await this.$(fieldList[i]).validate((errors) => {
if (!errors) {
return;
}
result.push({
fieldId: fieldList[i], // 组件标识
errors: this.utils.isMobile() ? errors.errors[fieldList[i]].errors : errors[fieldList[i]].errors, // 校验错误信息
});
});
}
return result;
}

2.7.5. Pagination settings​

"Total number", "current page number", "number of instances per page" bind variables

Switch page numbers and bind callback events

// 日视图 - 切换页码
export function onPaginationChange(currentPagination) {
this.setState({
currentPage: currentPagination,
});
this.getViewMainData();
}

// 日视图 - 切换每页显示数
export function onPageSizeChange(pageSize) {
this.setState({
pageSize,
});
this.getViewMainData();
}

2.8. Weekly view​

2.8.1. Time cell acquisition and rendering​

Page JS obtains time cell data


// 周视图 - 获取单元格 cell
export function getDateWeekList() {
const { dateType, dateLine } = this.state;
const startHour = dateType === 'all' ? 0 : 8;
const endHour = dateType === 'all' ? 24 : 22;
const weekDateCellList = {};
const weekDateLabelList = [];
for (let i = startHour; i < endHour; i += 0.5) {
weekDateCellList[`${parseInt(i, 10)}:${Number.isInteger(i) ? '00' : '30'}`] = [];
dateLine.forEach((item) => {
weekDateCellList[`${parseInt(i, 10)}:${Number.isInteger(i) ? '00' : '30'}`].push({
...item,
current: new Date(`${item.dateString} ${parseInt(i, 10)}:${Number.isInteger(i) ? '00' : '30'}`).getTime(),
});
});
}
for (let i = startHour; i <= endHour; i += 0.5) {
weekDateLabelList.push(`${parseInt(i, 10)}:${Number.isInteger(i) ? '00' : '30'}`);
}
this.setState({
dateWeekCellList: weekDateCellList,
weekDateLabelList,
});
}

Bind the time cell data source;

Dynamically Render the time scale position of the cell through the time cell data;

2.8.2. Obtain and render task data​

// 周视图 - 获取数据
export async function getWeekViewData() {
const { taskSearchQuery, dateLine } = this.state;
this.setState({
loading: true,
});
const taskDataResult = {
data: [],
totalCount: 0,
};
await this.dataSourceMap.getData.load({
formUuid: 'FORM-S9866D91J35FS450FVDK86VZULXJ232B6K6OLMQ',
page: 1,
limit: 100,
currentPage: 1,
pageSize: 100,
searchField: JSON.stringify([...[
{
key: 'dateField_llbm0xap',
value: new Date(dateLine[dateLine.length - 1].dateString).setHours(23, 59, 59, 999),
type: 'DOUBLE',
operator: 'le',
componentName: 'DateField',
}, {
key: 'dateField_llbm0xaq',
value: new Date(dateLine[0].dateString).setHours(0, 0, 0, 0),
type: 'DOUBLE',
operator: 'ge',
componentName: 'DateField',
},
], ...taskSearchQuery]),
logicOperator: 'AND',
}).then((res) => {
// 处理每次返回的结果
const { values = [], totalCount } = res;
const taskData = this.formatInstValue(values); // 格式化数据
taskDataResult.data.push(...taskData);
taskDataResult.totalCount = totalCount;
}).catch((error) => {
this.utils.toast({
title: error.message,
type: 'error',
});
});
if (taskDataResult.totalCount > 100) {
for (let i = 2; i < Math.ceil(taskDataResult.totalCount / 100) + 1; i++) {
const delay = i === 2 ? 0 : 100;
await new Promise((resolve) => {
setTimeout(async () => {
await this.dataSourceMap.getData.load({
formUuid: '任务录入页面formUuid',//任务录入formUuid
page: i,
currentPage: i,
limit: 100,
pageSize: 100,
searchField: JSON.stringify([...[
{
key: '开始时间',
value: new Date(dateLine[dateLine.length - 1].dateString).setHours(23, 59, 59, 999),
type: 'DOUBLE',
operator: 'le',
componentName: 'DateField',
}, {
key: '结束时间',
value: new Date(dateLine[0].dateString).setHours(0, 0, 0, 0),
type: 'DOUBLE',
operator: 'ge',
componentName: 'DateField',
},
], ...taskSearchQuery]),
logicOperator: 'AND',
}).then((res) => {
const { values = [] } = res;
const taskData = this.formatInstValue(values); // 格式化数据
taskDataResult.data.push(...taskData);
});
resolve();
}, delay);
});
}
}
this.setState({
userData: taskDataResult,
loading: false,
});
}

2.8.3. Render time cell task status​

// 周视图 - 单元格状态
export function weekDateCellStatus(currentTime) {
const { userData } = this.state;
if (!userData.totalCount || !currentTime) {
return {
taskList: [],
cellClassName: '',
};
}
const filterResult = userData.data.filter((f) => {
return currentTime >= f.dateField_llbm0xap && currentTime < f.dateField_llbm0xaq;
});
const taskStatusList = filterResult.map((i) => {
return i.radioField_llbm0xav_id;
});
if (!taskStatusList.length) {
return {
taskList: filterResult,
cellClassName: 'normal',
};
} else {
if (taskStatusList.indexOf('running') !== -1) {
return {
taskList: filterResult,
cellClassName: 'running',
};
}
return {
taskList: filterResult,
cellClassName: 'finish',
};
}
}

2.8.4. Cell Task status click callback event​


// 周视图 - 点击单元格
export function onWeekCellClick() {
const { taskList, cellClassName } = this.weekDateCellStatus(this._item.current);
switch (cellClassName) {
case 'finish':
case 'running':
this.setState({
taskDetail: taskList,
});
this.$('任务详情弹窗唯一标识').show();
break;
default:
this.$('任务指派弹窗唯一标识').show(() => {
this.$('任务类别唯一标识').reset(); //清空任务类别
this.$('任务名称唯一标识').reset();//清空任务名称
this.$('任务接收人唯一标识').reset();//清空任务接收人
});
}
}

2.9. Search box query configuration​

2.9.1. Add a query component​

2.9.2. Bind search events​


// 搜索
export function onSubmit() {
const { boardType } = this.state;
const values = {
employeeField_llbnstfm: !this.$('employeeField_llbnstfm').getValue() || !this.$('employeeField_llbnstfm').getValue().length ? '' : this.$('employeeField_llbnstfm').getValue(),
selectField_llbnstfn: this.$('selectField_llbnstfn').getValue(),
textField_llbnstfh: this.$('textField_llbnstfh').getValue(),
};
if (boardType === 'day') {
this.setState({
userSearchQuery: [{
key: 'employeeField_lldfain9',
value: values.employeeField_llbnstfm ? values.employeeField_llbnstfm.map((item) => { return item.value; }) : '',
type: 'STRING',
operator: 'contains',
componentName: 'EmployeeField',
}],
taskSearchQuery: [{
key: 'radioField_llbm0xaf',
value: values.selectField_llbnstfn === 'all' ? '' : values.selectField_llbnstfn,
type: 'ARRAY',
operator: 'eq',
componentName: 'RadioField',
}, {
key: 'textField_llbm0xai',
value: values.textField_llbnstfh || '',
type: 'TEXT',
operator: 'ilike',
componentName: 'TextField',
}],
currentPage: 1,
});
}
if (boardType === 'week') {
this.setState({
taskSearchQuery: [{
key: 'radioField_llbm0xaf',
value: values.selectField_llbnstfn === 'all' ? '' : values.selectField_llbnstfn,
type: 'ARRAY',
operator: 'eq',
componentName: 'RadioField',
}, {
key: 'textField_llbm0xai',
value: values.textField_llbnstfh || '',
type: 'TEXT',
operator: 'ilike',
componentName: 'TextField',
}, {
key: 'employeeField_llbm0xag',
value: values.employeeField_llbnstfm ? values.employeeField_llbnstfm.map((item) => { return item.value; }) : '',
type: 'STRING',
operator: 'contains',
componentName: 'EmployeeField',
}],
});
}
this.getViewMainData();
}

2.9.3. Bind reset event​

// 重置
export function onReset() {
this.$('selectField_llbnstfn').setValue('all');
this.$('textField_llbnstfh').reset();
this.$('employeeField_llbnstfm').reset();
this.setState({
userSearchQuery: {},
taskSearchQuery: [],
currentPage: 1,
});
this.getViewMainData();
}

3. Effect​

3.1. Day View​

3.2. Weekly view​

4. Precautions​

Note: modify the task assignment process Code first after you enable it. Otherwise, an error will be triggered [the association between the page and the process does not exist]].

View path: Application Settings-> deployment O & M-> task entry-> Process Code

5. Try it online​

This doc is generated using machine translation. Any discrepancies or differences created in the translation are not binding and have no legal effect for compliance or enforcement purposes.