提交图
153 次代码提交
作者 SHA1 备注 提交日期
Guoguo 7270b593ae docs: add updated protocol spec v3 and firmware-mp workflow v1 2026-06-12 08:52:09 -07:00
Guoguo b4d677a9b4 docs: add protocol docs and allow docx in docs/protocols 2026-06-11 04:16:56 -07:00
Guoguo fa44f4f5ad docs: add protocol specs, task sheet, and workflow docs to docs/protocols 2026-06-11 04:16:19 -07:00
Guoguo 340837c700 feat: rebrand to LumiFlow across miniprogram, admin-console, and server 2026-06-10 18:47:22 -07:00
Guoguo edf45690c3 fix: address audit findings for Phase 1 scan
- Extract _cleanup() to properly unregister ADC listener + clear timers
- ADC callback unregisters itself on first receive (prevent duplicates)
- setParams failure now stops scanning and clears all state
- Timeout handler unregisters ADC listener
- Add BLE connection check before scan
- SCAN_TIMEOUT 8s → 12s (must exceed hold_time 10s)
- Pre-compute barWidth in JS instead of float math in WXML
- Error only shows when scanning is false
2026-06-10 08:18:54 -07:00
Guoguo 0ffa67da65 feat: implement MVP Phase 1 — full-area scan with ADC data collection
- Send scan command: all 5 regions LED on, brightness 128
- Listen for ADC notify (17 bytes) instead of broken queryStatus
- Parse and display PD1-PD7 values with visual bars
- Show VBAT/battery info
- Store scan PD data in globalData for Phase 3 smart adjustment
- 8s timeout fallback, stop LED on page unload
2026-06-10 08:16:17 -07:00
Guoguo c9799a5fc1 chore: bump version to v0.1.6 2026-06-05 23:38:02 -07:00
Guoguo 44935c4bf3 fix: correct region mapping (swap left/right, swap middle/bottom) and auto-scan proceeds on timeout
Region name mapping corrected to match actual hardware IO positions:
- 0x01: 左区→右区, 0x02: 右区→左区
- 0x08: 下区→中区, 0x10: 中区→下区
Auto-scan no longer shows timeout error, proceeds to next step instead.
2026-06-05 23:37:03 -07:00
Guoguo 4666050458 feat: add version number v0.1.5 to profile page footer 2026-06-05 23:12:15 -07:00
Guoguo dc0bcbdca3 fix: decodeURIComponent device_id in ble-connect to fix space matching 2026-06-05 22:41:28 -07:00
Guoguo 5bce7060ac fix: BLE scan match use indexOf instead of exact equals
Fixes timeout during binding when targetDeviceId is set but exact
string match fails due to encoding differences. Also skips devices
with no name, and logs match result for every candidate.
2026-06-05 22:38:07 -07:00
Guoguo e4d11d30a8 feat: add BLE scan/connect/service discovery console logs 2026-06-05 22:30:01 -07:00
Guoguo 810a3a19a5 feat: support JW_ device ID format in QR scan and BLE matching
- parseDeviceId accepts hex with spaces (e.g. "672B6D5A 4DCD861")
- BLE scan does exact match on "JW_<device_id>" when target is known
- Manual input placeholder updated to show new format
2026-06-05 19:21:43 -07:00
Guoguo 9882d19b54 fix: replace leftover 我的光面膜 with 我的设备 on home page 2026-06-05 04:37:39 -07:00
Guoguo 3486cefa18 fix: remove remaining 光子美容仪 from server and admin-console
Replace with 智能面膜 (device name) and 智美 (brand name) for regulatory compliance.
2026-06-05 04:33:55 -07:00
Guoguo ba3c621294 feat: add JW_ prefix to BLE device scan filter 2026-06-05 03:59:05 -07:00
Guoguo 29ff1c015b fix: replace facial/medical terms with neutral position labels
Region names: 左脸→左区, 右脸→右区, 额头→上区, 下巴→下区,
鼻唇→中区, 左眼→左上区, 右眼→右上区, 全脸→全区域.
Replace 面部/面罩 with 设备 in wear-check and auto-scan pages.
2026-05-31 23:39:06 -07:00
Guoguo aff8c2d9b5 fix: remove all medical device terms from user-facing text
Replace '光子美容仪' with '智美'/'智能面膜'/'我的设备' throughout.
Replace '护理' with '使用' in all UI text.
Replace '皮肤' with '检测'/'智能' where applicable.
Replace 🌸 with 💎 for brand identity.
Internal code (variable names, API paths, file names) unchanged.
2026-05-29 01:34:54 -07:00
Guoguo 22110e866a feat: add Simple Peripheral back to BLE scan for dev board testing 2026-05-20 07:41:49 -07:00
Guoguo a65dbfc5a8 chore: remove dead debug code — isDevMode, debug CSS, __DEV__ flag 2026-05-20 07:23:26 -07:00
Guoguo f0fdb285b5 chore: remove all mock/debug code for production release
Miniprogram:
- ENV switched to 'prod' (disables __DEV__ flag)
- Deleted mock.js and test-ble-frame.js
- Removed mockBind/mockPurchase from api.js
- Removed all debug UI panels and onMock* handlers from 6 pages
- Removed mock purchase fallback in subscribe-plans
- Removed SIMPLE PERIPHERAL dev board from BLE scan

