diff --git a/WebVue/src/components/basic/VideoPlayModal.vue b/WebVue/src/components/basic/VideoPlayModal.vue
new file mode 100644
index 0000000..5df071c
--- /dev/null
+++ b/WebVue/src/components/basic/VideoPlayModal.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WebVue/src/utils/imageRetry.ts b/WebVue/src/utils/imageRetry.ts
new file mode 100644
index 0000000..9021d76
--- /dev/null
+++ b/WebVue/src/utils/imageRetry.ts
@@ -0,0 +1,39 @@
+/**
+ * 图片加载失败重试。
+ *
+ * 背景:视频封面(jpg)是服务端 ffmpeg 异步生成的,列表查询返回时文件常常还没落盘,
+ * 首次请求会拿到 404;而
一旦失败不会自动重试,只有 src 变了才会再请求一次,
+ * 表现就是"必须手动刷新页面才有图"。
+ *
+ * 这里失败后按退避重试,重试时把查询参数换成一次性时间戳绕开缓存。
+ * 重试次数用 dataset 记在
上,src 变了(重新查询拿到新地址)就重新计数。
+ */
+const RETRY_DELAYS = [800, 2000, 4000];
+
+export const retryImage = (e: Event, max: number = RETRY_DELAYS.length) => {
+ const img = e.target as HTMLImageElement | null;
+ if (!img) return;
+
+ const src = img.getAttribute("src") || img.src;
+ if (!src) return;
+
+ // 地址变了说明是新一轮数据,允许重新重试
+ if (img.dataset.retrySrc !== src) {
+ img.dataset.retrySrc = src;
+ img.dataset.retry = "0";
+ }
+
+ const times = Number(img.dataset.retry ?? 0);
+ if (times >= max) {
+ // 彻底拿不到就隐藏图片,露出底下的占位/播放图标,避免裂图
+ img.style.visibility = "hidden";
+ return;
+ }
+
+ img.dataset.retry = String(times + 1);
+ const base = src.split("?")[0];
+ window.setTimeout(() => {
+ img.src = `${base}?_t=${Date.now()}`;
+ img.style.visibility = "";
+ }, RETRY_DELAYS[Math.min(times, RETRY_DELAYS.length - 1)]);
+};