Skip to content

Commit f0cfa8c

Browse files
committed
2 parents be153a0 + 1b4519b commit f0cfa8c

18 files changed

+991
-652
lines changed

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
202505172114
1+
202505231250

css/player.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ body, html {
88
}
99
.player-container {
1010
width: 100%;
11-
max-width: 1200px;
11+
max-width: 1000px;
1212
margin: 0 auto;
1313
}
1414
#player {

image/logo-black.png

81.3 KB
Loading

image/logo.png

10.6 KB
Loading

image/retrotv_5520.png

-7.99 KB
Binary file not shown.

index.html

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
<meta name="author" content="JoyyaTV Team">
1010

1111
<!-- Favicon -->
12-
<link rel="icon" href="./image/retrotv_5520.png">
13-
<link rel="apple-touch-icon" href="./image/retrotv_5520.png">
12+
<link rel="icon" href="image/logo.png">
13+
<link rel="apple-touch-icon" href="image/logo-black.png">
1414
<link rel="manifest" href="manifest.json">
1515

1616
<script src="libs/tailwindcss.min.js"></script>
@@ -211,7 +211,18 @@ <h1 class="text-5xl font-bold gradient-text">JoyyaTV</h1>
211211
class="flex-1 bg-[#111] border-y border-[#333] text-white px-6 py-0 focus:outline-none transition-colors"
212212
placeholder="搜索你喜欢的视频..."
213213
autocomplete="off"
214-
aria-label="视频搜索框">
214+
aria-label="视频搜索框"
215+
oninput="toggleClearButton()">
216+
<!-- 清空按钮 -->
217+
<button id="clearSearchInput"
218+
class="flex pr-2 bg-[#111] border-y border-[#333] items-center justify-center text-gray-400 hover:text-white hidden"
219+
onclick="clearSearchInput()"
220+
aria-label="清空搜索框"
221+
title="清空搜索框">
222+
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
223+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
224+
</svg>
225+
</button>
215226
<!-- 搜索按钮 -->
216227
<button onclick="search()"
217228
class="w-20 sm:w-24 flex items-center justify-center bg-white text-black font-medium hover:bg-gray-200 transition-colors"

js/app.js

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// 全局变量
2-
let selectedAPIs = JSON.parse(localStorage.getItem('selectedAPIs') || '["tyyszy","dyttzy", "bfzy", "ruyi"]'); // 默认选中天涯资源、暴风资源和如意资源
2+
let selectedAPIs = JSON.parse(localStorage.getItem('selectedAPIs') || '["tyyszy","dyttzy", "bfzy", "ruyi"]'); // 默认选中资源
33
let customAPIs = JSON.parse(localStorage.getItem('customAPIs') || '[]'); // 存储自定义API列表
44