Server:
- Removed /device/mock-bind route
- Removed /subscription/mock-purchase route
- Removed dev_openid fallback in wechat.js
- Removed mockBind() from binding.dao.js
- Removed mock fallback in purchase endpoint
- NODE_ENV default changed to 'production'

Admin:
- ENV switched to 'prod'

All mock code preserved in 'test' branch for future development use.
2026-05-20 07:19:26 -07:00
Guoguo 0b82d9dbcf fix: sync endpoint uses amount.total instead of payer_total for consistency 2026-05-20 07:03:51 -07:00
Guoguo 778167e47d Merge branch 'feat/production-ready' 2026-05-20 06:59:35 -07:00
Guoguo f66fbe93ec refactor: extract grantTrialIfEligible, fix race condition + hardcoded days
- New grantTrialIfEligible() in subscription.dao.js with SELECT FOR UPDATE
  to prevent concurrent bind race condition granting double trials
- confirmBind + mockBind now call the shared function (was duplicated)
- Trial days no longer hardcoded to 7 in binding — respects settings
2026-05-20 02:37:10 -07:00
Guoguo 1a180ea07b fix: prevent trial reset on device rebind
confirmBind and mockBind now check trial history before granting trial.
Previously only checked for active subscriptions — if trial expired,
rebinding would create a new 7-day trial, allowing infinite free usage.
Now checks if user ever had a trial (any status), skips if so.
2026-05-20 02:25:51 -07:00
Guoguo f1a2523cb4 fix: ADC notifications no longer emit 'status' (prevents timer jump)
- ADC (17-byte) now emits 'adc' + 'battery' events, not 'status'
- Fixes CRITICAL timer jump: remaining_ms:0 was resetting countdown
- Drop ADC packets with bad XOR checksum
- treating.js + index.js subscribe to 'battery' for live battery updates
- onStatus only updates remaining_ms when > 0
2026-05-19 03:57:47 -07:00
Guoguo 3fd7578163 feat: support 17-byte ADC status from updated vendor protocol
Protocol update adds FFE4 Status format: 7×PD sensors (little-endian)
+ VBAT battery voltage (mV) + XOR checksum = 17 bytes.

- parseVendorStatus: handles 1-byte heartbeat, 17-byte ADC, 33-byte params
- handleValueChange: ADC type extracts PD array + battery % from VBAT
- Battery calculated as linear 3000mV(0%) to 4200mV(100%)
- PD data passed through status event for treatment pages
- Updated protocol doc with full byte table and old/new comparison
2026-05-19 03:54:15 -07:00
Guoguo 0feb900a1d docs: complete developer documentation (5 guides + index)
- 01-快速开始: local setup for all 3 modules, common issues
- 02-配置说明: all env vars, WeChat/Pay/DB/COS config details
- 03-架构说明: system overview, directory structure, data flows
- 04-部署指南: Tencent Cloud SCF/COS deployment, launch checklist
- 05-API接口文档: all 42 endpoints with params and response format
- README index with audience guide and quick links
2026-05-18 08:11:30 -07:00
Guoguo afcc8d12de fix: index page — no loading flash on tab switch, subscription always tappable
- Loading animation only shows on first visit, subsequent onShow updates silently
- Subscription row always navigates to plans page (was no-op when active)
- Move devMode init to onLoad (only needs to run once)
2026-05-18 06:04:25 -07:00
Guoguo fda403d6a9 fix: index page center-aligned layout for device card 2026-05-18 05:57:47 -07:00
Guoguo b9a4f484bb fix: index page layout — separate badge from reconnect, space buttons
- Device card: top row with icon+name+badge, reconnect button below
- Action buttons wrapped in flex column with 20rpx gap
- Removed inline device-battery, now part of device-meta row
2026-05-18 05:51:13 -07:00
Guoguo 46cc225fe8 fix: add HTTP timeout and cert cache error recovery in wxpay
- httpsRequest: 15s timeout, prevents hanging on WeChat API outage
- fetchPlatformCertificates: keeps old certs if refresh fails,
  only throws if no certs at all (first time failure)
