Skip to content

Commit 0839da6

Browse files
author
Taois
committed
feat: 直播代理播放使用独立代理地址
1 parent 9dae4dc commit 0839da6

File tree

3 files changed

+340
-78
lines changed

3 files changed

+340
-78
lines changed
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
<template>
2+
<div class="live-proxy-selector">
3+
<svg class="selector-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
4+
<path d="M12 2L2 7l10 5 10-5-10-5z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5+
<path d="M2 17l10 5 10-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
6+
<path d="M2 12l10 5 10-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
7+
</svg>
8+
<a-select
9+
:model-value="currentSelection"
10+
@change="handleSelectionChange"
11+
class="proxy-select"
12+
size="small"
13+
placeholder="选择代理播放地址"
14+
>
15+
<a-option value="disabled" title="关闭代理播放功能">代理播放:关闭</a-option>
16+
<a-option
17+
v-for="option in proxyOptions"
18+
:key="option.value"
19+
:value="option.value"
20+
:title="`${option.label}\n完整链接: ${option.url || option.value}`"
21+
>
22+
代理播放:{{ option.label }}
23+
</a-option>
24+
</a-select>
25+
</div>
26+
</template>
27+
28+
<script setup>
29+
import { ref, onMounted, onUnmounted } from 'vue'
30+
31+
// Props
32+
const props = defineProps({
33+
// 可以传入初始值,但组件会使用自己的存储
34+
initialValue: {
35+
type: String,
36+
default: 'disabled'
37+
}
38+
})
39+
40+
// Emits
41+
const emit = defineEmits(['change'])
42+
43+
// 响应式数据
44+
const currentSelection = ref('disabled')
45+
const proxyOptions = ref([])
46+
47+
// 存储键名 - 直播界面专用
48+
const LIVE_PROXY_STORAGE_KEY = 'live-proxy-selection'
49+
const GLOBAL_PROXY_HISTORY_KEY = 'address-history-proxy-play'
50+
51+
// 获取代理配置名称
52+
const getProxyName = (url) => {
53+
if (!url) return '未知'
54+
const hashIndex = url.indexOf('#')
55+
if (hashIndex !== -1 && hashIndex < url.length - 1) {
56+
return url.substring(hashIndex + 1)
57+
}
58+
return '默认代理'
59+
}
60+
61+
// 加载全局代理播放地址历史记录作为选项
62+
const loadProxyOptions = () => {
63+
try {
64+
// 从全局历史记录中加载选项
65+
const addressHistory = JSON.parse(localStorage.getItem(GLOBAL_PROXY_HISTORY_KEY) || '[]')
66+
67+
// 清空选项
68+
proxyOptions.value = []
69+
70+
// 添加历史记录到选项中
71+
addressHistory.forEach(item => {
72+
const url = item.url || item.value || ''
73+
if (!url) return
74+
75+
const proxyName = getProxyName(url)
76+
proxyOptions.value.push({
77+
value: url,
78+
label: proxyName,
79+
url: url
80+
})
81+
})
82+
83+
console.log('直播代理选项加载完成:', proxyOptions.value.length, '个选项')
84+
} catch (error) {
85+
console.error('加载直播代理选项失败:', error)
86+
}
87+
}
88+
89+
// 加载直播界面的独立选择状态
90+
const loadLiveProxySelection = () => {
91+
try {
92+
const savedSelection = localStorage.getItem(LIVE_PROXY_STORAGE_KEY)
93+
if (savedSelection && savedSelection !== 'null') {
94+
currentSelection.value = savedSelection
95+
} else {
96+
currentSelection.value = 'disabled'
97+
}
98+
99+
console.log('直播代理选择状态加载:', currentSelection.value)
100+
} catch (error) {
101+
console.error('加载直播代理选择状态失败:', error)
102+
currentSelection.value = 'disabled'
103+
}
104+
}
105+
106+
// 保存直播界面的独立选择状态
107+
const saveLiveProxySelection = (value) => {
108+
try {
109+
localStorage.setItem(LIVE_PROXY_STORAGE_KEY, value)
110+
console.log('直播代理选择状态已保存:', value)
111+
} catch (error) {
112+
console.error('保存直播代理选择状态失败:', error)
113+
}
114+
}
115+
116+
// 处理选择变更
117+
const handleSelectionChange = (value) => {
118+
currentSelection.value = value
119+
120+
// 保存到独立存储
121+
saveLiveProxySelection(value)
122+
123+
// 发送事件给父组件
124+
emit('change', {
125+
value: value,
126+
enabled: value !== 'disabled',
127+
url: value === 'disabled' ? '' : value
128+
})
129+
130+
console.log('直播代理选择已变更:', {
131+
value: value,
132+
enabled: value !== 'disabled'
133+
})
134+
}
135+
136+
// 监听全局代理历史变化,更新选项
137+
const handleGlobalProxyHistoryChange = (event) => {
138+
if (event.key === GLOBAL_PROXY_HISTORY_KEY) {
139+
loadProxyOptions()
140+
}
141+
}
142+
143+
// 监听自定义事件(用于同一页面内的历史变化)
144+
const handleAddressHistoryChanged = () => {
145+
loadProxyOptions()
146+
}
147+
148+
// 组件挂载时初始化
149+
onMounted(() => {
150+
loadProxyOptions()
151+
loadLiveProxySelection()
152+
153+
// 监听localStorage变化
154+
window.addEventListener('storage', handleGlobalProxyHistoryChange)
155+
156+
// 监听自定义事件
157+
window.addEventListener('addressHistoryChanged', handleAddressHistoryChanged)
158+
})
159+
160+
// 组件卸载时清理监听器
161+
onUnmounted(() => {
162+
window.removeEventListener('storage', handleGlobalProxyHistoryChange)
163+
window.removeEventListener('addressHistoryChanged', handleAddressHistoryChanged)
164+
})
165+
166+
// 暴露方法给父组件
167+
defineExpose({
168+
getCurrentSelection: () => currentSelection.value,
169+
isEnabled: () => currentSelection.value !== 'disabled',
170+
getProxyUrl: () => currentSelection.value === 'disabled' ? '' : currentSelection.value,
171+
refreshOptions: loadProxyOptions
172+
})
173+
</script>
174+
175+
<style scoped>
176+
.live-proxy-selector {
177+
display: flex;
178+
align-items: center;
179+
gap: 4px;
180+
padding: 6px 10px;
181+
border-radius: 4px;
182+
cursor: pointer;
183+
transition: all 0.2s ease;
184+
background: transparent;
185+
border: none;
186+
font-size: 12px;
187+
font-weight: 500;
188+
color: #495057;
189+
min-height: 28px;
190+
position: relative;
191+
}
192+
193+
.live-proxy-selector:hover {
194+
background: #e9ecef;
195+
color: #212529;
196+
transform: translateY(-1px);
197+
}
198+
199+
.selector-icon {
200+
width: 14px;
201+
height: 14px;
202+
flex-shrink: 0;
203+
}
204+
205+
.proxy-select {
206+
border: none !important;
207+
background: transparent !important;
208+
box-shadow: none !important;
209+
min-width: 120px;
210+
}
211+
212+
.proxy-select :deep(.arco-select-view) {
213+
border: none !important;
214+
background: transparent !important;
215+
padding: 0;
216+
font-size: 11px;
217+
font-weight: 500;
218+
}
219+
220+
.proxy-select :deep(.arco-select-view-suffix) {
221+
color: currentColor;
222+
}
223+
224+
.proxy-select :deep(.arco-select-view-value) {
225+
color: currentColor;
226+
}
227+
</style>

dashboard/src/components/players/PlayerHeader.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,11 @@
9494
</a-select>
9595
</div>
9696

97-
<!-- 代理播放地址选择器 -->
98-
<div class="compact-btn selector-btn">
97+
<!-- 代理播放地址选择器 - 仅在非直播模式下显示 -->
98+
<div
99+
v-if="!isLiveMode"
100+
class="compact-btn selector-btn"
101+
>
99102
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
100103
<path d="M12 2L2 7l10 5 10-5-10-5z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
101104
<path d="M2 17l10 5 10-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>

0 commit comments

Comments
 (0)