如何通过在线表格实现资源预定

本文介绍了如何通过zOffice在线表格实现资源预定,包括通过zOffice的多人协同编辑功能和SDK实现预定,确保数据安全,提供了详细的集成和实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在日常的工作和生活中,我们常常需要预定会议室或者某个场所进行某个活动,例如:在公司里,需要预定某个时间段的会议室,还有在学校里,我们需要预定羽毛球馆、篮球馆、等等活动,像这种资源预定的场景比比皆是,那我们怎么能简单的实现资源预定呢?答案是通过zOffice在线表格

zOffice简介

zOffice提供云端Office能力,包括word、excel、ppt三类办公文档的在线协同编辑,通过专业级的文档能力,高效的协作体验,内容级的安全管控,丰富的集成开发接口,来赋能企业的业务系统,帮助业务系统实现文档在线预览和编辑,文档操作过程全部线上进行,完成在线办公的场景闭环。

zOffice链接:https://www.filez.com/zoffice

集成介绍文档:http:// https://lenovocloud.zbox.filez.com/l/a0OsO0

实现方案

1、方式一:通过zOffice多人协同在线编辑实现资源预定

业务系统可以与zOffice集成,具体如何集成参考:

https://hello.word.com/(替换成集成链接)

比如会议室预定,我们建一个这样的在线表格,只要想订会议室的人都可以进这个表格,也许你会认为别人会篡改你的内容,但是zOffice在线编辑有单元格历史记录,还有协作记录,如果你的内容被改了,很快就能找到是谁,非常的安全好用。

2、方式二:通过zOffice SDK实现

通过zOffice SDK实现资源预定,zOffice SDK拥有非常丰富的接口,可以通过监听预定的区域,当有人输入内容时,校验是否有冲突,冲突的结果可以用颜色标记。

步骤一:挂载一个会议室模板文件,定义一个app变量,添加监听

app.addListener('Workbook.Event.Change', callback);

当你输入内容,callback函数就会执行。

步骤二:获取会议室模板文件的会议室,预定日期

const roomsheet = await app.ActiveWorkbook.getSheetByName('会议室预定');

const meetingRoomNum: number[] = [702, 708, 709, 710];

const listendRange = roomsheet.getRange(1, 1, 30, 25);

const firstCol = roomsheet.getRange(1, 1, 30, 1); // 第一列存储了会议室

const firstRow = roomsheet.getRange(1, 1, 1, 25); // 第一行存储了预定日期

步骤三:判断输入的预定时间是否冲突,1代表冲突,0代表不冲突,可以设置条件格式用红色表示1。

