Files
yangxiangyuan d4bf3627fd feat: 新增运动节拍训练工具套件与子工具页面
新增运动节拍RepClock全套小程序页面、后端API与数据库服务,新增subhub子工具汇总页面,优化全局主页样式与配置,为web静态资源添加版本缓存参数,补充配套调试脚本
2026-09-09 14:43:06 +08:00

144 lines
4.0 KiB
JavaScript

const api = require('../../api.js')
Page({
data: {
loading: true,
kits: [],
appNameZh: 'MilesYang时光助手',
clipVisible: false,
clipText: '',
clipCount: 0,
clipLines: 0,
clipPreview: '',
},
onLoad() { this.refresh() },
onShow() { this.checkClipboard() },
onPullDownRefresh() {
this.refresh().finally(() => wx.stopPullDownRefresh())
},
simpleHash(str) {
const s = String(str || '')
let h1 = 0x811c9dc5
let h2 = 0xdeadbeef
for (let i = 0; i < s.length; i++) {
const c = s.charCodeAt(i)
h1 = Math.imul(h1 ^ c, 16777619)
h2 = Math.imul(h2 ^ c, 2246822519)
}
h1 = (h1 ^ h1 >>> 16) >>> 0
h2 = (h2 ^ h2 >>> 15) >>> 0
return h1.toString(36) + h2.toString(36)
},
async refresh() {
this.setData({ loading: true })
try {
const res = await api.core.getMeta()
if (res && res.appNameZh) this.setData({ appNameZh: res.appNameZh })
} catch (e) {}
this.setData({
kits: this.buildKits(),
loading: false,
})
},
buildKits() {
return [
{
id: 'personal_collect',
name: '微信收藏夹',
description: '聊天图片 / 文件 / 文字收藏,标签搜索,软删除可追溯。',
icon: '📁',
path: '/kits/personal_collect/pages/list/list',
meta: 'API: /api/mp_personal_collect/ · DB: mp_personal_collect.db',
},
{
id: 'rep_clock',
name: '运动节拍 RepClock',
description: 'HIIT / Yoga / 拉伸节奏倒计时,锚点时钟 + 女声播报。',
icon: '⏱️',
path: '/kits/rep_clock/pages/cards/cards',
meta: 'API: /api/mp_rep_clock/ · DB: mp_rep_clock.db',
},
]
},
async onKitTap(e) {
const id = (e.currentTarget.dataset.id || '').trim()
const path = (e.currentTarget.dataset.path || '').trim()
if (!path) { wx.showToast({ title: '功能开发中', icon: 'none' }); return }
try { await api.core.setActiveKit(id) } catch (e) {}
wx.navigateTo({
url: path,
fail: () => wx.showToast({ title: '打开失败', icon: 'none' }),
})
},
checkClipboard() {
try {
const enable = wx.getStorageSync('mp_ta_clip_enable')
if (enable === false || enable === 'false') return
} catch (e) {}
wx.getClipboardData({
success: (res) => {
const text = (res.data || '').trim()
if (text.length < 6 || text.length > 30000) return
const hash = this.simpleHash(text)
try {
const last = wx.getStorageSync('mp_ta_clip_hash')
if (last === hash) return
wx.setStorageSync('mp_ta_clip_hash', hash)
} catch (e) {}
const count = text.length
const lines = text.split('\n').length
const preview = text.length > 220 ? text.slice(0, 220) + '\n\n……' : text
this.setData({
clipVisible: true,
clipText: text,
clipCount: count,
clipLines: lines,
clipPreview: preview,
})
},
fail: () => {}
})
},
onClipCollect() {
const text = this.data.clipText || ''
if (!text) { this.setData({ clipVisible: false }); return }
try { wx.setStorageSync('mp_ta_clip_text', text) } catch (e) {}
this.setData({ clipVisible: false })
wx.navigateTo({
url: '/kits/personal_collect/pages/edit/edit?mode=new',
fail: () => { wx.showToast({ title: '打开失败', icon: 'none' }) }
})
},
onClipCancel() {
this.setData({ clipVisible: false })
},
onClipDismissForever() {
wx.showModal({
title: '不再检测剪贴板?',
content: '关闭后可在未来任意新增收藏页面时重新开启。',
confirmText: '不再提示',
cancelText: '保留',
success: (r) => {
if (r.confirm) {
try { wx.setStorageSync('mp_ta_clip_enable', false) } catch (e) {}
this.setData({ clipVisible: false })
wx.showToast({ title: '已关闭检测', icon: 'none' })
}
}
})
},
noop() {},
})