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.
Copyright © 2024钉钉(中国)信息技术有限公司和/或其关联公司浙ICP备18037475号-4