跳到主要内容

与服务器协同工作

Booking 组件通过两个主要操作与后端集成:从服务器加载卡片数据,以及将时间段预订信息回传至服务器。本指南涵盖这两个流程,以及在服务器数据使用不同时区时所需的 UTC 转换。

从服务器加载数据

使用原生 fetch API(或任何等效的 HTTP 客户端)获取卡片数据,并通过 setConfig() 方法将解析后的 JSON 传入组件。

以下代码片段初始化一个空的 Booking 实例,并在响应返回后加载数据集:

const widget = new booking.Booking("#booking", { data: [] });
const server = "https://some-backend-url";

fetch(server + "/data")
.then((res) => res.json())
.then((data) => {
widget.setConfig({ data });
});

将时间段预订信息保存至服务器

要在后端处理时间段预订,请使用 setConfirmHandler() 方法注册确认处理函数。

该处理函数接收一个包含三个字段的事件对象:

  • slot — 已预订的时间段:id(卡片 ID)和 time[timestamp, duration]
  • data — 以 formShape 字段 ID 为键的表单值(默认值:nameemaildescription
  • confirm — 服务器响应 callback:成功时调用 done(),失败时调用 error()

以下代码片段将预订信息发送至服务器,并根据响应结果处理预订状态:

// 处理时间段预订逻辑
const handleSlotReservation = (event) => {
const { confirm, slot, data } = event;

// 构建请求体
const info = {
item: slot.id,
start: slot.time[0],
data
};

// 将请求体发送至服务器
fetch("/server/url", {
method: "POST",
body: JSON.stringify(info),
// 根据响应结果确认或拒绝预订
}).then((response) => {
if (response.ok) confirm.done();
else confirm.error();
});
};

// 创建 Booking 实例
const widget = new booking.Booking("#root", {
data: [],
// 配置参数
});

// 从服务器获取数据集
fetch("/server/url")
.then((res) => res.json())
.then((items) => {
// 将获取的数据加载至组件
widget.setConfig({ data: items });
// 注册预订处理函数
widget.setConfirmHandler(handleSlotReservation);
});
信息

setConfirmHandler() 方法是一个快捷方式,其内部通过 widget.api.on("confirm-slot", handler) 订阅 confirm-slot 事件。两种方式注册的处理函数具有相同的 callback 结构——当需要添加多个订阅者时,可直接调用 widget.api.on("confirm-slot", handler)

将 UTC 数据转换为本地时区

组件以本地时区运行。如果服务器返回的是 UTC 时间戳,请在将数据传入组件前进行转换,并在发送预订信息前将其转回 UTC。

以下辅助函数处理两个方向的转换:

  • g2l — 将 UTC 时间戳转换为本地时区(应用于传入的 usedSlotsslots.dates
  • l2g — 将本地时间戳转回 UTC(在发送至服务器前应用于 slot.time[0]

以下代码片段将两个辅助函数整合到一个完整的加载与预订流程中:

const serverURL = "https://some-backend-url";

function g2l(v) {
const utcDate = new Date(v);
return new Date(
utcDate.getUTCFullYear(),
utcDate.getUTCMonth(),
utcDate.getUTCDate(),
utcDate.getUTCHours(),
utcDate.getUTCMinutes(),
utcDate.getUTCSeconds(),
utcDate.getUTCMilliseconds(),
).valueOf();
}

function l2g(v) {
const date = new Date(v);
return Date.UTC(
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds(),
);
}

const handleSlotReservation = event => {
const { confirm, slot, data } = event;

const info = {
doctor: slot.id,
date: l2g(slot.time[0]),
form: {
name: data.name,
email: data.email,
details: data.description,
},
};

fetch( serverURL + "/doctors/reservations", {
method: "POST",
body: JSON.stringify(info),
}).then(response => {
if (response.ok) confirm.done();
else confirm.error();
});
};

// 组件初始化
const widget = new booking.Booking("#root", {
data: [],
});

// 加载数据
fetch( serverURL + "/units")
.then(res => res.json())
.then(units => {
units.forEach(unit => {
if (unit.usedSlots) unit.usedSlots = unit.usedSlots.map(g2l);
if (unit.slots) {
unit.slots = unit.slots.map(slot => {
if (slot.dates) {
return {
...slot,
dates: slot.dates.map(g2l)
};
}
return slot;
});
};
});

widget.setConfig({ data: units });
widget.setConfirmHandler(handleSlotReservation);
});

示例

以下代码片段演示了完整的服务器端预订流程:

相关文章