初始提交:OCI 面板前端(含 GenAI 网关一期)

This commit is contained in:
Wang Defa
2026-07-09 15:31:29 +08:00
commit db45a669e3
135 changed files with 25220 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
/** 5 段 cron 单字段匹配:支持 *、n、*\/k、a-b、逗号组合;超出子集返回 false */
function fieldMatch(field: string, v: number): boolean {
return field.split(',').some((seg) => {
const step = /^\*\/(\d+)$/.exec(seg)
if (step) return Number(step[1]) > 0 && v % Number(step[1]) === 0
const range = /^(\d+)-(\d+)$/.exec(seg)
if (range) return v >= Number(range[1]) && v <= Number(range[2])
return seg === '*' || seg === String(v)
})
}
/** 计算 5 段 cron 的下次执行时间(本地时区):
* 从下一分钟起逐分钟扫描 8 天,表达式非法或窗口内无匹配返回 null。
* 日与周同时受限时按 AND 近似(面板生成的表达式不会同时限制)。 */
export function nextCronRun(expr: string): Date | null {
const p = expr.trim().split(/\s+/)
if (p.length !== 5) return null
const t = new Date()
t.setSeconds(0, 0)
for (let i = 0; i < 8 * 24 * 60; i++) {
t.setMinutes(t.getMinutes() + 1)
if (
fieldMatch(p[0], t.getMinutes()) &&
fieldMatch(p[1], t.getHours()) &&
fieldMatch(p[2], t.getDate()) &&
fieldMatch(p[3], t.getMonth() + 1) &&
fieldMatch(p[4], t.getDay())
)
return new Date(t)
}
return null
}
const pad2 = (n: number) => String(n).padStart(2, '0')
/** 下次执行的短文案(MM-DD HH:mm);无法计算返回空串 */
export function nextCronRunLabel(expr: string): string {
const d = nextCronRun(expr)
if (!d) return ''
return `${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}`
}