| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 |
- const {
- createParameterDialogState,
- findParameterGroup,
- findParameterRegister,
- getActiveParameterGroup,
- getPageState,
- getSettingsPageState,
- getTransportPageState,
- getVisiblePageState,
- resolveActiveParamView
- } = require('../../features/parameter-groups/view-model.js')
- const {
- createDialogHandlers,
- createParameterGroupPoller,
- parameterGroupService
- } = require('../../features/parameter-groups/index.js')
- const settingsService = require('../../store/settings-store.js')
- const themeService = require('../../store/theme-store.js')
- const transport = require('../../transport/ble-core.js')
- const {
- createPageToast
- } = require('../../utils/page-toast.js')
- const {
- PARAMETER_REGISTER_DRAG_THRESHOLD_PX,
- buildActiveParameterRegisterRows,
- clampIndex,
- getFallbackDragRowOffsetPx,
- getWindowWidth,
- resolveDragTargetIndex
- } = require('../../features/parameter-groups/drag-view-model.js')
- function getParameterGroupsFromState(state = {}) {
- return state.parameterGroups || []
- }
- Page({
- data: {
- ...getPageState(),
- activeParamView: 'parameterGroups',
- activeParameterGroupId: '',
- activeParameterRegisterRows: [],
- parameterDialog: createParameterDialogState()
- },
- onTabItemTap() {
- this.backToParamsHome()
- },
- onLoad() {
- this.pageToast = createPageToast(this, this.data)
- this.parameterGroupPoller = createParameterGroupPoller(() => this.data)
- this.parameterGroupTouchStarts = {}
- this.parameterWindowWidth = getWindowWidth()
- parameterGroupService.init()
- themeService.init()
- settingsService.init()
- this.unsubscribeTheme = themeService.subscribe((themeState) => {
- this.setData(themeState)
- })
- this.unsubscribeTransport = transport.subscribe((transportState) => {
- this.setData(getTransportPageState(transportState))
- if (transportState.connectedDevice) {
- setTimeout(() => this.scheduleVisibleParameterAutoReads(), 0)
- } else {
- this.clearParameterAutoTimers()
- }
- })
- this.unsubscribeParameterGroups = parameterGroupService.subscribe((parameterState) => {
- const activeParameterGroup = getActiveParameterGroup(getParameterGroupsFromState(parameterState), this.data.activeParameterGroupId)
- this.setData({
- ...parameterState,
- activeParameterGroup,
- activeParameterRegisterRows: buildActiveParameterRegisterRows(activeParameterGroup, this.parameterRegisterDrag),
- activeParamView: this.data.activeParamView === 'parameterGroup' && !activeParameterGroup
- ? 'parameterGroups'
- : this.data.activeParamView
- })
- })
- this.unsubscribeSettings = settingsService.subscribe((settingsState) => {
- const protocolChanged = this.data.protocolMode && this.data.protocolMode !== settingsState.protocolMode
- const nextState = getSettingsPageState(this.data, settingsState)
- const activeParamView = protocolChanged ? 'parameterGroups' : nextState.activeParamView
- const parameterGroups = getParameterGroupsFromState(parameterGroupService.getState())
- const activeParameterGroupId = protocolChanged ? '' : this.data.activeParameterGroupId
- const activeParameterGroup = getActiveParameterGroup(parameterGroups, activeParameterGroupId)
- const safeActiveView = activeParamView === 'parameterGroup' && !activeParameterGroup
- ? 'parameterGroups'
- : activeParamView
- this.clearParameterAutoTimers()
- this.setData({
- ...nextState,
- parameterGroups,
- activeParameterGroupId,
- activeParamView: safeActiveView,
- activeParameterGroup,
- activeParameterRegisterRows: buildActiveParameterRegisterRows(activeParameterGroup, this.parameterRegisterDrag)
- })
- if (safeActiveView === 'parameterGroups' || safeActiveView === 'parameterGroup') {
- setTimeout(() => this.scheduleVisibleParameterAutoReads(), 0)
- } else {
- this.clearParameterAutoTimers()
- }
- })
- },
- onShow() {
- if (this.pageToast) {
- this.pageToast.setActive(true)
- }
- const pageState = getVisiblePageState(this.data)
- this.setData({
- ...pageState,
- activeParameterGroup: getActiveParameterGroup(getParameterGroupsFromState(pageState), this.data.activeParameterGroupId),
- activeParameterRegisterRows: buildActiveParameterRegisterRows(
- getActiveParameterGroup(getParameterGroupsFromState(pageState), this.data.activeParameterGroupId),
- this.parameterRegisterDrag
- )
- })
- this.pageToast.showFromState(pageState)
- this.scheduleVisibleParameterAutoReads()
- },
- onHide() {
- if (this.pageToast) {
- this.pageToast.setActive(false)
- }
- this.clearParameterRegisterDrag()
- this.clearParameterAutoTimers()
- },
- onUnload() {
- if (this.pageToast) {
- this.pageToast.destroy()
- this.pageToast = null
- }
- if (this.unsubscribeTheme) {
- this.unsubscribeTheme()
- this.unsubscribeTheme = null
- }
- if (this.unsubscribeTransport) {
- this.unsubscribeTransport()
- this.unsubscribeTransport = null
- }
- if (this.unsubscribeParameterGroups) {
- this.unsubscribeParameterGroups()
- this.unsubscribeParameterGroups = null
- }
- if (this.unsubscribeSettings) {
- this.unsubscribeSettings()
- this.unsubscribeSettings = null
- }
- this.clearParameterAutoTimers()
- },
- openParamView(event) {
- if (this.pageToast) this.pageToast.clear()
- this.closeParameterDraft()
- this.clearParameterRegisterDrag()
- const activeParamView = event.currentTarget.dataset.view
- if (!activeParamView) return
- this.setData({
- activeParamView
- })
- if (activeParamView === 'parameterGroups') {
- setTimeout(() => this.scheduleVisibleParameterAutoReads(), 0)
- }
- },
- openParameterGroup(event) {
- const groupId = event.currentTarget.dataset.groupId
- const group = findParameterGroup(getParameterGroupsFromState(this.data), groupId)
- if (!group) return
- if (this.pageToast) this.pageToast.clear()
- this.closeParameterDraft()
- this.setData({
- activeParameterGroup: group,
- activeParameterGroupId: groupId,
- activeParamView: 'parameterGroup',
- activeParameterRegisterRows: buildActiveParameterRegisterRows(group, this.parameterRegisterDrag)
- })
- },
- backToParamsHome() {
- if (this.pageToast) this.pageToast.clear()
- this.closeParameterDraft()
- this.clearParameterRegisterDrag()
- this.clearParameterAutoTimers()
- const activeParamView = resolveActiveParamView('', this.data)
- this.setData({
- activeParameterGroup: null,
- activeParameterGroupId: '',
- activeParamView,
- activeParameterRegisterRows: []
- })
- if (activeParamView === 'parameterGroups') {
- setTimeout(() => this.scheduleVisibleParameterAutoReads(), 0)
- }
- },
- noop() {},
- ...createDialogHandlers(parameterGroupService),
- async importParameterGroupsJson() {
- const count = await parameterGroupService.importJsonFromMessageFile()
- if (count && this.pageToast) this.pageToast.show(`已导入 ${count} 个寄存器组`)
- },
- async syncParameterGroups() {
- if (this.data.isModbusProtocol) return
- if (!this.data.connectedDevice) return
- const result = await parameterGroupService.syncFromStorageAccessCodeInfo({
- maxPacketLength: this.data.parameterMaxPacketLength
- })
- if (result && result.ok && this.pageToast) {
- const codeInfoAddressText = result.codeInfoAddressText || Number(result.codeInfoAddress || 0).toString(16).toUpperCase().padStart(4, '0')
- const codeInfoByteLengthText = result.codeInfoByteLengthText || Number(result.codeInfoByteLength || 0).toString(16).toUpperCase().padStart(4, '0')
- const addedCount = Number(result.addedGroups || 0) + Number(result.addedRegisters || 0)
- const updatedCount = Number(result.updatedGroups || 0) + Number(result.updatedRegisters || 0)
- const changedText = [
- addedCount ? `新增 ${addedCount}` : '',
- updatedCount ? `更新 ${updatedCount}` : ''
- ].filter(Boolean).join(',')
- this.pageToast.show(`同步完成 codeInfo 0x${codeInfoAddressText} / 0x${codeInfoByteLengthText},${result.structCount} 项${changedText ? `,${changedText}` : ''}`)
- }
- },
- async completeParameterStructs() {
- const result = await parameterGroupService.completeStructInstanceGroupsWithStructFile()
- if (result && result.completedCount && this.pageToast) {
- this.pageToast.show(`已补全 ${result.completedCount} 个寄存器组`)
- }
- },
- toggleParameterPolling() {
- if (this.data.isStorageAccessProtocol && !this.data.connectedDevice) return
- const enabled = !this.data.parameterAutoPollEnabled
- settingsService.setParameterAutoPollEnabled(enabled)
- if (enabled) {
- this.scheduleParameterAutoPoll(0)
- } else {
- this.clearParameterAutoTimers()
- }
- },
- async saveParameterGroupsJson() {
- const count = await parameterGroupService.saveJsonToChat()
- if (count && this.pageToast) this.pageToast.show(`已保存 ${count} 个寄存器组`)
- },
- toggleParameterGroup(event) {
- const groupId = event.currentTarget.dataset.groupId
- if (this.parameterGroupLongPressGuard === groupId) {
- this.parameterGroupLongPressGuard = ''
- return
- }
- const group = findParameterGroup(getParameterGroupsFromState(this.data), groupId)
- if (!group) return
- parameterGroupService.setGroupExpanded(groupId, !group.expanded)
- },
- onParameterRegisterValueInput(event) {
- parameterGroupService.updateRegisterValue(
- event.currentTarget.dataset.groupId,
- Number(event.currentTarget.dataset.index),
- event.detail.value
- )
- },
- async onParameterRegisterValueBlur(event) {
- const groupId = event.currentTarget.dataset.groupId
- const registerIndex = Number(event.currentTarget.dataset.index)
- try {
- parameterGroupService.validateRegisterInputValue(groupId, registerIndex, event.detail.value)
- } catch (error) {
- if (this.pageToast) this.pageToast.show(error.message || '输入值无效', 'error')
- return
- }
- if (!this.data.isStorageAccessProtocol || !this.data.connectedDevice) return
- const group = findParameterGroup(getParameterGroupsFromState(this.data), groupId)
- const register = group && group.registers ? group.registers[registerIndex] : null
- if (!group || !register || !register.isDirty || !group.writable || group.addressOverflow) return
- this.clearParameterAutoTimers()
- const ok = await parameterGroupService.writeRegister(groupId, registerIndex)
- if (this.data.parameterAutoPollEnabled) {
- this.scheduleParameterAutoPoll(this.data.parameterPollInterval || 100)
- }
- if (ok && this.pageToast) {
- this.pageToast.show(`${register.name || '变量'}已写入`)
- }
- },
- async readParameterGroup(event) {
- if (!this.data.connectedDevice) return
- const groupId = event.currentTarget.dataset.groupId
- const ok = await parameterGroupService.readGroup(groupId, {
- maxPacketLength: this.data.parameterMaxPacketLength
- })
- if (ok && this.pageToast) this.pageToast.show('参数组读取完成')
- },
- async writeParameterGroup(event) {
- if (!this.data.connectedDevice) return
- const groupId = event.currentTarget.dataset.groupId
- const ok = await parameterGroupService.writeGroup(groupId)
- if (ok && this.pageToast) this.pageToast.show('参数组写入完成')
- },
- onParameterGroupTouchStart(event) {
- const groupId = event.currentTarget.dataset.groupId
- const touch = (event.changedTouches || [])[0]
- if (!groupId || !touch) return
- this.parameterGroupTouchStarts[groupId] = touch.clientX
- },
- onParameterGroupTouchEnd(event) {
- const groupId = event.currentTarget.dataset.groupId
- const group = findParameterGroup(getParameterGroupsFromState(this.data), groupId)
- const touch = (event.changedTouches || [])[0]
- const startX = this.parameterGroupTouchStarts[groupId]
- if (!groupId || !group || group.expanded || !touch || !Number.isFinite(startX)) return
- const deltaX = touch.clientX - startX
- if (deltaX > 42) {
- parameterGroupService.setGroupDeleteVisible(groupId, true)
- } else if (deltaX < -24) {
- parameterGroupService.setGroupDeleteVisible(groupId, false)
- }
- },
- onParameterRegisterDragStart(event) {
- const touch = (event.changedTouches || [])[0]
- if (!touch) return
- const groupId = event.currentTarget.dataset.groupId
- const index = Number(event.currentTarget.dataset.index)
- const activeParameterGroup = findParameterGroup(getParameterGroupsFromState(this.data), groupId)
- if (!groupId || !activeParameterGroup || !Number.isInteger(index)) return
- this.parameterRegisterDrag = {
- groupId,
- index,
- moved: false,
- rowCenters: [],
- rowOffset: getFallbackDragRowOffsetPx(this.parameterWindowWidth),
- startY: touch.clientY,
- targetIndex: index,
- translateY: 0
- }
- if (this.data.activeParameterGroupId === groupId) {
- this.setData({
- activeParameterRegisterRows: buildActiveParameterRegisterRows(activeParameterGroup, this.parameterRegisterDrag)
- })
- }
- this.measureParameterRegisterRows(this.parameterRegisterDrag)
- },
- onParameterRegisterDragMove(event) {
- const touch = (event.changedTouches || [])[0]
- if (!touch || !this.parameterRegisterDrag) return
- const drag = this.parameterRegisterDrag
- const group = findParameterGroup(getParameterGroupsFromState(this.data), drag.groupId)
- if (!group) return
- const translateY = Math.round(touch.clientY - drag.startY)
- const moved = Math.abs(translateY) > PARAMETER_REGISTER_DRAG_THRESHOLD_PX
- const targetIndex = moved
- ? resolveDragTargetIndex(drag, touch.clientY, group.registers.length)
- : drag.index
- if (
- drag.translateY === translateY
- && drag.moved === moved
- && drag.targetIndex === targetIndex
- ) {
- return
- }
- drag.translateY = translateY
- drag.moved = moved
- drag.targetIndex = targetIndex
- if (this.data.activeParameterGroupId === group.id) {
- this.setData({
- activeParameterRegisterRows: buildActiveParameterRegisterRows(group, drag)
- })
- }
- },
- onParameterRegisterDragEnd(event) {
- const drag = this.parameterRegisterDrag
- this.parameterRegisterDrag = null
- if (!drag || !drag.groupId) return
- const group = findParameterGroup(getParameterGroupsFromState(this.data), drag.groupId)
- if (!group) return
- if (this.data.activeParameterGroupId === group.id) {
- this.setData({
- activeParameterRegisterRows: buildActiveParameterRegisterRows(group, null)
- })
- }
- if (!drag.moved) return
- const targetIndex = clampIndex(
- Number(drag.targetIndex) || drag.index,
- 0,
- group.registers.length - 1
- )
- if (targetIndex === drag.index) return
- const updatedGroup = parameterGroupService.reorderRegister(drag.groupId, drag.index, targetIndex)
- if (!updatedGroup) return
- this.parameterRegisterLongPressGuard = `${drag.groupId}:${targetIndex}`
- setTimeout(() => {
- if (this.parameterRegisterLongPressGuard === `${drag.groupId}:${targetIndex}`) {
- this.parameterRegisterLongPressGuard = ''
- }
- }, 260)
- if (this.data.activeParameterGroupId === updatedGroup.id) {
- this.setData({
- activeParameterGroup: updatedGroup,
- activeParameterRegisterRows: buildActiveParameterRegisterRows(updatedGroup, null)
- })
- }
- },
- onParameterRegisterDragCancel() {
- const drag = this.parameterRegisterDrag
- this.parameterRegisterDrag = null
- if (!drag || !drag.groupId) return
- const group = findParameterGroup(getParameterGroupsFromState(this.data), drag.groupId)
- if (!group || this.data.activeParameterGroupId !== group.id) return
- this.setData({
- activeParameterRegisterRows: buildActiveParameterRegisterRows(group, null)
- })
- },
- deleteParameterGroup(event) {
- const groupId = event.currentTarget.dataset.groupId
- this.clearParameterAutoTimer(groupId)
- parameterGroupService.removeGroup(groupId)
- if (this.data.activeParameterGroupId === groupId) {
- this.setData({
- activeParameterGroup: null,
- activeParameterGroupId: '',
- activeParamView: 'parameterGroups'
- })
- }
- if (this.pageToast) this.pageToast.show('寄存器组已删除')
- },
- clearParameterAutoTimer(groupId) {
- if (this.parameterGroupPoller) this.parameterGroupPoller.clearTimer(groupId)
- },
- clearParameterAutoTimers() {
- if (this.parameterGroupPoller) this.parameterGroupPoller.clearAll()
- },
- scheduleVisibleParameterAutoReads() {
- if (this.parameterGroupPoller) this.parameterGroupPoller.scheduleVisible()
- },
- scheduleParameterAutoPoll(delay) {
- if (this.parameterGroupPoller) this.parameterGroupPoller.schedule(delay)
- },
- clearParameterRegisterDrag() {
- if (!this.parameterRegisterDrag) return
- const drag = this.parameterRegisterDrag
- this.parameterRegisterDrag = null
- const group = findParameterGroup(getParameterGroupsFromState(this.data), drag.groupId)
- this.setData({
- activeParameterRegisterRows: buildActiveParameterRegisterRows(group, null)
- })
- },
- measureParameterRegisterRows(dragReference) {
- const query = this.createSelectorQuery()
- query.selectAll('.generic-register-row').boundingClientRect((rects) => {
- if (!this.parameterRegisterDrag || this.parameterRegisterDrag !== dragReference) return
- if (!Array.isArray(rects) || !rects.length) return
- dragReference.rowCenters = rects.map((rect) => Number(rect.top || 0) + Number(rect.height || 0) / 2)
- dragReference.rowOffset = Math.max(
- 1,
- Math.round(Number((rects[dragReference.index] || {}).height) || dragReference.rowOffset || 0)
- )
- const group = findParameterGroup(getParameterGroupsFromState(this.data), dragReference.groupId)
- if (!group || this.data.activeParameterGroupId !== group.id) return
- this.setData({
- activeParameterRegisterRows: buildActiveParameterRegisterRows(group, dragReference)
- })
- }).exec()
- }
- })
|