Docker Build and Push / build-image (push) Successful in 1m7s
- splitTitle: 截断后用 \p{P} 去掉标题尾部连续分隔符 (原字符类重组有
转义坑, 换 Unicode 属性类)
- 看板卡片左列 (状态点+⋯) 收窄至 14px 并负外距悬进卡片内边距
- 项目头像统一: 新增 .pavatar 基类与 projectIcon.colorOfProject,
项目管理预览改用同配色/同圆角/居中首字, 修复灰底与文字歪斜
77 lines
2.9 KiB
JavaScript
77 lines
2.9 KiB
JavaScript
// 快速添加的标题解析: 时间词前缀 + 30 字分隔符截断 (T-TK-14/16)
|
||
export const MAX_TITLE = 30
|
||
|
||
// 分隔符: 空格 / 中英文标点 / 斜杠等 —— 截断优先落在分隔符上, 不切词
|
||
const SEPARATOR = /[\s,,。;;、!!??::“”"'’‘()()\[\]【】\-_/\\|]/
|
||
|
||
/**
|
||
* 长文本拆分: ≤30 字原样; 超长时在 30 字内(且不少于 8 字)找最后一个分隔符截断,
|
||
* 前段为标题, **完整原文**作为描述 (整体进详情, 不丢内容)。
|
||
*/
|
||
export function splitTitle(raw) {
|
||
const text = String(raw || '').trim()
|
||
if (text.length <= MAX_TITLE) return { title: text, desc: '' }
|
||
let cut = -1
|
||
for (let i = MAX_TITLE; i >= 8; i--) {
|
||
if (SEPARATOR.test(text[i - 1])) { cut = i; break }
|
||
}
|
||
if (cut < 0) cut = MAX_TITLE
|
||
// 截断落在分隔符上: 分隔符留在标题末尾很难看, 去掉尾部连续分隔符/空白
|
||
// (\p{P} 覆盖中英文全部标点; 之前用 SEPARATOR.source 重组字符类有转义坑)
|
||
const title = text.slice(0, cut).replace(/[\s\p{P}]+$/u, '').trim()
|
||
return { title, desc: text }
|
||
}
|
||
|
||
// 时间词 → 日期 (返回 YYYY-MM-DD):
|
||
// 今天/明天/后天 = 当日 +0/+1/+2
|
||
// 本周 = 本周日, 下周 = 下周日 (周一定义为一周开始)
|
||
// 本月 = 本月最后一天, 下月 = 下月最后一天
|
||
const toISO = (d) => {
|
||
const p = (n) => String(n).padStart(2, '0')
|
||
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`
|
||
}
|
||
|
||
export function dateFromWord(word, now = new Date()) {
|
||
const day = (n) => { const d = new Date(now); d.setDate(d.getDate() + n); return toISO(d) }
|
||
const endOfWeek = (offsetWeeks) => {
|
||
const d = new Date(now)
|
||
const dow = (d.getDay() + 6) % 7 // 周一=0
|
||
d.setDate(d.getDate() + offsetWeeks * 7 + (6 - dow))
|
||
return toISO(d)
|
||
}
|
||
const endOfMonth = (offsetMonths) => {
|
||
const d = new Date(now.getFullYear(), now.getMonth() + offsetMonths + 1, 0)
|
||
return toISO(d)
|
||
}
|
||
switch (word) {
|
||
case '今天': return day(0)
|
||
case '明天': return day(1)
|
||
case '后天': return day(2)
|
||
case '本周': return endOfWeek(0)
|
||
case '下周': return endOfWeek(1)
|
||
case '本月': return endOfMonth(0)
|
||
case '下月': return endOfMonth(1)
|
||
default: return null
|
||
}
|
||
}
|
||
|
||
// 匹配最长的时间词前缀 (后面跟分隔符或直接结束)
|
||
const TIME_WORDS = ['本周', '下周', '本月', '下月', '今天', '明天', '后天']
|
||
|
||
/**
|
||
* 解析时间词前缀: "明天 交周报" → { markDate: '2026-10-26', rest: '交周报' }
|
||
* 无匹配时 rest 为原文, markDate 为 null。
|
||
*/
|
||
export function parseTimePrefix(raw) {
|
||
const text = String(raw || '').trim()
|
||
for (const w of TIME_WORDS) {
|
||
if (text.startsWith(w)) {
|
||
const after = text.slice(w.length)
|
||
if (after === '' || SEPARATOR.test(after[0])) {
|
||
return { markDate: dateFromWord(w), rest: after.trim() }
|
||
}
|
||
}
|
||
}
|
||
return { markDate: null, rest: text }
|
||
}
|