基于 Java Spring Boot + Vue3 + uni-app 打造「私域直播」能力(附源码)
如何用 Spring Boot + Vue3 + uni-app 落地一套可互动、可带货的 私域直播?本文基于已运行项目,讲清开播、倒计时、货架、IM 邀请到结束复盘的完整链路——面向品牌与社群,可控、可演示、可二次开发。
能力栈:内容笔记 + 腾讯云 TRTC + WebSocket + 商城货架 + IM 分享卡片,与社区、消息、市集同一套工程。
线上演示
- 移动端 H5:http://8.146.211.120:8081/
- 管理后台:http://8.146.211.120:8088/
手机浏览器或桌面 DevTools 切移动端预览;底部「+」→「开直播」/「音视频聊天室」。

一、什么是「私域直播」
| 维度 | 公域直播平台 | 本项目私域直播 |
|---|---|---|
| 流量来源 | 平台推荐 | 发现流、关注、私信/群聊邀请卡、房间链接 |
| 用户关系 | 弱关系为主 | 粉丝、互关、群成员等强关系 |
| 成交路径 | 平台店铺 | 自有商城 + 直播货架跳转下单 |
| 试用控制 | 平台规则 | 单场最长分钟 + 页面中部倒计时 |
闭环一句话:内容种草 → 关系触达(IM)→ 现场转化(直播)→ 下单履约(商城)。

二、技术选型
| 端 | 技术 | 直播职责 |
|---|---|---|
| 移动端 | uni-app + Vue3 | 开播页、直播间、结束页、Hybrid TRTC、倒计时与分享 |
| 管理端 | Vue3 + Element Plus | 内容运营、商品、TRTC / 时长 / 敏感词配置 |
| 后端 | Spring Boot 2.x(JDK 8) | UserSig、状态机、心跳、货架、公屏、体验关播 Job |
模块拆分示意:
backend/
├── member # 内容、直播、IM、语聊
├── mall # 商城(货架跳转下单)
├── pay # 支付
├── infra # 配置、文件、WebSocket、定时任务
└── system # 权限 / 租户
admin-ui/ # Vue3 管理端
mobile/ # uni-app
sql/ # yudao-full.sql + quartz.sql + xhs-init.sql
三、开播与进房
支持 视频直播 / 语音直播。开播后写直播状态,主播与观众拉取同一套进房凭证:
sdkAppId/userId/userSig/roomIdmaxMinutes/liveExpireTime(体验时长)- 主播信息、在线、公屏快照、货架列表等

后端在下发凭证时,按配置计算到期时间(节选):
int maxMinutes = getLiveMaxMinutes();
resp.setMaxMinutes(maxMinutes);
if (maxMinutes > 0 && note.getLiveStartTime() != null) {
resp.setLiveExpireTime(note.getLiveStartTime().plusMinutes(maxMinutes));
}
return resp;
定时任务扫描「开播时间 + 最长分钟」已过期的进行中场次,系统关播并推送 experience_timeout:
private int endExperienceExpiredLives() {
int maxMinutes = getLiveMaxMinutes();
if (maxMinutes <= 0) {
return 0;
}
LocalDateTime startDeadline = LocalDateTime.now().minusMinutes(maxMinutes);
List<MemberNoteDO> expired = memberNoteMapper.selectExperienceExpiredLiving(startDeadline);
// ... doEndLive(note, "experience_timeout", tipMessage);
}
H5 直接加载 TRTC Web SDK;App 用 WebView 打开同一套媒体页,query 带上 maxMinutes / expireAt 与 H5 对齐。
四、直播间:货架、公屏、体验倒计时
信息架构:
| 区域 | 内容 |
|---|---|
| 顶栏 | 主播胶囊、在线人数 |
| 主舞台 | 视频全屏 / 语音头像 |
| 中部 | 「体验剩余 MM:SS」(≤60s 标红) |
| 左侧 | 货架短轨 |
| 下部 | 公屏 |
| 底栏 | 输入、静音、摄像头、分享、离开 |
前端中部倒计时模板:
<view v-if="state.countdownVisible"
class="live__exp-cd"
:class="{ 'live__exp-cd--warn': state.remainSec <= 60 }">
<text class="live__exp-cd__label">体验剩余</text>
<text class="live__exp-cd__time">{{ state.countdownText }}</text>
</view>
凭证回来后启动秒表(直播 / 语聊共用 helper):
export function createExperienceCountdown(options) {
const expireAtMs = Number(options?.expireAtMs) || 0;
const onTick = options?.onTick;
const onExpire = options?.onExpire;
let timer = null;
const tick = () => {
const remain = Math.max(0, Math.ceil((expireAtMs - Date.now()) / 1000));
if (typeof onTick === 'function') onTick(remain, formatRemain(remain));
if (remain <= 0) {
clearInterval(timer);
if (typeof onExpire === 'function') onExpire();
}
};
return {
start() {
tick();
timer = setInterval(tick, 1000);
},
stop() {
if (timer) clearInterval(timer);
},
};
}
// 直播间内:
experienceCountdown = createExperienceCountdown({
expireAtMs: parseTimeMs(data.liveExpireTime),
onTick: (remain, text) => {
state.remainSec = remain;
state.countdownText = text;
},
onExpire: () => onForceEnded('体验时长已到,自动关闭。如需体验请联系管理员', true),
});
experienceCountdown.start();
关播三条路径:主播主动结束、心跳超时 Job、体验到期。结束页汇总时长 / 峰值在线 / 获赞:

