643 lines
20 KiB
JavaScript
643 lines
20 KiB
JavaScript
// 无限的 debugger 兼容性好
|
||
// setInterval(function () {
|
||
// debuggerCheck();
|
||
// }, 1000);
|
||
// var debuggerCheck = function () {
|
||
// function doCheck(a) {
|
||
// if (('' + a / a)['length'] !== 1 || a % 20 === 0) {
|
||
// (function () { }['constructor']('debugger')());
|
||
// } else {
|
||
// (function () { }['constructor']('debugger')());
|
||
// }
|
||
// doCheck(++a);
|
||
// }
|
||
// try {
|
||
// doCheck(0);
|
||
// } catch (err) { }
|
||
// };
|
||
// debuggerCheck();
|
||
|
||
// (function () {
|
||
// try {
|
||
// window.history.pushState(null, '');
|
||
// window.addEventListener(
|
||
// 'popstate',
|
||
// function () {
|
||
// window.location.href = atob('aHR0cHM6Ly9zczQwLnNnY2l6dC5jb206MTA4My80MC8=');
|
||
// },
|
||
// false
|
||
// );
|
||
// } catch (err) { }
|
||
// })();
|
||
|
||
function formatVideoUrl(strPinYin, intVId) {
|
||
return strVideoUrlTemp
|
||
.replace('{strPinYin}', encodeURIComponent(strPinYin))
|
||
.replace('{intVId}', intVId);
|
||
}
|
||
|
||
function formatVideoPlayUrl(strPinYin, intVId, strPlayType = 'defualt', intPlayIndex = 1) {
|
||
return strVideoPlayUrlTemp
|
||
.replace('{strPinYin}', encodeURIComponent(strPinYin))
|
||
.replace('{intVId}', intVId)
|
||
.replace('{strPlayType}', strPlayType)
|
||
.replace('{intPlayIndex}', intPlayIndex);
|
||
|
||
}
|
||
|
||
function formatSearchUrl(strKey, intPage = 1) {
|
||
return strSearchUrlTemp
|
||
.replace('{strSearchKeywords}', strKey)
|
||
.replace('{intPage}', intPage);
|
||
}
|
||
|
||
/**
|
||
* 获取当前页面的顶级域名
|
||
* @returns {string} - 顶级域名(如 'video.com', 'example.org'),若无法解析则返回空字符串
|
||
*/
|
||
function getTopLevelDomain() {
|
||
try {
|
||
const hostname = window.location.hostname; // 获取完整域名,如 'sub.video.com'
|
||
const parts = hostname.split('.'); // 按点号分割域名
|
||
// 返回最后两部分作为顶级域名(适用于大多数情况,如 'video.com')
|
||
return parts.length >= 2 ? `${parts[parts.length - 2]}.${parts[parts.length - 1]}` : '';
|
||
} catch (error) {
|
||
console.error('获取顶级域名失败:', error.message);
|
||
return '';
|
||
}
|
||
}
|
||
|
||
function isMobile() {
|
||
const ua = navigator.userAgent || navigator.vendor || window.opera;
|
||
|
||
// 常见移动端关键词
|
||
const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Windows Phone/i;
|
||
|
||
// 微信/QQ/支付宝内置浏览器也算移动端
|
||
const isMiniBrowser = /MicroMessenger|QQ\/|AlipayClient/i.test(ua);
|
||
|
||
// 判断触控点(Touch device)
|
||
const isTouchDevice = ('maxTouchPoints' in navigator && navigator.maxTouchPoints > 0) ||
|
||
('ontouchstart' in window);
|
||
|
||
return mobileRegex.test(ua) || isMiniBrowser || isTouchDevice;
|
||
}
|
||
|
||
// 懒加载
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
// 通用懒加载函数
|
||
function lazyLoad(elements, callback) {
|
||
const observer = new IntersectionObserver((entries, observer) => {
|
||
entries.forEach(entry => {
|
||
if (entry.isIntersecting) {
|
||
const element = entry.target;
|
||
callback(element);
|
||
observer.unobserve(element);
|
||
}
|
||
});
|
||
}, {
|
||
rootMargin: '100px' // 提前 100px 开始加载
|
||
});
|
||
|
||
elements.forEach(element => observer.observe(element));
|
||
}
|
||
|
||
// 背景封面懒加载
|
||
const lazyBackgrounds = document.querySelectorAll(".lazyload-bg");
|
||
lazyLoad(lazyBackgrounds, (element) => {
|
||
const src = element.getAttribute("data-src");
|
||
if (src) {
|
||
const img = new Image();
|
||
img.src = src;
|
||
img.onload = () => {
|
||
element.style.backgroundImage = `url(${src})`;
|
||
element.classList.remove("lazyload-bg");
|
||
};
|
||
img.onerror = () => {
|
||
// console.error(`Failed to load background image: ${src}`);
|
||
// 可选:设置默认背景或错误提示
|
||
};
|
||
}
|
||
});
|
||
|
||
// 章节图片懒加载
|
||
const lazyImages = document.querySelectorAll(".lazyload-img");
|
||
lazyLoad(lazyImages, (element) => {
|
||
const src = element.getAttribute("data-src");
|
||
if (src) {
|
||
const img = new Image();
|
||
img.src = src;
|
||
img.onload = () => {
|
||
element.setAttribute("src", src);
|
||
element.classList.remove("lazyload-img");
|
||
};
|
||
img.onerror = () => {
|
||
// console.error(`Failed to load image: ${src}`);
|
||
// 可选:设置占位图或错误提示
|
||
};
|
||
}
|
||
});
|
||
});
|
||
|
||
function handleRedirect() {
|
||
const { pathname, origin, search } = window.location;
|
||
|
||
// 规范化路径名,将多个斜杠替换为单个斜杠
|
||
const normalizedPath = pathname.replace(/\/+/g, '/');
|
||
var strCurrentPath = normalizedPath || '/index.html';
|
||
const arrPcPathUrl = ['/pc', '/web', '/desktop', '/index', '/shouye', '/zhuomian', '/windows']; // 所有模板的 PC 目录
|
||
// 构建URL,确保斜杠正确
|
||
const buildUrl = (path) => {
|
||
const cleanPath = `/${path.replace(/\/+/g, '/')}`.replace(/^\/+/, '/');
|
||
return `${origin}${cleanPath}${search}`;
|
||
};
|
||
|
||
// 获取当前路径的第一个目录
|
||
var firstSegment = strCurrentPath.split('/')[1] || '';
|
||
|
||
// 判断当前路径的第一个目录是否在其它模板的 PC 目录中
|
||
const isInPcPathArray = arrPcPathUrl.some(pcPath => firstSegment.startsWith(pcPath.replace('/', '')));
|
||
|
||
if (isMobile()) {
|
||
// 如果第一个目录 在pc 模板里面 则删除替换成空
|
||
if (isInPcPathArray) {
|
||
const newPath = strCurrentPath.replace(firstSegment, '');
|
||
window.location.href = buildUrl(newPath);
|
||
}
|
||
|
||
} else {
|
||
|
||
if (!isInPcPathArray) {
|
||
const newPath = strCurrentPath === '/' ? `/` : `${strCurrentPath}`;
|
||
window.location.href = buildUrl(newPath);
|
||
} else {
|
||
// 如果包含,则先判断是不是当前模板的 url,如果不是 则替换成当前模板的 url
|
||
if (firstSegment != strPcPath.replace('/', '')) {
|
||
strCurrentPath = strCurrentPath.replace(firstSegment, strPcPath.replace('/', ''));
|
||
window.location.href = buildUrl(strCurrentPath);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// handleRedirect();
|
||
|
||
function layerPopup(strContent, intTime) {
|
||
layer.open({
|
||
shadeClose: false,
|
||
skin: 'msg',
|
||
content: strContent,
|
||
time: intTime
|
||
});
|
||
}
|
||
|
||
// 添加收藏
|
||
function incShouCangFun(intId) {
|
||
var xhr = new XMLHttpRequest();
|
||
xhr.open('GET', "/sc?intId=" + intId, true);
|
||
xhr.setRequestHeader('accept', 'application/x.hubserver.admin+json');
|
||
xhr.send();
|
||
xhr.onreadystatechange = function () {
|
||
|
||
if (xhr.readyState == 4 && xhr.status == 200) {
|
||
layerPopup('收藏成功', 3)
|
||
}
|
||
if (xhr.readyState == 4 && xhr.status == 0) {
|
||
layerPopup('操作太频繁,稍后再试', 3)
|
||
}
|
||
}
|
||
}
|
||
|
||
const strBookshelfKey = window.location.hostname + 'strBookshelfKey';
|
||
const strHistoryKey = window.location.hostname + 'strHistoryKey';
|
||
|
||
// 加入书架
|
||
function addBookshelfFun(NovelInfo) {
|
||
|
||
if (!NovelInfo) {
|
||
NovelInfo = arrNovel
|
||
}
|
||
|
||
let arrBookshelf = JSON.parse(localStorage.getItem(strBookshelfKey)) || [];
|
||
|
||
// 检查书籍是否已存在
|
||
const index = arrBookshelf.findIndex(item => item.n_id === NovelInfo.n_id);
|
||
|
||
if (index !== -1) {
|
||
// 如果存在,更新该书籍的信息
|
||
arrBookshelf[index] = { ...arrBookshelf[index], ...NovelInfo };
|
||
layerPopup('已存在书架中!', 3)
|
||
} else {
|
||
// 如果不存在,添加到历史记录
|
||
arrBookshelf.push(NovelInfo);
|
||
layerPopup('已成功加入书架!', 3)
|
||
}
|
||
|
||
// 更新本地存储
|
||
localStorage.setItem(strBookshelfKey, JSON.stringify(arrBookshelf));
|
||
|
||
}
|
||
|
||
|
||
function displayShujia() {
|
||
|
||
// 获取书架数据
|
||
const shujia = JSON.parse(localStorage.getItem(strBookshelfKey)) || [];
|
||
|
||
if (shujia.length === 0) {
|
||
console.log('书架为空');
|
||
return;
|
||
}
|
||
|
||
// 渲染书籍列表
|
||
const shujiaContainer = document.getElementById('shujiaContainer');
|
||
shujiaContainer.innerHTML = ''; // 清空原内容
|
||
shujia.forEach(book => {
|
||
const bookElement = document.createElement('div');
|
||
let strNovelUrl = formatNovelUrl(book.n_name_pinyin, book.n_id)
|
||
let strNovelChapterUrl = formatNovelChapterUrl(book.n_name_pinyin, book.n_id, book.c_sort_num)
|
||
let strSearchUrl = formatSearchUrl(book.n_author, 1)
|
||
if (isMobile()) {
|
||
bookElement.innerHTML = `
|
||
<dl class="rec-focus-book">
|
||
<dt class="book-img">
|
||
<a href='${strNovelUrl}'>
|
||
<img height="100" width="80" src="${book.n_cover_path}" >
|
||
</a>
|
||
</dt>
|
||
<dd class="book-info">
|
||
<h2><a href='${strNovelUrl}'>${book.n_name}</a></h2>
|
||
<p>作者: ${book.n_author}</p>
|
||
<p> ${book.c_name}</p>
|
||
</dd>
|
||
</dl>
|
||
|
||
|
||
`;
|
||
} else {
|
||
bookElement.innerHTML = `
|
||
<div class="item">
|
||
<div class="image">
|
||
<a href='${strNovelUrl}'>
|
||
<img style="min-height:120px;" src="${book.n_cover_path}" alt="${book.n_name}">
|
||
</a>
|
||
</div>
|
||
<dl>
|
||
<dt>
|
||
<span>${book.n_author}</span>
|
||
<a href='${strNovelUrl}'>${book.n_name}</a>
|
||
</dt>
|
||
<dd style="height:90px">
|
||
<a href='${strNovelChapterUrl}'
|
||
style="color: #555">${book.c_name}</a>
|
||
</dd>
|
||
</dl>
|
||
</div>
|
||
|
||
`;
|
||
}
|
||
|
||
shujiaContainer.appendChild(bookElement);
|
||
});
|
||
|
||
|
||
|
||
}
|
||
|
||
// 加入阅读记录
|
||
function addHistoryFun(VideoInfo) {
|
||
// 如果没有传入 VideoInfo arrVideo 并补充字段
|
||
if (!VideoInfo) {
|
||
VideoInfo = arrVideo
|
||
|
||
}
|
||
|
||
// 获取本地存储中的历史记录
|
||
let arrHistory = JSON.parse(localStorage.getItem(strHistoryKey)) || [];
|
||
// 检查书籍是否已存在
|
||
const index = arrHistory.findIndex(item => item.v_id == VideoInfo.v_id);
|
||
|
||
if (index !== -1) {
|
||
// 如果存在,更新该书籍的信息
|
||
arrHistory[index] = { ...arrHistory[index], ...VideoInfo };
|
||
} else {
|
||
// 如果不存在,添加到历史记录
|
||
arrHistory.push(VideoInfo);
|
||
}
|
||
|
||
// 更新本地存储
|
||
localStorage.setItem(strHistoryKey, JSON.stringify(arrHistory));
|
||
}
|
||
|
||
|
||
const defaultTemplate = `
|
||
<li class="active clearfix">
|
||
<div class="thumb">
|
||
<a class="v-thumb stui-vodlist__thumb lazyload-bg"
|
||
href="{{videoUrl}}"
|
||
title="{{videoName}}"
|
||
data-src="{{videoPic}}">
|
||
<span class="play hidden-xs"></span>
|
||
<span class="pic-text text-right">{{videoRemarks}}</span>
|
||
</a>
|
||
</div>
|
||
<div class="detail">
|
||
<h3 class="title">
|
||
<a href="{{videoUrl}}">{{videoName}}</a>
|
||
</h3>
|
||
<p class="hidden-mi">
|
||
<span class="text-muted">简介:</span>
|
||
{{videoDescription}}
|
||
</p>
|
||
<p class="hidden-mi">
|
||
<span class="text-muted">类型:</span>
|
||
{{videoCategory}}
|
||
<span class="split-line"></span>
|
||
<span class="hidden-xs">
|
||
<span class="split-line"></span>
|
||
<span class="text-muted">年份:</span>
|
||
{{videoYear}}
|
||
</span>
|
||
</p>
|
||
<p class="margin-0">
|
||
<a class="btn btn-min btn-primary" href="{{videoPlayUrl}}">立即播放</a>
|
||
|
||
<a class="btn btn-min btn-default" href="{{videoUrl}}">查看详情</a>
|
||
</p>
|
||
</div>
|
||
</li>
|
||
`;
|
||
|
||
// 渲染历史记录函数,接受自定义模板参数
|
||
function displayHistory(template = defaultTemplate) {
|
||
// 获取数据
|
||
const arrHistory = JSON.parse(localStorage.getItem(strHistoryKey)) || [];
|
||
|
||
if (arrHistory.length === 0) {
|
||
console.log('记录为空');
|
||
return;
|
||
}
|
||
|
||
// 渲染列表
|
||
const historyContainer = document.getElementById('historyContainer');
|
||
if (!historyContainer) {
|
||
console.error('历史记录容器未找到');
|
||
return;
|
||
}
|
||
historyContainer.innerHTML = ''; // 清空原内容
|
||
|
||
arrHistory.forEach((video) => {
|
||
// 生成URL
|
||
const strVideoUrl = formatVideoUrl(video.v_name_en, video.v_id);
|
||
const strVideoPlayUrl = formatVideoPlayUrl(video.v_name_en, video.v_id, 'default', 1);
|
||
const strSearchUrl = formatSearchUrl(video.v_name, 1);
|
||
|
||
// 替换模板中的占位符
|
||
const renderedTemplate = template
|
||
.replace(/{{videoUrl}}/g, strVideoUrl)
|
||
.replace(/{{videoName}}/g, escapeHtml(video.v_name)) // 防止XSS
|
||
.replace(/{{videoPic}}/g, escapeHtml(video.v_pic))
|
||
.replace(/{{videoRemarks}}/g, escapeHtml(video.v_remarks))
|
||
.replace(/{{videoDescription}}/g, escapeHtml(video.v_description))
|
||
.replace(/{{videoCategory}}/g, escapeHtml(video.v_category))
|
||
.replace(/{{videoParentCategory}}/g, escapeHtml(video.v_parent_category))
|
||
.replace(/{{videoYear}}/g, escapeHtml(video.v_year))
|
||
.replace(/{{videoActor}}/g, escapeHtml(video.v_area))
|
||
.replace(/{{videoPlayUrl}}/g, strVideoPlayUrl)
|
||
.replace(/{{searchUrl}}/g, strSearchUrl);
|
||
|
||
// 创建元素并添加到容器
|
||
const videoElement = document.createElement('li');
|
||
videoElement.innerHTML = renderedTemplate;
|
||
historyContainer.appendChild(videoElement);
|
||
});
|
||
}
|
||
|
||
// 防止XSS攻击的转义函数
|
||
function escapeHtml(str) {
|
||
if (!str) return '';
|
||
return str.replace(/[&<>"']/g, (match) => ({
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"',
|
||
"'": '''
|
||
}[match]));
|
||
}
|
||
|
||
async function reportStats(data) {
|
||
|
||
try {
|
||
const response = await fetch(strPushApi + '/publishv', {
|
||
method: 'POST',
|
||
// mode: 'no-cors', // 添加这行
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
// 如果需要认证可以添加
|
||
'Authorization': 'Bearer your-token'
|
||
},
|
||
body: JSON.stringify(data)
|
||
});
|
||
|
||
if (!response.ok) {
|
||
throw new Error('上报失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('上报错误:', error);
|
||
}
|
||
}
|
||
|
||
function initDPlayer(strPlayUrl) {
|
||
let DomDPlayer = document.getElementById('dplayer')
|
||
videoPlayer = new DPlayer({
|
||
container: DomDPlayer,
|
||
autoplay: true,
|
||
screenshot: false,
|
||
//logo: dplayerLogo,
|
||
video: {
|
||
url: strPlayUrl,
|
||
type: 'hls',
|
||
},
|
||
pluginOptions: {
|
||
hls: {
|
||
maxBufferLength: 600,
|
||
},
|
||
},
|
||
});
|
||
|
||
videoPlayer.play()
|
||
|
||
// 监听全屏进入事件
|
||
videoPlayer.on('fullscreen', function () {
|
||
DomDPlayer.classList.add("dp-fullscreen");
|
||
// 设置视频元素的样式,取消 max-height
|
||
document.querySelector("video").style.maxHeight = "none";
|
||
document.querySelector(".video-play-page .dplayer-video-wrap").style.maxHeight = "none";
|
||
|
||
});
|
||
|
||
// 监听全屏退出事件
|
||
videoPlayer.on('fullscreen_cancel', function () {
|
||
DomDPlayer.classList.remove("dp-fullscreen");
|
||
// 恢复 max-height 为 480px
|
||
if (isMobile()) {
|
||
document.querySelector("video").style.maxHeight = "218px";
|
||
document.querySelector(".video-play-page .dplayer-video-wrap").style.maxHeight = "218px";
|
||
} else {
|
||
document.querySelector("video").style.maxHeight = strMaxPlayHeight ?? '480px';
|
||
document.querySelector(".video-play-page .dplayer-video-wrap").style.maxHeight = strMaxPlayHeight ?? '480px';
|
||
}
|
||
|
||
});
|
||
|
||
videoPlayer.on('error', function () {
|
||
|
||
});
|
||
videoPlayer.on('play', function () {
|
||
|
||
});
|
||
// 监听当前播放时间
|
||
videoPlayer.on('timeupdate', function () {
|
||
|
||
});
|
||
}
|
||
|
||
function findFirstUrl(obj) {
|
||
// 优先取 默认
|
||
// if (Array.isArray(obj?.douban) && obj.douban.length > 0 && obj.douban[0].url) {
|
||
// return obj.douban[0].url;
|
||
// }
|
||
// 如果没有 douban,尝试取对象中第一个数组的第一个 url
|
||
for (const key in obj) {
|
||
if (Array.isArray(obj[key]) && obj[key].length > 0 && obj[key][0].url) {
|
||
return obj[key];
|
||
// return obj[key][0].url;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
|
||
// 切换播放线路
|
||
// 切换播放线路
|
||
function checkLine(val) {
|
||
// 构造 ID
|
||
let strLineHeadId = `line_head_${val}`;
|
||
let strLineListId = `playlist_${val}`;
|
||
|
||
// 获取目标元素
|
||
let headElement = document.getElementById(strLineHeadId);
|
||
let listElement = document.getElementById(strLineListId);
|
||
|
||
// 获取所有头部导航和播放列表
|
||
let navItems = document.querySelectorAll('.play-group-head');
|
||
let tabPanes = document.querySelectorAll('.play-group-list');
|
||
|
||
// ✅ 如果目标元素不存在,则默认选中第一个
|
||
if (!headElement || !listElement) {
|
||
if (navItems.length > 0 && tabPanes.length > 0) {
|
||
headElement = navItems[0];
|
||
listElement = tabPanes[0];
|
||
} else {
|
||
console.warn('没有可用的播放线路元素');
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 1. 更新头部导航 active 状态
|
||
navItems.forEach(item => {
|
||
item.classList.toggle('active', item === headElement);
|
||
});
|
||
|
||
// 2. 更新播放列表 active 状态
|
||
tabPanes.forEach(pane => {
|
||
pane.classList.toggle('active', pane === listElement);
|
||
});
|
||
}
|
||
|
||
function reorderObj(obj) {
|
||
if (!obj || typeof obj !== 'object') return obj;
|
||
let newObj = {};
|
||
if (obj.hasOwnProperty('douban')) {
|
||
newObj['douban'] = obj['douban'];
|
||
}
|
||
for (let key in obj) {
|
||
if (key !== 'douban' && obj.hasOwnProperty(key)) {
|
||
newObj[key] = obj[key];
|
||
}
|
||
}
|
||
return newObj;
|
||
}
|
||
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
|
||
|
||
if (typeof strVideoId !== "undefined") {
|
||
|
||
// if (typeof arrPlayUrl !== "undefined" && arrPlayUrl) {
|
||
// arrPlayUrl = reorderObj(arrPlayUrl);
|
||
// }
|
||
|
||
// 使用示例
|
||
const statsData = {
|
||
v_id: strVideoId,
|
||
};
|
||
|
||
// 调用方法1
|
||
reportStats(statsData);
|
||
|
||
// if (typeof strPlayType !== "undefined" && boolIsPlayPage) {
|
||
// if (strPlayType == 'default') {
|
||
// strPlayUrl = findFirstUrl(arrPlayUrl)
|
||
// checkLine('douban');
|
||
// } else {
|
||
// var ActivePlayUrl = arrPlayUrl[strPlayType][intPlayUrlIndex - 1]
|
||
// strPlayUrl = ActivePlayUrl.url
|
||
// checkLine(strPlayType);
|
||
// }
|
||
// initDPlayer(strPlayUrl)
|
||
// }else if(strPlayType == "default" && !boolIsPlayPage){
|
||
// checkLine('douban');
|
||
// }
|
||
if (typeof strPlayType !== "undefined" && boolIsPlayPage) {
|
||
|
||
// 用户指定线路
|
||
if (strPlayType !== "default") {
|
||
const activeUrl = arrPlayUrl[strPlayType][intPlayUrlIndex - 1];
|
||
strPlayUrl = activeUrl.url;
|
||
checkLine(strPlayType);
|
||
|
||
// 默认播放第一个线路的第一个 URL
|
||
} else {
|
||
const defaultLine = getDefaultLine();
|
||
strPlayUrl = getFirstPlayUrl(defaultLine);
|
||
checkLine(defaultLine);
|
||
}
|
||
|
||
initDPlayer(strPlayUrl);
|
||
|
||
} else if (strPlayType == "default" && !boolIsPlayPage) {
|
||
|
||
const defaultLine = getDefaultLine();
|
||
checkLine(defaultLine);
|
||
}
|
||
|
||
addHistoryFun();
|
||
|
||
}
|
||
|
||
// 获取第一个线路 key
|
||
function getDefaultLine() {
|
||
return Object.keys(arrPlayUrl)[0]; // 后端已经排序,第一位永远是默认线路
|
||
}
|
||
|
||
// 获取某个线路的第一个 url
|
||
function getFirstPlayUrl(playLine) {
|
||
return arrPlayUrl[playLine][0].url;
|
||
}
|
||
|
||
|
||
})
|
||
|
||
|