所有的demo的代码如下:

      {

        text: '会议室demo',

        exec: async(app: Excel.APP) => {

          if (app.events.includes('Workbook.Event.Change')) {

            app.removeListener('Workbook.Event.Change');

            console.log('取消监听Change');

            return;

          }

          const callback = async(range: Excel.Range) => {

            console.log('会议室callback执行');

            if (isInsectedRange(listendRange, range)) { // 修改位置位于监听区域内

              const timeTableMap = await updateModel(); // update model

                // 获得冲突位置对应的item

                for (let i = 0; i < timeTableMap.length; i += 1) {

                  const currentRange = timeTableMap[i].timeRange;

                  if (isInsectedRange(currentRange, range)) { // 是冲突区间

                    const repeatTime = getRepeatTime(timeTableMap[i].timeArr);

                    const posRange = timeTableMap[i].posRange;

                    const ret = [];

                    for (let j = 0; j < repeatTime.length; j += 1) {

                      if (repeatTime[j]) {

                        ret.push(['1']);

                      } else {

                        ret.push(['0']);

                      }

                    }

                    await posRange.setValues(ret);

                  }

                }

            }

          };

          app.addListener('Workbook.Event.Change', callback);

          console.log('添加监听Change');

          const roomsheet = await app.ActiveWorkbook.getSheetByName('会议室预定');

          const meetingRoomNum: number[] = [702, 708, 709, 710];

          const listendRange = roomsheet.getRange(1, 1, 30, 25);

          const firstCol = roomsheet.getRange(1, 1, 30, 1); // 第一列存储了会议室

          const firstRow = roomsheet.getRange(1, 1, 1, 25); // 第一行存储了预定日期

          interface timeTableItem {

            room: number; // 房间号

            date: string; // 日期

            timeArr: string [][]; // 二维数组,n x 2 eg.start_time end_time

            timeRange: Excel.Range; // 用来存储timeArr所在的位置

            posRange: Excel.Range; // 用来存储冲突校验的结果

          }

          enum FindingType {

            FindDate = 1,

            FindRoom = 2,

            // FindCondition = 3,

          }

          const getIndexTable = async(targetRange: Excel.Range, type: FindingType): Promise<any> => {

            const mergedRanges = await targetRange.getMergedRanges();

            if (mergedRanges.length > 0) {

              switch (type) {

                case FindingType.FindDate: {

                  const ret: number[][] = [];

                  for (let i = 0; i < mergedRanges.length; i += 1) {

                    const current = mergedRanges[i];

                    if (current.endColumn > current.column) { // colspan > 1 认为是date

                      ret.push([current.column, current.endColumn]);

                    }

                  }

                  return ret;

                }

                case FindingType.FindRoom: {

                  const ret: number[][] = [];

                  for (let i = 0; i < mergedRanges.length; i += 1) {

                    const current = mergedRanges[i];

                    if (current.endRow > current.row) { // rowspan > 1 认为是room

                      ret.push([current.row, current.endRow]);

                    }

                  }

                  return ret;

                }

              }

            }

          };

          const rowIdx = await getIndexTable(firstCol, FindingType.FindRoom);

          const colIdx = await getIndexTable(firstRow, FindingType.FindDate);

          // 首先填充数据模型

          const updateModel = async() => {

            const timeTableMap: timeTableItem[] = [];

            for (let i = 0; i < rowIdx.length; i += 1) {

              for (let j = 0; j < colIdx.length; j += 1) {

                const roomCell = await firstCol.getCell(rowIdx[i][0], 1);

                const roomValue = await roomCell.getValue(); // 拿到房间号

                const dateCell = await firstRow.getCell(1, colIdx[j][0]);

                const dateValue = await dateCell.getValue(); // 拿到日期

                const timeRange = await roomsheet.getRange(rowIdx[i][0], colIdx[j][0], rowIdx[i][1], colIdx[j][1]); // 拿到时间数组所在的位置

                const timeValues = await timeRange.getValues(); // 拿到时间数组

                // 拿到条件格式位置信息(没有时间内容,不算posRange

                const timeLen = timeValues.length;

                const posRange = await roomsheet.getRange(rowIdx[i][0], colIdx[j][1] + 1, rowIdx[i][0] + timeLen - 1, colIdx[j][1] + 1);

                timeTableMap.push({ room: roomValue, date: dateValue, timeArr: timeValues, posRange, timeRange });

              }

            }

            return timeTableMap;

          };

          // 寻找冲突项

          const isInsectedRange = (targetRange: Excel.Range, sourceRange: Excel.Range) => {

            const rowInsected = !(targetRange.endRow < sourceRange.row  targetRange.row > sourceRange.endRow);

            const colInseted = !(targetRange.endColumn < sourceRange.column  targetRange.column > sourceRange.endColumn);

            return rowInsected && colInseted ? true : false;

          };

          // 其次判断时间冲突

          const getRepeatTime = (timeArr: string[][]) => {

            const len = timeArr.length;

            const repeatFlag: boolean[] = Array(len).fill(false);

            for (let i = 0; i < timeArr.length; i += 1) {

              const orderA = timeArr[i];

              if (!isValidTimeArr(orderA)) {

                repeatFlag[i] = true;

                if (isEmptyArray(orderA)) repeatFlag[i] = false;

                continue;

              }

              for (let j = i + 1; j < timeArr.length; j += 1) {

                const orderB = timeArr[j];

                if (!isValidTimeArr(orderB)) {

                  repeatFlag[j] = true;

                  if (isEmptyArray(orderB)) repeatFlag[i] = false;

                  continue;

                }

                if (!(orderA[1] <= orderB[0]  orderA[0] >= orderB[1])) {

                  repeatFlag[i] = true;

                  repeatFlag[j] = true;

                }

              }

            }

            return repeatFlag;

          };

          // 是否是合法的时间组

          const isValidTimeArr = (timeArr: string[]) => {

            const startTime = timeArr[0];

            const endTime = timeArr[1];

            // eslint-disable-next-line eqeqeq

            if (startTime === ''  startTime == null  endTime === ''  endTime == null) { // 缺少开始时间或者结束时间,false

              return false;

            }

            if (startTime > endTime) { // 开始时间大于结束时间,false

              return false;

            }

            return true;

          }

          // 是否为空数组

          const isEmptyArray = (arr: string[]) => {

            if (arr.length > 0) {

              return false;

            }

            return true;

          };

        },

      },

    ],

  },

总结

综上,可以通过集成zOffice在线编辑和zOffice SDK两种方式简单快捷的实现资源预定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值