feat: complete feature gaps across all modules

Server:
- Add settings-cache with 60s TTL for feature toggle checks
- Enforce maintenance_mode on login, enable_binding on device bind

Admin console:
- Remove dead "发送通知" button from user detail
- Firmware check calls real API and compares versions

Miniprogram:
- Wear-check: dynamic battery/connected from BLE state
- Login: hide non-functional phone auth button
- Treating: show actual selected regions instead of hardcoded "全脸"
- Index: display subscription status with tap to manage
- Auto-scan: show "待检测" instead of "--" for PD data
- Agreements: tap shows "内容建设中" modal
这个提交包含在:
Guoguo
2026-05-02 08:48:26 -07:00
父节点 1017fb5dae
当前提交 031678c03f
修改 17 个文件,包含 116 行新增12 行删除
+14
查看文件
@@ -0,0 +1,14 @@
const settingsDao = require('../dao/settings.dao')
let cache = null
let cacheTime = 0
const TTL = 60000 // 1 minute
async function getSettings() {
if (cache && Date.now() - cacheTime < TTL) return cache
cache = await settingsDao.getAll()
cacheTime = Date.now()
return cache
}
module.exports = { getSettings }
+4
查看文件
@@ -3,6 +3,7 @@ const router = require('express').Router()
const { ok, fail } = require('../lib/response')
const { signUser, readBearer } = require('../lib/auth')
const { code2Session } = require('../lib/wechat')
const { getSettings } = require('../lib/settings-cache')
const config = require('../config')
const userDao = require('../dao/user.dao')
const logDao = require('../dao/log.dao')
@@ -10,6 +11,9 @@ const logDao = require('../dao/log.dao')
const wrap = fn => (req, res, next) => fn(req, res, next).catch(next)
router.post('/auth/login', wrap(async (req, res) => {
const settings = await getSettings()
if (settings.maintenance_mode === true) return res.json(fail(2001, '系统维护中,请稍后再试'))
const session = await code2Session(req.body.code || '')
let user = await userDao.findByOpenid(session.openid)
if (!user) {
+4
查看文件
@@ -2,6 +2,7 @@ const router = require('express').Router()
const { ok, fail } = require('../lib/response')
const { requireUser } = require('../middleware/auth')
const { randomHex } = require('../lib/auth')
const { getSettings } = require('../lib/settings-cache')
const bindingDao = require('../dao/binding.dao')
const deviceDao = require('../dao/device.dao')
const commandDao = require('../dao/command.dao')
@@ -12,6 +13,9 @@ const logDao = require('../dao/log.dao')
const wrap = fn => (req, res, next) => fn(req, res, next).catch(next)
router.post('/device/bind', requireUser, wrap(async (req, res) => {
const settings = await getSettings()
if (settings.enable_binding === false) return res.json(fail(2001, '设备绑定已关闭'))
const deviceId = String(req.body.device_id || '').trim()
if (!deviceId) return res.json(fail(2001, 'device_id required'))