var ble = require('../../services/ble') var i18n = require('../../i18n/index') // Manual care page: user directly picks a care function (-> single light // wavelength), regions and duration, then starts — skipping the smart scan. // // Care function -> wavelength (protocol WAVELENGTH: IR=1, R=2, UV=3, Y=4). // SINGLE light per session: buildVendorCommand only lights one wavelength. // FUTURE EXTENSION: a composite/multi-light care mode would require the vendor // command builder to accept several wavelengths at once — not implemented here. Page({ data: { statusBarHeight: 44, // fixed safe brightness for care sessions: 140 ≈ 55% (护理中档位). // Do NOT expose a brightness slider (safety); the hardware also enforces // its own current/thermal limits regardless of this value. brightness: 140, functions: [ { id: 'rejuvenate', wavelength: 2, wl: 'red', color: '#E8503A' }, { id: 'acne', wavelength: 3, wl: 'uv', color: '#7C4DFF' }, { id: 'eventone', wavelength: 4, wl: 'yellow', color: '#F5B841' }, { id: 'revitalize', wavelength: 1, wl: 'infrared', color: '#8B2E3C' } ], selectedFunctionId: 'rejuvenate', selectedWavelength: 2, // region mask mapping identical to treatment-setup: 右=0x01 左=0x02 上=0x04 中=0x08 下=0x10 regions: [ { key: 'right', mask: 0x01, checked: true }, { key: 'left', mask: 0x02, checked: true }, { key: 'top', mask: 0x04, checked: true }, { key: 'middle', mask: 0x08, checked: true }, { key: 'bottom', mask: 0x10, checked: true } ], // safety: a single session must NOT exceed 10 minutes (hardware caps at 10). durations: [5, 10], selectedMinutes: 10, durationOptions: [], submitting: false, error: '' }, onLoad: function () { var app = getApp() if (app && app.globalData && app.globalData.statusBarHeight) { this.setData({ statusBarHeight: app.globalData.statusBarHeight }) } }, onShow: function () { i18n.bind(this) this.refreshDurationOptions() }, // Duration labels carry a dynamic number, which WXML cannot substitute, so // build the final strings in JS. Re-run on every onShow to follow locale. refreshDurationOptions: function () { var options = this.data.durations.map(function (min) { return { min: min, label: i18n.t('manual.durationUnit', { min: min }) } }) this.setData({ durationOptions: options }) }, onBack: function () { wx.navigateBack({ fail: function () { wx.reLaunch({ url: '/pages/index/index' }) } }) }, onSelectFunction: function (e) { var id = e.currentTarget.dataset.id var funcs = this.data.functions var wavelength = this.data.selectedWavelength for (var i = 0; i < funcs.length; i++) { if (funcs[i].id === id) { wavelength = funcs[i].wavelength break } } this.setData({ selectedFunctionId: id, selectedWavelength: wavelength }) }, onToggleRegion: function (e) { var idx = e.currentTarget.dataset.idx var regions = this.data.regions regions[idx].checked = !regions[idx].checked this.setData({ regions: regions }) }, onSelectDuration: function (e) { var min = parseInt(e.currentTarget.dataset.min, 10) this.setData({ selectedMinutes: min }) }, onStart: function () { var self = this if (!ble.isConnected()) { self.setData({ error: i18n.t('common.deviceNotConnected') }) return } var mask = 0 self.data.regions.forEach(function (r) { if (r.checked) mask |= r.mask }) if (mask === 0) { wx.showToast({ title: i18n.t('manual.noRegionSelected'), icon: 'none' }) return } var wavelength = self.data.selectedWavelength var durationMs = self.data.selectedMinutes * 60000 self.setData({ submitting: true, error: '' }) ble.setParams({ region_mask: mask, wavelength: wavelength, brightness: self.data.brightness, duration_ms: durationMs, mode: 0, control: 0x02 }).then(function () { return ble.startTreatment(mask) }).then(function () { self.setData({ submitting: false }) wx.redirectTo({ url: '/pages/treating/treating?regions=' + mask + '&wavelength=' + wavelength + '&duration=' + durationMs + '&mode=0' }) }).catch(function (err) { self.setData({ submitting: false, error: (err && err.error_msg) || i18n.t('manual.startFailed') }) }) } })