2026-05-18 05:35:17 -07:00
Guoguo 2e63213e60 fix: handle literal \n in WX_MCH_PRIVATE_KEY env var
- Replace literal '\n' with real newlines when reading private key from env
- Add PEM header validation to catch format errors early
- File-based key (privateKeyPath) unaffected
2026-05-18 05:32:22 -07:00
Guoguo c21a0912c6 fix: auto-cleanup stale payment orders and expired pending bindings
- closeStaleOrders: marks payment orders older than 24h as 'closed'
- closeExpiredPending: marks expired binding requests (bind_status=3) as cancelled
- Both run on app startup (SCF cold start), no cron needed
- countPendingByUser already filters to 2h window (previous commit)
2026-05-18 03:52:03 -07:00
Guoguo 343eeca89a fix: pending order count only includes orders created within 2 hours 2026-05-18 03:49:11 -07:00
Guoguo 05e990eda5 fix: payment security hardening — 3 CRITICAL + 3 HIGH
CRITICAL fixes:
- C1: Notify amount validation now unconditional (was skippable if amount field missing)
- C2: Sync endpoint validates payer_total against order amount before activation
- C3: Order ID uses crypto.randomBytes(6) instead of Math.random (collision-safe)

HIGH fixes:
- H1: Payment endpoints rate limited to 5/min per IP
- H2: Max 5 pending orders per user, reject new ones until completed/cancelled
- H3: Purchase endpoint returns error (not mock) when wxpay unconfigured in production

Also fixed:
- Notify handler asserts Buffer body, rejects non-Buffer (L3)
- Notify error response is generic, no internal message leak (M1)
- Private key cached in memory after first read (L2)
- Fixed duplicate paymentOrderDao const declaration
2026-05-18 03:45:57 -07:00
Guoguo 0ef359b563 fix: add WECHAT_APPID to production guard 2026-05-18 03:18:45 -07:00
Guoguo 731122064b fix: 5 critical payment issues from code review
1. Move notify route before authMiddleware (WeChat callback has no JWT)
2. Add await to verifyNotifySignature call (was fire-and-forget)
3. Remove dangerous verify fallback — all signature failures now throw
4. Payment sync polls 3x before giving up, never redirects to success
   page unless confirmed paid
5. Production guard enforces all WX_MCH_* env vars on startup
2026-05-18 03:16:44 -07:00
Guoguo e9681cdd21 fix: implement real notify signature verification + replay protection
- Fetch and cache WeChat platform certificates via /v3/certificates
- Verify notification RSA-SHA256 signature against platform cert
- Reject notifications with timestamp older than 5 minutes (anti-replay)
- Split decryptResource (raw string) from decryptNotifyResource (JSON)
  so platform cert PEM decryption works correctly
2026-05-18 03:11:33 -07:00
Guoguo 78ea1a03c5 feat: WeChat Pay V3 integration (fill credentials to activate)
Server:
- New lib/wxpay.js: native crypto RSA-SHA256 signing, JSAPI prepay,
  AES-256-GCM notify decryption, order query (no npm deps)
- New dao/payment-order.dao.js: createOrder, markPrepay,
  markPaidAndActivateSubscription (idempotent + transactional)
- New routes/payment.js: GET order status, POST order sync
- New routes/payment-notify.js: WeChat async callback handler with
  signature verification, amount/appid/mchid validation
- Modified subscription/purchase: auto-detects wxpay config, returns
  real payment_params or mock fallback
- Schema: payment_orders table with out_trade_no unique key
- app.js: express.raw() for notify path, payment routes mounted
- config.js: wxpay block with 7 env vars
- .env.example: all WeChat Pay fields documented
- .gitignore: certs/, *.pem, *.p12

Miniprogram:
- subscribe-plans doPurchase: calls real purchase API, falls back to
  mockPurchase only when server returns mock:true
