feat: add password change, trial subscription, batch import, UX improvements

Server:
- POST /api/v1/admin/password: admin password change with bcrypt migration
- POST /api/v1/subscription/trial: user trial activation, one per user
- POST /api/v1/admin/devices/batch: bulk device import (up to 500)
- Add trial plan (7 days, free) to PLANS constant

Admin console:
- Settings page: add password change form with validation
- Device page: add batch import modal with textarea input

Miniprogram:
- Treating page: add back button with stop-treatment confirmation
- Index page: add mock device bind button (dev mode only)
这个提交包含在:
Guoguo
2026-04-28 19:42:23 -07:00
父节点 4ec42e7816
当前提交 1f55e430c8
修改 9 个文件,包含 258 行新增3 行删除
+28 -1
查看文件
@@ -1,5 +1,6 @@
var ble = require('../../services/ble')
var http = require('../../utils/request')
var config = require('../../config/env')
var app = getApp()
Page({
@@ -12,10 +13,12 @@ Page({
modeState: '空闲',
bleState: 'disconnected',
hasDevice: false,
deviceInfo: null
deviceInfo: null,
devMode: false
},
onShow: function () {
this.setData({ devMode: config.__DEV__ || false })
this.checkState()
this._onStatus = this.onBleStatus.bind(this)
ble.on('status', this._onStatus)
@@ -145,6 +148,30 @@ Page({
wx.navigateTo({ url: '/pages/wear-check/wear-check' })
},
onMockBind: function () {
var self = this
var mockDeviceId = 'MOCK_' + Date.now().toString(36).toUpperCase()
wx.showModal({
title: '模拟绑定',
content: '将创建一个模拟设备 ' + mockDeviceId + ' 并绑定到当前账号',
success: function (res) {
if (res.confirm) {
http.post('/api/v1/device/bind', { device_id: mockDeviceId }).then(function (data) {
return http.post('/api/v1/device/bind/confirm', {
device_id: data.device_id,
bind_token: data.bind_token
})
}).then(function () {
wx.showToast({ title: '模拟绑定成功', icon: 'success' })
self.checkState()
}).catch(function (err) {
wx.showToast({ title: err.message || '绑定失败', icon: 'none' })
})
}
}
})
},
onViewSubscription: function () {
if (!this.data.subscription || this.data.subscription.status !== 'active') {
wx.navigateTo({ url: '/pages/subscribe-plans/subscribe-plans' })
+4
查看文件
@@ -4,6 +4,10 @@
<text class="empty-icon">📱</text>
<view class="empty-text">还没有绑定设备</view>
<button class="btn-primary mt-30" bindtap="onAddDevice">扫码添加设备</button>
<view class="debug-actions" wx:if="{{devMode}}">
<view class="debug-label">🔧 调试工具</view>
<button class="btn-secondary btn-sm" bindtap="onMockBind">模拟绑定设备</button>
</view>
</view>
</view>
+4
查看文件
@@ -178,6 +178,10 @@ Page({
})
},
onBack: function () {
this.onStop()
},
onStop: function () {
var self = this
wx.showModal({
+1
查看文件
@@ -1,5 +1,6 @@
<view class="page">
<view class="page-header page-header-blue" style="padding-top: {{statusBarHeight + 24}}px;">
<view class="nav-back nav-back-light" bindtap="onBack"> 返回</view>
<view class="page-header-title">护理中</view>
<view class="page-header-subtitle">正在护理...</view>
</view>