Files
2026-04-21 13:46:20 +08:00

323 lines
9.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 首页逻辑 - 深色主题信息流
const app = getApp()
Page({
data: {
// 用户信息
hasUserInfo: false,
openId: '',
phoneNumber: '',
unionId: '',
locationInfo: null,
deviceInfo: null,
systemInfo: null,
networkType: '',
wxVersion: '',
accountInfo: null,
clipboardData: null,
// 时间显示
currentTime: '',
yesterdayTime: '',
// 轮播Banner数据 - 蓝色主题
banners: [
{ id: 1, tag: '健康科普', title: '在多才和多艺之间\n我选择了多肉~', desc: '医生,我喝水都要胖,咋个整?', image: '' },
{ id: 2, tag: '专家讲座', title: '春季养生指南:\n中医教你调理身体', desc: '', image: '' }
],
// 轮播Banner数据 - 红色喜报主题
redBanners: [
{ id: 1, title: '四川省人民医院高质量发展跃上新台阶,成功迈入全国公立医院第一方阵!', image: '' }
],
websocketConnected: false,
version: app.globalData.version || '1.0.0',
socketTask: null,
},
onLoad() {
this.updateTimeDisplay()
this.loadStoredInfo()
this.initWebSocketSafe()
},
onShow() {
this.updateTimeDisplay()
this.setTabBarActive()
if (this.data.hasUserInfo) this.loadStoredInfo()
},
// ==============================================
// 加载本地存储的信息
// ==============================================
loadStoredInfo() {
const openId = wx.getStorageSync('openId') || ''
const phoneNumber = wx.getStorageSync('phoneNumber') || ''
const deviceInfo = app.getDeviceInfo?.() || null
this.setData({ openId, phoneNumber, deviceInfo })
if (openId) {
this.setData({ hasUserInfo: true })
}
// 获取网络状态
app.getNetworkType?.((networkType) => {
if (networkType) this.setData({ networkType })
})
// 获取位置(需要授权)
app.getLocation?.((locationInfo) => {
if (locationInfo) this.setData({ locationInfo })
})
// 获取小程序信息
try {
const accountInfo = wx.getAccountInfoSync()
this.setData({ accountInfo })
} catch (error) {
console.error('获取小程序信息失败:', error)
this.setData({ accountInfo: null })
}
// 获取剪贴板信息(需要授权)
wx.getClipboardData({
success: (res) => {
this.setData({ clipboardData: res.data })
},
fail: (error) => {
console.error('获取剪贴板信息失败:', error)
this.setData({ clipboardData: null })
}
})
// 获取微信版本信息
try {
const systemInfo = wx.getSystemInfoSync()
this.setData({ wxVersion: systemInfo.version, systemInfo })
} catch (error) {
console.error('获取微信版本信息失败:', error)
this.setData({ wxVersion: null, systemInfo: null })
}
// 获取UnionID个人小程序无法获取
this.setData({ unionId: '无法获取(需企业资质)' })
// 获取手机号(个人小程序无法获取)
if (!phoneNumber) {
this.setData({ phoneNumber: '无法获取(需企业资质)' })
}
},
// ==============================================
// 登录:通过 WebSocket 发 wechat_login收到 openid 后存本地
// ==============================================
onLogin() {
// 确保 WebSocket 已连接
if (!this.data.socketTask || !this.data.websocketConnected) {
// 先重连
this.initWebSocketSafe()
setTimeout(() => this._doLogin(), 1500)
return
}
this._doLogin()
},
_doLogin() {
if (!this.data.websocketConnected) {
wx.showToast({ title: '连接中...', icon: 'none' })
return
}
wx.login({
success: (res) => {
if (!res.code) {
wx.showToast({ title: '微信登录失败', icon: 'none' })
return
}
// 记录待处理登录(收到 wechat_login_ret 时判断)
this._pendingLogin = true
this.data.socketTask.send({
data: JSON.stringify({
type: 'wechat_login',
data: { code: res.code }
}),
fail: () => {
this._pendingLogin = false
wx.showToast({ title: '发送失败', icon: 'none' })
}
})
},
fail:
// ==============================================
// 获取手机号button open-type="getPhoneNumber"
// ==============================================
onGetPhoneNumber(e) {
// 检查是否有加密数据(旧版方式,个人小程序可用)
const { encryptedData, iv, code } = e.detail
if (!encryptedData || !iv) {
wx.showToast({ title: '请允许授权', icon: 'none' })
return
}
// 必须先登录有 openid
const openid = this.data.openId || wx.getStorageSync('openId')
if (!openid) {
wx.showToast({ title: '请先登录', icon: 'none' })
return
}
// 确保 WebSocket 连接
if (!this.data.websocketConnected) {
wx.showToast({ title: '连接中...', icon: 'none' })
this.initWebSocketSafe()
setTimeout(() => {
this._sendPhoneDecrypt(openid, encryptedData, iv)
}, 1500)
return
}
this._sendPhoneDecrypt(openid, encryptedData, iv)
},
_sendPhoneDecrypt(openid, encryptedData, iv) {
if (!this.data.websocketConnected) {
wx.showToast({ title: 'WebSocket 未连接', icon: 'none' })
return
}
this._pendingPhone = true
this.data.socketTask.send({
data: JSON.stringify({
type: 'wechat_decrypt_phone',
data: { openid, encryptedData, iv }
}),
fail: () => {
this._pendingPhone = false
wx.showToast({ title: '发送失败', icon: 'none' })
}
})
},
// ==============================================
// 时间显示
// ==============================================
updateTimeDisplay() {
const now = new Date()
const m = now.getMonth() + 1
const d = now.getDate()
const h = now.getHours()
const mm = String(now.getMinutes()).padStart(2, '0')
const period = h >= 12 ? '下午' : '上午'
const displayH = h > 12 ? h - 12 : h
this.setData({
currentTime: `${m}${d}${period}${displayH}:${mm}`,
yesterdayTime: `昨天 晚上8:36`
})
},
// ==============================================
// TabBar 选中
// ==============================================
setTabBarActive() {
if (this.getTabBar) this.getTabBar()?.setData({ currentTab: 0 })
},
// ==============================================
// 新闻点击
// ==============================================
onNewsTap(e) {
const id = e.currentTarget.dataset.id
console.log('点击新闻:', id)
wx.showToast({ title: '加载中...', icon: 'none' })
},
// ==============================================
// WebSocket 安全版(防重复连接、防崩溃)
// ==============================================
initWebSocketSafe() {
if (this.data.socketTask) return
const socket = wx.connectSocket({ url: app.globalData.websocketUrl })
this.setData({ socketTask: socket })
socket.onOpen(() => {
this.setData({ websocketConnected: true })
socket.send({
data: JSON.stringify({
type: 'auth',
userId: app.globalData.userInfo?.nickName || 'anonymous',
deviceId: app.globalData.systemInfo?.model || '',
timestamp: Date.now()
})
})
})
socket.onMessage(msg => {
try {
const data = JSON.parse(msg.data)
this.handleWebSocketMessage(data)
} catch (e) {}
})
socket.onClose(() => {
this.setData({ websocketConnected: false, socketTask: null })
setTimeout(() => this.initWebSocketSafe(), 3000)
})
socket.onError(() => {
this.setData({ websocketConnected: false, socketTask: null })
})
},
handleWebSocketMessage(data) {
switch (data.type) {
case 'wechat_login_ret':
// 收到登录响应(可能比 send 回调更早或更晚到达)
if (data.data?.openid) {
wx.setStorageSync('openId', data.data.openid)
this.setData({ openId: data.data.openid, hasUserInfo: true })
wx.showToast({ title: '登录成功', icon: 'success' })
} else {
wx.showToast({ title: '登录失败:' + (data.data?.error || '未知'), icon: 'none' })
}
this._pendingLogin = false
break
case 'ai_message':
// AI 回复(聊天页使用)
if (this.handleAiMessage) this.handleAiMessage(data)
break
case 'wechat_decrypt_phone_ret':
// 手机号解密响应
if (data.data?.phone) {
wx.setStorageSync('phoneNumber', data.data.phone)
this.setData({ phoneNumber: data.data.phone })
wx.showToast({ title: '绑定成功', icon: 'success' })
} else {
wx.showToast({ title: '获取失败:' + (data.data?.error || '未知'), icon: 'none' })
}
this._pendingPhone = false
break
case 'pong':
break
default:
break
}
},
// ==============================================
// 跳转聊天页
// ==============================================
goToChat() {
wx.navigateTo({ url: '/pages/chat/chat' })
},
// ==============================================
// 跳转任务页
// ==============================================
goToTask() {
wx.navigateTo({ url: '/pages/task/task' })
}
})