From ca3610ce366174dc14530c158c6f6d496f8abe9e Mon Sep 17 00:00:00 2001 From: Fang_Zhijian Date: Thu, 25 Sep 2025 20:29:30 +0800 Subject: [PATCH] download must login --- extend.php | 5 +++++ js/dist/admin.js | 2 +- js/dist/admin.js.map | 2 +- js/dist/forum.js | 2 +- js/dist/forum.js.map | 2 +- js/src/admin/index.ts | 10 ++++++++-- js/src/forum/util/renderPulseViewers.ts | 11 ++++++++++- 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/extend.php b/extend.php index 7402723..9081539 100644 --- a/extend.php +++ b/extend.php @@ -17,8 +17,13 @@ return [ (new Extend\Frontend('forum')) ->js(__DIR__.'/js/dist/forum.js') ->css(__DIR__.'/less/forum.less'), + (new Extend\Frontend('admin')) + ->js(__DIR__.'/js/dist/admin.js'), new Extend\Locales(__DIR__.'/locale'), (new Extend\Formatter()) ->configure(FormatterConfigure::class), + + (new Extend\Settings()) + ->serializeToForum('klxf-coyote-pulse-viewer.download-must-login', 'klxf-coyote-pulse-viewer.download-must-login'), ]; diff --git a/js/dist/admin.js b/js/dist/admin.js index 86c0b8f..cd2a874 100644 --- a/js/dist/admin.js +++ b/js/dist/admin.js @@ -1,2 +1,2 @@ -(()=>{var e={n:o=>{var l=o&&o.__esModule?()=>o.default:()=>o;return e.d(l,{a:l}),l},d:(o,l)=>{for(var r in l)e.o(l,r)&&!e.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:l[r]})},o:(e,o)=>Object.prototype.hasOwnProperty.call(e,o)};(()=>{"use strict";const o=flarum.core.compat["common/app"];e.n(o)().initializers.add("klxf/flarum-coyote-pulse-viewer",function(){console.log("[klxf/flarum-coyote-pulse-viewer] Hello, forum and admin!")});const l=flarum.core.compat["admin/app"];e.n(l)().initializers.add("klxf/flarum-coyote-pulse-viewer",function(){console.log("[klxf/flarum-coyote-pulse-viewer] Hello, admin!")})})(),module.exports={}})(); +(()=>{var e={n:o=>{var t=o&&o.__esModule?()=>o.default:()=>o;return e.d(t,{a:t}),t},d:(o,t)=>{for(var r in t)e.o(t,r)&&!e.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:t[r]})},o:(e,o)=>Object.prototype.hasOwnProperty.call(e,o)};(()=>{"use strict";const o=flarum.core.compat["common/app"];e.n(o)().initializers.add("klxf/flarum-coyote-pulse-viewer",function(){console.log("[klxf/flarum-coyote-pulse-viewer] Hello, forum and admin!")});const t=flarum.core.compat["admin/app"];var r=e.n(t);r().initializers.add("klxf-coyote-pulse-viewer",function(){r().extensionData.for("klxf-coyote-pulse-viewer").registerSetting({setting:"klxf-coyote-pulse-viewer.download-must-login",type:"switch",label:"下载波形文件必须登录"})})})(),module.exports={}})(); //# sourceMappingURL=admin.js.map \ No newline at end of file diff --git a/js/dist/admin.js.map b/js/dist/admin.js.map index 7d9d967..541628f 100644 --- a/js/dist/admin.js.map +++ b/js/dist/admin.js.map @@ -1 +1 @@ -{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,GCLRF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,MCJ3ER,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,I,mBCAlF,MAAM,EAA+BI,OAAOC,KAAKC,OAAO,c,MCExDC,GAAAA,aAAiBC,IAAI,kCAAmC,WACtDC,QAAQC,IAAI,4DACd,GCJA,MAAM,EAA+BN,OAAOC,KAAKC,OAAO,a,MCExDC,GAAAA,aAAiBC,IAAI,kCAAmC,WACtDC,QAAQC,IAAI,kDACd,E","sources":["webpack://@klxf/flarum-coyote-pulse-viewer/webpack/bootstrap","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/compat get default export","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/define property getters","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/hasOwnProperty shorthand","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/app']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/common/index.ts","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['admin/app']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/app'];","import app from 'flarum/common/app';\n\napp.initializers.add('klxf/flarum-coyote-pulse-viewer', () => {\n console.log('[klxf/flarum-coyote-pulse-viewer] Hello, forum and admin!');\n});\n","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('klxf/flarum-coyote-pulse-viewer', () => {\n console.log('[klxf/flarum-coyote-pulse-viewer] Hello, admin!');\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","flarum","core","compat","app","add","console","log"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,GCLRF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,MCJ3ER,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,I,mBCAlF,MAAM,EAA+BI,OAAOC,KAAKC,OAAO,c,MCExDC,GAAAA,aAAiBC,IAAI,kCAAmC,WACtDC,QAAQC,IAAI,4DACd,GCJA,MAAM,EAA+BN,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAiBC,IAAI,2BAA4B,WAC/CD,IAAAA,cAAiB,IACV,4BACJI,gBAAgB,CACfC,QAAS,+CACTC,KAAM,SACNC,MAAO,cAEb,E","sources":["webpack://@klxf/flarum-coyote-pulse-viewer/webpack/bootstrap","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/compat get default export","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/define property getters","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/hasOwnProperty shorthand","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/app']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/common/index.ts","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['admin/app']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/app'];","import app from 'flarum/common/app';\n\napp.initializers.add('klxf/flarum-coyote-pulse-viewer', () => {\n console.log('[klxf/flarum-coyote-pulse-viewer] Hello, forum and admin!');\n});\n","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('klxf-coyote-pulse-viewer', () => {\n app.extensionData\n .for(\"klxf-coyote-pulse-viewer\")\n .registerSetting({\n setting: \"klxf-coyote-pulse-viewer.download-must-login\",\n type: \"switch\",\n label: \"下载波形文件必须登录\",\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","flarum","core","compat","app","add","console","log","registerSetting","setting","type","label"],"sourceRoot":""} \ No newline at end of file diff --git a/js/dist/forum.js b/js/dist/forum.js index 08db859..1adff25 100644 --- a/js/dist/forum.js +++ b/js/dist/forum.js @@ -1,2 +1,2 @@ -(()=>{var t={n:e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return t.d(n,{a:n}),n},d:(e,n)=>{for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)};(()=>{"use strict";const e=flarum.core.compat["common/app"];t.n(e)().initializers.add("klxf/flarum-coyote-pulse-viewer",function(){console.log("[klxf/flarum-coyote-pulse-viewer] Hello, forum and admin!")});const n=flarum.core.compat["forum/app"];var r=t.n(n);const o=flarum.core.compat["common/extend"],i=flarum.core.compat["common/components/TextEditor"];var a=t.n(i);const l=flarum.core.compat["common/components/TextEditorButton"];var s=t.n(l),u=[10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200,233,266,300,333,366,400,450,500,550,600,700,800,900,1e3],c=[.1,.2,.3,.4,.5,.6,.7,.8,.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,3,3.1,3.2,3.3,3.4,3.5,3.6,3.7,3.8,3.9,4,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,5,5.2,5.4,5.6,5.8,6,6.2,6.4,6.6,6.8,7,7.2,7.4,7.6,7.8,8,8.5,9,9.5,10,11,12,13,14,15,16,17,18,19,20,23.4,26.6,30,33.4,36.6,40,45,50,55,60,70,80,90,100,120,140,160,180,200,250,300];const d=function(){document.querySelectorAll(".coyote-pulse-viewer").forEach(function(t){if(!t.getAttribute("data-pulse-rendered")){var e=!1,n=[],r=t.getAttribute("data-pulse"),o=t.getAttribute("data-title")?t.getAttribute("data-title"):"自定义波形",i=t.getAttribute("data-version")?t.getAttribute("data-version"):"3";if(r){var a;t.innerHTML+='
波形: '+(o&&o.length>12?o.slice(0,12)+"...":o)+'v'+i+'
',"3"!=i&&(e=!0,n.push("目前仅支持 v3 版本的波形数据")),function(t){if(!t.startsWith("Dungeonlab+pulse:"))return!1;var e,n,r=t.substring(17).split("+section+"),o=r[0],i=o.split("/"),a=o.match(/^(\d+,\d+,\d+=)?/);if(a&&a[1]){var l=o.substring(a[0].length).split("/");if(2!==l.length)return!1;e=l[0].split(","),n=l[1].split(",")}else{if(2!==i.length)return!1;e=i[0].split(","),n=i[1].split(",")}if(5!==e.length)return!1;if(!e.every(function(t){return/^\d+$/.test(t)}))return!1;if(!n.every(function(t){return/^-?\d+(\.\d+)?-\d+$/.test(t)}))return!1;for(var s=1;s 错误:'+n.join("; ")+""):t.innerHTML+=function(t){var e=t.replace("Dungeonlab+pulse:","").split("+section+"),n=0,r="";n+=0;var o=1,i=e[0].split("=");if(2===i.length){var a=i[0],l=i[1],s=a.split(",").map(Number),d=(s[0],s[1]);s[2],o=d||1,e[0]=l}return e.forEach(function(t){var e=t.split("/"),o=e[0],i=e[1],a=o.split(",").map(Number),l=a[0],s=a[1],d=a[2],p=a[3],f=a[4],m=c[d];if(0!==f)for(var v=i.split(","),h=10*v.length,b=Math.ceil(m/(h/100)),g=function(t){var e=10*v.length;n+=e,v.forEach(function(o,i){var a,c=o.split("-").map(Number),d=c[0],f=(c[1],d),m=n-e+10*i,h=100-f;a=1===p?u[l]:2===p?u[l+Math.floor((s-l)*((v.length*t+i)/(v.length*b)))]:3===p?u[l+Math.floor((s-l)*i/v.length)]:4===p?u[l+Math.floor(t/b*(s-l))]:u[l];var g=.5,y=Math.floor(100/a);if(y>0){var w=(10-y*g)/y;w<0&&(w=0);for(var x=0;x',r+=''}}else r+=''})},y=0;y\n\t\t\t \n\t\t\t '+r+'\n\t\t\t \n\t\t\t \n\t\t\t \n\t\t\t \n\t\t\t \n\t\t\t '}(r),t.setAttribute("data-pulse-rendered","1");var l=t.querySelector(".pulse-download-btn");l&&l.addEventListener("click",function(){var t=new Blob([r],{type:"text/plain"}),e=document.createElement("a");e.href=URL.createObjectURL(t),e.download=o+".pulse",document.body.appendChild(e),e.click(),document.body.removeChild(e),URL.revokeObjectURL(e.href)})}}})};r().initializers.add("klxf-coyote-pulse-viewer",function(){(0,o.extend)(a().prototype,"toolbarItems",function(t){var e=this;t.add("pulse-file-upload",m(s(),{icon:"fas fa-file-import",title:"波形分享",onclick:function(){var t=document.createElement("input");t.type="file",t.accept=".pulse",t.style.display="none",t.addEventListener("change",function(){var n,r=null==(n=t.files)?void 0:n[0];if(r){var o=new FileReader;o.onload=function(){var t,n=r.name.replace(/\.pulse$/,""),i=n.match(/^pulse-(.+?)-\d+$/),a='[pulse title="'+(i?i[1]:n)+'"]'+o.result+"[/pulse]";null==(t=e.attrs)||null==(t=t.composer)||t.editor.insertAtCursor(a)},o.readAsText(r)}}),document.body.appendChild(t),t.click(),document.body.removeChild(t)}}),81)}),d(),document.body.addEventListener("contentupdated",d),new MutationObserver(function(){d()}).observe(document.body,{childList:!0,subtree:!0})})})(),module.exports={}})(); +(()=>{var t={n:e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return t.d(n,{a:n}),n},d:(e,n)=>{for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)};(()=>{"use strict";const e=flarum.core.compat["common/app"];t.n(e)().initializers.add("klxf/flarum-coyote-pulse-viewer",function(){console.log("[klxf/flarum-coyote-pulse-viewer] Hello, forum and admin!")});const n=flarum.core.compat["forum/app"];var r=t.n(n);const o=flarum.core.compat["common/extend"],a=flarum.core.compat["common/components/TextEditor"];var l=t.n(a);const i=flarum.core.compat["common/components/TextEditorButton"];var s=t.n(i),u=[10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200,233,266,300,333,366,400,450,500,550,600,700,800,900,1e3],c=[.1,.2,.3,.4,.5,.6,.7,.8,.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,3,3.1,3.2,3.3,3.4,3.5,3.6,3.7,3.8,3.9,4,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,5,5.2,5.4,5.6,5.8,6,6.2,6.4,6.6,6.8,7,7.2,7.4,7.6,7.8,8,8.5,9,9.5,10,11,12,13,14,15,16,17,18,19,20,23.4,26.6,30,33.4,36.6,40,45,50,55,60,70,80,90,100,120,140,160,180,200,250,300];const d=flarum.core.compat["forum/components/LogInModal"];var p=t.n(d);const f=function(){document.querySelectorAll(".coyote-pulse-viewer").forEach(function(t){if(!t.getAttribute("data-pulse-rendered")){var e=!1,n=[],o=(t.getAttribute("data-pulse")||"").replace(/\r?\n|\r/g,""),a=t.getAttribute("data-title")?t.getAttribute("data-title"):"自定义波形",l=t.getAttribute("data-version")?t.getAttribute("data-version"):"3";if(o){var i;t.innerHTML+='
波形: '+(a&&a.length>12?a.slice(0,12)+"...":a)+'v'+l+'
',"3"!=l&&(e=!0,n.push("目前仅支持 v3 版本的波形数据")),function(t){if(!t.startsWith("Dungeonlab+pulse:"))return!1;var e,n,r=t.substring(17).split("+section+"),o=r[0],a=o.split("/"),l=o.match(/^(\d+,\d+,\d+=)?/);if(l&&l[1]){var i=o.substring(l[0].length).split("/");if(2!==i.length)return!1;e=i[0].split(","),n=i[1].split(",")}else{if(2!==a.length)return!1;e=a[0].split(","),n=a[1].split(",")}if(5!==e.length)return!1;if(!e.every(function(t){return/^\d+$/.test(t)}))return!1;if(!n.every(function(t){return/^-?\d+(\.\d+)?-\d+$/.test(t)}))return!1;for(var s=1;s 错误:'+n.join("; ")+""):t.innerHTML+=function(t){var e=t.replace("Dungeonlab+pulse:","").split("+section+"),n=0,r="";n+=0;var o=1,a=e[0].split("=");if(2===a.length){var l=a[0],i=a[1],s=l.split(",").map(Number),d=(s[0],s[1]);s[2],o=d||1,e[0]=i}return e.forEach(function(t){var e=t.split("/"),o=e[0],a=e[1],l=o.split(",").map(Number),i=l[0],s=l[1],d=l[2],p=l[3],f=l[4],m=c[d];if(0!==f)for(var v=a.split(","),h=10*v.length,b=Math.ceil(m/(h/100)),g=function(t){var e=10*v.length;n+=e,v.forEach(function(o,a){var l,c=o.split("-").map(Number),d=c[0],f=(c[1],d),m=n-e+10*a,h=100-f;l=1===p?u[i]:2===p?u[i+Math.floor((s-i)*((v.length*t+a)/(v.length*b)))]:3===p?u[i+Math.floor((s-i)*a/v.length)]:4===p?u[i+Math.floor(t/b*(s-i))]:u[i];var g=.5,y=Math.floor(100/l);if(y>0){var w=(10-y*g)/y;w<0&&(w=0);for(var x=0;x',r+=''}}else r+=''})},y=0;y\n\t\t\t \n\t\t\t '+r+'\n\t\t\t \n\t\t\t \n\t\t\t \n\t\t\t \n\t\t\t \n\t\t\t '}(o),t.setAttribute("data-pulse-rendered","1");var s=t.querySelector(".pulse-download-btn");s&&s.addEventListener("click",function(){if(r().forum.attribute("klxf-coyote-pulse-viewer.download-must-login")&&null==r().session.user)return r().alerts.show({type:"warn"},"请先登录以下载波形文件"),void r().modal.show(p());var t=new Blob([o],{type:"text/plain"}),e=document.createElement("a");e.href=URL.createObjectURL(t),e.download=a+".pulse",document.body.appendChild(e),e.click(),document.body.removeChild(e),URL.revokeObjectURL(e.href)})}}})};r().initializers.add("klxf-coyote-pulse-viewer",function(){(0,o.extend)(l().prototype,"toolbarItems",function(t){var e=this;t.add("pulse-file-upload",m(s(),{icon:"fas fa-file-import",title:"波形分享",onclick:function(){var t=document.createElement("input");t.type="file",t.accept=".pulse",t.style.display="none",t.addEventListener("change",function(){var n,r=null==(n=t.files)?void 0:n[0];if(r){var o=new FileReader;o.onload=function(){var t,n=r.name.replace(/\.pulse$/,""),a=n.match(/^pulse-(.+?)-\d+$/),l='[pulse title="'+(a?a[1]:n)+'"]'+o.result+"[/pulse]";null==(t=e.attrs)||null==(t=t.composer)||t.editor.insertAtCursor(l)},o.readAsText(r)}}),document.body.appendChild(t),t.click(),document.body.removeChild(t)}}),81)}),f(),document.body.addEventListener("contentupdated",f),new MutationObserver(function(){f()}).observe(document.body,{childList:!0,subtree:!0})})})(),module.exports={}})(); //# sourceMappingURL=forum.js.map \ No newline at end of file diff --git a/js/dist/forum.js.map b/js/dist/forum.js.map index 38742b2..6865a5b 100644 --- a/js/dist/forum.js.map +++ b/js/dist/forum.js.map @@ -1 +1 @@ -{"version":3,"file":"forum.js","mappings":"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","sources":["webpack://@klxf/flarum-coyote-pulse-viewer/webpack/bootstrap","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/compat get default export","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/define property getters","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/hasOwnProperty shorthand","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/app']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/common/index.ts","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['forum/app']\"","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/extend']\"","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/components/TextEditor']\"","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/components/TextEditorButton']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/forum/util/generateSVG.ts","webpack://@klxf/flarum-coyote-pulse-viewer/./src/forum/util/renderPulseViewers.ts","webpack://@klxf/flarum-coyote-pulse-viewer/./src/forum/util/validatePulseData.ts","webpack://@klxf/flarum-coyote-pulse-viewer/./src/forum/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/app'];","import app from 'flarum/common/app';\n\napp.initializers.add('klxf/flarum-coyote-pulse-viewer', () => {\n console.log('[klxf/flarum-coyote-pulse-viewer] Hello, forum and admin!');\n});\n","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/app'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/components/TextEditor'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/components/TextEditorButton'];","const FREQ_SLIDER_VALUE_MAP = [\n 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,\n 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,\n 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78,\n 80, 85, 90, 95,\n 100, 110, 120, 130, 140, 150, 160, 170, 180, 190,\n 200, 233, 266, 300, 333, 366,\n 400, 450, 500, 550,\n 600, 700, 800, 900, 1000\n];\n\nconst SECTION_TIME_MAP = [\n 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2,\n 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4, 4.1, 4.2, 4.3, 4.4,\n 4.5, 4.6, 4.7, 4.8, 4.9,\n 5, 5.2, 5.4, 5.6, 5.8, 6, 6.2, 6.4, 6.6, 6.8, 7, 7.2, 7.4, 7.6, 7.8,\n 8, 8.5, 9, 9.5,\n 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 23.4, 26.6, 30, 33.4, 36.6,\n 40, 45, 50, 55,\n 60, 70, 80, 90,\n 100, 120, 140, 160, 180,\n 200, 250, 300\n];\n\nfunction generateSVG(data: string) {\n const sections = data.replace('Dungeonlab+pulse:', '').split('+section+');\n\n let svgWidth = 0;\n let svgHeight = 100;\n\n let svgContent = '';\n\n const startPadding = 0;\n const endPadding = 0;\n svgWidth += startPadding;\n\n let restDuration = 0;\n let speedRate = 1;\n\n // 只在最开始解析新的数据格式\n const firstSectionParts = sections[0].split('=');\n if (firstSectionParts.length === 2) {\n const [prefix, data] = firstSectionParts;\n const [rest, speed, num] = prefix.split(',').map(Number);\n restDuration = rest || 0;\n speedRate = speed || 1;\n sections[0] = data; // 将 sections[0] 替换为原始数据部分\n }\n\n sections.forEach(section => {\n const [header, pulsesStr] = section.split('/');\n const [minFreq, maxFreq, durationIndex, mode, isOn] = header.split(',').map(Number);\n const duration = SECTION_TIME_MAP[durationIndex];\n\n if (isOn === 0) {\n return;\n }\n\n const pulses = pulsesStr.split(',');\n const pulsesDuration = pulses.length * 10; // 计算pulses总宽度, 每个 pulse 宽度为 10\n const repeatTimes = Math.ceil(duration / (pulsesDuration /\n 100)); // pulsesDuration 单位是 0.1 秒,duration 单位是秒,需要转换单位, pulsesDuration / 100 得到秒\n\n for (let j = 0; j < repeatTimes; j++) {\n const sectionWidth = pulses.length * 10;\n svgWidth += sectionWidth;\n\n pulses.forEach((pulseStr, index) => {\n const [value, type] = pulseStr.split('-').map(Number);\n const pulseHeight = value;\n\n const xPos = svgWidth - sectionWidth + index * 10;\n const yPos = svgHeight - pulseHeight;\n\n const pulseWidth = 10; // 每个 pulse 宽度固定为 10\n let freq;\n\n if (mode === 1) {\n // 频率恒定\n freq = FREQ_SLIDER_VALUE_MAP[minFreq];\n } else if (mode === 2) {\n // 频率从 minFreq 增加到 maxFreq\n freq = FREQ_SLIDER_VALUE_MAP[minFreq + Math.floor((maxFreq - minFreq) * ((pulses\n .length * j + index) / (pulses.length * repeatTimes)))];\n } else if (mode === 3) {\n // 每个脉冲元内频率从 minFreq 增加到 maxFreq\n freq = FREQ_SLIDER_VALUE_MAP[minFreq + Math.floor((maxFreq - minFreq) * index /\n pulses.length)];\n } else if (mode === 4) {\n // 频率变化仅发生在脉冲元之间\n freq = FREQ_SLIDER_VALUE_MAP[minFreq + Math.floor((maxFreq - minFreq) * (j /\n repeatTimes))];\n } else {\n freq = FREQ_SLIDER_VALUE_MAP[minFreq];\n }\n\n const blackBarWidth = 0.5;\n const pulseDurationInSecond = pulseWidth / 100; // 假设 10 宽度对应 0.1 秒,需要根据实际情况调整\n const numBars = Math.floor(pulseDurationInSecond * 1000 / freq); // 频率单位是毫秒,pulseDurationInSecond 单位是秒,需要转换单位\n\n if (numBars > 0) {\n let whiteBarWidth = (pulseWidth - numBars * blackBarWidth) / numBars;\n if (whiteBarWidth < 0) whiteBarWidth = 0; // 避免条纹宽度为负数的情况\n\n for (let i = 0; i < numBars; i++) {\n const barXPos = xPos + i * (blackBarWidth + whiteBarWidth);\n svgContent +=\n ``;\n const whiteBarXPos = barXPos + blackBarWidth;\n svgContent +=\n ``;\n }\n } else {\n // 如果 numBars 为 0, 则填充整个 pulse\n svgContent +=\n ``;\n }\n });\n }\n });\n\n svgWidth += endPadding;\n\n const scrollSpeed = 50 * speedRate; // 应用 speedRate\n const totalScrollDistance = svgWidth + 100;\n const animationDuration = totalScrollDistance / scrollSpeed;\n\n const animationContent = `\n\t\t\t \n\t\t\t `;\n\n return `\n\t\t\t \n\t\t\t \n\t\t\t ${svgContent}\n\t\t\t ${animationContent}\n\t\t\t \n\t\t\t \n\t\t\t `;\n}\n\nexport default generateSVG;\n","import generateSVG from './generateSVG';\nimport validatePulseData from \"./validatePulseData\";\n\nfunction renderPulseViewers() {\n document.querySelectorAll('.coyote-pulse-viewer').forEach(el => {\n if (el.getAttribute('data-pulse-rendered')) return;\n let error = false;\n let errorArray: string[] = [];\n const pulseData = el.getAttribute('data-pulse');\n const pulseTitle = el.getAttribute('data-title') ? el.getAttribute('data-title'): '自定义波形';\n const pulseVersion = el.getAttribute('data-version') ? el.getAttribute('data-version') : '3';\n if (pulseData) {\n el.innerHTML += `
波形: ${pulseTitle && pulseTitle.length > 12 ? pulseTitle.slice(0, 12) + '...' : pulseTitle}v${pulseVersion}
`;\n\n if (pulseVersion != '3') {\n error = true;\n errorArray.push('目前仅支持 v3 版本的波形数据');\n }\n\n if (!validatePulseData(pulseData)) {\n error = true;\n errorArray.push('解析失败,请检查数据格式是否正确');\n }\n\n if (!error) {\n el.innerHTML += generateSVG(pulseData);\n } else {\n el.querySelector('.pulse-download-btn')?.remove();\n el.innerHTML += `
错误:${errorArray.join('; ')}
`;\n }\n\n el.setAttribute('data-pulse-rendered', '1');\n\n const downloadBtn = el.querySelector('.pulse-download-btn');\n if (downloadBtn) {\n downloadBtn.addEventListener('click', () => {\n const blob = new Blob([pulseData], { type: 'text/plain' });\n const a = document.createElement('a');\n a.href = URL.createObjectURL(blob);\n a.download = `${pulseTitle}.pulse`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(a.href);\n });\n }\n }\n });\n}\n\nexport default renderPulseViewers;\n","function validatePulseData(decodedData: string) {\n // 1. 检查开头是否为 \"Dungeonlab+pulse:\"\n if (!decodedData.startsWith(\"Dungeonlab+pulse:\")) {\n return false;\n }\n\n // 2. 移除开头标识\n const data = decodedData.substring(\"Dungeonlab+pulse:\".length);\n\n // 3. 分割数据段\n const sections = data.split(\"+section+\");\n\n // 4. 校验第一段数据(兼容新格式)\n const firstSection = sections[0];\n const firstSectionParts = firstSection.split(\"/\");\n\n // 检查是否存在前缀\n const prefixRegex = /^(\\d+,\\d+,\\d+=)?/; // 匹配 \"数字,数字,数字=\" 的可选前缀\n const prefixMatch = firstSection.match(prefixRegex);\n const hasPrefix = prefixMatch && prefixMatch[1];\n\n let intCounts, floatCounts;\n\n if (hasPrefix) {\n // 新格式:包含前缀\n const dataPart = firstSection.substring(prefixMatch[0].length); // 移除前缀\n const dataParts = dataPart.split(\"/\");\n\n if (dataParts.length !== 2) {\n return false;\n }\n\n intCounts = dataParts[0].split(\",\");\n floatCounts = dataParts[1].split(\",\");\n } else {\n // 旧格式:不包含前缀\n if (firstSectionParts.length !== 2) {\n return false;\n }\n\n intCounts = firstSectionParts[0].split(\",\");\n floatCounts = firstSectionParts[1].split(\",\");\n }\n\n if (intCounts.length !== 5) {\n return false;\n }\n if (!intCounts.every(count => /^\\d+$/.test(count))) {\n return false;\n }\n\n if (!floatCounts.every(count => /^-?\\d+(\\.\\d+)?-\\d+$/.test(count))) {\n return false;\n }\n\n // 5. 校验后续数据段(与旧格式相同)\n for (let i = 1; i < sections.length; i++) {\n const section = sections[i];\n const sectionParts = section.split(\"/\");\n if (sectionParts.length !== 2) {\n return false;\n }\n\n const intCounts = sectionParts[0].split(\",\");\n if (intCounts.length !== 5) {\n return false;\n }\n if (!intCounts.every(count => /^\\d+$/.test(count))) {\n return false;\n }\n\n const floatCounts = sectionParts[1].split(\",\");\n if (!floatCounts.every(count => /^-?\\d+(\\.\\d+)?-\\d+$/.test(count))) {\n return false;\n }\n }\n\n return true;\n}\n\nexport default validatePulseData;\n","import app from 'flarum/forum/app';\nimport {extend} from \"flarum/common/extend\";\nimport TextEditor from \"flarum/common/components/TextEditor\";\nimport TextEditorButton from \"flarum/common/components/TextEditorButton\";\nimport renderPulseViewers from \"./util/renderPulseViewers\";\n\napp.initializers.add('klxf-coyote-pulse-viewer', () => {\n extend(TextEditor.prototype, 'toolbarItems', function (items) {\n items.add(\n 'pulse-file-upload',\n m(TextEditorButton, {\n icon: 'fas fa-file-import',\n title: '波形分享',\n onclick: () => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.pulse';\n input.style.display = 'none';\n\n input.addEventListener('change', () => {\n const file = input.files?.[0];\n if (file) {\n const reader = new FileReader();\n reader.onload = () => {\n const fileNameWithoutExtension = file.name.replace(/\\.pulse$/, '');\n const match = fileNameWithoutExtension.match(/^pulse-(.+?)-\\d+$/);\n\n let title: string;\n\n if (match) title = match[1];\n else title = fileNameWithoutExtension;\n\n const pulseText = `[pulse title=\"${title}\"]${reader.result}[/pulse]`;\n // @ts-ignore\n this.attrs?.composer?.editor.insertAtCursor(pulseText);\n };\n reader.readAsText(file);\n }\n });\n\n document.body.appendChild(input);\n input.click();\n document.body.removeChild(input);\n }\n }),\n 81\n );\n });\n\n renderPulseViewers();\n document.body.addEventListener('contentupdated', renderPulseViewers);\n const observer = new MutationObserver(() => {\n renderPulseViewers();\n });\n observer.observe(document.body, {childList: true, subtree: true});\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","flarum","core","compat","app","add","console","log","FREQ_SLIDER_VALUE_MAP","SECTION_TIME_MAP","document","querySelectorAll","forEach","el","getAttribute","error","errorArray","pulseData","pulseTitle","pulseVersion","_el$querySelector","innerHTML","length","slice","push","decodedData","startsWith","intCounts","floatCounts","sections","substring","split","firstSection","firstSectionParts","prefixMatch","match","dataParts","every","count","test","i","sectionParts","validatePulseData","querySelector","remove","join","data","replace","svgWidth","svgContent","speedRate","prefix","_prefix$split$map","map","Number","speed","section","_section$split","header","pulsesStr","_header$split$map","minFreq","maxFreq","durationIndex","mode","isOn","duration","pulses","pulsesDuration","repeatTimes","Math","ceil","_loop","j","sectionWidth","pulseStr","index","freq","_pulseStr$split$map","value","pulseHeight","xPos","yPos","floor","blackBarWidth","numBars","pulseDurationInSecond","whiteBarWidth","barXPos","generateSVG","setAttribute","downloadBtn","addEventListener","blob","Blob","type","createElement","href","URL","createObjectURL","download","body","appendChild","click","removeChild","revokeObjectURL","extend","TextEditor","items","_this","m","TextEditorButton","icon","title","onclick","input","accept","style","display","_input$files","file","files","reader","FileReader","onload","_this$attrs","fileNameWithoutExtension","name","pulseText","result","attrs","composer","editor","insertAtCursor","readAsText","renderPulseViewers","MutationObserver","observe","childList","subtree"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"forum.js","mappings":"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","sources":["webpack://@klxf/flarum-coyote-pulse-viewer/webpack/bootstrap","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/compat get default export","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/define property getters","webpack://@klxf/flarum-coyote-pulse-viewer/webpack/runtime/hasOwnProperty shorthand","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/app']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/common/index.ts","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['forum/app']\"","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/extend']\"","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/components/TextEditor']\"","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['common/components/TextEditorButton']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/forum/util/generateSVG.ts","webpack://@klxf/flarum-coyote-pulse-viewer/external root \"flarum.core.compat['forum/components/LogInModal']\"","webpack://@klxf/flarum-coyote-pulse-viewer/./src/forum/util/renderPulseViewers.ts","webpack://@klxf/flarum-coyote-pulse-viewer/./src/forum/util/validatePulseData.ts","webpack://@klxf/flarum-coyote-pulse-viewer/./src/forum/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/app'];","import app from 'flarum/common/app';\n\napp.initializers.add('klxf/flarum-coyote-pulse-viewer', () => {\n console.log('[klxf/flarum-coyote-pulse-viewer] Hello, forum and admin!');\n});\n","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/app'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/components/TextEditor'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/components/TextEditorButton'];","const FREQ_SLIDER_VALUE_MAP = [\n 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,\n 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,\n 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78,\n 80, 85, 90, 95,\n 100, 110, 120, 130, 140, 150, 160, 170, 180, 190,\n 200, 233, 266, 300, 333, 366,\n 400, 450, 500, 550,\n 600, 700, 800, 900, 1000\n];\n\nconst SECTION_TIME_MAP = [\n 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2,\n 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4, 4.1, 4.2, 4.3, 4.4,\n 4.5, 4.6, 4.7, 4.8, 4.9,\n 5, 5.2, 5.4, 5.6, 5.8, 6, 6.2, 6.4, 6.6, 6.8, 7, 7.2, 7.4, 7.6, 7.8,\n 8, 8.5, 9, 9.5,\n 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 23.4, 26.6, 30, 33.4, 36.6,\n 40, 45, 50, 55,\n 60, 70, 80, 90,\n 100, 120, 140, 160, 180,\n 200, 250, 300\n];\n\nfunction generateSVG(data: string) {\n const sections = data.replace('Dungeonlab+pulse:', '').split('+section+');\n\n let svgWidth = 0;\n let svgHeight = 100;\n\n let svgContent = '';\n\n const startPadding = 0;\n const endPadding = 0;\n svgWidth += startPadding;\n\n let restDuration = 0;\n let speedRate = 1;\n\n // 只在最开始解析新的数据格式\n const firstSectionParts = sections[0].split('=');\n if (firstSectionParts.length === 2) {\n const [prefix, data] = firstSectionParts;\n const [rest, speed, num] = prefix.split(',').map(Number);\n restDuration = rest || 0;\n speedRate = speed || 1;\n sections[0] = data; // 将 sections[0] 替换为原始数据部分\n }\n\n sections.forEach(section => {\n const [header, pulsesStr] = section.split('/');\n const [minFreq, maxFreq, durationIndex, mode, isOn] = header.split(',').map(Number);\n const duration = SECTION_TIME_MAP[durationIndex];\n\n if (isOn === 0) {\n return;\n }\n\n const pulses = pulsesStr.split(',');\n const pulsesDuration = pulses.length * 10; // 计算pulses总宽度, 每个 pulse 宽度为 10\n const repeatTimes = Math.ceil(duration / (pulsesDuration /\n 100)); // pulsesDuration 单位是 0.1 秒,duration 单位是秒,需要转换单位, pulsesDuration / 100 得到秒\n\n for (let j = 0; j < repeatTimes; j++) {\n const sectionWidth = pulses.length * 10;\n svgWidth += sectionWidth;\n\n pulses.forEach((pulseStr, index) => {\n const [value, type] = pulseStr.split('-').map(Number);\n const pulseHeight = value;\n\n const xPos = svgWidth - sectionWidth + index * 10;\n const yPos = svgHeight - pulseHeight;\n\n const pulseWidth = 10; // 每个 pulse 宽度固定为 10\n let freq;\n\n if (mode === 1) {\n // 频率恒定\n freq = FREQ_SLIDER_VALUE_MAP[minFreq];\n } else if (mode === 2) {\n // 频率从 minFreq 增加到 maxFreq\n freq = FREQ_SLIDER_VALUE_MAP[minFreq + Math.floor((maxFreq - minFreq) * ((pulses\n .length * j + index) / (pulses.length * repeatTimes)))];\n } else if (mode === 3) {\n // 每个脉冲元内频率从 minFreq 增加到 maxFreq\n freq = FREQ_SLIDER_VALUE_MAP[minFreq + Math.floor((maxFreq - minFreq) * index /\n pulses.length)];\n } else if (mode === 4) {\n // 频率变化仅发生在脉冲元之间\n freq = FREQ_SLIDER_VALUE_MAP[minFreq + Math.floor((maxFreq - minFreq) * (j /\n repeatTimes))];\n } else {\n freq = FREQ_SLIDER_VALUE_MAP[minFreq];\n }\n\n const blackBarWidth = 0.5;\n const pulseDurationInSecond = pulseWidth / 100; // 假设 10 宽度对应 0.1 秒,需要根据实际情况调整\n const numBars = Math.floor(pulseDurationInSecond * 1000 / freq); // 频率单位是毫秒,pulseDurationInSecond 单位是秒,需要转换单位\n\n if (numBars > 0) {\n let whiteBarWidth = (pulseWidth - numBars * blackBarWidth) / numBars;\n if (whiteBarWidth < 0) whiteBarWidth = 0; // 避免条纹宽度为负数的情况\n\n for (let i = 0; i < numBars; i++) {\n const barXPos = xPos + i * (blackBarWidth + whiteBarWidth);\n svgContent +=\n ``;\n const whiteBarXPos = barXPos + blackBarWidth;\n svgContent +=\n ``;\n }\n } else {\n // 如果 numBars 为 0, 则填充整个 pulse\n svgContent +=\n ``;\n }\n });\n }\n });\n\n svgWidth += endPadding;\n\n const scrollSpeed = 50 * speedRate; // 应用 speedRate\n const totalScrollDistance = svgWidth + 100;\n const animationDuration = totalScrollDistance / scrollSpeed;\n\n const animationContent = `\n\t\t\t \n\t\t\t `;\n\n return `\n\t\t\t \n\t\t\t \n\t\t\t ${svgContent}\n\t\t\t ${animationContent}\n\t\t\t \n\t\t\t \n\t\t\t `;\n}\n\nexport default generateSVG;\n","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/components/LogInModal'];","import generateSVG from './generateSVG';\nimport validatePulseData from \"./validatePulseData\";\nimport app from 'flarum/forum/app';\nimport LogInModal from \"flarum/forum/components/LogInModal\";\n\nfunction renderPulseViewers() {\n document.querySelectorAll('.coyote-pulse-viewer').forEach(el => {\n if (el.getAttribute('data-pulse-rendered')) return;\n let error = false;\n let errorArray: string[] = [];\n // 替换掉换行\n const pulseData = (el.getAttribute('data-pulse') || '').replace(/\\r?\\n|\\r/g, '');\n const pulseTitle = el.getAttribute('data-title') ? el.getAttribute('data-title'): '自定义波形';\n const pulseVersion = el.getAttribute('data-version') ? el.getAttribute('data-version') : '3';\n if (pulseData) {\n el.innerHTML += `
波形: ${pulseTitle && pulseTitle.length > 12 ? pulseTitle.slice(0, 12) + '...' : pulseTitle}v${pulseVersion}
`;\n\n if (pulseVersion != '3') {\n error = true;\n errorArray.push('目前仅支持 v3 版本的波形数据');\n }\n\n if (!validatePulseData(pulseData)) {\n error = true;\n errorArray.push('解析失败,请检查数据格式是否正确');\n }\n\n if (!error) {\n el.innerHTML += generateSVG(pulseData);\n } else {\n el.querySelector('.pulse-download-btn')?.remove();\n el.innerHTML += `
错误:${errorArray.join('; ')}
`;\n }\n\n el.setAttribute('data-pulse-rendered', '1');\n\n const downloadBtn = el.querySelector('.pulse-download-btn');\n if (downloadBtn) {\n downloadBtn.addEventListener('click', () => {\n if (app.forum.attribute(\"klxf-coyote-pulse-viewer.download-must-login\") && app.session.user == null) {\n app.alerts.show({ type: 'warn' }, '请先登录以下载波形文件');\n app.modal.show(LogInModal);\n return;\n }\n\n const blob = new Blob([pulseData], { type: 'text/plain' });\n const a = document.createElement('a');\n a.href = URL.createObjectURL(blob);\n a.download = `${pulseTitle}.pulse`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(a.href);\n });\n }\n }\n });\n}\n\nexport default renderPulseViewers;\n","function validatePulseData(decodedData: string) {\n // 1. 检查开头是否为 \"Dungeonlab+pulse:\"\n if (!decodedData.startsWith(\"Dungeonlab+pulse:\")) {\n return false;\n }\n\n // 2. 移除开头标识\n const data = decodedData.substring(\"Dungeonlab+pulse:\".length);\n\n // 3. 分割数据段\n const sections = data.split(\"+section+\");\n\n // 4. 校验第一段数据(兼容新格式)\n const firstSection = sections[0];\n const firstSectionParts = firstSection.split(\"/\");\n\n // 检查是否存在前缀\n const prefixRegex = /^(\\d+,\\d+,\\d+=)?/; // 匹配 \"数字,数字,数字=\" 的可选前缀\n const prefixMatch = firstSection.match(prefixRegex);\n const hasPrefix = prefixMatch && prefixMatch[1];\n\n let intCounts, floatCounts;\n\n if (hasPrefix) {\n // 新格式:包含前缀\n const dataPart = firstSection.substring(prefixMatch[0].length); // 移除前缀\n const dataParts = dataPart.split(\"/\");\n\n if (dataParts.length !== 2) {\n return false;\n }\n\n intCounts = dataParts[0].split(\",\");\n floatCounts = dataParts[1].split(\",\");\n } else {\n // 旧格式:不包含前缀\n if (firstSectionParts.length !== 2) {\n return false;\n }\n\n intCounts = firstSectionParts[0].split(\",\");\n floatCounts = firstSectionParts[1].split(\",\");\n }\n\n if (intCounts.length !== 5) {\n return false;\n }\n if (!intCounts.every(count => /^\\d+$/.test(count))) {\n return false;\n }\n\n if (!floatCounts.every(count => /^-?\\d+(\\.\\d+)?-\\d+$/.test(count))) {\n return false;\n }\n\n // 5. 校验后续数据段(与旧格式相同)\n for (let i = 1; i < sections.length; i++) {\n const section = sections[i];\n const sectionParts = section.split(\"/\");\n if (sectionParts.length !== 2) {\n return false;\n }\n\n const intCounts = sectionParts[0].split(\",\");\n if (intCounts.length !== 5) {\n return false;\n }\n if (!intCounts.every(count => /^\\d+$/.test(count))) {\n return false;\n }\n\n const floatCounts = sectionParts[1].split(\",\");\n if (!floatCounts.every(count => /^-?\\d+(\\.\\d+)?-\\d+$/.test(count))) {\n return false;\n }\n }\n\n return true;\n}\n\nexport default validatePulseData;\n","import app from 'flarum/forum/app';\nimport {extend} from \"flarum/common/extend\";\nimport TextEditor from \"flarum/common/components/TextEditor\";\nimport TextEditorButton from \"flarum/common/components/TextEditorButton\";\nimport renderPulseViewers from \"./util/renderPulseViewers\";\n\napp.initializers.add('klxf-coyote-pulse-viewer', () => {\n extend(TextEditor.prototype, 'toolbarItems', function (items) {\n items.add(\n 'pulse-file-upload',\n m(TextEditorButton, {\n icon: 'fas fa-file-import',\n title: '波形分享',\n onclick: () => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.pulse';\n input.style.display = 'none';\n\n input.addEventListener('change', () => {\n const file = input.files?.[0];\n if (file) {\n const reader = new FileReader();\n reader.onload = () => {\n const fileNameWithoutExtension = file.name.replace(/\\.pulse$/, '');\n const match = fileNameWithoutExtension.match(/^pulse-(.+?)-\\d+$/);\n\n let title: string;\n\n if (match) title = match[1];\n else title = fileNameWithoutExtension;\n\n const pulseText = `[pulse title=\"${title}\"]${reader.result}[/pulse]`;\n // @ts-ignore\n this.attrs?.composer?.editor.insertAtCursor(pulseText);\n };\n reader.readAsText(file);\n }\n });\n\n document.body.appendChild(input);\n input.click();\n document.body.removeChild(input);\n }\n }),\n 81\n );\n });\n\n renderPulseViewers();\n document.body.addEventListener('contentupdated', renderPulseViewers);\n const observer = new MutationObserver(() => {\n renderPulseViewers();\n });\n observer.observe(document.body, {childList: true, subtree: true});\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","flarum","core","compat","app","add","console","log","FREQ_SLIDER_VALUE_MAP","SECTION_TIME_MAP","document","querySelectorAll","forEach","el","getAttribute","error","errorArray","pulseData","replace","pulseTitle","pulseVersion","_el$querySelector","innerHTML","length","slice","push","decodedData","startsWith","intCounts","floatCounts","sections","substring","split","firstSection","firstSectionParts","prefixMatch","match","dataParts","every","count","test","i","sectionParts","validatePulseData","querySelector","remove","join","data","svgWidth","svgContent","speedRate","prefix","_prefix$split$map","map","Number","speed","section","_section$split","header","pulsesStr","_header$split$map","minFreq","maxFreq","durationIndex","mode","isOn","duration","pulses","pulsesDuration","repeatTimes","Math","ceil","_loop","j","sectionWidth","pulseStr","index","freq","_pulseStr$split$map","value","pulseHeight","xPos","yPos","floor","blackBarWidth","numBars","pulseDurationInSecond","whiteBarWidth","barXPos","generateSVG","setAttribute","downloadBtn","addEventListener","attribute","user","show","type","LogInModal","blob","Blob","createElement","href","URL","createObjectURL","download","body","appendChild","click","removeChild","revokeObjectURL","extend","TextEditor","items","_this","m","TextEditorButton","icon","title","onclick","input","accept","style","display","_input$files","file","files","reader","FileReader","onload","_this$attrs","fileNameWithoutExtension","name","pulseText","result","attrs","composer","editor","insertAtCursor","readAsText","renderPulseViewers","MutationObserver","observe","childList","subtree"],"sourceRoot":""} \ No newline at end of file diff --git a/js/src/admin/index.ts b/js/src/admin/index.ts index 8f8ca60..6fd0d99 100644 --- a/js/src/admin/index.ts +++ b/js/src/admin/index.ts @@ -1,5 +1,11 @@ import app from 'flarum/admin/app'; -app.initializers.add('klxf/flarum-coyote-pulse-viewer', () => { - console.log('[klxf/flarum-coyote-pulse-viewer] Hello, admin!'); +app.initializers.add('klxf-coyote-pulse-viewer', () => { + app.extensionData + .for("klxf-coyote-pulse-viewer") + .registerSetting({ + setting: "klxf-coyote-pulse-viewer.download-must-login", + type: "switch", + label: "下载波形文件必须登录", + }); }); diff --git a/js/src/forum/util/renderPulseViewers.ts b/js/src/forum/util/renderPulseViewers.ts index 541823c..27701be 100644 --- a/js/src/forum/util/renderPulseViewers.ts +++ b/js/src/forum/util/renderPulseViewers.ts @@ -1,12 +1,15 @@ import generateSVG from './generateSVG'; import validatePulseData from "./validatePulseData"; +import app from 'flarum/forum/app'; +import LogInModal from "flarum/forum/components/LogInModal"; function renderPulseViewers() { document.querySelectorAll('.coyote-pulse-viewer').forEach(el => { if (el.getAttribute('data-pulse-rendered')) return; let error = false; let errorArray: string[] = []; - const pulseData = el.getAttribute('data-pulse'); + // 替换掉换行 + const pulseData = (el.getAttribute('data-pulse') || '').replace(/\r?\n|\r/g, ''); const pulseTitle = el.getAttribute('data-title') ? el.getAttribute('data-title'): '自定义波形'; const pulseVersion = el.getAttribute('data-version') ? el.getAttribute('data-version') : '3'; if (pulseData) { @@ -34,6 +37,12 @@ function renderPulseViewers() { const downloadBtn = el.querySelector('.pulse-download-btn'); if (downloadBtn) { downloadBtn.addEventListener('click', () => { + if (app.forum.attribute("klxf-coyote-pulse-viewer.download-must-login") && app.session.user == null) { + app.alerts.show({ type: 'warn' }, '请先登录以下载波形文件'); + app.modal.show(LogInModal); + return; + } + const blob = new Blob([pulseData], { type: 'text/plain' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob);