fix: resolve multiple miniprogram bugs and extend admin console

- fix manual bind stuck at BLE scan, redirect to bind-success
- add 15s timeout and stopScan to ble-connect
- add stopScan method to ble.js
- add back-to-home button on bind-success page
- fix field name in subscribe-plans (plan -> plan_type)
- fix history.js to handle created_at field
- fix index.js to handle device name field
- add subscription route alias in request.js
- extend admin cloud function from 1 to 9 actions
- add mock mode to admin-console request.js
- remove unused discover page and legacy record function

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
这个提交包含在:
Guoguo
2026-04-24 23:28:53 +08:00
共同撰写人 Claude Opus 4.6
父节点 52cb1f72dc
当前提交 267c75718b
修改 18 个文件,包含 332 行新增169 行删除
-136
查看文件
@@ -1,136 +0,0 @@
var db = require('../common/db')
var RESPONSE = require('../common/response').RESPONSE
var ERROR_CODES = require('../common/response').ERROR_CODES
exports.main_handler = async function (event, context) {
try {
var token = extractToken(event)
if (!token) {
return RESPONSE.error(ERROR_CODES.UNAUTHORIZED.code, ERROR_CODES.UNAUTHORIZED.message)
}
var user = await verifyToken(token)
if (!user) {
return RESPONSE.error(ERROR_CODES.TOKEN_EXPIRED.code, ERROR_CODES.TOKEN_EXPIRED.message)
}
var body = parseBody(event)
switch (event.path || event.action) {
case '/record/sync':
return await syncRecord(user, body)
case '/record/list':
return await listRecords(user, body)
case '/record/detail':
return await getRecordDetail(user, body)
default:
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, '未知操作')
}
} catch (err) {
return RESPONSE.error(ERROR_CODES.INTERNAL_ERROR.code, err.message)
}
}
async function syncRecord(user, body) {
if (!body.device_id || !body.started_at || !body.ended_at) {
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, '参数不完整')
}
var dbConfig = getDbConfig()
var sessionResult = await db.query(
'INSERT INTO sessions (user_id, device_id, status, started_at, ended_at, created_at, updated_at) ' +
'VALUES (?, ?, 2, ?, ?, NOW(), NOW())',
[user.id, body.device_id, body.started_at, body.ended_at],
dbConfig
)
var sessionId = sessionResult.insertId
await db.query(
'INSERT INTO treatment_records ' +
'(session_id, user_id, device_id, duration_seconds, mode, result_summary, sync_status, synced_at, started_at, ended_at, created_at, updated_at) ' +
'VALUES (?, ?, ?, ?, ?, ?, 2, NOW(), ?, ?, NOW(), NOW())',
[
sessionId,
user.id,
body.device_id,
body.duration_seconds || null,
body.mode || null,
body.result_summary || null,
body.started_at,
body.ended_at
],
dbConfig
)
return RESPONSE.success({ session_id: sessionId })
}
async function listRecords(user, body) {
var dbConfig = getDbConfig()
var limit = parseInt(body.limit) || 20
var offset = parseInt(body.offset) || 0
var records = await db.query(
'SELECT * FROM treatment_records WHERE user_id = ? ORDER BY started_at DESC LIMIT ? OFFSET ?',
[user.id, limit, offset],
dbConfig
)
return RESPONSE.success({ list: records })
}
async function getRecordDetail(user, body) {
if (!body.record_id) {
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, '缺少记录ID')
}
var dbConfig = getDbConfig()
var records = await db.query(
'SELECT * FROM treatment_records WHERE id = ? AND user_id = ? LIMIT 1',
[body.record_id, user.id],
dbConfig
)
if (records.length === 0) {
return RESPONSE.error(ERROR_CODES.NOT_FOUND.code, ERROR_CODES.NOT_FOUND.message)
}
return RESPONSE.success(records[0])
}
function extractToken(event) {
var header = event.headers || {}
var auth = header['Authorization'] || header['authorization'] || ''
if (auth.startsWith('Bearer ')) {
return auth.substring(7)
}
return null
}
async function verifyToken(token) {
return { id: 1, openid: 'placeholder' }
}
function parseBody(event) {
if (event.body) {
try {
return JSON.parse(event.body)
} catch (e) {
return {}
}
}
return event.queryString || {}
}
function getDbConfig() {
return {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '3306'),
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'hox'
}
}