Files
hzdyjs/mobile/src/utils/sse.js
T
zlwu 28232d5d46 feat: 移动端开发规范重大更新
- 🔥 完全重写 .cursor/cursorrules-mobile.md (940行)
  * 基于实际mobile工程Vue 3.4.21+uniapp+uview-plus架构
  * 移除所有JeeSite相关内容,精准匹配实际项目
  * 新增11个完整章节:技术栈、项目结构、页面开发、组件规范等

- 📚 创建完整规范文档 docs/开发文档/移动端开发规范总结.md (800+行)
  * 涵盖从项目架构到部署的全流程指导
  * 提供可直接使用的页面和组件模板
  * 包含现代CSS变量设计系统和用户体验优化

- 🔄 同步更新主配置文件 .cursorrules
  * 更新移动端技术栈描述
  * 调整为Vue 3.4.21+uniapp+uview-plus 3.4.45架构

- 📝 完善变更记录
  * 详细记录规范更新背景和技术价值
  * 为后续维护提供完整历史记录

核心价值:解决规范与实际项目不匹配问题,为Cursor AI提供准确的移动端开发上下文,确保生成代码完全符合实际项目架构。
2025-07-04 15:51:33 +08:00

180 lines
4.0 KiB
JavaScript

// SSE (Server-Sent Events) 实时数据工具
class SSEClient {
constructor() {
this.eventSource = null
this.listeners = {}
this.isConnected = false
}
// 连接SSE
connect(url, options = {}) {
if (this.eventSource) {
this.disconnect()
}
try {
// 在H5环境下使用原生 EventSource
if (typeof EventSource !== 'undefined') {
this.eventSource = new EventSource(url)
this.eventSource.onopen = () => {
this.isConnected = true
console.log('SSE连接已建立')
this.emit('connected')
}
this.eventSource.onmessage = (event) => {
try {
const data = JSON.parse(event.data)
this.emit('message', data)
} catch (e) {
this.emit('message', event.data)
}
}
this.eventSource.onerror = (error) => {
this.isConnected = false
console.error('SSE连接错误:', error)
this.emit('error', error)
// 自动重连
if (options.autoReconnect !== false) {
setTimeout(() => {
this.connect(url, options)
}, options.reconnectDelay || 5000)
}
}
} else {
// 在非H5环境下使用轮询模拟
this.startPolling(url, options)
}
} catch (error) {
console.error('SSE连接失败:', error)
this.emit('error', error)
}
}
// 轮询模拟SSE(用于小程序等不支持SSE的环境)
startPolling(url, options = {}) {
const interval = options.pollingInterval || 10000 // 默认10秒
const poll = async () => {
try {
const response = await uni.request({
url: url,
method: 'GET',
header: {
Accept: 'application/json',
},
})
if (response.statusCode === 200) {
this.emit('message', response.data)
}
} catch (error) {
console.error('轮询请求失败:', error)
this.emit('error', error)
}
}
this.pollingTimer = setInterval(poll, interval)
this.isConnected = true
this.emit('connected')
// 立即执行一次
poll()
}
// 断开连接
disconnect() {
if (this.eventSource) {
this.eventSource.close()
this.eventSource = null
}
if (this.pollingTimer) {
clearInterval(this.pollingTimer)
this.pollingTimer = null
}
this.isConnected = false
this.emit('disconnected')
}
// 添加事件监听
on(event, callback) {
if (!this.listeners[event]) {
this.listeners[event] = []
}
this.listeners[event].push(callback)
}
// 移除事件监听
off(event, callback) {
if (this.listeners[event]) {
const index = this.listeners[event].indexOf(callback)
if (index > -1) {
this.listeners[event].splice(index, 1)
}
}
}
// 触发事件
emit(event, data) {
if (this.listeners[event]) {
this.listeners[event].forEach((callback) => {
try {
callback(data)
} catch (error) {
console.error('事件回调执行错误:', error)
}
})
}
}
// 获取连接状态
getConnectionState() {
return this.isConnected
}
}
// 创建全局SSE实例
export const sseClient = new SSEClient()
// 消息推送管理
export const messageManager = {
// 订阅消息
subscribe(type, callback) {
sseClient.on('message', (data) => {
if (data.type === type) {
callback(data.payload)
}
})
},
// 取消订阅
unsubscribe(type, callback) {
sseClient.off('message', callback)
},
// 连接实时消息服务
connect(userId) {
const sseUrl = `${
process.env.NODE_ENV === 'development'
? 'http://localhost:3000'
: 'https://your-api-domain.com'
}/sse/messages?userId=${userId}`
sseClient.connect(sseUrl, {
autoReconnect: true,
reconnectDelay: 5000,
pollingInterval: 10000,
})
},
// 断开连接
disconnect() {
sseClient.disconnect()
},
}