feat: 抽离404数据处理 & 支持多时间点提醒
This commit is contained in:
parent
bcb9b42db2
commit
b4208be2b6
@ -19,8 +19,8 @@
|
||||
"litiany4.umijs-plugin-model",
|
||||
"oderwat.indent-rainbow",
|
||||
"jock.svg",
|
||||
"GitHub.copilot",
|
||||
// "aminer.codegeex",
|
||||
// "GitHub.copilot",
|
||||
"aminer.codegeex",
|
||||
"ChakrounAnas.turbo-console-log",
|
||||
"Gruntfuggly.todo-tree",
|
||||
"MS-CEINTL.vscode-language-pack-zh-hans"
|
||||
|
57
README.md
57
README.md
@ -23,8 +23,6 @@
|
||||
|
||||
[ ] 支持编辑更多设置,飞书网页就行
|
||||
|
||||
[ ] 支持同一提醒设置多个时间点
|
||||
|
||||
[ ] 支持快速提醒,输入数字,[1-120]分钟
|
||||
|
||||
[ ] 销毁创建用卡片,创建卡片添加取消按钮,点击去掉卡片可交互部分
|
||||
@ -41,6 +39,10 @@
|
||||
|
||||
[ ] 离职人员的提醒会发一条通知,然后提醒别人认领
|
||||
|
||||
[x] 支持同一提醒设置多个时间
|
||||
|
||||
[x] 每个时间,支持多时间点设置,类似每周一二三,每月1 3 10号
|
||||
|
||||
[x] 通过info指令,在对话里返回请求的数据
|
||||
|
||||
[x] 用药提醒的卡片模板,确认、取消、延迟
|
||||
@ -75,6 +77,10 @@ interface Remind {
|
||||
* 所有者信息,绑定用户表的id
|
||||
*/
|
||||
owner: string;
|
||||
/**
|
||||
* 消息Id
|
||||
*/
|
||||
messageId: string;
|
||||
/**
|
||||
* 接收者类型
|
||||
*/
|
||||
@ -151,6 +157,31 @@ interface Remind {
|
||||
*/
|
||||
delayedTemplateId: string;
|
||||
} | null;
|
||||
|
||||
/**
|
||||
* 提醒时间
|
||||
*/
|
||||
remindTimes: RemindTime[];
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
enabled: boolean;
|
||||
/**
|
||||
* 下次提醒的时间,格式为yyyy-MM-dd HH:mm
|
||||
*/
|
||||
nextRemindTime: string;
|
||||
/**
|
||||
* 下次提醒时间的中文,类似每天 07:00
|
||||
*/
|
||||
nextRemindTimeCHS: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提醒时间
|
||||
* 为了支持多个时间点提醒,将时间存成数组
|
||||
*/
|
||||
interface RemindTime {
|
||||
/**
|
||||
* 重复类型
|
||||
* single: 一次性
|
||||
@ -170,29 +201,21 @@ interface Remind {
|
||||
| "workday"
|
||||
| "holiday";
|
||||
/**
|
||||
* 提醒时间,格式为HH:mm
|
||||
* 提醒时间,格式为HH:mm, single类型时仅作展示用,类型为yyyy-MM-dd HH:mm
|
||||
*/
|
||||
time: string;
|
||||
/**
|
||||
* 星期几,当frequency为weekly时有效
|
||||
* 星期几[1-7],当frequency为weekly时有效
|
||||
*/
|
||||
dayOfWeek: number;
|
||||
daysOfWeek: number[];
|
||||
/**
|
||||
* 每月的几号,当frequency为monthly时有效
|
||||
* 每月的几号[1-31],当frequency为monthly时有效
|
||||
*/
|
||||
dayOfMonth: number;
|
||||
daysOfMonth: number[];
|
||||
/**
|
||||
* 每年的哪天提醒,当frequency为yearly时有效,格式为MM-dd
|
||||
* 每年的哪天提醒,当frequency为 yearly 时有效,格式为MM-dd
|
||||
*/
|
||||
dayOfYear: string;
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
enabled: boolean;
|
||||
/**
|
||||
* 下次提醒的时间,格式为yyyy-MM-dd HH:mm
|
||||
*/
|
||||
nextRemindTime: string;
|
||||
}
|
||||
```
|
||||
|
||||
@ -236,7 +259,7 @@ interface RemindRecord {
|
||||
/**
|
||||
* 用户回答的结果
|
||||
*/
|
||||
result: string;
|
||||
result: object;
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -1,3 +1,4 @@
|
||||
const { isSingleRemind } = require("../../utils");
|
||||
const { genSetRemindCard, genRemindCard } = require("../../utils/genCard");
|
||||
const { getNextRemindTime } = require("../../utils/nextRemindTime");
|
||||
const {
|
||||
@ -5,9 +6,8 @@ const {
|
||||
upsertRemindByMessageId,
|
||||
getRemindRecordByMessageId,
|
||||
getRemind,
|
||||
updateNextRemindTime,
|
||||
updateRemind,
|
||||
updateRemindRecord,
|
||||
closeRemind,
|
||||
} = require("../../utils/pb");
|
||||
const { updateCard } = require("../../utils/sendMsg");
|
||||
const { trans2LocalTime, getNowStr, getDelayedTimeStr } = require("../../utils/time");
|
||||
@ -63,10 +63,13 @@ const manageTimePicker = async (body) => {
|
||||
title: "🍳小煎蛋提醒!",
|
||||
content: `📝 ${content}`,
|
||||
},
|
||||
frequency: "single",
|
||||
time,
|
||||
remindTimes: [{
|
||||
frequency: "single",
|
||||
time,
|
||||
}],
|
||||
enabled: true,
|
||||
nextRemindTime: time,
|
||||
nextRemindTimeCHS: time,
|
||||
};
|
||||
// 数据库写入提醒,这里根据messageId更新或者创建是为了防止垃圾飞书不更新消息
|
||||
await upsertRemindByMessageId(remindInfo);
|
||||
@ -99,22 +102,24 @@ const manageBtnClick = async (body) => {
|
||||
await updateCard(body.open_message_id, card)
|
||||
// 更新remindRecord
|
||||
const newRecord = {
|
||||
...remindRecord,
|
||||
status: type,
|
||||
interactTime,
|
||||
result: JSON.stringify({ type, text, result }),
|
||||
result: { type, text, result },
|
||||
}
|
||||
await updateRemindRecord(remindRecord.id, newRecord)
|
||||
|
||||
// 如果是非延迟的单次提醒到此就结束了
|
||||
if (type !== 'delayed' && remind.frequency === 'single') {
|
||||
closeRemind(remind.id)
|
||||
if (type !== 'delayed' && isSingleRemind(remind.remindTimes)) {
|
||||
updateRemind(remind.id, { enabled: false })
|
||||
return
|
||||
}
|
||||
// 延迟提醒
|
||||
if (type === 'delayed') {
|
||||
updateRemind(remind.id, { nextRemindTime: getDelayedTimeStr(remind.delayTime) })
|
||||
return
|
||||
}
|
||||
|
||||
// 更新下一次的提醒时间
|
||||
const nextRemindTime = type === 'delayed' ? getDelayedTimeStr(remind.delayTime) : getNextRemindTime(remind)
|
||||
await updateNextRemindTime(remind.id, nextRemindTime)
|
||||
updateRemind(remind.id, getNextRemindTime(remind.remindTimes))
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
const { isSingleRemind } = require("../utils")
|
||||
const { genRemindCard } = require("../utils/genCard")
|
||||
const { getNextRemindTime } = require("../utils/nextRemindTime")
|
||||
const { getCurrRemind, updateNextRemindTime, getPendingRemindRecord, updateRemindRecord, createRemindRecord, closeRemind } = require("../utils/pb")
|
||||
const { getCurrTimeRemind, updateRemind, getPendingRemindRecord, updateRemindRecord, createRemindRecord } = require("../utils/pb")
|
||||
const { sendMsg, updateCard } = require("../utils/sendMsg")
|
||||
const { getNowStr, getDelayedTimeStr } = require("../utils/time")
|
||||
|
||||
@ -41,14 +42,17 @@ const manageRemind = async (remind) => {
|
||||
// 创建remindRecord
|
||||
await createRemindRecord(remind.id, messageId, cardType)
|
||||
// 如果是不需要回复的单次提醒到此就结束了
|
||||
if (remind.frequency === 'single' && !remind.needReply) {
|
||||
closeRemind(remind.id)
|
||||
if (isSingleRemind(remind.remindTimes) && !remind.needReply) {
|
||||
updateRemind(remind.id, { enabled: false })
|
||||
return
|
||||
}
|
||||
// 获取下一次提醒时间,不需要回复的直接时下一次提醒时间,需要回复的则是当前时间延后10min
|
||||
const nextRemindTime = remind.needReply ? getDelayedTimeStr(remind.delayTime) : getNextRemindTime(remind)
|
||||
// 更新下一次提醒时间
|
||||
await updateNextRemindTime(remind.id, nextRemindTime)
|
||||
// 需要回复的卡片下次提醒时间是delayTime(min)之后的时间
|
||||
if (remind.needReply) {
|
||||
updateRemind(remind.id, { nextRemindTime: getDelayedTimeStr(remind.delayTime) })
|
||||
return
|
||||
}
|
||||
// 不需要回复的循环提醒,更新下一次的提醒时间
|
||||
updateRemind(remind.id, getNextRemindTime(remind.remindTimes))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,11 +60,11 @@ const manageRemind = async (remind) => {
|
||||
* 发送提醒、更新上一个pending状态的卡片至delayed
|
||||
*/
|
||||
module.exports.sendCurrTimeReminds = async () => {
|
||||
const remindList = await getCurrRemind()
|
||||
const remindList = await getCurrTimeRemind()
|
||||
// 没有需要提醒的卡片
|
||||
if (!remindList.length) return
|
||||
if (!remindList?.length) return
|
||||
// 处理提醒
|
||||
for (const remind of remindList) {
|
||||
await manageRemind(remind)
|
||||
manageRemind(remind)
|
||||
}
|
||||
}
|
114
typings.d.ts
vendored
114
typings.d.ts
vendored
@ -113,6 +113,31 @@ interface Remind {
|
||||
*/
|
||||
delayedTemplateId: string;
|
||||
} | null;
|
||||
|
||||
/**
|
||||
* 提醒时间
|
||||
*/
|
||||
remindTimes: RemindTime[];
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
enabled: boolean;
|
||||
/**
|
||||
* 下次提醒的时间,格式为yyyy-MM-dd HH:mm
|
||||
*/
|
||||
nextRemindTime: string;
|
||||
/**
|
||||
* 下次提醒时间的中文
|
||||
*/
|
||||
nextRemindTimeCHS: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提醒时间
|
||||
* 为了支持多个时间点提醒,将时间存成数组
|
||||
*/
|
||||
interface RemindTime {
|
||||
/**
|
||||
* 重复类型
|
||||
* single: 一次性
|
||||
@ -138,24 +163,17 @@ interface Remind {
|
||||
/**
|
||||
* 星期几[1-7],当frequency为weekly时有效
|
||||
*/
|
||||
dayOfWeek: number;
|
||||
daysOfWeek: number[];
|
||||
/**
|
||||
* 每月的几号[1-31],当frequency为monthly时有效
|
||||
*/
|
||||
dayOfMonth: number;
|
||||
daysOfMonth: number[];
|
||||
/**
|
||||
* 每年的哪天提醒,当frequency为 yearly 时有效,格式为MM-dd
|
||||
*/
|
||||
dayOfYear: string;
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
enabled: boolean;
|
||||
/**
|
||||
* 下次提醒的时间,格式为yyyy-MM-dd HH:mm
|
||||
*/
|
||||
nextRemindTime: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提醒记录
|
||||
* 记录提醒时间,回答结果等
|
||||
@ -190,9 +208,9 @@ interface RemindRecord {
|
||||
*/
|
||||
interactTime: string;
|
||||
/**
|
||||
* 用户回答的结果
|
||||
* 用户回答的结果,类似每天 07:00
|
||||
*/
|
||||
result: string;
|
||||
result: object;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,32 +221,32 @@ interface Header {
|
||||
* 事件ID
|
||||
* @example 0f8ab23b60993cf8dd15c8cde4d7b0f5
|
||||
*/
|
||||
event_id: string;
|
||||
event_id: string;
|
||||
/**
|
||||
* token
|
||||
* @example tV9djUKSjzVnekV7xTg2Od06NFTcsBnj
|
||||
*/
|
||||
token: string;
|
||||
token: string;
|
||||
/**
|
||||
* 创建时间戳
|
||||
* @example 1693565712117
|
||||
*/
|
||||
create_time: string;
|
||||
create_time: string;
|
||||
/**
|
||||
* 事件类型
|
||||
* @example im.message.receive_v1
|
||||
*/
|
||||
event_type: string;
|
||||
event_type: string;
|
||||
/**
|
||||
* tenant_key
|
||||
* @example 2ee61fe50f4f1657
|
||||
*/
|
||||
tenant_key: string;
|
||||
tenant_key: string;
|
||||
/**
|
||||
* app_id
|
||||
* @example cli_a1eff35b43b89063
|
||||
*/
|
||||
app_id: string;
|
||||
app_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,17 +257,17 @@ interface UserIdInfo {
|
||||
* 用户标记
|
||||
* @example ou_032f507d08f9a7f28b042fcd086daef5
|
||||
*/
|
||||
open_id: string;
|
||||
open_id: string;
|
||||
/**
|
||||
* 用户标记
|
||||
* @example on_7111660fddd8302ce47bf1999147c011
|
||||
*/
|
||||
union_id: string;
|
||||
union_id: string;
|
||||
/**
|
||||
* 用户名
|
||||
* @example zhaoyingbo
|
||||
*/
|
||||
user_id: string;
|
||||
user_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,22 +277,22 @@ interface Mention {
|
||||
/**
|
||||
* 被艾特的人的ID信息
|
||||
*/
|
||||
id: UserIdInfo;
|
||||
id: UserIdInfo;
|
||||
/**
|
||||
* 对应到文本内的内容
|
||||
* @example "@_user_1"
|
||||
*/
|
||||
key: string;
|
||||
key: string;
|
||||
/**
|
||||
* 用户名
|
||||
* @example 小煎蛋
|
||||
*/
|
||||
name: string;
|
||||
name: string;
|
||||
/**
|
||||
* 应用ID
|
||||
* @example 2ee61fe50f4f1657
|
||||
*/
|
||||
tenant_key: string;
|
||||
tenant_key: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -285,36 +303,36 @@ interface Message {
|
||||
* 对话流ID
|
||||
* @example oc_433b1cb7a9dbb7ebe70a4e1a59cb8bb1
|
||||
*/
|
||||
chat_id: string;
|
||||
chat_id: string;
|
||||
/**
|
||||
* 消息类型
|
||||
* @example group | p2p
|
||||
*/
|
||||
chat_type: string;
|
||||
chat_type: string;
|
||||
/**
|
||||
* JSON字符串文本内容
|
||||
* @example "{\"text\":\"@_user_1 测试\"}"
|
||||
*/
|
||||
content: string;
|
||||
content: string;
|
||||
/**
|
||||
* 消息发送时间戳
|
||||
* @example 1693565711996
|
||||
*/
|
||||
create_time: string;
|
||||
create_time: string;
|
||||
/**
|
||||
* 被艾特的人信息
|
||||
*/
|
||||
mentions? : Mention[];
|
||||
mentions?: Mention[];
|
||||
/**
|
||||
* 当前消息的ID
|
||||
* @example om_038fc0eceed6224a1abc1cdaa4266405
|
||||
*/
|
||||
message_id: string;
|
||||
message_id: string;
|
||||
/**
|
||||
* 消息类型
|
||||
* @example text、post、image、file、audio、media、sticker、interactive、share_chat、share_user
|
||||
*/
|
||||
message_type: string;
|
||||
message_type: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -324,25 +342,25 @@ interface Sender {
|
||||
/**
|
||||
* id 相关信息
|
||||
*/
|
||||
sender_id: UserIdInfo;
|
||||
sender_id: UserIdInfo;
|
||||
/**
|
||||
* 发送者类型
|
||||
* @example user
|
||||
*/
|
||||
sender_type: string;
|
||||
sender_type: string;
|
||||
/**
|
||||
* 应用ID
|
||||
* @example 2ee61fe50f4f1657
|
||||
*/
|
||||
tenant_key: string;
|
||||
tenant_key: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件详情
|
||||
*/
|
||||
interface Event {
|
||||
message: Message;
|
||||
sender: Sender;
|
||||
message: Message;
|
||||
sender: Sender;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -353,15 +371,15 @@ interface LarkMessageEvent {
|
||||
* 协议版本
|
||||
* @example 2.0
|
||||
*/
|
||||
schema: string;
|
||||
schema: string;
|
||||
/**
|
||||
* 事件头
|
||||
*/
|
||||
header: Header;
|
||||
header: Header;
|
||||
/**
|
||||
* 事件详情
|
||||
*/
|
||||
event: Event;
|
||||
event: Event;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -371,36 +389,36 @@ interface LarkUserAction {
|
||||
/**
|
||||
* open_id
|
||||
*/
|
||||
open_id: string;
|
||||
open_id: string;
|
||||
/**
|
||||
* 用户名
|
||||
* @example zhaoyingbo
|
||||
*/
|
||||
user_id: string;
|
||||
user_id: string;
|
||||
/**
|
||||
* 当前消息的ID
|
||||
* @example om_038fc0eceed6224a1abc1cdaa4266405
|
||||
*/
|
||||
open_message_id: string;
|
||||
open_message_id: string;
|
||||
/**
|
||||
* 对话流ID
|
||||
* @example oc_433b1cb7a9dbb7ebe70a4e1a59cb8bb1
|
||||
*/
|
||||
open_chat_id: string;
|
||||
open_chat_id: string;
|
||||
/**
|
||||
* 应用ID
|
||||
* @example 2ee61fe50f4f1657
|
||||
*/
|
||||
tenant_key: string;
|
||||
tenant_key: string;
|
||||
/**
|
||||
* token
|
||||
* @example tV9djUKSjzVnekV7xTg2Od06NFTcsBnj
|
||||
*/
|
||||
token: string;
|
||||
token: string;
|
||||
/**
|
||||
* 事件结果
|
||||
*/
|
||||
action: {
|
||||
action: {
|
||||
/**
|
||||
* 传的参数
|
||||
*/
|
||||
@ -420,4 +438,4 @@ interface LarkUserAction {
|
||||
*/
|
||||
timezone: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,43 +1,3 @@
|
||||
/**
|
||||
* 生成提醒时间文本
|
||||
*/
|
||||
const genRemindTimeText = (
|
||||
frequency,
|
||||
time,
|
||||
dayOfWeek,
|
||||
dayOfMonth,
|
||||
dayOfYear
|
||||
) => {
|
||||
const weekCN = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
|
||||
let remindTimeText = "";
|
||||
switch (frequency) {
|
||||
case "single":
|
||||
remindTimeText = `${dayOfYear} ${time}`;
|
||||
break;
|
||||
case "daily":
|
||||
remindTimeText = `每天 ${time}`;
|
||||
break;
|
||||
case "weekly":
|
||||
remindTimeText = `每${weekCN[dayOfWeek - 1]} ${time}`;
|
||||
break;
|
||||
case "monthly":
|
||||
remindTimeText = `每月${dayOfMonth}日 ${time}`;
|
||||
break;
|
||||
case "yearly":
|
||||
remindTimeText = `每年${dayOfYear} ${time}`;
|
||||
break;
|
||||
case "workday":
|
||||
remindTimeText = `工作日 ${time}`;
|
||||
break;
|
||||
case "holiday":
|
||||
remindTimeText = `节假日 ${time}`;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return remindTimeText;
|
||||
};
|
||||
|
||||
/**
|
||||
* 生成交互结果
|
||||
*/
|
||||
@ -119,7 +79,7 @@ const genRemindInfo = (
|
||||
needReply,
|
||||
cardType,
|
||||
owner,
|
||||
remindTime,
|
||||
nextRemindTimeCHS,
|
||||
interactTime,
|
||||
result
|
||||
) => {
|
||||
@ -140,7 +100,7 @@ const genRemindInfo = (
|
||||
});
|
||||
// 如果是非交互卡片,展示创建人、提醒时间
|
||||
columns.push(genColumn(`**创建人**\n${owner}`));
|
||||
columns.push(genColumn(`**提醒时间**\n${remindTime}`));
|
||||
columns.push(genColumn(`**提醒时间**\n${nextRemindTimeCHS}`));
|
||||
// 如果是交互卡片,还需要展示交互结果、交互时间
|
||||
if (needReply) {
|
||||
columns.push(genColumn(`**交互结果**\n${result}`));
|
||||
@ -156,10 +116,10 @@ const genRemindInfo = (
|
||||
|
||||
/**
|
||||
* 根据提醒信息生成卡片
|
||||
* @param {*} remindInfo 提醒信息
|
||||
* @param {*} cardType 卡片类型
|
||||
* @param {*} interactInfo 交互信息
|
||||
* @param {*} interactTime 交互时间,在上层已经转成 yyyy-MM-dd HH:mm 格式了
|
||||
* @param {Remind} remindInfo 提醒信息
|
||||
* @param {string} cardType 卡片类型
|
||||
* @param {object} interactInfo 交互信息
|
||||
* @param {string} interactTime 交互时间,在上层已经转成 yyyy-MM-dd HH:mm 格式了
|
||||
*/
|
||||
module.exports.genRemindCard = (
|
||||
remindInfo,
|
||||
@ -172,22 +132,13 @@ module.exports.genRemindCard = (
|
||||
cardInfo,
|
||||
templateInfo,
|
||||
needReply,
|
||||
frequency,
|
||||
time,
|
||||
dayOfWeek,
|
||||
dayOfMonth,
|
||||
dayOfYear,
|
||||
nextRemindTimeCHS,
|
||||
expand: {
|
||||
owner: {
|
||||
userId: owner,
|
||||
}
|
||||
},
|
||||
} = remindInfo;
|
||||
// TODO: Onwer信息获取,先暂定自己
|
||||
const owner = "zhaoyingbo";
|
||||
// 生成提醒时间文本
|
||||
const remindTime = genRemindTimeText(
|
||||
frequency,
|
||||
time,
|
||||
dayOfWeek,
|
||||
dayOfMonth,
|
||||
dayOfYear
|
||||
);
|
||||
// 生成交互结果
|
||||
const result = genResult(interactInfo, cardInfo, cardType);
|
||||
// 优先返回模板信息
|
||||
@ -196,11 +147,11 @@ module.exports.genRemindCard = (
|
||||
cardType === "pending"
|
||||
? {
|
||||
owner,
|
||||
remindTime,
|
||||
remindTime: nextRemindTimeCHS,
|
||||
}
|
||||
: {
|
||||
owner,
|
||||
remindTime,
|
||||
remindTime: nextRemindTimeCHS,
|
||||
result,
|
||||
interactTime,
|
||||
};
|
||||
@ -261,7 +212,7 @@ module.exports.genRemindCard = (
|
||||
needReply,
|
||||
cardType,
|
||||
owner,
|
||||
remindTime,
|
||||
nextRemindTimeCHS,
|
||||
interactTime,
|
||||
result
|
||||
);
|
||||
|
11
utils/index.js
Normal file
11
utils/index.js
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
*
|
||||
* @param {RemindTime[]} remindTimes
|
||||
*/
|
||||
const isSingleRemind = (remindTimes) => {
|
||||
return remindTimes.every(remindTime => remindTime.frequency === 'single')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isSingleRemind,
|
||||
}
|
@ -33,14 +33,11 @@ const judgeIsWorkDay = (time) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下次提醒时间
|
||||
* @param {Remind} remind 提醒信息
|
||||
* @returns {string} 下次提醒时间, 格式为yyyy-MM-dd HH:mm
|
||||
* 获取指定配置下一次的提醒时间以及对应中文显示
|
||||
* @param {RemindTime} remindTime 提醒时间配置
|
||||
*/
|
||||
module.exports.getNextRemindTime = (remind) => {
|
||||
const { frequency, time, dayOfWeek, dayOfMonth, dayOfYear } = remind;
|
||||
// 单次提醒没有下次,正常会取delayTime
|
||||
if (remind.frequency === 'single') return remind.nextRemindTime
|
||||
const genNextRemindTimeWithCHS = (remindTime) => {
|
||||
const { frequency, time, daysOfWeek, daysOfMonth, dayOfYear } = remindTime;
|
||||
// 拆分时间
|
||||
const [hour, minute] = time.split(':');
|
||||
// 当前时间
|
||||
@ -49,34 +46,63 @@ module.exports.getNextRemindTime = (remind) => {
|
||||
if (frequency === 'daily') {
|
||||
const remindMoment = moment().hour(hour).minute(minute);
|
||||
// 判断当前时间是否已经过了今天的提醒时间
|
||||
if (!remindMoment.isAfter(nowMoment)) {
|
||||
if (remindMoment.isBefore(nowMoment)) {
|
||||
// 如果已经过了,那么下次提醒时间为明天的提醒时间
|
||||
remindMoment.add(1, 'day');
|
||||
}
|
||||
return remindMoment.format('YYYY-MM-DD HH:mm');
|
||||
return {
|
||||
nextRemindTime: remindMoment.format('YYYY-MM-DD HH:mm'),
|
||||
nextRemindTimeCHS: `每天 ${time}`,
|
||||
};
|
||||
}
|
||||
// 每周循环
|
||||
if (frequency === 'weekly') {
|
||||
const remindMoment = moment().hour(hour).minute(minute).isoWeekday(dayOfWeek);
|
||||
// 判断当前时间是否已经过了本周的提醒时间
|
||||
if (!remindMoment.isAfter(nowMoment)) {
|
||||
// 如果已经过了,那么下次提醒时间为下周的提醒时间
|
||||
remindMoment.add(1, 'week');
|
||||
}
|
||||
return remindMoment.format('YYYY-MM-DD HH:mm');
|
||||
// 也是取离当前时间点最近的某一天
|
||||
return daysOfWeek.reduce(({ nextRemindTime, nextRemindTimeCHS }, dayOfWeek) => {
|
||||
const remindMoment = moment().hour(hour).minute(minute).isoWeekday(dayOfWeek);
|
||||
// 判断当前时间是否已经过了本周的提醒时间
|
||||
if (remindMoment.isBefore(nowMoment)) {
|
||||
// 如果已经过了,那么下次提醒时间为下周的提醒时间
|
||||
remindMoment.add(1, 'week');
|
||||
}
|
||||
// 取最近的时间
|
||||
if (remindMoment.isBefore(moment(nextRemindTime))) {
|
||||
return {
|
||||
nextRemindTime: remindMoment.format('YYYY-MM-DD HH:mm'),
|
||||
nextRemindTimeCHS: `每${["周一", "周二", "周三", "周四", "周五", "周六", "周日"][dayOfWeek - 1]} ${time}`
|
||||
}
|
||||
}
|
||||
return {
|
||||
nextRemindTime,
|
||||
nextRemindTimeCHS,
|
||||
}
|
||||
}, { nextRemindTime: '2099-12-31 23:59', nextRemindTimeCHS: '' })
|
||||
}
|
||||
// 每月循环
|
||||
if (frequency === 'monthly') {
|
||||
// 获取最近应该提醒的日期,如果一个月没有31天,那么就是最后一天
|
||||
const dayOfMonthNum = moment().daysInMonth();
|
||||
const remindMoment = moment().hour(hour).minute(minute).date(dayOfMonthNum < dayOfMonth ? dayOfMonthNum : dayOfMonth);
|
||||
// 判断当前时间是否已经过了本月的提醒时间
|
||||
if (!remindMoment.isAfter(nowMoment)) {
|
||||
// 如果已经过了,那么下次提醒时间为下月的提醒时间,需要重新判断一下是否有31号
|
||||
const nextDayOfMonthNum = moment().add(1, 'month').daysInMonth();
|
||||
remindMoment.add(1, 'month').date(nextDayOfMonthNum < dayOfMonth ? nextDayOfMonthNum : dayOfMonth);
|
||||
}
|
||||
return remindMoment.format('YYYY-MM-DD HH:mm');
|
||||
// 也是取里当前时间点最近的某一天
|
||||
return daysOfMonth.reduce(({ nextRemindTime, nextRemindTimeCHS }, dayOfMonth) => {
|
||||
// 获取最近应该提醒的日期,如果一个月没有31天,那么就是最后一天
|
||||
const dayOfMonthNum = moment().daysInMonth();
|
||||
const remindMoment = moment().hour(hour).minute(minute).date(dayOfMonthNum < dayOfMonth ? dayOfMonthNum : dayOfMonth);
|
||||
// 判断当前时间是否已经过了本月的提醒时间
|
||||
if (remindMoment.isBefore(nowMoment)) {
|
||||
// 如果已经过了,那么下次提醒时间为下月的提醒时间,需要重新判断一下是否有31号
|
||||
const nextDayOfMonthNum = moment().add(1, 'month').daysInMonth();
|
||||
remindMoment.add(1, 'month').date(nextDayOfMonthNum < dayOfMonth ? nextDayOfMonthNum : dayOfMonth);
|
||||
}
|
||||
// 取最近的时间
|
||||
if (remindMoment.isBefore(moment(nextRemindTime))) {
|
||||
return {
|
||||
nextRemindTime: remindMoment.format('YYYY-MM-DD HH:mm'),
|
||||
nextRemindTimeCHS: `每月${dayOfMonth}日 ${time}`
|
||||
}
|
||||
}
|
||||
return {
|
||||
nextRemindTime,
|
||||
nextRemindTimeCHS,
|
||||
}
|
||||
}, { nextRemindTime: '2099-12-31 23:59', nextRemindTimeCHS: '' })
|
||||
}
|
||||
// 每年循环
|
||||
if (frequency === 'yearly') {
|
||||
@ -88,12 +114,15 @@ module.exports.getNextRemindTime = (remind) => {
|
||||
const dayOfMonthNum = moment().month(month).daysInMonth();
|
||||
const remindMoment = moment().hour(hour).minute(minute).month(month).date(dayOfMonthNum < dayOfMonth ? dayOfMonthNum : dayOfMonth);
|
||||
// 判断当前时间是否已经过了今年的提醒时间
|
||||
if (!remindMoment.isAfter(nowMoment)) {
|
||||
if (remindMoment.isBefore(nowMoment)) {
|
||||
// 如果已经过了,那么下次提醒时间为明年的提醒时间,需要重新判断一下是否有29号
|
||||
const nextDayOfMonthNum = moment().add(1, 'year').month(month).daysInMonth();
|
||||
remindMoment.add(1, 'year').date(nextDayOfMonthNum < dayOfMonth ? nextDayOfMonthNum : dayOfMonth);
|
||||
}
|
||||
return remindMoment.format('YYYY-MM-DD HH:mm');
|
||||
return {
|
||||
nextRemindTime: remindMoment.format('YYYY-MM-DD HH:mm'),
|
||||
nextRemindTimeCHS: `每年${dayOfYear} ${time}`
|
||||
};
|
||||
}
|
||||
// 工作日循环
|
||||
if (frequency === 'workday') {
|
||||
@ -101,13 +130,16 @@ module.exports.getNextRemindTime = (remind) => {
|
||||
// 今天是否是工作日
|
||||
const isWorkday = judgeIsWorkDay();
|
||||
// 如果今天非工作日或者如果是工作日,且当前时间过了提醒时间,那么下次提醒时间为下次工作日的提醒时间
|
||||
if (!isWorkday || (isWorkday && !remindMoment.isAfter(nowMoment))) {
|
||||
if (!isWorkday || (isWorkday && remindMoment.isBefore(nowMoment))) {
|
||||
remindMoment.add(1, 'day');
|
||||
while (!judgeIsWorkDay(remindMoment)) {
|
||||
remindMoment.add(1, 'day');
|
||||
}
|
||||
}
|
||||
return remindMoment.format('YYYY-MM-DD HH:mm');
|
||||
return {
|
||||
nextRemindTime: remindMoment.format('YYYY-MM-DD HH:mm'),
|
||||
nextRemindTimeCHS: `工作日 ${time}`
|
||||
};
|
||||
}
|
||||
// 非工作日循环
|
||||
if (frequency === 'holiday') {
|
||||
@ -115,12 +147,42 @@ module.exports.getNextRemindTime = (remind) => {
|
||||
// 今天是否是工作日
|
||||
const isWorkday = judgeIsWorkDay();
|
||||
// 如果今天是工作日或者如果是非工作日,且当前时间过了提醒时间,那么下次提醒时间为下次非工作日的提醒时间
|
||||
if (isWorkday || (!isWorkday && !remindMoment.isAfter(nowMoment))) {
|
||||
if (isWorkday || (!isWorkday && remindMoment.isBefore(nowMoment))) {
|
||||
remindMoment.add(1, 'day');
|
||||
while (judgeIsWorkDay(remindMoment)) {
|
||||
remindMoment.add(1, 'day');
|
||||
}
|
||||
}
|
||||
return remindMoment.format('YYYY-MM-DD HH:mm');
|
||||
return {
|
||||
nextRemindTime: remindMoment.format('YYYY-MM-DD HH:mm'),
|
||||
nextRemindTimeCHS: `节假日 ${time}`
|
||||
};
|
||||
}
|
||||
}
|
||||
// 单次提醒
|
||||
// 此时的time是完整的时间,直接返回即可
|
||||
return {
|
||||
nextRemindTime: time,
|
||||
nextRemindTimeCHS: time,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下次提醒时间,在传入的所有时间配置中获取最早的一个
|
||||
* @param {RemindTime[]} remindTimes 提醒信息
|
||||
* @returns {{ nextRemindTime: string, nextRemindTimeCHS: string }} 下次提醒时间, 格式为yyyy-MM-dd HH:mm 以及对应中文显示
|
||||
*/
|
||||
module.exports.getNextRemindTime = (remindTimes) => {
|
||||
return remindTimes.reduce(({ nextRemindTime, nextRemindTimeCHS }, remindTime) => {
|
||||
const { nextRemindTime: nextTime, nextRemindTimeCHS: nextTimeCHS } = genNextRemindTimeWithCHS(remindTime)
|
||||
if (moment(nextTime).isBefore(moment(nextRemindTime))) {
|
||||
return {
|
||||
nextRemindTime: nextTime,
|
||||
nextRemindTimeCHS: nextTimeCHS,
|
||||
}
|
||||
}
|
||||
return {
|
||||
nextRemindTime,
|
||||
nextRemindTimeCHS,
|
||||
}
|
||||
}, { nextRemindTime: '2099-12-31 23:59', nextRemindTimeCHS: '' });
|
||||
}
|
||||
|
256
utils/pb.js
256
utils/pb.js
@ -4,38 +4,11 @@ require('cross-fetch/polyfill')
|
||||
|
||||
const pb = new PocketBase('https://eggpb.imoaix.cn')
|
||||
|
||||
/**
|
||||
* 更新租户的token
|
||||
* @param {string} value 新的token
|
||||
*/
|
||||
module.exports.updateTenantAccessToken = async (value) => {
|
||||
await pb.collection('config').update('ugel8f0cpk0rut6', { value })
|
||||
console.log('reset access token success', value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取租户的token
|
||||
* @returns {string} 租户的token
|
||||
*/
|
||||
module.exports.getTenantAccessToken = async () => {
|
||||
const { value } = await pb.collection('config').getOne('ugel8f0cpk0rut6')
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新提醒
|
||||
*/
|
||||
module.exports.createRemind = async (remind) => {
|
||||
await pb.collection('remind').create(remind)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提醒信息
|
||||
*/
|
||||
module.exports.getRemind = async (id) => {
|
||||
const manage404 = async (dbFunc) => {
|
||||
try {
|
||||
return await pb.collection('remind').getOne(id)
|
||||
return await dbFunc()
|
||||
} catch (err) {
|
||||
console.log('errdfsfsfsfsdf', err)
|
||||
// 没有这个提醒就返回空
|
||||
if (err.message === "The requested resource wasn't found.") {
|
||||
return null
|
||||
@ -44,120 +17,118 @@ module.exports.getRemind = async (id) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据messageId更新或者创建提醒
|
||||
* @param {Remind} remind
|
||||
* 更新租户的token
|
||||
* @param {string} value 新的token
|
||||
*/
|
||||
module.exports.upsertRemindByMessageId = async (remind) => {
|
||||
try {
|
||||
const record = await pb.collection('remind').getFirstListItem(
|
||||
`messageId = "${remind.messageId}" && enabled = true`
|
||||
)
|
||||
await pb.collection('remind').update(record.id, remind)
|
||||
} catch (err) {
|
||||
// 没有这个提醒就创建
|
||||
if (err.message === "The requested resource wasn't found.") {
|
||||
await pb.collection('remind').create(remind)
|
||||
} else throw err;
|
||||
}
|
||||
const updateTenantAccessToken = async (value) => {
|
||||
await pb.collection('config').update('ugel8f0cpk0rut6', { value })
|
||||
console.log('reset access token success', value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取租户的token
|
||||
* @returns {string} 租户的token
|
||||
*/
|
||||
const getTenantAccessToken = async () => {
|
||||
const { value } = await pb.collection('config').getOne('ugel8f0cpk0rut6')
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新提醒
|
||||
* @param {Remind} remind 提醒内容
|
||||
*/
|
||||
const createRemind = async (remind) => {
|
||||
return await pb.collection('remind').create(remind)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新提醒
|
||||
* @param {string} remindId 提醒ID
|
||||
* @param {Remind} remind 提醒内容
|
||||
*/
|
||||
const updateRemind = async (remindId, remind) => {
|
||||
return await pb.collection('remind').update(remindId, remind)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提醒信息
|
||||
* @param {string} id 提醒ID
|
||||
* @returns {Remind | null}
|
||||
*/
|
||||
const getRemind = async (remindId) => manage404(async () =>
|
||||
await pb.collection('remind').getOne(remindId, { expand: 'owner' })
|
||||
)
|
||||
|
||||
/**
|
||||
* 获取对应messageId对应的提醒
|
||||
* @param {string} messageId 消息ID
|
||||
* @returns {Remind | null}
|
||||
*/
|
||||
const getRemindByMessageId = async (messageId) => manage404(async () =>
|
||||
await pb.collection('remind').getFirstListItem(
|
||||
`messageId = "${messageId}" && enabled = true`
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* 根据messageId更新或者创建提醒
|
||||
* @param {Remind} remind 提醒内容
|
||||
*/
|
||||
const upsertRemindByMessageId = async (remind) => {
|
||||
const record = await getRemindByMessageId(remind.messageId)
|
||||
if (record) updateRemind(record.id, remind)
|
||||
else createRemind(remind)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前分钟应该提醒的所有提醒
|
||||
*/
|
||||
module.exports.getCurrRemind = async () => {
|
||||
const nowStr = getNowStr()
|
||||
// TODO: 应该不会同时出现同一时间100个需要提醒的情况?等通知系统完善这里加个分页提醒吧
|
||||
const { items } = await pb.collection('remind').getList(1, 100, {
|
||||
filter: `nextRemindTime = "${nowStr}" && enabled = true`,
|
||||
const getCurrTimeRemind = async () => manage404(async () => {
|
||||
const { items } = await pb.collection('remind').getList(1, 1000, {
|
||||
filter: `nextRemindTime = "${getNowStr()}" && enabled = true`,
|
||||
expand: 'owner'
|
||||
})
|
||||
return items
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对应messageId对应的提醒
|
||||
*/
|
||||
module.exports.getRemindByMessageId = async (messageId) => {
|
||||
try {
|
||||
const record = await pb.collection('remind').getFirstListItem(
|
||||
`messageId = "${messageId}" && enabled = true`
|
||||
)
|
||||
return record
|
||||
} catch (err) {
|
||||
// 没有这个提醒不返回
|
||||
if (err.message === "The requested resource wasn't found.") {
|
||||
return null
|
||||
} else throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新指定Remind的下次提醒时间
|
||||
* @param {string} remindId 提醒信息Id
|
||||
* @param {string} nextRemindTime 下次提醒时间
|
||||
*/
|
||||
module.exports.updateNextRemindTime = async (remindId, nextRemindTime) => {
|
||||
await pb.collection('remind').update(remindId, { nextRemindTime })
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭指定的Remind
|
||||
* @param {string} remindId 提醒信息Id
|
||||
*/
|
||||
module.exports.closeRemind = async (remindId) => {
|
||||
await pb.collection('remind').update(remindId, { enabled: false })
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取指定remind的pending状态的remindRecord
|
||||
* @param {string} remindId remind的id
|
||||
* @returns {RemindRecord | null} remindRecord
|
||||
*/
|
||||
module.exports.getPendingRemindRecord = async (remindId) => {
|
||||
try {
|
||||
const record = await pb.collection('remindRecord').getFirstListItem(
|
||||
`remindId = "${remindId}" && status = "pending"`
|
||||
)
|
||||
return record
|
||||
} catch (err) {
|
||||
// 没有这个record不返回
|
||||
if (err.message === "The requested resource wasn't found.") {
|
||||
return null
|
||||
} else throw err;
|
||||
}
|
||||
}
|
||||
const getPendingRemindRecord = async (remindId) => manage404(async () =>
|
||||
await pb.collection('remindRecord').getFirstListItem(
|
||||
`remindId = "${remindId}" && status = "pending"`
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* 获取指定messageId状态的remindRecord
|
||||
* @param {string} remindId remind的id
|
||||
* @returns {RemindRecord | null} remindRecord
|
||||
*/
|
||||
module.exports.getRemindRecordByMessageId = async (messageId) => {
|
||||
try {
|
||||
const record = await pb.collection('remindRecord').getFirstListItem(
|
||||
`messageId = "${messageId}"`
|
||||
)
|
||||
return record
|
||||
} catch (err) {
|
||||
// 没有这个record不返回
|
||||
if (err.message === "The requested resource wasn't found.") {
|
||||
return null
|
||||
} else throw err;
|
||||
}
|
||||
}
|
||||
const getRemindRecordByMessageId = async (messageId) => manage404(async () =>
|
||||
await pb.collection('remindRecord').getFirstListItem(
|
||||
`messageId = "${messageId}"`
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* 创建remindRecord
|
||||
* @param {string} remindId 提醒ID
|
||||
* @param {string} messageId 消息ID
|
||||
* @param {string} status 交互状态
|
||||
*/
|
||||
module.exports.createRemindRecord = async (remindId, messageId, status) => {
|
||||
const createRemindRecord = async (remindId, messageId, status) => {
|
||||
const remindRecord = {
|
||||
remindId,
|
||||
messageId,
|
||||
status: status,
|
||||
remindTime: getNowStr(),
|
||||
interactTime: status === 'pending' ? '' : getNowStr(),
|
||||
result: '',
|
||||
}
|
||||
await pb.collection('remindRecord').create(remindRecord)
|
||||
return await pb.collection('remindRecord').create(remindRecord)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,8 +136,8 @@ module.exports.createRemindRecord = async (remindId, messageId, status) => {
|
||||
* @param {string} id remindRecord的id
|
||||
* @param {RemindRecord} record remindRecord的信息
|
||||
*/
|
||||
module.exports.updateRemindRecord = async (id, record) => {
|
||||
await pb.collection('remindRecord').update(id, record)
|
||||
const updateRemindRecord = async (id, record) => {
|
||||
return await pb.collection('remindRecord').update(id, record)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,9 +145,9 @@ module.exports.updateRemindRecord = async (id, record) => {
|
||||
* @param {string} userId 用户id
|
||||
* @returns {User} 用户信息
|
||||
*/
|
||||
const getUser = async (userId) => {
|
||||
return await pb.collection("user").getFirstListItem(`userId="${userId}"`)
|
||||
}
|
||||
const getUser = async (userId) => manage404(async () =>
|
||||
await pb.collection("user").getFirstListItem(`userId="${userId}"`)
|
||||
)
|
||||
|
||||
/**
|
||||
* 创建用户
|
||||
@ -191,7 +162,7 @@ const createUser = async (userId, openId) => {
|
||||
/**
|
||||
* 更新用户信息
|
||||
* @param {string} id 用户id
|
||||
* @param {*} data 用户信息
|
||||
* @param {User} data 用户信息
|
||||
* @returns {User} 用户信息
|
||||
*/
|
||||
const updateUser = async (id, data) => {
|
||||
@ -200,25 +171,34 @@ const updateUser = async (id, data) => {
|
||||
|
||||
/**
|
||||
* 更新用户信息,如果用户不存在则创建
|
||||
* @param {User} userInfo
|
||||
* @param {User} userInfo 用户信息
|
||||
* @returns {User} 用户信息
|
||||
*/
|
||||
module.exports.upsertUser = async (userInfo) => {
|
||||
try {
|
||||
const user = await getUser(userInfo.user_id);
|
||||
// 如果用户信息没变化,直接返回
|
||||
if (user.openId === userInfo.open_id) {
|
||||
return user;
|
||||
}
|
||||
// 如果用户信息有变化,更新
|
||||
return await updateUser(user.id, {
|
||||
openId: userInfo.open_id,
|
||||
});
|
||||
} catch (err) {
|
||||
// 没有这个用户上传个新的
|
||||
if (err.message === "The requested resource wasn't found.") {
|
||||
const user = await createUser(userInfo.user_id, userInfo.open_id);
|
||||
return user;
|
||||
} else throw err;
|
||||
const upsertUser = async (userInfo) => {
|
||||
const user = await getUser(userInfo.user_id);
|
||||
if (!user) return await createUser(userInfo.user_id, userInfo.open_id);
|
||||
// 如果用户信息没变化,直接返回
|
||||
if (user.openId === userInfo.open_id) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
// 如果用户信息有变化,更新
|
||||
return await updateUser(user.id, {
|
||||
openId: userInfo.open_id,
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
updateTenantAccessToken,
|
||||
getTenantAccessToken,
|
||||
createRemind,
|
||||
updateRemind,
|
||||
getRemind,
|
||||
getRemindByMessageId,
|
||||
upsertRemindByMessageId,
|
||||
getCurrTimeRemind,
|
||||
getPendingRemindRecord,
|
||||
getRemindRecordByMessageId,
|
||||
createRemindRecord,
|
||||
updateRemindRecord,
|
||||
upsertUser,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user