55
// 添加当前播放的集数索引
@@ -27,7 +27,7 @@ document.addEventListener('DOMContentLoaded', function() {
2727

2828
// 设置默认API选择(如果是第一次加载)
2929
if (!localStorage.getItem('hasInitializedDefaults')) {
30-
// 仅选择天涯资源、暴风资源和如意资源
30+
// 默认选中资源
3131
selectedAPIs = ["tyyszy","bfzy","dyttzy", "ruyi"];
3232
localStorage.setItem('selectedAPIs', JSON.stringify(selectedAPIs));
3333

@@ -888,6 +888,50 @@ async function search() {
888888
}
889889
}
890890

891+
// 切换清空按钮的显示状态
892+
function toggleClearButton() {
893+
const searchInput = document.getElementById('searchInput');
894+
const clearButton = document.getElementById('clearSearchInput');
895+
if (searchInput.value !== '') {
896+
clearButton.classList.remove('hidden');
897+
} else {
898+
clearButton.classList.add('hidden');
899+
}
900+
}
901+
902+
// 清空搜索框内容
903+
function clearSearchInput() {
904+
const searchInput = document.getElementById('searchInput');
905+
searchInput.value = '';
906+
const clearButton = document.getElementById('clearSearchInput');
907+
clearButton.classList.add('hidden');
908+
}
909+
910+
// 劫持搜索框的value属性以检测外部修改
911+
function hookInput() {
912+
const input = document.getElementById('searchInput');
913+
const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
914+
915+
// 重写 value 属性的 getter 和 setter
916+
Object.defineProperty(input, 'value', {
917+
get: function() {
918+
// 确保读取时返回字符串(即使原始值为 undefined/null)
919+
const originalValue = descriptor.get.call(this);
920+
return originalValue != null ? String(originalValue) : '';
921+
},
922+
set: function(value) {
923+
// 显式将值转换为字符串后写入
924+
const strValue = String(value);
925+
descriptor.set.call(this, strValue);
926+
this.dispatchEvent(new Event('input', { bubbles: true }));
927+
}
928+
});
929+
930+
// 初始化输入框值为空字符串(避免初始值为 undefined)
931+
input.value = '';
932+
}
933+
document.addEventListener('DOMContentLoaded', hookInput);
934+
891935
// 显示详情 - 修改为支持自定义API
892936
async function showDetails(id, vod_name, sourceCode) {
893937
// 密码保护校验
@@ -927,7 +971,10 @@ async function showDetails(id, vod_name, sourceCode) {
927971
apiParams = '&source=' + sourceCode;
928972
}
929973

930-
const response = await fetch('/api/detail?id=' + encodeURIComponent(id) + apiParams);
974+
// Add a timestamp to prevent caching
975+
const timestamp = new Date().getTime();
976+
const cacheBuster = `&_t=${timestamp}`;
977+
const response = await fetch(`/api/detail?id=${encodeURIComponent(id)}${apiParams}${cacheBuster}`);
931978

932979
const data = await response.json();
933980

@@ -1007,8 +1054,19 @@ function playVideo(url, vod_name, sourceCode, episodeIndex = 0) {
10071054
// 获取当前路径作为返回页面
10081055
let currentPath = window.location.href;
10091056

1057+
// 如果有ID参数,也传递过去
1058+
let videoId = '';
1059+
try {
1060+
// 尝试从URL中提取id参数(如果存在)
1061+
const urlObj = new URL(url);
1062+
videoId = urlObj.searchParams.get('id') || '';
1063+
} catch (e) {
1064+
// 忽略错误
1065+
console.log('解析视频URL获取ID失败:', e);
1066+
}
1067+
10101068
// 构建播放页面URL,使用watch.html作为中间跳转页
1011-
let watchUrl = `watch.html?id=${currentEpisodes[episodeIndex].id || ''}&source=${sourceCode || ''}&url=${encodeURIComponent(url)}&index=${episodeIndex}&title=${encodeURIComponent(vod_name || '')}`;
1069+
let watchUrl = `watch.html?id=${videoId}&source=${sourceCode || ''}&url=${encodeURIComponent(url)}&index=${episodeIndex}&title=${encodeURIComponent(vod_name || '')}`;
10121070

10131071
// 添加返回URL参数
10141072
watchUrl += `&back=${encodeURIComponent(currentPath)}`;
@@ -1026,8 +1084,8 @@ function playVideo(url, vod_name, sourceCode, episodeIndex = 0) {
10261084
console.error('保存播放状态失败:', e);
10271085
}
10281086

1029-
// 在新窗口/标签页中打开播放页面
1030-
window.open(watchUrl, '_blank');
1087+
// 在当前标签页中打开播放页面
1088+
window.location.href = watchUrl;
10311089
}
10321090

10331091
// 弹出播放器页面
@@ -1046,10 +1104,12 @@ function showVideoPlayer(url) {
10461104
videoPlayerFrame.className = 'fixed w-full h-screen z-40';
10471105
videoPlayerFrame.src = url;
10481106
document.body.appendChild(videoPlayerFrame);
1107+
// 将焦点移入iframe
1108+
videoPlayerFrame.focus();
10491109
}
10501110

10511111
// 关闭播放器页面
1052-
function closeVideoPlayer() {
1112+
function closeVideoPlayer(home = false) {
10531113
videoPlayerFrame = document.getElementById('VideoPlayerFrame');
10541114
if (videoPlayerFrame) {
10551115
videoPlayerFrame.remove();
@@ -1065,6 +1125,10 @@ function closeVideoPlayer() {
10651125
document.getElementById('doubanArea').classList.remove('hidden');
10661126
}
10671127
}
1128+
if (home) {
1129+
// 刷新主页
1130+
window.location.href = '/'
1131+
}
10681132
}
10691133

10701134
// 播放上一集
@@ -1447,14 +1511,4 @@ function saveStringAsFile(content, fileName) {
14471511
window.URL.revokeObjectURL(url);
14481512
}
14491513

1450-
// app.js 或路由文件中
1451-
const authMiddleware = require('./middleware/auth');
1452-
const config = require('./config');
1453-
1454-
// 对所有请求启用鉴权(按需调整作用范围)
1455-
if (config.auth.enabled) {
1456-
app.use(authMiddleware);
1457-
}
1458-
1459-
// 或者针对特定路由
1460-
app.use('/api', authMiddleware);
1514+
// 移除Node.js的require语句,因为这是在浏览器环境中运行的

js/config.js

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const PASSWORD_CONFIG = {
1313
// 网站信息配置
1414
const SITE_CONFIG = {
1515
name: 'JoyyaTV',
16-
url: 'https://Joyyatv.is-an.org',
16+
url: 'https://tv.lvbyte.top',
1717
description: 'Joyya的在线影视站',
1818
logo: './image/retrotv_5520.png',
1919
version: '1.0.3'
@@ -22,91 +22,95 @@ const SITE_CONFIG = {
2222
// API站点配置
2323
const API_SITES = {
2424
dyttzy: {
25-
api: 'http://caiji.dyttzyapi.com',
25+
api: 'http://caiji.dyttzyapi.com/api.php/provide/vod',
2626
name: '电影天堂资源',
27-
detail: 'http://caiji.dyttzyapi.com',
27+
detail: 'http://caiji.dyttzyapi.com',
2828
},
2929
ruyi: {
30-
api: 'https://cj.rycjapi.com',
30+
api: 'https://cj.rycjapi.com/api.php/provide/vod',
3131
name: '如意资源',
3232
},
3333
bfzy: {
34-
api: 'https://bfzyapi.com',
34+
api: 'https://bfzyapi.com/api.php/provide/vod',
3535
name: '暴风资源',
3636
},
3737
tyyszy: {
38-
api: 'https://tyyszy.com',
38+
api: 'https://tyyszy.com/api.php/provide/vod',
3939
name: '天涯资源',
4040
},
4141
// xiaomaomi: {
42-
// api: 'https://zy.xiaomaomi.cc',
42+
// api: 'https://zy.xiaomaomi.cc/api.php/provide/vod',
4343
// name: '小猫咪资源',
4444
// },
4545
ffzy: {
46-
api: 'http://ffzy5.tv',
46+
api: 'http://ffzy5.tv/api.php/provide/vod',
4747
name: '非凡影视',
48-
detail: 'http://ffzy5.tv',
48+
detail: 'http://ffzy5.tv',
4949
},
5050
heimuer: {
51-
api: 'https://json.heimuer.xyz',
51+
api: 'https://json.heimuer.xyz/api.php/provide/vod',
5252
name: '黑木耳',
53-
detail: 'https://heimuer.tv',
53+
detail: 'https://heimuer.tv',
5454
},
5555
zy360: {
56-
api: 'https://360zy.com',
56+
api: 'https://360zy.com/api.php/provide/vod',
5757
name: '360资源',
5858
},
59+
iqiyi: {
60+
api: 'https://www.iqiyizyapi.com/api.php/provide/vod',
61+
name: 'iqiyi资源',
62+
},
5963
wolong: {
60-
api: 'https://wolongzyw.com',
64+
api: 'https://wolongzyw.com/api.php/provide/vod',
6165
name: '卧龙资源',
62-
},
66+
},
6367
hwba: {
64-
api: 'https://cjhwba.com',
68+
api: 'https://cjhwba.com/api.php/provide/vod',
6569
name: '华为吧资源',
6670
},
6771
jisu: {
68-
api: 'https://jszyapi.com',
72+
api: 'https://jszyapi.com/api.php/provide/vod',
6973
name: '极速资源',
70-
detail: 'https://jszyapi.com'
74+
detail: 'https://jszyapi.com',
7175
},
7276
dbzy: {
73-
api: 'https://dbzy.com',
77+
api: 'https://dbzy.com/api.php/provide/vod',
7478
name: '豆瓣资源',
7579
},
7680
mozhua: {
77-
api: 'https://mozhuazy.com',
81+
api: 'https://mozhuazy.com/api.php/provide/vod',
7882
name: '魔爪资源',
7983
},
8084
mdzy: {
81-
api: 'https://www.mdzyapi.com',
85+
api: 'https://www.mdzyapi.com/api.php/provide/vod',
8286
name: '魔都资源',
8387
},
8488
zuid: {
85-
api: 'https://api.zuidapi.com',
89+
api: 'https://api.zuidapi.com/api.php/provide/vod',
8690
name: '最大资源'
8791
},
8892
yinghua: {
89-
api: 'https://m3u8.apiyhzy.com',
93+
api: 'https://m3u8.apiyhzy.com/api.php/provide/vod',
9094
name: '樱花资源'
9195
},
9296
baidu: {
93-
api: 'https://api.apibdzy.com',
97+
api: 'https://api.apibdzy.com/api.php/provide/vod',
9498
name: '百度云资源'
9599
},
96100
wujin: {
97-
api: 'https://api.wujinapi.me',
101+
api: 'https://api.wujinapi.me/api.php/provide/vod',
98102
name: '无尽资源'
99103
},
100104
wwzy: {
101-
api: 'https://wwzy.tv',
105+
api: 'https://wwzy.tv/api.php/provide/vod',
102106
name: '旺旺短剧'
103107
},
104108
ikun: {
105-
api: 'https://ikunzyapi.com',
109+
api: 'https://ikunzyapi.com/api.php/provide/vod',
106110
name: 'iKun资源'
107111
},
108112
testSource: {
109-
api: 'https://www.example.com',
113+
api: 'https://www.example.com/api.php/provide/vod',
110114
name: '空内容测试源',
111115
adult: true
112116
},
@@ -159,6 +163,20 @@ const API_SITES = {
159163
// name: '玉兔资源',
160164
// adult: true
161165
// },
166+
167+
// 下面是资源失效率高的API源,不建议使用
168+
// subo: {
169+
// api: 'https://subocaiji.com/api.php/provide/vod',
170+
// name: '速播资源'
171+
// },
172+
// fczy: {
173+
// api: 'https://api.fczy888.me/api.php/provide/vod',
174+
// name: '蜂巢资源'
175+
// },
176+
// ukzy: {
177+
// api: 'https://api.ukuapi88.com/api.php/provide/vod',
178+
// name: 'U酷资源'
179+
// },
162180
};
163181

164182
// 添加聚合搜索的配置选项
@@ -173,18 +191,18 @@ const AGGREGATED_SEARCH_CONFIG = {
173191
// 抽象API请求配置
174192
const API_CONFIG = {
175193
search: {
176-
// 修改搜索接口支持分页参数
177-
path: '/api.php/provide/vod/?ac=videolist&wd=',
178-
pagePath: '/api.php/provide/vod/?ac=videolist&wd={query}&pg={page}',
194+
// 只拼接参数部分,不再包含 /api.php/provide/vod/
195+
path: '?ac=videolist&wd=',
196+
pagePath: '?ac=videolist&wd={query}&pg={page}',
179197
maxPages: 50, // 最大获取页数
180198
headers: {
181199
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
182200
'Accept': 'application/json'
183201
}
184202
},
185203
detail: {
186-
// 修改详情接口也使用videolist接口,但是通过ID查询,减少请求次数
187-
path: '/api.php/provide/vod/?ac=videolist&ids=',
204+
// 只拼接参数部分
205+
path: '?ac=videolist&ids=',
188206
headers: {
189207
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
190208
'Accept': 'application/json'

js/index-page.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ document.addEventListener('DOMContentLoaded', function() {
3535
if (keyword) {
3636
// 设置搜索框的值
3737
document.getElementById('searchInput').value = keyword;
38+
// 显示清空按钮
39+
toggleClearButton();
3840
// 执行搜索
3941
setTimeout(() => {
4042
// 使用setTimeout确保其他DOM加载和初始化完成

0 commit comments

Comments
 (0)