@macroui/queue-stream
v0.1.0
Published
openretail 排队 (queue) 实时推送客户端 - SSE 优先 + 轮询降级 + 自动重连
Maintainers
Readme
@openretail/queue-stream
openretail 排队 (queue) 模块的实时推送客户端, 供 or-admin / or-merchant-app / or-customer-app 共同使用.
特性
- SSE 优先: 浏览器/H5 自动用
EventSource订阅/admin/oms/queue/stream - 降级 polling: 小程序 / 原生无
EventSource时自动降级到setInterval轮询 - 自动重连: SSE 断线 3s 后自动重试, 连续失败 N 次后降级到 polling
- 类型安全: 完整 TS 类型导出
- 零依赖: 不依赖 axios / dayjs, 仅
vue作为可选 peer
安装
# or-admin (Vue 3, 支持 npm)
npm install @openretail/queue-stream
# uni-app x 项目 (or-merchant-app / or-customer-app)
# 通过 npm 安装后, 用 @openretail/queue-stream/adapters/uni-app 适配器
npm install @openretail/queue-stream用法
Vue 3 组合式 (推荐 or-admin)
import { useQueueStream } from '@openretail/queue-stream'
const { state, latestEvent } = useQueueStream({
baseUrl: '/api',
path: '/admin/oms/queue/stream',
headers: () => ({ 'x-token': token }),
pollIntervalMs: 3000,
onEvent: (e) => {
console.log('收到排队事件:', e.type, e.queueNo)
refreshList()
}
})
// state.value.state: 'idle' | 'connecting' | 'connected' | 'reconnecting' | 'fallback-polling' | 'closed'
// state.value.mode: 'sse' | 'polling'纯 JS 类 (任意框架)
import { QueueStreamClient } from '@openretail/queue-stream'
const client = new QueueStreamClient({
baseUrl: '/api',
path: '/merchant/oms/queue/stream',
storeId: 14,
headers: { 'x-token': token },
onEvent: (e) => console.log(e),
onStateChange: (s) => console.log(s)
})
client.start()
// ... 卸载时 client.stop()uni-app x 小程序 (or-merchant-app / or-customer-app)
小程序没有 EventSource, 也没有 window.fetch. 用内置适配器:
// pages/queue/list.uvue
import { QueueStreamClient, createUniAppAdapter } from '@openretail/queue-stream'
import { createUniAppAdapter } from '@openretail/queue-stream/adapters/uni-app'
const token = ref('')
const client = new QueueStreamClient({
baseUrl: '/api',
path: '/merchant/oms/queue/stream',
storeId: 14,
mode: 'polling', // 强制 polling, 因为没有 EventSource
pollIntervalMs: 3000,
pollUrl: '/api/merchant/oms/queue/list?status=0',
headers: () => ({ 'x-token': token.value }),
requestAdapter: createUniAppAdapter(() => ({ 'x-token': token.value })),
onEvent: (e) => {
console.log('排队事件', e.type, e.queueNo)
refreshList()
}
})
onMounted(() => client.start())
onBeforeUnmount(() => client.stop())
createUniAppAdapter(headerProvider)内部包装uni.request, 返回符合客户端期望的{ status, json() }形态, 业务无需关心底层差异.
配置
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
| baseUrl | string | /api | API 基础路径 |
| path | string | /admin/oms/queue/stream | SSE 端点路径 |
| storeId | number | - | 门店过滤 (商家/C端用) |
| headers | object | () => object | - | fetch / EventSource 头 |
| pollIntervalMs | number | 3000 | polling 间隔 |
| sseReconnectMs | number | 3000 | SSE 重连间隔 |
| pollUrl | string | 自动推断 | polling 拉取的 URL |
| mode | 'sse' \| 'polling' \| 'auto' | auto | 强制模式 |
| fallbackAfterFailures | number | 3 | 失败 N 次后降级 polling |
| debug | boolean | false | 调试日志 |
| requestAdapter | function | - | 自定义请求适配器 (小程序必须传 createUniAppAdapter) |
事件 payload
interface QueueEvent {
type: 'create' | 'call' | 'pass' | 'seat' | 'cancel'
storeId: number
orgId: number
queueId: number
queueNo: string
status: 0 | 1 | 2 | 3 | 4 // 0排队 1叫号 2过号 3入座 4取消
name: string
phone: string
people: number
timestamp: number // 毫秒
}License
MIT
