feat(mp, web, calendar): 新增微信收藏夹与日历批量生成功能
- 新增微信小程序版个人收藏夹全套功能,包含聚合首页、收藏列表、编辑、详情页面与配套后端API - 新增web版时光助手门户与个人收藏夹工具,支持与小程序共享后端数据 - 优化日历提醒工具:替换本地bootstrap资源为公共CDN版本,新增批量生成循环提醒的前端界面与后端逻辑,新增数据库batch_id字段,更新鉴权配置文件 - 补充项目配置、站点地图、调试诊断脚本等配套文件 - 完善各模块的页面配置与样式文件
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
// 快速诊断:batch_sql_check 对含 xxx_col 的 INSERT 返回什么
|
||||
// 用法:node 临时脚本放在项目根,直接 require
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
const TMP_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'cal_diag_'))
|
||||
const BACKUP_DIR = path.join(process.cwd(), 'data', 'calendar_reminder_backups')
|
||||
const latest = fs.readdirSync(BACKUP_DIR).filter(f => f.startsWith('calendar_reminder_2') && f.endsWith('.db')).sort().slice(-1)[0]
|
||||
const SRC = path.join(BACKUP_DIR, latest)
|
||||
const DST_DIR = path.join(process.cwd(), 'data', 'calendar_reminder_backups', '_diag')
|
||||
fs.mkdirSync(DST_DIR, { recursive: true })
|
||||
for (const suf of ['.db', '.db-wal', '.db-shm']) {
|
||||
fs.copyFileSync(SRC.replace(/\.db$/,'') + suf, path.join(DST_DIR, 'calendar_reminder' + suf))
|
||||
}
|
||||
const modSrc = fs.readFileSync(path.join(process.cwd(), 'src','server','calendar_reminder.js'), 'utf8')
|
||||
const NEEDLE = "const DB_PATH = path.join(process.cwd(), 'data', 'calendar_reminder.db')"
|
||||
if (!modSrc.includes(NEEDLE)) { throw new Error('NEEDLE NOT FOUND') }
|
||||
const modTmp = path.join(process.cwd(), 'dev_test_scripts','unit','_calendar_reminder_diag.js')
|
||||
fs.writeFileSync(modTmp, modSrc.replace(NEEDLE,
|
||||
'const DB_PATH = path.join(process.cwd(), "data/calendar_reminder_backups/_diag", "calendar_reminder.db")'))
|
||||
const express = require('express')
|
||||
const { createHash } = require('crypto')
|
||||
const cookie = require('cookie')
|
||||
const app = express()
|
||||
app.use((req, res, next) => {
|
||||
req.headers.cookie = (req.headers.cookie || '') + '; calendar_reminder_gate=1'
|
||||
next()
|
||||
})
|
||||
const mod = require(modTmp)
|
||||
mod.bindRoutes(app)
|
||||
const PORT = 18795
|
||||
const server = app.listen(PORT, '127.0.0.1', async () => {
|
||||
try {
|
||||
const badCol = `INSERT INTO events (title,xxx_col,start) VALUES ('t',1,'2026-09-02 09:00');`
|
||||
const http = require('http')
|
||||
const r = await new Promise((resolve, reject) => {
|
||||
const body = JSON.stringify({ sql_text: badCol })
|
||||
const req = http.request({ hostname: '127.0.0.1', port: PORT, path: '/api/calendar_reminder/batch_sql_check', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) } }, res => {
|
||||
let buf = ''; res.on('data', d => buf += d); res.on('end', () => resolve({ status: res.statusCode, body: buf }))
|
||||
})
|
||||
req.on('error', reject); req.write(body); req.end()
|
||||
})
|
||||
console.log('STATUS', r.status)
|
||||
console.log('BODY', r.body)
|
||||
let j
|
||||
try { j = JSON.parse(r.body) } catch (e) { j = null }
|
||||
if (j) {
|
||||
console.log('col_errors length:', j.col_errors && j.col_errors.length)
|
||||
console.log('col_errors:', JSON.stringify(j.col_errors, null, 2))
|
||||
console.log('syntax_errors:', JSON.stringify(j.syntax_errors, null, 2))
|
||||
console.log('forbidden:', JSON.stringify(j.forbidden, null, 2))
|
||||
console.log('ok?', j.ok)
|
||||
}
|
||||
server.close(() => {
|
||||
fs.rmSync(DST_DIR, { recursive: true, force: true })
|
||||
fs.unlinkSync(modTmp)
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
try { server.close() } catch {}
|
||||
try { fs.rmSync(DST_DIR, { recursive: true, force: true }) } catch {}
|
||||
try { fs.unlinkSync(modTmp) } catch {}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user