メインコンテンツまでスキップ

カスタムページとカレンダー図を組み合わせてタスク看板を実現

1. 使用シーン

この例では、カスタムページで「日ビュー」と「週ビュー」のタスク看板をどのように実現するかを紹介します。

2. 機能を実現する

2.1. ページストレージタスクとタスク実行者の作成

2.1.1. タスク入力

プロセスページで、現在のページにタスク詳細データを公開します

2.1.2. タスク実行者

プロセスページ、タスク実行者の基礎データを入力する

2.2. カスタムページの作成

2.3. データソースと変数の設定

2.3.1. リモートデータソースの設定

タスク/タスク実行者を取得します。インタフェース構成は次の図のとおりです

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

【タスク入力】開始、インタフェース構成は次の図のようになります

参考ドキュメント:プロセス開始

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

2.4. 設定変数

2.4.1. 現在のビュータイプ

2.4.2. タスク実行者データ

2.4.3. タスク受信者照会パラメータ

2.4.4. タスク照会パラメータ

2.4.5. 1ページあたりのインスタンス数

2.4.6. 現在のページ番号

2.4.7. ロードステータス

2.4.8. 頭部時間軸 (月曜日から日曜日まで) のデータ

2.4.9. 「日ビュー」タスク時間セルデータ

2.4.10. 「日ビュー」タスクセル時間スケール

2.4.11. 「週ビュー」タスクセル時間スケール

2.4.12. 「週ビュー」タスク時間セルデータ

2.4.13. タスク日付照会パラメータ

2.4.14. タスクセル時間スケールタイプ

2.4.15. タスク詳細データ

2.4.16. カレンダー図データ

2.4.17. 「カレンダー」図の日付選択クエリパラメータ

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

2.4.18. 「カレンダー」図は年を表示します

2.4.19. 「カレンダー」グラフには月が表示されます

2.5. ヘッド切替パネル配置

2.5.1. カスタムスタイルクラスを使用して、タスクの状態を異なる色にレンダリングします

タスクは「進行中」で、「running」をバインドします

タスクは「完了」で、「finish」をバインドします

ページプロパティ-スタイル、設定タスクは、次の図のように異なる状態でスタイルされます

2.5.2. ビュータイプの切り替え、デフォルトの【日ビュー】、コールバックイベントをバインドし、異なるタイプのタスクビューをレンダリングします

カスタムスタイルクラスをバインドすることで、タスクビューの選択ステータスを表示します

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

次の図のようにステータススタイル設定を選択します

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

「その他」をクリックして、コールバックイベントを設定します

// 切换面板显示类型
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. 時間タイプを切り替え、異なるタイプの時間cellをレンダリングします

デフォルトの時間タイプ: 8-22; カスタムスタイルクラスをバインドすることで、時間タイプの選択ステータスをレンダリングします

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

設定アクションパネルの8-22時間タイプパラメータ

時間タイプ-終日

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

時間タイプは、次の図のように、バインドコールバックイベントを切り替えます


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

2.6. 頭部時間軸レンダリング

「ページjs」ヘッダ時間軸データ取得

// 创建头部时间轴
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],
});
}

次の図に示すように、頭部時間軸データソースのバインディング

レンダリング日

日付が「土曜日の日」の時間枠を、カスタムスタイルクラスをバインドすることで、平日とスタイルを区別する

ヘッダータイムライン-日付セル、クリック時のコールバックイベントを設定します

// 选择日期
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();
}
}

時間枠内の日付が現在の日付かどうかを判断し、カスタムスタイルクラスで当日を区別する

もっとクリックすると、「カレンダー」の弾倉がカレンダー図を表示してロードします

// 更多日期
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();
}

「カレンダー」の日付をクリックして、次の図のようにコールバックイベントを設定します

// 点击日历
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. 日ビュー

2.7.1. 時間セルcellの取得とレンダリング

2.7.1.1. 時間セルデータ取得
// 日视图 - 获取单元格 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. 時間セルデータソースバインディング

時間タイプに応じて、タイムスケール表示位置を動的にレンダリングします

// 日视图 - 时间刻度动态定位
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. タスク実行者とタスクデータの取得とレンダリング

「ページjs」didmount呼び出し

タスク実行者とタスクデータを取得する

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,
};
});
}

「タスク実行者」データソースのバインド

レンダリングタスク実行者名

2.7.3. 取得したタスクをカスタムスタイルクラスと組み合わせてパラメータを渡すことで、セルの状態をレンダリング-進行中、完了

// 日视图 - 单元格状态
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. タスクステータスセルのクリックコールバックイベントの設定

セルの状態に応じて、異なる弾倉を表示します

// 日视图 - 点击单元格
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. セルステータス-実行中、完了時に「タスク詳細」ポップアップが表示されます

タスク詳細データソースバインディング

タスクの詳細では、「タスク番号」フィールドの内容が次の図のようにレンダリングされます

タスクの詳細では、「タスク名」フィールドの内容が次の図のようにレンダリングされます

タスクの詳細では、「タスクカテゴリ」フィールドの内容が次の図のようにレンダリングされます

タスクの詳細では、「開始時間」フィールドの内容が次の図のようにレンダリングされます

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

タスクの詳細では、「タスク時間」フィールドの内容が次の図のようにレンダリングされます

タスクの詳細では、「タスクステータス」フィールドの内容が次の図のようにレンダリングされます

タスクの詳細では、「タスク実行者」フィールドの内容が次の図のようにレンダリングされます

2.7.4.2. セルステータス-アイドル時に「タスク割り当て」ポップアップが表示されます

「タスク割り当て」ダイアログには、次の関数がバインドされています

// 日视图 - 任务指派
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. ページング設定

「総件数」、「現在のページ番号」、「ページあたりのインスタンス数」のバインディング変数

ページ番号を切り替え、コールバックイベントをバインドします

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

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

2.8. 周ビュー

2.8.1. 時間セルcellの取得とレンダリング

「ページjs」は時間セルデータを取得します


// 周视图 - 获取单元格 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,
});
}

時間セルデータソースをバインドする

時間セルデータにより、セル時間スケール位置を動的にレンダリングする;

2.8.2. タスクデータの取得とレンダリング

// 周视图 - 获取数据
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. レンダリング時間セルタスクステータス

// 周视图 - 单元格状态
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. セルタスクステータスのクリックコールバックイベント


// 周视图 - 点击单元格
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. 検索ボックスクエリ設定

2.9.1. クエリコンポーネントの追加

2.9.2. 検索イベントのバインド


// 搜索
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. バインディングリセットイベント

// 重置
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. 効果を実現する

3.1. 日ビュー

3.2. 周ビュー

4. 注意事項

特に注意: 有効にすると、まずタスク割り当てプロセスcodeを変更してください。変更しないと、「ページとプロセスの関連関係が存在しません」というエラーが発生します。

パスの表示: アプリケーション設定-> 輸送次元の導入-> タスク入力-> プロセスコード

5. オンラインで試遊する

Copyright © 2025钉钉(中国)信息技术有限公司和/或其关联公司浙ICP备18037475号-4