Files
yangxiangyuan db7648eb4d feat(mp, web, calendar): 新增微信收藏夹与日历批量生成功能
- 新增微信小程序版个人收藏夹全套功能,包含聚合首页、收藏列表、编辑、详情页面与配套后端API
- 新增web版时光助手门户与个人收藏夹工具,支持与小程序共享后端数据
- 优化日历提醒工具:替换本地bootstrap资源为公共CDN版本,新增批量生成循环提醒的前端界面与后端逻辑,新增数据库batch_id字段,更新鉴权配置文件
- 补充项目配置、站点地图、调试诊断脚本等配套文件
- 完善各模块的页面配置与样式文件
2026-09-02 22:20:37 +08:00

265 lines
17 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>日历批量生成工具 · 独立窗口</title>
<link rel="icon" href="calendar.svg" type="image/svg+xml" />
<link rel="stylesheet" href="/lib/bootstrap.min.css?v=1.6">
<link rel="stylesheet" href="css/styles.css?v=1.6">
</head>
<body class="bg-light">
<header class="navbar navbar-dark bg-warning sticky-top">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">🧺 日历批量生成工具 · 仅循环场景</span>
<div class="d-flex align-items-center gap-2">
<button id="btnBackToMain" class="btn btn-light btn-sm" title="回到日历主界面">🗓 返回主日历</button>
<button id="btnReload" class="btn btn-light btn-sm" title="刷新批次列表">⟳ 刷新</button>
</div>
</div>
</header>
<main class="container py-3" style="max-width:1280px">
<ul class="nav nav-tabs mb-3" id="batchTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="tab-generator" data-bs-toggle="tab" data-bs-target="#panel-generator" type="button">生成器</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-batches" data-bs-toggle="tab" data-bs-target="#panel-batches" type="button" onclick="CalendarBatchTool && CalendarBatchTool.loadBatches && CalendarBatchTool.loadBatches()">批次管理</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tab-sql" data-bs-toggle="tab" data-bs-target="#panel-sql" type="button">🧪 SQL 执行</button>
</li>
</ul>
<div class="tab-content" id="batchTabsContent">
<div class="tab-pane fade show active" id="panel-generator" role="tabpanel">
<form id="batchForm" class="vstack gap-3">
<div class="row g-2">
<div class="col-8">
<label class="form-label">批次名称(可选)</label>
<input type="text" id="batch_name" class="form-control" placeholder="如:2026Q4 洗被子提醒">
</div>
<div class="col-4">
<label class="form-label">循环模式</label>
<select id="batch_mode" class="form-select">
<option value="monthlyByDay" selected>每月 N 号(推荐)</option>
<option value="monthlyByNthWeekday">每月第 N 周星期 X</option>
<option value="weekly">每 N 周 · 星期多选</option>
<option value="daily">每 N 天</option>
</select>
</div>
</div>
<div class="row g-2">
<div class="col-3"><label class="form-label">时间范围 · 起</label><input type="date" id="batch_rangeStart" class="form-control" required></div>
<div class="col-3"><label class="form-label">时间范围 · 止</label><input type="date" id="batch_rangeEnd" class="form-control" required></div>
<div class="col-6 d-flex align-items-end gap-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="batch_allDay">
<label class="form-check-label" for="batch_allDay">全天(忽略时分)</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="batch_skipExternal">
<label class="form-check-label" for="batch_skipExternal">不联动周报下游</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="batch_completed">
<label class="form-check-label" for="batch_completed">全部标记已完成</label>
</div>
</div>
</div>
<div class="mode-fieldset" data-mode="daily">
<div class="row g-2"><div class="col-4">
<label class="form-label">每 _ 天</label>
<input type="number" min="1" value="1" id="batch_dailyEvery" class="form-control">
</div></div>
</div>
<div class="mode-fieldset" data-mode="weekly" style="display:none">
<div class="row g-2">
<div class="col-4"><label class="form-label">每 _ 周</label><input type="number" min="1" value="1" id="batch_weeklyEvery" class="form-control"></div>
<div class="col-8">
<label class="form-label">星期(可多选)</label>
<div id="batch_weekdays" class="hstack gap-3 flex-wrap">
<label class="form-check"><input type="checkbox" value="0" class="form-check-input batch-wd">周日</label>
<label class="form-check"><input type="checkbox" value="1" class="form-check-input batch-wd">周一</label>
<label class="form-check"><input type="checkbox" value="2" class="form-check-input batch-wd">周二</label>
<label class="form-check"><input type="checkbox" value="3" class="form-check-input batch-wd">周三</label>
<label class="form-check"><input type="checkbox" value="4" class="form-check-input batch-wd">周四</label>
<label class="form-check"><input type="checkbox" value="5" class="form-check-input batch-wd">周五</label>
<label class="form-check"><input type="checkbox" value="6" class="form-check-input batch-wd">周六</label>
</div>
</div>
</div>
</div>
<div class="mode-fieldset" data-mode="monthlyByDay">
<div class="row g-2">
<div class="col-4"><label class="form-label">每 _ 月</label><input type="number" min="1" value="2" id="batch_monthlyEvery" class="form-control"></div>
<div class="col-8">
<label class="form-label">每月哪些号(支持 1-5,15,25-28 混合写法)</label>
<input type="text" id="batch_monthlyDays" class="form-control" value="1-5" placeholder="例如:1-5,15,25-28">
</div>
</div>
</div>
<div class="mode-fieldset" data-mode="monthlyByNthWeekday" style="display:none">
<div class="row g-2">
<div class="col-4"><label class="form-label">每 _ 月</label><input type="number" min="1" value="1" id="batch_monthlyEvery2" class="form-control"></div>
<div class="col-4"><label class="form-label">第几周</label>
<select id="batch_nthWeek" class="form-select"><option>1</option><option>2</option><option selected>3</option><option>4</option><option>5</option></select>
</div>
<div class="col-4"><label class="form-label">星期</label>
<select id="batch_nthWeekday" class="form-select">
<option value="0">周日</option><option value="1">周一</option><option value="2">周二</option>
<option value="3">周三</option><option value="4">周四</option><option value="5">周五</option><option value="6">周六</option>
</select>
</div>
</div>
</div>
<div class="row g-2">
<div class="col-4"><label class="form-label">开始时分</label><input type="time" id="batch_startTime" class="form-control" value="09:00"></div>
<div class="col-4"><label class="form-label">结束时分(留空=不设)</label><input type="time" id="batch_endTime" class="form-control" value="10:00"></div>
<div class="col-4"><label class="form-label">提醒时分(留空=不提醒)</label><input type="time" id="batch_remindTime" class="form-control" value="08:30"></div>
</div>
<div>
<label class="form-label">标题模板(支持 {date} {yyyy} {MM} {dd} {W})</label>
<input type="text" id="batch_title" class="form-control" value="洗被子提醒({MM}-{dd})" required maxlength="150" placeholder="如:洗被子提醒({MM}-{dd})">
</div>
<div>
<label class="form-label">内容模板(同上占位符)</label>
<textarea id="batch_content" class="form-control" rows="3" placeholder="写备注,支持 {date} 占位符"></textarea>
</div>
<div class="hstack gap-2">
<button type="button" id="batch_btnPreview" class="btn btn-outline-primary">👁 预览 SQL</button>
<button type="button" id="batch_btnApply" class="btn btn-primary" disabled>▶ 直接入库</button>
<button type="button" id="batch_btnDownload" class="btn btn-outline-secondary" disabled>💾 下载 SQL</button>
<span id="batch_previewHint" class="text-muted small ms-2">请先点「预览 SQL」再入库</span>
</div>
</form>
<div id="batch_previewArea" class="mt-3 d-none">
<div class="card">
<div class="card-header small">预览信息</div>
<div class="card-body small">
<div id="batch_previewStats" class="mb-2"></div>
<div class="mb-2"><span class="text-danger fw-bold" id="batch_preExisting"></span></div>
<div class="mb-2"><strong>样例(前 20 条):</strong></div>
<table class="table table-sm table-hover" id="batch_sampleTable"><thead><tr><th>开始</th><th>结束</th><th>提醒</th><th>标题</th></tr></thead><tbody></tbody></table>
<div class="mb-2"><strong>SQL(前 503 行,完整的请下载文件):</strong></div>
<textarea id="batch_sqlText" readonly rows="14" class="form-control font-monospace small"></textarea>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="panel-batches" role="tabpanel">
<div class="d-flex justify-content-between mb-2">
<div style="width:360px"><input id="batch_search" class="form-control form-control-sm" placeholder="搜索标题 / 模式…(输入即搜)"></div>
<button type="button" id="batch_refresh" class="btn btn-outline-secondary btn-sm">⟳ 刷新批次</button>
</div>
<div class="table-responsive">
<table class="table table-sm table-hover align-middle" id="batch_listTable">
<thead><tr>
<th>批次名</th><th>模式</th><th>时间范围</th>
<th>生成 / 入库 / 去重 / 已回滚</th>
<th>状态</th><th>创建时间</th><th>操作</th>
</tr></thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="tab-pane fade" id="panel-sql" role="tabpanel">
<form class="vstack gap-3">
<div class="row g-2">
<div class="col-6">
<label class="form-label">批次名称(必填,便于后面批次管理/回滚查找)</label>
<input type="text" id="sql_batch_name" class="form-control" placeholder="如:2026-09-02 手动导入客户提醒 SQL">
</div>
<div class="col-6 d-flex align-items-end gap-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="sql_skipExternal" checked>
<label class="form-check-label" for="sql_skipExternal">不联动周报下游(默认勾,避免爆量)</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="sql_completed">
<label class="form-check-label" for="sql_completed">全部标记已完成</label>
</div>
</div>
</div>
<div>
<label class="form-label">SQL 文本框(只支持 <code>INSERT INTO events (...) VALUES (...)</code>;单条 / 多条 / 多个语句用 ; 分开都行;每行 events 字段允许:id/title/content/start/end/allDay/remindAt/recurrence/createdAt/updatedAt/completed/deleted/batch_id/completedAt/deletedAt,其他字段一律被拒绝;禁止 UPDATE / DELETE / DROP / ALTER)</label>
<textarea id="sql_textarea" rows="22" class="form-control font-monospace small" placeholder="INSERT INTO events (title,content,start,end,allDay,remindAt,completed,deleted,batch_id) VALUES
('客户A回访','准备季度会议','2026-09-03 09:00','2026-09-03 10:00',0,'2026-09-03 08:30',0,0,NULL),
('客户B回访','报价最终版本','2026-09-05 14:00','2026-09-05 15:00',0,'2026-09-05 13:30',0,0,NULL);
"></textarea>
</div>
<div class="hstack gap-2">
<button type="button" id="sql_btnCheck" class="btn btn-outline-info">🧪 SQL 语句检查</button>
<button type="button" id="sql_btnApply" class="btn btn-warning" disabled>▶ 执行 SQL 入库(生成批次,可回滚)</button>
<button type="button" id="sql_btnDownload" class="btn btn-outline-secondary">💾 下载 SQL</button>
<span id="sql_hint" class="text-muted small ms-2">建议先点「检查」确认语法/重复后再执行</span>
</div>
<div id="sql_checkArea" class="d-none mt-3">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<span>🧪 检查结果</span>
<span id="sql_checkSummary" class="badge bg-light"></span>
</div>
<div class="card-body small">
<div id="sql_checkMeta" class="mb-2"></div>
<div id="sql_checkForbidden" class="d-none text-danger mb-2"></div>
<div id="sql_checkSyntaxErrors" class="d-none text-danger mb-2"></div>
<div id="sql_checkColErrors" class="d-none text-danger mb-2"></div>
<div id="sql_checkDuplicate" class="d-none text-warning mb-2">
<span class="fw-bold">⚠️ 检测到重复(宽松模式):</span>
<button id="sql_dupDetail" class="btn btn-outline-warning btn-sm ms-2">查看重复明细…</button>
</div>
<div><strong>样例行(前 15 条):</strong></div>
<div class="table-responsive">
<table class="table table-sm table-hover"><thead><tr><th>语句#</th><th>行#</th><th>标题</th><th>开始</th><th>结束</th></tr></thead><tbody id="sql_checkSampleTbody"></tbody></table>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</main>
<div class="modal fade" id="batchDetailModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header"><h5 class="modal-title">批次详情</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
<div class="modal-body">
<div id="batch_detailBody"></div>
</div>
<div class="modal-footer"><button class="btn btn-secondary" data-bs-dismiss="modal">关闭</button></div>
</div>
</div>
</div>
<div class="modal fade" id="sqlDuplicateModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">⚠️ SQL 批次检测到重复(宽松模式)</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body small">
<div id="sql_dupSummary" class="mb-2"></div>
<div class="table-responsive">
<table class="table table-sm table-hover">
<thead><tr><th>你的 SQL 语句#-行#</th><th>你的标题</th><th>你的开始</th><th>匹配库内事件标题</th><th>匹配库内开始</th><th>相似度</th><th>操作</th></tr></thead>
<tbody id="sql_dupTbody"></tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="sql_dupCancel">先不执行,回去改 SQL</button>
<button type="button" class="btn btn-warning" data-bs-dismiss="modal" id="sql_dupConfirm">我已知悉重复,继续执行生成批次</button>
</div>
</div>
</div>
</div>
<script src="js/config.js"></script>
<script src="/lib/bootstrap.bundle.min.js"></script>
<script src="js/batch.js?v=1.7"></script>
</body>
</html>