- Added syncAndRedirect for post-payment order confirmation
- api.js: getPaymentOrder, syncPaymentOrder
- Removed "模拟支付"/"测试环境" from UI text
2026-05-18 03:07:59 -07:00
Guoguo 92416261ee feat: production readiness — feature gaps + config hardening
Miniprogram:
- Add BLE reconnect button on home page when disconnected
- Add loading states to index, profile, subscribe-plans pages
- Add profile editing (avatar + nickname) with COS upload
- Enable pull-to-refresh on history page
- Fix auto-scan self.options → self.data inconsistency
- Add console.error to silent catch blocks
- Gate 'Simple Peripheral' BLE scan behind __DEV__ flag
- Add production config comment to env.js

Admin console:
- Add empty state '暂无数据' to all 5 list views
- Replace plain text plan input with select dropdown
- Add type="date" to record date filters
- Add production config comment

Server:
- CORS origin restricted in production (env CORS_ORIGIN)
- DB pool size configurable via DB_POOL_SIZE env var
- .env.example updated with WeChat Pay + production fields
2026-05-15 09:07:41 -07:00
Guoguo 7e036576e3 fix: wear-check reconnect scans and connects directly
- Retry button disconnects then re-scans for device (no page navigation)
- Prevents duplicate scan with checking guard
- Disconnect before scan with 500ms delay for adapter recovery
- Clears reconnect timer on success/error/unload
- Error text updated to guide user to retry button
2026-05-12 06:37:51 -07:00
Guoguo 4149c35a0a fix: wear-check page stuck spinning in vendor_33 mode
- vendor_33 mode skips BLE wear detection (protocol doesn't support it)
  and passes check immediately if device is connected
- Show error message if device is not connected
- Retry button navigates back if disconnected instead of re-checking
2026-05-12 06:34:52 -07:00
Guoguo f69da211ab fix: BLE connection leak on page unload and retry timer cleanup
- onUnload disconnects BLE if not in 'done' state (prevents connection leak)
- onUnload clears retry timer to prevent setData on dead page
- Store retry setTimeout ref for proper cleanup
2026-05-12 06:28:36 -07:00
Guoguo 1fa6434451 fix: BLE reconnect stuck on binding state
- onRetry clears bind_result listener before disconnect
- Add 1s delay after closeBluetoothAdapter before re-scanning
- Fix binding state text from '点击连接' to '正在配对...'
2026-05-12 06:25:53 -07:00
Guoguo 8e306819ff fix: heartbeat no longer emits 'status' with remaining_ms=0
Heartbeat (1-byte FFE4 notify) now emits 'heartbeat' event only.
Only 33-byte state responses emit 'status' with parsed IO data.
Fixes timer jumping to 0 every second during treatment.
2026-05-12 06:22:28 -07:00
Guoguo 7d7cb9d081 feat: add 'Simple Peripheral' to BLE scan name filter for dev board 2026-05-12 06:19:12 -07:00
Guoguo 20d37982ca fix: vendor_33 BLE emits compatible 'status' event for existing pages
- handleValueChange now calls parseVendorStatus and emits 'status'
  with legacy-compatible shape (mode_state, battery, remaining_ms, etc.)
- 1-byte heartbeat mapped to mode_state, 33-byte state parsed for
  active IO detection
- Fixes regression where treating, index, wear-check, auto-scan pages
  never received status updates in vendor_33 mode
- Also emits 'vendor_raw' with full parsed data for future use
2026-05-12 06:03:28 -07:00
Guoguo cd088dbddc fix: BLE protocol handling matches actual device behavior
- discoverChars uses properties (write/notify) to distinguish FFE1
  command characteristic from FFE1 service UUID
- handleValueChange: vendor_33 mode emits vendor_status (FFE4 heartbeat)
  and vendor_data separately, no longer tries parseFrame on raw bytes
- parseVendorStatus handles 1-byte heartbeat and 33-byte state readback
  with proper IO1-IO5 field parsing
2026-05-12 05:59:16 -07:00
Guoguo 624f52f4cc fix: admin records filter by user_id instead of keyword search
- RecordView passes user_id as separate filter param, not as keyword
- Admin records endpoint forwards user_id to DAO
- treatmentDao.listAdmin supports exact user_id match filter
- Added visible filter tag with clear button in RecordView
2026-05-11 07:15:40 -07:00