五、私域触达:链接 + IM 卡片
直播间内可:
- 复制邀请链接(发到微信等站外私域)
- 发给互关好友 → 走私信 / 群聊卡片,点击直达直播间或语聊房

链接拼装(H5 hash 路由):
export function buildLiveInviteLink(noteId) {
// #ifdef H5
if (typeof location !== 'undefined') {
const base = `${location.origin}${location.pathname || '/'}`;
return `${base}#/pages/note/live?id=${encodeURIComponent(noteId)}`;
}
// #endif
return `/pages/note/live?id=${noteId}`;
}
export function buildVoiceRoomInviteLink(roomNo) {
// #ifdef H5
if (typeof location !== 'undefined') {
const base = `${location.origin}${location.pathname || '/'}`;
return `${base}#/pages/voice-room/room?roomNo=${encodeURIComponent(roomNo)}`;
}
// #endif
return `/pages/voice-room/room?roomNo=${roomNo}`;
}
卡片协议与笔记分享、语聊房间卡同一套 IM contentType 扩展,是私域拉新的关键一跳。
六、内容带货:直播货架
不另起直播电商中台,直接嵌商城 SPU:
| 能力 | 说明 |
|---|---|
| 上架 / 下架 | 主播从商品库选品进本场货架 |
| 讲解中 | 左侧浮卡高亮当前讲解商品 |
| 购买 | 跳转商城详情下单 |
| 购买播报 | 可选打进公屏 |
适合私域「边聊边卖」。货架 ID 存在内容表的 live_goods_json / live_explain_spu_id 字段上。
七、音视频聊天室(会后讨论)
与直播互补:直播是「一对多现场」,语聊是「多人麦位闲聊」。同一套 TRTC + 体验时长 + 邀请卡片。


创建 / 加入房间后进入 8 麦位舞台;倒计时 helper 与直播共用,配置 key 为 member.voice-room.max-minutes。
八、数据与配置
内容表直播字段(节选)
| 字段 | 含义 |
|---|---|
live_room_id |
TRTC 房间号 |
live_mode |
0 视频 / 1 语音 |
live_status |
0 结束 / 1 直播中 |
live_start_time / live_end_time |
开播、结束 |
live_peak_online |
峰值在线 |
live_heartbeat_time |
主播心跳 |
live_chat_json |
最近公屏 |
live_goods_json |
货架 SPU 列表 |
live_explain_spu_id |
当前讲解商品 |
系统配置(幂等插入示例)
INSERT INTO `infra_config`
(`category`, `type`, `name`, `config_key`, `value`, `visible`, `remark`,
`creator`, `create_time`, `updater`, `update_time`, `deleted`)
SELECT 'member', 2, '会员直播-单场最长分钟', 'member.live.max-minutes', '30', b'1',
'体验限制:开播超过该分钟数自动关播;0=不限制',
'1', NOW(), '1', NOW(), b'0'
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `infra_config`
WHERE `config_key` = 'member.live.max-minutes' AND `deleted` = b'0'
);
同类还有:member.trtc.sdk-app-id、member.trtc.secret-key、member.live.chat-sensitive-words、member.voice-room.max-minutes,以及心跳超时 Job。全部收敛在 sql/mysql/xhs-init.sql(可重复执行)。
全新库建议顺序:yudao-full.sql →(可选)quartz.sql → xhs-init.sql。
九、开播时序(简化)
主播 后端 TRTC 观众
│ 开播/拿凭证 │ │ │
│──────────────────►│ 写直播状态 + 签 UserSig │
│◄──── credentials ─│ │ │
│ enterRoom+推流 │───────────────────────────────────────►│
│ │◄── 观众 credentials─┼───────────────────│
│ 公屏/点赞/货架 │◄────── WS/HTTP ────┼───────────────────│
│ 心跳 │ 扫描超时/体验到期 │ │
│ 结束 │ 推结束事件 │──────────────────►│
接口能力一览:进房凭证、结束、场次汇总、离开、心跳、点赞、公屏、禁言、货架、购买播报。建议集中在一个直播应用服务类,避免凭证签发与状态机散落。
十、落地建议
适合:粉丝专场、教学演示(可配体验时长)、已有 Java 商城要接「边播边卖」。
可扩展:连麦 / PK、直播回放挂回内容详情、开播自动发群公告 + 批量私信卡片、场次 GMV / 观看时长看板、会后导流进语聊房。
十一、总结
私域直播不是「接个推流 SDK」,而是把 内容对象、关系链、实时互动、商品成交、试用治理 串在同一产品里:
- Spring Boot:凭证、状态机、心跳、货架、敏感词、配置化时长
- uni-app:直播间 + Hybrid TRTC + 体验倒计时
- Vue3 管理端:内容 / 商品运营与系统参数
- IM 卡片:把场次送进私域会话
在社区与市集跑通后,直播补上的是 实时现场与转化瞬间——这是很多团队从内容工具走向商业闭环时,最值得优先打磨的一块。
演示地址
移动端:http://8.146.211.120:8081/#/
管理端:http://8.146.211.120:8088/#/
更多推荐




所有评论(0)