@@ -171,13 +171,22 @@ const isRetrying = ref(false) // 是否正在重连
171171const dynamicHeight = ref (450 ) // 动态计算的高度
172172
173173// 自动下一集功能相关数据
174- const autoNextEnabled = ref (true ) // 自动下一集开关,默认关闭
175- const loopEnabled = ref (JSON .parse (localStorage .getItem (' loopEnabled' ) || ' false' )) // 循环播放开关,从本地存储读取
174+ // 初始化互斥逻辑:自动连播和循环播放不能同时开启
175+ const savedLoopEnabled = JSON .parse (localStorage .getItem (' loopEnabled' ) || ' false' )
176+ const savedAutoNextEnabled = JSON .parse (localStorage .getItem (' autoNextEnabled' ) || ' true' )
177+
178+ // 确保互斥:如果循环播放开启,则关闭自动连播
179+ const autoNextEnabled = ref (savedLoopEnabled ? false : savedAutoNextEnabled)
180+ const loopEnabled = ref (savedLoopEnabled)
176181const autoNextCountdown = ref (0 ) // 自动下一集倒计时
177182const autoNextTimer = ref (null ) // 自动下一集定时器
178183const showAutoNextDialog = ref (false ) // 显示自动下一集对话框
179184const countdownEnabled = ref (false ) // 倒计时开关,默认关闭
180185
186+ // 防抖标志,防止重复触发
187+ const isProcessingAutoNext = ref (false ) // 防止自动下一集重复触发
188+ const isProcessingLoop = ref (false ) // 防止循环播放重复触发
189+
181190// 调试相关
182191const showDebugDialog = ref (false )
183192const detectedFormat = ref (' ' )
@@ -324,6 +333,9 @@ const initArtPlayer = async (url) => {
324333 // 重置片头片尾状态
325334 resetSkipState ()
326335
336+ // 重置防抖标志
337+ resetDebounceFlags ()
338+
327339 // 等待 DOM 更新后计算动态高度
328340 await nextTick ()
329341 dynamicHeight .value = calculateDynamicHeight ()
@@ -620,6 +632,9 @@ const initArtPlayer = async (url) => {
620632 // 视频开始播放时,重置重连计数器
621633 resetRetryState ()
622634
635+ // 重置防抖标志,确保新的播放周期可以正常处理自动下一集和循环播放
636+ resetDebounceFlags ()
637+
623638 // 立即尝试片头跳过(针对视频刚开始播放的情况)
624639 const immediateSkipped = applyIntroSkipImmediate ()
625640
@@ -665,9 +680,17 @@ const initArtPlayer = async (url) => {
665680 try {
666681 console .log (' 视频播放结束' )
667682
683+ // 防抖检查:如果正在处理自动下一集或循环播放,则忽略
684+ if (isProcessingAutoNext .value || isProcessingLoop .value ) {
685+ console .log (' 正在处理中,忽略重复的视频结束事件' )
686+ return
687+ }
688+
668689 // 优先处理循环播放
669690 if (loopEnabled .value ) {
670691 console .log (' 循环播放:重新播放当前选集' )
692+ isProcessingLoop .value = true // 设置防抖标志
693+
671694 // 重新执行当前选集的播放逻辑
672695 setTimeout (() => {
673696 try {
@@ -676,20 +699,25 @@ const initArtPlayer = async (url) => {
676699 } catch (error) {
677700 console .error (' 循环播放触发选集事件失败:' , error)
678701 Message .error (' 循环播放失败,请重试' )
702+ isProcessingLoop .value = false // 出错时重置标志
679703 }
680704 }, 1000 )
681705 return
682706 }
683707
684708 // 视频结束时启动自动下一集
685709 if (autoNextEnabled .value && hasNextEpisode ()) {
710+ isProcessingAutoNext .value = true // 设置防抖标志
686711 startAutoNextCountdown ()
687712 } else if (! hasNextEpisode ()) {
688713 Message .info (' 全部播放完毕' )
689714 }
690715 } catch (error) {
691716 console .error (' 视频结束事件处理失败:' , error)
692717 Message .error (' 视频结束处理失败' )
718+ // 出错时重置防抖标志
719+ isProcessingAutoNext .value = false
720+ isProcessingLoop .value = false
693721 }
694722 })
695723
@@ -908,7 +936,7 @@ const saveSkipSettings = (settings) => {
908936}
909937
910938// 处理重连逻辑
911- const handleRetry = (url ) => {
939+ const handleRetry = (originalUrl ) => {
912940 if (isRetrying .value ) {
913941 return // 如果正在重连,避免重复触发
914942 }
@@ -924,13 +952,22 @@ const handleRetry = (url) => {
924952 setTimeout (() => {
925953 if (artPlayerInstance .value ) {
926954 try {
955+ // 重连时也要使用代理处理后的URL,确保代理设置生效
956+ const headers = props .headers || {}
957+ const processedUrl = processVideoUrl (originalUrl, headers)
958+
959+ console .log (' 重连使用URL:' , processedUrl)
960+ if (processedUrl !== originalUrl) {
961+ console .log (' 🔄 [代理播放] 重连时使用代理地址' )
962+ }
963+
927964 // 重新加载视频
928- artPlayerInstance .value .switchUrl (url )
965+ artPlayerInstance .value .switchUrl (processedUrl )
929966 isRetrying .value = false
930967 } catch (error) {
931968 console .error (' 重连时出错:' , error)
932969 isRetrying .value = false
933- handleRetry (url ) // 递归重试
970+ handleRetry (originalUrl ) // 递归重试
934971 }
935972 }
936973 }, 2000 * retryCount .value ) // 递增延迟:2秒、4秒、6秒
@@ -973,6 +1010,12 @@ const calculateDynamicHeight = () => {
9731010 return Math .round (calculatedHeight)
9741011}
9751012
1013+ // 防抖标志重置函数
1014+ const resetDebounceFlags = () => {
1015+ isProcessingAutoNext .value = false
1016+ isProcessingLoop .value = false
1017+ }
1018+
9761019// 自动下一集功能相关函数
9771020
9781021// 检查是否有下一集
@@ -1021,13 +1064,18 @@ const cancelAutoNext = () => {
10211064 }
10221065 autoNextCountdown .value = 0
10231066 showAutoNextDialog .value = false
1067+
1068+ // 重置防抖标志
1069+ resetDebounceFlags ()
1070+
10241071 console .log (' 用户取消自动下一集' )
10251072}
10261073
10271074// 立即播放下一集
10281075const playNextEpisode = () => {
10291076 if (! hasNextEpisode ()) {
10301077 Message .info (' 已经是最后一集了' )
1078+ resetDebounceFlags () // 重置防抖标志
10311079 return
10321080 }
10331081
@@ -1036,6 +1084,9 @@ const playNextEpisode = () => {
10361084 // 清理倒计时
10371085 cancelAutoNext ()
10381086
1087+ // 重置防抖标志
1088+ resetDebounceFlags ()
1089+
10391090 // 通知父组件切换到下一集
10401091 emit (' next-episode' , props .currentEpisodeIndex + 1 )
10411092
@@ -1046,6 +1097,8 @@ const playNextEpisode = () => {
10461097// 切换自动下一集开关
10471098const toggleAutoNext = () => {
10481099 autoNextEnabled .value = ! autoNextEnabled .value
1100+ // 保存自动连播状态到本地存储
1101+ localStorage .setItem (' autoNextEnabled' , JSON .stringify (autoNextEnabled .value ))
10491102
10501103 // 如果开启自动连播,则关闭循环播放
10511104 if (autoNextEnabled .value ) {
@@ -1068,6 +1121,7 @@ const toggleLoop = () => {
10681121 // 如果开启循环播放,则关闭自动连播
10691122 if (loopEnabled .value ) {
10701123 autoNextEnabled .value = false
1124+ localStorage .setItem (' autoNextEnabled' , ' false' )
10711125 cancelAutoNext ()
10721126 }
10731127
@@ -1498,11 +1552,23 @@ const handleResize = () => {
14981552 }
14991553}
15001554
1555+ // 处理代理设置变化
1556+ const handleAddressSettingsChange = () => {
1557+ console .log (' 检测到代理设置变化,重新初始化播放器' )
1558+ if (props .videoUrl && props .visible ) {
1559+ nextTick (() => {
1560+ initArtPlayer (props .videoUrl )
1561+ })
1562+ }
1563+ }
1564+
15011565// 组件挂载时的初始化
15021566onMounted (() => {
15031567 console .log (' ArtVideoPlayer 组件已挂载 - 动态高度版本' )
15041568 // 添加窗口大小变化监听
15051569 window .addEventListener (' resize' , handleResize)
1570+ // 添加代理设置变化监听
1571+ window .addEventListener (' addressSettingsChanged' , handleAddressSettingsChange)
15061572 // 初始化片头片尾设置
15071573 initSkipSettings ()
15081574 // 初始化画质数据
@@ -1515,6 +1581,8 @@ onUnmounted(() => {
15151581
15161582 // 移除窗口大小变化监听器
15171583 window .removeEventListener (' resize' , handleResize)
1584+ // 移除代理设置变化监听器
1585+ window .removeEventListener (' addressSettingsChanged' , handleAddressSettingsChange)
15181586
15191587 // 清理自动下一集相关资源
15201588 cancelAutoNext ()
0 commit comments