d4bf3627fd
新增运动节拍RepClock全套小程序页面、后端API与数据库服务,新增subhub子工具汇总页面,优化全局主页样式与配置,为web静态资源添加版本缓存参数,补充配套调试脚本
102 lines
2.7 KiB
JavaScript
102 lines
2.7 KiB
JavaScript
const Database = require('better-sqlite3')
|
|
const path = require('path')
|
|
|
|
const CORE_DB_PATH = path.join(process.cwd(), 'data', 'mp_time_assistant_core.db')
|
|
|
|
let db = null
|
|
|
|
const KIT_META = [
|
|
{
|
|
id: 'personal_collect',
|
|
name: '微信收藏夹',
|
|
description: '聊天图片 / 文件 / 文字收藏,标签搜索,软删除可追溯。独立部署,零共享。',
|
|
icon: '📁',
|
|
meta: 'API: /api/mp_personal_collect/ · DB: mp_personal_collect.db',
|
|
},
|
|
{
|
|
id: 'rep_clock',
|
|
name: '运动节拍 RepClock',
|
|
description: 'HIIT / Yoga / 拉伸节奏倒计时,锚点时钟 + 女声播报,后台时间自动补偿。',
|
|
icon: '⏱️',
|
|
meta: 'API: /api/mp_rep_clock/ · DB: mp_rep_clock.db',
|
|
},
|
|
]
|
|
|
|
const nowIso = () => new Date().toISOString()
|
|
|
|
const getDb = () => {
|
|
if (db) return db
|
|
db = new Database(CORE_DB_PATH)
|
|
db.pragma('journal_mode = WAL')
|
|
db.exec(`CREATE TABLE IF NOT EXISTS core_state (
|
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
active_kit TEXT,
|
|
updated_at TEXT NOT NULL
|
|
);`)
|
|
db.prepare(`
|
|
INSERT OR IGNORE INTO core_state (id, active_kit, updated_at)
|
|
VALUES (1, NULL, ?)
|
|
`).run(nowIso())
|
|
return db
|
|
}
|
|
|
|
const getStateRow = () => {
|
|
const row = getDb().prepare(`SELECT * FROM core_state WHERE id = 1 LIMIT 1`).get()
|
|
if (!row) {
|
|
getDb().prepare(`
|
|
INSERT INTO core_state (id, active_kit, updated_at)
|
|
VALUES (1, NULL, ?)
|
|
`).run(nowIso())
|
|
return getStateRow()
|
|
}
|
|
return row
|
|
}
|
|
|
|
const setActiveKit = kitId => {
|
|
getDb().prepare(`UPDATE core_state SET active_kit = ?, updated_at = ? WHERE id = 1`).run(kitId || null, nowIso())
|
|
}
|
|
|
|
const serializeState = () => {
|
|
const row = getStateRow()
|
|
return {
|
|
ok: true,
|
|
activeKit: row.active_kit || null,
|
|
active_kit: row.active_kit || null,
|
|
}
|
|
}
|
|
|
|
const bindRoutes = app => {
|
|
getDb()
|
|
|
|
app.get('/api/mp_time_assistant/meta', (req, res) => {
|
|
res.json({
|
|
ok: true,
|
|
appName: 'MpTimeAssistant',
|
|
appNameZh: 'MilesYang时光助手',
|
|
kits: KIT_META,
|
|
notes: {
|
|
'personal_collect_api_prefix': '/api/mp_personal_collect/kits/personal_collect',
|
|
'rep_clock_api_prefix': '/api/mp_rep_clock/kits/rep_clock',
|
|
},
|
|
})
|
|
})
|
|
|
|
app.get('/api/mp_time_assistant/state', (req, res) => {
|
|
res.json(serializeState())
|
|
})
|
|
|
|
app.put('/api/mp_time_assistant/state/active-kit', (req, res) => {
|
|
try {
|
|
const raw = String(req.body && req.body.kitId || req.body && req.body.kit_id || '').trim()
|
|
const nextKit = raw || null
|
|
setActiveKit(nextKit)
|
|
return res.json({ ok: true, activeKit: nextKit, active_kit: nextKit })
|
|
} catch (e) {
|
|
return res.status(500).json({ ok: false, error: String(e.message || e) })
|
|
}
|
|
})
|
|
}
|
|
|
|
module.exports = { bindRoutes }
|
|
|