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>
这个提交包含在:
@@ -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'
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户