/* @header({ searchable: 1, filterable: 1, quickSearch: 1, title: 'alist', lang: 'cat' }) */ // import {distance} from '../catLib/mod.js' import {distance} from 'assets://js/lib/mod.js' // import {sortListByCN} from '../catLib/sortName.js' import {sortListByCN} from 'assets://js/lib/sortName.js' import {ungzip} from "../../libs_drpy/drpyCustom.js"; /** * alist js * 配置设置 {"key":"Alist","name":"Alist","type":3,"api":"http://xxx.com/alist.js","searchable":0,"quickSearch":0,"filterable":0,"ext":"http://xxx.com/alist.json"} * alist.json [{ name:'名称', server:'地址', startPage:'/', //启动文件夹 showAll: false , //是否显示全部文件,默认false只显示 音视频和文件夹 search: true, // 启用小雅的搜索,搜索只会搜第一个开启此开关的磁盘 params:{ //对应文件夹参数 如设置对应文件夹的密码 '/abc':{ password : '123' }, '/abc/abc':{ password : '123' }, } }] * 提示 想要加载文件夹里面全部视频到详情(看剧可以自动播放下一集支持历史记录) * 需要改软件才能支持,,建议长按文件夹时添加判断 tag == folder 时跳转 DetailActivity */ String.prototype.rstrip = function (chars) { let regex = new RegExp(chars + "$"); return this.replace(regex, ""); }; var showMode = 'single'; var searchDriver = ''; var limit_search_show = 200; var search_type = ''; var detail_order = 'name'; var playRaw = 1; // 播放直链获取,默认0直接拼接/d 填1可以获取阿里oss链接。注意,有时效性 const request_timeout = 5000; const VERSION = 'alist v2/v3 20221223'; const UA = 'Mozilla/5.0'; //默认请求ua /** * 打印日志 * @param any 任意变量 */ function print(any) { any = any || ''; if (typeof (any) == 'object' && Object.keys(any).length > 0) { try { any = JSON.stringify(any); console.log(any); } catch (e) { // console.log('print:'+e.message); console.log(typeof (any) + ':' + any.length); } } else if (typeof (any) == 'object' && Object.keys(any).length < 1) { console.log('null object'); } else { console.log(any); } } /*** js自封装的方法 ***/ /** * 获取链接的host(带http协议的完整链接) * @param url 任意一个正常完整的Url,自动提取根 * @returns {string} */ function getHome(url) { if (!url) { return '' } let tmp = url.split('//'); url = tmp[0] + '//' + tmp[1].split('/')[0]; try { url = decodeURIComponent(url); } catch (e) { } return url } const http = async function (url, options = {}) { // console.log('http url:', url); if (options.method === 'POST' && options.data) { options.body = JSON.stringify(options.data); options.headers = Object.assign({'content-type': 'application/json'}, options.headers); } options.timeout = request_timeout; if (!options.headers) { options.headers = {}; } let keys = Object.keys(options.headers).map(it => it.toLowerCase()); if (!keys.includes('referer')) { options.headers['Referer'] = getHome(url); } if (!keys.includes('user-agent')) { options.headers['User-Agent'] = UA; } console.log(JSON.stringify(options.headers)); try { const res = await req(url, options); // if(options.headers['Authorization']){ // console.log(res.content); // } res.json = () => res && res.content ? JSON.parse(res.content) : null; res.text = () => res && res.content ? res.content : ''; return res } catch (e) { log('http error:', e.message) return { json() { return null }, text() { return '' } } } }; ["get", "post"].forEach(method => { http[method] = function (url, options = {}) { return http(url, Object.assign(options, {method: method.toUpperCase()})); } }); const __drives = {}; function isMedia(file) { return /\.(dff|dsf|mp3|aac|wav|wma|cda|flac|m4a|mid|mka|mp2|mpa|mpc|ape|ofr|ogg|ra|wv|tta|ac3|dts|tak|webm|wmv|mpeg|mov|ram|swf|mp4|avi|rm|rmvb|flv|mpg|mkv|m3u8|ts|3gp|asf)$/.test(file.toLowerCase()); } async function get_drives_path(tid) { const index = tid.indexOf('$'); const name = tid.substring(0, index); const path = tid.substring(index + 1); return {drives: await get_drives(name), path}; } async function get_drives(name) { const {settings, api, server, headers} = __drives[name]; if (settings.v3 == null) { //获取 设置 settings.v3 = false; const data = (await http.get(server + '/api/public/settings', {headers: headers})).json().data; if (Array.isArray(data)) { settings.title = data.find(x => x.key === 'title')?.value; settings.v3 = false; settings.version = data.find(x => x.key === 'version')?.value; settings.enableSearch = data.find(x => x.key === 'enable search')?.value === 'true'; } else { settings.title = data.title; settings.v3 = true; settings.version = data.version; settings.enableSearch = false; //v3 没有找到 搜索配置 } //不同版本 接口不一样 api.path = settings.v3 ? '/api/fs/list' : '/api/public/path'; api.file = settings.v3 ? '/api/fs/get' : '/api/public/path'; api.search = settings.v3 ? '/api/public/search' : '/api/public/search'; } return __drives[name] } let _CFG = {}; async function init(cfg) { console.log("当前版本号:" + VERSION); let data; _CFG = cfg; // if(ext && typeof ext === 'string' && !/http/.test(ext)){ // try { // ext = ungzip(ext) // }catch (e) {} // } let ext = cfg.ext; console.log('ext:', ext); if (typeof ext == 'object') { data = ext; print('alist ext:object'); } else if (typeof ext == 'string') { if (ext.startsWith('http')) { let alist_data = ext.split(';'); let alist_data_url = alist_data[0]; limit_search_show = alist_data.length > 1 ? Number(alist_data[1]) || limit_search_show : limit_search_show; search_type = alist_data.length > 2 ? alist_data[2] : search_type; data = (await http.get(alist_data_url)).json(); // .map(it=>{it.name='🙋丫仙女';return it}) // log('data:', data); } else { print('alist ext:json string'); data = JSON.parse(ext); } } // log('data:', data); // 测试证明壳子标题支持emoji,是http请求源码不支持emoji let drives = []; if (Array.isArray(data) && data.length > 0 && data[0].hasOwnProperty('server') && data[0].hasOwnProperty('name')) { drives = data; } else if (!Array.isArray(data) && data.hasOwnProperty('drives') && Array.isArray(data.drives)) { drives = data.drives.filter(it => (it.type && it.type === 'alist') || !it.type); } // print(drives); searchDriver = (drives.find(x => x.search) || {}).name || ''; if (!searchDriver && drives.length > 0) { searchDriver = drives[0].name; } print(searchDriver); drives.forEach(item => { let _path_param = []; if (item.params) { _path_param = Object.keys(item.params); // 升序排列 _path_param.sort((a, b) => (a.length - b.length)); } if (item.password) { let pwdObj = { password: item.password }; if (!item.params) { item.params = {'/': pwdObj}; } else { item.params['/'] = pwdObj; } _path_param.unshift('/'); } __drives[item.name] = { name: item.name, server: item.server.endsWith("/") ? item.server.rstrip("/") : item.server, startPage: item.startPage || '/', //首页 showAll: item.showAll === true, //默认只显示 视频和文件夹,如果想显示全部 showAll 设置true search: !!item.search, //是否支持搜索,只有小丫的可以,多个可搜索只取最前面的一个 params: item.params || {}, _path_param: _path_param, settings: {}, api: {}, headers: item.headers || {}, getParams(path) { const key = this._path_param.find(x => path.startsWith(x)); return Object.assign({}, this.params[key], {path}); }, async getPath(path) { const res = (await http.post(this.server + this.api.path, { data: this.getParams(path), headers: this.headers })).json(); // console.log(res); try { return this.settings.v3 ? res.data.content : res.data.files } catch (e) { console.log(`getPath发生错误:${e.message}`); console.log(JSON.stringify(res)); return [{name: 'error', value: JSON.stringify(res)}] } }, async getFile(path) { let raw_url = this.server + '/d' + path; raw_url = encodeURI(raw_url); let data = {raw_url: raw_url, raw_url1: raw_url}; if (playRaw === 1) { try { const res = (await http.post(this.server + this.api.file, { data: this.getParams(path), headers: this.headers })).json(); data = this.settings.v3 ? res.data : res.data.files[0]; if (!this.settings.v3) { data.raw_url = data.url; //v2 的url和v3不一样 } data.raw_url1 = raw_url; return data } catch (e) { return data } } else { return data } }, isFolder(data) { return data.type === 1 }, isVideo(data) { //判断是否是 视频文件 // return this.settings.v3 ? data.type === 2 : data.type === 3 // 增加音乐识别 视频,其他,音频 return this.settings.v3 ? (data.type === 2 || data.type === 0 || data.type === 3) : (data.type === 3 || data.type === 0 || data.type === 4) }, is_subt(data) { if (data.type === 1) { return false; } const ext = /\.(srt|ass|scc|stl|ttml)$/; // [".srt", ".ass", ".scc", ".stl", ".ttml"]; // return ext.some(x => data.name.endsWith(x)); return ext.test(data.name); }, getPic(data) { let pic = this.settings.v3 ? data.thumb : data.thumbnail; return pic || (this.isFolder(data) ? "https://t9.baidu.com/it/u=2555298136,3592163114&fm=193" : ''); }, getTime(data, isStandard) { isStandard = isStandard || false; try { let tTime = data.updated_at || data.time_str || data.modified || ""; let date = ''; if (tTime) { tTime = tTime.split("T"); date = tTime[0]; if (isStandard) { date = date.replace(/-/g, "/"); } tTime = tTime[1].split(/Z|\./); date += " " + tTime[0]; } return date; } catch (e) { // print(e.message); // print(data); return '' } }, } } ); print('init执行完毕'); } async function home(filter) { let classes = Object.keys(__drives).map(key => ({ type_id: `${key}$${__drives[key].startPage}`, type_name: key, type_flag: '1', })); let filter_dict = {}; let filters = [{ 'key': 'order', 'name': '排序', 'value': [{'n': '名称⬆️', 'v': 'vod_name_asc'}, {'n': '名称⬇️', 'v': 'vod_name_desc'}, {'n': '中英⬆️', 'v': 'vod_cn_asc'}, {'n': '中英⬇️', 'v': 'vod_cn_desc'}, {'n': '时间⬆️', 'v': 'vod_time_asc'}, {'n': '时间⬇️', 'v': 'vod_time_desc'}, {'n': '大小⬆️', 'v': 'vod_size_asc'}, {'n': '大小⬇️', 'v': 'vod_size_desc'}, {'n': '无', 'v': 'none'}] }, {'key': 'show', 'name': '播放展示', 'value': [{'n': '单集', 'v': 'single'}, {'n': '全集', 'v': 'all'}]} ]; classes.forEach(it => { filter_dict[it.type_id] = filters; }); print("----home----"); print(classes); return JSON.stringify({'class': classes, 'filters': filter_dict}); } async function homeVod(params) { let _post_data = {"pageNum": 0, "pageSize": 100}; let _post_url = 'https://pbaccess.video.qq.com/trpc.videosearch.hot_rank.HotRankServantHttp/HotRankHttp'; let data = (await http.post(_post_url, {data: _post_data})).json(); let _list = []; try { data = data['data']['navItemList'][0]['hotRankResult']['rankItemList']; // print(data); data.forEach(it => { _list.push({ vod_name: it.title, vod_id: 'msearch:' + it.title, vod_pic: 'https://avatars.githubusercontent.com/u/97389433?s=120&v=4', vod_remarks: it.changeOrder, }); }); } catch (e) { print('Alist获取首页推荐发送错误:' + e.message); } return JSON.stringify({'list': _list}); } async function category(tid, pg, filter, extend) { let orid = tid.replace(/#all#|#search#/g, ''); let {drives, path} = await get_drives_path(orid); const id = orid.endsWith('/') ? orid : orid + '/'; // log('drives:',drives); const list = await drives.getPath(path); let subList = []; let vodFiles = []; let allList = []; let fl = filter ? extend : {}; if (fl.show) { showMode = fl.show; } list.forEach(item => { if (item.name !== 'error') { if (drives.is_subt(item)) { subList.push(item.name); } if (!drives.showAll && !drives.isFolder(item) && !drives.isVideo(item)) { return //只显示视频文件和文件夹 } let vod_time = drives.getTime(item); let vod_size = get_size(item.size); let remark = vod_time.split(' ')[0].substr(3) + '\t' + vod_size; let vod_id = id + item.name + (drives.isFolder(item) ? '/' : ''); if (showMode === 'all') { vod_id += '#all#'; } print(vod_id); const vod = { 'vod_id': vod_id, 'vod_name': item.name.replaceAll("$", "").replaceAll("#", ""), 'vod_pic': drives.getPic(item), 'vod_time': vod_time, 'vod_size': item.size, 'vod_tag': drives.isFolder(item) ? 'folder' : 'file', 'vod_remarks': drives.isFolder(item) ? remark + ' 文件夹' : remark }; if (drives.isVideo(item)) { vodFiles.push(vod); } allList.push(vod); } else { console.log(item); const vod = { vod_name: item.value, vod_id: 'no_data', vod_remarks: '不要点,会崩的', vod_pic: 'https://ghproxy.net/https://raw.githubusercontent.com/hjdhnx/dr_py/main/404.jpg' } allList.push(vod); } }); if (vodFiles.length === 1 && subList.length > 0) { //只有一个视频 一个或者多个字幕 取相似度最高的 // let sub = subList.length === 1 ? subList[0] : _.chain(allList).sortBy(x => (x.includes('chs') ? 100 : 0) + levenshteinDistance(x, vodFiles[0].vod_name)).last().value(); let sub; // 字幕文件名称 if (subList.length === 1) { sub = subList[0]; } else { let subs = JSON.parse(JSON.stringify(subList)); subs.sort((a, b) => { // chs是简体中文字幕 let a_similar = (a.includes('chs') ? 100 : 0) + levenshteinDistance(a, vodFiles[0].vod_name); let b_similar = (b.includes('chs') ? 100 : 0) + levenshteinDistance(b, vodFiles[0].vod_name); if (a_similar > b_similar) { // 按相似度正序排列 return 1; } else { //否则,位置不变 return -1; } }); sub = subs.slice(-1)[0]; } vodFiles[0].vod_id += "@@@" + sub; // vodFiles[0].vod_remarks += " 有字幕"; vodFiles[0].vod_remarks += "🏷️"; } else { vodFiles.forEach(item => { const lh = 0; let sub; subList.forEach(s => { //编辑距离相似度 const l = levenshteinDistance(s, item.vod_name); if (l > 60 && l > lh) { sub = s; } }); if (sub) { item.vod_id += "@@@" + sub; // item.vod_remarks += " 有字幕"; item.vod_remarks += "🏷️"; } }); } if (fl.order) { // print(fl.order); let key = fl.order.split('_').slice(0, -1).join('_'); let order = fl.order.split('_').slice(-1)[0]; print(`排序key:${key},排序order:${order}`); if (key.includes('name')) { detail_order = 'name'; allList = sortListByName(allList, key, order); } else if (key.includes('cn')) { detail_order = 'cn'; allList = sortListByCN(allList, 'vod_name', order); } else if (key.includes('time')) { detail_order = 'time'; allList = sortListByTime(allList, key, order); } else if (key.includes('size')) { detail_order = 'size'; allList = sortListBySize(allList, key, order); } else if (fl.order.includes('none')) { detail_order = 'none'; print('不排序'); } } else { // 没传order是其他地方调用的,自动按名称正序排序方便追剧,如果传了none进去就不排序,假装云盘里本身文件顺序是正常的 if (detail_order !== 'none') { allList = sortListByName(allList, 'vod_name', 'asc'); } } print("----category----" + `tid:${tid},detail_order:${detail_order},showMode:${showMode}`); // print(allList); return JSON.stringify({ 'page': 1, 'pagecount': 1, 'limit': allList.length, 'total': allList.length, 'list': allList, }); } async function getAll(otid, tid, drives, path) { try { const content = await category(tid, null, false, null); const isFile = isMedia(otid.replace(/#all#|#search#/g, '').split('@@@')[0]); const {list} = JSON.parse(content); let vod_play_url = []; list.forEach(x => { if (x.vod_tag === 'file') { let vid = x.vod_id.replace(/#all#|#search#/g, ''); vod_play_url.push(`${x.vod_name}$${vid.substring(vid.indexOf('$') + 1)}`); } }); const pl = path.split("/").filter(it => it); let vod_name = pl[pl.length - 1] || drives.name; if (vod_name === drives.name) { print(pl); } if (otid.includes('#search#')) { vod_name += '[搜]'; } let vod = { // vod_id: tid, vod_id: otid, vod_name: vod_name, type_name: "文件夹", vod_pic: "https://avatars.githubusercontent.com/u/97389433?s=120&v=4", vod_content: tid, vod_tag: 'folder', vod_play_from: drives.name, vod_play_url: vod_play_url.join('#'), vod_remarks: drives.settings.title, } print("----detail1----"); print(vod); return JSON.stringify({'list': [vod]}); } catch (e) { print(e.message); let list = [{ vod_name: '无数据,防无限请求', type_name: "文件夹", vod_id: 'no_data', vod_remarks: '不要点,会崩的', vod_pic: 'https://ghproxy.net/https://raw.githubusercontent.com/hjdhnx/dr_py/main/static/img/404.jpg', vod_actor: e.message, vod_director: tid, vod_content: otid }]; return JSON.stringify({'list': list}); } } async function detail(tid) { let isSearch = tid.includes('#search#'); let isAll = tid.includes('#all#'); let otid = tid; tid = tid.replace(/#all#|#search#/g, ''); let isFile = isMedia(tid.split('@@@')[0]); print(`isFile:${tid}?${isFile}`); let {drives, path} = await get_drives_path(tid); print(`drives:${drives},path:${path},`); if (path.endsWith("/")) { //长按文件夹可以 加载里面全部视频到详情 return await getAll(otid, tid, drives, path); } else { if (isSearch && !isFile) { // 搜索结果 当前目录获取所有文件 return await getAll(otid, tid, drives, path); } else if (isAll) { // 上级目录获取所有文件 不管是搜索还是分类,只要不是 搜索到的文件夹,且展示模式为全部,都获取上级目录的所有文件 // 是文件就取上级目录 let new_tid; if (isFile) { new_tid = tid.split('/').slice(0, -1).join('/') + '/'; } else { new_tid = tid; } print(`全集模式 tid:${tid}=>tid:${new_tid}`); let {drives, path} = await get_drives_path(new_tid); return await getAll(otid, new_tid, drives, path); } else if (isFile) { // 单文件进入 let paths = path.split("@@@"); let vod_name = paths[0].substring(paths[0].lastIndexOf("/") + 1); let vod_title = vod_name; if (otid.includes('#search#')) { vod_title += '[搜]'; } let vod = { vod_id: otid, vod_name: vod_title, type_name: "文件", vod_pic: "https://avatars.githubusercontent.com/u/97389433?s=120&v=4", vod_content: tid, vod_play_from: drives.name, vod_play_url: vod_name + "$" + path, vod_remarks: drives.settings.title, }; print("----detail2----"); print(vod); return JSON.stringify({ 'list': [vod] }); } else { return JSON.stringify({ 'list': [] }); } } } async function play(flag, id, flags) { const drives = await get_drives(flag); const urls = id.split("@@@"); // @@@ 分割前是 相对文件path,分割后是字幕文件 log('urls[0]:', urls[0]) const a = await drives.getFile(urls[0]); log('a:', a) let vod = { 'parse': 0, 'playUrl': '', // 'url': drives.getFile(urls[0]).raw_url+'#.m3u8' // 加 # 没法播放 'url': (await drives.getFile(urls[0])).raw_url }; if (urls.length >= 2) { const path = urls[0].substring(0, urls[0].lastIndexOf('/') + 1); vod.subt = (await drives.getFile(path + urls[1])).raw_url1; } print("----play----"); print(vod); return JSON.stringify(vod); } async function search(wd, quick) { print(__drives); print('可搜索的alist驱动:' + searchDriver); if (!searchDriver || !wd) { return JSON.stringify({ 'list': [] }); } else { let driver = __drives[searchDriver]; wd = wd.split(' ').filter(it => it.trim()).join('+'); print(driver); let surl = driver.server + '/search?box=' + wd + '&url='; if (search_type) { surl += '&type=' + search_type; } print('搜索链接:' + surl); let html = (await http.get(surl)).text(); let lists = []; try { lists = pdfa(html, 'div&&ul&&a'); } catch (e) { } print(`搜索结果数:${lists.length},搜索结果显示数量限制:${limit_search_show}`); let vods = []; let excludeReg = /\.(pdf|epub|mobi|txt|doc|lrc)$/; // 过滤后缀文件 let cnt = 0; lists.forEach(it => { let vhref = pdfh(it, 'a&&href'); if (vhref) { vhref = unescape(vhref); } if (excludeReg.test(vhref)) { return; //跳过本次循环 } if (cnt < limit_search_show) { print(vhref); } cnt++; let vid = searchDriver + '$' + vhref + '#search#'; if (showMode === 'all') { vid += '#all#'; } vods.push({ vod_name: pdfh(it, 'a&&Text'), vod_id: vid, vod_tag: isMedia(vhref) ? 'file' : 'folder', vod_pic: 'http://img1.3png.com/281e284a670865a71d91515866552b5f172b.png', vod_remarks: searchDriver }); }); // 截取搜索结果 vods = vods.slice(0, limit_search_show); print(vods); return JSON.stringify({ 'list': vods }); } } function get_size(sz) { if (sz <= 0) { return ""; } let filesize = ""; if (sz > 1024 * 1024 * 1024 * 1024.0) { sz /= (1024 * 1024 * 1024 * 1024.0); filesize = "TB"; } else if (sz > 1024 * 1024 * 1024.0) { sz /= (1024 * 1024 * 1024.0); filesize = "GB"; } else if (sz > 1024 * 1024.0) { sz /= (1024 * 1024.0); filesize = "MB"; } else if (sz > 1024.0) { sz /= 1024.0; filesize = "KB"; } else { filesize = "B"; } // 转成字符串 let sizeStr = sz.toFixed(2) + filesize, // 获取小数点处的索引 index = sizeStr.indexOf("."), // 获取小数点后两位的值 dou = sizeStr.substr(index + 1, 2); if (dou === "00") { return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2); } else { return sizeStr; } } // 相似度获取 function levenshteinDistance(str1, str2) { return 100 - 100 * distance(str1, str2) / Math.max(str1.length, str2.length); } /** * 自然排序 * ["第1集","第10集","第20集","第2集","1","2","10","12","23","01","02"].sort(naturalSort()) * @param options {{key,caseSensitive, order: string}} */ function naturalSort(options) { if (!options) { options = {}; } return function (a, b) { if (options.key) { a = a[options.key]; b = b[options.key]; } var EQUAL = 0; var GREATER = (options.order === 'desc' ? -1 : 1 ); var SMALLER = -GREATER; var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi; var sre = /(^[ ]*|[ ]*$)/g; var dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/; var hre = /^0x[0-9a-f]+$/i; var ore = /^0/; var normalize = function normalize(value) { var string = '' + value; return (options.caseSensitive ? string : string.toLowerCase() ); }; // Normalize values to strings var x = normalize(a).replace(sre, '') || ''; var y = normalize(b).replace(sre, '') || ''; // chunk/tokenize var xN = x.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0'); var yN = y.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0'); // Return immediately if at least one of the values is empty. if (!x && !y) return EQUAL; if (!x && y) return GREATER; if (x && !y) return SMALLER; // numeric, hex or date detection var xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)); var yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null; var oFxNcL, oFyNcL; // first try and sort Hex codes or Dates if (yD) { if (xD < yD) return SMALLER; else if (xD > yD) return GREATER; } // natural sorting through split numeric strings and default strings for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { // find floats not starting with '0', string or 0 if not defined (Clint Priest) oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; // handle numeric vs string comparison - number < string - (Kyle Adams) if (isNaN(oFxNcL) !== isNaN(oFyNcL)) return (isNaN(oFxNcL)) ? GREATER : SMALLER; // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' else if (typeof oFxNcL !== typeof oFyNcL) { oFxNcL += ''; oFyNcL += ''; } if (oFxNcL < oFyNcL) return SMALLER; if (oFxNcL > oFyNcL) return GREATER; } return EQUAL; }; } // 完整名称排序 const sortListByName = (vodList, key, order) => { if (!key) { return vodList } order = order || 'asc'; // 默认正序 // 排序键,顺序,区分大小写 return vodList.sort(naturalSort({key: key, order: order, caseSensitive: true})) }; const getTimeInt = (timeStr) => { return (new Date(timeStr)).getTime(); }; // 时间 const sortListByTime = (vodList, key, order) => { if (!key) { return vodList } let ASCarr = vodList.sort((a, b) => { a = a[key]; b = b[key]; return getTimeInt(a) - getTimeInt(b); }); if (order === 'desc') { ASCarr.reverse(); } return ASCarr }; // 大小 const sortListBySize = (vodList, key, order) => { if (!key) { return vodList } let ASCarr = vodList.sort((a, b) => { a = a[key]; b = b[key]; return (Number(a) || 0) - (Number(b) || 0); }); if (order === 'desc') { ASCarr.reverse(); } return ASCarr }; // 导出函数对象 export default { init: init, home: home, homeVod: homeVod, category: category, detail: detail, play: play, search: search }