Files
ruo-shan-cloud-pharmacy/miniprogram/package-live/wxroom/index.ts
T
陈誉午 994b267f5c feat: 电子药箱小程序 - 4Tab药品管理
- 电子药箱: 药品库存管理 + 手动录入 + 今日用药打卡
- 药品百科: 搜索 + 分类筛选 + 20种药品静态数据
- 惠教中心: 4条药品使用指南课程
- 我的: 家庭成员信息管理
- 自定义TabBar + navigation-bar组件
- SVG药品分类插图
2026-07-29 11:20:52 +08:00

282 lines
7.6 KiB
TypeScript

// package-live/wxroom/index.ts
import VolcMiniSdk, { EVENTS } from "../volc-mini-sdk/index";
import { request } from "../../utils/request";
import { appId } from "../../env";
import { aesDecrypt, aesEncrypt } from "../../utils/crypto";
import { AES_KEY, AES_IV } from "../../env";
import { receiveRedPacket, lockPromise } from "../../utils/util";
const WXROOM_REDIRECT_PATH_KEY = "wxroomRedirectPath";
const WXROOM_PAGE_PATH = "/package-live/wxroom/index";
const isMobileEnvironment = (): boolean => {
const platform = wx.getSystemInfoSync().platform?.toLowerCase() || '';
return platform !== 'windows' && platform !== 'mac';
};
let pageOptionsCache: Record<string, string | undefined> = {};
Page({
data: {
sdk: null as any,
activityId: 0,
loading: false,
loadingText: "",
showError: false,
errorTitle: "",
errorMessage: "",
inviterToken: "",
msg: "",
userId: "",
isLandscape: false,
},
async onLoad(options: Record<string, string | undefined>) {
pageOptionsCache = options || {};
const activityId = this.getActivityId(options);
if (!activityId) {
this.handleEnterError(
"缺少直播间ID,请重新从正确的直播链接进入。",
"无法进入直播间",
);
return;
}
if (!isMobileEnvironment()) {
this.handleEnterError(
"当前环境不支持观看直播,请使用手机观看。",
"环境不支持",
);
return;
}
this.cacheRedirectPath(options);
this.setData({ activityId, inviterToken: options.inviterToken, userId: options.userId, isLandscape: String(options.isLandscape) === "true", });
const app = getApp<IAppOption>();
this.setLoading("正在校验登录状态...");
const isLogin = app.checkLoginState();
if (!isLogin) {
wx.reLaunch({ url: `/package-live/login/login?userId=${options?.userId}&activityId=${activityId}` });
return;
};
},
onReady() {
// onReady在页面生命周期中只执行一次,将初始化放在此处避免
// onHide销毁SDK后onShow重复初始化导致声音重复播放
this.initSdk(this.data.activityId, pageOptionsCache);
},
onShow() {
if (!this.data.sdk && this.data.activityId) {
this.initSdk(this.data.activityId, pageOptionsCache);
}
},
async initSdk(
activityId: number,
options?: Record<string, string | undefined>,
) {
try {
this.clearError();
this.setLoading("正在获取直播凭证...");
const signToken = await this.fetchSignToken();
if (!signToken) {
wx.redirectTo({
url: `/package-live/login/login?userId=${options?.userId}&activityId=${activityId}&show=${true}&msg=${this.data.msg}`
})
throw new Error("未获取到直播凭证,请稍后重试");
}
this.destroySdk();
this.setLoading("正在进入直播间...");
const sdk = VolcMiniSdk({
activityId,
signToken,
mode: Number(options?.mode || 2) || 2,
} as any);
sdk.on(EVENTS.error, (err: any) => {
console.log("sdk error", err?.code, err?.message);
this.handleEnterError(
err?.message || "直播间加载失败,请稍后重试",
"直播间加载失败",
);
});
const debugInfo = sdk.getDebugInfo()
console.log('debugInfo:', debugInfo)
sdk.on(EVENTS.card.click, (payload: any) => {
wx.navigateTo({
url: payload?.url
})
});
// 监听浮窗商品卡片点击事件。
sdk.on('floatingCard.click', (payload: any) => {
wx.navigateTo({
url: payload?.url
})
})
// 按钮红包功能
sdk.on(EVENTS.feature.click, (payload: any) => {
console.log('feature.click', payload)
})
sdk.on(EVENTS.luckymoney.withdrawal, (payload: any) => {
this.handleReceive(payload);
});
this.setData({
sdk,
loading: false,
loadingText: "",
});
} catch (error: any) {
console.error("init wxroom sdk failed:", error);
this.handleEnterError(
error?.message || "进入直播间失败,请稍后重试",
"进入直播间失败",
);
}
},
async fetchSignToken() {
const nickName = wx.getStorageSync("userName") || "微信用户";
const userIdStr = String(wx.getStorageSync("mbuId") || "");
const avatarUrl = wx.getStorageSync("avatarUrl") || "";
if (!userIdStr) {
throw new Error("登录信息缺失,请重新登录后再进入直播间");
}
const res = await request<any>({
options: {
url: "/app/saas/activity-login",
method: "POST",
data: aesEncrypt(JSON.stringify({
nickName,
userIdStr,
avatarUrl,
userId: this.data.userId,
inviterToken: this.data.inviterToken,
activityId: this.data.activityId,
mpUserId: wx.getStorageSync("userId"),
}), AES_KEY, AES_IV)
},
loadingTitle: "进入直播间",
isLoading: false,
});
const data = JSON.parse(aesDecrypt(res?.data, AES_KEY, AES_IV))
this.setData({ msg: data?.msg ?? "暂无活动" });
return (
data?.signToken || ""
);
},
handleReceive: lockPromise(async function(data: any) {
const params = {
appId: appId,
outRewardsId: data.redPacketId,
openId: wx.getStorageSync("openId"),
}
try {
await receiveRedPacket(
params,
'/app/general/receive-red',
appId
);
} catch (err) {
console.error('领取红包失败:', err);
}
}),
getActivityId(options: Record<string, string | undefined>) {
const rawActivityId = options.activityId || options.roomId || "";
const activityId = Number(rawActivityId);
return Number.isFinite(activityId) ? activityId : 0;
},
buildQueryString(params: Record<string, string | undefined>) {
return Object.entries(params)
.filter(([, value]) => value !== undefined && value !== "")
.map(
([key, value]) =>
`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`,
)
.join("&");
},
cacheRedirectPath(options: Record<string, string | undefined>) {
const query = this.buildQueryString(options);
const path = query ? `${WXROOM_PAGE_PATH}?${query}` : WXROOM_PAGE_PATH;
wx.setStorageSync(WXROOM_REDIRECT_PATH_KEY, path);
},
setLoading(text: string) {
this.setData({
loading: true,
loadingText: text,
showError: false,
errorTitle: "",
errorMessage: "",
});
},
clearError() {
this.setData({
showError: false,
errorTitle: "",
errorMessage: "",
});
},
handleEnterError(message: string, title = "无法进入直播间") {
this.destroySdk();
this.setData({
loading: false,
loadingText: "",
showError: true,
errorTitle: title,
errorMessage: message,
});
},
retryEnter() {
const activityId =
this.data.activityId || this.getActivityId(pageOptionsCache);
if (!activityId) {
this.handleEnterError(
"缺少直播间ID,请重新从正确的直播链接进入。",
"无法进入直播间",
);
return;
}
this.initSdk(activityId, pageOptionsCache);
},
goBack() {
const pages = getCurrentPages();
if (pages.length > 1) {
wx.navigateBack({
delta: 1,
});
return;
}
wx.switchTab({
url: "/pages/tab-bar/medicine-box/index",
});
},
destroySdk() {
this.data.sdk?.destroy?.();
if (this.data.sdk) {
this.setData({
sdk: null,
});
}
},
commentCheck() { },
onUnload() {
this.destroySdk();
},
});