db7648eb4d
- 新增微信小程序版个人收藏夹全套功能,包含聚合首页、收藏列表、编辑、详情页面与配套后端API - 新增web版时光助手门户与个人收藏夹工具,支持与小程序共享后端数据 - 优化日历提醒工具:替换本地bootstrap资源为公共CDN版本,新增批量生成循环提醒的前端界面与后端逻辑,新增数据库batch_id字段,更新鉴权配置文件 - 补充项目配置、站点地图、调试诊断脚本等配套文件 - 完善各模块的页面配置与样式文件
265 lines
17 KiB
HTML
265 lines
17 KiB
HTML
<!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>
|