去评论
dz插件网

为你的discuz x3.5网站引入APlayer和Meting,播放网易云、QQ等各平台音乐仅需要在第三方统计里面引入一段js即可

惧愁人
2024/07/25 21:08:52
为你的discuz x3.5网站引入APlayer和Meting,播放网易云、QQ等各平台音乐仅需要在第三方统计里面引入一段js即可:
一个只需加载JS,即可调用 APlayerMeting,不依赖插件和服务器计算存储,任意站点都可使用的来播放 网易云QQ 音乐酷狗虾米百度 以及 自定义的 单曲和歌单的方法,在此记录并分享给大家。
引入 JS:
  1. <script>
  2.     // APlayer API
  3.     document.addEventListener('DOMContentLoaded', initAplayer);
  4.     window.aplayers = window.aplayers || [];
  5.     function initAplayer(option) {
  6.         const common = {
  7.             loadResource: function (id, resource, type) {
  8.                 return new Promise(function (resolve, reject) {
  9.                     let loaded = document.head.querySelector('#' + id);
  10.                     if (loaded) {
  11.                         resolve('success: ' + resource);
  12.                         return;
  13.                     }
  14.                     const element = document.createElement(type);
  15.                     element.onload = element.onreadystatechange = () => {
  16.                         if (!loaded && (!element.readyState || /loaded|complete/.test(element.readyState))) {
  17.                             element.onload = element.onreadystatechange = null;
  18.                             loaded = true;
  19.                             resolve('success: ' + resource);
  20.                         }
  21.                     }
  22.                     element.onerror = function () {
  23.                         reject(Error(resource + ' load error!'));
  24.                     };
  25.                     if (type === 'link') {
  26.                         element.rel = 'stylesheet';
  27.                         element.href = resource;
  28.                     } else {
  29.                         element.src = resource;
  30.                     }
  31.                     element.id = id;
  32.                     document.getElementsByTagName('head')[0].appendChild(element);
  33.                 });
  34.             },
  35.             loadResources: function (callback) {
  36.                 const loadResource = this.loadResource;
  37.                 const pt = '//s0.pstatp.com/cdn/expire-1-M/';
  38.                 const jd = '//gcore.jsdelivr.net/npm/';
  39.                 const resources = [
  40.                     pt + 'aplayer/1.10.1/APlayer.min.css',
  41.                     pt + 'aplayer/1.10.1/APlayer.min.js',
  42.                     jd + 'meting@2/dist/Meting.min.js'
  43.                 ];
  44.                 const loadPromises = [];
  45.                 resources.forEach(resource => {
  46.                     loadPromises.push(loadResource(btoa(resource).replace(/[=+\/]/g, ''), resource,
  47.                         ({
  48.                             'css': 'link',
  49.                             'js': 'script'
  50.                         })[resource.split('.').pop()]
  51.                     ));
  52.                 });
  53.                 Promise.all(loadPromises).then(
  54.                     function () {
  55.                         if (typeof callback !== 'function') return;
  56.                         let flag = false;
  57.                         const waitAM = setInterval(() => {
  58.                             if (!flag
  59.                                 && typeof APlayer === 'function'
  60.                                 && typeof MetingJSElement === 'function') {
  61.                                 flag = true;
  62.                                 callback();
  63.                                 clearInterval(waitAM);
  64.                             }
  65.                         }, 100);
  66.                     }
  67.                 );
  68.             },
  69.             createAplayers: function (sources) {
  70.                 for (let i = 0; i < sources.length; i++) {
  71.                     const child = document.createElement('div');
  72.                     sources[i].parentNode.insertBefore(child, sources[i]);
  73.                     sources[i].style.display = 'none';
  74.                     const songsTag = sources[i].querySelectorAll('s');
  75.                     const songs = [];
  76.                     songsTag.forEach(songTag => {
  77.                         const song = {};
  78.                         for (let i = 0; i < songTag.attributes.length; i++) {
  79.                             song[songTag.attributes[i].name] = songTag.attributes[i].value;
  80.                         }
  81.                         songs.push(song);
  82.                     });
  83.                     const options = { container: child, preload: 'none', autoplay: false, audio: songs };
  84.                     const optionMap = sources[i].attributes;
  85.                     for (let i = 0; i < optionMap.length; i++) {
  86.                         options[optionMap[i].name] = optionMap[i].value;
  87.                     }
  88.                     this.loadResources(() => window.aplayers.push(new APlayer(options)));
  89.                 }
  90.             }
  91.         };

  92.         if (option == 'manual') return new Promise((resolve, reject) => {
  93.             common.loadResources(() => resolve('success'));
  94.         });

  95.         const aps = document.querySelectorAll('ap');
  96.         if (aps.length !== 0) common.createAplayers(aps);

  97.         const mts = document.querySelectorAll('meting-js');
  98.         if (!window.refreshing && mts.length !== 0) common.loadResources(
  99.             function () {
  100.                 mts.forEach(mt => {
  101.                     if (!mt.aplayer) {
  102.                         const html = mt.outerHTML;
  103.                         mt.aplayer = { destroy: new Function(), list: { index: undefined } };
  104.                         mt.outerHTML = '\n' + html;
  105.                     }
  106.                 });
  107.                 document.querySelectorAll('meting-js').forEach(mt => {
  108.                     let flag = false;
  109.                     const waitMT = setInterval(() => {
  110.                         if (!flag && mt.aplayer) {
  111.                             flag = true;
  112.                             window.aplayers.push(mt.aplayer);
  113.                             console.log('replaced unloaded aplayer.')
  114.                             clearInterval(waitMT);
  115.                         }
  116.                     }, 300);
  117.                 });
  118.             }
  119.         );
  120.     }
  121. </script>

  122. <script>
  123.     // PJAX 相关 BUG
  124.     document.addEventListener('DOMContentLoaded', function () {
  125.         let flag = false;
  126.         window.needReloadUrls = window.needReloadUrls || new Set();
  127.         const jqueryWaitor = setInterval(() => {
  128.             if (!flag && jQuery) {
  129.                 flag = true;
  130.                 $(document).on('pjax:start', function () {
  131.                     if (!window.refreshing || !window.pjaxStarted) {
  132.                         window.pjaxStarted = true;
  133.                         console.log('pjax:start');
  134.                         window.aplayers.forEach(ap => {
  135.                             ap.list.index = undefined;
  136.                             ap.destroy();
  137.                         });
  138.                         window.aplayers = [];
  139.                         setTimeout(() => window.pjaxStarted = false, 2000);
  140.                     }
  141.                 });
  142.                 $(document).on('pjax:end', function () {
  143.                     if (document.querySelector('meting-js')
  144.                         || document.querySelector('.collapse-block')
  145.                         || document.querySelector('#toggle-menu-tree')
  146.                         || document.querySelectorAll('.content-tab-title').length > 1
  147.                     ) {
  148.                         if (!window.needReloadUrls.has(location.href)) {
  149.                             window.needReloadUrls.add(location.href);
  150.                             console.log('captured a neededReloadUrl.');
  151.                         }
  152.                     }
  153.                 });
  154.                 $(document).on('pjax:popstate', function (event) {
  155.                     if (event.state && window.needReloadUrls.has(event.state.url) && !window.refreshing) {
  156.                         window.refreshing = true;
  157.                         console.log('back-forward handler.');
  158.                         $.pjax.reload({
  159.                             url: location.href,
  160.                             container: '#body',
  161.                             fragment: '#body',
  162.                             scrollTo: false,
  163.                             timeout: 8000
  164.                         });
  165.                         setTimeout(() => window.refreshing = false, 2000);
  166.                     }
  167.                 });
  168.                 clearInterval(jqueryWaitor);
  169.             }
  170.         }, 500);
  171.     });
  172. </script>
放到你论坛后台——全局——站点信息——第三方统计代码里面:


页面添加效果:(比如首页、版块页面、帖子内容页等~)
网易云歌单引入方式:
  1. !!!
  2. <!-- 引入方式 -->
  3. <meting-js auto="https://music.163.com/#/playlist?id=110459831"></meting-js>
  4. !!!
QQ音乐歌单:
  1. !!!
  2. <!-- 引入方式 -->
  3. <meting-js auto="https://y.qq.com/n/yqq/playlist/7355087593.html"></meting-js>
  4. !!!
比如我在我第三方模板的/common/footer.php插入效果: