- 电子药箱: 药品库存管理 + 手动录入 + 今日用药打卡 - 药品百科: 搜索 + 分类筛选 + 20种药品静态数据 - 惠教中心: 4条药品使用指南课程 - 我的: 家庭成员信息管理 - 自定义TabBar + navigation-bar组件 - SVG药品分类插图
263 lines
7.3 KiB
TypeScript
263 lines
7.3 KiB
TypeScript
// components/my-video/index.ts
|
|
import { AES_KEY, AES_IV } from "../../env";
|
|
import { request } from "../../utils/request";
|
|
import { aesEncrypt } from "../../utils/crypto";
|
|
|
|
interface VideoData {
|
|
screen: boolean;
|
|
playing: boolean;
|
|
currentTime: number;
|
|
isReady: boolean;
|
|
sendDurationTimer: number | null;
|
|
lastUpdateTime: number;
|
|
isConnected: boolean; // 新增网络连接状态字段
|
|
}
|
|
interface MyVideoComponent {
|
|
data: VideoData;
|
|
videoContext: WechatMiniprogram.VideoContext | null;
|
|
pauseVideoHandler?: () => void;
|
|
resumeVideoHandler?: () => void;
|
|
setData: (d: Partial<VideoData>, cb?: () => void) => void;
|
|
initNetworkListener: () => void;
|
|
startSendProgress: () => void;
|
|
clearSendProgressTimer: () => void;
|
|
sendProgress: () => Promise<void>;
|
|
}
|
|
|
|
Component({
|
|
properties: {
|
|
src: String,
|
|
backgroundUrl: String,
|
|
},
|
|
|
|
data: {
|
|
screen: false,
|
|
playing: false,
|
|
currentTime: 0,
|
|
isReady: false,
|
|
isConnected: false,
|
|
sendDurationTimer: 0,
|
|
lastUpdateTime: 0,
|
|
} as VideoData,
|
|
|
|
lifetimes: {
|
|
attached(this: MyVideoComponent) {
|
|
this.initNetworkListener();
|
|
|
|
// 获取 videoContext 并初始化
|
|
this.videoContext = wx.createVideoContext("videoPlayer", this as any);
|
|
|
|
const pauseVideo = () => {
|
|
if (this.data.playing) {
|
|
wx.setStorageSync("interruptedTime", this.data.currentTime);
|
|
this.videoContext?.pause();
|
|
this.setData({ playing: false });
|
|
this.clearSendProgressTimer();
|
|
}
|
|
};
|
|
|
|
const resumeVideo = () => {
|
|
if (!this.videoContext) {
|
|
this.videoContext = wx.createVideoContext("videoPlayer", this as any);
|
|
}
|
|
this.videoContext.pause();
|
|
};
|
|
|
|
this.pauseVideoHandler = pauseVideo;
|
|
this.resumeVideoHandler = resumeVideo;
|
|
|
|
wx.onAudioInterruptionBegin(this.pauseVideoHandler);
|
|
wx.onAudioInterruptionEnd(this.resumeVideoHandler);
|
|
wx.onAppHide(this.pauseVideoHandler);
|
|
wx.onAppShow(this.resumeVideoHandler);
|
|
},
|
|
|
|
detached(this: MyVideoComponent) {
|
|
if (this.pauseVideoHandler) {
|
|
wx.offAudioInterruptionBegin(this.pauseVideoHandler);
|
|
wx.offAppHide(this.pauseVideoHandler);
|
|
}
|
|
if (this.resumeVideoHandler) {
|
|
wx.offAudioInterruptionEnd(this.resumeVideoHandler);
|
|
wx.offAppShow(this.resumeVideoHandler);
|
|
}
|
|
this.clearSendProgressTimer();
|
|
this.videoContext = null;
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
initNetworkListener(this: MyVideoComponent) {
|
|
// 首先获取当前网络状态
|
|
wx.getNetworkType({
|
|
success: (res) => {
|
|
this.setData({
|
|
isConnected: res.networkType !== "none",
|
|
});
|
|
},
|
|
});
|
|
wx.onNetworkStatusChange(
|
|
(res: WechatMiniprogram.OnNetworkStatusChangeCallbackResult) => {
|
|
this.setData({
|
|
isConnected: res.isConnected,
|
|
});
|
|
if (!res.isConnected && this.data.playing) {
|
|
this.videoContext?.pause();
|
|
this.setData({ playing: false });
|
|
wx.showToast({
|
|
title: "网络连接已断开",
|
|
icon: "none",
|
|
duration: 2000,
|
|
});
|
|
}
|
|
if (res.isConnected) {
|
|
wx.showToast({
|
|
title: "网络已连接",
|
|
icon: "success",
|
|
duration: 1500,
|
|
});
|
|
}
|
|
}
|
|
);
|
|
},
|
|
|
|
handleLoadedMetadata(this: MyVideoComponent) {
|
|
this.setData({ isReady: true });
|
|
},
|
|
|
|
handlePosterTap(this: MyVideoComponent) {
|
|
if (!this.videoContext || !this.data.isReady) return;
|
|
if (!this.data.isConnected) {
|
|
wx.showToast({
|
|
title: "网络连接异常,请检查网络设置",
|
|
icon: "none",
|
|
duration: 2000,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const newPlaying = !this.data.playing;
|
|
const resumeTime =
|
|
(wx.getStorageSync("interruptedTime") as number) ||
|
|
this.data.currentTime ||
|
|
(wx.getStorageSync("currentTime") as number) ||
|
|
0;
|
|
|
|
if (newPlaying) {
|
|
if (resumeTime > 0) {
|
|
this.videoContext.seek(resumeTime);
|
|
}
|
|
this.videoContext.play();
|
|
if (!this.data.sendDurationTimer) {
|
|
this.startSendProgress();
|
|
}
|
|
} else {
|
|
this.videoContext.pause();
|
|
this.clearSendProgressTimer();
|
|
}
|
|
|
|
this.setData({ playing: newPlaying });
|
|
wx.removeStorageSync("interruptedTime");
|
|
},
|
|
|
|
handlePause(this: MyVideoComponent) {
|
|
wx.setStorageSync("interruptedTime", this.data.currentTime);
|
|
this.setData({ playing: false });
|
|
this.clearSendProgressTimer();
|
|
},
|
|
|
|
handleTimeUpdate(
|
|
this: MyVideoComponent,
|
|
e: WechatMiniprogram.VideoTimeUpdate
|
|
) {
|
|
const now = Date.now();
|
|
const currentTime = Math.floor(e.detail.currentTime ?? 0);
|
|
if (now - this.data.lastUpdateTime >= 1000) {
|
|
this.setData({ currentTime });
|
|
(this.data as VideoData).lastUpdateTime = now;
|
|
wx.setStorageSync("currentTime", currentTime);
|
|
}
|
|
},
|
|
|
|
handleEnded(this: MyVideoComponent) {
|
|
this.sendProgress();
|
|
wx.setStorageSync("ended", true);
|
|
this.setData({ playing: false, currentTime: 0 });
|
|
wx.removeStorageSync("currentTime");
|
|
wx.removeStorageSync("interruptedTime");
|
|
this.clearSendProgressTimer();
|
|
},
|
|
|
|
handleFullscreenChange(this: MyVideoComponent) {
|
|
const newScreen = !this.data.screen;
|
|
if (newScreen) {
|
|
this.videoContext?.requestFullScreen({ direction: 90 });
|
|
} else {
|
|
this.videoContext?.exitFullScreen();
|
|
}
|
|
this.setData({ screen: newScreen });
|
|
},
|
|
|
|
handleError(this: MyVideoComponent, e: WechatMiniprogram.VideoError) {
|
|
console.error("播放错误:", e.detail.errMsg);
|
|
this.setData({ playing: false });
|
|
},
|
|
|
|
startSendProgress(this: MyVideoComponent) {
|
|
this.clearSendProgressTimer();
|
|
const timer = setInterval(() => {
|
|
this.sendProgress();
|
|
}, 15000) as unknown as number;
|
|
this.setData({ sendDurationTimer: timer });
|
|
},
|
|
|
|
clearSendProgressTimer(this: MyVideoComponent) {
|
|
const t = this.data.sendDurationTimer;
|
|
if (t) {
|
|
clearInterval(t);
|
|
this.setData({ sendDurationTimer: 0 });
|
|
}
|
|
},
|
|
|
|
async sendProgress(this: MyVideoComponent) {
|
|
try {
|
|
const openId = wx.getStorageSync("openId");
|
|
const code = wx.getStorageSync("code");
|
|
const state = wx.getStorageSync("state");
|
|
const seeId = wx.getStorageSync("seeId");
|
|
const duration = this.data.currentTime + 1;
|
|
if (code) {
|
|
const params = {
|
|
openId,
|
|
code,
|
|
duration
|
|
};
|
|
await request({
|
|
options: {
|
|
url: `/app/video-watch/inspect`,
|
|
data: aesEncrypt(JSON.stringify(params), AES_KEY, AES_IV),
|
|
},
|
|
isLoading: false,
|
|
});
|
|
} else {
|
|
const params = {
|
|
openId,
|
|
state,
|
|
seeId,
|
|
duration
|
|
};
|
|
await request({
|
|
options: {
|
|
url: `/app/watch/inspect`,
|
|
data: aesEncrypt(JSON.stringify(params), AES_KEY, AES_IV),
|
|
},
|
|
isLoading: false,
|
|
});
|
|
}
|
|
} catch (err) {
|
|
console.error("上报观看进度失败:", err);
|
|
}
|
|
},
|
|
},
|
|
});
|