{var f=n??t.appendChild(Hn());return Dn(()=>{if(i){ue({});var d=Ye;d.c=i}o&&(r.$$events=o),Se&&Dt(f,null),u=e(f,r)||{},Se&&(Ke.nodes_end=Ve),i&&ce()}),()=>{var p;for(var d of a){t.removeEventListener(d,io);var g=Pr.get(d);--g===0?(document.removeEventListener(d,io),Pr.delete(d)):Pr.set(d,g)}ws.delete(l),f!==n&&((p=f.parentNode)==null||p.removeChild(f))}});return xs.set(u,c),u}let xs=new WeakMap;function Uf(e,t){const n=xs.get(e);return n?(xs.delete(e),n(t)):Promise.resolve()}function ke(e,t,[n,r]=[0,0]){Se&&n===0&&vn();var o=e,i=null,s=null,a=Tt,l=n>0?br:0,u=!1;const c=(d,g=!0)=>{u=!0,f(g,d)},f=(d,g)=>{if(a===(a=d))return;let p=!1;if(Se&&r!==-1){if(n===0){const C=o.data;C===ns?r=0:C===rs?r=1/0:(r=parseInt(C.substring(1)),r!==r&&(r=a?1/0:-1))}const x=r>n;!!a===x&&(o=fs(),bt(o),It(!1),p=!0,r=-1)}a?(i?oo(i):g&&(i=Dn(()=>g(o))),s&&Er(s,()=>{s=null})):(s?oo(s):g&&(s=Dn(()=>g(o,[n+1,r]))),i&&Er(i,()=>{i=null})),p&&It(!0)};lr(()=>{u=!1,t(c),u||f(null,null)},l),Se&&(o=Ve)}function oi(e,t){return t}function jf(e,t,n,r){for(var o=[],i=t.length,s=0;s0&&o.length===0&&n!==null;if(a){var l=n.parentNode;hs(l),l.append(n),r.clear(),Gn(e,t[0].prev,t[i-1].next)}tl(o,()=>{for(var u=0;u{var g=n();return Gr(g)?g:g==null?[]:as(g)});lr(()=>{var g=h(d),p=g.length;if(f&&p===0)return;f=p===0;let x=!1;if(Se){var C=s.data===rs;C!==(p===0)&&(s=fs(),bt(s),It(!1),x=!0)}if(Se){for(var $=null,m,_=0;_0&&bt(fs())}Se||Jf(g,a,s,o,t,r,n),i!==null&&(p===0?c?oo(c):c=Dn(()=>i(s)):c!==null&&Er(c,()=>{c=null})),x&&It(!0),h(d)}),Se&&(s=Ve)}function Jf(e,t,n,r,o,i,s){var S,M,k,P;var a=(o&Xd)!==0,l=(o&(es|ts))!==0,u=e.length,c=t.items,f=t.first,d=f,g,p=null,x,C=[],$=[],m,_,v,b;if(a)for(b=0;b0){var R=o&Ca&&u===0?n:null;if(a){for(b=0;b{var H;if(x!==void 0)for(v of x)(H=v.a)==null||H.apply()}),Ke.first=t.first&&t.first.e,Ke.last=p&&p.e}function Qf(e,t,n,r){r&es&&ds(e.v,t),r&ts?ds(e.i,n):e.i=n}function ul(e,t,n,r,o,i,s,a,l,u){var c=(l&es)!==0,f=(l&Fd)===0,d=c?f?no(o):Mt(o):o,g=l&ts?Mt(s):s,p={i:g,v:d,k:i,a:null,e:null,prev:n,next:r};try{return p.e=Dn(()=>a(e,d,g,u),Se),p.e.prev=n&&n.e,p.e.next=r&&r.e,n===null?t.first=p:(n.next=p,n.e.next=p.e),r!==null&&(r.prev=p,r.e.prev=p.e),p}finally{}}function cl(e,t,n){for(var r=e.next?e.next.e.nodes_start:n,o=t?t.e.nodes_start:n,i=e.e.nodes_start;i!==r;){var s=pn(i);o.before(i),i=s}}function Gn(e,t,n){t===null?e.first=n:(t.next=n,t.e.next=n&&n.e),n!==null&&(n.prev=t,n.e.prev=t&&t.e)}function dl(e,t,n,r,o){var i=e,s="",a;lr(()=>{if(s===(s=t()??"")){Se&&vn();return}a!==void 0&&(qt(a),a=void 0),s!==""&&(a=Dn(()=>{if(Se){Ve.data;for(var l=vn(),u=l;l!==null&&(l.nodeType!==8||l.data!=="");)u=l,l=pn(l);if(l===null)throw Wo(),_r;Dt(Ve,u),i=bt(l);return}var c=s+"",f=_s(c);Dt(Ct(f),f.lastChild),i.before(f)}))})}function wt(e,t,n,r,o){var a;Se&&vn();var i=(a=t.$$slots)==null?void 0:a[n],s=!1;i===!0&&(i=t[n==="default"?"children":n],s=!0),i===void 0||i(e,s?()=>r:r)}function e1(e){const t={};e.children&&(t.default=!0);for(const n in e.$$slots)t[n]=!0;return t}function cr(e,t,...n){var r=e,o=gt,i;lr(()=>{o!==(o=t())&&(i&&(qt(i),i=null),i=Dn(()=>o(r,...n)))},br),Se&&(r=Ve)}function fl(e,t,n){Se&&vn();var r=e,o,i;lr(()=>{o!==(o=t())&&(i&&(Er(i),i=null),o&&(i=Dn(()=>n(r,o))))},br),Se&&(r=Ve)}function t1(e,t,n,r,o,i){let s=Se;Se&&vn();var a,l,u=null;Se&&Ve.nodeType===1&&(u=Ve,vn());var c=Se?Ve:e,f;lr(()=>{const d=t()||null;var g=d==="svg"?Ea:null;d!==a&&(f&&(d===null?Er(f,()=>{f=null,l=null}):d===l?oo(f):qt(f)),d&&d!==l&&(f=Dn(()=>{if(u=Se?u:g?document.createElementNS(g,d):document.createElement(d),Dt(u,u),r){Se&&Xf(d)&&u.append(document.createComment(""));var p=Se?Ct(u):u.appendChild(Hn());Se&&(p===null?It(!1):bt(p)),r(u,p)}Ke.nodes_end=u,c.before(u)})),a=d,a&&(l=a))},br),s&&(It(!0),bt(c))}function et(e,t){to(()=>{var n=e.getRootNode(),r=n.host?n:n.head??n.ownerDocument.head;if(!r.querySelector("#"+t.hash)){const o=document.createElement("style");o.id=t.hash,o.textContent=t.code,r.appendChild(o)}})}function _t(e,t,n){Rt(()=>{var r=yn(()=>t(e,n==null?void 0:n())||{});if(n&&(r!=null&&r.update)){var o=!1,i={};$r(()=>{var s=n();j(s),o&&us(i,s)&&(i=s,r.update(s))}),o=!0}if(r!=null&&r.destroy)return()=>r.destroy()})}function gl(e){var t,n,r="";if(typeof e=="string"||typeof e=="number")r+=e;else if(typeof e=="object")if(Array.isArray(e)){var o=e.length;for(t=0;t=0;){var a=s+i;(s===0||hl.includes(r[s-1]))&&(a===r.length||hl.includes(r[a]))?r=(s===0?"":r.substring(0,s))+r.substring(a+1):s=a}}return r===""?null:r}function $t(e,t,n,r,o,i){var s=e.__className;if(Se||s!==n){var a=r1(n,r,i);(!Se||a!==e.getAttribute("class"))&&(a==null?e.removeAttribute("class"):t?e.className=a:e.setAttribute("class",a)),e.__className=n}else if(i)for(var l in i){var u=!!i[l];(o==null||u!==!!o[l])&&e.classList.toggle(l,u)}return i}const so=Symbol("class");function ao(e){if(Se){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute("value")){var r=e.value;de(e,"value",null),e.value=r}if(e.hasAttribute("checked")){var o=e.checked;de(e,"checked",null),e.checked=o}}};e.__on_r=n,af(n),Kf()}}function bs(e,t){var n=e.__attributes??(e.__attributes={});n.value===(n.value=t??void 0)||e.value===t&&(t!==0||e.nodeName!=="PROGRESS")||(e.value=t??"")}function o1(e,t){t?e.hasAttribute("selected")||e.setAttribute("selected",""):e.removeAttribute("selected")}function de(e,t,n,r){var o=e.__attributes??(e.__attributes={});Se&&(o[t]=e.getAttribute(t),t==="src"||t==="srcset"||t==="href"&&e.nodeName==="LINK")||o[t]!==(o[t]=n)&&(t==="style"&&"__styles"in e&&(e.__styles={}),t==="loading"&&(e[ef]=n),n==null?e.removeAttribute(t):typeof n!="string"&&pl(e).includes(t)?e[t]=n:e.setAttribute(t,n))}function nn(e,t,n,r,o=!1,i=!1,s=!1){let a=Se&&i;a&&It(!1);var l=t||{},u=e.tagName==="OPTION";for(var c in t)c in n||(n[c]=null);n.class?n.class=wn(n.class):(r||n[so])&&(n.class=null);var f=pl(e),d=e.__attributes??(e.__attributes={});for(const _ in n){let v=n[_];if(u&&_==="value"&&v==null){e.value=e.__value="",l[_]=v;continue}if(_==="class"){var g=e.namespaceURI==="http://www.w3.org/1999/xhtml";$t(e,g,v,r,t==null?void 0:t[so],n[so]),l[_]=v,l[so]=n[so];continue}var p=l[_];if(v!==p){l[_]=v;var x=_[0]+_[1];if(x!=="$$"){if(x==="on"){const b={},N="$$"+_;let E=_.slice(2);var C=If(E);if(Lf(E)&&(E=E.slice(0,-7),b.capture=!0),!C&&p){if(v!=null)continue;e.removeEventListener(E,l[N],b),l[N]=null}if(v!=null)if(C)e[`__${E}`]=v,ri([E]);else{let T=function(D){l[_].call(this,D)};l[N]=sl(E,e,T,b)}else C&&(e[`__${E}`]=void 0)}else if(_==="style"&&v!=null)e.style.cssText=v+"";else if(_==="autofocus")Ff(e,!!v);else if(!i&&(_==="__value"||_==="value"&&v!=null))e.value=e.__value=v;else if(_==="selected"&&u)o1(e,v);else{var $=_;o||($=Rf($));var m=$==="defaultValue"||$==="defaultChecked";if(v==null&&!i&&!m)if(d[_]=null,$==="value"||$==="checked"){let b=e;const N=t===void 0;if($==="value"){let E=b.defaultValue;b.removeAttribute($),b.defaultValue=E,b.value=b.__value=N?E:null}else{let E=b.defaultChecked;b.removeAttribute($),b.defaultChecked=E,b.checked=N?E:!1}}else e.removeAttribute(_);else m||f.includes($)&&(i||typeof v!="string")?e[$]=v:typeof v!="function"&&de(e,$,v)}_==="style"&&"__styles"in e&&(e.__styles={})}}}return a&&It(!0),l}var vl=new Map;function pl(e){var t=vl.get(e.nodeName);if(t)return t;vl.set(e.nodeName,t=[]);for(var n,r=e,o=Element.prototype;o!==r;){n=Ta(r);for(var i in n)n[i].set&&t.push(i);r=ls(r)}return t}function at(e,t,n,r){var o=e.__styles??(e.__styles={});o[t]!==n&&(o[t]=n,n==null?e.style.removeProperty(t):e.style.setProperty(t,n,""))}const Ui=class Ui{constructor(t){wr(this,Gi);wr(this,or,new WeakMap);wr(this,qr);wr(this,Lo);zo(this,Lo,t)}observe(t,n){var r=ut(this,or).get(t)||new Set;return r.add(n),ut(this,or).set(t,r),Bd(this,Gi,Yd).call(this).observe(t,ut(this,Lo)),()=>{var o=ut(this,or).get(t);o.delete(n),o.size===0&&(ut(this,or).delete(t),ut(this,qr).unobserve(t))}}};or=new WeakMap,qr=new WeakMap,Lo=new WeakMap,Gi=new WeakSet,Yd=function(){return ut(this,qr)??zo(this,qr,new ResizeObserver(t=>{for(var n of t){Ui.entries.set(n.target,n);for(var r of ut(this,or).get(n.target)||[])r(n)}}))},Nt(Ui,"entries",new WeakMap);let Cs=Ui;var i1=new Cs({box:"border-box"});function ml(e,t,n){var r=i1.observe(e,()=>n(e[t]));Rt(()=>(yn(()=>n(e[t])),r))}function yl(e,t){return e===t||(e==null?void 0:e[Xn])===t}function An(e={},t,n,r){return Rt(()=>{var o,i;return $r(()=>{o=i,i=[],yn(()=>{e!==n(...i)&&(t(e,...i),o&&yl(n(...o),e)&&t(null,...o))})}),()=>{to(()=>{i&&yl(n(...i),e)&&t(null,...i)})}}),e}function ks(e){return function(...t){var n=t[0];return n.stopPropagation(),e==null?void 0:e.apply(this,t)}}function He(e=!1){const t=Ye,n=t.l.u;if(!n)return;let r=()=>j(t.s);if(e){let o=0,i={};const s=Ne(()=>{let a=!1;const l=t.s;for(const u in l)l[u]!==i[u]&&(i[u]=l[u],a=!0);return a&&o++,o});r=()=>h(s)}n.b.length&&Tf(()=>{wl(t,r),Jr(n.b)}),kr(()=>{const o=yn(()=>n.m.map(of));return()=>{for(const i of o)typeof i=="function"&&i()}}),n.a.length&&kr(()=>{wl(t,r),Jr(n.a)})}function wl(e,t){if(e.l.s)for(const n of e.l.s)h(n);t()}function De(e,t){var i;var n=(i=e.$$events)==null?void 0:i[t.type],r=Gr(n)?n.slice():n==null?[]:[n];for(var o of r)o.call(this,t)}function rn(e){Ye===null&&ti(),ot&&Ye.l!==null?a1(Ye).m.push(e):kr(()=>{const t=yn(e);if(typeof t=="function")return t})}function $s(e){Ye===null&&ti(),rn(()=>()=>yn(e))}function s1(e,t,{bubbles:n=!1,cancelable:r=!1}={}){return new CustomEvent(e,{detail:t,bubbles:n,cancelable:r})}function ii(){const e=Ye;return e===null&&ti(),(t,n,r)=>{var i;const o=(i=e.s.$$events)==null?void 0:i[t];if(o){const s=Gr(o)?o.slice():[o],a=s1(t,n,r);for(const l of s)l.call(e.x,a);return!a.defaultPrevented}return!0}}function a1(e){var t=e.l;return t.u??(t.u={a:[],b:[],m:[]})}function Es(e,t,n){if(e==null)return t(void 0),n&&n(void 0),gt;const r=yn(()=>e.subscribe(t,n));return r.unsubscribe?()=>r.unsubscribe():r}const Nr=[];function Gt(e,t){return{subscribe:we(e,t).subscribe}}function we(e,t=gt){let n=null;const r=new Set;function o(a){if(us(e,a)&&(e=a,n)){const l=!Nr.length;for(const u of r)u[1](),Nr.push(u,e);if(l){for(let u=0;u{r.delete(u),r.size===0&&n&&(n(),n=null)}}return{set:o,update:i,subscribe:s}}function Un(e,t,n){const r=!Array.isArray(e),o=r?[e]:e;if(!o.every(Boolean))throw new Error("derived() expects stores as input, got a falsy value");const i=t.length<2;return Gt(n,(s,a)=>{let l=!1;const u=[];let c=0,f=gt;const d=()=>{if(c)return;f();const p=t(r?u[0]:u,s,a);i?s(p):f=typeof p=="function"?p:gt},g=o.map((p,x)=>Es(p,C=>{u[x]=C,c&=~(1<{c|=1<t=n)(),t}let si=!1,Ss=Symbol();function Q(e,t,n){const r=n[t]??(n[t]={store:null,source:no(void 0),unsubscribe:gt});if(r.store!==e&&!(Ss in n))if(r.unsubscribe(),r.store=e??null,e==null)r.source.v=void 0,r.unsubscribe=gt;else{var o=!0;r.unsubscribe=Es(e,i=>{o?r.source.v=i:U(r.source,i)}),o=!1}return e&&Ss in n?q(e):h(r.source)}function l1(e,t,n){let r=n[t];return r&&r.store!==e&&(r.unsubscribe(),r.unsubscribe=gt),e}function ai(e,t){return e.set(t),t}function nt(){const e={};function t(){ja(()=>{for(var n in e)e[n].unsubscribe();Ur(e,Ss,{enumerable:!1,value:!0})})}return[e,t]}function u1(e){var t=si;try{return si=!1,[e(),si]}finally{si=t}}const c1={get(e,t){if(!e.exclude.includes(t))return e.props[t]},set(e,t){return!1},getOwnPropertyDescriptor(e,t){if(!e.exclude.includes(t)&&t in e.props)return{enumerable:!0,configurable:!0,value:e.props[t]}},has(e,t){return e.exclude.includes(t)?!1:t in e.props},ownKeys(e){return Reflect.ownKeys(e.props).filter(t=>!e.exclude.includes(t))}};function xt(e,t,n){return new Proxy({props:e,exclude:t},c1)}const d1={get(e,t){if(!e.exclude.includes(t))return h(e.version),t in e.special?e.special[t]():e.props[t]},set(e,t,n){return t in e.special||(e.special[t]=w({get[t](){return e.props[t]}},t,ka)),e.special[t](n),La(e.version),!0},getOwnPropertyDescriptor(e,t){if(!e.exclude.includes(t)&&t in e.props)return{enumerable:!0,configurable:!0,value:e.props[t]}},deleteProperty(e,t){return e.exclude.includes(t)||(e.exclude.push(t),La(e.version)),!0},has(e,t){return e.exclude.includes(t)?!1:t in e.props},ownKeys(e){return Reflect.ownKeys(e.props).filter(t=>!e.exclude.includes(t))}};function it(e,t){return new Proxy({props:e,exclude:t,special:{},version:Mt(0)},d1)}const f1={get(e,t){let n=e.props.length;for(;n--;){let r=e.props[n];if(jr(r)&&(r=r()),typeof r=="object"&&r!==null&&t in r)return r[t]}},set(e,t,n){let r=e.props.length;for(;r--;){let o=e.props[r];jr(o)&&(o=o());const i=Mn(o,t);if(i&&i.set)return i.set(n),!0}return!1},getOwnPropertyDescriptor(e,t){let n=e.props.length;for(;n--;){let r=e.props[n];if(jr(r)&&(r=r()),typeof r=="object"&&r!==null&&t in r){const o=Mn(r,t);return o&&!o.configurable&&(o.configurable=!0),o}}},has(e,t){if(t===Xn||t===ss)return!1;for(let n of e.props)if(jr(n)&&(n=n()),n!=null&&t in n)return!0;return!1},ownKeys(e){const t=[];for(let n of e.props){jr(n)&&(n=n());for(const r in n)t.includes(r)||t.push(r)}return t}};function ft(...e){return new Proxy({props:e},f1)}function w(e,t,n,r){var N;var o=(n&Wd)!==0,i=!ot||(n&Kd)!==0,s=(n&qd)!==0,a=(n&Gd)!==0,l=!1,u;s?[u,l]=u1(()=>e[t]):u=e[t];var c=Xn in e||ss in e,f=s&&(((N=Mn(e,t))==null?void 0:N.set)??(c&&t in e&&(E=>e[t]=E)))||void 0,d=r,g=!0,p=!1,x=()=>(p=!0,g&&(g=!1,a?d=yn(r):d=r),d);u===void 0&&r!==void 0&&(f&&i&&gf(),u=x(),f&&f(u));var C;if(i)C=()=>{var E=e[t];return E===void 0?x():(g=!0,p=!1,E)};else{var $=(o?Ne:ve)(()=>e[t]);$.f|=Jd,C=()=>{var E=h($);return E!==void 0&&(d=void 0),E===void 0?d:E}}if(!(n&ka))return C;if(f){var m=e.$$legacy;return function(E,T){return arguments.length>0?((!i||!T||m||l)&&f(T?C():E),E):C()}}var _=!1,v=no(u),b=Ne(()=>{var E=C(),T=h(v);return _?(_=!1,T):v.v=E});return o||(b.equals=cs),function(E,T){if(arguments.length>0){const D=T?h(b):i&&s?Ht(E):E;return b.equals(D)||(_=!0,U(v,D),p&&d!==void 0&&(d=D),yn(()=>h(b))),E}return h(b)}}function g1(e){return new h1(e)}class h1{constructor(t){wr(this,Zn);wr(this,jt);var i;var n=new Map,r=(s,a)=>{var l=no(a);return n.set(s,l),l};const o=new Proxy({...t.props||{},$$events:{}},{get(s,a){return h(n.get(a)??r(a,Reflect.get(s,a)))},has(s,a){return a===ss?!0:(h(n.get(a)??r(a,Reflect.get(s,a))),Reflect.has(s,a))},set(s,a,l){return U(n.get(a)??r(a,l),l),Reflect.set(s,a,l)}});zo(this,jt,(t.hydrate?Gf:al)(t.component,{target:t.target,anchor:t.anchor,props:o,context:t.context,intro:t.intro??!1,recover:t.recover})),(!((i=t==null?void 0:t.props)!=null&&i.$$host)||t.sync===!1)&&y(),zo(this,Zn,o.$$events);for(const s of Object.keys(ut(this,jt)))s==="$set"||s==="$destroy"||s==="$on"||Ur(this,s,{get(){return ut(this,jt)[s]},set(a){ut(this,jt)[s]=a},enumerable:!0});ut(this,jt).$set=s=>{Object.assign(o,s)},ut(this,jt).$destroy=()=>{Uf(ut(this,jt))}}$set(t){ut(this,jt).$set(t)}$on(t,n){ut(this,Zn)[t]=ut(this,Zn)[t]||[];const r=(...o)=>n.call(this,...o);return ut(this,Zn)[t].push(r),()=>{ut(this,Zn)[t]=ut(this,Zn)[t].filter(o=>o!==r)}}$destroy(){ut(this,jt).$destroy()}}Zn=new WeakMap,jt=new WeakMap;let _l;typeof HTMLElement=="function"&&(_l=class extends HTMLElement{constructor(t,n,r){super();Nt(this,"$$ctor");Nt(this,"$$s");Nt(this,"$$c");Nt(this,"$$cn",!1);Nt(this,"$$d",{});Nt(this,"$$r",!1);Nt(this,"$$p_d",{});Nt(this,"$$l",{});Nt(this,"$$l_u",new Map);Nt(this,"$$me");this.$$ctor=t,this.$$s=n,r&&this.attachShadow({mode:"open"})}addEventListener(t,n,r){if(this.$$l[t]=this.$$l[t]||[],this.$$l[t].push(n),this.$$c){const o=this.$$c.$on(t,n);this.$$l_u.set(n,o)}super.addEventListener(t,n,r)}removeEventListener(t,n,r){if(super.removeEventListener(t,n,r),this.$$c){const o=this.$$l_u.get(n);o&&(o(),this.$$l_u.delete(n))}}async connectedCallback(){if(this.$$cn=!0,!this.$$c){let t=function(o){return i=>{const s=document.createElement("slot");o!=="default"&&(s.name=o),L(i,s)}};if(await Promise.resolve(),!this.$$cn||this.$$c)return;const n={},r=v1(this);for(const o of this.$$s)o in r&&(o==="default"&&!this.$$d.children?(this.$$d.children=t(o),n.default=!0):n[o]=t(o));for(const o of this.attributes){const i=this.$$g_p(o.name);i in this.$$d||(this.$$d[i]=li(i,o.value,this.$$p_d,"toProp"))}for(const o in this.$$p_d)!(o in this.$$d)&&this[o]!==void 0&&(this.$$d[o]=this[o],delete this[o]);this.$$c=g1({component:this.$$ctor,target:this.shadowRoot||this,props:{...this.$$d,$$slots:n,$$host:this}}),this.$$me=Mf(()=>{$r(()=>{var o;this.$$r=!0;for(const i of Fo(this.$$c)){if(!((o=this.$$p_d[i])!=null&&o.reflect))continue;this.$$d[i]=this.$$c[i];const s=li(i,this.$$d[i],this.$$p_d,"toAttribute");s==null?this.removeAttribute(this.$$p_d[i].attribute||i):this.setAttribute(this.$$p_d[i].attribute||i,s)}this.$$r=!1})});for(const o in this.$$l)for(const i of this.$$l[o]){const s=this.$$c.$on(o,i);this.$$l_u.set(i,s)}this.$$l={}}}attributeChangedCallback(t,n,r){var o;this.$$r||(t=this.$$g_p(t),this.$$d[t]=li(t,r,this.$$p_d,"toProp"),(o=this.$$c)==null||o.$set({[t]:this.$$d[t]}))}disconnectedCallback(){this.$$cn=!1,Promise.resolve().then(()=>{!this.$$cn&&this.$$c&&(this.$$c.$destroy(),this.$$me(),this.$$c=void 0)})}$$g_p(t){return Fo(this.$$p_d).find(n=>this.$$p_d[n].attribute===t||!this.$$p_d[n].attribute&&n.toLowerCase()===t)||t}});function li(e,t,n,r){var i;const o=(i=n[e])==null?void 0:i.type;if(t=o==="Boolean"&&typeof t!="boolean"?t!=null:t,!r||!n[e])return t;if(r==="toAttribute")switch(o){case"Object":case"Array":return t==null?null:JSON.stringify(t);case"Boolean":return t?"":null;case"Number":return t??null;default:return t}else switch(o){case"Object":case"Array":return t&&JSON.parse(t);case"Boolean":return t;case"Number":return t!=null?+t:t;default:return t}}function v1(e){const t={};return e.childNodes.forEach(n=>{t[n.slot||"default"]=!0}),t}function ie(e,t,n,r,o,i){let s=class extends _l{constructor(){super(e,n,o),this.$$p_d=t}static get observedAttributes(){return Fo(t).map(a=>(t[a].attribute||a).toLowerCase())}};return Fo(t).forEach(a=>{Ur(s.prototype,a,{get(){return this.$$c&&a in this.$$c?this.$$c[a]:this.$$d[a]},set(l){var f;l=li(a,l,t),this.$$d[a]=l;var u=this.$$c;if(u){var c=(f=Mn(u,a))==null?void 0:f.get;c?u[a]=l:u.$set({[a]:l})}}})}),r.forEach(a=>{Ur(s.prototype,a,{get(){var l;return(l=this.$$c)==null?void 0:l[a]}})}),e.element=s,s}function Et(e){if(typeof e=="string"||typeof e=="number")return""+e;let t="";if(Array.isArray(e))for(let n=0,r;n{}};function ui(){for(var e=0,t=arguments.length,n={},r;e=0&&(r=n.slice(o+1),n=n.slice(0,o)),n&&!t.hasOwnProperty(n))throw new Error("unknown type: "+n);return{type:n,name:r}})}ci.prototype=ui.prototype={constructor:ci,on:function(e,t){var n=this._,r=m1(e+"",n),o,i=-1,s=r.length;if(arguments.length<2){for(;++i0)for(var n=new Array(o),r=0,o,i;r=0&&(t=e.slice(0,n))!=="xmlns"&&(e=e.slice(n+1)),bl.hasOwnProperty(t)?{space:bl[t],local:e}:e}function w1(e){return function(){var t=this.ownerDocument,n=this.namespaceURI;return n===Ps&&t.documentElement.namespaceURI===Ps?t.createElement(e):t.createElementNS(n,e)}}function _1(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function Cl(e){var t=di(e);return(t.local?_1:w1)(t)}function x1(){}function Ns(e){return e==null?x1:function(){return this.querySelector(e)}}function b1(e){typeof e!="function"&&(e=Ns(e));for(var t=this._groups,n=t.length,r=new Array(n),o=0;o=_&&(_=m+1);!(b=C[_])&&++_=0;)(s=r[o])&&(i&&s.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(s,i),i=s);return this}function K1(e){e||(e=q1);function t(f,d){return f&&d?e(f.__data__,d.__data__):!f-!d}for(var n=this._groups,r=n.length,o=new Array(r),i=0;it?1:e>=t?0:NaN}function G1(){var e=arguments[0];return arguments[0]=this,e.apply(null,arguments),this}function U1(){return Array.from(this)}function j1(){for(var e=this._groups,t=0,n=e.length;t1?this.each((t==null?lg:typeof t=="function"?cg:ug)(e,t,n??"")):Tr(this.node(),e)}function Tr(e,t){return e.style.getPropertyValue(t)||Pl(e).getComputedStyle(e,null).getPropertyValue(t)}function fg(e){return function(){delete this[e]}}function gg(e,t){return function(){this[e]=t}}function hg(e,t){return function(){var n=t.apply(this,arguments);n==null?delete this[e]:this[e]=n}}function vg(e,t){return arguments.length>1?this.each((t==null?fg:typeof t=="function"?hg:gg)(e,t)):this.node()[e]}function Nl(e){return e.trim().split(/^|\s+/)}function Ts(e){return e.classList||new Tl(e)}function Tl(e){this._node=e,this._names=Nl(e.getAttribute("class")||"")}Tl.prototype={add:function(e){var t=this._names.indexOf(e);t<0&&(this._names.push(e),this._node.setAttribute("class",this._names.join(" ")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(e){return this._names.indexOf(e)>=0}};function Ml(e,t){for(var n=Ts(e),r=-1,o=t.length;++r=0&&(n=t.slice(r+1),t=t.slice(0,r)),{type:t,name:n}})}function Zg(e){return function(){var t=this.__on;if(t){for(var n=0,r=-1,o=t.length,i;n()=>e;function Hs(e,{sourceEvent:t,subject:n,target:r,identifier:o,active:i,x:s,y:a,dx:l,dy:u,dispatch:c}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},subject:{value:n,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:o,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:s,enumerable:!0,configurable:!0},y:{value:a,enumerable:!0,configurable:!0},dx:{value:l,enumerable:!0,configurable:!0},dy:{value:u,enumerable:!0,configurable:!0},_:{value:c}})}Hs.prototype.on=function(){var e=this._.on.apply(this._,arguments);return e===this._?this:e};function Qg(e){return!e.ctrlKey&&!e.button}function eh(){return this.parentNode}function th(e,t){return t??{x:e.x,y:e.y}}function nh(){return navigator.maxTouchPoints||"ontouchstart"in this}function rh(){var e=Qg,t=eh,n=th,r=nh,o={},i=ui("start","drag","end"),s=0,a,l,u,c,f=0;function d(v){v.on("mousedown.drag",g).filter(r).on("touchstart.drag",C).on("touchmove.drag",$,Jg).on("touchend.drag touchcancel.drag",m).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function g(v,b){if(!(c||!e.call(this,v,b))){var N=_(this,t.call(this,v,b),v,b,"mouse");N&&(Ut(v.view).on("mousemove.drag",p,uo).on("mouseup.drag",x,uo),Al(v.view),Ms(v),u=!1,a=v.clientX,l=v.clientY,N("start",v))}}function p(v){if(Mr(v),!u){var b=v.clientX-a,N=v.clientY-l;u=b*b+N*N>f}o.mouse("drag",v)}function x(v){Ut(v.view).on("mousemove.drag mouseup.drag",null),Ll(v.view,u),Mr(v),o.mouse("end",v)}function C(v,b){if(e.call(this,v,b)){var N=v.changedTouches,E=t.call(this,v,b),T=N.length,D,V;for(D=0;D>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):n===8?vi(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):n===4?vi(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=ih.exec(e))?new At(t[1],t[2],t[3],1):(t=sh.exec(e))?new At(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=ah.exec(e))?vi(t[1],t[2],t[3],t[4]):(t=lh.exec(e))?vi(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=uh.exec(e))?Xl(t[1],t[2]/100,t[3]/100,1):(t=ch.exec(e))?Xl(t[1],t[2]/100,t[3]/100,t[4]):Il.hasOwnProperty(e)?Bl(Il[e]):e==="transparent"?new At(NaN,NaN,NaN,0):null}function Bl(e){return new At(e>>16&255,e>>8&255,e&255,1)}function vi(e,t,n,r){return r<=0&&(e=t=n=NaN),new At(e,t,n,r)}function gh(e){return e instanceof co||(e=ho(e)),e?(e=e.rgb(),new At(e.r,e.g,e.b,e.opacity)):new At}function Ds(e,t,n,r){return arguments.length===1?gh(e):new At(e,t,n,r??1)}function At(e,t,n,r){this.r=+e,this.g=+t,this.b=+n,this.opacity=+r}Vs(At,Ds,Ol(co,{brighter(e){return e=e==null?hi:Math.pow(hi,e),new At(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?fo:Math.pow(fo,e),new At(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new At(dr(this.r),dr(this.g),dr(this.b),pi(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Yl,formatHex:Yl,formatHex8:hh,formatRgb:Zl,toString:Zl}));function Yl(){return`#${fr(this.r)}${fr(this.g)}${fr(this.b)}`}function hh(){return`#${fr(this.r)}${fr(this.g)}${fr(this.b)}${fr((isNaN(this.opacity)?1:this.opacity)*255)}`}function Zl(){const e=pi(this.opacity);return`${e===1?"rgb(":"rgba("}${dr(this.r)}, ${dr(this.g)}, ${dr(this.b)}${e===1?")":`, ${e})`}`}function pi(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function dr(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function fr(e){return e=dr(e),(e<16?"0":"")+e.toString(16)}function Xl(e,t,n,r){return r<=0?e=t=n=NaN:n<=0||n>=1?e=t=NaN:t<=0&&(e=NaN),new sn(e,t,n,r)}function Fl(e){if(e instanceof sn)return new sn(e.h,e.s,e.l,e.opacity);if(e instanceof co||(e=ho(e)),!e)return new sn;if(e instanceof sn)return e;e=e.rgb();var t=e.r/255,n=e.g/255,r=e.b/255,o=Math.min(t,n,r),i=Math.max(t,n,r),s=NaN,a=i-o,l=(i+o)/2;return a?(t===i?s=(n-r)/a+(n0&&l<1?0:s,new sn(s,a,l,e.opacity)}function vh(e,t,n,r){return arguments.length===1?Fl(e):new sn(e,t,n,r??1)}function sn(e,t,n,r){this.h=+e,this.s=+t,this.l=+n,this.opacity=+r}Vs(sn,vh,Ol(co,{brighter(e){return e=e==null?hi:Math.pow(hi,e),new sn(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?fo:Math.pow(fo,e),new sn(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*t,o=2*n-r;return new At(As(e>=240?e-240:e+120,o,r),As(e,o,r),As(e<120?e+240:e-120,o,r),this.opacity)},clamp(){return new sn(Wl(this.h),mi(this.s),mi(this.l),pi(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const e=pi(this.opacity);return`${e===1?"hsl(":"hsla("}${Wl(this.h)}, ${mi(this.s)*100}%, ${mi(this.l)*100}%${e===1?")":`, ${e})`}`}}));function Wl(e){return e=(e||0)%360,e<0?e+360:e}function mi(e){return Math.max(0,Math.min(1,e||0))}function As(e,t,n){return(e<60?t+(n-t)*e/60:e<180?n:e<240?t+(n-t)*(240-e)/60:t)*255}const Kl=e=>()=>e;function ph(e,t){return function(n){return e+n*t}}function mh(e,t,n){return e=Math.pow(e,n),t=Math.pow(t,n)-e,n=1/n,function(r){return Math.pow(e+r*t,n)}}function yh(e){return(e=+e)==1?ql:function(t,n){return n-t?mh(t,n,e):Kl(isNaN(t)?n:t)}}function ql(e,t){var n=t-e;return n?ph(e,n):Kl(isNaN(e)?t:e)}const Gl=function e(t){var n=yh(t);function r(o,i){var s=n((o=Ds(o)).r,(i=Ds(i)).r),a=n(o.g,i.g),l=n(o.b,i.b),u=ql(o.opacity,i.opacity);return function(c){return o.r=s(c),o.g=a(c),o.b=l(c),o.opacity=u(c),o+""}}return r.gamma=e,r}(1);function jn(e,t){return e=+e,t=+t,function(n){return e*(1-n)+t*n}}var Ls=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Os=new RegExp(Ls.source,"g");function wh(e){return function(){return e}}function _h(e){return function(t){return e(t)+""}}function xh(e,t){var n=Ls.lastIndex=Os.lastIndex=0,r,o,i,s=-1,a=[],l=[];for(e=e+"",t=t+"";(r=Ls.exec(e))&&(o=Os.exec(t));)(i=o.index)>n&&(i=t.slice(n,i),a[s]?a[s]+=i:a[++s]=i),(r=r[0])===(o=o[0])?a[s]?a[s]+=o:a[++s]=o:(a[++s]=null,l.push({i:s,x:jn(r,o)})),n=Os.lastIndex;return n180?c+=360:c-u>180&&(u+=360),d.push({i:f.push(o(f)+"rotate(",null,r)-2,x:jn(u,c)})):c&&f.push(o(f)+"rotate("+c+r)}function a(u,c,f,d){u!==c?d.push({i:f.push(o(f)+"skewX(",null,r)-2,x:jn(u,c)}):c&&f.push(o(f)+"skewX("+c+r)}function l(u,c,f,d,g,p){if(u!==f||c!==d){var x=g.push(o(g)+"scale(",null,",",null,")");p.push({i:x-4,x:jn(u,f)},{i:x-2,x:jn(c,d)})}else(f!==1||d!==1)&&g.push(o(g)+"scale("+f+","+d+")")}return function(u,c){var f=[],d=[];return u=e(u),c=e(c),i(u.translateX,u.translateY,c.translateX,c.translateY,f,d),s(u.rotate,c.rotate,f,d),a(u.skewX,c.skewX,f,d),l(u.scaleX,u.scaleY,c.scaleX,c.scaleY,f,d),u=c=null,function(g){for(var p=-1,x=d.length,C;++p=0&&e._call.call(void 0,t),e=e._next;--Vr}function ru(){gr=(_i=yo.now())+xi,Vr=vo=0;try{Mh()}finally{Vr=0,Vh(),gr=0}}function Hh(){var e=yo.now(),t=e-_i;t>eu&&(xi-=t,_i=e)}function Vh(){for(var e,t=wi,n,r=1/0;t;)t._call?(r>t._time&&(r=t._time),e=t,t=t._next):(n=t._next,t._next=null,t=e?e._next=n:wi=n);mo=e,Rs(r)}function Rs(e){if(!Vr){vo&&(vo=clearTimeout(vo));var t=e-gr;t>24?(e<1/0&&(vo=setTimeout(ru,e-yo.now()-xi)),po&&(po=clearInterval(po))):(po||(_i=yo.now(),po=setInterval(Hh,eu)),Vr=1,tu(ru))}}function ou(e,t,n){var r=new bi;return t=t==null?0:+t,r.restart(o=>{r.stop(),e(o+t)},t,n),r}var Dh=ui("start","end","cancel","interrupt"),Ah=[],iu=0,su=1,Bs=2,Ci=3,au=4,Ys=5,ki=6;function $i(e,t,n,r,o,i){var s=e.__transition;if(!s)e.__transition={};else if(n in s)return;Lh(e,n,{name:t,index:r,group:o,on:Dh,tween:Ah,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:iu})}function Zs(e,t){var n=an(e,t);if(n.state>iu)throw new Error("too late; already scheduled");return n}function xn(e,t){var n=an(e,t);if(n.state>Ci)throw new Error("too late; already running");return n}function an(e,t){var n=e.__transition;if(!n||!(n=n[t]))throw new Error("transition not found");return n}function Lh(e,t,n){var r=e.__transition,o;r[t]=n,n.timer=nu(i,0,n.time);function i(u){n.state=su,n.timer.restart(s,n.delay,n.time),n.delay<=u&&s(u-n.delay)}function s(u){var c,f,d,g;if(n.state!==su)return l();for(c in r)if(g=r[c],g.name===n.name){if(g.state===Ci)return ou(s);g.state===au?(g.state=ki,g.timer.stop(),g.on.call("interrupt",e,e.__data__,g.index,g.group),delete r[c]):+cBs&&r.state=0&&(t=t.slice(0,n)),!t||t==="start"})}function fv(e,t,n){var r,o,i=dv(t)?Zs:xn;return function(){var s=i(this,e),a=s.on;a!==r&&(o=(r=a).copy()).on(t,n),s.on=o}}function gv(e,t){var n=this._id;return arguments.length<2?an(this.node(),n).on.on(e):this.each(fv(n,e,t))}function hv(e){return function(){var t=this.parentNode;for(var n in this.__transition)if(+n!==e)return;t&&t.removeChild(this)}}function vv(){return this.on("end.remove",hv(this._id))}function pv(e){var t=this._name,n=this._id;typeof e!="function"&&(e=Ns(e));for(var r=this._groups,o=r.length,i=new Array(o),s=0;s()=>e;function Bv(e,{sourceEvent:t,target:n,transform:r,dispatch:o}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},target:{value:n,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:o}})}function In(e,t,n){this.k=e,this.x=t,this.y=n}In.prototype={constructor:In,scale:function(e){return e===1?this:new In(this.k*e,this.x,this.y)},translate:function(e,t){return e===0&t===0?this:new In(this.k,this.x+this.k*e,this.y+this.k*t)},apply:function(e){return[e[0]*this.k+this.x,e[1]*this.k+this.y]},applyX:function(e){return e*this.k+this.x},applyY:function(e){return e*this.k+this.y},invert:function(e){return[(e[0]-this.x)/this.k,(e[1]-this.y)/this.k]},invertX:function(e){return(e-this.x)/this.k},invertY:function(e){return(e-this.y)/this.k},rescaleX:function(e){return e.copy().domain(e.range().map(this.invertX,this).map(e.invert,e))},rescaleY:function(e){return e.copy().domain(e.range().map(this.invertY,this).map(e.invert,e))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Pi=new In(1,0,0);du.prototype=In.prototype;function du(e){for(;!e.__zoom;)if(!(e=e.parentNode))return Pi;return e.__zoom}function Fs(e){e.stopImmediatePropagation()}function wo(e){e.preventDefault(),e.stopImmediatePropagation()}function Yv(e){return(!e.ctrlKey||e.type==="wheel")&&!e.button}function Zv(){var e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,e.hasAttribute("viewBox")?(e=e.viewBox.baseVal,[[e.x,e.y],[e.x+e.width,e.y+e.height]]):[[0,0],[e.width.baseVal.value,e.height.baseVal.value]]):[[0,0],[e.clientWidth,e.clientHeight]]}function fu(){return this.__zoom||Pi}function Xv(e){return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*(e.ctrlKey?10:1)}function Fv(){return navigator.maxTouchPoints||"ontouchstart"in this}function Wv(e,t,n){var r=e.invertX(t[0][0])-n[0][0],o=e.invertX(t[1][0])-n[1][0],i=e.invertY(t[0][1])-n[0][1],s=e.invertY(t[1][1])-n[1][1];return e.translate(o>r?(r+o)/2:Math.min(0,r)||Math.max(0,o),s>i?(i+s)/2:Math.min(0,i)||Math.max(0,s))}function gu(){var e=Yv,t=Zv,n=Wv,r=Xv,o=Fv,i=[0,1/0],s=[[-1/0,-1/0],[1/0,1/0]],a=250,l=Nh,u=ui("start","zoom","end"),c,f,d,g=500,p=150,x=0,C=10;function $(S){S.property("__zoom",fu).on("wheel.zoom",T,{passive:!1}).on("mousedown.zoom",D).on("dblclick.zoom",V).filter(o).on("touchstart.zoom",A).on("touchmove.zoom",O).on("touchend.zoom touchcancel.zoom",R).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}$.transform=function(S,M,k,P){var H=S.selection?S.selection():S;H.property("__zoom",fu),S!==H?b(S,M,k,P):H.interrupt().each(function(){N(this,arguments).event(P).start().zoom(null,typeof M=="function"?M.apply(this,arguments):M).end()})},$.scaleBy=function(S,M,k,P){$.scaleTo(S,function(){var H=this.__zoom.k,I=typeof M=="function"?M.apply(this,arguments):M;return H*I},k,P)},$.scaleTo=function(S,M,k,P){$.transform(S,function(){var H=t.apply(this,arguments),I=this.__zoom,B=k==null?v(H):typeof k=="function"?k.apply(this,arguments):k,F=I.invert(B),K=typeof M=="function"?M.apply(this,arguments):M;return n(_(m(I,K),B,F),H,s)},k,P)},$.translateBy=function(S,M,k,P){$.transform(S,function(){return n(this.__zoom.translate(typeof M=="function"?M.apply(this,arguments):M,typeof k=="function"?k.apply(this,arguments):k),t.apply(this,arguments),s)},null,P)},$.translateTo=function(S,M,k,P,H){$.transform(S,function(){var I=t.apply(this,arguments),B=this.__zoom,F=P==null?v(I):typeof P=="function"?P.apply(this,arguments):P;return n(Pi.translate(F[0],F[1]).scale(B.k).translate(typeof M=="function"?-M.apply(this,arguments):-M,typeof k=="function"?-k.apply(this,arguments):-k),I,s)},P,H)};function m(S,M){return M=Math.max(i[0],Math.min(i[1],M)),M===S.k?S:new In(M,S.x,S.y)}function _(S,M,k){var P=M[0]-k[0]*S.k,H=M[1]-k[1]*S.k;return P===S.x&&H===S.y?S:new In(S.k,P,H)}function v(S){return[(+S[0][0]+ +S[1][0])/2,(+S[0][1]+ +S[1][1])/2]}function b(S,M,k,P){S.on("start.zoom",function(){N(this,arguments).event(P).start()}).on("interrupt.zoom end.zoom",function(){N(this,arguments).event(P).end()}).tween("zoom",function(){var H=this,I=arguments,B=N(H,I).event(P),F=t.apply(H,I),K=k==null?v(F):typeof k=="function"?k.apply(H,I):k,se=Math.max(F[1][0]-F[0][0],F[1][1]-F[0][1]),ee=H.__zoom,W=typeof M=="function"?M.apply(H,I):M,fe=l(ee.invert(K).concat(se/ee.k),W.invert(K).concat(se/W.k));return function(me){if(me===1)me=W;else{var Ce=fe(me),he=se/Ce[2];me=new In(he,K[0]-Ce[0]*he,K[1]-Ce[1]*he)}B.zoom(null,me)}})}function N(S,M,k){return!k&&S.__zooming||new E(S,M)}function E(S,M){this.that=S,this.args=M,this.active=0,this.sourceEvent=null,this.extent=t.apply(S,M),this.taps=0}E.prototype={event:function(S){return S&&(this.sourceEvent=S),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(S,M){return this.mouse&&S!=="mouse"&&(this.mouse[1]=M.invert(this.mouse[0])),this.touch0&&S!=="touch"&&(this.touch0[1]=M.invert(this.touch0[0])),this.touch1&&S!=="touch"&&(this.touch1[1]=M.invert(this.touch1[0])),this.that.__zoom=M,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(S){var M=Ut(this.that).datum();u.call(S,this.that,new Bv(S,{sourceEvent:this.sourceEvent,target:$,transform:this.that.__zoom,dispatch:u}),M)}};function T(S,...M){if(!e.apply(this,arguments))return;var k=N(this,M).event(S),P=this.__zoom,H=Math.max(i[0],Math.min(i[1],P.k*Math.pow(2,r.apply(this,arguments)))),I=on(S);if(k.wheel)(k.mouse[0][0]!==I[0]||k.mouse[0][1]!==I[1])&&(k.mouse[1]=P.invert(k.mouse[0]=I)),clearTimeout(k.wheel);else{if(P.k===H)return;k.mouse=[I,P.invert(I)],Ei(this),k.start()}wo(S),k.wheel=setTimeout(B,p),k.zoom("mouse",n(_(m(P,H),k.mouse[0],k.mouse[1]),k.extent,s));function B(){k.wheel=null,k.end()}}function D(S,...M){if(d||!e.apply(this,arguments))return;var k=S.currentTarget,P=N(this,M,!0).event(S),H=Ut(S.view).on("mousemove.zoom",K,!0).on("mouseup.zoom",se,!0),I=on(S,k),B=S.clientX,F=S.clientY;Al(S.view),Fs(S),P.mouse=[I,this.__zoom.invert(I)],Ei(this),P.start();function K(ee){if(wo(ee),!P.moved){var W=ee.clientX-B,fe=ee.clientY-F;P.moved=W*W+fe*fe>x}P.event(ee).zoom("mouse",n(_(P.that.__zoom,P.mouse[0]=on(ee,k),P.mouse[1]),P.extent,s))}function se(ee){H.on("mousemove.zoom mouseup.zoom",null),Ll(ee.view,P.moved),wo(ee),P.event(ee).end()}}function V(S,...M){if(e.apply(this,arguments)){var k=this.__zoom,P=on(S.changedTouches?S.changedTouches[0]:S,this),H=k.invert(P),I=k.k*(S.shiftKey?.5:2),B=n(_(m(k,I),P,H),t.apply(this,M),s);wo(S),a>0?Ut(this).transition().duration(a).call(b,B,P,S):Ut(this).call($.transform,B,P,S)}}function A(S,...M){if(e.apply(this,arguments)){var k=S.touches,P=k.length,H=N(this,M,S.changedTouches.length===P).event(S),I,B,F,K;for(Fs(S),B=0;B"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001",error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:e=>`Node type "${e}" not found. Using fallback type "default".`,error004:()=>"The React Flow parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:e=>`The old edge with id=${e} does not exist.`,error009:e=>`Marker type "${e}" doesn't exist.`,error008:(e,{id:t,sourceHandle:n,targetHandle:r})=>`Couldn't create edge for ${e} handle id: "${e==="source"?n:r}", edge id: ${t}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:e=>`Edge type "${e}" not found. Using fallback type "default".`,error012:e=>`Node with id "${e}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(e="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${e}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs."},Ni=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]];var hr;(function(e){e.Strict="strict",e.Loose="loose"})(hr||(hr={}));var Jn;(function(e){e.Free="free",e.Vertical="vertical",e.Horizontal="horizontal"})(Jn||(Jn={}));var Ti;(function(e){e.Partial="partial",e.Full="full"})(Ti||(Ti={}));const Ws={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null};var Ar;(function(e){e.Bezier="default",e.Straight="straight",e.Step="step",e.SmoothStep="smoothstep",e.SimpleBezier="simplebezier"})(Ar||(Ar={}));var _o;(function(e){e.Arrow="arrow",e.ArrowClosed="arrowclosed"})(_o||(_o={}));var $e;(function(e){e.Left="left",e.Top="top",e.Right="right",e.Bottom="bottom"})($e||($e={}));const hu={[$e.Left]:$e.Right,[$e.Right]:$e.Left,[$e.Top]:$e.Bottom,[$e.Bottom]:$e.Top};function Kv(e,t){if(!e&&!t)return!0;if(!e||!t||e.size!==t.size)return!1;if(!e.size&&!t.size)return!0;for(const n of e.keys())if(!t.has(n))return!1;return!0}function vu(e,t,n){if(!n)return;const r=[];e.forEach((o,i)=>{t!=null&&t.has(i)||r.push(o)}),r.length&&n(r)}function qv(e){return e===null?null:e?"valid":"invalid"}const Gv=e=>"id"in e&&"source"in e&&"target"in e,Uv=e=>"id"in e&&"position"in e&&!("source"in e)&&!("target"in e),Ks=e=>"id"in e&&"internals"in e&&!("source"in e)&&!("target"in e),xo=(e,t=[0,0])=>{const{width:n,height:r}=Qn(e),o=e.origin??t,i=n*o[0],s=r*o[1];return{x:e.position.x-i,y:e.position.y-s}},jv=(e,t={nodeOrigin:[0,0],nodeLookup:void 0})=>{if(e.length===0)return{x:0,y:0,width:0,height:0};const n=e.reduce((r,o)=>{const i=typeof o=="string";let s=!t.nodeLookup&&!i?o:void 0;t.nodeLookup&&(s=i?t.nodeLookup.get(o):Ks(o)?o:t.nodeLookup.get(o.id));const a=s?Vi(s,t.nodeOrigin):{x:0,y:0,x2:0,y2:0};return Mi(r,a)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return Hi(n)},bo=(e,t={})=>{if(e.size===0)return{x:0,y:0,width:0,height:0};let n={x:1/0,y:1/0,x2:-1/0,y2:-1/0};return e.forEach(r=>{if(t.filter===void 0||t.filter(r)){const o=Vi(r);n=Mi(n,o)}}),Hi(n)},pu=(e,t,[n,r,o]=[0,0,1],i=!1,s=!1)=>{const a={...ko(t,[n,r,o]),width:t.width/o,height:t.height/o},l=[];for(const u of e.values()){const{measured:c,selectable:f=!0,hidden:d=!1}=u;if(s&&!f||d)continue;const g=c.width??u.width??u.initialWidth??null,p=c.height??u.height??u.initialHeight??null,x=Co(a,Or(u)),C=(g??0)*(p??0),$=i&&x>0;(!u.internals.handleBounds||$||x>=C||u.dragging)&&l.push(u)}return l},qs=(e,t)=>{const n=new Set;return e.forEach(r=>{n.add(r.id)}),t.filter(r=>n.has(r.source)||n.has(r.target))};function mu(e,t){const n=new Map,r=t!=null&&t.nodes?new Set(t.nodes.map(o=>o.id)):null;return e.forEach(o=>{o.measured.width&&o.measured.height&&((t==null?void 0:t.includeHiddenNodes)||!o.hidden)&&(!r||r.has(o.id))&&n.set(o.id,o)}),n}async function yu({nodes:e,width:t,height:n,panZoom:r,minZoom:o,maxZoom:i},s){if(e.size===0)return Promise.resolve(!1);const a=bo(e),l=js(a,t,n,(s==null?void 0:s.minZoom)??o,(s==null?void 0:s.maxZoom)??i,(s==null?void 0:s.padding)??.1);return await r.setViewport(l,{duration:s==null?void 0:s.duration}),Promise.resolve(!0)}function Jv({nodeId:e,nextPosition:t,nodeLookup:n,nodeOrigin:r=[0,0],nodeExtent:o,onError:i}){const s=n.get(e),a=s.parentId?n.get(s.parentId):void 0,{x:l,y:u}=a?a.internals.positionAbsolute:{x:0,y:0},c=s.origin??r;let f=o;if(s.extent==="parent"&&!s.expandParent)if(!a)i==null||i("005",Dr.error005());else{const g=a.measured.width,p=a.measured.height;g&&p&&(f=[[l,u],[l+g,u+p]])}else a&&Ir(s.extent)&&(f=[[s.extent[0][0]+l,s.extent[0][1]+u],[s.extent[1][0]+l,s.extent[1][1]+u]]);const d=Ir(f)?vr(t,f,s.measured):t;return(s.measured.width===void 0||s.measured.height===void 0)&&(i==null||i("015",Dr.error015())),{position:{x:d.x-l+(s.measured.width??0)*c[0],y:d.y-u+(s.measured.height??0)*c[1]},positionAbsolute:d}}async function wu({nodesToRemove:e=[],edgesToRemove:t=[],nodes:n,edges:r,onBeforeDelete:o}){const i=new Set(e.map(d=>d.id)),s=[];for(const d of n){if(d.deletable===!1)continue;const g=i.has(d.id),p=!g&&d.parentId&&s.find(x=>x.id===d.parentId);(g||p)&&s.push(d)}const a=new Set(t.map(d=>d.id)),l=r.filter(d=>d.deletable!==!1),c=qs(s,l);for(const d of l)a.has(d.id)&&!c.find(p=>p.id===d.id)&&c.push(d);if(!o)return{edges:c,nodes:s};const f=await o({nodes:s,edges:c});return typeof f=="boolean"?f?{edges:c,nodes:s}:{edges:[],nodes:[]}:f}const Lr=(e,t=0,n=1)=>Math.min(Math.max(e,t),n),vr=(e={x:0,y:0},t,n)=>({x:Lr(e.x,t[0][0],t[1][0]-((n==null?void 0:n.width)??0)),y:Lr(e.y,t[0][1],t[1][1]-((n==null?void 0:n.height)??0))});function _u(e,t,n){const{width:r,height:o}=Qn(n),{x:i,y:s}=n.internals.positionAbsolute;return vr(e,[[i,s],[i+r,s+o]],t)}const xu=(e,t,n)=>en?-Lr(Math.abs(e-n),1,t)/t:0,bu=(e,t,n=15,r=40)=>{const o=xu(e.x,r,t.width-r)*n,i=xu(e.y,r,t.height-r)*n;return[o,i]},Mi=(e,t)=>({x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),x2:Math.max(e.x2,t.x2),y2:Math.max(e.y2,t.y2)}),Gs=({x:e,y:t,width:n,height:r})=>({x:e,y:t,x2:e+n,y2:t+r}),Hi=({x:e,y:t,x2:n,y2:r})=>({x:e,y:t,width:n-e,height:r-t}),Or=(e,t=[0,0])=>{var o,i;const{x:n,y:r}=Ks(e)?e.internals.positionAbsolute:xo(e,t);return{x:n,y:r,width:((o=e.measured)==null?void 0:o.width)??e.width??e.initialWidth??0,height:((i=e.measured)==null?void 0:i.height)??e.height??e.initialHeight??0}},Vi=(e,t=[0,0])=>{var o,i;const{x:n,y:r}=Ks(e)?e.internals.positionAbsolute:xo(e,t);return{x:n,y:r,x2:n+(((o=e.measured)==null?void 0:o.width)??e.width??e.initialWidth??0),y2:r+(((i=e.measured)==null?void 0:i.height)??e.height??e.initialHeight??0)}},Cu=(e,t)=>Hi(Mi(Gs(e),Gs(t))),Co=(e,t)=>{const n=Math.max(0,Math.min(e.x+e.width,t.x+t.width)-Math.max(e.x,t.x)),r=Math.max(0,Math.min(e.y+e.height,t.y+t.height)-Math.max(e.y,t.y));return Math.ceil(n*r)},ku=e=>zn(e.width)&&zn(e.height)&&zn(e.x)&&zn(e.y),zn=e=>!isNaN(e)&&isFinite(e),Qv=(e,t)=>{},Us=(e,t=[1,1])=>({x:t[0]*Math.round(e.x/t[0]),y:t[1]*Math.round(e.y/t[1])}),ko=({x:e,y:t},[n,r,o],i=!1,s=[1,1])=>{const a={x:(e-n)/o,y:(t-r)/o};return i?Us(a,s):a},$u=({x:e,y:t},[n,r,o])=>({x:e*o+n,y:t*o+r}),js=(e,t,n,r,o,i)=>{const s=t/(e.width*(1+i)),a=n/(e.height*(1+i)),l=Math.min(s,a),u=Lr(l,r,o),c=e.x+e.width/2,f=e.y+e.height/2,d=t/2-c*u,g=n/2-f*u;return{x:d,y:g,zoom:u}},Di=()=>{var e;return typeof navigator<"u"&&((e=navigator==null?void 0:navigator.userAgent)==null?void 0:e.indexOf("Mac"))>=0};function Ir(e){return e!==void 0&&e!=="parent"}function Qn(e){var t,n;return{width:((t=e.measured)==null?void 0:t.width)??e.width??e.initialWidth??0,height:((n=e.measured)==null?void 0:n.height)??e.height??e.initialHeight??0}}function Eu(e){var t,n;return(((t=e.measured)==null?void 0:t.width)??e.width??e.initialWidth)!==void 0&&(((n=e.measured)==null?void 0:n.height)??e.height??e.initialHeight)!==void 0}function e0(e,t={width:0,height:0},n,r,o){const i={...e},s=r.get(n);if(s){const a=s.origin||o;i.x+=s.internals.positionAbsolute.x-(t.width??0)*a[0],i.y+=s.internals.positionAbsolute.y-(t.height??0)*a[1]}return i}function Js(e,{snapGrid:t=[0,0],snapToGrid:n=!1,transform:r,containerBounds:o}){const{x:i,y:s}=Rn(e),a=ko({x:i-((o==null?void 0:o.left)??0),y:s-((o==null?void 0:o.top)??0)},r),{x:l,y:u}=n?Us(a,t):a;return{xSnapped:l,ySnapped:u,...a}}const Qs=e=>({width:e.offsetWidth,height:e.offsetHeight}),t0=e=>{var t;return((t=e==null?void 0:e.getRootNode)==null?void 0:t.call(e))||(window==null?void 0:window.document)},n0=["INPUT","SELECT","TEXTAREA"];function r0(e){var r,o;const t=((o=(r=e.composedPath)==null?void 0:r.call(e))==null?void 0:o[0])||e.target;return(t==null?void 0:t.nodeType)!==1?!1:n0.includes(t.nodeName)||t.hasAttribute("contenteditable")||!!t.closest(".nokey")}const Su=e=>"clientX"in e,Rn=(e,t)=>{var i,s;const n=Su(e),r=n?e.clientX:(i=e.touches)==null?void 0:i[0].clientX,o=n?e.clientY:(s=e.touches)==null?void 0:s[0].clientY;return{x:r-((t==null?void 0:t.left)??0),y:o-((t==null?void 0:t.top)??0)}},Pu=(e,t,n,r,o)=>{const i=t.querySelectorAll(`.${e}`);return!i||!i.length?null:Array.from(i).map(s=>{const a=s.getBoundingClientRect();return{id:s.getAttribute("data-handleid"),type:e,nodeId:o,position:s.getAttribute("data-handlepos"),x:(a.left-n.left)/r,y:(a.top-n.top)/r,...Qs(s)}})};function o0({sourceX:e,sourceY:t,targetX:n,targetY:r,sourceControlX:o,sourceControlY:i,targetControlX:s,targetControlY:a}){const l=e*.125+o*.375+s*.375+n*.125,u=t*.125+i*.375+a*.375+r*.125,c=Math.abs(l-e),f=Math.abs(u-t);return[l,u,c,f]}function Ai(e,t){return e>=0?.5*e:t*25*Math.sqrt(-e)}function Nu({pos:e,x1:t,y1:n,x2:r,y2:o,c:i}){switch(e){case $e.Left:return[t-Ai(t-r,i),n];case $e.Right:return[t+Ai(r-t,i),n];case $e.Top:return[t,n-Ai(n-o,i)];case $e.Bottom:return[t,n+Ai(o-n,i)]}}function Tu({sourceX:e,sourceY:t,sourcePosition:n=$e.Bottom,targetX:r,targetY:o,targetPosition:i=$e.Top,curvature:s=.25}){const[a,l]=Nu({pos:n,x1:e,y1:t,x2:r,y2:o,c:s}),[u,c]=Nu({pos:i,x1:r,y1:o,x2:e,y2:t,c:s}),[f,d,g,p]=o0({sourceX:e,sourceY:t,targetX:r,targetY:o,sourceControlX:a,sourceControlY:l,targetControlX:u,targetControlY:c});return[`M${e},${t} C${a},${l} ${u},${c} ${r},${o}`,f,d,g,p]}function Mu({sourceX:e,sourceY:t,targetX:n,targetY:r}){const o=Math.abs(n-e)/2,i=n0}const a0=({source:e,sourceHandle:t,target:n,targetHandle:r})=>`xy-edge__${e}${t||""}-${n}${r||""}`,l0=(e,t)=>t.some(n=>n.source===e.source&&n.target===e.target&&(n.sourceHandle===e.sourceHandle||!n.sourceHandle&&!e.sourceHandle)&&(n.targetHandle===e.targetHandle||!n.targetHandle&&!e.targetHandle)),u0=(e,t)=>{if(!e.source||!e.target)return t;let n;return Gv(e)?n={...e}:n={...e,id:a0(e)},l0(n,t)?t:(n.sourceHandle===null&&delete n.sourceHandle,n.targetHandle===null&&delete n.targetHandle,t.concat(n))};function ea({sourceX:e,sourceY:t,targetX:n,targetY:r}){const[o,i,s,a]=Mu({sourceX:e,sourceY:t,targetX:n,targetY:r});return[`M ${e},${t}L ${n},${r}`,o,i,s,a]}const Hu={[$e.Left]:{x:-1,y:0},[$e.Right]:{x:1,y:0},[$e.Top]:{x:0,y:-1},[$e.Bottom]:{x:0,y:1}},c0=({source:e,sourcePosition:t=$e.Bottom,target:n})=>t===$e.Left||t===$e.Right?e.xMath.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));function d0({source:e,sourcePosition:t=$e.Bottom,target:n,targetPosition:r=$e.Top,center:o,offset:i}){const s=Hu[t],a=Hu[r],l={x:e.x+s.x*i,y:e.y+s.y*i},u={x:n.x+a.x*i,y:n.y+a.y*i},c=c0({source:l,sourcePosition:t,target:u}),f=c.x!==0?"x":"y",d=c[f];let g=[],p,x;const C={x:0,y:0},$={x:0,y:0},[m,_,v,b]=Mu({sourceX:e.x,sourceY:e.y,targetX:n.x,targetY:n.y});if(s[f]*a[f]===-1){p=o.x??m,x=o.y??_;const E=[{x:p,y:l.y},{x:p,y:u.y}],T=[{x:l.x,y:x},{x:u.x,y:x}];s[f]===d?g=f==="x"?E:T:g=f==="x"?T:E}else{const E=[{x:l.x,y:u.y}],T=[{x:u.x,y:l.y}];if(f==="x"?g=s.x===d?T:E:g=s.y===d?E:T,t===r){const R=Math.abs(e[f]-n[f]);if(R<=i){const S=Math.min(i-1,i-R);s[f]===d?C[f]=(l[f]>e[f]?-1:1)*S:$[f]=(u[f]>n[f]?-1:1)*S}}if(t!==r){const R=f==="x"?"y":"x",S=s[f]===a[R],M=l[R]>u[R],k=l[R]=O?(p=(D.x+V.x)/2,x=g[0].y):(p=g[0].x,x=(D.y+V.y)/2)}return[[e,{x:l.x+C.x,y:l.y+C.y},...g,{x:u.x+$.x,y:u.y+$.y},n],p,x,v,b]}function f0(e,t,n,r){const o=Math.min(Vu(e,t)/2,Vu(t,n)/2,r),{x:i,y:s}=t;if(e.x===i&&i===n.x||e.y===s&&s===n.y)return`L${i} ${s}`;if(e.y===s){const u=e.x{let _="";return m>0&&mn.id===t):e[0])||null}function ta(e,t){return e?typeof e=="string"?e:`${t?`${t}__`:""}${Object.keys(e).sort().map(r=>`${r}=${e[r]}`).join("&")}`:""}function h0(e,{id:t,defaultColor:n,defaultMarkerStart:r,defaultMarkerEnd:o}){const i=new Set;return e.reduce((s,a)=>([a.markerStart||r,a.markerEnd||o].forEach(l=>{if(l&&typeof l=="object"){const u=ta(l,t);i.has(u)||(s.push({id:u,color:l.color||n,...l}),i.add(u))}}),s),[]).sort((s,a)=>s.id.localeCompare(a.id))}function v0(e,t,n,r,o){let i=.5;o==="start"?i=0:o==="end"&&(i=1);let s=[(e.x+e.width*i)*t.zoom+t.x,e.y*t.zoom+t.y-r],a=[-100*i,-100];switch(n){case $e.Right:s=[(e.x+e.width)*t.zoom+t.x+r,(e.y+e.height*i)*t.zoom+t.y],a=[0,-100*i];break;case $e.Bottom:s[1]=(e.y+e.height)*t.zoom+t.y+r,a[1]=0;break;case $e.Left:s=[e.x*t.zoom+t.x-r,(e.y+e.height*i)*t.zoom+t.y],a=[-100,-100*i];break}return`translate(${s[0]}px, ${s[1]}px) translate(${a[0]}%, ${a[1]}%)`}const na={nodeOrigin:[0,0],nodeExtent:Ni,elevateNodesOnSelect:!0,defaults:{}},p0={...na,checkEquality:!0};function ra(e,t){const n={...e};for(const r in t)t[r]!==void 0&&(n[r]=t[r]);return n}function m0(e,t,n){const r=ra(na,n);for(const o of e.values())if(o.parentId)oa(o,e,t,r);else{const i=xo(o,r.nodeOrigin),s=Ir(o.extent)?o.extent:r.nodeExtent,a=vr(i,s,Qn(o));o.internals.positionAbsolute=a}}function Ou(e,t,n,r){var a,l;const o=ra(p0,r),i=new Map(t),s=o!=null&&o.elevateNodesOnSelect?1e3:0;t.clear(),n.clear();for(const u of e){let c=i.get(u.id);if(o.checkEquality&&u===(c==null?void 0:c.internals.userNode))t.set(u.id,c);else{const f=xo(u,o.nodeOrigin),d=Ir(u.extent)?u.extent:o.nodeExtent,g=vr(f,d,Qn(u));c={...o.defaults,...u,measured:{width:(a=u.measured)==null?void 0:a.width,height:(l=u.measured)==null?void 0:l.height},internals:{positionAbsolute:g,handleBounds:u.measured?c==null?void 0:c.internals.handleBounds:void 0,z:Iu(u,s),userNode:u}},t.set(u.id,c)}u.parentId&&oa(c,t,n,r)}}function y0(e,t){if(!e.parentId)return;const n=t.get(e.parentId);n?n.set(e.id,e):t.set(e.parentId,new Map([[e.id,e]]))}function oa(e,t,n,r){const{elevateNodesOnSelect:o,nodeOrigin:i,nodeExtent:s}=ra(na,r),a=e.parentId,l=t.get(a);if(!l){console.warn(`Parent node ${a} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}y0(e,n);const u=o?1e3:0,{x:c,y:f,z:d}=w0(e,l,i,s,u),{positionAbsolute:g}=e.internals,p=c!==g.x||f!==g.y;(p||d!==e.internals.z)&&t.set(e.id,{...e,internals:{...e.internals,positionAbsolute:p?{x:c,y:f}:g,z:d}})}function Iu(e,t){return(zn(e.zIndex)?e.zIndex:0)+(e.selected?t:0)}function w0(e,t,n,r,o){const{x:i,y:s}=t.internals.positionAbsolute,a=Qn(e),l=xo(e,n),u=Ir(e.extent)?vr(l,e.extent,a):l;let c=vr({x:i+u.x,y:s+u.y},r,a);e.extent==="parent"&&(c=_u(c,a,t));const f=Iu(e,o),d=t.internals.z??0;return{x:c.x,y:c.y,z:d>f?d:f}}function _0(e,t,n,r=[0,0]){var s;const o=[],i=new Map;for(const a of e){const l=t.get(a.parentId);if(!l)continue;const u=((s=i.get(a.parentId))==null?void 0:s.expandedRect)??Or(l),c=Cu(u,a.rect);i.set(a.parentId,{expandedRect:c,parent:l})}return i.size>0&&i.forEach(({expandedRect:a,parent:l},u)=>{var _;const c=l.internals.positionAbsolute,f=Qn(l),d=l.origin??r,g=a.x0||p>0||$||m)&&(o.push({id:u,type:"position",position:{x:l.position.x-g+$,y:l.position.y-p+m}}),(_=n.get(u))==null||_.forEach(v=>{e.some(b=>b.id===v.id)||o.push({id:v.id,type:"position",position:{x:v.position.x+g,y:v.position.y+p}})})),(f.width0){const d=_0(f,t,n,o);l.push(...d)}return{changes:l,updatedInternals:a}}async function b0({delta:e,panZoom:t,transform:n,translateExtent:r,width:o,height:i}){if(!t||!e.x&&!e.y)return Promise.resolve(!1);const s=await t.setViewportConstrained({x:n[0]+e.x,y:n[1]+e.y,zoom:n[2]},[[0,0],[o,i]],r),a=!!s&&(s.x!==n[0]||s.y!==n[1]||s.k!==n[2]);return Promise.resolve(a)}function zu(e,t,n,r,o,i){let s=o;const a=r.get(s)||new Map;r.set(s,a.set(n,t)),s=`${o}-${e}`;const l=r.get(s)||new Map;if(r.set(s,l.set(n,t)),i){s=`${o}-${e}-${i}`;const u=r.get(s)||new Map;r.set(s,u.set(n,t))}}function Ru(e,t,n){e.clear(),t.clear();for(const r of n){const{source:o,target:i,sourceHandle:s=null,targetHandle:a=null}=r,l={edgeId:r.id,source:o,target:i,sourceHandle:s,targetHandle:a},u=`${o}-${s}--${i}-${a}`,c=`${i}-${a}--${o}-${s}`;zu("source",l,c,e,o,s),zu("target",l,u,e,i,a),t.set(r.id,r)}}function C0(e,t){if(e===null||t===null)return!1;const n=Array.isArray(e)?e:[e],r=Array.isArray(t)?t:[t];if(n.length!==r.length)return!1;for(let o=0;o"u")){const a=e.get(i);a&&o.set(i,{id:i,position:a.position||{x:0,y:0},distance:{x:n.x-a.internals.positionAbsolute.x,y:n.y-a.internals.positionAbsolute.y},extent:a.extent,parentId:a.parentId,origin:a.origin,expandParent:a.expandParent,internals:{positionAbsolute:a.internals.positionAbsolute||{x:0,y:0}},measured:{width:a.measured.width??0,height:a.measured.height??0}})}return o}function ia({nodeId:e,dragItems:t,nodeLookup:n,dragging:r=!0}){var s,a,l;const o=[];for(const[u,c]of t){const f=(s=n.get(u))==null?void 0:s.internals.userNode;f&&o.push({...f,position:c.position,dragging:r})}if(!e)return[o[0],o];const i=(a=n.get(e))==null?void 0:a.internals.userNode;return[i?{...i,position:((l=t.get(e))==null?void 0:l.position)||i.position,dragging:r}:o[0],o]}function $0({onNodeMouseDown:e,getStoreItems:t,onDragStart:n,onDrag:r,onDragStop:o}){let i={x:null,y:null},s=0,a=new Map,l=!1,u={x:0,y:0},c=null,f=!1,d=null,g=!1;function p({noDragClassName:C,handleSelector:$,domNode:m,isSelectable:_,nodeId:v,nodeClickDistance:b=0}){d=Ut(m);function N({x:V,y:A},O){const{nodeLookup:R,nodeExtent:S,snapGrid:M,snapToGrid:k,nodeOrigin:P,onNodeDrag:H,onSelectionDrag:I,onError:B,updateNodePositions:F}=t();i={x:V,y:A};let K=!1,se={x:0,y:0,x2:0,y2:0};if(a.size>1&&S){const ee=bo(a);se=Gs(ee)}for(const[ee,W]of a){if(!R.has(ee))continue;let fe={x:V-W.distance.x,y:A-W.distance.y};k&&(fe=Us(fe,M));let me=[[S[0][0],S[0][1]],[S[1][0],S[1][1]]];if(a.size>1&&S&&!W.extent){const{positionAbsolute:ze}=W.internals,G=ze.x-se.x+S[0][0],ae=ze.x+W.measured.width-se.x2+S[1][0],Me=ze.y-se.y+S[0][1],Le=ze.y+W.measured.height-se.y2+S[1][1];me=[[G,Me],[ae,Le]]}const{position:Ce,positionAbsolute:he}=Jv({nodeId:ee,nextPosition:fe,nodeLookup:R,nodeExtent:me,nodeOrigin:P,onError:B});K=K||W.position.x!==Ce.x||W.position.y!==Ce.y,W.position=Ce,W.internals.positionAbsolute=he}if(K&&(F(a,!0),O&&(r||H||!v&&I))){const[ee,W]=ia({nodeId:v,dragItems:a,nodeLookup:R});r==null||r(O,a,ee,W),H==null||H(O,ee,W),v||I==null||I(O,W)}}async function E(){if(!c)return;const{transform:V,panBy:A,autoPanSpeed:O,autoPanOnNodeDrag:R}=t();if(!R){l=!1,cancelAnimationFrame(s);return}const[S,M]=bu(u,c,O);(S!==0||M!==0)&&(i.x=(i.x??0)-S/V[2],i.y=(i.y??0)-M/V[2],await A({x:S,y:M})&&N(i,null)),s=requestAnimationFrame(E)}function T(V){var K;const{nodeLookup:A,multiSelectionActive:O,nodesDraggable:R,transform:S,snapGrid:M,snapToGrid:k,selectNodesOnDrag:P,onNodeDragStart:H,onSelectionDragStart:I,unselectNodesAndEdges:B}=t();f=!0,(!P||!_)&&!O&&v&&((K=A.get(v))!=null&&K.selected||B()),_&&P&&v&&(e==null||e(v));const F=Js(V.sourceEvent,{transform:S,snapGrid:M,snapToGrid:k,containerBounds:c});if(i=F,a=k0(A,R,F,v),a.size>0&&(n||H||!v&&I)){const[se,ee]=ia({nodeId:v,dragItems:a,nodeLookup:A});n==null||n(V.sourceEvent,a,se,ee),H==null||H(V.sourceEvent,se,ee),v||I==null||I(V.sourceEvent,ee)}}const D=rh().clickDistance(b).on("start",V=>{const{domNode:A,nodeDragThreshold:O,transform:R,snapGrid:S,snapToGrid:M}=t();c=(A==null?void 0:A.getBoundingClientRect())||null,g=!1,O===0&&T(V),i=Js(V.sourceEvent,{transform:R,snapGrid:S,snapToGrid:M,containerBounds:c}),u=Rn(V.sourceEvent,c)}).on("drag",V=>{const{autoPanOnNodeDrag:A,transform:O,snapGrid:R,snapToGrid:S,nodeDragThreshold:M,nodeLookup:k}=t(),P=Js(V.sourceEvent,{transform:O,snapGrid:R,snapToGrid:S,containerBounds:c});if((V.sourceEvent.type==="touchmove"&&V.sourceEvent.touches.length>1||v&&!k.has(v))&&(g=!0),!g){if(!l&&A&&f&&(l=!0,E()),!f){const H=P.xSnapped-(i.x??0),I=P.ySnapped-(i.y??0);Math.sqrt(H*H+I*I)>M&&T(V)}(i.x!==P.xSnapped||i.y!==P.ySnapped)&&a&&f&&(u=Rn(V.sourceEvent,c),N(P,V.sourceEvent))}}).on("end",V=>{if(!(!f||g)&&(l=!1,f=!1,cancelAnimationFrame(s),a.size>0)){const{nodeLookup:A,updateNodePositions:O,onNodeDragStop:R,onSelectionDragStop:S}=t();if(O(a,!1),o||R||!v&&S){const[M,k]=ia({nodeId:v,dragItems:a,nodeLookup:A,dragging:!1});o==null||o(V.sourceEvent,a,M,k),R==null||R(V.sourceEvent,M,k),v||S==null||S(V.sourceEvent,k)}}}).filter(V=>{const A=V.target;return!V.button&&(!C||!Yu(A,`.${C}`,m))&&(!$||Yu(A,$,m))});d.call(D)}function x(){d==null||d.on(".drag",null)}return{update:p,destroy:x}}function E0(e,t,n){const r=[],o={x:e.x-n,y:e.y-n,width:n*2,height:n*2};for(const i of t.values())Co(o,Or(i))>0&&r.push(i);return r}const S0=250;function P0(e,t,n,r){var a,l;let o=[],i=1/0;const s=E0(e,n,t+S0);for(const u of s){const c=[...((a=u.internals.handleBounds)==null?void 0:a.source)??[],...((l=u.internals.handleBounds)==null?void 0:l.target)??[]];for(const f of c){if(r.nodeId===f.nodeId&&r.type===f.type&&r.id===f.id)continue;const{x:d,y:g}=$o(u,f,f.position,!0),p=Math.sqrt(Math.pow(d-e.x,2)+Math.pow(g-e.y,2));p>t||(p1){const u=r.type==="source"?"target":"source";return o.find(c=>c.type===u)??o[0]}return o[0]}function Zu(e,t,n,r,o,i=!1){var u,c,f;const s=r.get(e);if(!s)return null;const a=o==="strict"?(u=s.internals.handleBounds)==null?void 0:u[t]:[...((c=s.internals.handleBounds)==null?void 0:c.source)??[],...((f=s.internals.handleBounds)==null?void 0:f.target)??[]],l=(n?a==null?void 0:a.find(d=>d.id===n):a==null?void 0:a[0])??null;return l&&i?{...l,...$o(s,l,l.position,!0)}:l}function Xu(e,t){return e||(t!=null&&t.classList.contains("target")?"target":t!=null&&t.classList.contains("source")?"source":null)}function N0(e,t){let n=null;return t?n=!0:e&&!t&&(n=!1),n}const Fu=()=>!0;function T0(e,{connectionMode:t,connectionRadius:n,handleId:r,nodeId:o,edgeUpdaterType:i,isTarget:s,domNode:a,nodeLookup:l,lib:u,autoPanOnConnect:c,flowId:f,panBy:d,cancelConnection:g,onConnectStart:p,onConnect:x,onConnectEnd:C,isValidConnection:$=Fu,onReconnectEnd:m,updateConnection:_,getTransform:v,getFromHandle:b,autoPanSpeed:N}){const E=t0(e.target);let T=0,D;const{x:V,y:A}=Rn(e),O=E==null?void 0:E.elementFromPoint(V,A),R=Xu(i,O),S=a==null?void 0:a.getBoundingClientRect();if(!S||!R)return;const M=Zu(o,R,r,l,t);if(!M)return;let k=Rn(e,S),P=!1,H=null,I=!1,B=null;function F(){if(!c||!S)return;const[he,ze]=bu(k,S,N);d({x:he,y:ze}),T=requestAnimationFrame(F)}const K={...M,nodeId:o,type:R,position:M.position},se=l.get(o),W={inProgress:!0,isValid:null,from:$o(se,K,$e.Left,!0),fromHandle:K,fromPosition:K.position,fromNode:se,to:k,toHandle:null,toPosition:hu[K.position],toNode:null};_(W);let fe=W;p==null||p(e,{nodeId:o,handleId:r,handleType:R});function me(he){if(!b()||!K){Ce(he);return}const ze=v();k=Rn(he,S),D=P0(ko(k,ze,!1,[1,1]),n,l,K),P||(F(),P=!0);const G=Wu(he,{handle:D,connectionMode:t,fromNodeId:o,fromHandleId:r,fromType:s?"target":"source",isValidConnection:$,doc:E,lib:u,flowId:f,nodeLookup:l});B=G.handleDomNode,H=G.connection,I=N0(!!D,G.isValid);const ae={...fe,isValid:I,to:D&&I?$u({x:D.x,y:D.y},ze):k,toHandle:G.toHandle,toPosition:I&&G.toHandle?G.toHandle.position:hu[K.position],toNode:G.toHandle?l.get(G.toHandle.nodeId):null};I&&D&&fe.toHandle&&ae.toHandle&&fe.toHandle.type===ae.toHandle.type&&fe.toHandle.nodeId===ae.toHandle.nodeId&&fe.toHandle.id===ae.toHandle.id&&fe.to.x===ae.to.x&&fe.to.y===ae.to.y||(_(ae),fe=ae)}function Ce(he){(D||B)&&H&&I&&(x==null||x(H));const{inProgress:ze,...G}=fe,ae={...G,toPosition:fe.toHandle?fe.toPosition:null};C==null||C(he,ae),i&&(m==null||m(he,ae)),g(),cancelAnimationFrame(T),P=!1,I=!1,H=null,B=null,E.removeEventListener("mousemove",me),E.removeEventListener("mouseup",Ce),E.removeEventListener("touchmove",me),E.removeEventListener("touchend",Ce)}E.addEventListener("mousemove",me),E.addEventListener("mouseup",Ce),E.addEventListener("touchmove",me),E.addEventListener("touchend",Ce)}function Wu(e,{handle:t,connectionMode:n,fromNodeId:r,fromHandleId:o,fromType:i,doc:s,lib:a,flowId:l,isValidConnection:u=Fu,nodeLookup:c}){const f=i==="target",d=t?s.querySelector(`.${a}-flow__handle[data-id="${l}-${t==null?void 0:t.nodeId}-${t==null?void 0:t.id}-${t==null?void 0:t.type}"]`):null,{x:g,y:p}=Rn(e),x=s.elementFromPoint(g,p),C=x!=null&&x.classList.contains(`${a}-flow__handle`)?x:d,$={handleDomNode:C,isValid:!1,connection:null,toHandle:null};if(C){const m=Xu(void 0,C),_=C.getAttribute("data-nodeid"),v=C.getAttribute("data-handleid"),b=C.classList.contains("connectable"),N=C.classList.contains("connectableend");if(!_||!m)return $;const E={source:f?_:r,sourceHandle:f?v:o,target:f?r:_,targetHandle:f?o:v};$.connection=E;const D=b&&N&&(n===hr.Strict?f&&m==="source"||!f&&m==="target":_!==r||v!==o);$.isValid=D&&u(E),$.toHandle=Zu(_,m,v,c,n,!1)}return $}const M0={onPointerDown:T0,isValid:Wu};function H0({domNode:e,panZoom:t,getTransform:n,getViewScale:r}){const o=Ut(e);function i({translateExtent:a,width:l,height:u,zoomStep:c=10,pannable:f=!0,zoomable:d=!0,inversePan:g=!1}){const p=_=>{const v=n();if(_.sourceEvent.type!=="wheel"||!t)return;const b=-_.sourceEvent.deltaY*(_.sourceEvent.deltaMode===1?.05:_.sourceEvent.deltaMode?1:.002)*c,N=v[2]*Math.pow(2,b);t.scaleTo(N)};let x=[0,0];const C=_=>{(_.sourceEvent.type==="mousedown"||_.sourceEvent.type==="touchstart")&&(x=[_.sourceEvent.clientX??_.sourceEvent.touches[0].clientX,_.sourceEvent.clientY??_.sourceEvent.touches[0].clientY])},$=_=>{const v=n();if(_.sourceEvent.type!=="mousemove"&&_.sourceEvent.type!=="touchmove"||!t)return;const b=[_.sourceEvent.clientX??_.sourceEvent.touches[0].clientX,_.sourceEvent.clientY??_.sourceEvent.touches[0].clientY],N=[b[0]-x[0],b[1]-x[1]];x=b;const E=r()*Math.max(v[2],Math.log(v[2]))*(g?-1:1),T={x:v[0]-N[0]*E,y:v[1]-N[1]*E},D=[[0,0],[l,u]];t.setViewportConstrained({x:T.x,y:T.y,zoom:v[2]},D,a)},m=gu().on("start",C).on("zoom",f?$:null).on("zoom.wheel",d?p:null);o.call(m,{})}function s(){o.on("zoom",null)}return{update:i,destroy:s,pointer:on}}const V0=(e,t)=>e.x!==t.x||e.y!==t.y||e.zoom!==t.k,Oi=e=>({x:e.x,y:e.y,zoom:e.k}),sa=({x:e,y:t,zoom:n})=>Pi.translate(e,t).scale(n),zr=(e,t)=>e.target.closest(`.${t}`),Ku=(e,t)=>t===2&&Array.isArray(e)&&e.includes(2),aa=(e,t=0,n=()=>{})=>{const r=typeof t=="number"&&t>0;return r||n(),r?e.transition().duration(t).on("end",n):e},qu=e=>{const t=e.ctrlKey&&Di()?10:1;return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*t};function D0({zoomPanValues:e,noWheelClassName:t,d3Selection:n,d3Zoom:r,panOnScrollMode:o,panOnScrollSpeed:i,zoomOnPinch:s,onPanZoomStart:a,onPanZoom:l,onPanZoomEnd:u}){return c=>{if(zr(c,t))return!1;c.preventDefault(),c.stopImmediatePropagation();const f=n.property("__zoom").k||1;if(c.ctrlKey&&s){const C=on(c),$=qu(c),m=f*Math.pow(2,$);r.scaleTo(n,m,C,c);return}const d=c.deltaMode===1?20:1;let g=o===Jn.Vertical?0:c.deltaX*d,p=o===Jn.Horizontal?0:c.deltaY*d;!Di()&&c.shiftKey&&o!==Jn.Vertical&&(g=c.deltaY*d,p=0),r.translateBy(n,-(g/f)*i,-(p/f)*i,{internal:!0});const x=Oi(n.property("__zoom"));clearTimeout(e.panScrollTimeout),e.isPanScrolling||(e.isPanScrolling=!0,a==null||a(c,x)),e.isPanScrolling&&(l==null||l(c,x),e.panScrollTimeout=setTimeout(()=>{u==null||u(c,x),e.isPanScrolling=!1},150))}}function A0({noWheelClassName:e,preventScrolling:t,d3ZoomHandler:n}){return function(r,o){if(!t&&r.type==="wheel"&&!r.ctrlKey||zr(r,e))return null;r.preventDefault(),n.call(this,r,o)}}function L0({zoomPanValues:e,onDraggingChange:t,onPanZoomStart:n}){return r=>{var i,s,a;if((i=r.sourceEvent)!=null&&i.internal)return;const o=Oi(r.transform);e.mouseButton=((s=r.sourceEvent)==null?void 0:s.button)||0,e.isZoomingOrPanning=!0,e.prevViewport=o,((a=r.sourceEvent)==null?void 0:a.type)==="mousedown"&&t(!0),n&&(n==null||n(r.sourceEvent,o))}}function O0({zoomPanValues:e,panOnDrag:t,onPaneContextMenu:n,onTransformChange:r,onPanZoom:o}){return i=>{var s,a;e.usedRightMouseButton=!!(n&&Ku(t,e.mouseButton??0)),(s=i.sourceEvent)!=null&&s.sync||r([i.transform.x,i.transform.y,i.transform.k]),o&&!((a=i.sourceEvent)!=null&&a.internal)&&(o==null||o(i.sourceEvent,Oi(i.transform)))}}function I0({zoomPanValues:e,panOnDrag:t,panOnScroll:n,onDraggingChange:r,onPanZoomEnd:o,onPaneContextMenu:i}){return s=>{var a;if(!((a=s.sourceEvent)!=null&&a.internal)&&(e.isZoomingOrPanning=!1,i&&Ku(t,e.mouseButton??0)&&!e.usedRightMouseButton&&s.sourceEvent&&i(s.sourceEvent),e.usedRightMouseButton=!1,r(!1),o&&V0(e.prevViewport,s.transform))){const l=Oi(s.transform);e.prevViewport=l,clearTimeout(e.timerId),e.timerId=setTimeout(()=>{o==null||o(s.sourceEvent,l)},n?150:0)}}}function z0({zoomActivationKeyPressed:e,zoomOnScroll:t,zoomOnPinch:n,panOnDrag:r,panOnScroll:o,zoomOnDoubleClick:i,userSelectionActive:s,noWheelClassName:a,noPanClassName:l,lib:u}){return c=>{var p;const f=e||t,d=n&&c.ctrlKey;if(c.button===1&&c.type==="mousedown"&&(zr(c,`${u}-flow__node`)||zr(c,`${u}-flow__edge`)))return!0;if(!r&&!f&&!o&&!i&&!n||s||zr(c,a)&&c.type==="wheel"||zr(c,l)&&(c.type!=="wheel"||o&&c.type==="wheel"&&!e)||!n&&c.ctrlKey&&c.type==="wheel")return!1;if(!n&&c.type==="touchstart"&&((p=c.touches)==null?void 0:p.length)>1)return c.preventDefault(),!1;if(!f&&!o&&!d&&c.type==="wheel"||!r&&(c.type==="mousedown"||c.type==="touchstart")||Array.isArray(r)&&!r.includes(c.button)&&c.type==="mousedown")return!1;const g=Array.isArray(r)&&r.includes(c.button)||!c.button||c.button<=1;return(!c.ctrlKey||c.type==="wheel")&&g}}function R0({domNode:e,minZoom:t,maxZoom:n,paneClickDistance:r,translateExtent:o,viewport:i,onPanZoom:s,onPanZoomStart:a,onPanZoomEnd:l,onDraggingChange:u}){const c={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},f=e.getBoundingClientRect(),d=gu().clickDistance(!zn(r)||r<0?0:r).scaleExtent([t,n]).translateExtent(o),g=Ut(e).call(d);_({x:i.x,y:i.y,zoom:Lr(i.zoom,t,n)},[[0,0],[f.width,f.height]],o);const p=g.on("wheel.zoom"),x=g.on("dblclick.zoom");d.wheelDelta(qu);function C(O,R){return g?new Promise(S=>{d==null||d.transform(aa(g,R==null?void 0:R.duration,()=>S(!0)),O)}):Promise.resolve(!1)}function $({noWheelClassName:O,noPanClassName:R,onPaneContextMenu:S,userSelectionActive:M,panOnScroll:k,panOnDrag:P,panOnScrollMode:H,panOnScrollSpeed:I,preventScrolling:B,zoomOnPinch:F,zoomOnScroll:K,zoomOnDoubleClick:se,zoomActivationKeyPressed:ee,lib:W,onTransformChange:fe}){M&&!c.isZoomingOrPanning&&m();const Ce=k&&!ee&&!M?D0({zoomPanValues:c,noWheelClassName:O,d3Selection:g,d3Zoom:d,panOnScrollMode:H,panOnScrollSpeed:I,zoomOnPinch:F,onPanZoomStart:a,onPanZoom:s,onPanZoomEnd:l}):A0({noWheelClassName:O,preventScrolling:B,d3ZoomHandler:p});if(g.on("wheel.zoom",Ce,{passive:!1}),!M){const ze=L0({zoomPanValues:c,onDraggingChange:u,onPanZoomStart:a});d.on("start",ze);const G=O0({zoomPanValues:c,panOnDrag:P,onPaneContextMenu:!!S,onPanZoom:s,onTransformChange:fe});d.on("zoom",G);const ae=I0({zoomPanValues:c,panOnDrag:P,panOnScroll:k,onPaneContextMenu:S,onPanZoomEnd:l,onDraggingChange:u});d.on("end",ae)}const he=z0({zoomActivationKeyPressed:ee,panOnDrag:P,zoomOnScroll:K,panOnScroll:k,zoomOnDoubleClick:se,zoomOnPinch:F,userSelectionActive:M,noPanClassName:R,noWheelClassName:O,lib:W});d.filter(he),se?g.on("dblclick.zoom",x):g.on("dblclick.zoom",null)}function m(){d.on("zoom",null)}async function _(O,R,S){const M=sa(O),k=d==null?void 0:d.constrain()(M,R,S);return k&&await C(k),new Promise(P=>P(k))}async function v(O,R){const S=sa(O);return await C(S,R),new Promise(M=>M(S))}function b(O){if(g){const R=sa(O),S=g.property("__zoom");(S.k!==O.zoom||S.x!==O.x||S.y!==O.y)&&(d==null||d.transform(g,R,null,{sync:!0}))}}function N(){const O=g?du(g.node()):{x:0,y:0,k:1};return{x:O.x,y:O.y,zoom:O.k}}function E(O,R){return g?new Promise(S=>{d==null||d.scaleTo(aa(g,R==null?void 0:R.duration,()=>S(!0)),O)}):Promise.resolve(!1)}function T(O,R){return g?new Promise(S=>{d==null||d.scaleBy(aa(g,R==null?void 0:R.duration,()=>S(!0)),O)}):Promise.resolve(!1)}function D(O){d==null||d.scaleExtent(O)}function V(O){d==null||d.translateExtent(O)}function A(O){const R=!zn(O)||O<0?0:O;d==null||d.clickDistance(R)}return{update:$,destroy:m,setViewport:v,setViewportConstrained:_,getViewport:N,scaleTo:E,scaleBy:T,setScaleExtent:D,setTranslateExtent:V,syncViewport:b,setClickDistance:A}}var Gu;(function(e){e.Line="line",e.Handle="handle"})(Gu||(Gu={}));var B0=ne('');function er(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(se,"$connectable",n),i=()=>Q(Ce,"$connectionRadius",n),s=()=>Q(fe,"$domNode",n),a=()=>Q(me,"$nodeLookup",n),l=()=>Q(W,"$connectionMode",n),u=()=>Q(G,"$lib",n),c=()=>Q(Fe,"$autoPanOnConnect",n),f=()=>Q(Ie,"$flowId",n),d=()=>Q(ze,"$isValidConnectionStore",n),g=()=>Q(Me,"$onedgecreate",n),p=()=>Q(oe,"$onConnectAction",n),x=()=>Q(pe,"$onConnectStartAction",n),C=()=>Q(be,"$onConnectEndAction",n),$=()=>Q(he,"$viewport",n),m=()=>Q(ht,"$connection",n),_=()=>Q(Oe,"$edges",n),v=()=>Q(rt,"$connectionLookup",n),b=re(),N=re(),E=re(),T=re(),D=re(),V=re(),A=re(),O=re();let R=w(t,"id",12,void 0),S=w(t,"type",12,"source"),M=w(t,"position",28,()=>$e.Top),k=w(t,"style",12,void 0),P=w(t,"isValidConnection",12,void 0),H=w(t,"onconnect",12,void 0),I=w(t,"ondisconnect",12,void 0),B=w(t,"isConnectable",12,void 0),F=w(t,"class",12,void 0);const K=ur("svelteflow__node_id"),se=ur("svelteflow__node_connectable"),ee=Ue(),{connectionMode:W,domNode:fe,nodeLookup:me,connectionRadius:Ce,viewport:he,isValidConnection:ze,lib:G,addEdge:ae,onedgecreate:Me,panBy:Le,cancelConnection:Xe,updateConnection:te,autoPanOnConnect:Fe,edges:Oe,connectionLookup:rt,onconnect:oe,onconnectstart:pe,onconnectend:be,flowId:Ie,connection:ht}=ee;function dt(Te){const st=Su(Te);(st&&Te.button===0||!st)&&M0.onPointerDown(Te,{handleId:h(E),nodeId:K,isTarget:h(b),connectionRadius:i(),domNode:s(),nodeLookup:a(),connectionMode:l(),lib:u(),autoPanOnConnect:c(),flowId:f(),isValidConnection:P()??d(),updateConnection:te,cancelConnection:Xe,panBy:Le,onConnect:ye=>{var ct;const lt=g()?g()(ye):ye;lt&&(ae(lt),(ct=p())==null||ct(ye))},onConnectStart:(ye,lt)=>{var ct;(ct=x())==null||ct(ye,{nodeId:lt.nodeId,handleId:lt.handleId,handleType:lt.handleType})},onConnectEnd:(ye,lt)=>{var ct;(ct=C())==null||ct(ye,lt)},getTransform:()=>[$().x,$().y,$().zoom],getFromHandle:()=>m().fromHandle})}let J=re(null),Re=re();ge(()=>j(S()),()=>{U(b,S()==="target")}),ge(()=>(j(B()),o()),()=>{U(N,B()!==void 0?B():o())}),ge(()=>j(R()),()=>{U(E,R()||null)}),ge(()=>(j(H()),j(I()),_(),v(),j(S()),j(R())),()=>{(H()||I())&&(_(),U(Re,v().get(`${K}-${S()}${R()?`-${R()}`:""}`)))}),ge(()=>(h(J),h(Re),j(I()),j(H())),()=>{if(h(J)&&!Kv(h(Re),h(J))){const Te=h(Re)??new Map;vu(h(J),Te,I()),vu(Te,h(J),H())}U(J,h(Re)??new Map)}),ge(()=>m(),()=>{U(T,!!m().fromHandle)}),ge(()=>(m(),j(S()),h(E)),()=>{var Te,st,ye;U(D,((Te=m().fromHandle)==null?void 0:Te.nodeId)===K&&((st=m().fromHandle)==null?void 0:st.type)===S()&&((ye=m().fromHandle)==null?void 0:ye.id)===h(E))}),ge(()=>(m(),j(S()),h(E)),()=>{var Te,st,ye;U(V,((Te=m().toHandle)==null?void 0:Te.nodeId)===K&&((st=m().toHandle)==null?void 0:st.type)===S()&&((ye=m().toHandle)==null?void 0:ye.id)===h(E))}),ge(()=>(l(),m(),j(S()),h(E)),()=>{var Te,st,ye;U(A,l()===hr.Strict?((Te=m().fromHandle)==null?void 0:Te.type)!==S():K!==((st=m().fromHandle)==null?void 0:st.nodeId)||h(E)!==((ye=m().fromHandle)==null?void 0:ye.id))}),ge(()=>(h(V),m()),()=>{U(O,h(V)&&m().isValid)}),vt(),He();var le=B0();de(le,"data-nodeid",K);let $n;var fn=X(le);wt(fn,t,"default",{}),Z(le),Ee(Te=>{de(le,"data-handleid",h(E)),de(le,"data-handlepos",M()),de(le,"data-id",`${f()??""}-${K??""}-${R()||""}-${S()??""}`),$n=$t(le,1,wn(Te),null,$n,{valid:h(O),connectingto:h(V),connectingfrom:h(D),source:!h(b),target:h(b),connectablestart:h(N),connectableend:h(N),connectable:h(N),connectionindicator:h(N)&&(!h(T)||h(A))}),de(le,"style",k())},[()=>Et(["svelte-flow__handle",`svelte-flow__handle-${M()}`,"nodrag","nopan",M(),F()])],ve),Ze("mousedown",le,dt),Ze("touchstart",le,dt),L(e,le);var En=ce({get id(){return R()},set id(Te){R(Te),y()},get type(){return S()},set type(Te){S(Te),y()},get position(){return M()},set position(Te){M(Te),y()},get style(){return k()},set style(Te){k(Te),y()},get isValidConnection(){return P()},set isValidConnection(Te){P(Te),y()},get onconnect(){return H()},set onconnect(Te){H(Te),y()},get ondisconnect(){return I()},set ondisconnect(Te){I(Te),y()},get isConnectable(){return B()},set isConnectable(Te){B(Te),y()},get class(){return F()},set class(Te){F(Te),y()}});return r(),En}ie(er,{id:{},type:{},position:{},style:{},isValidConnection:{},onconnect:{},ondisconnect:{},isConnectable:{},class:{}},["default"],[],!0);var Y0=ne(" ",1);function Ii(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]);it(n,["data","targetPosition","sourcePosition"]),ue(t,!1);let r=w(t,"data",28,()=>({label:"Node"})),o=w(t,"targetPosition",12,void 0),i=w(t,"sourcePosition",12,void 0);He();var s=Y0(),a=xe(s);const l=ve(()=>o()??$e.Top);er(a,{type:"target",get position(){return h(l)}});var u=z(a),c=z(u);const f=ve(()=>i()??$e.Bottom);return er(c,{type:"source",get position(){return h(f)}}),Ee(()=>{var d;return Bt(u,` ${((d=r())==null?void 0:d.label)??""} `)}),L(e,s),ce({get data(){return r()},set data(d){r(d),y()},get targetPosition(){return o()},set targetPosition(d){o(d),y()},get sourcePosition(){return i()},set sourcePosition(d){i(d),y()}})}ie(Ii,{data:{},targetPosition:{},sourcePosition:{}},[],[],!0);var Z0=ne(" ",1);function Uu(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]);it(n,["data","sourcePosition"]),ue(t,!1);let r=w(t,"data",28,()=>({label:"Node"})),o=w(t,"sourcePosition",12,void 0);He(),Pe();var i=Z0(),s=xe(i),a=z(s);const l=ve(()=>o()??$e.Bottom);return er(a,{type:"source",get position(){return h(l)}}),Ee(()=>{var u;return Bt(s,`${((u=r())==null?void 0:u.label)??""} `)}),L(e,i),ce({get data(){return r()},set data(u){r(u),y()},get sourcePosition(){return o()},set sourcePosition(u){o(u),y()}})}ie(Uu,{data:{},sourcePosition:{}},[],[],!0);var X0=ne(" ",1);function ju(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]);it(n,["data","targetPosition"]),ue(t,!1);let r=w(t,"data",28,()=>({label:"Node"})),o=w(t,"targetPosition",12,void 0);He(),Pe();var i=X0(),s=xe(i),a=z(s);const l=ve(()=>o()??$e.Top);return er(a,{type:"target",get position(){return h(l)}}),Ee(()=>{var u;return Bt(s,`${((u=r())==null?void 0:u.label)??""} `)}),L(e,i),ce({get data(){return r()},set data(u){r(u),y()},get targetPosition(){return o()},set targetPosition(u){o(u),y()}})}ie(ju,{data:{},targetPosition:{}},[],[],!0);function Ju(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]);it(n,[])}ie(Ju,{},[],[],!0);function Qu(e,t,n){if(!t)return;const r=n?t.querySelector(n):t;r&&r.appendChild(e)}function Rr(e,{target:t,domNode:n}){return Qu(e,n,t),{async update({target:r,domNode:o}){Qu(e,o,r)},destroy(){e.parentNode&&e.parentNode.removeChild(e)}}}var F0=ne("");function ec(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(i,"$domNode",n),{domNode:i}=Ue();He();var s=F0(),a=X(s);wt(a,t,"default",{}),Z(s),_t(s,(l,u)=>Rr==null?void 0:Rr(l,u),()=>({target:".svelte-flow__edgelabel-renderer",domNode:o()})),L(e,s),ce(),r()}ie(ec,{},["default"],[],!0);function tc(){const{edgeLookup:e,selectionRect:t,selectionRectMode:n,multiselectionKeyPressed:r,addSelectedEdges:o,unselectNodesAndEdges:i,elementsSelectable:s}=Ue();return a=>{const l=q(e).get(a);if(!l){console.warn("012",Dr.error012(a));return}(l.selectable||q(s)&&typeof l.selectable>"u")&&(t.set(null),n.set(null),l.selected?l.selected&&q(r)&&i({nodes:[],edges:[l]}):o([a]))}}var W0=ne('');function nc(e,t){ue(t,!1);let n=w(t,"style",12,void 0),r=w(t,"x",12,void 0),o=w(t,"y",12,void 0);const i=tc(),s=ur("svelteflow__edge_id");return He(),ec(e,{children:(a,l)=>{var u=W0(),c=X(u);wt(c,t,"default",{}),Z(u),Ee(()=>{de(u,"style","pointer-events: all;"+n()),at(u,"transform",`translate(-50%, -50%) translate(${r()??""}px,${o()??""}px)`)}),Ze("keyup",u,()=>{}),Ze("click",u,()=>{s&&i(s)}),L(a,u)},$$slots:{default:!0}}),ce({get style(){return n()},set style(a){n(a),y()},get x(){return r()},set x(a){r(a),y()},get y(){return o()},set y(a){o(a),y()}})}ie(nc,{style:{},x:{},y:{}},["default"],[],!0);var K0=_e(''),q0=_e('',1);function Eo(e,t){ue(t,!1);let n=w(t,"id",12,void 0),r=w(t,"path",12),o=w(t,"label",12,void 0),i=w(t,"labelX",12,void 0),s=w(t,"labelY",12,void 0),a=w(t,"labelStyle",12,void 0),l=w(t,"markerStart",12,void 0),u=w(t,"markerEnd",12,void 0),c=w(t,"style",12,void 0),f=w(t,"interactionWidth",12,20),d=w(t,"class",12,void 0),g=f()===void 0?20:f();He();var p=q0(),x=xe(p),C=z(x);{var $=v=>{var b=K0();de(b,"stroke-opacity",0),de(b,"stroke-width",g),Ee(()=>de(b,"d",r())),L(v,b)};ke(C,v=>{g&&v($)})}var m=z(C);{var _=v=>{nc(v,{get x(){return i()},get y(){return s()},get style(){return a()},children:(b,N)=>{Pe();var E=Ae();Ee(()=>Bt(E,o())),L(b,E)},$$slots:{default:!0}})};ke(m,v=>{o()&&v(_)})}return Ee(v=>{de(x,"id",n()),de(x,"d",r()),$t(x,0,wn(v)),de(x,"marker-start",l()),de(x,"marker-end",u()),de(x,"style",c())},[()=>Et(["svelte-flow__edge-path",d()])],ve),L(e,p),ce({get id(){return n()},set id(v){n(v),y()},get path(){return r()},set path(v){r(v),y()},get label(){return o()},set label(v){o(v),y()},get labelX(){return i()},set labelX(v){i(v),y()},get labelY(){return s()},set labelY(v){s(v),y()},get labelStyle(){return a()},set labelStyle(v){a(v),y()},get markerStart(){return l()},set markerStart(v){l(v),y()},get markerEnd(){return u()},set markerEnd(v){u(v),y()},get style(){return c()},set style(v){c(v),y()},get interactionWidth(){return f()},set interactionWidth(v){f(v),y()},get class(){return d()},set class(v){d(v),y()}})}ie(Eo,{id:{},path:{},label:{},labelX:{},labelY:{},labelStyle:{},markerStart:{},markerEnd:{},style:{},interactionWidth:{},class:{}},[],[],!0);function zi(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]);it(n,["label","labelStyle","style","markerStart","markerEnd","interactionWidth","sourceX","sourceY","sourcePosition","targetX","targetY","targetPosition"]),ue(t,!1);const r=re(),o=re(),i=re();let s=w(t,"label",12,void 0),a=w(t,"labelStyle",12,void 0),l=w(t,"style",12,void 0),u=w(t,"markerStart",12,void 0),c=w(t,"markerEnd",12,void 0),f=w(t,"interactionWidth",12,void 0),d=w(t,"sourceX",12),g=w(t,"sourceY",12),p=w(t,"sourcePosition",12),x=w(t,"targetX",12),C=w(t,"targetY",12),$=w(t,"targetPosition",12);return ge(()=>(h(r),h(o),h(i),j(d()),j(g()),j(x()),j(C()),j(p()),j($())),()=>{(m=>(U(r,m[0]),U(o,m[1]),U(i,m[2])))(Tu({sourceX:d(),sourceY:g(),targetX:x(),targetY:C(),sourcePosition:p(),targetPosition:$()}))}),vt(),He(),Eo(e,{get path(){return h(r)},get labelX(){return h(o)},get labelY(){return h(i)},get label(){return s()},get labelStyle(){return a()},get markerStart(){return u()},get markerEnd(){return c()},get interactionWidth(){return f()},get style(){return l()}}),ce({get label(){return s()},set label(m){s(m),y()},get labelStyle(){return a()},set labelStyle(m){a(m),y()},get style(){return l()},set style(m){l(m),y()},get markerStart(){return u()},set markerStart(m){u(m),y()},get markerEnd(){return c()},set markerEnd(m){c(m),y()},get interactionWidth(){return f()},set interactionWidth(m){f(m),y()},get sourceX(){return d()},set sourceX(m){d(m),y()},get sourceY(){return g()},set sourceY(m){g(m),y()},get sourcePosition(){return p()},set sourcePosition(m){p(m),y()},get targetX(){return x()},set targetX(m){x(m),y()},get targetY(){return C()},set targetY(m){C(m),y()},get targetPosition(){return $()},set targetPosition(m){$(m),y()}})}ie(zi,{label:{},labelStyle:{},style:{},markerStart:{},markerEnd:{},interactionWidth:{},sourceX:{},sourceY:{},sourcePosition:{},targetX:{},targetY:{},targetPosition:{}},[],[],!0);function rc(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]);it(n,["label","labelStyle","style","markerStart","markerEnd","interactionWidth","sourceX","sourceY","sourcePosition","targetX","targetY","targetPosition"]),ue(t,!1);const r=re(),o=re(),i=re();let s=w(t,"label",12,void 0),a=w(t,"labelStyle",12,void 0),l=w(t,"style",12,void 0),u=w(t,"markerStart",12,void 0),c=w(t,"markerEnd",12,void 0),f=w(t,"interactionWidth",12,void 0),d=w(t,"sourceX",12),g=w(t,"sourceY",12),p=w(t,"sourcePosition",12),x=w(t,"targetX",12),C=w(t,"targetY",12),$=w(t,"targetPosition",12);return ge(()=>(h(r),h(o),h(i),j(d()),j(g()),j(x()),j(C()),j(p()),j($())),()=>{(m=>(U(r,m[0]),U(o,m[1]),U(i,m[2])))(Li({sourceX:d(),sourceY:g(),targetX:x(),targetY:C(),sourcePosition:p(),targetPosition:$()}))}),vt(),He(),Eo(e,{get path(){return h(r)},get labelX(){return h(o)},get labelY(){return h(i)},get label(){return s()},get labelStyle(){return a()},get markerStart(){return u()},get markerEnd(){return c()},get interactionWidth(){return f()},get style(){return l()}}),ce({get label(){return s()},set label(m){s(m),y()},get labelStyle(){return a()},set labelStyle(m){a(m),y()},get style(){return l()},set style(m){l(m),y()},get markerStart(){return u()},set markerStart(m){u(m),y()},get markerEnd(){return c()},set markerEnd(m){c(m),y()},get interactionWidth(){return f()},set interactionWidth(m){f(m),y()},get sourceX(){return d()},set sourceX(m){d(m),y()},get sourceY(){return g()},set sourceY(m){g(m),y()},get sourcePosition(){return p()},set sourcePosition(m){p(m),y()},get targetX(){return x()},set targetX(m){x(m),y()},get targetY(){return C()},set targetY(m){C(m),y()},get targetPosition(){return $()},set targetPosition(m){$(m),y()}})}ie(rc,{label:{},labelStyle:{},style:{},markerStart:{},markerEnd:{},interactionWidth:{},sourceX:{},sourceY:{},sourcePosition:{},targetX:{},targetY:{},targetPosition:{}},[],[],!0);function oc(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]);it(n,["label","labelStyle","style","markerStart","markerEnd","interactionWidth","sourceX","sourceY","targetX","targetY"]),ue(t,!1);const r=re(),o=re(),i=re();let s=w(t,"label",12,void 0),a=w(t,"labelStyle",12,void 0),l=w(t,"style",12,void 0),u=w(t,"markerStart",12,void 0),c=w(t,"markerEnd",12,void 0),f=w(t,"interactionWidth",12,void 0),d=w(t,"sourceX",12),g=w(t,"sourceY",12),p=w(t,"targetX",12),x=w(t,"targetY",12);return ge(()=>(h(r),h(o),h(i),j(d()),j(g()),j(p()),j(x())),()=>{(C=>(U(r,C[0]),U(o,C[1]),U(i,C[2])))(ea({sourceX:d(),sourceY:g(),targetX:p(),targetY:x()}))}),vt(),He(),Eo(e,{get path(){return h(r)},get labelX(){return h(o)},get labelY(){return h(i)},get label(){return s()},get labelStyle(){return a()},get markerStart(){return u()},get markerEnd(){return c()},get interactionWidth(){return f()},get style(){return l()}}),ce({get label(){return s()},set label(C){s(C),y()},get labelStyle(){return a()},set labelStyle(C){a(C),y()},get style(){return l()},set style(C){l(C),y()},get markerStart(){return u()},set markerStart(C){u(C),y()},get markerEnd(){return c()},set markerEnd(C){c(C),y()},get interactionWidth(){return f()},set interactionWidth(C){f(C),y()},get sourceX(){return d()},set sourceX(C){d(C),y()},get sourceY(){return g()},set sourceY(C){g(C),y()},get targetX(){return p()},set targetX(C){p(C),y()},get targetY(){return x()},set targetY(C){x(C),y()}})}ie(oc,{label:{},labelStyle:{},style:{},markerStart:{},markerEnd:{},interactionWidth:{},sourceX:{},sourceY:{},targetX:{},targetY:{}},[],[],!0);function ic(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]);it(n,["label","labelStyle","style","markerStart","markerEnd","interactionWidth","sourceX","sourceY","sourcePosition","targetX","targetY","targetPosition"]),ue(t,!1);const r=re(),o=re(),i=re();let s=w(t,"label",12,void 0),a=w(t,"labelStyle",12,void 0),l=w(t,"style",12,void 0),u=w(t,"markerStart",12,void 0),c=w(t,"markerEnd",12,void 0),f=w(t,"interactionWidth",12,void 0),d=w(t,"sourceX",12),g=w(t,"sourceY",12),p=w(t,"sourcePosition",12),x=w(t,"targetX",12),C=w(t,"targetY",12),$=w(t,"targetPosition",12);return ge(()=>(h(r),h(o),h(i),j(d()),j(g()),j(x()),j(C()),j(p()),j($())),()=>{(m=>(U(r,m[0]),U(o,m[1]),U(i,m[2])))(Li({sourceX:d(),sourceY:g(),targetX:x(),targetY:C(),sourcePosition:p(),targetPosition:$(),borderRadius:0}))}),vt(),He(),Eo(e,{get path(){return h(r)},get labelX(){return h(o)},get labelY(){return h(i)},get label(){return s()},get labelStyle(){return a()},get markerStart(){return u()},get markerEnd(){return c()},get interactionWidth(){return f()},get style(){return l()}}),ce({get label(){return s()},set label(m){s(m),y()},get labelStyle(){return a()},set labelStyle(m){a(m),y()},get style(){return l()},set style(m){l(m),y()},get markerStart(){return u()},set markerStart(m){u(m),y()},get markerEnd(){return c()},set markerEnd(m){c(m),y()},get interactionWidth(){return f()},set interactionWidth(m){f(m),y()},get sourceX(){return d()},set sourceX(m){d(m),y()},get sourceY(){return g()},set sourceY(m){g(m),y()},get sourcePosition(){return p()},set sourcePosition(m){p(m),y()},get targetX(){return x()},set targetX(m){x(m),y()},get targetY(){return C()},set targetY(m){C(m),y()},get targetPosition(){return $()},set targetPosition(m){$(m),y()}})}ie(ic,{label:{},labelStyle:{},style:{},markerStart:{},markerEnd:{},interactionWidth:{},sourceX:{},sourceY:{},sourcePosition:{},targetX:{},targetY:{},targetPosition:{}},[],[],!0);function G0(e,t){const n=e.set,r=t.set,o=q(e),i=q(t);let a=o.length===0&&i.length>0?i:o;e.set(a);const l=u=>{const c=n(u);return a=c,r(a),c};e.set=t.set=l,e.update=t.update=u=>l(u(a))}function U0(e,t){const n=e.set,r=t.set;let o=q(t);e.set(o);const i=s=>{n(s),r(s),o=s};e.set=t.set=i,e.update=t.update=s=>i(s(o))}const j0=(e,t,n)=>{if(!n)return;const r=q(e),o=t.set,i=n.set;let s=n?q(n):{x:0,y:0,zoom:1};t.set(s),t.set=a=>(o(a),i(a),s=a,a),n.set=a=>(r==null||r.syncViewport(a),o(a),i(a),s=a,a),t.update=a=>{t.set(a(s))},n.update=a=>{n.set(a(s))}},J0=(e,t,n,r=[0,0],o=Ni)=>{const{subscribe:i,set:s,update:a}=we([]);let l=e,u={},c=!0;const f=x=>(Ou(x,t,n,{elevateNodesOnSelect:c,nodeOrigin:r,nodeExtent:o,defaults:u,checkEquality:!1}),l=x,s(l),l),d=x=>f(x(l)),g=x=>{u=x},p=x=>{c=x.elevateNodesOnSelect??c};return f(l),{subscribe:i,set:f,update:d,setDefaultOptions:g,setOptions:p}},Q0=(e,t,n,r)=>{const{subscribe:o,set:i,update:s}=we([]);let a=e,l={};const u=d=>{const g=l?d.map(p=>({...l,...p})):d;Ru(t,n,g),a=g,i(a)},c=d=>u(d(a)),f=d=>{l=d};return u(a),{subscribe:o,set:u,update:c,setDefaultOptions:f}},sc={input:Uu,output:ju,default:Ii,group:Ju},ac={straight:oc,smoothstep:rc,default:zi,step:ic},e2=({nodes:e=[],edges:t=[],width:n,height:r,fitView:o,nodeOrigin:i,nodeExtent:s})=>{const a=new Map,l=new Map,u=new Map,c=new Map,f=i??[0,0],d=s??Ni;Ou(e,a,l,{nodeExtent:d,nodeOrigin:f,elevateNodesOnSelect:!1,checkEquality:!1}),Ru(u,c,t);let g={x:0,y:0,zoom:1};if(o&&n&&r){const p=bo(a,{filter:x=>!!((x.width||x.initialWidth)&&(x.height||x.initialHeight))});g=js(p,n,r,.5,2,.1)}return{flowId:we(null),nodes:J0(e,a,l,f,d),nodeLookup:Gt(a),parentLookup:Gt(l),edgeLookup:Gt(c),visibleNodes:Gt([]),edges:Q0(t,u,c),visibleEdges:Gt([]),connectionLookup:Gt(u),height:we(500),width:we(500),minZoom:we(.5),maxZoom:we(2),nodeOrigin:we(f),nodeDragThreshold:we(1),nodeExtent:we(d),translateExtent:we(Ni),autoPanOnNodeDrag:we(!0),autoPanOnConnect:we(!0),fitViewOnInit:we(!1),fitViewOnInitDone:we(!1),fitViewOptions:we(void 0),panZoom:we(null),snapGrid:we(null),dragging:we(!1),selectionRect:we(null),selectionKeyPressed:we(!1),multiselectionKeyPressed:we(!1),deleteKeyPressed:we(!1),panActivationKeyPressed:we(!1),zoomActivationKeyPressed:we(!1),selectionRectMode:we(null),selectionMode:we(Ti.Partial),nodeTypes:we(sc),edgeTypes:we(ac),viewport:we(g),connectionMode:we(hr.Strict),domNode:we(null),connection:Gt(Ws),connectionLineType:we(Ar.Bezier),connectionRadius:we(20),isValidConnection:we(()=>!0),nodesDraggable:we(!0),nodesConnectable:we(!0),elementsSelectable:we(!0),selectNodesOnDrag:we(!0),markers:Gt([]),defaultMarkerColor:we("#b1b1b7"),lib:Gt("svelte"),onlyRenderVisibleElements:we(!1),onerror:we(Qv),ondelete:we(void 0),onedgecreate:we(void 0),onconnect:we(void 0),onconnectstart:we(void 0),onconnectend:we(void 0),onbeforedelete:we(void 0),nodesInitialized:we(!1),edgesInitialized:we(!1),viewportInitialized:we(!1),initialized:Gt(!1)}};function t2(e){const t=Un([e.edges,e.nodes,e.nodeLookup,e.onlyRenderVisibleElements,e.viewport,e.width,e.height],([n,,r,o,i,s,a])=>o&&s&&a?n.filter(u=>{const c=r.get(u.source),f=r.get(u.target);return c&&f&&s0({sourceNode:c,targetNode:f,width:s,height:a,transform:[i.x,i.y,i.zoom]})}):n);return Un([t,e.nodes,e.nodeLookup,e.connectionMode,e.onerror],([n,,r,o,i])=>n.reduce((a,l)=>{const u=r.get(l.source),c=r.get(l.target);if(!u||!c)return a;const f=g0({id:l.id,sourceNode:u,targetNode:c,sourceHandle:l.sourceHandle||null,targetHandle:l.targetHandle||null,connectionMode:o,onError:i});return f&&a.push({...l,zIndex:i0({selected:l.selected,zIndex:l.zIndex,sourceNode:u,targetNode:c,elevateOnSelect:!1}),...f}),a},[]))}function n2(e){return Un([e.nodeLookup,e.onlyRenderVisibleElements,e.width,e.height,e.viewport,e.nodes],([t,n,r,o,i])=>{const s=[i.x,i.y,i.zoom];return n?pu(t,{x:0,y:0,width:r,height:o},s,!0):Array.from(t.values())})}const Ri=Symbol();function lc({nodes:e,edges:t,width:n,height:r,fitView:o,nodeOrigin:i,nodeExtent:s}){const a=e2({nodes:e,edges:t,width:n,height:r,fitView:o,nodeOrigin:i,nodeExtent:s});function l(k){a.nodeTypes.set({...sc,...k})}function u(k){a.edgeTypes.set({...ac,...k})}function c(k){const P=q(a.edges);a.edges.set(u0(k,P))}const f=(k,P=!1)=>{var I;const H=q(a.nodeLookup);for(const[B,F]of k){const K=(I=H.get(B))==null?void 0:I.internals.userNode;K&&(K.position=F.position,K.dragging=P)}a.nodes.update(B=>B)};function d(k){var F,K,se;const P=q(a.nodeLookup),H=q(a.parentLookup),{changes:I,updatedInternals:B}=x0(k,P,q(a.parentLookup),q(a.domNode),q(a.nodeOrigin));if(B){if(m0(P,H,{nodeOrigin:i,nodeExtent:s}),!q(a.fitViewOnInitDone)&&q(a.fitViewOnInit)){const ee=q(a.fitViewOptions),W=p({...ee,nodes:ee==null?void 0:ee.nodes});a.fitViewOnInitDone.set(W)}for(const ee of I){const W=(F=P.get(ee.id))==null?void 0:F.internals.userNode;if(W)switch(ee.type){case"dimensions":{const fe={...W.measured,...ee.dimensions};ee.setAttributes&&(W.width=((K=ee.dimensions)==null?void 0:K.width)??W.width,W.height=((se=ee.dimensions)==null?void 0:se.height)??W.height),W.measured=fe;break}case"position":W.position=ee.position??W.position;break}}a.nodes.update(ee=>ee),q(a.nodesInitialized)||a.nodesInitialized.set(!0)}}function g(k){const P=q(a.panZoom),H=q(a.domNode);if(!P||!H)return Promise.resolve(!1);const{width:I,height:B}=Qs(H),F=mu(q(a.nodeLookup),k);return yu({nodes:F,width:I,height:B,minZoom:q(a.minZoom),maxZoom:q(a.maxZoom),panZoom:P},k)}function p(k){const P=q(a.panZoom);if(!P)return!1;const H=mu(q(a.nodeLookup),k);return yu({nodes:H,width:q(a.width),height:q(a.height),minZoom:q(a.minZoom),maxZoom:q(a.maxZoom),panZoom:P},k),H.size>0}function x(k,P){const H=q(a.panZoom);return H?H.scaleBy(k,P):Promise.resolve(!1)}function C(k){return x(1.2,k)}function $(k){return x(1/1.2,k)}function m(k){const P=q(a.panZoom);P&&(P.setScaleExtent([k,q(a.maxZoom)]),a.minZoom.set(k))}function _(k){const P=q(a.panZoom);P&&(P.setScaleExtent([q(a.minZoom),k]),a.maxZoom.set(k))}function v(k){const P=q(a.panZoom);P&&(P.setTranslateExtent(k),a.translateExtent.set(k))}function b(k){let P=!1;return k.forEach(H=>{H.selected&&(H.selected=!1,P=!0)}),P}function N(k){var P;(P=q(a.panZoom))==null||P.setClickDistance(k)}function E(k){b((k==null?void 0:k.nodes)||q(a.nodes))&&a.nodes.set(q(a.nodes)),b((k==null?void 0:k.edges)||q(a.edges))&&a.edges.set(q(a.edges))}a.deleteKeyPressed.subscribe(async k=>{var P;if(k){const H=q(a.nodes),I=q(a.edges),B=H.filter(ee=>ee.selected),F=I.filter(ee=>ee.selected),{nodes:K,edges:se}=await wu({nodesToRemove:B,edgesToRemove:F,nodes:H,edges:I,onBeforeDelete:q(a.onbeforedelete)});(K.length||se.length)&&(a.nodes.update(ee=>ee.filter(W=>!K.some(fe=>fe.id===W.id))),a.edges.update(ee=>ee.filter(W=>!se.some(fe=>fe.id===W.id))),(P=q(a.ondelete))==null||P({nodes:K,edges:se}))}});function T(k){const P=q(a.multiselectionKeyPressed);a.nodes.update(H=>H.map(I=>{const B=k.includes(I.id),F=P&&I.selected||B;return I.selected=F,I})),P||a.edges.update(H=>H.map(I=>(I.selected=!1,I)))}function D(k){const P=q(a.multiselectionKeyPressed);a.edges.update(H=>H.map(I=>{const B=k.includes(I.id),F=P&&I.selected||B;return I.selected=F,I})),P||a.nodes.update(H=>H.map(I=>(I.selected=!1,I)))}function V(k){var H;const P=(H=q(a.nodes))==null?void 0:H.find(I=>I.id===k);if(!P){console.warn("012",Dr.error012(k));return}a.selectionRect.set(null),a.selectionRectMode.set(null),P.selected?P.selected&&q(a.multiselectionKeyPressed)&&E({nodes:[P],edges:[]}):T([k])}function A(k){const P=q(a.viewport);return b0({delta:k,panZoom:q(a.panZoom),transform:[P.x,P.y,P.zoom],translateExtent:q(a.translateExtent),width:q(a.width),height:q(a.height)})}const O=we(Ws),R=k=>{O.set({...k})};function S(){O.set(Ws)}function M(){a.fitViewOnInitDone.set(!1),a.selectionRect.set(null),a.selectionRectMode.set(null),a.snapGrid.set(null),a.isValidConnection.set(()=>!0),E(),S()}return{...a,visibleEdges:t2(a),visibleNodes:n2(a),connection:Un([O,a.viewport],([k,P])=>k.inProgress?{...k,to:ko(k.to,[P.x,P.y,P.zoom])}:{...k}),markers:Un([a.edges,a.defaultMarkerColor,a.flowId],([k,P,H])=>h0(k,{defaultColor:P,id:H})),initialized:(()=>{let k=!1;const P=q(a.nodes).length,H=q(a.edges).length;return Un([a.nodesInitialized,a.edgesInitialized,a.viewportInitialized],([I,B,F])=>k||(P===0?k=F:H===0?k=F&&I:k=F&&I&&B,k))})(),syncNodeStores:k=>G0(a.nodes,k),syncEdgeStores:k=>U0(a.edges,k),syncViewport:k=>j0(a.panZoom,a.viewport,k),setNodeTypes:l,setEdgeTypes:u,addEdge:c,updateNodePositions:f,updateNodeInternals:d,zoomIn:C,zoomOut:$,fitView:k=>g(k),setMinZoom:m,setMaxZoom:_,setTranslateExtent:v,setPaneClickDistance:N,unselectNodesAndEdges:E,addSelectedNodes:T,addSelectedEdges:D,handleNodeSelection:V,panBy:A,updateConnection:R,cancelConnection:S,reset:M}}function Ue(){const e=ur(Ri);if(!e)throw new Error("In order to use useStore you need to wrap your component in a ");return e.getStore()}function r2({nodes:e,edges:t,width:n,height:r,fitView:o,nodeOrigin:i,nodeExtent:s}){const a=lc({nodes:e,edges:t,width:n,height:r,fitView:o,nodeOrigin:i,nodeExtent:s});return Sr(Ri,{getStore:()=>a}),a}function la(e,t){const{panZoom:n,minZoom:r,maxZoom:o,initialViewport:i,viewport:s,dragging:a,translateExtent:l,paneClickDistance:u}=t,c=R0({domNode:e,minZoom:r,maxZoom:o,translateExtent:l,viewport:i,paneClickDistance:u,onDraggingChange:a.set}),f=c.getViewport();return s.set(f),n.set(c),c.update(t),{update(d){c.update(d)}}}var o2=ne('');const i2={hash:"svelte-4xkw84",code:".svelte-flow__zoom.svelte-4xkw84 {width:100%;height:100%;position:absolute;top:0;left:0;z-index:4;}"};function uc(e,t){ue(t,!1),et(e,i2);const[n,r]=nt(),o=()=>Q(H,"$panActivationKeyPressed",n),i=()=>Q(R,"$minZoom",n),s=()=>Q(S,"$maxZoom",n),a=()=>Q(I,"$zoomActivationKeyPressed",n),l=()=>Q(O,"$selectionRect",n),u=()=>Q(k,"$translateExtent",n),c=()=>Q(P,"$lib",n),f=re(),d=re(),g=re();let p=w(t,"initialViewport",12,void 0),x=w(t,"onMoveStart",12,void 0),C=w(t,"onMove",12,void 0),$=w(t,"onMoveEnd",12,void 0),m=w(t,"panOnScrollMode",12),_=w(t,"preventScrolling",12),v=w(t,"zoomOnScroll",12),b=w(t,"zoomOnDoubleClick",12),N=w(t,"zoomOnPinch",12),E=w(t,"panOnDrag",12),T=w(t,"panOnScroll",12),D=w(t,"paneClickDistance",12);const{viewport:V,panZoom:A,selectionRect:O,minZoom:R,maxZoom:S,dragging:M,translateExtent:k,lib:P,panActivationKeyPressed:H,zoomActivationKeyPressed:I,viewportInitialized:B}=Ue(),F=W=>V.set({x:W[0],y:W[1],zoom:W[2]});rn(()=>{ai(B,!0)}),ge(()=>j(p()),()=>{U(f,p()||{x:0,y:0,zoom:1})}),ge(()=>(o(),j(E())),()=>{U(d,o()||E())}),ge(()=>(o(),j(T())),()=>{U(g,o()||T())}),vt(),He();var K=o2(),se=X(K);wt(se,t,"default",{}),Z(K),_t(K,(W,fe)=>la==null?void 0:la(W,fe),()=>({viewport:V,minZoom:i(),maxZoom:s(),initialViewport:h(f),dragging:M,panZoom:A,onPanZoomStart:x(),onPanZoom:C(),onPanZoomEnd:$(),zoomOnScroll:v(),zoomOnDoubleClick:b(),zoomOnPinch:N(),panOnScroll:h(g),panOnDrag:h(d),panOnScrollSpeed:.5,panOnScrollMode:m()||Jn.Free,zoomActivationKeyPressed:a(),preventScrolling:typeof _()=="boolean"?_():!0,noPanClassName:"nopan",noWheelClassName:"nowheel",userSelectionActive:!!l(),translateExtent:u(),lib:c(),paneClickDistance:D(),onTransformChange:F})),L(e,K);var ee=ce({get initialViewport(){return p()},set initialViewport(W){p(W),y()},get onMoveStart(){return x()},set onMoveStart(W){x(W),y()},get onMove(){return C()},set onMove(W){C(W),y()},get onMoveEnd(){return $()},set onMoveEnd(W){$(W),y()},get panOnScrollMode(){return m()},set panOnScrollMode(W){m(W),y()},get preventScrolling(){return _()},set preventScrolling(W){_(W),y()},get zoomOnScroll(){return v()},set zoomOnScroll(W){v(W),y()},get zoomOnDoubleClick(){return b()},set zoomOnDoubleClick(W){b(W),y()},get zoomOnPinch(){return N()},set zoomOnPinch(W){N(W),y()},get panOnDrag(){return E()},set panOnDrag(W){E(W),y()},get panOnScroll(){return T()},set panOnScroll(W){T(W),y()},get paneClickDistance(){return D()},set paneClickDistance(W){D(W),y()}});return r(),ee}ie(uc,{initialViewport:{},onMoveStart:{},onMove:{},onMoveEnd:{},panOnScrollMode:{},preventScrolling:{},zoomOnScroll:{},zoomOnDoubleClick:{},zoomOnPinch:{},panOnDrag:{},panOnScroll:{},paneClickDistance:{}},["default"],[],!0);function cc(e,t){return n=>{n.target===t&&(e==null||e(n))}}function dc(e){return t=>{const n=e.includes(t.id);return t.selected!==n&&(t.selected=n),t}}var s2=ne("");const a2={hash:"svelte-1esy7hx",code:".svelte-flow__pane.svelte-1esy7hx {position:absolute;top:0;left:0;width:100%;height:100%;}"};function fc(e,t){ue(t,!1),et(e,a2);const[n,r]=nt(),o=()=>Q(S,"$panActivationKeyPressed",n),i=()=>Q(O,"$selectionKeyPressed",n),s=()=>Q(V,"$selectionRect",n),a=()=>Q(D,"$elementsSelectable",n),l=()=>Q(A,"$selectionRectMode",n),u=()=>Q(N,"$edges",n),c=()=>Q(b,"$nodeLookup",n),f=()=>Q(E,"$viewport",n),d=()=>Q(R,"$selectionMode",n),g=()=>Q(T,"$dragging",n),p=re(),x=re(),C=re();let $=w(t,"panOnDrag",12,void 0),m=w(t,"selectionOnDrag",12,void 0);const _=ii(),{nodes:v,nodeLookup:b,edges:N,viewport:E,dragging:T,elementsSelectable:D,selectionRect:V,selectionRectMode:A,selectionKeyPressed:O,selectionMode:R,panActivationKeyPressed:S,unselectNodesAndEdges:M}=Ue();let k=re(),P=null,H=[],I=!1;function B(G){if(I){I=!1;return}_("paneclick",{event:G}),M(),A.set(null)}function F(G){var Le,Xe;if(P=h(k).getBoundingClientRect(),!D||!h(x)||G.button!==0||G.target!==h(k)||!P)return;(Xe=(Le=G.target)==null?void 0:Le.setPointerCapture)==null||Xe.call(Le,G.pointerId);const{x:ae,y:Me}=Rn(G,P);M(),V.set({width:0,height:0,startX:ae,startY:Me,x:ae,y:Me})}function K(G){if(!h(x)||!P||!s())return;I=!0;const ae=Rn(G,P),Me=s().startX??0,Le=s().startY??0,Xe={...s(),x:ae.xoe.id),Fe=qs(H,u()).map(oe=>oe.id);H=pu(c(),Xe,[f().x,f().y,f().zoom],d()===Ti.Partial,!0);const Oe=qs(H,u()).map(oe=>oe.id),rt=H.map(oe=>oe.id);(te.length!==rt.length||rt.some(oe=>!te.includes(oe)))&&v.update(oe=>oe.map(dc(rt))),(Fe.length!==Oe.length||Oe.some(oe=>!Fe.includes(oe)))&&N.update(oe=>oe.map(dc(Oe))),A.set("user"),V.set(Xe)}function se(G){var ae,Me;G.button===0&&((Me=(ae=G.target)==null?void 0:ae.releasePointerCapture)==null||Me.call(ae,G.pointerId),!h(x)&&l()==="user"&&G.target===h(k)&&(B==null||B(G)),V.set(null),H.length>0&&ai(A,"nodes"),i()&&(I=!1))}const ee=G=>{var ae;if(Array.isArray(h(p))&&((ae=h(p))!=null&&ae.includes(2))){G.preventDefault();return}_("panecontextmenu",{event:G})};ge(()=>(o(),j($())),()=>{U(p,o()||$())}),ge(()=>(i(),s(),j(m()),h(p)),()=>{U(x,i()||s()||m()&&h(p)!==!0)}),ge(()=>(a(),h(x),l()),()=>{U(C,a()&&(h(x)||l()==="user"))}),vt(),He();var W=s2(),fe=Ne(()=>h(C)?void 0:cc(B,h(k))),me=Ne(()=>cc(ee,h(k)));let Ce;var he=X(W);wt(he,t,"default",{}),Z(W),An(W,G=>U(k,G),()=>h(k)),Ee(G=>Ce=$t(W,1,"svelte-flow__pane svelte-1esy7hx",null,Ce,{draggable:G,dragging:g(),selection:h(x)}),[()=>$()===!0||Array.isArray($())&&$().includes(0)],ve),Ze("click",W,function(...G){var ae;(ae=h(fe))==null||ae.apply(this,G)}),Ze("pointerdown",W,function(...G){var ae;(ae=h(C)?F:void 0)==null||ae.apply(this,G)}),Ze("pointermove",W,function(...G){var ae;(ae=h(C)?K:void 0)==null||ae.apply(this,G)}),Ze("pointerup",W,function(...G){var ae;(ae=h(C)?se:void 0)==null||ae.apply(this,G)}),Ze("contextmenu",W,function(...G){var ae;(ae=h(me))==null||ae.apply(this,G)}),L(e,W);var ze=ce({get panOnDrag(){return $()},set panOnDrag(G){$(G),y()},get selectionOnDrag(){return m()},set selectionOnDrag(G){m(G),y()}});return r(),ze}ie(fc,{panOnDrag:{},selectionOnDrag:{}},["default"],[],!0);var l2=ne('');const u2={hash:"svelte-1floaup",code:".svelte-flow__viewport.svelte-1floaup {width:100%;height:100%;position:absolute;top:0;left:0;}"};function gc(e,t){ue(t,!1),et(e,u2);const[n,r]=nt(),o=()=>Q(i,"$viewport",n),{viewport:i}=Ue();He();var s=l2(),a=X(s);wt(a,t,"default",{}),Z(s),Ee(()=>de(s,"style",`transform: translate(${o().x??""}px, ${o().y??""}px) scale(${o().zoom??""})`)),L(e,s),ce(),r()}ie(gc,{},["default"],[],!0);function Br(e,t){const{store:n,onDrag:r,onDragStart:o,onDragStop:i,onNodeMouseDown:s}=t,a=$0({onDrag:r,onDragStart:o,onDragStop:i,onNodeMouseDown:s,getStoreItems:()=>{const u=q(n.snapGrid),c=q(n.viewport);return{nodes:q(n.nodes),nodeLookup:q(n.nodeLookup),edges:q(n.edges),nodeExtent:q(n.nodeExtent),snapGrid:u||[0,0],snapToGrid:!!u,nodeOrigin:q(n.nodeOrigin),multiSelectionActive:q(n.multiselectionKeyPressed),domNode:q(n.domNode),transform:[c.x,c.y,c.zoom],autoPanOnNodeDrag:q(n.autoPanOnNodeDrag),nodesDraggable:q(n.nodesDraggable),selectNodesOnDrag:q(n.selectNodesOnDrag),nodeDragThreshold:q(n.nodeDragThreshold),unselectNodesAndEdges:n.unselectNodesAndEdges,updateNodePositions:n.updateNodePositions,panBy:n.panBy}}});function l(u,c){if(c.disabled){a.destroy();return}a.update({domNode:u,noDragClassName:c.noDragClass,handleSelector:c.handleSelector,nodeId:c.nodeId,isSelectable:c.isSelectable,nodeClickDistance:c.nodeClickDistance})}return l(e,t),{update(u){l(e,u)},destroy(){a.destroy()}}}function c2({width:e,height:t,initialWidth:n,initialHeight:r,measuredWidth:o,measuredHeight:i}){if(o===void 0&&i===void 0){const s=e??n,a=t??r;return{width:s?`width:${s}px;`:"",height:a?`height:${a}px;`:""}}return{width:e?`width:${e}px;`:"",height:t?`height:${t}px;`:""}}var d2=ne("");function hc(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(me,"$nodeTypes",n),i=()=>Q(ae,"$elementsSelectable",n),s=()=>Q(Me,"$nodesDraggable",n),a=()=>Q(Fe,"$connectableStore",n),l=re(void 0,!0),u=re(void 0,!0),c=re(void 0,!0),f=re(void 0,!0);let d=w(t,"node",13),g=w(t,"id",13),p=w(t,"data",29,()=>({})),x=w(t,"selected",13,!1),C=w(t,"draggable",13,void 0),$=w(t,"selectable",13,void 0),m=w(t,"connectable",13,!0),_=w(t,"deletable",13,!0),v=w(t,"hidden",13,!1),b=w(t,"dragging",13,!1),N=w(t,"resizeObserver",13,null),E=w(t,"style",13,void 0),T=w(t,"type",13,"default"),D=w(t,"isParent",13,!1),V=w(t,"positionX",13),A=w(t,"positionY",13),O=w(t,"sourcePosition",13,void 0),R=w(t,"targetPosition",13,void 0),S=w(t,"zIndex",13),M=w(t,"measuredWidth",13,void 0),k=w(t,"measuredHeight",13,void 0),P=w(t,"initialWidth",13,void 0),H=w(t,"initialHeight",13,void 0),I=w(t,"width",13,void 0),B=w(t,"height",13,void 0),F=w(t,"dragHandle",13,void 0),K=w(t,"initialized",13,!1),se=w(t,"parentId",13,void 0),ee=w(t,"nodeClickDistance",13,void 0),W=w(t,"class",13,"");const fe=Ue(),{nodeTypes:me,nodeDragThreshold:Ce,selectNodesOnDrag:he,handleNodeSelection:ze,updateNodeInternals:G,elementsSelectable:ae,nodesDraggable:Me}=fe;let Le=re(void 0,!0),Xe=re(null,!0);const te=ii(),Fe=we(m());let Oe=re(void 0,!0),rt=re(void 0,!0),oe=re(void 0,!0);Sr("svelteflow__node_id",g()),Sr("svelteflow__node_connectable",Fe),$s(()=>{var J;h(Xe)&&((J=N())==null||J.unobserve(h(Xe)))});function pe(J){$()&&(!q(he)||!C()||q(Ce)>0)&&ze(g()),te("nodeclick",{node:d().internals.userNode,event:J})}ge(()=>j(T()),()=>{U(l,T()||"default")}),ge(()=>(o(),h(l)),()=>{U(u,!!o()[h(l)])}),ge(()=>(o(),h(l),Ii),()=>{U(c,o()[h(l)]||Ii)}),ge(()=>(h(u),j(T())),()=>{h(u)||console.warn("003",Dr.error003(T()))}),ge(()=>(j(I()),j(B()),j(P()),j(H()),j(M()),j(k())),()=>{U(f,c2({width:I(),height:B(),initialWidth:P(),initialHeight:H(),measuredWidth:M(),measuredHeight:k()}))}),ge(()=>j(m()),()=>{Fe.set(!!m())}),ge(()=>(h(Oe),h(l),h(rt),j(O()),h(oe),j(R()),j(g()),h(Le)),()=>{(h(Oe)&&h(l)!==h(Oe)||h(rt)&&O()!==h(rt)||h(oe)&&R()!==h(oe))&&requestAnimationFrame(()=>G(new Map([[g(),{id:g(),nodeElement:h(Le),force:!0}]]))),U(Oe,h(l)),U(rt,O()),U(oe,R())}),ge(()=>(j(N()),h(Le),h(Xe),j(K())),()=>{N()&&(h(Le)!==h(Xe)||!K())&&(h(Xe)&&N().unobserve(h(Xe)),h(Le)&&N().observe(h(Le)),U(Xe,h(Le)))}),vt(),He(!0);var be=tt(),Ie=xe(be);{var ht=J=>{var Re=d2();let le;var $n=X(Re);const fn=ve(()=>x()??!1),En=ve(()=>$()??i()??!0),Te=ve(()=>_()??!0),st=ve(()=>C()??s()??!0);fl($n,()=>h(c),(ye,lt)=>{lt(ye,{get data(){return p()},get id(){return g()},get selected(){return h(fn)},get selectable(){return h(En)},get deletable(){return h(Te)},get sourcePosition(){return O()},get targetPosition(){return R()},get zIndex(){return S()},get dragging(){return b()},get draggable(){return h(st)},get dragHandle(){return F()},get parentId(){return se()},get type(){return h(l)},get isConnectable(){return a()},get positionAbsoluteX(){return V()},get positionAbsoluteY(){return A()},get width(){return I()},get height(){return B()}})}),Z(Re),_t(Re,(ye,lt)=>Br==null?void 0:Br(ye,lt),()=>({nodeId:g(),isSelectable:$(),disabled:!1,handleSelector:F(),noDragClass:"nodrag",nodeClickDistance:ee(),onNodeMouseDown:ze,onDrag:(ye,lt,ct,Jt)=>{te("nodedrag",{event:ye,targetNode:ct,nodes:Jt})},onDragStart:(ye,lt,ct,Jt)=>{te("nodedragstart",{event:ye,targetNode:ct,nodes:Jt})},onDragStop:(ye,lt,ct,Jt)=>{te("nodedragstop",{event:ye,targetNode:ct,nodes:Jt})},store:fe})),An(Re,ye=>U(Le,ye),()=>h(Le)),Rt(()=>Ze("click",Re,pe)),Rt(()=>Ze("mouseenter",Re,ye=>te("nodemouseenter",{node:d(),event:ye}))),Rt(()=>Ze("mouseleave",Re,ye=>te("nodemouseleave",{node:d(),event:ye}))),Rt(()=>Ze("mousemove",Re,ye=>te("nodemousemove",{node:d(),event:ye}))),Rt(()=>Ze("contextmenu",Re,ye=>te("nodecontextmenu",{node:d(),event:ye}))),Ee(ye=>{de(Re,"data-id",g()),le=$t(Re,1,wn(ye),null,le,{dragging:b(),selected:x(),draggable:C(),connectable:m(),selectable:$(),nopan:C(),parent:D()}),de(Re,"style",`${E()??""};${h(f).width??""}${h(f).height??""}`),at(Re,"z-index",S()),at(Re,"transform",`translate(${V()??""}px, ${A()??""}px)`),at(Re,"visibility",K()?"visible":"hidden")},[()=>Et(["svelte-flow__node",`svelte-flow__node-${h(l)}`,W()])],ve),L(J,Re)};ke(Ie,J=>{v()||J(ht)})}L(e,be);var dt=ce({get node(){return d()},set node(J){d(J),y()},get id(){return g()},set id(J){g(J),y()},get data(){return p()},set data(J){p(J),y()},get selected(){return x()},set selected(J){x(J),y()},get draggable(){return C()},set draggable(J){C(J),y()},get selectable(){return $()},set selectable(J){$(J),y()},get connectable(){return m()},set connectable(J){m(J),y()},get deletable(){return _()},set deletable(J){_(J),y()},get hidden(){return v()},set hidden(J){v(J),y()},get dragging(){return b()},set dragging(J){b(J),y()},get resizeObserver(){return N()},set resizeObserver(J){N(J),y()},get style(){return E()},set style(J){E(J),y()},get type(){return T()},set type(J){T(J),y()},get isParent(){return D()},set isParent(J){D(J),y()},get positionX(){return V()},set positionX(J){V(J),y()},get positionY(){return A()},set positionY(J){A(J),y()},get sourcePosition(){return O()},set sourcePosition(J){O(J),y()},get targetPosition(){return R()},set targetPosition(J){R(J),y()},get zIndex(){return S()},set zIndex(J){S(J),y()},get measuredWidth(){return M()},set measuredWidth(J){M(J),y()},get measuredHeight(){return k()},set measuredHeight(J){k(J),y()},get initialWidth(){return P()},set initialWidth(J){P(J),y()},get initialHeight(){return H()},set initialHeight(J){H(J),y()},get width(){return I()},set width(J){I(J),y()},get height(){return B()},set height(J){B(J),y()},get dragHandle(){return F()},set dragHandle(J){F(J),y()},get initialized(){return K()},set initialized(J){K(J),y()},get parentId(){return se()},set parentId(J){se(J),y()},get nodeClickDistance(){return ee()},set nodeClickDistance(J){ee(J),y()},get class(){return W()},set class(J){W(J),y()}});return r(),dt}ie(hc,{node:{},id:{},data:{},selected:{},draggable:{},selectable:{},connectable:{},deletable:{},hidden:{},dragging:{},resizeObserver:{},style:{},type:{},isParent:{},positionX:{},positionY:{},sourcePosition:{},targetPosition:{},zIndex:{},measuredWidth:{},measuredHeight:{},initialWidth:{},initialHeight:{},width:{},height:{},dragHandle:{},initialized:{},parentId:{},nodeClickDistance:{},class:{}},[],[],!0);var f2=ne('');const g2={hash:"svelte-tf4uy4",code:".svelte-flow__nodes.svelte-tf4uy4 {width:100%;height:100%;position:absolute;left:0;top:0;}"};function vc(e,t){ue(t,!1),et(e,g2);const[n,r]=nt(),o=()=>Q(c,"$visibleNodes",n),i=()=>Q(f,"$nodesDraggable",n),s=()=>Q(g,"$elementsSelectable",n),a=()=>Q(d,"$nodesConnectable",n),l=()=>Q(x,"$parentLookup",n);let u=w(t,"nodeClickDistance",12,0);const{visibleNodes:c,nodesDraggable:f,nodesConnectable:d,elementsSelectable:g,updateNodeInternals:p,parentLookup:x}=Ue(),C=typeof ResizeObserver>"u"?null:new ResizeObserver(_=>{const v=new Map;_.forEach(b=>{const N=b.target.getAttribute("data-id");v.set(N,{id:N,nodeElement:b.target,force:!0})}),p(v)});$s(()=>{C==null||C.disconnect()}),He();var $=f2();Yt($,5,o,_=>_.id,(_,v)=>{const b=ve(()=>!!h(v).selected),N=ve(()=>!!h(v).hidden),E=ve(()=>!!(h(v).draggable||i()&&typeof h(v).draggable>"u")),T=ve(()=>!!(h(v).selectable||s()&&typeof h(v).selectable>"u")),D=ve(()=>!!(h(v).connectable||a()&&typeof h(v).connectable>"u")),V=ve(()=>h(v).deletable??!0),A=ve(()=>l().has(h(v).id)),O=ve(()=>h(v).type??"default"),R=ve(()=>h(v).internals.z??0),S=ve(()=>Eu(h(v)));hc(_,{get node(){return h(v)},get id(){return h(v).id},get data(){return h(v).data},get selected(){return h(b)},get hidden(){return h(N)},get draggable(){return h(E)},get selectable(){return h(T)},get connectable(){return h(D)},get deletable(){return h(V)},get positionX(){return h(v).internals.positionAbsolute.x},get positionY(){return h(v).internals.positionAbsolute.y},get isParent(){return h(A)},get style(){return h(v).style},get class(){return h(v).class},get type(){return h(O)},get sourcePosition(){return h(v).sourcePosition},get targetPosition(){return h(v).targetPosition},get dragging(){return h(v).dragging},get zIndex(){return h(R)},get dragHandle(){return h(v).dragHandle},get initialized(){return h(S)},get width(){return h(v).width},get height(){return h(v).height},get initialWidth(){return h(v).initialWidth},get initialHeight(){return h(v).initialHeight},get measuredWidth(){return h(v).measured.width},get measuredHeight(){return h(v).measured.height},get parentId(){return h(v).parentId},resizeObserver:C,get nodeClickDistance(){return u()},$$events:{nodeclick(M){De.call(this,t,M)},nodemouseenter(M){De.call(this,t,M)},nodemousemove(M){De.call(this,t,M)},nodemouseleave(M){De.call(this,t,M)},nodedrag(M){De.call(this,t,M)},nodedragstart(M){De.call(this,t,M)},nodedragstop(M){De.call(this,t,M)},nodecontextmenu(M){De.call(this,t,M)}}})}),Z($),L(e,$);var m=ce({get nodeClickDistance(){return u()},set nodeClickDistance(_){u(_),y()}});return r(),m}ie(vc,{nodeClickDistance:{}},[],[],!0);var h2=_e('');function pc(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(W,"$edgeTypes",n),i=()=>Q(fe,"$flowId",n),s=()=>Q(me,"$elementsSelectable",n),a=()=>Q(ee,"$edgeLookup",n),l=re(void 0,!0),u=re(void 0,!0),c=re(void 0,!0),f=re(void 0,!0),d=re(void 0,!0);let g=w(t,"id",13),p=w(t,"type",13,"default"),x=w(t,"source",13,""),C=w(t,"target",13,""),$=w(t,"data",29,()=>({})),m=w(t,"style",13,void 0),_=w(t,"zIndex",13,void 0),v=w(t,"animated",13,!1),b=w(t,"selected",13,!1),N=w(t,"selectable",13,void 0),E=w(t,"deletable",13,void 0),T=w(t,"hidden",13,!1),D=w(t,"label",13,void 0),V=w(t,"labelStyle",13,void 0),A=w(t,"markerStart",13,void 0),O=w(t,"markerEnd",13,void 0),R=w(t,"sourceHandle",13,void 0),S=w(t,"targetHandle",13,void 0),M=w(t,"sourceX",13),k=w(t,"sourceY",13),P=w(t,"targetX",13),H=w(t,"targetY",13),I=w(t,"sourcePosition",13),B=w(t,"targetPosition",13),F=w(t,"ariaLabel",13,void 0),K=w(t,"interactionWidth",13,void 0),se=w(t,"class",13,"");Sr("svelteflow__edge_id",g());const{edgeLookup:ee,edgeTypes:W,flowId:fe,elementsSelectable:me}=Ue(),Ce=ii(),he=tc();function ze(te){const Fe=a().get(g());Fe&&(he(g()),Ce("edgeclick",{event:te,edge:Fe}))}function G(te,Fe){const Oe=a().get(g());Oe&&Ce(Fe,{event:te,edge:Oe})}ge(()=>j(p()),()=>{U(l,p()||"default")}),ge(()=>(o(),h(l),zi),()=>{U(u,o()[h(l)]||zi)}),ge(()=>(j(A()),i()),()=>{U(c,A()?`url('#${ta(A(),i())}')`:void 0)}),ge(()=>(j(O()),i()),()=>{U(f,O()?`url('#${ta(O(),i())}')`:void 0)}),ge(()=>(j(N()),s()),()=>{U(d,N()??s())}),vt(),He(!0);var ae=tt(),Me=xe(ae);{var Le=te=>{var Fe=h2(),Oe=X(Fe);let rt;var oe=X(Oe);const pe=ve(()=>E()??!0);fl(oe,()=>h(u),(be,Ie)=>{Ie(be,{get id(){return g()},get source(){return x()},get target(){return C()},get sourceX(){return M()},get sourceY(){return k()},get targetX(){return P()},get targetY(){return H()},get sourcePosition(){return I()},get targetPosition(){return B()},get animated(){return v()},get selected(){return b()},get label(){return D()},get labelStyle(){return V()},get data(){return $()},get style(){return m()},get interactionWidth(){return K()},get selectable(){return h(d)},get deletable(){return h(pe)},get type(){return h(l)},get sourceHandleId(){return R()},get targetHandleId(){return S()},get markerStart(){return h(c)},get markerEnd(){return h(f)}})}),Z(Oe),Z(Fe),Ee(be=>{at(Fe,"z-index",_()),rt=$t(Oe,0,wn(be),null,rt,{animated:v(),selected:b(),selectable:h(d)}),de(Oe,"data-id",g()),de(Oe,"aria-label",F()===null?void 0:F()?F():`Edge from ${x()} to ${C()}`)},[()=>Et(["svelte-flow__edge",se()])],ve),Ze("click",Oe,ze),Ze("contextmenu",Oe,be=>{G(be,"edgecontextmenu")}),Ze("mouseenter",Oe,be=>{G(be,"edgemouseenter")}),Ze("mouseleave",Oe,be=>{G(be,"edgemouseleave")}),L(te,Fe)};ke(Me,te=>{T()||te(Le)})}L(e,ae);var Xe=ce({get id(){return g()},set id(te){g(te),y()},get type(){return p()},set type(te){p(te),y()},get source(){return x()},set source(te){x(te),y()},get target(){return C()},set target(te){C(te),y()},get data(){return $()},set data(te){$(te),y()},get style(){return m()},set style(te){m(te),y()},get zIndex(){return _()},set zIndex(te){_(te),y()},get animated(){return v()},set animated(te){v(te),y()},get selected(){return b()},set selected(te){b(te),y()},get selectable(){return N()},set selectable(te){N(te),y()},get deletable(){return E()},set deletable(te){E(te),y()},get hidden(){return T()},set hidden(te){T(te),y()},get label(){return D()},set label(te){D(te),y()},get labelStyle(){return V()},set labelStyle(te){V(te),y()},get markerStart(){return A()},set markerStart(te){A(te),y()},get markerEnd(){return O()},set markerEnd(te){O(te),y()},get sourceHandle(){return R()},set sourceHandle(te){R(te),y()},get targetHandle(){return S()},set targetHandle(te){S(te),y()},get sourceX(){return M()},set sourceX(te){M(te),y()},get sourceY(){return k()},set sourceY(te){k(te),y()},get targetX(){return P()},set targetX(te){P(te),y()},get targetY(){return H()},set targetY(te){H(te),y()},get sourcePosition(){return I()},set sourcePosition(te){I(te),y()},get targetPosition(){return B()},set targetPosition(te){B(te),y()},get ariaLabel(){return F()},set ariaLabel(te){F(te),y()},get interactionWidth(){return K()},set interactionWidth(te){K(te),y()},get class(){return se()},set class(te){se(te),y()}});return r(),Xe}ie(pc,{id:{},type:{},source:{},target:{},data:{},style:{},zIndex:{},animated:{},selected:{},selectable:{},deletable:{},hidden:{},label:{},labelStyle:{},markerStart:{},markerEnd:{},sourceHandle:{},targetHandle:{},sourceX:{},sourceY:{},targetX:{},targetY:{},sourcePosition:{},targetPosition:{},ariaLabel:{},interactionWidth:{},class:{}},[],[],!0);function mc(e,t){ue(t,!1);let n=w(t,"onMount",12,void 0),r=w(t,"onDestroy",12,void 0);return rn(()=>{var o;return(o=n())==null||o(),r()}),He(),ce({get onMount(){return n()},set onMount(o){n(o),y()},get onDestroy(){return r()},set onDestroy(o){r(o),y()}})}ie(mc,{onMount:{},onDestroy:{}},[],[],!0);var v2=_e("");function yc(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(i,"$markers",n),{markers:i}=Ue();He();var s=v2();Yt(s,5,o,a=>a.id,(a,l)=>{wc(a,ft(()=>h(l)))}),Z(s),L(e,s),ce(),r()}ie(yc,{},[],[],!0);var p2=_e(''),m2=_e(''),y2=_e('');function wc(e,t){ue(t,!1);let n=w(t,"id",12),r=w(t,"type",12),o=w(t,"width",12,12.5),i=w(t,"height",12,12.5),s=w(t,"markerUnits",12,"strokeWidth"),a=w(t,"orient",12,"auto-start-reverse"),l=w(t,"color",12,void 0),u=w(t,"strokeWidth",12,void 0);He();var c=y2(),f=X(c);{var d=p=>{var x=p2();Ee(()=>{de(x,"stroke",l()),de(x,"stroke-width",u())}),L(p,x)},g=(p,x)=>{{var C=$=>{var m=m2();Ee(()=>{de(m,"stroke",l()),de(m,"stroke-width",u()),de(m,"fill",l())}),L($,m)};ke(p,$=>{r()===_o.ArrowClosed&&$(C)},x)}};ke(f,p=>{r()===_o.Arrow?p(d):p(g,!1)})}return Z(c),Ee(()=>{de(c,"id",n()),de(c,"markerWidth",`${o()}`),de(c,"markerHeight",`${i()}`),de(c,"markerUnits",s()),de(c,"orient",a())}),L(e,c),ce({get id(){return n()},set id(p){n(p),y()},get type(){return r()},set type(p){r(p),y()},get width(){return o()},set width(p){o(p),y()},get height(){return i()},set height(p){i(p),y()},get markerUnits(){return s()},set markerUnits(p){s(p),y()},get orient(){return a()},set orient(p){a(p),y()},get color(){return l()},set color(p){l(p),y()},get strokeWidth(){return u()},set strokeWidth(p){u(p),y()}})}ie(wc,{id:{},type:{},width:{},height:{},markerUnits:{},orient:{},color:{},strokeWidth:{}},[],[],!0);var w2=ne('
');function _c(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(a,"$visibleEdges",n),i=()=>Q(c,"$elementsSelectable",n);let s=w(t,"defaultEdgeOptions",12);const{visibleEdges:a,edgesInitialized:l,edges:{setDefaultOptions:u},elementsSelectable:c}=Ue();rn(()=>{s()&&u(s())}),He();var f=w2(),d=X(f),g=X(d);yc(g,{}),Z(d);var p=z(d,2);Yt(p,1,o,m=>m.id,(m,_)=>{const v=ve(()=>h(_).selectable??i()),b=ve(()=>h(_).type||"default");pc(m,{get id(){return h(_).id},get source(){return h(_).source},get target(){return h(_).target},get data(){return h(_).data},get style(){return h(_).style},get animated(){return h(_).animated},get selected(){return h(_).selected},get selectable(){return h(v)},get deletable(){return h(_).deletable},get hidden(){return h(_).hidden},get label(){return h(_).label},get labelStyle(){return h(_).labelStyle},get markerStart(){return h(_).markerStart},get markerEnd(){return h(_).markerEnd},get sourceHandle(){return h(_).sourceHandle},get targetHandle(){return h(_).targetHandle},get sourceX(){return h(_).sourceX},get sourceY(){return h(_).sourceY},get targetX(){return h(_).targetX},get targetY(){return h(_).targetY},get sourcePosition(){return h(_).sourcePosition},get targetPosition(){return h(_).targetPosition},get ariaLabel(){return h(_).ariaLabel},get interactionWidth(){return h(_).interactionWidth},get class(){return h(_).class},get type(){return h(b)},get zIndex(){return h(_).zIndex},$$events:{edgeclick(N){De.call(this,t,N)},edgecontextmenu(N){De.call(this,t,N)},edgemouseenter(N){De.call(this,t,N)},edgemouseleave(N){De.call(this,t,N)}}})});var x=z(p,2);{var C=m=>{mc(m,{onMount:()=>{ai(l,!0)},onDestroy:()=>{ai(l,!1)}})};ke(x,m=>{o().length>0&&m(C)})}Z(f),L(e,f);var $=ce({get defaultEdgeOptions(){return s()},set defaultEdgeOptions(m){s(m),y()}});return r(),$}ie(_c,{defaultEdgeOptions:{}},[],[],!0);var _2=ne('');const x2={hash:"svelte-1iugwpu",code:".svelte-flow__selection.svelte-1iugwpu {position:absolute;top:0;left:0;}"};function ua(e,t){ue(t,!1),et(e,x2);let n=w(t,"x",12,0),r=w(t,"y",12,0),o=w(t,"width",12,0),i=w(t,"height",12,0),s=w(t,"isVisible",12,!0);var a=tt(),l=xe(a);{var u=c=>{var f=_2();Ee(()=>{at(f,"width",typeof o()=="string"?o():`${o()}px`),at(f,"height",typeof i()=="string"?i():`${i()}px`),at(f,"transform",`translate(${n()}px, ${r()}px)`)}),L(c,f)};ke(l,c=>{s()&&c(u)})}return L(e,a),ce({get x(){return n()},set x(c){n(c),y()},get y(){return r()},set y(c){r(c),y()},get width(){return o()},set width(c){o(c),y()},get height(){return i()},set height(c){i(c),y()},get isVisible(){return s()},set isVisible(c){s(c),y()}})}ie(ua,{x:{},y:{},width:{},height:{},isVisible:{}},[],[],!0);function xc(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(s,"$selectionRect",n),i=()=>Q(a,"$selectionRectMode",n),{selectionRect:s,selectionRectMode:a}=Ue();He();const l=ve(()=>!!(o()&&i()==="user")),u=ve(()=>{var g;return(g=o())==null?void 0:g.width}),c=ve(()=>{var g;return(g=o())==null?void 0:g.height}),f=ve(()=>{var g;return(g=o())==null?void 0:g.x}),d=ve(()=>{var g;return(g=o())==null?void 0:g.y});ua(e,{get isVisible(){return h(l)},get width(){return h(u)},get height(){return h(c)},get x(){return h(f)},get y(){return h(d)}}),ce(),r()}ie(xc,{},[],[],!0);var b2=ne('');const C2={hash:"svelte-5pxri",code:".selection-wrapper.svelte-5pxri {position:absolute;top:0;left:0;z-index:7;pointer-events:all;}"};function bc(e,t){ue(t,!1),et(e,C2);const[n,r]=nt(),o=()=>Q(l,"$selectionRectMode",n),i=()=>Q(c,"$nodeLookup",n),s=()=>Q(u,"$nodes",n),a=Ue(),{selectionRectMode:l,nodes:u,nodeLookup:c}=a,f=ii();let d=re(null);function g(m){const _=s().filter(v=>v.selected);f("selectioncontextmenu",{nodes:_,event:m})}function p(m){const _=s().filter(v=>v.selected);f("selectionclick",{nodes:_,event:m})}ge(()=>(o(),i(),s()),()=>{o()==="nodes"&&(U(d,bo(i(),{filter:m=>!!m.selected})),s())}),vt(),He();var x=tt(),C=xe(x);{var $=m=>{var _=b2(),v=X(_);ua(v,{width:"100%",height:"100%",x:0,y:0}),Z(_),_t(_,(b,N)=>Br==null?void 0:Br(b,N),()=>({disabled:!1,store:a,onDrag:(b,N,E,T)=>{f("nodedrag",{event:b,targetNode:null,nodes:T})},onDragStart:(b,N,E,T)=>{f("nodedragstart",{event:b,targetNode:null,nodes:T})},onDragStop:(b,N,E,T)=>{f("nodedragstop",{event:b,targetNode:null,nodes:T})}})),Rt(()=>Ze("contextmenu",_,g)),Rt(()=>Ze("click",_,p)),Rt(()=>Ze("keyup",_,()=>{})),Ee(()=>de(_,"style",`width: ${h(d).width??""}px; height: ${h(d).height??""}px; transform: translate(${h(d).x??""}px, ${h(d).y??""}px)`)),L(m,_)};ke(C,m=>{o()==="nodes"&&h(d)&&zn(h(d).x)&&zn(h(d).y)&&m($)})}L(e,x),ce(),r()}ie(bc,{},[],[],!0);function qe(e,t){let{enabled:n=!0,trigger:r,type:o="keydown"}=t;function i(s){const a=Array.isArray(r)?r:[r],l={alt:s.altKey,ctrl:s.ctrlKey,shift:s.shiftKey,meta:s.metaKey};for(const u of a){const c={modifier:[],preventDefault:!1,enabled:!0,...u},{modifier:f,key:d,callback:g,preventDefault:p,enabled:x}=c;if(x){if(f.length&&!(Array.isArray(f)?f:[f]).map(m=>typeof m=="string"?[m]:m).some(m=>m.every(_=>l[_])))continue;if(s.key===d){p&&s.preventDefault();const C={node:e,trigger:c,originalEvent:s};e.dispatchEvent(new CustomEvent("shortcut",{detail:C})),g==null||g(C)}}}}return n&&e.addEventListener(o,i),{update:s=>{const{enabled:a=!0,type:l="keydown"}=s;n&&(!a||o!==l)?e.removeEventListener(o,i):!n&&a&&e.addEventListener(l,i),n=a,o=l,r=s.trigger},destroy:()=>{e.removeEventListener(o,i)}}}function Cc(e,t){ue(t,!1);let n=w(t,"selectionKey",12,"Shift"),r=w(t,"multiSelectionKey",28,()=>Di()?"Meta":"Control"),o=w(t,"deleteKey",12,"Backspace"),i=w(t,"panActivationKey",12," "),s=w(t,"zoomActivationKey",28,()=>Di()?"Meta":"Control");const{selectionKeyPressed:a,multiselectionKeyPressed:l,deleteKeyPressed:u,panActivationKeyPressed:c,zoomActivationKeyPressed:f,selectionRect:d}=Ue();function g(m){return m!==null&&typeof m=="object"}function p(m){return g(m)?m.modifier||[]:[]}function x(m){return m==null?"":g(m)?m.key:m}function C(m,_){return(Array.isArray(m)?m:[m]).map(b=>{const N=x(b);return{key:N,modifier:p(b),enabled:N!==null,callback:_}})}function $(){d.set(null),a.set(!1),l.set(!1),u.set(!1),c.set(!1),f.set(!1)}return He(),Ze("blur",Vt,$),Ze("contextmenu",Vt,$),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(n(),()=>a.set(!0)),type:"keydown"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(n(),()=>a.set(!1)),type:"keyup"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(r(),()=>l.set(!0)),type:"keydown"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(r(),()=>l.set(!1)),type:"keyup"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(o(),m=>{!(m.originalEvent.ctrlKey||m.originalEvent.metaKey||m.originalEvent.shiftKey)&&!r0(m.originalEvent)&&u.set(!0)}),type:"keydown"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(o(),()=>u.set(!1)),type:"keyup"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(i(),()=>c.set(!0)),type:"keydown"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(i(),()=>c.set(!1)),type:"keyup"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(s(),()=>f.set(!0)),type:"keydown"})),_t(Vt,(m,_)=>qe==null?void 0:qe(m,_),()=>({trigger:C(s(),()=>f.set(!1)),type:"keyup"})),ce({get selectionKey(){return n()},set selectionKey(m){n(m),y()},get multiSelectionKey(){return r()},set multiSelectionKey(m){r(m),y()},get deleteKey(){return o()},set deleteKey(m){o(m),y()},get panActivationKey(){return i()},set panActivationKey(m){i(m),y()},get zoomActivationKey(){return s()},set zoomActivationKey(m){s(m),y()}})}ie(Cc,{selectionKey:{},multiSelectionKey:{},deleteKey:{},panActivationKey:{},zoomActivationKey:{}},[],[],!0);var k2=_e(''),$2=_e('');function kc(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(g,"$connection",n),i=()=>Q(p,"$connectionLineType",n),s=()=>Q(f,"$width",n),a=()=>Q(d,"$height",n);let l=w(t,"containerStyle",12,""),u=w(t,"style",12,""),c=w(t,"isCustomComponent",12,!1);const{width:f,height:d,connection:g,connectionLineType:p}=Ue();let x=re(null);ge(()=>(o(),j(c()),i(),h(x),ea),()=>{if(o().inProgress&&!c()){const{from:v,to:b,fromPosition:N,toPosition:E}=o(),T={sourceX:v.x,sourceY:v.y,sourcePosition:N,targetX:b.x,targetY:b.y,targetPosition:E};switch(i()){case Ar.Bezier:(D=>U(x,D[0]))(Tu(T));break;case Ar.Step:(D=>U(x,D[0]))(Li({...T,borderRadius:0}));break;case Ar.SmoothStep:(D=>U(x,D[0]))(Li(T));break;default:(D=>U(x,D[0]))(ea(T))}}}),vt(),He();var C=tt(),$=xe(C);{var m=v=>{var b=$2(),N=X(b),E=X(N);wt(E,t,"connectionLine",{});var T=z(E);{var D=V=>{var A=k2();Ee(()=>{de(A,"d",h(x)),de(A,"style",u())}),L(V,A)};ke(T,V=>{c()||V(D)})}Z(N),Z(b),Ee(V=>{de(b,"width",s()),de(b,"height",a()),de(b,"style",l()),$t(N,0,wn(V))},[()=>Et(["svelte-flow__connection",qv(o().isValid)])],ve),L(v,b)};ke($,v=>{o().inProgress&&v(m)})}L(e,C);var _=ce({get containerStyle(){return l()},set containerStyle(v){l(v),y()},get style(){return u()},set style(v){u(v),y()},get isCustomComponent(){return c()},set isCustomComponent(v){c(v),y()}});return r(),_}ie(kc,{containerStyle:{},style:{},isCustomComponent:{}},["connectionLine"],[],!0);var E2=ne("");function So(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]),r=it(n,["position","style","class"]);ue(t,!1);const[o,i]=nt(),s=()=>Q(f,"$selectionRectMode",o),a=re();let l=w(t,"position",12,"top-right"),u=w(t,"style",12,void 0),c=w(t,"class",12,void 0);const{selectionRectMode:f}=Ue();ge(()=>j(l()),()=>{U(a,`${l()}`.split("-"))}),vt(),He();var d=E2();let g;var p=X(d);wt(p,t,"default",{}),Z(d),Ee(C=>{g=nn(d,g,{class:C,style:u(),...r}),at(d,"pointer-events",s()?"none":"")},[()=>Et(["svelte-flow__panel",c(),...h(a)])],ve),L(e,d);var x=ce({get position(){return l()},set position(C){l(C),y()},get style(){return u()},set style(C){u(C),y()},get class(){return c()},set class(C){c(C),y()}});return i(),x}ie(So,{position:{},style:{},class:{}},["default"],[],!0);var S2=ne('Svelte Flow');function $c(e,t){ue(t,!1);let n=w(t,"proOptions",12,void 0),r=w(t,"position",12,"bottom-right");He();var o=tt(),i=xe(o);{var s=a=>{So(a,{get position(){return r()},class:"svelte-flow__attribution","data-message":"Feel free to remove the attribution or check out how you could support us: https://svelteflow.dev/support-us",children:(l,u)=>{var c=S2();L(l,c)},$$slots:{default:!0}})};ke(i,a=>{var l;(l=n())!=null&&l.hideAttribution||a(s)})}return L(e,o),ce({get proOptions(){return n()},set proOptions(a){n(a),y()},get position(){return r()},set position(a){r(a),y()}})}ie($c,{proOptions:{},position:{}},[],[],!0);function Ec(e,{nodeTypes:t,edgeTypes:n,minZoom:r,maxZoom:o,translateExtent:i,paneClickDistance:s}){t!==void 0&&e.setNodeTypes(t),n!==void 0&&e.setEdgeTypes(n),r!==void 0&&e.setMinZoom(r),o!==void 0&&e.setMaxZoom(o),i!==void 0&&e.setTranslateExtent(i),s!==void 0&&e.setPaneClickDistance(s)}const P2=e=>Object.keys(e);function Sc(e,t){P2(t).forEach(n=>{const r=t[n];r!==void 0&&e[n].set(r)})}function N2(){return typeof window>"u"||!window.matchMedia?null:window.matchMedia("(prefers-color-scheme: dark)")}function T2(e="light"){return Gt("light",n=>{if(e!=="system"){n(e);return}const r=N2(),o=()=>n(r!=null&&r.matches?"dark":"light");return n(r!=null&&r.matches?"dark":"light"),r==null||r.addEventListener("change",o),()=>{r==null||r.removeEventListener("change",o)}})}var M2=ne(' ',1),H2=ne(" ",1),V2=ne("
");const D2={hash:"svelte-12wlba6",code:".svelte-flow.svelte-12wlba6 {width:100%;height:100%;overflow:hidden;position:relative;z-index:0;background-color:var(--background-color, var(--background-color-default));}:root {--background-color-default: #fff;--background-pattern-color-default: #ddd;--minimap-mask-color-default: rgb(240, 240, 240, 0.6);--minimap-mask-stroke-color-default: none;--minimap-mask-stroke-width-default: 1;--controls-button-background-color-default: #fefefe;--controls-button-background-color-hover-default: #f4f4f4;--controls-button-color-default: inherit;--controls-button-color-hover-default: inherit;--controls-button-border-color-default: #eee;}"};function Pc(e,t){const n=e1(t),r=it(t,["children","$$slots","$$events","$$legacy","$$host"]),o=it(r,["id","nodes","edges","fitView","fitViewOptions","minZoom","maxZoom","initialViewport","viewport","nodeTypes","edgeTypes","selectionKey","selectionMode","panActivationKey","multiSelectionKey","zoomActivationKey","nodesDraggable","nodesConnectable","nodeDragThreshold","elementsSelectable","snapGrid","deleteKey","connectionRadius","connectionLineType","connectionMode","connectionLineStyle","connectionLineContainerStyle","onMoveStart","onMove","onMoveEnd","isValidConnection","translateExtent","nodeExtent","onlyRenderVisibleElements","panOnScrollMode","preventScrolling","zoomOnScroll","zoomOnDoubleClick","zoomOnPinch","panOnScroll","panOnDrag","selectionOnDrag","autoPanOnConnect","autoPanOnNodeDrag","onerror","ondelete","onedgecreate","attributionPosition","proOptions","defaultEdgeOptions","width","height","colorMode","onconnect","onconnectstart","onconnectend","onbeforedelete","oninit","nodeOrigin","paneClickDistance","nodeClickDistance","defaultMarkerColor","style","class"]);ue(t,!1),et(e,D2);const[i,s]=nt(),a=()=>Q(_(),"$viewport",i),l=()=>Q(xa,"$initialized",i),u=()=>Q(h(c),"$colorModeClass",i),c=re();let f=w(t,"id",12,"1"),d=w(t,"nodes",12),g=w(t,"edges",12),p=w(t,"fitView",12,void 0),x=w(t,"fitViewOptions",12,void 0),C=w(t,"minZoom",12,void 0),$=w(t,"maxZoom",12,void 0),m=w(t,"initialViewport",12,void 0),_=w(t,"viewport",12,void 0),v=w(t,"nodeTypes",12,void 0),b=w(t,"edgeTypes",12,void 0),N=w(t,"selectionKey",12,void 0),E=w(t,"selectionMode",12,void 0),T=w(t,"panActivationKey",12,void 0),D=w(t,"multiSelectionKey",12,void 0),V=w(t,"zoomActivationKey",12,void 0),A=w(t,"nodesDraggable",12,void 0),O=w(t,"nodesConnectable",12,void 0),R=w(t,"nodeDragThreshold",12,void 0),S=w(t,"elementsSelectable",12,void 0),M=w(t,"snapGrid",12,void 0),k=w(t,"deleteKey",12,void 0),P=w(t,"connectionRadius",12,void 0),H=w(t,"connectionLineType",12,void 0),I=w(t,"connectionMode",28,()=>hr.Strict),B=w(t,"connectionLineStyle",12,""),F=w(t,"connectionLineContainerStyle",12,""),K=w(t,"onMoveStart",12,void 0),se=w(t,"onMove",12,void 0),ee=w(t,"onMoveEnd",12,void 0),W=w(t,"isValidConnection",12,void 0),fe=w(t,"translateExtent",12,void 0),me=w(t,"nodeExtent",12,void 0),Ce=w(t,"onlyRenderVisibleElements",12,void 0),he=w(t,"panOnScrollMode",28,()=>Jn.Free),ze=w(t,"preventScrolling",12,!0),G=w(t,"zoomOnScroll",12,!0),ae=w(t,"zoomOnDoubleClick",12,!0),Me=w(t,"zoomOnPinch",12,!0),Le=w(t,"panOnScroll",12,!1),Xe=w(t,"panOnDrag",12,!0),te=w(t,"selectionOnDrag",12,void 0),Fe=w(t,"autoPanOnConnect",12,!0),Oe=w(t,"autoPanOnNodeDrag",12,!0),rt=w(t,"onerror",12,void 0),oe=w(t,"ondelete",12,void 0),pe=w(t,"onedgecreate",12,void 0),be=w(t,"attributionPosition",12,void 0),Ie=w(t,"proOptions",12,void 0),ht=w(t,"defaultEdgeOptions",12,void 0),dt=w(t,"width",12,void 0),J=w(t,"height",12,void 0),Re=w(t,"colorMode",12,"light"),le=w(t,"onconnect",12,void 0),$n=w(t,"onconnectstart",12,void 0),fn=w(t,"onconnectend",12,void 0),En=w(t,"onbeforedelete",12,void 0),Te=w(t,"oninit",12,void 0),st=w(t,"nodeOrigin",12,void 0),ye=w(t,"paneClickDistance",12,0),lt=w(t,"nodeClickDistance",12,0),ct=w(t,"defaultMarkerColor",12,"#b1b1b7"),Jt=w(t,"style",12,void 0),Oo=w(t,"class",12,void 0),Wt=re(),Ot=re(),Sn=re();const gn=a()||m(),mt=Df(Ri)?Ue():r2({nodes:q(d()),edges:q(g()),width:dt(),height:J(),fitView:p(),nodeOrigin:st(),nodeExtent:me()});rn(()=>(mt.width.set(h(Ot)),mt.height.set(h(Sn)),mt.domNode.set(h(Wt)),mt.syncNodeStores(d()),mt.syncEdgeStores(g()),mt.syncViewport(_()),p()!==void 0&&mt.fitViewOnInit.set(p()),x()&&mt.fitViewOptions.set(x()),Ec(mt,{nodeTypes:v(),edgeTypes:b(),minZoom:C(),maxZoom:$(),translateExtent:fe(),paneClickDistance:ye()}),()=>{mt.reset()}));const{initialized:xa}=mt;let yr=re(!1);ge(()=>(h(Ot),h(Sn)),()=>{h(Ot)!==void 0&&h(Sn)!==void 0&&(mt.width.set(h(Ot)),mt.height.set(h(Sn)))}),ge(()=>(h(yr),l(),j(Te())),()=>{var Y;!h(yr)&&l()&&((Y=Te())==null||Y(),U(yr,!0))}),ge(()=>(j(f()),j(H()),j(P()),j(E()),j(M()),j(ct()),j(A()),j(O()),j(S()),j(Ce()),j(W()),j(Fe()),j(Oe()),j(rt()),j(oe()),j(pe()),j(I()),j(R()),j(le()),j($n()),j(fn()),j(En()),j(st()),Sc),()=>{const Y={flowId:f(),connectionLineType:H(),connectionRadius:P(),selectionMode:E(),snapGrid:M(),defaultMarkerColor:ct(),nodesDraggable:A(),nodesConnectable:O(),elementsSelectable:S(),onlyRenderVisibleElements:Ce(),isValidConnection:W(),autoPanOnConnect:Fe(),autoPanOnNodeDrag:Oe(),onerror:rt(),ondelete:oe(),onedgecreate:pe(),connectionMode:I(),nodeDragThreshold:R(),onconnect:le(),onconnectstart:$n(),onconnectend:fn(),onbeforedelete:En(),nodeOrigin:st()};Sc(mt,Y)}),ge(()=>(j(v()),j(b()),j(C()),j($()),j(fe()),j(ye())),()=>{Ec(mt,{nodeTypes:v(),edgeTypes:b(),minZoom:C(),maxZoom:$(),translateExtent:fe(),paneClickDistance:ye()})}),ge(()=>j(Re()),()=>{l1(U(c,T2(Re())),"$colorModeClass",i)}),vt(),He();var hn=V2();let ji;var Ji=X(hn);Cc(Ji,{get selectionKey(){return N()},get deleteKey(){return k()},get panActivationKey(){return T()},get multiSelectionKey(){return D()},get zoomActivationKey(){return V()}});var Qi=z(Ji,2);const jy=ve(()=>he()===void 0?Jn.Free:he()),Jy=ve(()=>ze()===void 0?!0:ze()),Qy=ve(()=>G()===void 0?!0:G()),ew=ve(()=>ae()===void 0?!0:ae()),tw=ve(()=>Me()===void 0?!0:Me()),nw=ve(()=>Le()===void 0?!1:Le()),rw=ve(()=>Xe()===void 0?!0:Xe()),ow=ve(()=>ye()===void 0?0:ye());uc(Qi,{initialViewport:gn,get onMoveStart(){return K()},get onMove(){return se()},get onMoveEnd(){return ee()},get panOnScrollMode(){return h(jy)},get preventScrolling(){return h(Jy)},get zoomOnScroll(){return h(Qy)},get zoomOnDoubleClick(){return h(ew)},get zoomOnPinch(){return h(tw)},get panOnScroll(){return h(nw)},get panOnDrag(){return h(rw)},get paneClickDistance(){return h(ow)},children:(Y,pw)=>{const aw=ve(()=>Xe()===void 0?!0:Xe());fc(Y,{get panOnDrag(){return h(aw)},get selectionOnDrag(){return te()},$$events:{paneclick(Io){De.call(this,t,Io)},panecontextmenu(Io){De.call(this,t,Io)}},children:(Io,mw)=>{var Vd=H2(),Dd=xe(Vd);gc(Dd,{children:(uw,yw)=>{var Ad=M2(),Ld=xe(Ad);_c(Ld,{get defaultEdgeOptions(){return ht()},$$events:{edgeclick(Be){De.call(this,t,Be)},edgecontextmenu(Be){De.call(this,t,Be)},edgemouseenter(Be){De.call(this,t,Be)},edgemouseleave(Be){De.call(this,t,Be)}}});var Od=z(Ld,2);kc(Od,{get containerStyle(){return F()},get style(){return B()},isCustomComponent:n.connectionLine,$$slots:{connectionLine:(Be,ww)=>{var zd=tt(),dw=xe(zd);wt(dw,t,"connectionLine",{}),L(Be,zd)}}});var Id=z(Od,6);vc(Id,{get nodeClickDistance(){return lt()},$$events:{nodeclick(Be){De.call(this,t,Be)},nodemouseenter(Be){De.call(this,t,Be)},nodemousemove(Be){De.call(this,t,Be)},nodemouseleave(Be){De.call(this,t,Be)},nodedragstart(Be){De.call(this,t,Be)},nodedrag(Be){De.call(this,t,Be)},nodedragstop(Be){De.call(this,t,Be)},nodecontextmenu(Be){De.call(this,t,Be)}}});var cw=z(Id,2);bc(cw,{$$events:{selectionclick(Be){De.call(this,t,Be)},selectioncontextmenu(Be){De.call(this,t,Be)},nodedragstart(Be){De.call(this,t,Be)},nodedrag(Be){De.call(this,t,Be)},nodedragstop(Be){De.call(this,t,Be)}}}),L(uw,Ad)},$$slots:{default:!0}});var lw=z(Dd,2);xc(lw,{}),L(Io,Vd)},$$slots:{default:!0}})},$$slots:{default:!0}});var Hd=z(Qi,2);$c(Hd,{get proOptions(){return Ie()},get position(){return be()}});var iw=z(Hd,2);wt(iw,t,"default",{}),Z(hn),An(hn,Y=>U(Wt,Y),()=>h(Wt)),Ee(Y=>ji=nn(hn,ji,{style:Jt(),class:Y,"data-testid":"svelte-flow__wrapper",...o,role:"application"},"svelte-12wlba6"),[()=>Et(["svelte-flow",Oo(),u()])],ve),ml(hn,"clientWidth",Y=>U(Ot,Y)),ml(hn,"clientHeight",Y=>U(Sn,Y)),Ze("dragover",hn,function(Y){De.call(this,t,Y)}),Ze("drop",hn,function(Y){De.call(this,t,Y)}),L(e,hn);var sw=ce({get id(){return f()},set id(Y){f(Y),y()},get nodes(){return d()},set nodes(Y){d(Y),y()},get edges(){return g()},set edges(Y){g(Y),y()},get fitView(){return p()},set fitView(Y){p(Y),y()},get fitViewOptions(){return x()},set fitViewOptions(Y){x(Y),y()},get minZoom(){return C()},set minZoom(Y){C(Y),y()},get maxZoom(){return $()},set maxZoom(Y){$(Y),y()},get initialViewport(){return m()},set initialViewport(Y){m(Y),y()},get viewport(){return _()},set viewport(Y){_(Y),y()},get nodeTypes(){return v()},set nodeTypes(Y){v(Y),y()},get edgeTypes(){return b()},set edgeTypes(Y){b(Y),y()},get selectionKey(){return N()},set selectionKey(Y){N(Y),y()},get selectionMode(){return E()},set selectionMode(Y){E(Y),y()},get panActivationKey(){return T()},set panActivationKey(Y){T(Y),y()},get multiSelectionKey(){return D()},set multiSelectionKey(Y){D(Y),y()},get zoomActivationKey(){return V()},set zoomActivationKey(Y){V(Y),y()},get nodesDraggable(){return A()},set nodesDraggable(Y){A(Y),y()},get nodesConnectable(){return O()},set nodesConnectable(Y){O(Y),y()},get nodeDragThreshold(){return R()},set nodeDragThreshold(Y){R(Y),y()},get elementsSelectable(){return S()},set elementsSelectable(Y){S(Y),y()},get snapGrid(){return M()},set snapGrid(Y){M(Y),y()},get deleteKey(){return k()},set deleteKey(Y){k(Y),y()},get connectionRadius(){return P()},set connectionRadius(Y){P(Y),y()},get connectionLineType(){return H()},set connectionLineType(Y){H(Y),y()},get connectionMode(){return I()},set connectionMode(Y){I(Y),y()},get connectionLineStyle(){return B()},set connectionLineStyle(Y){B(Y),y()},get connectionLineContainerStyle(){return F()},set connectionLineContainerStyle(Y){F(Y),y()},get onMoveStart(){return K()},set onMoveStart(Y){K(Y),y()},get onMove(){return se()},set onMove(Y){se(Y),y()},get onMoveEnd(){return ee()},set onMoveEnd(Y){ee(Y),y()},get isValidConnection(){return W()},set isValidConnection(Y){W(Y),y()},get translateExtent(){return fe()},set translateExtent(Y){fe(Y),y()},get nodeExtent(){return me()},set nodeExtent(Y){me(Y),y()},get onlyRenderVisibleElements(){return Ce()},set onlyRenderVisibleElements(Y){Ce(Y),y()},get panOnScrollMode(){return he()},set panOnScrollMode(Y){he(Y),y()},get preventScrolling(){return ze()},set preventScrolling(Y){ze(Y),y()},get zoomOnScroll(){return G()},set zoomOnScroll(Y){G(Y),y()},get zoomOnDoubleClick(){return ae()},set zoomOnDoubleClick(Y){ae(Y),y()},get zoomOnPinch(){return Me()},set zoomOnPinch(Y){Me(Y),y()},get panOnScroll(){return Le()},set panOnScroll(Y){Le(Y),y()},get panOnDrag(){return Xe()},set panOnDrag(Y){Xe(Y),y()},get selectionOnDrag(){return te()},set selectionOnDrag(Y){te(Y),y()},get autoPanOnConnect(){return Fe()},set autoPanOnConnect(Y){Fe(Y),y()},get autoPanOnNodeDrag(){return Oe()},set autoPanOnNodeDrag(Y){Oe(Y),y()},get onerror(){return rt()},set onerror(Y){rt(Y),y()},get ondelete(){return oe()},set ondelete(Y){oe(Y),y()},get onedgecreate(){return pe()},set onedgecreate(Y){pe(Y),y()},get attributionPosition(){return be()},set attributionPosition(Y){be(Y),y()},get proOptions(){return Ie()},set proOptions(Y){Ie(Y),y()},get defaultEdgeOptions(){return ht()},set defaultEdgeOptions(Y){ht(Y),y()},get width(){return dt()},set width(Y){dt(Y),y()},get height(){return J()},set height(Y){J(Y),y()},get colorMode(){return Re()},set colorMode(Y){Re(Y),y()},get onconnect(){return le()},set onconnect(Y){le(Y),y()},get onconnectstart(){return $n()},set onconnectstart(Y){$n(Y),y()},get onconnectend(){return fn()},set onconnectend(Y){fn(Y),y()},get onbeforedelete(){return En()},set onbeforedelete(Y){En(Y),y()},get oninit(){return Te()},set oninit(Y){Te(Y),y()},get nodeOrigin(){return st()},set nodeOrigin(Y){st(Y),y()},get paneClickDistance(){return ye()},set paneClickDistance(Y){ye(Y),y()},get nodeClickDistance(){return lt()},set nodeClickDistance(Y){lt(Y),y()},get defaultMarkerColor(){return ct()},set defaultMarkerColor(Y){ct(Y),y()},get style(){return Jt()},set style(Y){Jt(Y),y()},get class(){return Oo()},set class(Y){Oo(Y),y()}});return s(),sw}ie(Pc,{id:{},nodes:{},edges:{},fitView:{},fitViewOptions:{},minZoom:{},maxZoom:{},initialViewport:{},viewport:{},nodeTypes:{},edgeTypes:{},selectionKey:{},selectionMode:{},panActivationKey:{},multiSelectionKey:{},zoomActivationKey:{},nodesDraggable:{},nodesConnectable:{},nodeDragThreshold:{},elementsSelectable:{},snapGrid:{},deleteKey:{},connectionRadius:{},connectionLineType:{},connectionMode:{},connectionLineStyle:{},connectionLineContainerStyle:{},onMoveStart:{},onMove:{},onMoveEnd:{},isValidConnection:{},translateExtent:{},nodeExtent:{},onlyRenderVisibleElements:{},panOnScrollMode:{},preventScrolling:{},zoomOnScroll:{},zoomOnDoubleClick:{},zoomOnPinch:{},panOnScroll:{},panOnDrag:{},selectionOnDrag:{},autoPanOnConnect:{},autoPanOnNodeDrag:{},onerror:{},ondelete:{},onedgecreate:{},attributionPosition:{},proOptions:{},defaultEdgeOptions:{},width:{},height:{},colorMode:{},onconnect:{},onconnectstart:{},onconnectend:{},onbeforedelete:{},oninit:{},nodeOrigin:{},paneClickDistance:{},nodeClickDistance:{},defaultMarkerColor:{},style:{},class:{}},["connectionLine","default"],[],!0);function Nc(e,t){ue(t,!1);let n=w(t,"initialNodes",12,void 0),r=w(t,"initialEdges",12,void 0),o=w(t,"initialWidth",12,void 0),i=w(t,"initialHeight",12,void 0),s=w(t,"fitView",12,void 0),a=w(t,"nodeOrigin",12,void 0);const l=lc({nodes:n(),edges:r(),width:o(),height:i(),nodeOrigin:a(),fitView:s()});Sr(Ri,{getStore:()=>l}),$s(()=>{l.reset()}),He();var u=tt(),c=xe(u);return wt(c,t,"default",{}),L(e,u),ce({get initialNodes(){return n()},set initialNodes(f){n(f),y()},get initialEdges(){return r()},set initialEdges(f){r(f),y()},get initialWidth(){return o()},set initialWidth(f){o(f),y()},get initialHeight(){return i()},set initialHeight(f){i(f),y()},get fitView(){return s()},set fitView(f){s(f),y()},get nodeOrigin(){return a()},set nodeOrigin(f){a(f),y()}})}ie(Nc,{initialNodes:{},initialEdges:{},initialWidth:{},initialHeight:{},fitView:{},nodeOrigin:{}},["default"],[],!0);var A2=ne("");function Po(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]),r=it(n,["class","bgColor","bgColorHover","color","colorHover","borderColor"]);ue(t,!1);let o=w(t,"class",12,void 0),i=w(t,"bgColor",12,void 0),s=w(t,"bgColorHover",12,void 0),a=w(t,"color",12,void 0),l=w(t,"colorHover",12,void 0),u=w(t,"borderColor",12,void 0);He();var c=A2();let f;var d=X(c);return wt(d,t,"default",{class:"button-svg"}),Z(c),Ee(g=>{f=nn(c,f,{type:"button",class:g,...r}),at(c,"--xy-controls-button-background-color-props",i()),at(c,"--xy-controls-button-background-color-hover-props",s()),at(c,"--xy-controls-button-color-props",a()),at(c,"--xy-controls-button-color-hover-props",l()),at(c,"--xy-controls-button-border-color-props",u())},[()=>Et(["svelte-flow__controls-button",o()])],ve),Ze("click",c,function(g){De.call(this,t,g)}),L(e,c),ce({get class(){return o()},set class(g){o(g),y()},get bgColor(){return i()},set bgColor(g){i(g),y()},get bgColorHover(){return s()},set bgColorHover(g){s(g),y()},get color(){return a()},set color(g){a(g),y()},get colorHover(){return l()},set colorHover(g){l(g),y()},get borderColor(){return u()},set borderColor(g){u(g),y()}})}ie(Po,{class:{},bgColor:{},bgColorHover:{},color:{},colorHover:{},borderColor:{}},["default"],[],!0);var L2=_e('');function Tc(e){var t=L2();L(e,t)}ie(Tc,{},[],[],!0);var O2=_e('');function Mc(e){var t=O2();L(e,t)}ie(Mc,{},[],[],!0);var I2=_e('');function Hc(e){var t=I2();L(e,t)}ie(Hc,{},[],[],!0);var z2=_e('');function Vc(e){var t=z2();L(e,t)}ie(Vc,{},[],[],!0);var R2=_e('');function Dc(e){var t=R2();L(e,t)}ie(Dc,{},[],[],!0);var B2=ne(" ",1),Y2=ne(" ",1);function Ac(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(H,"$nodesDraggable",n),i=()=>Q(I,"$nodesConnectable",n),s=()=>Q(B,"$elementsSelectable",n),a=()=>Q(M,"$viewport",n),l=()=>Q(k,"$minZoom",n),u=()=>Q(P,"$maxZoom",n),c=re(),f=re(),d=re(),g=re();let p=w(t,"position",12,"bottom-left"),x=w(t,"showZoom",12,!0),C=w(t,"showFitView",12,!0),$=w(t,"showLock",12,!0),m=w(t,"buttonBgColor",12,void 0),_=w(t,"buttonBgColorHover",12,void 0),v=w(t,"buttonColor",12,void 0),b=w(t,"buttonColorHover",12,void 0),N=w(t,"buttonBorderColor",12,void 0),E=w(t,"ariaLabel",12,void 0),T=w(t,"style",12,void 0),D=w(t,"orientation",12,"vertical"),V=w(t,"fitViewOptions",12,void 0),A=w(t,"class",12,"");const{zoomIn:O,zoomOut:R,fitView:S,viewport:M,minZoom:k,maxZoom:P,nodesDraggable:H,nodesConnectable:I,elementsSelectable:B}=Ue(),F={bgColor:m(),bgColorHover:_(),color:v(),colorHover:b(),borderColor:N()},K=()=>{O()},se=()=>{R()},ee=()=>{S(V())},W=()=>{U(c,!h(c)),H.set(h(c)),I.set(h(c)),B.set(h(c))};ge(()=>(o(),i(),s()),()=>{U(c,o()||i()||s())}),ge(()=>(a(),l()),()=>{U(f,a().zoom<=l())}),ge(()=>(a(),u()),()=>{U(d,a().zoom>=u())}),ge(()=>j(D()),()=>{U(g,D()==="horizontal"?"horizontal":"vertical")}),vt(),He();const fe=ve(()=>Et(["svelte-flow__controls",h(g),A()])),me=ve(()=>E()??"Svelte Flow controls");So(e,{get class(){return h(fe)},get position(){return p()},"data-testid":"svelte-flow__controls",get"aria-label"(){return h(me)},get style(){return T()},children:(he,ze)=>{var G=Y2(),ae=xe(G);wt(ae,t,"before",{});var Me=z(ae,2);{var Le=pe=>{var be=B2(),Ie=xe(be);Po(Ie,ft({class:"svelte-flow__controls-zoomin",title:"zoom in","aria-label":"zoom in",get disabled(){return h(d)}},F,{$$events:{click:K},children:(dt,J)=>{Tc(dt)},$$slots:{default:!0}}));var ht=z(Ie,2);Po(ht,ft({class:"svelte-flow__controls-zoomout",title:"zoom out","aria-label":"zoom out",get disabled(){return h(f)}},F,{$$events:{click:se},children:(dt,J)=>{Mc(dt)},$$slots:{default:!0}})),L(pe,be)};ke(Me,pe=>{x()&&pe(Le)})}var Xe=z(Me,2);{var te=pe=>{Po(pe,ft({class:"svelte-flow__controls-fitview",title:"fit view","aria-label":"fit view"},F,{$$events:{click:ee},children:(be,Ie)=>{Hc(be)},$$slots:{default:!0}}))};ke(Xe,pe=>{C()&&pe(te)})}var Fe=z(Xe,2);{var Oe=pe=>{Po(pe,ft({class:"svelte-flow__controls-interactive",title:"toggle interactivity","aria-label":"toggle interactivity"},F,{$$events:{click:W},children:(be,Ie)=>{var ht=tt(),dt=xe(ht);{var J=le=>{Dc(le)},Re=le=>{Vc(le)};ke(dt,le=>{h(c)?le(J):le(Re,!1)})}L(be,ht)},$$slots:{default:!0}}))};ke(Fe,pe=>{$()&&pe(Oe)})}var rt=z(Fe,2);wt(rt,t,"default",{});var oe=z(rt,2);wt(oe,t,"after",{}),L(he,G)},$$slots:{default:!0}});var Ce=ce({get position(){return p()},set position(he){p(he),y()},get showZoom(){return x()},set showZoom(he){x(he),y()},get showFitView(){return C()},set showFitView(he){C(he),y()},get showLock(){return $()},set showLock(he){$(he),y()},get buttonBgColor(){return m()},set buttonBgColor(he){m(he),y()},get buttonBgColorHover(){return _()},set buttonBgColorHover(he){_(he),y()},get buttonColor(){return v()},set buttonColor(he){v(he),y()},get buttonColorHover(){return b()},set buttonColorHover(he){b(he),y()},get buttonBorderColor(){return N()},set buttonBorderColor(he){N(he),y()},get ariaLabel(){return E()},set ariaLabel(he){E(he),y()},get style(){return T()},set style(he){T(he),y()},get orientation(){return D()},set orientation(he){D(he),y()},get fitViewOptions(){return V()},set fitViewOptions(he){V(he),y()},get class(){return A()},set class(he){A(he),y()}});return r(),Ce}ie(Ac,{position:{},showZoom:{},showFitView:{},showLock:{},buttonBgColor:{},buttonBgColorHover:{},buttonColor:{},buttonColorHover:{},buttonBorderColor:{},ariaLabel:{},style:{},orientation:{},fitViewOptions:{},class:{}},["before","default","after"],[],!0);var tr;(function(e){e.Lines="lines",e.Dots="dots",e.Cross="cross"})(tr||(tr={}));var Z2=_e("");function Lc(e,t){ue(t,!1);let n=w(t,"radius",12,5),r=w(t,"class",12,"");He();var o=Z2();return Ee(i=>{de(o,"cx",n()),de(o,"cy",n()),de(o,"r",n()),$t(o,0,wn(i))},[()=>Et(["svelte-flow__background-pattern","dots",r()])],ve),L(e,o),ce({get radius(){return n()},set radius(i){n(i),y()},get class(){return r()},set class(i){r(i),y()}})}ie(Lc,{radius:{},class:{}},[],[],!0);var X2=_e("");function Oc(e,t){ue(t,!1);let n=w(t,"lineWidth",12,1),r=w(t,"dimensions",12),o=w(t,"variant",12,void 0),i=w(t,"class",12,"");He();var s=X2();return Ee(a=>{de(s,"stroke-width",n()),de(s,"d",`M${r()[0]/2} 0 V${r()[1]} M0 ${r()[1]/2} H${r()[0]}`),$t(s,0,wn(a))},[()=>Et(["svelte-flow__background-pattern",o(),i()])],ve),L(e,s),ce({get lineWidth(){return n()},set lineWidth(a){n(a),y()},get dimensions(){return r()},set dimensions(a){r(a),y()},get variant(){return o()},set variant(a){o(a),y()},get class(){return i()},set class(a){i(a),y()}})}ie(Oc,{lineWidth:{},dimensions:{},variant:{},class:{}},[],[],!0);const F2={[tr.Dots]:1,[tr.Lines]:1,[tr.Cross]:6};var W2=_e('');const K2={hash:"svelte-1r7pe8d",code:".svelte-flow__background.svelte-1r7pe8d {position:absolute;width:100%;height:100%;top:0;left:0;}"};function Ic(e,t){ue(t,!1),et(e,K2);const[n,r]=nt(),o=()=>Q(b,"$flowId",n),i=()=>Q(v,"$viewport",n),s=re(),a=re(),l=re(),u=re(),c=re();let f=w(t,"id",12,void 0),d=w(t,"variant",28,()=>tr.Dots),g=w(t,"gap",12,20),p=w(t,"size",12,1),x=w(t,"lineWidth",12,1),C=w(t,"bgColor",12,void 0),$=w(t,"patternColor",12,void 0),m=w(t,"patternClass",12,void 0),_=w(t,"class",12,"");const{viewport:v,flowId:b}=Ue(),N=p()||F2[d()],E=d()===tr.Dots,T=d()===tr.Cross,D=Array.isArray(g())?g():[g(),g()];ge(()=>(o(),j(f())),()=>{U(s,`background-pattern-${o()}-${f()?f():""}`)}),ge(()=>i(),()=>{U(a,[D[0]*i().zoom||1,D[1]*i().zoom||1])}),ge(()=>i(),()=>{U(l,N*i().zoom)}),ge(()=>(h(l),h(a)),()=>{U(u,T?[h(l),h(l)]:h(a))}),ge(()=>(h(l),h(u)),()=>{U(c,E?[h(l)/2,h(l)/2]:[h(u)[0]/2,h(u)[1]/2])}),vt(),He();var V=W2(),A=X(V),O=X(A);{var R=P=>{const H=ve(()=>h(l)/2);Lc(P,{get radius(){return h(H)},get class(){return m()}})},S=P=>{Oc(P,{get dimensions(){return h(u)},get variant(){return d()},get lineWidth(){return x()},get class(){return m()}})};ke(O,P=>{E?P(R):P(S,!1)})}Z(A);var M=z(A);Z(V),Ee(P=>{$t(V,0,wn(P),"svelte-1r7pe8d"),at(V,"--xy-background-color-props",C()),at(V,"--xy-background-pattern-color-props",$()),de(A,"id",h(s)),de(A,"x",i().x%h(a)[0]),de(A,"y",i().y%h(a)[1]),de(A,"width",h(a)[0]),de(A,"height",h(a)[1]),de(A,"patternTransform",`translate(-${h(c)[0]},-${h(c)[1]})`),de(M,"fill",`url(#${h(s)})`)},[()=>Et(["svelte-flow__background",_()])],ve),L(e,V);var k=ce({get id(){return f()},set id(P){f(P),y()},get variant(){return d()},set variant(P){d(P),y()},get gap(){return g()},set gap(P){g(P),y()},get size(){return p()},set size(P){p(P),y()},get lineWidth(){return x()},set lineWidth(P){x(P),y()},get bgColor(){return C()},set bgColor(P){C(P),y()},get patternColor(){return $()},set patternColor(P){$(P),y()},get patternClass(){return m()},set patternClass(P){m(P),y()},get class(){return _()},set class(P){_(P),y()}});return r(),k}ie(Ic,{id:{},variant:{},gap:{},size:{},lineWidth:{},bgColor:{},patternColor:{},patternClass:{},class:{}},[],[],!0);var q2=_e("");function zc(e,t){ue(t,!1);let n=w(t,"x",12),r=w(t,"y",12),o=w(t,"width",12,0),i=w(t,"height",12,0),s=w(t,"borderRadius",12,5),a=w(t,"color",12,void 0),l=w(t,"shapeRendering",12),u=w(t,"strokeColor",12,void 0),c=w(t,"strokeWidth",12,2),f=w(t,"selected",12,!1),d=w(t,"class",12,"");He();var g=q2();let p;return Ee(x=>{p=$t(g,0,wn(x),null,p,{selected:f()}),de(g,"x",n()),de(g,"y",r()),de(g,"rx",s()),de(g,"ry",s()),de(g,"width",o()),de(g,"height",i()),de(g,"style",`${a()?`fill: ${a()};`:""}${u()?`stroke: ${u()};`:""}${c()?`stroke-width: ${c()};`:""}`),de(g,"shape-rendering",l())},[()=>Et(["svelte-flow__minimap-node",d()])],ve),L(e,g),ce({get x(){return n()},set x(x){n(x),y()},get y(){return r()},set y(x){r(x),y()},get width(){return o()},set width(x){o(x),y()},get height(){return i()},set height(x){i(x),y()},get borderRadius(){return s()},set borderRadius(x){s(x),y()},get color(){return a()},set color(x){a(x),y()},get shapeRendering(){return l()},set shapeRendering(x){l(x),y()},get strokeColor(){return u()},set strokeColor(x){u(x),y()},get strokeWidth(){return c()},set strokeWidth(x){c(x),y()},get selected(){return f()},set selected(x){f(x),y()},get class(){return d()},set class(x){d(x),y()}})}ie(zc,{x:{},y:{},width:{},height:{},borderRadius:{},color:{},shapeRendering:{},strokeColor:{},strokeWidth:{},selected:{},class:{}},[],[],!0);function ca(e,t){const n=H0({domNode:e,panZoom:t.panZoom,getTransform:()=>{const o=q(t.viewport);return[o.x,o.y,o.zoom]},getViewScale:t.getViewScale});function r(o){n.update({translateExtent:o.translateExtent,width:o.width,height:o.height,inversePan:o.inversePan,zoomStep:o.zoomStep,pannable:o.pannable,zoomable:o.zoomable})}return{update:r,destroy(){n.destroy()}}}const da=e=>e instanceof Function?e:()=>e;var G2=_e(" "),U2=_e('');function Rc(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(Xe,"$flowId",n),i=()=>Q(ae,"$viewport",n),s=()=>Q(Me,"$containerWidth",n),a=()=>Q(Le,"$containerHeight",n),l=()=>Q(G,"$nodeLookup",n),u=()=>Q(ze,"$nodes",n),c=()=>Q(te,"$panZoom",n),f=()=>Q(Fe,"$translateExtent",n),d=re(),g=re(),p=re(),x=re(),C=re(),$=re(),m=re(),_=re(),v=re(),b=re(),N=re(),E=re(),T=re();let D=w(t,"position",12,"bottom-right"),V=w(t,"ariaLabel",12,"Mini map"),A=w(t,"nodeStrokeColor",12,"transparent"),O=w(t,"nodeColor",12,void 0),R=w(t,"nodeClass",12,""),S=w(t,"nodeBorderRadius",12,5),M=w(t,"nodeStrokeWidth",12,2),k=w(t,"bgColor",12,void 0),P=w(t,"maskColor",12,void 0),H=w(t,"maskStrokeColor",12,void 0),I=w(t,"maskStrokeWidth",12,void 0),B=w(t,"width",12,void 0),F=w(t,"height",12,void 0),K=w(t,"pannable",12,!0),se=w(t,"zoomable",12,!0),ee=w(t,"inversePan",12,void 0),W=w(t,"zoomStep",12,void 0),fe=w(t,"style",12,""),me=w(t,"class",12,"");const Ce=200,he=150,{nodes:ze,nodeLookup:G,viewport:ae,width:Me,height:Le,flowId:Xe,panZoom:te,translateExtent:Fe}=Ue(),Oe=O()===void 0?void 0:da(O()),rt=da(A()),oe=da(R()),pe=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision",be=`svelte-flow__minimap-desc-${o()}`;let Ie=re(h(d));const ht=()=>h($);ge(()=>(i(),s(),a()),()=>{U(d,{x:-i().x/i().zoom,y:-i().y/i().zoom,width:s()/i().zoom,height:a()/i().zoom})}),ge(()=>(l(),h(d),u()),()=>{U(Ie,l().size>0?Cu(bo(l()),h(d)):h(d)),u()}),ge(()=>j(B()),()=>{U(g,B()??Ce)}),ge(()=>j(F()),()=>{U(p,F()??he)}),ge(()=>(h(Ie),h(g)),()=>{U(x,h(Ie).width/h(g))}),ge(()=>(h(Ie),h(p)),()=>{U(C,h(Ie).height/h(p))}),ge(()=>(h(x),h(C)),()=>{U($,Math.max(h(x),h(C)))}),ge(()=>(h($),h(g)),()=>{U(m,h($)*h(g))}),ge(()=>(h($),h(p)),()=>{U(_,h($)*h(p))}),ge(()=>h($),()=>{U(v,5*h($))}),ge(()=>(h(Ie),h(m),h(v)),()=>{U(b,h(Ie).x-(h(m)-h(Ie).width)/2-h(v))}),ge(()=>(h(Ie),h(_),h(v)),()=>{U(N,h(Ie).y-(h(_)-h(Ie).height)/2-h(v))}),ge(()=>(h(m),h(v)),()=>{U(E,h(m)+h(v)*2)}),ge(()=>(h(_),h(v)),()=>{U(T,h(_)+h(v)*2)}),vt(),He();const dt=ve(()=>fe()+(k()?`;--xy-minimap-background-color-props:${k()}`:"")),J=ve(()=>Et(["svelte-flow__minimap",me()]));So(e,{get position(){return D()},get style(){return h(dt)},get class(){return h(J)},"data-testid":"svelte-flow__minimap",children:(le,$n)=>{var fn=tt(),En=xe(fn);{var Te=st=>{var ye=U2();de(ye,"aria-labelledby",be);var lt=X(ye);{var ct=Wt=>{var Ot=G2();de(Ot,"id",be);var Sn=X(Ot,!0);Z(Ot),Ee(()=>Bt(Sn,V())),L(Wt,Ot)};ke(lt,Wt=>{V()&&Wt(ct)})}var Jt=z(lt);Yt(Jt,1,u,Wt=>Wt.id,(Wt,Ot)=>{var Sn=tt();const gn=ve(()=>l().get(h(Ot).id));var mt=xe(Sn);{var xa=yr=>{const hn=ve(()=>Qn(h(gn))),ji=ve(()=>Oe==null?void 0:Oe(h(gn))),Ji=ve(()=>rt(h(gn))),Qi=ve(()=>oe(h(gn)));zc(yr,ft({get x(){return h(gn).internals.positionAbsolute.x},get y(){return h(gn).internals.positionAbsolute.y}},()=>h(hn),{get selected(){return h(gn).selected},get color(){return h(ji)},get borderRadius(){return S()},get strokeColor(){return h(Ji)},get strokeWidth(){return M()},shapeRendering:pe,get class(){return h(Qi)}}))};ke(mt,yr=>{h(gn)&&Eu(h(gn))&&yr(xa)})}L(Wt,Sn)});var Oo=z(Jt);Z(ye),_t(ye,(Wt,Ot)=>ca==null?void 0:ca(Wt,Ot),()=>({panZoom:c(),viewport:ae,getViewScale:ht,translateExtent:f(),width:s(),height:a(),inversePan:ee(),zoomStep:W(),pannable:K(),zoomable:se()})),Ee(()=>{de(ye,"width",h(g)),de(ye,"height",h(p)),de(ye,"viewBox",`${h(b)??""} ${h(N)??""} ${h(E)??""} ${h(T)??""}`),at(ye,"--xy-minimap-mask-background-color-props",P()),at(ye,"--xy-minimap-mask-stroke-color-props",H()),at(ye,"--xy-minimap-mask-stroke-width-props",I()?I()*h($):void 0),de(Oo,"d",`M${h(b)-h(v)},${h(N)-h(v)}h${h(E)+h(v)*2}v${h(T)+h(v)*2}h${-h(E)-h(v)*2}z
+ M${h(d).x??""},${h(d).y??""}h${h(d).width??""}v${h(d).height??""}h${-h(d).width}z`)}),L(st,ye)};ke(En,st=>{c()&&st(Te)})}L(le,fn)},$$slots:{default:!0}});var Re=ce({get position(){return D()},set position(le){D(le),y()},get ariaLabel(){return V()},set ariaLabel(le){V(le),y()},get nodeStrokeColor(){return A()},set nodeStrokeColor(le){A(le),y()},get nodeColor(){return O()},set nodeColor(le){O(le),y()},get nodeClass(){return R()},set nodeClass(le){R(le),y()},get nodeBorderRadius(){return S()},set nodeBorderRadius(le){S(le),y()},get nodeStrokeWidth(){return M()},set nodeStrokeWidth(le){M(le),y()},get bgColor(){return k()},set bgColor(le){k(le),y()},get maskColor(){return P()},set maskColor(le){P(le),y()},get maskStrokeColor(){return H()},set maskStrokeColor(le){H(le),y()},get maskStrokeWidth(){return I()},set maskStrokeWidth(le){I(le),y()},get width(){return B()},set width(le){B(le),y()},get height(){return F()},set height(le){F(le),y()},get pannable(){return K()},set pannable(le){K(le),y()},get zoomable(){return se()},set zoomable(le){se(le),y()},get inversePan(){return ee()},set inversePan(le){ee(le),y()},get zoomStep(){return W()},set zoomStep(le){W(le),y()},get style(){return fe()},set style(le){fe(le),y()},get class(){return me()},set class(le){me(le),y()}});return r(),Re}ie(Rc,{position:{},ariaLabel:{},nodeStrokeColor:{},nodeColor:{},nodeClass:{},nodeBorderRadius:{},nodeStrokeWidth:{},bgColor:{},maskColor:{},maskStrokeColor:{},maskStrokeWidth:{},width:{},height:{},pannable:{},zoomable:{},inversePan:{},zoomStep:{},style:{},class:{}},[],[],!0);const Bc=e=>Uv(e);function Lt(){const{zoomIn:e,zoomOut:t,fitView:n,onbeforedelete:r,snapGrid:o,viewport:i,width:s,height:a,minZoom:l,maxZoom:u,panZoom:c,nodes:f,edges:d,domNode:g,nodeLookup:p,nodeOrigin:x,edgeLookup:C,connectionLookup:$}=Ue(),m=b=>{var V,A;const N=q(p),E=Bc(b)?b:N.get(b.id),T=E.parentId?e0(E.position,E.measured,E.parentId,N,q(x)):E.position,D={...E,position:T,width:((V=E.measured)==null?void 0:V.width)??E.width,height:((A=E.measured)==null?void 0:A.height)??E.height};return Or(D)},_=(b,N,E={replace:!1})=>{var V;const T=(V=q(p).get(b))==null?void 0:V.internals.userNode;if(!T)return;const D=typeof N=="function"?N(T):N;E.replace?f.update(A=>A.map(O=>O.id===b?Bc(D)?D:{...O,...D}:O)):(Object.assign(T,D),f.update(A=>A))},v=b=>q(p).get(b);return{zoomIn:e,zoomOut:t,getInternalNode:v,getNode:b=>{var N;return(N=v(b))==null?void 0:N.internals.userNode},getNodes:b=>b===void 0?q(f):Yc(q(p),b),getEdge:b=>q(C).get(b),getEdges:b=>b===void 0?q(d):Yc(q(C),b),setZoom:(b,N)=>{const E=q(c);return E?E.scaleTo(b,{duration:N==null?void 0:N.duration}):Promise.resolve(!1)},getZoom:()=>q(i).zoom,setViewport:async(b,N)=>{const E=q(i),T=q(c);return T?(await T.setViewport({x:b.x??E.x,y:b.y??E.y,zoom:b.zoom??E.zoom},{duration:N==null?void 0:N.duration}),Promise.resolve(!0)):Promise.resolve(!1)},getViewport:()=>q(i),setCenter:async(b,N,E)=>{const T=typeof(E==null?void 0:E.zoom)<"u"?E.zoom:q(u),D=q(c);return D?(await D.setViewport({x:q(s)/2-b*T,y:q(a)/2-N*T,zoom:T},{duration:E==null?void 0:E.duration}),Promise.resolve(!0)):Promise.resolve(!1)},fitView:n,fitBounds:async(b,N)=>{const E=q(c);if(!E)return Promise.resolve(!1);const T=js(b,q(s),q(a),q(l),q(u),(N==null?void 0:N.padding)??.1);return await E.setViewport(T,{duration:N==null?void 0:N.duration}),Promise.resolve(!0)},getIntersectingNodes:(b,N=!0,E)=>{const T=ku(b),D=T?b:m(b);return D?(E||q(f)).filter(V=>{const A=q(p).get(V.id);if(!A||!T&&V.id===b.id)return!1;const O=Or(A),R=Co(O,D);return N&&R>0||R>=D.width*D.height}):[]},isNodeIntersecting:(b,N,E=!0)=>{const D=ku(b)?b:m(b);if(!D)return!1;const V=Co(D,N);return E&&V>0||V>=D.width*D.height},deleteElements:async({nodes:b=[],edges:N=[]})=>{const{nodes:E,edges:T}=await wu({nodesToRemove:b,edgesToRemove:N,nodes:q(f),edges:q(d),onBeforeDelete:q(r)});return E&&f.update(D=>D.filter(V=>!E.some(({id:A})=>A===V.id))),T&&d.update(D=>D.filter(V=>!T.some(({id:A})=>A===V.id))),{deletedNodes:E,deletedEdges:T}},screenToFlowPosition:(b,N={snapToGrid:!0})=>{const E=q(g);if(!E)return b;const T=N.snapToGrid?q(o):!1,{x:D,y:V,zoom:A}=q(i),{x:O,y:R}=E.getBoundingClientRect(),S={x:b.x-O,y:b.y-R};return ko(S,[D,V,A],T!==null,T||[1,1])},flowToScreenPosition:b=>{const N=q(g);if(!N)return b;const{x:E,y:T,zoom:D}=q(i),{x:V,y:A}=N.getBoundingClientRect(),O=$u(b,[E,T,D]);return{x:O.x+V,y:O.y+A}},toObject:()=>({nodes:q(f).map(b=>({...b,position:{...b.position},data:{...b.data}})),edges:q(d).map(b=>({...b})),viewport:{...q(i)}}),updateNode:_,updateNodeData:(b,N,E)=>{var V;const T=(V=q(p).get(b))==null?void 0:V.internals.userNode;if(!T)return;const D=typeof N=="function"?N(T):N;T.data=E!=null&&E.replace?D:{...T.data,...D},f.update(A=>A)},getNodesBounds:b=>{const N=q(p),E=q(x);return jv(b,{nodeLookup:N,nodeOrigin:E})},getHandleConnections:({type:b,id:N,nodeId:E})=>{var T;return Array.from(((T=q($).get(`${E}-${b}-${N??null}`))==null?void 0:T.values())??[])},viewport:i}}function Yc(e,t){var r;const n=[];for(const o of t){const i=e.get(o);if(i){const s="internals"in i?(r=i.internals)==null?void 0:r.userNode:i;n.push(s)}}return n}var j2=ne('');function Zc(e,t){ue(t,!1);const[n,r]=nt(),o=()=>Q(_,"$nodes",n),i=()=>Q(m,"$nodeLookup",n),s=()=>Q($,"$viewport",n),a=()=>Q(C,"$domNode",n),l=re(),u=re(),c=re();let f=w(t,"nodeId",12,void 0),d=w(t,"position",12,void 0),g=w(t,"align",12,void 0),p=w(t,"offset",12,void 0),x=w(t,"isVisible",12,void 0);const{domNode:C,viewport:$,nodeLookup:m,nodes:_}=Ue(),{getNodesBounds:v}=Lt(),b=ur("svelteflow__node_id");let N=re(),E=re([]),T=p()!==void 0?p():10,D=d()!==void 0?d():$e.Top,V=g()!==void 0?g():"center";ge(()=>(o(),j(f()),i()),()=>{o();const M=Array.isArray(f())?f():[f()||b];U(E,M.reduce((k,P)=>{const H=i().get(P);return H&&k.push(H),k},[]))}),ge(()=>(h(E),s()),()=>{const M=v(h(E));M&&U(N,v0(M,s(),D,T,V))}),ge(()=>h(E),()=>{U(l,h(E).length===0?1:Math.max(...h(E).map(M=>(M.internals.z||5)+1)))}),ge(()=>o(),()=>{U(u,o().filter(M=>M.selected).length)}),ge(()=>(j(x()),h(E),h(u)),()=>{U(c,typeof x()=="boolean"?x():h(E).length===1&&h(E)[0].selected&&h(u)===1)}),vt(),He();var A=tt(),O=xe(A);{var R=M=>{var k=j2(),P=X(k);wt(P,t,"default",{}),Z(k),_t(k,(H,I)=>Rr==null?void 0:Rr(H,I),()=>({domNode:a()})),Ee(H=>{de(k,"data-id",H),at(k,"position","absolute"),at(k,"transform",h(N)),at(k,"z-index",h(l))},[()=>h(E).reduce((H,I)=>`${H}${I.id} `,"").trim()],ve),L(M,k)};ke(O,M=>{a()&&h(c)&&h(E)&&M(R)})}L(e,A);var S=ce({get nodeId(){return f()},set nodeId(M){f(M),y()},get position(){return d()},set position(M){d(M),y()},get align(){return g()},set align(M){g(M),y()},get offset(){return p()},set offset(M){p(M),y()},get isVisible(){return x()},set isVisible(M){x(M),y()}});return r(),S}ie(Zc,{nodeId:{},position:{},align:{},offset:{},isVisible:{}},["default"],[],!0);function pr(e){const{nodes:t,nodeLookup:n}=Ue();let r=[],o=!0;return Un([t,n],([,i],s)=>{var c;const a=[],l=Array.isArray(e),u=l?e:[e];for(const f of u){const d=(c=i.get(f))==null?void 0:c.internals.userNode;d&&a.push({id:d.id,type:d.type,data:d.data})}(!C0(a,r)||o)&&(r=a,s(l?a:a[0]??null),o=!1)})}const Xc="tinyflow-component";class J2{constructor(t){Nt(this,"options");Nt(this,"rootEl");Nt(this,"svelteFlowInstance");if(typeof t.element!="string"&&!(t.element instanceof Element))throw new Error("element must be a string or Element");this._setOptions(t),this._init()}_init(){if(typeof this.options.element=="string"){if(this.rootEl=document.querySelector(this.options.element),!this.rootEl)throw new Error(`element not found by document.querySelector('${this.options.element}')`)}else if(this.options.element instanceof Element)this.rootEl=this.options.element;else throw new Error("element must be a string or Element");const t=document.createElement(Xc);t.style.display="block",t.style.width="100%",t.style.height="100%",t.classList.add("tf-theme-light"),t.options=this.options,t.onInit=n=>{this.svelteFlowInstance=n},this.rootEl.appendChild(t)}_setOptions(t){this.options={...t}}getOptions(){return this.options}getData(){return this.svelteFlowInstance.toObject()}setData(t){this.options.data=t;const n=document.createElement(Xc);n.style.display="block",n.style.width="100%",n.style.height="100%",n.classList.add("tf-theme-light"),n.options=this.options,n.onInit=r=>{this.svelteFlowInstance=r},this.destroy(),this.rootEl.appendChild(n)}destroy(){for(;this.rootEl.firstChild;)this.rootEl.removeChild(this.rootEl.firstChild)}}const Bi=(()=>{const e=we([]),t=we([]),n=we({x:250,y:100,zoom:1});return{nodes:e,edges:t,viewport:n,init:(r,o)=>{e.set(r),t.set(o)},addNode:r=>{e.update(o=>[...o,r])},removeNode:r=>{e.update(o=>o.filter(i=>i.id!==r))},updateNode:(r,o)=>{e.update(i=>i.map(s=>s.id===r?o:s))},updateNodeData:(r,o)=>{e.update(i=>i.map(s=>s.id===r?{...s,data:{...s.data,...o}}:s))},selectNodeOnly:r=>{e.update(o=>o.map(i=>i.id===r?{...i,selected:!0}:{...i,selected:!1}))},addEdge:r=>{t.update(o=>[...o,r])},removeEdge:r=>{t.update(o=>o.filter(i=>i.id!==r))},updateEdge:(r,o)=>{t.update(i=>i.map(s=>s.id===r?o:s))},updateEdgeData:(r,o)=>{t.update(i=>i.map(s=>s.id===r?{...s,data:o}:s))}}})();var Q2=ne("");function Ge(e,t){ue(t,!0);const n=w(t,"children",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","children"]);var o=Q2();let i;var s=X(o);return cr(s,()=>n()??gt),Z(o),Ee(()=>i=nn(o,i,{type:"button",...r,class:`tf-btn nopan nodrag ${t.class??""}`})),L(e,o),ce({get children(){return n()},set children(a){n(a),y()}})}ie(Ge,{children:{}},[],[],!0);var ep=ne("");function Fc(e,t){ue(t,!0);const n=xt(t,["$$slots","$$events","$$legacy","$$host"]);var r=ep();ao(r);let o;Ee(()=>o=nn(r,o,{type:"checkbox",...n,class:`tf-checkbox nopan nodrag ${t.class??""}`})),L(e,r),ce()}ie(Fc,{},[],[],!0);var tp=ne("");function St(e,t){ue(t,!0);const n=xt(t,["$$slots","$$events","$$legacy","$$host"]);var r=tp();ao(r);let o;Ee(()=>o=nn(r,o,{type:"text",...n,class:`tf-input nopan nodrag ${t.class??""}`})),L(e,r),ce()}ie(St,{},[],[],!0);var np=ne("");function Pt(e,t){ue(t,!0);const n=xt(t,["$$slots","$$events","$$legacy","$$host"]);var r=np();Wf(r);let o;Ee(()=>o=nn(r,o,{...n,class:`tf-textarea nodrag ${t.class??""}`})),L(e,r),ce()}ie(Pt,{},[],[],!0);var rp=ne(''),op=ne("");function Wc(e,t){const n=it(t,["children","$$slots","$$events","$$legacy","$$host"]),r=it(n,["items","onChange","activeIndex"]);ue(t,!1);let o=w(t,"items",28,()=>[]),i=w(t,"onChange",12,()=>{}),s=w(t,"activeIndex",12,0);function a(c,f){var d;s(f),(d=i())==null||d(c,f)}He();var l=op();let u;return Yt(l,5,o,oi,(c,f,d)=>{var g=rp();de(g,"tabindex",d),g.__click=()=>a(h(f),d),g.__keydown=$=>{($.key==="Enter"||$.key===" ")&&($.preventDefault(),a(h(f),d))};var p=X(g);{var x=$=>{var m=Ae();Ee(()=>Bt(m,h(f).label)),L($,m)},C=$=>{var m=tt(),_=xe(m);cr(_,()=>h(f).label??gt),L($,m)};ke(p,$=>{typeof h(f).label=="string"?$(x):$(C,!1)})}Z(g),Ee(()=>$t(g,1,`tf-tabs-item ${(d===s()?"active":"")??""}`)),L(c,g)}),Z(l),Ee(()=>u=nn(l,u,{...r,class:`tf-tabs ${r.class??""}`})),L(e,l),ce({get items(){return o()},set items(c){o(c),y()},get onChange(){return i()},set onChange(c){i(c),y()},get activeIndex(){return s()},set activeIndex(c){s(c),y()}})}ri(["click","keydown"]),ie(Wc,{items:{},onChange:{},activeIndex:{}},[],[],!0);var ip=(e,t,n)=>t(h(n)),sp=(e,t,n)=>{(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),t(h(n)))},ap=ne(''),lp=ne(''),up=ne(''),cp=ne(''),dp=ne("");const fp={hash:"svelte-1jfktzw",code:`\r
+ /* 定义旋转的 CSS 类 */.rotate-90.svelte-1jfktzw {transform:rotate(90deg);transition:transform 0.3s ease;}`};function Kc(e,t){ue(t,!0),et(e,fp);let n=w(t,"items",7),r=w(t,"onChange",7),o=w(t,"activeKeys",31,()=>Ht([]));function i(a){var l;o().includes(a.key)?o(o().filter(u=>u!==a.key)):(o().push(a.key),o(o())),(l=r())==null||l(a,o())}var s=dp();return Yt(s,21,n,oi,(a,l,u)=>{var c=cp(),f=X(c);de(f,"tabindex",u),f.__click=[ip,i,l],f.__keydown=[sp,i,l];var d=X(f);{var g=v=>{var b=ap(),N=X(b);nr(N,{get target(){return h(l).icon}}),Z(b),L(v,b)};ke(d,v=>{h(l).icon&&v(g)})}var p=z(d,2);nr(p,{get target(){return h(l).title}});var x=z(p,2);Z(f);var C=z(f,2);{var $=v=>{var b=lp(),N=X(b);nr(N,{get target(){return h(l).description}}),Z(b),L(v,b)};ke(C,v=>{h(l).description&&v($)})}var m=z(C,2);{var _=v=>{var b=up(),N=X(b);nr(N,{get target(){return h(l).content}}),Z(b),L(v,b)};ke(m,v=>{o().includes(h(l).key)&&v(_)})}Z(c),Ee(v=>$t(x,1,`tf-collapse-item-title-arrow ${v??""}`,"svelte-1jfktzw"),[()=>o().includes(h(l).key)?"rotate-90":""]),L(a,c)}),Z(s),Ee(()=>{de(s,"style",t.style),$t(s,1,`tf-collapse ${t.class??""}`,"svelte-1jfktzw")}),L(e,s),ce({get items(){return n()},set items(a){n(a),y()},get onChange(){return r()},set onChange(a){r(a),y()},get activeKeys(){return o()},set activeKeys(a=[]){o(a),y()}})}ri(["click","keydown"]),ie(Kc,{items:{},onChange:{},activeKeys:{}},[],[],!0);function nr(e,t){ue(t,!0);let n=w(t,"target",7);typeof n()>"u"&&n("undefined");var r=tt(),o=xe(r);{var i=a=>{var l=tt(),u=xe(l);cr(u,()=>n()??gt),L(a,l)},s=a=>{var l=tt(),u=xe(l);dl(u,n),L(a,l)};ke(o,a=>{typeof n()=="function"?a(i):a(s,!1)})}return L(e,r),ce({get target(){return n()},set target(a){n(a),y()}})}ie(nr,{target:{}},[],[],!0);var gp=(e,t,n)=>t(h(n)),hp=_e(''),vp=ne(''),pp=ne(' ',1),mp=ne(''),yp=ne(" ",1),wp=ne('
'),_p=ne(''),xp=ne("");function ln(e,t){ue(t,!0);const n=(_,v=gt)=>{var b=tt(),N=xe(b);Yt(N,19,v,(E,T)=>`${T}_${E.value}`,(E,T)=>{var D=pp(),V=xe(D);V.__click=[gp,x,T];var A=X(V),O=X(A);{var R=P=>{var H=hp();L(P,H)};ke(O,P=>{h(T).children&&h(T).children.length>0&&P(R)})}Z(A);var S=z(A,2);nr(S,{get target(){return h(T).label}}),Z(V);var M=z(V,2);{var k=P=>{var H=vp(),I=X(H);n(I,()=>h(T).children),Z(H),L(P,H)};ke(M,P=>{h(T).children&&h(T).children.length>0&&(l()||c().includes(h(T).value))&&P(k)})}L(E,D)}),L(_,b)};let r=w(t,"items",7),o=w(t,"onExpand",7),i=w(t,"onSelect",7),s=w(t,"value",23,()=>[]),a=w(t,"defaultValue",23,()=>[]),l=w(t,"expandAll",7,!0),u=w(t,"multiple",7,!1),c=w(t,"expandValue",23,()=>[]),f=w(t,"placeholder",7),d=xt(t,["$$slots","$$events","$$legacy","$$host","items","onExpand","onSelect","value","defaultValue","expandAll","multiple","expandValue","placeholder"]),g=Ne(()=>{const _=[],v=b=>{for(let N of b)s().length>0?s().includes(N.value)&&_.push(N):a().includes(N.value)&&_.push(N),N.children&&N.children.length>0&&v(N.children)};return v(r()),_}),p;function x(_){var v,b;if(_.children&&_.children.length>0){(v=o())==null||v(_);return}else p==null||p.hide(),(b=i())==null||b(_)}var C=xp();let $;var m=X(C);return An(Do(m,{floating:v=>{var b=mp(),N=X(b);n(N,r),Z(b),L(v,b)},children:(v,b)=>{var N=_p();let E;var T=X(N);Yt(T,23,()=>h(g),(D,V)=>`${V}_${D.value}`,(D,V,A)=>{var O=tt(),R=xe(O);{var S=k=>{var P=tt(),H=xe(P);{var I=B=>{nr(B,{get target(){return h(V).label}})};ke(H,B=>{h(A)===0&&B(I)})}L(k,P)},M=k=>{var P=yp(),H=xe(P);nr(H,{get target(){return h(V).label}});var I=z(H,2);{var B=F=>{var K=Ae(",");L(F,K)};ke(I,F=>{h(A){u()?k(M,!1):k(S)})}L(D,O)},D=>{var V=wp(),A=X(V,!0);Z(V),Ee(()=>Bt(A,f())),L(D,V)}),Z(T),Pe(2),Z(N),Ee(()=>E=nn(N,E,{class:"tf-select-input nopan nodrag",...d})),L(v,N)},$$slots:{floating:!0,default:!0}}),v=>p=v,()=>p),Z(C),Ee(()=>$=nn(C,$,{...d,class:`tf-select ${d.class??""}`})),L(e,C),ce({get items(){return r()},set items(_){r(_),y()},get onExpand(){return o()},set onExpand(_){o(_),y()},get onSelect(){return i()},set onSelect(_){i(_),y()},get value(){return s()},set value(_=[]){s(_),y()},get defaultValue(){return a()},set defaultValue(_=[]){a(_),y()},get expandAll(){return l()},set expandAll(_=!0){l(_),y()},get multiple(){return u()},set multiple(_=!1){u(_),y()},get expandValue(){return c()},set expandValue(_=[]){c(_),y()},get placeholder(){return f()},set placeholder(_){f(_),y()}})}ri(["click"]),ie(ln,{items:{},onExpand:{},onSelect:{},value:{},defaultValue:{},expandAll:{},multiple:{},expandValue:{},placeholder:{}},[],[],!0);const No=Math.min,Yr=Math.max,Yi=Math.round,bn=e=>({x:e,y:e}),bp={left:"right",right:"left",bottom:"top",top:"bottom"},Cp={start:"end",end:"start"};function fa(e,t,n){return Yr(e,No(t,n))}function To(e,t){return typeof e=="function"?e(t):e}function mr(e){return e.split("-")[0]}function Mo(e){return e.split("-")[1]}function qc(e){return e==="x"?"y":"x"}function ga(e){return e==="y"?"height":"width"}function Zr(e){return["top","bottom"].includes(mr(e))?"y":"x"}function ha(e){return qc(Zr(e))}function kp(e,t,n){n===void 0&&(n=!1);const r=Mo(e),o=ha(e),i=ga(o);let s=o==="x"?r===(n?"end":"start")?"right":"left":r==="start"?"bottom":"top";return t.reference[i]>t.floating[i]&&(s=Zi(s)),[s,Zi(s)]}function $p(e){const t=Zi(e);return[va(e),t,va(t)]}function va(e){return e.replace(/start|end/g,t=>Cp[t])}function Ep(e,t,n){const r=["left","right"],o=["right","left"],i=["top","bottom"],s=["bottom","top"];switch(e){case"top":case"bottom":return n?t?o:r:t?r:o;case"left":case"right":return t?i:s;default:return[]}}function Sp(e,t,n,r){const o=Mo(e);let i=Ep(mr(e),n==="start",r);return o&&(i=i.map(s=>s+"-"+o),t&&(i=i.concat(i.map(va)))),i}function Zi(e){return e.replace(/left|right|bottom|top/g,t=>bp[t])}function Pp(e){return{top:0,right:0,bottom:0,left:0,...e}}function Gc(e){return typeof e!="number"?Pp(e):{top:e,right:e,bottom:e,left:e}}function Xi(e){const{x:t,y:n,width:r,height:o}=e;return{width:r,height:o,top:n,left:t,right:t+r,bottom:n+o,x:t,y:n}}function Uc(e,t,n){let{reference:r,floating:o}=e;const i=Zr(t),s=ha(t),a=ga(s),l=mr(t),u=i==="y",c=r.x+r.width/2-o.width/2,f=r.y+r.height/2-o.height/2,d=r[a]/2-o[a]/2;let g;switch(l){case"top":g={x:c,y:r.y-o.height};break;case"bottom":g={x:c,y:r.y+r.height};break;case"right":g={x:r.x+r.width,y:f};break;case"left":g={x:r.x-o.width,y:f};break;default:g={x:r.x,y:r.y}}switch(Mo(t)){case"start":g[s]-=d*(n&&u?-1:1);break;case"end":g[s]+=d*(n&&u?-1:1);break}return g}const Np=async(e,t,n)=>{const{placement:r="bottom",strategy:o="absolute",middleware:i=[],platform:s}=n,a=i.filter(Boolean),l=await(s.isRTL==null?void 0:s.isRTL(t));let u=await s.getElementRects({reference:e,floating:t,strategy:o}),{x:c,y:f}=Uc(u,r,l),d=r,g={},p=0;for(let x=0;x({name:"arrow",options:e,async fn(t){const{x:n,y:r,placement:o,rects:i,platform:s,elements:a,middlewareData:l}=t,{element:u,padding:c=0}=To(e,t)||{};if(u==null)return{};const f=Gc(c),d={x:n,y:r},g=ha(o),p=ga(g),x=await s.getDimensions(u),C=g==="y",$=C?"top":"left",m=C?"bottom":"right",_=C?"clientHeight":"clientWidth",v=i.reference[p]+i.reference[g]-d[g]-i.floating[p],b=d[g]-i.reference[g],N=await(s.getOffsetParent==null?void 0:s.getOffsetParent(u));let E=N?N[_]:0;(!E||!await(s.isElement==null?void 0:s.isElement(N)))&&(E=a.floating[_]||i.floating[p]);const T=v/2-b/2,D=E/2-x[p]/2-1,V=No(f[$],D),A=No(f[m],D),O=V,R=E-x[p]-A,S=E/2-x[p]/2+T,M=fa(O,S,R),k=!l.arrow&&Mo(o)!=null&&S!==M&&i.reference[p]/2-(SS<=0)){var A,O;const S=(((A=i.flip)==null?void 0:A.index)||0)+1,M=E[S];if(M)return{data:{index:S,overflows:V},reset:{placement:M}};let k=(O=V.filter(P=>P.overflows[0]<=0).sort((P,H)=>P.overflows[1]-H.overflows[1])[0])==null?void 0:O.placement;if(!k)switch(g){case"bestFit":{var R;const P=(R=V.filter(H=>{if(N){const I=Zr(H.placement);return I===m||I==="y"}return!0}).map(H=>[H.placement,H.overflows.filter(I=>I>0).reduce((I,B)=>I+B,0)]).sort((H,I)=>H[1]-I[1])[0])==null?void 0:R[0];P&&(k=P);break}case"initialPlacement":k=a;break}if(o!==k)return{reset:{placement:k}}}return{}}}};async function Hp(e,t){const{placement:n,platform:r,elements:o}=e,i=await(r.isRTL==null?void 0:r.isRTL(o.floating)),s=mr(n),a=Mo(n),l=Zr(n)==="y",u=["left","top"].includes(s)?-1:1,c=i&&l?-1:1,f=To(t,e);let{mainAxis:d,crossAxis:g,alignmentAxis:p}=typeof f=="number"?{mainAxis:f,crossAxis:0,alignmentAxis:null}:{mainAxis:f.mainAxis||0,crossAxis:f.crossAxis||0,alignmentAxis:f.alignmentAxis};return a&&typeof p=="number"&&(g=a==="end"?p*-1:p),l?{x:g*c,y:d*u}:{x:d*u,y:g*c}}const Vp=function(e){return e===void 0&&(e=0),{name:"offset",options:e,async fn(t){var n,r;const{x:o,y:i,placement:s,middlewareData:a}=t,l=await Hp(t,e);return s===((n=a.offset)==null?void 0:n.placement)&&(r=a.arrow)!=null&&r.alignmentOffset?{}:{x:o+l.x,y:i+l.y,data:{...l,placement:s}}}}},Dp=function(e){return e===void 0&&(e={}),{name:"shift",options:e,async fn(t){const{x:n,y:r,placement:o}=t,{mainAxis:i=!0,crossAxis:s=!1,limiter:a={fn:C=>{let{x:$,y:m}=C;return{x:$,y:m}}},...l}=To(e,t),u={x:n,y:r},c=await jc(t,l),f=Zr(mr(o)),d=qc(f);let g=u[d],p=u[f];if(i){const C=d==="y"?"top":"left",$=d==="y"?"bottom":"right",m=g+c[C],_=g-c[$];g=fa(m,g,_)}if(s){const C=f==="y"?"top":"left",$=f==="y"?"bottom":"right",m=p+c[C],_=p-c[$];p=fa(m,p,_)}const x=a.fn({...t,[d]:g,[f]:p});return{...x,data:{x:x.x-n,y:x.y-r,enabled:{[d]:i,[f]:s}}}}}};function Fi(){return typeof window<"u"}function Xr(e){return Jc(e)?(e.nodeName||"").toLowerCase():"#document"}function Xt(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t.defaultView)||window}function Bn(e){var t;return(t=(Jc(e)?e.ownerDocument:e.document)||window.document)==null?void 0:t.documentElement}function Jc(e){return Fi()?e instanceof Node||e instanceof Xt(e).Node:!1}function un(e){return Fi()?e instanceof Element||e instanceof Xt(e).Element:!1}function Cn(e){return Fi()?e instanceof HTMLElement||e instanceof Xt(e).HTMLElement:!1}function Qc(e){return!Fi()||typeof ShadowRoot>"u"?!1:e instanceof ShadowRoot||e instanceof Xt(e).ShadowRoot}function Ho(e){const{overflow:t,overflowX:n,overflowY:r,display:o}=cn(e);return/auto|scroll|overlay|hidden|clip/.test(t+r+n)&&!["inline","contents"].includes(o)}function Ap(e){return["table","td","th"].includes(Xr(e))}function Wi(e){return[":popover-open",":modal"].some(t=>{try{return e.matches(t)}catch{return!1}})}function pa(e){const t=ma(),n=un(e)?cn(e):e;return["transform","translate","scale","rotate","perspective"].some(r=>n[r]?n[r]!=="none":!1)||(n.containerType?n.containerType!=="normal":!1)||!t&&(n.backdropFilter?n.backdropFilter!=="none":!1)||!t&&(n.filter?n.filter!=="none":!1)||["transform","translate","scale","rotate","perspective","filter"].some(r=>(n.willChange||"").includes(r))||["paint","layout","strict","content"].some(r=>(n.contain||"").includes(r))}function Lp(e){let t=rr(e);for(;Cn(t)&&!Fr(t);){if(pa(t))return t;if(Wi(t))return null;t=rr(t)}return null}function ma(){return typeof CSS>"u"||!CSS.supports?!1:CSS.supports("-webkit-backdrop-filter","none")}function Fr(e){return["html","body","#document"].includes(Xr(e))}function cn(e){return Xt(e).getComputedStyle(e)}function Ki(e){return un(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function rr(e){if(Xr(e)==="html")return e;const t=e.assignedSlot||e.parentNode||Qc(e)&&e.host||Bn(e);return Qc(t)?t.host:t}function ed(e){const t=rr(e);return Fr(t)?e.ownerDocument?e.ownerDocument.body:e.body:Cn(t)&&Ho(t)?t:ed(t)}function td(e,t,n){var r;t===void 0&&(t=[]);const o=ed(e),i=o===((r=e.ownerDocument)==null?void 0:r.body),s=Xt(o);return i?(ya(s),t.concat(s,s.visualViewport||[],Ho(o)?o:[],[])):t.concat(o,td(o,[]))}function ya(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}function nd(e){const t=cn(e);let n=parseFloat(t.width)||0,r=parseFloat(t.height)||0;const o=Cn(e),i=o?e.offsetWidth:n,s=o?e.offsetHeight:r,a=Yi(n)!==i||Yi(r)!==s;return a&&(n=i,r=s),{width:n,height:r,$:a}}function rd(e){return un(e)?e:e.contextElement}function Wr(e){const t=rd(e);if(!Cn(t))return bn(1);const n=t.getBoundingClientRect(),{width:r,height:o,$:i}=nd(t);let s=(i?Yi(n.width):n.width)/r,a=(i?Yi(n.height):n.height)/o;return(!s||!Number.isFinite(s))&&(s=1),(!a||!Number.isFinite(a))&&(a=1),{x:s,y:a}}const Op=bn(0);function od(e){const t=Xt(e);return!ma()||!t.visualViewport?Op:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function Ip(e,t,n){return t===void 0&&(t=!1),!n||t&&n!==Xt(e)?!1:t}function Vo(e,t,n,r){t===void 0&&(t=!1),n===void 0&&(n=!1);const o=e.getBoundingClientRect(),i=rd(e);let s=bn(1);t&&(r?un(r)&&(s=Wr(r)):s=Wr(e));const a=Ip(i,n,r)?od(i):bn(0);let l=(o.left+a.x)/s.x,u=(o.top+a.y)/s.y,c=o.width/s.x,f=o.height/s.y;if(i){const d=Xt(i),g=r&&un(r)?Xt(r):r;let p=d,x=ya(p);for(;x&&r&&g!==p;){const C=Wr(x),$=x.getBoundingClientRect(),m=cn(x),_=$.left+(x.clientLeft+parseFloat(m.paddingLeft))*C.x,v=$.top+(x.clientTop+parseFloat(m.paddingTop))*C.y;l*=C.x,u*=C.y,c*=C.x,f*=C.y,l+=_,u+=v,p=Xt(x),x=ya(p)}}return Xi({width:c,height:f,x:l,y:u})}function wa(e,t){const n=Ki(e).scrollLeft;return t?t.left+n:Vo(Bn(e)).left+n}function id(e,t,n){n===void 0&&(n=!1);const r=e.getBoundingClientRect(),o=r.left+t.scrollLeft-(n?0:wa(e,r)),i=r.top+t.scrollTop;return{x:o,y:i}}function zp(e){let{elements:t,rect:n,offsetParent:r,strategy:o}=e;const i=o==="fixed",s=Bn(r),a=t?Wi(t.floating):!1;if(r===s||a&&i)return n;let l={scrollLeft:0,scrollTop:0},u=bn(1);const c=bn(0),f=Cn(r);if((f||!f&&!i)&&((Xr(r)!=="body"||Ho(s))&&(l=Ki(r)),Cn(r))){const g=Vo(r);u=Wr(r),c.x=g.x+r.clientLeft,c.y=g.y+r.clientTop}const d=s&&!f&&!i?id(s,l,!0):bn(0);return{width:n.width*u.x,height:n.height*u.y,x:n.x*u.x-l.scrollLeft*u.x+c.x+d.x,y:n.y*u.y-l.scrollTop*u.y+c.y+d.y}}function Rp(e){return Array.from(e.getClientRects())}function Bp(e){const t=Bn(e),n=Ki(e),r=e.ownerDocument.body,o=Yr(t.scrollWidth,t.clientWidth,r.scrollWidth,r.clientWidth),i=Yr(t.scrollHeight,t.clientHeight,r.scrollHeight,r.clientHeight);let s=-n.scrollLeft+wa(e);const a=-n.scrollTop;return cn(r).direction==="rtl"&&(s+=Yr(t.clientWidth,r.clientWidth)-o),{width:o,height:i,x:s,y:a}}function Yp(e,t){const n=Xt(e),r=Bn(e),o=n.visualViewport;let i=r.clientWidth,s=r.clientHeight,a=0,l=0;if(o){i=o.width,s=o.height;const u=ma();(!u||u&&t==="fixed")&&(a=o.offsetLeft,l=o.offsetTop)}return{width:i,height:s,x:a,y:l}}function Zp(e,t){const n=Vo(e,!0,t==="fixed"),r=n.top+e.clientTop,o=n.left+e.clientLeft,i=Cn(e)?Wr(e):bn(1),s=e.clientWidth*i.x,a=e.clientHeight*i.y,l=o*i.x,u=r*i.y;return{width:s,height:a,x:l,y:u}}function sd(e,t,n){let r;if(t==="viewport")r=Yp(e,n);else if(t==="document")r=Bp(Bn(e));else if(un(t))r=Zp(t,n);else{const o=od(e);r={x:t.x-o.x,y:t.y-o.y,width:t.width,height:t.height}}return Xi(r)}function ad(e,t){const n=rr(e);return n===t||!un(n)||Fr(n)?!1:cn(n).position==="fixed"||ad(n,t)}function Xp(e,t){const n=t.get(e);if(n)return n;let r=td(e,[]).filter(a=>un(a)&&Xr(a)!=="body"),o=null;const i=cn(e).position==="fixed";let s=i?rr(e):e;for(;un(s)&&!Fr(s);){const a=cn(s),l=pa(s);!l&&a.position==="fixed"&&(o=null),(i?!l&&!o:!l&&a.position==="static"&&!!o&&["absolute","fixed"].includes(o.position)||Ho(s)&&!l&&ad(e,s))?r=r.filter(c=>c!==s):o=a,s=rr(s)}return t.set(e,r),r}function Fp(e){let{element:t,boundary:n,rootBoundary:r,strategy:o}=e;const s=[...n==="clippingAncestors"?Wi(t)?[]:Xp(t,this._c):[].concat(n),r],a=s[0],l=s.reduce((u,c)=>{const f=sd(t,c,o);return u.top=Yr(f.top,u.top),u.right=No(f.right,u.right),u.bottom=No(f.bottom,u.bottom),u.left=Yr(f.left,u.left),u},sd(t,a,o));return{width:l.right-l.left,height:l.bottom-l.top,x:l.left,y:l.top}}function Wp(e){const{width:t,height:n}=nd(e);return{width:t,height:n}}function Kp(e,t,n){const r=Cn(t),o=Bn(t),i=n==="fixed",s=Vo(e,!0,i,t);let a={scrollLeft:0,scrollTop:0};const l=bn(0);if(r||!r&&!i)if((Xr(t)!=="body"||Ho(o))&&(a=Ki(t)),r){const d=Vo(t,!0,i,t);l.x=d.x+t.clientLeft,l.y=d.y+t.clientTop}else o&&(l.x=wa(o));const u=o&&!r&&!i?id(o,a):bn(0),c=s.left+a.scrollLeft-l.x-u.x,f=s.top+a.scrollTop-l.y-u.y;return{x:c,y:f,width:s.width,height:s.height}}function _a(e){return cn(e).position==="static"}function ld(e,t){if(!Cn(e)||cn(e).position==="fixed")return null;if(t)return t(e);let n=e.offsetParent;return Bn(e)===n&&(n=n.ownerDocument.body),n}function ud(e,t){const n=Xt(e);if(Wi(e))return n;if(!Cn(e)){let o=rr(e);for(;o&&!Fr(o);){if(un(o)&&!_a(o))return o;o=rr(o)}return n}let r=ld(e,t);for(;r&&Ap(r)&&_a(r);)r=ld(r,t);return r&&Fr(r)&&_a(r)&&!pa(r)?n:r||Lp(e)||n}const qp=async function(e){const t=this.getOffsetParent||ud,n=this.getDimensions,r=await n(e.floating);return{reference:Kp(e.reference,await t(e.floating),e.strategy),floating:{x:0,y:0,width:r.width,height:r.height}}};function Gp(e){return cn(e).direction==="rtl"}const Up={convertOffsetParentRelativeRectToViewportRelativeRect:zp,getDocumentElement:Bn,getClippingRect:Fp,getOffsetParent:ud,getElementRects:qp,getClientRects:Rp,getDimensions:Wp,getScale:Wr,isElement:un,isRTL:Gp},jp=Vp,Jp=Dp,Qp=Mp,em=Tp,tm=(e,t,n)=>{const r=new Map,o={platform:Up,...n},i={...o.platform,_c:r};return Np(e,t,{...o,platform:i})},nm=({trigger:e,triggerEvent:t,floatContent:n,placement:r="bottom",offsetOptions:o,flipOptions:i,shiftOptions:s,interactive:a,showArrow:l})=>{if(typeof e=="string"){const $=document.querySelector(e);if($)e=$;else throw new Error("element not found by document.querySelector('"+e+"')")}let u;if(typeof n=="string"){const $=document.querySelector(n);if($)u=$;else throw new Error("element not found by document.querySelector('"+n+"')")}else u=n;let c;l&&(c=document.createElement("div"),c.style.position="absolute",c.style.backgroundColor="#222",c.style.width="8px",c.style.height="8px",c.style.transform="rotate(45deg)",c.style.display="none",u.firstElementChild.before(c));function f(){tm(e,u,{placement:r,middleware:[jp(o),Qp(i),Jp(s),...l?[em({element:c})]:[]]}).then(({x:$,y:m,placement:_,middlewareData:v})=>{if(Object.assign(u.style,{left:`${$}px`,top:`${m}px`}),l){const{x:b,y:N}=v.arrow,E={top:"bottom",right:"left",bottom:"top",left:"right"}[_.split("-")[0]];Object.assign(c.style,{zIndex:-1,left:b!=null?`${b}px`:"",top:N!=null?`${N}px`:"",right:"",bottom:"",[E]:"2px"})}})}let d=!1;function g(){u.style.display="block",u.style.visibility="block",u.style.position="absolute",l&&(c.style.display="block"),d=!0,f()}function p(){u.style.display="none",l&&(c.style.display="none"),d=!1}function x($){$.stopPropagation(),d?p():g()}function C($){u.contains($.target)||p()}return(!t||t.length==0)&&(t=["click"]),t.forEach($=>{e.addEventListener($,x)}),document.addEventListener("click",C),{destroy(){t.forEach($=>{e.removeEventListener($,x)}),document.removeEventListener("click",C)},hide(){p()},isVisible(){return d}}};var rm=ne('');function Do(e,t){ue(t,!0);const n=w(t,"children",7),r=w(t,"floating",7),o=w(t,"placement",7,"bottom");let i,s,a;rn(()=>(a=nm({trigger:i,floatContent:s,interactive:!0,placement:o()}),()=>{a.destroy()}));function l(){a.hide()}var u=rm(),c=X(u),f=X(c);cr(f,n),Z(c),An(c,p=>i=p,()=>i);var d=z(c,2),g=X(d);return cr(g,r),Z(d),An(d,p=>s=p,()=>s),Z(u),L(e,u),ce({hide:l,get children(){return n()},set children(p){n(p),y()},get floating(){return r()},set floating(p){r(p),y()},get placement(){return o()},set placement(p="bottom"){o(p),y()}})}ie(Do,{children:{},floating:{},placement:{}},[],["hide"],!0);function je(e,t){ue(t,!0);const n=w(t,"children",7),r=w(t,"level",7,1),o=w(t,"mt",7),i=w(t,"mb",7);var s=tt(),a=xe(s);return t1(a,()=>`h${r()}`,!1,(l,u)=>{let c;Ee(()=>c=nn(l,c,{class:"tf-heading",style:`margin-top:${o()||"0"};margin-bottom:${i()||"0"}`},void 0,l.namespaceURI===Ea,l.nodeName.includes("-")));var f=tt(),d=xe(f);cr(d,()=>n()??gt),L(u,f)}),L(e,s),ce({get children(){return n()},set children(l){n(l),y()},get level(){return r()},set level(l=1){r(l),y()},get mt(){return o()},set mt(l){o(l),y()},get mb(){return i()},set mb(l){i(l),y()}})}ie(je,{children:{},level:{},mt:{},mb:{}},[],[],!0);var om=_e('');const im={hash:"svelte-1rvn4a8",code:".input-btn-more {border:1px solid transparent;padding:3px;&:hover {background:#eee;border:1px solid transparent;}}"};function qi(e,t){ue(t,!0),et(e,im);const n=xt(t,["$$slots","$$events","$$legacy","$$host"]);Ge(e,ft(()=>n,{get class(){return`input-btn-more ${t.class??""}`},children:(r,o)=>{var i=om();L(r,i)},$$slots:{default:!0}})),ce()}ie(qi,{},[],[],!0);const sm=()=>{const e=Ue();return{deleteNode:n=>{e.nodes.update(r=>r.filter(o=>o.id!==n)),e.edges.update(r=>r.filter(o=>o.source!==n&&o.target!==n))}}},Kr=(e=16)=>{const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",n=new Uint8Array(e);return crypto.getRandomValues(n),Array.from(n,r=>t[r%t.length]).join("")},am=()=>{const{nodes:e,nodeLookup:t}=Ue();return{copyNode:r=>{var s;const i=(s=q(t).get(r))==null?void 0:s.internals.userNode;if(i){const a=Kr(),l={...i,id:a,position:{x:i.position.x+50,y:i.position.y+50}};e.update(u=>[...u,l]),e.update(u=>u.map(c=>c.id===a?{...c,selected:!0}:{...c,selected:!1}))}}}};var lm=_e(''),um=_e(''),cm=_e(''),dm=ne('
'),fm=ne(' ',1);const gm={hash:"svelte-44dmwv",code:".tf-node-toolbar.svelte-44dmwv {display:flex;gap:5px;padding:5px;border-radius:5px;background:#fff;border:1px solid #eee;box-shadow:0 0 5px rgba(0, 0, 0, 0.1);}.tf-node-toolbar-item {border:1px solid transparent;}"};function dn(e,t){ue(t,!0),et(e,gm);const n=w(t,"data",7),r=w(t,"id",7,""),o=w(t,"icon",7),i=w(t,"handle",7),s=w(t,"children",7),a=w(t,"allowExecute",7,!0),l=w(t,"allowCopy",7,!0),u=w(t,"allowDelete",7,!0),c=w(t,"showSourceHandle",7,!0),f=w(t,"showTargetHandle",7,!0);let d=n().expand?["key"]:[];const{updateNodeData:g}=Lt(),p=[{key:"key",icon:o(),title:n().title,description:n().description,content:s()}],{deleteNode:x}=sm(),{copyNode:C}=am();var $=fm(),m=xe($);{var _=O=>{Zc(O,{get position(){return $e.Top},align:"end",children:(R,S)=>{var M=dm(),k=X(M);{var P=K=>{Ge(K,{class:"tf-node-toolbar-item",children:(se,ee)=>{var W=lm();L(se,W)},$$slots:{default:!0}})};ke(k,K=>{a()&&K(P)})}var H=z(k,2);{var I=K=>{Ge(K,{class:"tf-node-toolbar-item",onclick:()=>{C(r())},children:(se,ee)=>{var W=um();L(se,W)},$$slots:{default:!0}})};ke(H,K=>{l()&&K(I)})}var B=z(H,2);{var F=K=>{Ge(K,{class:"tf-node-toolbar-item",onclick:()=>{x(r())},children:(se,ee)=>{var W=cm();L(se,W)},$$slots:{default:!0}})};ke(B,K=>{u()&&K(F)})}Z(M),L(R,M)},$$slots:{default:!0}})};ke(m,O=>{(a()||l()||u())&&O(_)})}var v=z(m,2),b=z(X(v),2),N=X(b);Kc(N,{items:p,activeKeys:d,onChange:(O,R)=>{g(r(),{expand:R==null?void 0:R.includes("key")})}}),Z(b),Z(v);var E=z(v,2);{var T=O=>{er(O,{type:"target",get position(){return $e.Left},style:" left: -12px;top: 20px"})};ke(E,O=>{f()&&O(T)})}var D=z(E,2);{var V=O=>{er(O,{type:"source",get position(){return $e.Right},style:"right: -12px;top: 20px"})};ke(D,O=>{c()&&O(V)})}var A=z(D,2);return cr(A,()=>i()??gt),L(e,$),ce({get data(){return n()},set data(O){n(O),y()},get id(){return r()},set id(O=""){r(O),y()},get icon(){return o()},set icon(O){o(O),y()},get handle(){return i()},set handle(O){i(O),y()},get children(){return s()},set children(O){s(O),y()},get allowExecute(){return a()},set allowExecute(O=!0){a(O),y()},get allowCopy(){return l()},set allowCopy(O=!0){l(O),y()},get allowDelete(){return u()},set allowDelete(O=!0){u(O),y()},get showSourceHandle(){return c()},set showSourceHandle(O=!0){c(O),y()},get showTargetHandle(){return f()},set showTargetHandle(O=!0){f(O),y()}})}ie(dn,{data:{},id:{},icon:{},handle:{},children:{},allowExecute:{},allowCopy:{},allowDelete:{},showSourceHandle:{},showTargetHandle:{}},[],[],!0);function pt(){return ur("svelteflow__node_id")}const cd=[{value:"String",label:"String"},{value:"Number",label:"Number"},{value:"Boolean",label:"Boolean"},{value:"File",label:"File"},{value:"Object",label:"Object"},{value:"Array",label:"Array"}],hm=[{value:"ref",label:"引用"},{value:"input",label:"固定值"}];var vm=ne(''),pm=_e(''),mm=ne(' ',1);const ym={hash:"svelte-laou7w",code:".input-item.svelte-laou7w {display:flex;align-items:center;}.input-more-setting.svelte-laou7w {display:flex;flex-direction:column;gap:10px;padding:10px;background:#fff;border:1px solid #ddd;border-radius:5px;width:200px;box-shadow:0 0 10px 2px rgba(0, 0, 0, 0.1);}.input-more-setting.svelte-laou7w .input-more-item:where(.svelte-laou7w) {display:flex;flex-direction:column;gap:3px;font-size:12px;color:#666;}"};function dd(e,t){ue(t,!0),et(e,ym);const[n,r]=nt(),o=()=>Q(h(l),"$node",n),i=w(t,"parameter",7),s=w(t,"index",7);let a=pt(),l=Ne(()=>pr(a)),u=Ne(()=>{var T,D;return{...i(),...(D=(T=o())==null?void 0:T.data)==null?void 0:D.parameters[s()]}});const{updateNodeData:c}=Lt(),f=T=>{const D=T.target.value;c(a,V=>{let A=V.data.parameters;return A[s()].name=D,{parameters:A}})},d=T=>{const D=T.target.checked;c(a,V=>{let A=V.data.parameters;return A[s()].required=D,{parameters:A}})},g=T=>{const D=T.value;D&&c(a,V=>{let A=V.data.parameters;return A[s()].dataType=D,{parameters:A}})};let p;const x=()=>{c(a,T=>{let D=T.data.parameters;return D.splice(s(),1),{parameters:[...D]}}),p==null||p.hide()};var C=mm(),$=xe(C),m=X($);St(m,{style:"width: 100%;",get value(){return h(u).name},placeholder:"请输入参数名称",oninput:f}),Z($);var _=z($,2),v=X(_);Fc(v,{get checked(){return h(u).required},onchange:d}),Z(_);var b=z(_,2),N=X(b);An(Do(N,{placement:"bottom",floating:D=>{var V=vm(),A=X(V),O=z(X(A));const R=Ne(()=>h(u).dataType?[h(u).dataType]:["String"]);ln(O,{items:cd,style:"width: 100%",onSelect:g,get value(){return h(R)}}),Z(A);var S=z(A,2),M=z(X(S));Pt(M,{rows:1,style:"width: 100%;"}),Z(S);var k=z(S,2),P=z(X(k));Pt(P,{rows:3,style:"width: 100%;"}),Z(k);var H=z(k,2),I=X(H);Ge(I,{onclick:x,children:(B,F)=>{Pe();var K=Ae("删除");L(B,K)},$$slots:{default:!0}}),Z(H),Z(V),L(D,V)},children:(D,V)=>{Ge(D,{class:"input-btn-more",children:(A,O)=>{var R=pm();L(A,R)},$$slots:{default:!0}})},$$slots:{floating:!0,default:!0}}),D=>p=D,()=>p),Z(b),L(e,C);var E=ce({get parameter(){return i()},set parameter(T){i(T),y()},get index(){return s()},set index(T){s(T),y()}});return r(),E}ie(dd,{parameter:{},index:{}},[],[],!0);var wm=ne(' ',1),_m=ne('无输入参数
'),xm=ne('
');const bm={hash:"svelte-3n0wca",code:`.input-container.svelte-3n0wca {display:grid;grid-template-columns:80% 10% 10%;row-gap:5px;column-gap:3px;}.input-container.svelte-3n0wca .none-params:where(.svelte-3n0wca) {font-size:12px;background:#f8f8f8;height:40px;display:flex;justify-content:center;align-items:center;border-radius:5px;width:calc(100% - 5px);grid-column:1 / -1;
+ /* 从第一列开始到最后一列结束 */}.input-container.svelte-3n0wca .input-header:where(.svelte-3n0wca) {font-size:12px;color:#666;}`};function fd(e,t){ue(t,!0),et(e,bm);const[n,r]=nt(),o=()=>Q(h(s),"$node",n);let i=pt(),s=Ne(()=>pr(i)),a=Ne(()=>{var d,g;return[...((g=(d=o())==null?void 0:d.data)==null?void 0:g.parameters)||[]]});var l=xm(),u=X(l);{var c=d=>{var g=wm();Pe(4),L(d,g)};ke(u,d=>{h(a).length!==0&&d(c)})}var f=z(u,2);Yt(f,19,()=>h(a),d=>d.id,(d,g,p)=>{dd(d,{get parameter(){return h(g)},get index(){return h(p)}})},d=>{var g=_m();L(d,g)}),Z(l),L(e,l),ce(),r()}ie(fd,{},[],[],!0);const gd=e=>{!e||e.length==0||e.forEach(t=>{t.id||(t.id=Kr()),gd(t.children)})},kn=()=>{const{updateNodeData:e}=Lt();return{addParameter:(t,n="parameters",r)=>{gd(r==null?void 0:r.children);const o={...r,id:Kr()};e(t,i=>{let s=i.data[n];return s?s.push(o):s=[o],{[n]:[...s]}})}}};var Cm=_e(''),km=_e(''),$m=ne('
',1);const Em={hash:"svelte-r5g35l",code:".heading.svelte-r5g35l {display:flex;margin-bottom:10px;}.input-btn-more {border:1px solid transparent;padding:3px;}.input-btn-more:hover {background:#eee;border:1px solid transparent;}"};function hd(e,t){ue(t,!0),et(e,Em);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn();return dn(e,ft(()=>r,{get data(){return n()},allowExecute:!1,showTargetHandle:!1,icon:a=>{var l=Cm();L(a,l)},children:(a,l)=>{var u=$m(),c=xe(u),f=X(c);je(f,{level:3,children:(p,x)=>{Pe();var C=Ae("输入参数");L(p,C)},$$slots:{default:!0}});var d=z(f,2);Ge(d,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o)},children:(p,x)=>{var C=km();L(p,C)},$$slots:{default:!0}}),Z(c);var g=z(c,2);fd(g,{}),L(a,u)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(s){n(s),y()}})}ie(hd,{data:{}},[],[],!0);const vd=(e,t,n)=>{for(let r of n)r.target===t&&r.source&&(e.push(r.source),vd(e,r.source,n))},pd=(e,t)=>{if(e.type==="startNode"){const n=e.data.parameters,r=[];if(n)for(const o of n)r.push({label:o.name+(t?` (Array<${o.dataType||"String"}>)`:` (${o.dataType||"String"})`),value:e.id+"."+o.name});return{label:e.data.title,value:e.id,children:r}}else{if(e.type==="loopNode"&&t)return{label:e.data.title,value:e.id,children:[{label:"loopItem",value:e.id+".loop"},{label:"index (Number)",value:e.id+".index"}]};{const n=e.data.outputDefs;if(n){const r=(o,i)=>!o||o.length===0?[]:o.map(s=>({label:s.name+(t?` (Array<${s.dataType||"String"}>)`:` (${s.dataType||"String"})`),value:i+"."+s.name,children:r(s.children,i+"."+s.name)}));return{label:e.data.title,value:e.id,children:r(n,e.id)}}}}},Sm=(e=!1)=>{const t=pt(),n=pr(t),{nodes:r,edges:o}=Ue();return Un([n,r,o],([i,s,a])=>{const l=[];if(e){for(let u of s)if(u.parentId===i.id){const c=pd(u,u.parentId===i.id);c&&l.push(c)}}else{const u=[];vd(u,t,a);for(let c of s)if(u.includes(c.id)){const f=pd(c,c.parentId===i.id);f&&l.push(f)}}return l})};var Pm=ne(''),Nm=ne(' ',1);const Tm={hash:"svelte-laou7w",code:".input-item.svelte-laou7w {display:flex;align-items:center;}.input-more-setting.svelte-laou7w {display:flex;flex-direction:column;gap:10px;padding:10px;background:#fff;border:1px solid #ddd;border-radius:5px;width:200px;box-shadow:0 0 10px 2px rgba(0, 0, 0, 0.1);}.input-more-setting.svelte-laou7w .input-more-item:where(.svelte-laou7w) {display:flex;flex-direction:column;gap:3px;font-size:12px;color:#666;}"};function md(e,t){ue(t,!0),et(e,Tm);const[n,r]=nt(),o=()=>Q(h(c),"$node",n),i=()=>Q(v,"$selectItems",n),s=w(t,"parameter",7),a=w(t,"index",7),l=w(t,"dataKeyName",7);let u=pt(),c=Ne(()=>pr(u)),f=Ne(()=>{var M;return{...s(),...(M=o())==null?void 0:M.data[l()][a()]}});const{updateNodeData:d}=Lt(),g=(M,k)=>{d(u,P=>{let H=P.data[l()];return H[a()]={...H[a()],[M]:k},{[l()]:H}})},p=M=>{const k=M.target.value;g("name",k)},x=M=>{const k=M.target.value;g("value",k)},C=M=>{const k=M.value;g("ref",k)},$=M=>{const k=M.value;g("refType",k)};let m;const _=()=>{d(u,M=>{let k=M.data[l()];return k.splice(a(),1),{[l()]:[...k]}}),m==null||m.hide()},v=Sm();var b=Nm(),N=xe(b),E=X(N);St(E,{style:"width: 100%;",get value(){return h(f).name},placeholder:"请输入参数名称",oninput:p}),Z(N);var T=z(N,2),D=X(T);{var V=M=>{St(M,{get value(){return h(f).value},placeholder:"请输入参数值",oninput:x})},A=M=>{const k=Ne(()=>[h(f).ref]);ln(M,{get items(){return i()},style:"width: 100%",defaultValue:["ref"],get value(){return h(k)},expandAll:!0,onSelect:C})};ke(D,M=>{h(f).refType==="input"?M(V):M(A,!1)})}Z(T);var O=z(T,2),R=X(O);An(Do(R,{placement:"bottom",floating:k=>{var P=Pm(),H=X(P),I=z(X(H));const B=Ne(()=>h(f).refType?[h(f).refType]:[]);ln(I,{items:hm,style:"width: 100%",defaultValue:["ref"],get value(){return h(B)},onSelect:$}),Z(H);var F=z(H,2),K=z(X(F));Pt(K,{rows:1,style:"width: 100%;",onchange:me=>{const Ce=me.target.value;g("defaultValue",Ce)}}),Z(F);var se=z(F,2),ee=z(X(se));Pt(ee,{rows:3,style:"width: 100%;",onchange:me=>{const Ce=me.target.value;g("description",Ce)}}),Z(se);var W=z(se,2),fe=X(W);Ge(fe,{onclick:_,children:(me,Ce)=>{Pe();var he=Ae("删除");L(me,he)},$$slots:{default:!0}}),Z(W),Z(P),L(k,P)},children:(k,P)=>{qi(k,{})},$$slots:{floating:!0,default:!0}}),k=>m=k,()=>m),Z(O),L(e,b);var S=ce({get parameter(){return s()},set parameter(M){s(M),y()},get index(){return a()},set index(M){a(M),y()},get dataKeyName(){return l()},set dataKeyName(M){l(M),y()}});return r(),S}ie(md,{parameter:{},index:{},dataKeyName:{}},[],[],!0);var Mm=ne(' ',1),Hm=ne('
'),Vm=ne('
');const Dm={hash:"svelte-1sm1mgi",code:`.input-container.svelte-1sm1mgi {display:grid;grid-template-columns:40% 50% 10%;row-gap:5px;column-gap:3px;}.input-container.svelte-1sm1mgi .none-params:where(.svelte-1sm1mgi) {font-size:12px;background:#f8f8f8;height:40px;display:flex;justify-content:center;align-items:center;border-radius:5px;width:calc(100% - 5px);grid-column:1 / -1;
+ /* 从第一列开始到最后一列结束 */}.input-container.svelte-1sm1mgi .input-header:where(.svelte-1sm1mgi) {font-size:12px;color:#666;}`};function Ft(e,t){ue(t,!0),et(e,Dm);const[n,r]=nt(),o=()=>Q(h(l),"$node",n),i=w(t,"noneParameterText",7,"无输入参数"),s=w(t,"dataKeyName",7,"parameters");let a=pt(),l=Ne(()=>pr(a)),u=Ne(()=>{var x;return[...((x=o())==null?void 0:x.data[s()])||[]]});var c=Vm(),f=X(c);{var d=x=>{var C=Mm();Pe(4),L(x,C)};ke(f,x=>{h(u).length!==0&&x(d)})}var g=z(f,2);Yt(g,19,()=>h(u),x=>x.id,(x,C,$)=>{md(x,{get parameter(){return h(C)},get index(){return h($)},get dataKeyName(){return s()}})},x=>{var C=Hm(),$=X(C,!0);Z(C),Ee(()=>Bt($,i())),L(x,C)}),Z(c),L(e,c);var p=ce({get noneParameterText(){return i()},set noneParameterText(x="无输入参数"){i(x),y()},get dataKeyName(){return s()},set dataKeyName(x="parameters"){s(x),y()}});return r(),p}ie(Ft,{noneParameterText:{},dataKeyName:{}},[],[],!0);var Am=_e(''),Lm=_e(''),Om=ne('
',1);const Im={hash:"svelte-11h445j",code:".heading.svelte-11h445j {display:flex;margin-bottom:10px;}"};function yd(e,t){ue(t,!0),et(e,Im);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn();return dn(e,ft({get data(){return n()}},()=>r,{allowExecute:!1,showSourceHandle:!1,icon:a=>{var l=Am();L(a,l)},children:(a,l)=>{var u=Om(),c=xe(u),f=X(c);je(f,{level:3,children:(p,x)=>{Pe();var C=Ae("输出参数");L(p,C)},$$slots:{default:!0}});var d=z(f,2);Ge(d,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o,"outputDefs")},children:(p,x)=>{var C=Lm();L(p,C)},$$slots:{default:!0}}),Z(c);var g=z(c,2);Ft(g,{noneParameterText:"无输出参数",dataKeyName:"outputDefs"}),L(a,u)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(s){n(s),y()}})}ie(yd,{data:{}},[],[],!0);const Ao=()=>ur("tinyflow_options");var zm=_e(''),Rm=ne(''),Bm=ne(''),Ym=ne('
',1);const Zm={hash:"svelte-1cfeest",code:".input-item.svelte-1cfeest {display:flex;align-items:center;gap:2px;}.input-more-setting.svelte-1cfeest {display:flex;flex-direction:column;gap:10px;padding:10px;background:#fff;border:1px solid #ddd;border-radius:5px;width:200px;box-shadow:0 0 10px 2px rgba(0, 0, 0, 0.1);}.input-more-setting.svelte-1cfeest .input-more-item:where(.svelte-1cfeest) {display:flex;flex-direction:column;gap:3px;font-size:12px;color:#666;}"};function wd(e,t){ue(t,!0),et(e,Zm);const[n,r]=nt(),o=()=>Q(h(u),"$node",n),i=w(t,"parameter",7),s=w(t,"position",7),a=w(t,"dataKeyName",7);let l=pt(),u=Ne(()=>pr(l)),c=Ne(()=>{var I;let P=(I=o())==null?void 0:I.data[a()],H;if(P&&s().length>0){let B=P;for(let F=0;F{f(l,I=>{const B=I.data[a()];if(B&&s().length>0){let F=B;for(let K=0;K{const H=P.target.value;d("name",H)},p=P=>{const H=P.value;d("dataType",H)};let x;const C=()=>{f(l,P=>{let H=P.data[a()];if(H&&s().length>0){let I=H;for(let B=0;B{f(l,P=>{let H=P.data[a()];if(H&&s().length>0){let I=H;for(let B=0;B{var H=tt(),I=xe(H);Yt(I,17,s,oi,(B,F)=>{Pe();var K=Ae(" ");L(B,K)}),L(P,H)};ke(v,P=>{s().length>1&&P(b)})}var N=z(v,2);const E=Ne(()=>h(c).nameDisabled===!0);St(N,{style:"width: 100%;",get value(){return h(c).name},placeholder:"请输入参数名称",oninput:g,get disabled(){return h(E)}}),Z(_);var T=z(_,2),D=X(T);const V=Ne(()=>h(c).dataType?[h(c).dataType]:[]),A=Ne(()=>h(c).dataTypeDisabled===!0);ln(D,{items:cd,style:"width: 100%",defaultValue:["String"],get value(){return h(V)},get disabled(){return h(A)},onSelect:p});var O=z(D,2);{var R=P=>{Ge(P,{class:"input-btn-more",style:"margin-left: auto",onclick:$,children:(H,I)=>{var B=zm();L(H,B)},$$slots:{default:!0}})};ke(O,P=>{(h(c).dataType==="Object"||h(c).dataType==="Array")&&h(c).addChildDisabled!==!0&&P(R)})}Z(T);var S=z(T,2),M=X(S);An(Do(M,{placement:"bottom",floating:H=>{var I=Bm(),B=X(I),F=z(X(B));Pt(F,{rows:1,style:"width: 100%;",onchange:fe=>{const me=fe.target.value;d("defaultValue",me)}}),Z(B);var K=z(B,2),se=z(X(K));Pt(se,{rows:3,style:"width: 100%;",onchange:fe=>{const me=fe.target.value;d("description",me)}}),Z(K);var ee=z(K,2);{var W=fe=>{var me=Rm(),Ce=X(me);Ge(Ce,{onclick:C,children:(he,ze)=>{Pe();var G=Ae("删除");L(he,G)},$$slots:{default:!0}}),Z(me),L(fe,me)};ke(ee,fe=>{h(c).deleteDisabled!==!0&&fe(W)})}Z(I),L(H,I)},children:(H,I)=>{qi(H,{})},$$slots:{floating:!0,default:!0}}),H=>x=H,()=>x),Z(S),L(e,m);var k=ce({get parameter(){return i()},set parameter(P){i(P),y()},get position(){return s()},set position(P){s(P),y()},get dataKeyName(){return a()},set dataKeyName(P){a(P),y()}});return r(),k}ie(wd,{parameter:{},position:{},dataKeyName:{}},[],[],!0);var Xm=ne(" ",1),Fm=ne('
'),Wm=ne(' ',1),Km=ne('
');const qm={hash:"svelte-1sm1mgi",code:`.input-container.svelte-1sm1mgi {display:grid;grid-template-columns:40% 50% 10%;row-gap:5px;column-gap:3px;}.input-container.svelte-1sm1mgi .none-params:where(.svelte-1sm1mgi) {font-size:12px;background:#f8f8f8;height:40px;display:flex;justify-content:center;align-items:center;border-radius:5px;width:calc(100% - 5px);grid-column:1 / -1;
+ /* 从第一列开始到最后一列结束 */}.input-container.svelte-1sm1mgi .input-header:where(.svelte-1sm1mgi) {font-size:12px;color:#666;}`};function Yn(e,t){ue(t,!0),et(e,qm);const[n,r]=nt(),o=()=>Q(h(u),"$node",n),i=(C,$=gt,m=gt)=>{var _=tt(),v=xe(_);Yt(v,19,$,b=>`${b.id}_${b.children?b.children.length:0}`,(b,N,E)=>{var T=Xm(),D=xe(T);const V=Ne(()=>[...m(),h(E)]);wd(D,{get parameter(){return h(N)},get position(){return h(V)},get dataKeyName(){return a()}});var A=z(D,2);{var O=R=>{var S=ve(()=>[...m(),h(E)]);i(R,()=>h(N).children,()=>h(S))};ke(A,R=>{h(N).children&&R(O)})}L(b,T)},b=>{var N=tt(),E=xe(N);{var T=D=>{var V=Fm(),A=X(V,!0);Z(V),Ee(()=>Bt(A,s())),L(D,V)};ke(E,D=>{m().length===0&&D(T)})}L(b,N)}),L(C,_)},s=w(t,"noneParameterText",7,"无输出参数"),a=w(t,"dataKeyName",7,"outputDefs");let l=pt(),u=Ne(()=>pr(l)),c=Ne(()=>{var C;return[...((C=o())==null?void 0:C.data[a()])||[]]});var f=Km(),d=X(f);{var g=C=>{var $=Wm();Pe(4),L(C,$)};ke(d,C=>{h(c).length!==0&&C(g)})}var p=z(d,2);i(p,()=>h(c)||[],()=>[]),Z(f),L(e,f);var x=ce({get noneParameterText(){return s()},set noneParameterText(C="无输出参数"){s(C),y()},get dataKeyName(){return a()},set dataKeyName(C="outputDefs"){a(C),y()}});return r(),x}ie(Yn,{noneParameterText:{},dataKeyName:{}},[],[],!0);var Gm=_e(''),Um=_e(''),jm=_e(''),Jm=ne('
模型
采样参数
系统提示词
用户提示词
',1);const Qm={hash:"svelte-wn2kra",code:`.heading.svelte-wn2kra {display:flex;margin-bottom:10px;}.setting-title.svelte-wn2kra {font-size:12px;color:#999;margin-bottom:4px;margin-top:10px;}.setting-item.svelte-wn2kra {display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;gap:10px;}\r
+ /* 新增样式 */.slider-container.svelte-wn2kra {width:100%;display:flex;flex-direction:column;gap:4px;}.slider-container.svelte-wn2kra label:where(.svelte-wn2kra) {font-size:12px;color:#666;display:flex;justify-content:space-between;align-items:center;}input[type="range"].svelte-wn2kra {width:100%;height:4px;background:#ddd;border-radius:2px;outline:none;-webkit-appearance:none;}input[type="range"].svelte-wn2kra::-webkit-slider-thumb {-webkit-appearance:none;width:14px;height:14px;background:#007bff;border-radius:50%;cursor:pointer;}`};function _d(e,t){ue(t,!0),et(e,Qm);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn(),s=Ao();let a=Fn(Ht([]));rn(async()=>{var c,f;const u=await((f=(c=s.provider)==null?void 0:c.llm)==null?void 0:f.call(c));h(a).push(...u||[])});const{updateNodeData:l}=Lt();return dn(e,ft({get data(){return n()}},()=>r,{icon:c=>{var f=Gm();L(c,f)},children:(c,f)=>{var d=Jm(),g=xe(d),p=X(g);je(p,{level:3,children:(G,ae)=>{Pe();var Me=Ae("输入参数");L(G,Me)},$$slots:{default:!0}});var x=z(p,2);Ge(x,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o)},children:(G,ae)=>{var Me=Um();L(G,Me)},$$slots:{default:!0}}),Z(g);var C=z(g,2);Ft(C,{});var $=z(C,2);je($,{level:3,mt:"10px",children:(G,ae)=>{Pe();var Me=Ae("模型设置");L(G,Me)},$$slots:{default:!0}});var m=z($,4),_=X(m);const v=Ne(()=>n().llmId?[n().llmId]:[]);ln(_,{get items(){return h(a)},style:"width: 100%",placeholder:"请选择模型",onSelect:G=>{const ae=G.value;l(o,()=>({llmId:ae}))},get value(){return h(v)}});var b=z(_,2);qi(b,{}),Z(m);var N=z(m,4),E=X(N),T=X(E),D=X(T);Z(T);var V=z(T,2);ao(V),Z(E),Z(N);var A=z(N,2),O=X(A),R=X(O),S=X(R);Z(R);var M=z(R,2);ao(M),Z(O),Z(A);var k=z(A,2),P=X(k),H=X(P),I=X(H);Z(H);var B=z(H,2);ao(B),Z(P),Z(k);var F=z(k,4),K=X(F);const se=Ne(()=>n().systemPrompt||"");Pt(K,{rows:5,placeholder:"请输入系统提示词",style:"width: 100%",get value(){return h(se)},oninput:G=>{l(o,{systemPrompt:G.target.value})}}),Z(F);var ee=z(F,4),W=X(ee);const fe=Ne(()=>n().userPrompt||"");Pt(W,{rows:5,placeholder:"请输入用户提示词",style:"width: 100%",get value(){return h(fe)},oninput:G=>{l(o,{userPrompt:G.target.value})}}),Z(ee);var me=z(ee,2),Ce=X(me);je(Ce,{level:3,mt:"10px",children:(G,ae)=>{Pe();var Me=Ae("输出参数");L(G,Me)},$$slots:{default:!0}});var he=z(Ce,2);Ge(he,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o,"outputDefs")},children:(G,ae)=>{var Me=jm();L(G,Me)},$$slots:{default:!0}}),Z(me);var ze=z(me,2);Yn(ze,{}),Ee(()=>{Bt(D,`Temperature: ${n().temperature??.5}`),bs(V,n().temperature??.5),Bt(S,`Top P: ${n().topP??.9}`),bs(M,n().topP??.9),Bt(I,`Top K: ${n().topK??50}`),bs(B,n().topK??50)}),Ze("mousedown",V,ks(function(G){De.call(this,t,G)})),Ze("input",V,G=>l(o,{temperature:parseFloat(G.target.value)})),Ze("mousedown",M,ks(function(G){De.call(this,t,G)})),Ze("input",M,G=>l(o,{topP:parseFloat(G.target.value)})),Ze("mousedown",B,ks(function(G){De.call(this,t,G)})),Ze("input",B,G=>l(o,{topK:parseInt(G.target.value)})),L(c,d)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(u){n(u),y()}})}ie(_d,{data:{}},[],[],!0);var ey=_e(''),ty=_e(''),ny=_e(''),ry=ne('
执行引擎
执行代码
',1);const oy={hash:"svelte-15t2v24",code:".heading.svelte-15t2v24 {display:flex;margin-bottom:10px;}.setting-title.svelte-15t2v24 {font-size:12px;color:#999;margin-bottom:4px;margin-top:10px;}.setting-item.svelte-15t2v24 {display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;gap:10px;}"};function xd(e,t){ue(t,!0),et(e,oy);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn(),{updateNodeData:s}=Lt(),a=[{label:"QLExpress",value:"qlexpress"},{label:"Groovy",value:"groovy"},{label:"JavaScript",value:"js"}];return dn(e,ft({get data(){return n()}},()=>r,{icon:u=>{var c=ey();L(u,c)},children:(u,c)=>{var f=ry(),d=xe(f),g=X(d);je(g,{level:3,children:(A,O)=>{Pe();var R=Ae("输入参数");L(A,R)},$$slots:{default:!0}});var p=z(g,2);Ge(p,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o)},children:(A,O)=>{var R=ty();L(A,R)},$$slots:{default:!0}}),Z(d);var x=z(d,2);Ft(x,{});var C=z(x,2);je(C,{level:3,mt:"10px",children:(A,O)=>{Pe();var R=Ae("代码");L(A,R)},$$slots:{default:!0}});var $=z(C,4),m=X($);const _=Ne(()=>n().engine?[n().engine]:["qlexpress"]);ln(m,{items:a,style:"width: 100%",placeholder:"请选择执行引擎",onSelect:A=>{const O=A.value;s(o,()=>({engine:O}))},get value(){return h(_)}}),Z($);var v=z($,4),b=X(v);const N=Ne(()=>n().code||"");Pt(b,{rows:10,placeholder:"请输入执行代码,注:输出内容需添加到_result中,如:_result.put(key, value)",style:"width: 100%",onchange:A=>{s(o,()=>({code:A.target.value}))},get value(){return h(N)}}),Z(v);var E=z(v,2),T=X(E);je(T,{level:3,mt:"10px",children:(A,O)=>{Pe();var R=Ae("输出参数");L(A,R)},$$slots:{default:!0}});var D=z(T,2);Ge(D,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o,"outputDefs")},children:(A,O)=>{var R=ny();L(A,R)},$$slots:{default:!0}}),Z(E);var V=z(E,2);Yn(V,{}),L(u,f)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(l){n(l),y()}})}ie(xd,{data:{}},[],[],!0);var iy=_e(''),sy=_e(''),ay=ne('
执行代码
',1);const ly={hash:"svelte-15t2v24",code:".heading.svelte-15t2v24 {display:flex;margin-bottom:10px;}.setting-title.svelte-15t2v24 {font-size:12px;color:#999;margin-bottom:4px;margin-top:10px;}.setting-item.svelte-15t2v24 {display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;gap:10px;}"};function bd(e,t){ue(t,!0),et(e,ly);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn(),{updateNodeData:s}=Lt();return kr(()=>{(!n().outputDefs||n().outputDefs.length===0)&&i(o,"outputDefs",{name:"output",dataType:"String",dataTypeDisabled:!0,deleteDisabled:!0})}),dn(e,ft({get data(){return n()}},()=>r,{icon:l=>{var u=iy();L(l,u)},children:(l,u)=>{var c=ay(),f=xe(c),d=X(f);je(d,{level:3,children:(N,E)=>{Pe();var T=Ae("输入参数");L(N,T)},$$slots:{default:!0}});var g=z(d,2);Ge(g,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o)},children:(N,E)=>{var T=sy();L(N,T)},$$slots:{default:!0}}),Z(f);var p=z(f,2);Ft(p,{});var x=z(p,2);je(x,{level:3,mt:"10px",children:(N,E)=>{Pe();var T=Ae("代码");L(N,T)},$$slots:{default:!0}});var C=z(x,4),$=X(C);const m=Ne(()=>n().template||"");Pt($,{rows:10,placeholder:"请输入执行代码",style:"width: 100%",onchange:N=>{s(o,()=>({template:N.target.value}))},get value(){return h(m)}}),Z(C);var _=z(C,2),v=X(_);je(v,{level:3,mt:"10px",children:(N,E)=>{Pe();var T=Ae("输出参数");L(N,T)},$$slots:{default:!0}}),Z(_);var b=z(_,2);Yn(b,{}),L(l,c)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(a){n(a),y()}})}ie(bd,{data:{}},[],[],!0);var uy=_e(''),cy=_e(''),dy=_e(''),fy=_e(''),gy=ne('
',1),hy=_e(''),vy=ne('
',1),py=ne(''),my=ne(''),yy=_e(''),wy=ne('
',1);const _y={hash:"svelte-1vtcqdz",code:".heading.svelte-1vtcqdz {display:flex;margin-bottom:10px;}.radio-group.svelte-1vtcqdz {display:flex;margin:10px 0;}.radio-group.svelte-1vtcqdz label:where(.svelte-1vtcqdz) {display:flex;font-size:14px;}"};function Cd(e,t){ue(t,!0),et(e,_y);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=[{value:"get",label:"GET"},{value:"post",label:"POST"},{value:"put",label:"PUT"},{value:"delete",label:"DELETE"},{value:"head",label:"HEAD"},{value:"patch",label:"PATCH"}],i=pt(),{addParameter:s}=kn(),{updateNodeData:a}=Lt();return dn(e,ft({get data(){return n()}},()=>r,{icon:u=>{var c=uy();L(u,c)},children:(u,c)=>{var f=wy(),d=xe(f),g=X(d),p=X(g);const x=Ne(()=>n().method?[n().method]:["get"]);ln(p,{items:o,style:"width: 100%",placeholder:"请选择请求方式",onSelect:oe=>{const pe=oe.value;a(i,()=>({method:pe}))},get value(){return h(x)}}),Z(g);var C=z(g,2),$=X(C);const m=Ne(()=>n().url||"");St($,{placeholder:"请输入url",style:"width: 100%",onchange:oe=>{a(i,()=>({url:oe.target.value}))},get value(){return h(m)}}),Z(C),Z(d);var _=z(d,2),v=X(_);je(v,{level:3,children:(oe,pe)=>{Pe();var be=Ae("Http 头信息");L(oe,be)},$$slots:{default:!0}});var b=z(v,2);Ge(b,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{s(i,"headers")},children:(oe,pe)=>{var be=cy();L(oe,be)},$$slots:{default:!0}}),Z(_);var N=z(_,2);Ft(N,{dataKeyName:"headers"});var E=z(N,2),T=X(E);je(T,{level:3,children:(oe,pe)=>{Pe();var be=Ae("参数");L(oe,be)},$$slots:{default:!0}});var D=z(T,2);Ge(D,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{s(i,"urlParameters")},children:(oe,pe)=>{var be=dy();L(oe,be)},$$slots:{default:!0}}),Z(E);var V=z(E,2);Ft(V,{dataKeyName:"urlParameters"});var A=z(V,2);je(A,{level:3,mt:"10px",children:(oe,pe)=>{Pe();var be=Ae("Body");L(oe,be)},$$slots:{default:!0}});var O=z(A,2),R=X(O),S=X(R);const M=Ne(()=>!n().bodyType);St(S,{type:"radio",name:"bodyType",value:"",get checked(){return h(M)},onchange:oe=>{var pe;(pe=oe.target)!=null&&pe.checked&&a(i,{bodyType:""})}}),Pe(),Z(R);var k=z(R,2),P=X(k);const H=Ne(()=>n().bodyType==="form-data");St(P,{type:"radio",name:"bodyType",value:"form-data",get checked(){return h(H)},onchange:oe=>{var pe;(pe=oe.target)!=null&&pe.checked&&a(i,{bodyType:"form-data"})}}),Pe(),Z(k);var I=z(k,2),B=X(I);const F=Ne(()=>n().bodyType==="x-www-form-urlencoded");St(B,{type:"radio",name:"bodyType",value:"x-www-form-urlencoded",get checked(){return h(F)},onchange:oe=>{var pe;(pe=oe.target)!=null&&pe.checked&&a(i,{bodyType:"x-www-form-urlencoded"})}}),Pe(),Z(I);var K=z(I,2),se=X(K);const ee=Ne(()=>n().bodyType==="json");St(se,{type:"radio",name:"bodyType",value:"json",get checked(){return h(ee)},onchange:oe=>{var pe;(pe=oe.target)!=null&&pe.checked&&a(i,{bodyType:"json"})}}),Pe(),Z(K);var W=z(K,2),fe=X(W);const me=Ne(()=>n().bodyType==="raw");St(fe,{type:"radio",name:"bodyType",value:"raw",get checked(){return h(me)},onchange:oe=>{var pe;(pe=oe.target)!=null&&pe.checked&&a(i,{bodyType:"raw"})}}),Pe(),Z(W),Z(O);var Ce=z(O,2);{var he=oe=>{var pe=gy(),be=xe(pe),Ie=X(be);je(Ie,{level:3,children:(J,Re)=>{Pe();var le=Ae("参数");L(J,le)},$$slots:{default:!0}});var ht=z(Ie,2);Ge(ht,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{s(i,"fromData")},children:(J,Re)=>{var le=fy();L(J,le)},$$slots:{default:!0}}),Z(be);var dt=z(be,2);Ft(dt,{dataKeyName:"fromData"}),L(oe,pe)};ke(Ce,oe=>{n().bodyType==="form-data"&&oe(he)})}var ze=z(Ce,2);{var G=oe=>{var pe=vy(),be=xe(pe),Ie=X(be);je(Ie,{level:3,children:(J,Re)=>{Pe();var le=Ae("参数");L(J,le)},$$slots:{default:!0}});var ht=z(Ie,2);Ge(ht,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{s(i,"fromUrlencoded")},children:(J,Re)=>{var le=hy();L(J,le)},$$slots:{default:!0}}),Z(be);var dt=z(be,2);Ft(dt,{dataKeyName:"fromUrlencoded"}),L(oe,pe)};ke(ze,oe=>{n().bodyType==="x-www-form-urlencoded"&&oe(G)})}var ae=z(ze,2);{var Me=oe=>{var pe=py(),be=X(pe);Pt(be,{rows:"5",style:"width: 100%",placeholder:"请输入 json 信息",get value(){return n().bodyJson},oninput:Ie=>{a(i,{bodyJson:Ie.target.value})}}),Z(pe),L(oe,pe)};ke(ae,oe=>{n().bodyType==="json"&&oe(Me)})}var Le=z(ae,2);{var Xe=oe=>{var pe=my(),be=X(pe);Pt(be,{rows:"5",style:"width: 100%",placeholder:"请输入请求信息",get value(){return n().bodyRaw},oninput:Ie=>{a(i,{bodyRaw:Ie.target.value})}}),Z(pe),L(oe,pe)};ke(Le,oe=>{n().bodyType==="raw"&&oe(Xe)})}var te=z(Le,2),Fe=X(te);je(Fe,{level:3,mt:"10px",children:(oe,pe)=>{Pe();var be=Ae("输出参数");L(oe,be)},$$slots:{default:!0}});var Oe=z(Fe,2);Ge(Oe,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{s(i,"outputDefs")},children:(oe,pe)=>{var be=yy();L(oe,be)},$$slots:{default:!0}}),Z(te);var rt=z(te,2);Yn(rt,{}),L(u,f)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(l){n(l),y()}})}ie(Cd,{data:{}},[],[],!0);var xy=_e(''),by=_e(''),Cy=ne('
知识库
获取数据量
',1);const ky={hash:"svelte-15t2v24",code:".heading.svelte-15t2v24 {display:flex;margin-bottom:10px;}.setting-title.svelte-15t2v24 {font-size:12px;color:#999;margin-bottom:4px;margin-top:10px;}.setting-item.svelte-15t2v24 {display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;gap:10px;}"};function kd(e,t){ue(t,!0),et(e,ky);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn(),s=Ao();let a=Fn(Ht([]));rn(async()=>{var c,f;const u=await((f=(c=s.provider)==null?void 0:c.knowledge)==null?void 0:f.call(c));h(a).push(...u||[])});const{updateNodeData:l}=Lt();return kr(()=>{(!n().outputDefs||n().outputDefs.length===0)&&i(o,"outputDefs",{name:"documents",dataType:"Array",nameDisabled:!0,dataTypeDisabled:!0,addChildDisabled:!0,children:[{name:"title",dataType:"String",nameDisabled:!0,dataTypeDisabled:!0},{name:"content",dataType:"String",nameDisabled:!0,dataTypeDisabled:!0},{name:"documentId",dataType:"Number",nameDisabled:!0,dataTypeDisabled:!0},{name:"knowledgeId",dataType:"Number",nameDisabled:!0,dataTypeDisabled:!0}]})}),dn(e,ft({get data(){return n()}},()=>r,{icon:c=>{var f=xy();L(c,f)},children:(c,f)=>{var d=Cy(),g=xe(d),p=X(g);je(p,{level:3,children:(V,A)=>{Pe();var O=Ae("输入参数");L(V,O)},$$slots:{default:!0}});var x=z(p,2);Ge(x,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o)},children:(V,A)=>{var O=by();L(V,O)},$$slots:{default:!0}}),Z(g);var C=z(g,2);Ft(C,{});var $=z(C,2);je($,{level:3,mt:"10px",children:(V,A)=>{Pe();var O=Ae("知识库设置");L(V,O)},$$slots:{default:!0}});var m=z($,4),_=X(m);const v=Ne(()=>n().knowledgeId?[n().knowledgeId]:[]);ln(_,{get items(){return h(a)},style:"width: 100%",placeholder:"请选择知识库",onSelect:V=>{const A=V.value;l(o,()=>({knowledgeId:A}))},get value(){return h(v)}}),Z(m);var b=z(m,4),N=X(b);St(N,{placeholder:"搜索的数据条数",style:"width: 100%"}),Z(b);var E=z(b,2),T=X(E);je(T,{level:3,mt:"10px",children:(V,A)=>{Pe();var O=Ae("输出参数");L(V,O)},$$slots:{default:!0}}),Z(E);var D=z(E,2);Yn(D,{}),L(c,d)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(u){n(u),y()}})}ie(kd,{data:{}},[],[],!0);var $y=_e(''),Ey=_e(''),Sy=ne('
API 服务商
API Key
关键字
数据量
其他参数
',1);const Py={hash:"svelte-15t2v24",code:".heading.svelte-15t2v24 {display:flex;margin-bottom:10px;}.setting-title.svelte-15t2v24 {font-size:12px;color:#999;margin-bottom:4px;margin-top:10px;}.setting-item.svelte-15t2v24 {display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;gap:10px;}"};function $d(e,t){ue(t,!0),et(e,Py);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn(),s=Ao();let a=Fn(Ht([]));rn(async()=>{var c;const u=await((c=s.provider)==null?void 0:c.knowledge());h(a).push(...u||[])});const{updateNodeData:l}=Lt();return kr(()=>{(!n().outputDefs||n().outputDefs.length===0)&&i(o,"outputDefs",{name:"documents",dataType:"Array",nameDisabled:!0,dataTypeDisabled:!0,addChildDisabled:!0,children:[{name:"title",dataType:"String",nameDisabled:!0,dataTypeDisabled:!0},{name:"content",dataType:"String",nameDisabled:!0,dataTypeDisabled:!0},{name:"documentId",dataType:"Number",nameDisabled:!0,dataTypeDisabled:!0},{name:"knowledgeId",dataType:"Number",nameDisabled:!0,dataTypeDisabled:!0}]})}),dn(e,ft({get data(){return n()}},()=>r,{icon:c=>{var f=$y();L(c,f)},children:(c,f)=>{var d=Sy(),g=xe(d),p=X(g);je(p,{level:3,children:(k,P)=>{Pe();var H=Ae("输入参数");L(k,H)},$$slots:{default:!0}});var x=z(p,2);Ge(x,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o)},children:(k,P)=>{var H=Ey();L(k,H)},$$slots:{default:!0}}),Z(g);var C=z(g,2);Ft(C,{});var $=z(C,2);je($,{level:3,mt:"10px",children:(k,P)=>{Pe();var H=Ae("搜索引擎设置");L(k,H)},$$slots:{default:!0}});var m=z($,4),_=X(m);const v=Ne(()=>n().knowledgeId?[n().knowledgeId]:[]);ln(_,{get items(){return h(a)},style:"width: 100%",placeholder:"请选择 API 服务商",onSelect:k=>{const P=k.value;l(o,()=>({knowledgeId:P}))},get value(){return h(v)}}),Z(m);var b=z(m,4),N=X(b);St(N,{placeholder:"请输入 API Key",style:"width: 100%"}),Z(b);var E=z(b,4),T=X(E);St(T,{placeholder:"请输入关键字",style:"width: 100%"}),Z(E);var D=z(E,4),V=X(D);St(V,{placeholder:"搜索的数据条数",style:"width: 100%"}),Z(D);var A=z(D,4),O=X(A);Pt(O,{rows:3,placeholder:"请输入其他参数(Property 格式)",style:"width: 100%"}),Z(A);var R=z(A,2),S=X(R);je(S,{level:3,mt:"10px",children:(k,P)=>{Pe();var H=Ae("输出参数");L(k,H)},$$slots:{default:!0}}),Z(R);var M=z(R,2);Yn(M,{}),L(c,d)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(u){n(u),y()}})}ie($d,{data:{}},[],[],!0);var Ny=_e(''),Ty=_e(''),My=ne('
',1);const Hy={hash:"svelte-md8tgj",code:".heading.svelte-md8tgj {display:flex;margin-bottom:10px;}.loop_handle_wrapper ::after {content:'循环体';width:100px;height:20px;background:#000;color:#fff;display:flex;justify-content:center;align-items:center;}"};function Ed(e,t){ue(t,!0),et(e,Hy);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn(),s=Ao();let a=Fn(Ht([]));return rn(async()=>{var u;const l=await((u=s.provider)==null?void 0:u.knowledge());h(a).push(...l||[])}),dn(e,ft({get data(){return n()}},()=>r,{icon:c=>{var f=Ny();L(c,f)},handle:c=>{er(c,{type:"source",get position(){return $e.Bottom},id:"loop_handle",style:"bottom: -12px;width: 100px",class:"loop_handle_wrapper"})},children:(c,f)=>{var d=My(),g=xe(d),p=X(g);je(p,{level:3,children:(v,b)=>{Pe();var N=Ae("循环变量");L(v,N)},$$slots:{default:!0}});var x=z(p,2);Ge(x,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o)},children:(v,b)=>{var N=Ty();L(v,N)},$$slots:{default:!0}}),Z(g);var C=z(g,2);Ft(C,{});var $=z(C,2),m=X($);je(m,{level:3,mt:"10px",children:(v,b)=>{Pe();var N=Ae("输出参数");L(v,N)},$$slots:{default:!0}}),Z($);var _=z($,2);Yn(_,{}),L(c,d)},$$slots:{icon:!0,handle:!0,default:!0}})),ce({get data(){return n()},set data(l){n(l),y()}})}ie(Ed,{data:{}},[],[],!0);var Vy=_e(''),Dy=_e(''),Ay=_e(''),Ly=ne('
选择内部接口
',1);const Oy={hash:"svelte-15t2v24",code:".heading.svelte-15t2v24 {display:flex;margin-bottom:10px;}.setting-title.svelte-15t2v24 {font-size:12px;color:#999;margin-bottom:4px;margin-top:10px;}.setting-item.svelte-15t2v24 {display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;gap:10px;}"};function Sd(e,t){ue(t,!0),et(e,Oy);const n=w(t,"data",7),r=xt(t,["$$slots","$$events","$$legacy","$$host","data"]),o=pt(),{addParameter:i}=kn(),{updateNodeData:s}=Lt(),a=Ao();let l=Fn(Ht([]));return rn(async()=>{var c,f;const u=await((f=(c=a.provider)==null?void 0:c.internal)==null?void 0:f.call(c));h(l).push(...u||[])}),dn(e,ft({get data(){return n()}},()=>r,{icon:c=>{var f=Vy();L(c,f)},children:(c,f)=>{var d=Ly(),g=xe(d),p=X(g);je(p,{level:3,children:(D,V)=>{Pe();var A=Ae("输入参数");L(D,A)},$$slots:{default:!0}});var x=z(p,2);Ge(x,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o)},children:(D,V)=>{var A=Dy();L(D,A)},$$slots:{default:!0}}),Z(g);var C=z(g,2);Ft(C,{});var $=z(C,2);je($,{level:3,mt:"10px",children:(D,V)=>{Pe();var A=Ae("接口");L(D,A)},$$slots:{default:!0}});var m=z($,4),_=X(m);const v=Ne(()=>n().method?[n().method]:[""]);ln(_,{get items(){return h(l)},style:"width: 100%",placeholder:"请选择内部接口",onSelect:D=>{const V=D.value;s(o,()=>({method:V}))},get value(){return h(v)}}),Z(m);var b=z(m,2),N=X(b);je(N,{level:3,mt:"10px",children:(D,V)=>{Pe();var A=Ae("输出参数");L(D,A)},$$slots:{default:!0}});var E=z(N,2);Ge(E,{class:"input-btn-more",style:"margin-left: auto",onclick:()=>{i(o,"outputDefs")},children:(D,V)=>{var A=Ay();L(D,A)},$$slots:{default:!0}}),Z(b);var T=z(b,2);Yn(T,{}),L(c,d)},$$slots:{icon:!0,default:!0}})),ce({get data(){return n()},set data(u){n(u),y()}})}ie(Sd,{data:{}},[],[],!0);const Iy={startNode:hd,codeNode:xd,llmNode:_d,templateNode:bd,httpNode:Cd,knowledgeNode:kd,searchEngineNode:$d,loopNode:Ed,internalNode:Sd,endNode:yd};var zy=ne(" ",1);function Pd(e,t){ue(t,!0);const n=w(t,"icon",7),r=w(t,"title",7),o=w(t,"type",7),i=w(t,"description",7),s=w(t,"extra",7);return Ge(e,{draggable:!0,ondragstart:l=>{if(!l.dataTransfer)return null;const u={type:o(),data:{title:r(),description:i(),systemPrompt:"",userPrompt:"",...s()}};l.dataTransfer.setData("application/tinyflow",JSON.stringify(u)),l.dataTransfer.effectAllowed="move"},children:(l,u)=>{var c=zy(),f=xe(c);dl(f,n);var d=z(f);Ee(()=>Bt(d,` ${r()??""}`)),L(l,c)},$$slots:{default:!0}}),ce({get icon(){return n()},set icon(l){n(l),y()},get title(){return r()},set title(l){r(l),y()},get type(){return o()},set type(l){o(l),y()},get description(){return i()},set description(l){i(l),y()},get extra(){return s()},set extra(l){s(l),y()}})}ie(Pd,{icon:{},title:{},type:{},description:{},extra:{}},[],[],!0);var Ry=_e(''),By=_e(''),Yy=ne('');function Nd(e){let t=Fn("base"),n=Fn("show");const r=[{icon:'',title:"开始节点",type:"startNode",description:"开始定义输入参数"},{icon:'',title:"循环",type:"loopNode",description:"用于循环执行任务"},{icon:'',title:"大模型",type:"llmNode",description:"使用大模型处理问题"},{icon:'',title:"知识库",type:"knowledgeNode",description:"通过知识库获取内容"},{icon:'',title:"搜索引擎",type:"searchEngineNode",description:"通过搜索引擎搜索内容"},{icon:'',title:"Http 请求",type:"httpNode",description:"通过 HTTP 请求获取数据"},{icon:'',title:"动态代码",type:"codeNode",description:"动态执行代码"},{icon:'',title:"内容模板",type:"templateNode",description:"通过模板引擎生成内容"},{icon:'',title:"内部接口",type:"internalNode",description:"执行内部提供接口"},{icon:'',title:"结束节点",type:"endNode",description:"结束定义输出参数"}],o=[{label:"基础节点",value:"base"},{label:"业务工具",value:"tools"}];var i=Yy(),s=X(i),a=X(s),l=X(a);Wc(l,{style:"width: 100%",items:o,onChange:p=>{U(t,Ht(p.value.toString()))}}),Z(a);var u=z(a,2),c=X(u);Yt(c,21,()=>r,oi,(p,x)=>{Pd(p,ft(()=>h(x)))}),Z(c);var f=z(c,2),d=X(f);Ge(d,{children:(p,x)=>{Pe();var C=Ae("测试业务按钮");L(p,C)},$$slots:{default:!0}}),Z(f),Z(u),Z(s);var g=z(s,2);Ge(g,{onclick:()=>{U(n,Ht(h(n)?"":"show"))},children:(p,x)=>{var C=tt(),$=xe(C);{var m=v=>{var b=Ry();L(v,b)},_=v=>{var b=By();L(v,b)};ke($,v=>{h(n)==="show"?v(m):v(_,!1)})}L(p,C)},$$slots:{default:!0}}),Z(i),Ee(()=>{$t(i,1,`tf-toolbar ${h(n)??""}`),de(c,"style",`display: ${(h(t)==="base"?"flex":"none")??""}`),de(f,"style",`display: ${(h(t)!=="base"?"flex":"none")??""}`)}),L(e,i)}ie(Nd,{},[],[],!0);const Zy=()=>{const{nodeLookup:e}=Ue();return{getNode:n=>{var o;return(o=q(e).get(n))==null?void 0:o.internals.userNode}}},Xy=()=>{const{nodes:e}=Ue();return{ensureParentInNodesBefore:(n,r)=>{e.update(o=>{let i=-1;for(let l=0;ls;l--)o[l]=o[l-1];return o[s]=a,o})}}},Fy=()=>{const{edges:e}=Ue();return{getEdgesByTarget:n=>q(e).filter(o=>o.target===n)}};var Wy=ne(''),Ky=ne(" ",1),qy=ne('
');const Gy={hash:"svelte-1oe15vw",code:".panel-content.svelte-1oe15vw {padding:10px;background-color:#fff;border-radius:5px;box-shadow:0 2px 4px rgba(0, 0, 0, 0.1);width:200px;border:1px solid #efefef;}.setting-title.svelte-1oe15vw {margin:10px 0;font-size:12px;color:#999;}"};function Td(e,t){ue(t,!0),et(e,Gy);const n=w(t,"onInit",7),r=Lt();n()(r);let o=Fn(!1);const i=_=>{_.preventDefault(),_.dataTransfer&&(_.dataTransfer.dropEffect="move")},s=_=>{var T;_.preventDefault();const v=r.screenToFlowPosition({x:_.clientX-250,y:_.clientY-100}),b=(T=_.dataTransfer)==null?void 0:T.getData("application/tinyflow"),N=b?JSON.parse(b):{},E={id:`node_${Kr()}`,position:v,data:{},...N};Bi.addNode(E),Bi.selectNodeOnly(E.id)},{getNode:a}=Zy(),l=_=>{const v=a(_.source),b=a(_.target);if(_.sourceHandle==="loop_handle"||v.parentId){const N=r.getEdges();for(let E of N)if(E.target===_.target){const T=a(E.source);if(_.sourceHandle==="loop_handle"&&T.parentId!==v.id||v.parentId&&T.parentId!==v.parentId)return!1}}return!(!v.parentId&&b.parentId&&b.parentId!==v.id)},{ensureParentInNodesBefore:u}=Xy(),c=(_,v)=>{if(!v.isValid)return;const b=v.toNode;if(b.parentId)return;const N=v.fromNode,E=v.fromHandle,T={position:{...b.position}};if(E.id==="loop_handle"?T.parentId=N.id:N.parentId&&(T.parentId=N.parentId),T.parentId){const D=a(T.parentId);T.position={x:b.position.x-D.position.x,y:b.position.y-D.position.y},u(T.parentId,b.id),r.updateNode(b.id,T)}},{getEdgesByTarget:f}=Fy(),d=_=>{_.edges.forEach(b=>{const N=a(b.target);if(N.parentId){const E=f(b.target),T=a(N.parentId);if(E.length===0)r.updateNode(N.id,{parentId:void 0,position:{x:N.position.x+T.position.x,y:N.position.y+T.position.y}});else{let D=!1;for(let V=0;V{console.log("onconnectstart: ",_,v)},p=_=>{console.log("onconnect: ",_)};var x=qy(),C=X(x);Nd(C);var $=z(C,2);const m=Ne(()=>({markerEnd:{type:_o.ArrowClosed,width:20,height:20}}));return Pc($,ft({nodeTypes:Iy},Bi,{class:"tinyflow-logo",isValidConnection:l,onconnectend:c,onconnectstart:g,onconnect:p,connectionRadius:50,ondelete:d,onclick:_=>{const v=_.target;v.classList.contains("svelte-flow__edge-interaction")||v.classList.contains("panel-content")||v.closest(".panel-content")||U(o,!1)},get defaultEdgeOptions(){return h(m)},$$events:{drop:s,dragover:i,edgeclick:()=>{U(o,!0)}},children:(_,v)=>{var b=Ky(),N=xe(b);Ic(N,{});var E=z(N,2);Ac(E,{});var T=z(E,2);Rc(T,{});var D=z(T,2);{var V=A=>{So(A,{children:(O,R)=>{var S=Wy(),M=z(X(S),4),k=X(M);Pt(k,{rows:3,placeholder:"请输入边条件",style:"width: 100%",oninput:P=>{}}),Z(M),Z(S),L(O,S)},$$slots:{default:!0}})};ke(D,A=>{h(o)&&A(V)})}L(_,b)},$$slots:{default:!0}})),Z(x),L(e,x),ce({get onInit(){return n()},set onInit(_){n(_),y()}})}ie(Td,{onInit:{}},[],[],!0);function Uy(e,t){ue(t,!0);const n=w(t,"options",7),r=w(t,"onInit",7),{data:o}=n();return Bi.init((o==null?void 0:o.nodes)||[],(o==null?void 0:o.edges)||[]),Sr("tinyflow_options",n()),Nc(e,{fitView:!0,children:(i,s)=>{Td(i,{get onInit(){return r()}})},$$slots:{default:!0}}),ce({get options(){return n()},set options(i){n(i),y()},get onInit(){return r()},set onInit(i){r(i),y()}})}customElements.define("tinyflow-component",ie(Uy,{options:{},onInit:{}},[],[],!1)),We.Tinyflow=J2,Object.defineProperty(We,Symbol.toStringTag,{value:"Module"})});
+//# sourceMappingURL=index.umd.js.map
diff --git a/marketing-ui/admin-ui/src/components/Tooltip/index.ts b/marketing-ui/admin-ui/src/components/Tooltip/index.ts
new file mode 100644
index 0000000..ab66ddf
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Tooltip/index.ts
@@ -0,0 +1,3 @@
+import Tooltip from './src/Tooltip.vue'
+
+export { Tooltip }
diff --git a/marketing-ui/admin-ui/src/components/Tooltip/src/Tooltip.vue b/marketing-ui/admin-ui/src/components/Tooltip/src/Tooltip.vue
new file mode 100644
index 0000000..1a2e09c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Tooltip/src/Tooltip.vue
@@ -0,0 +1,17 @@
+
+
+ {{ title }}
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/UploadFile/index.ts b/marketing-ui/admin-ui/src/components/UploadFile/index.ts
new file mode 100644
index 0000000..97c1d66
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/UploadFile/index.ts
@@ -0,0 +1,5 @@
+import UploadImg from './src/UploadImg.vue'
+import UploadImgs from './src/UploadImgs.vue'
+import UploadFile from './src/UploadFile.vue'
+
+export { UploadImg, UploadImgs, UploadFile }
diff --git a/marketing-ui/admin-ui/src/components/UploadFile/src/UploadFile.vue b/marketing-ui/admin-ui/src/components/UploadFile/src/UploadFile.vue
new file mode 100644
index 0000000..9d0a904
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/UploadFile/src/UploadFile.vue
@@ -0,0 +1,230 @@
+
+
+
+
+
+ 选取文件
+
+
+
+ 大小不超过 {{ fileSize }}MB
+
+
+ 格式为 {{ fileType.join('/') }} 的文件
+
+
+
+
+
{{ row.file.name }}
+
+
+ 下载
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
{{ file.name }}
+
+
+ 下载
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/UploadFile/src/UploadImg.vue b/marketing-ui/admin-ui/src/components/UploadFile/src/UploadImg.vue
new file mode 100644
index 0000000..ac0c162
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/UploadFile/src/UploadImg.vue
@@ -0,0 +1,271 @@
+
+
+
+
+
+
+
+
+ {{ t('action.edit') }}
+
+
+
+ {{ t('action.detail') }}
+
+
+
+ {{ t('action.del') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/UploadFile/src/UploadImgs.vue b/marketing-ui/admin-ui/src/components/UploadFile/src/UploadImgs.vue
new file mode 100644
index 0000000..59857a9
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/UploadFile/src/UploadImgs.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/UploadFile/src/useUpload.ts b/marketing-ui/admin-ui/src/components/UploadFile/src/useUpload.ts
new file mode 100644
index 0000000..2981e12
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/UploadFile/src/useUpload.ts
@@ -0,0 +1,106 @@
+import * as FileApi from '@/api/infra/file'
+import CryptoJS from 'crypto-js'
+import { UploadRawFile, UploadRequestOptions } from 'element-plus/es/components/upload/src/upload'
+import axios from 'axios'
+
+/**
+ * 获得上传 URL
+ */
+export const getUploadUrl = (): string => {
+ return import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/infra/file/upload'
+}
+
+export const useUpload = () => {
+ // 后端上传地址
+ const uploadUrl = getUploadUrl()
+ // 是否使用前端直连上传
+ const isClientUpload = UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE
+ // 重写ElUpload上传方法
+ const httpRequest = async (options: UploadRequestOptions) => {
+ // 模式一:前端上传
+ if (isClientUpload) {
+ // 1.1 生成文件名称
+ const fileName = await generateFileName(options.file)
+ // 1.2 获取文件预签名地址
+ const presignedInfo = await FileApi.getFilePresignedUrl(fileName)
+ // 1.3 上传文件(不能使用 ElUpload 的 ajaxUpload 方法的原因:其使用的是 FormData 上传,Minio 不支持)
+ return axios
+ .put(presignedInfo.uploadUrl, options.file, {
+ headers: {
+ 'Content-Type': options.file.type
+ }
+ })
+ .then(() => {
+ // 1.4. 记录文件信息到后端(异步)
+ createFile(presignedInfo, fileName, options.file)
+ // 通知成功,数据格式保持与后端上传的返回结果一致
+ return { data: presignedInfo.url }
+ })
+ } else {
+ // 模式二:后端上传
+ // 重写 el-upload httpRequest 文件上传成功会走成功的钩子,失败走失败的钩子
+ return new Promise((resolve, reject) => {
+ FileApi.updateFile({ file: options.file })
+ .then((res) => {
+ if (res.code === 0) {
+ resolve(res)
+ } else {
+ reject(res)
+ }
+ })
+ .catch((res) => {
+ reject(res)
+ })
+ })
+ }
+ }
+
+ return {
+ uploadUrl,
+ httpRequest
+ }
+}
+
+/**
+ * 创建文件信息
+ * @param vo 文件预签名信息
+ * @param name 文件名称
+ * @param file 文件
+ */
+function createFile(vo: FileApi.FilePresignedUrlRespVO, name: string, file: UploadRawFile) {
+ const fileVo = {
+ configId: vo.configId,
+ url: vo.url,
+ path: name,
+ name: file.name,
+ type: file.type,
+ size: file.size
+ }
+ FileApi.createFile(fileVo)
+ return fileVo
+}
+
+/**
+ * 生成文件名称(使用算法SHA256)
+ * @param file 要上传的文件
+ */
+async function generateFileName(file: UploadRawFile) {
+ // 读取文件内容
+ const data = await file.arrayBuffer()
+ const wordArray = CryptoJS.lib.WordArray.create(data)
+ // 计算SHA256
+ const sha256 = CryptoJS.SHA256(wordArray).toString()
+ // 拼接后缀
+ const ext = file.name.substring(file.name.lastIndexOf('.'))
+ return `${sha256}${ext}`
+}
+
+/**
+ * 上传类型
+ */
+enum UPLOAD_TYPE {
+ // 客户端直接上传(只支持S3服务)
+ CLIENT = 'client',
+ // 客户端发送到后端上传
+ SERVER = 'server'
+}
diff --git a/marketing-ui/admin-ui/src/components/UserSelectForm/index.vue b/marketing-ui/admin-ui/src/components/UserSelectForm/index.vue
new file mode 100644
index 0000000..5ed99f8
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/UserSelectForm/index.vue
@@ -0,0 +1,171 @@
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/Verifition/index.ts b/marketing-ui/admin-ui/src/components/Verifition/index.ts
new file mode 100644
index 0000000..bcfe6d9
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Verifition/index.ts
@@ -0,0 +1,3 @@
+import Verify from './src/Verify.vue'
+
+export { Verify }
diff --git a/marketing-ui/admin-ui/src/components/Verifition/src/Verify.vue b/marketing-ui/admin-ui/src/components/Verifition/src/Verify.vue
new file mode 100644
index 0000000..b7b5048
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Verifition/src/Verify.vue
@@ -0,0 +1,441 @@
+
+
+
+
+ {{ t('captcha.verification') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/Verifition/src/Verify/VerifyPoints.vue b/marketing-ui/admin-ui/src/components/Verifition/src/Verify/VerifyPoints.vue
new file mode 100644
index 0000000..9d04f29
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Verifition/src/Verify/VerifyPoints.vue
@@ -0,0 +1,250 @@
+
+
+
+
+
+
+
+
![]()
+
+
+ {{ index + 1 }}
+
+
+
+
+
+ {{ text }}
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/Verifition/src/Verify/VerifySlide.vue b/marketing-ui/admin-ui/src/components/Verifition/src/Verify/VerifySlide.vue
new file mode 100644
index 0000000..f3c7bfe
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Verifition/src/Verify/VerifySlide.vue
@@ -0,0 +1,376 @@
+
+
+
+
+
![]()
+
+
+
+
+
+ {{ tipWords }}
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/Verifition/src/Verify/index.ts b/marketing-ui/admin-ui/src/components/Verifition/src/Verify/index.ts
new file mode 100644
index 0000000..0daa63a
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Verifition/src/Verify/index.ts
@@ -0,0 +1,4 @@
+import VerifySlide from './VerifySlide.vue'
+import VerifyPoints from './VerifyPoints.vue'
+
+export { VerifySlide, VerifyPoints }
diff --git a/marketing-ui/admin-ui/src/components/Verifition/src/utils/ase.ts b/marketing-ui/admin-ui/src/components/Verifition/src/utils/ase.ts
new file mode 100644
index 0000000..d2e6b98
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Verifition/src/utils/ase.ts
@@ -0,0 +1,14 @@
+import CryptoJS from 'crypto-js'
+/**
+ * @word 要加密的内容
+ * @keyWord String 服务器随机返回的关键字
+ * */
+export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') {
+ const key = CryptoJS.enc.Utf8.parse(keyWord)
+ const srcs = CryptoJS.enc.Utf8.parse(word)
+ const encrypted = CryptoJS.AES.encrypt(srcs, key, {
+ mode: CryptoJS.mode.ECB,
+ padding: CryptoJS.pad.Pkcs7
+ })
+ return encrypted.toString()
+}
diff --git a/marketing-ui/admin-ui/src/components/Verifition/src/utils/util.ts b/marketing-ui/admin-ui/src/components/Verifition/src/utils/util.ts
new file mode 100644
index 0000000..15c1627
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/Verifition/src/utils/util.ts
@@ -0,0 +1,97 @@
+export function resetSize(vm) {
+ let img_width, img_height, bar_width, bar_height //图片的宽度、高度,移动条的宽度、高度
+ const EmployeeWindow = window as any
+ const parentWidth = vm.$el.parentNode.offsetWidth || EmployeeWindow.offsetWidth
+ const parentHeight = vm.$el.parentNode.offsetHeight || EmployeeWindow.offsetHeight
+ if (vm.imgSize.width.indexOf('%') != -1) {
+ img_width = (parseInt(vm.imgSize.width) / 100) * parentWidth + 'px'
+ } else {
+ img_width = vm.imgSize.width
+ }
+
+ if (vm.imgSize.height.indexOf('%') != -1) {
+ img_height = (parseInt(vm.imgSize.height) / 100) * parentHeight + 'px'
+ } else {
+ img_height = vm.imgSize.height
+ }
+
+ if (vm.barSize.width.indexOf('%') != -1) {
+ bar_width = (parseInt(vm.barSize.width) / 100) * parentWidth + 'px'
+ } else {
+ bar_width = vm.barSize.width
+ }
+
+ if (vm.barSize.height.indexOf('%') != -1) {
+ bar_height = (parseInt(vm.barSize.height) / 100) * parentHeight + 'px'
+ } else {
+ bar_height = vm.barSize.height
+ }
+
+ return { imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height }
+}
+
+export const _code_chars = [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 'a',
+ 'b',
+ 'c',
+ 'd',
+ 'e',
+ 'f',
+ 'g',
+ 'h',
+ 'i',
+ 'j',
+ 'k',
+ 'l',
+ 'm',
+ 'n',
+ 'o',
+ 'p',
+ 'q',
+ 'r',
+ 's',
+ 't',
+ 'u',
+ 'v',
+ 'w',
+ 'x',
+ 'y',
+ 'z',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F',
+ 'G',
+ 'H',
+ 'I',
+ 'J',
+ 'K',
+ 'L',
+ 'M',
+ 'N',
+ 'O',
+ 'P',
+ 'Q',
+ 'R',
+ 'S',
+ 'T',
+ 'U',
+ 'V',
+ 'W',
+ 'X',
+ 'Y',
+ 'Z'
+]
+export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0']
+export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC']
diff --git a/marketing-ui/admin-ui/src/components/VerticalButtonGroup/index.vue b/marketing-ui/admin-ui/src/components/VerticalButtonGroup/index.vue
new file mode 100644
index 0000000..9c78ea2
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/VerticalButtonGroup/index.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/XButton/index.ts b/marketing-ui/admin-ui/src/components/XButton/index.ts
new file mode 100644
index 0000000..be0f0d4
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/XButton/index.ts
@@ -0,0 +1,4 @@
+import XButton from './src/XButton.vue'
+import XTextButton from './src/XTextButton.vue'
+
+export { XButton, XTextButton }
diff --git a/marketing-ui/admin-ui/src/components/XButton/src/XButton.vue b/marketing-ui/admin-ui/src/components/XButton/src/XButton.vue
new file mode 100644
index 0000000..40cba1a
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/XButton/src/XButton.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+ {{ title ? title : '' }}
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/XButton/src/XTextButton.vue b/marketing-ui/admin-ui/src/components/XButton/src/XTextButton.vue
new file mode 100644
index 0000000..b1a922b
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/XButton/src/XTextButton.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+ {{ title ? title : '' }}
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue
new file mode 100644
index 0000000..00e887c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue
@@ -0,0 +1,655 @@
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue
new file mode 100644
index 0000000..34a54c8
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.assigneeUser?.nickname || scope.row.ownerUser?.nickname }}
+
+
+
+
+
+ {{ scope.row.assigneeUser?.deptName || scope.row.ownerUser?.deptName }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formatPast2(scope.row.durationInMillis) }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ Math.floor(defaultZoom * 10 * 10) + '%' }}
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/index.ts b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/index.ts
new file mode 100644
index 0000000..8522846
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/index.ts
@@ -0,0 +1,8 @@
+import MyProcessDesigner from './ProcessDesigner.vue'
+
+MyProcessDesigner.install = function (Vue) {
+ Vue.component(MyProcessDesigner.name, MyProcessDesigner)
+}
+
+// 流程图的设计器,可编辑
+export default MyProcessDesigner
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/index2.ts b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/index2.ts
new file mode 100644
index 0000000..ebe8ca7
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/index2.ts
@@ -0,0 +1,8 @@
+import MyProcessViewer from './ProcessViewer.vue'
+
+MyProcessViewer.install = function (Vue) {
+ Vue.component(MyProcessViewer.name, MyProcessViewer)
+}
+
+// 流程图的查看器,不可编辑
+export default MyProcessViewer
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js
new file mode 100644
index 0000000..8783493
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js
@@ -0,0 +1,423 @@
+import { assign, forEach, isArray } from 'min-dash'
+
+import { is } from 'bpmn-js/lib/util/ModelUtil'
+
+import { isExpanded, isEventSubProcess } from 'bpmn-js/lib/util/DiUtil'
+
+import { isAny } from 'bpmn-js/lib/features/modeling/util/ModelingUtil'
+
+import { getChildLanes } from 'bpmn-js/lib/features/modeling/util/LaneUtil'
+
+import { hasPrimaryModifier } from 'diagram-js/lib/util/Mouse'
+
+/**
+ * A provider for BPMN 2.0 elements context pad
+ */
+export default function ContextPadProvider(
+ config,
+ injector,
+ eventBus,
+ contextPad,
+ modeling,
+ elementFactory,
+ connect,
+ create,
+ popupMenu,
+ canvas,
+ rules,
+ translate
+) {
+ config = config || {}
+
+ contextPad.registerProvider(this)
+
+ this._contextPad = contextPad
+
+ this._modeling = modeling
+
+ this._elementFactory = elementFactory
+ this._connect = connect
+ this._create = create
+ this._popupMenu = popupMenu
+ this._canvas = canvas
+ this._rules = rules
+ this._translate = translate
+
+ if (config.autoPlace !== false) {
+ this._autoPlace = injector.get('autoPlace', false)
+ }
+
+ eventBus.on('create.end', 250, function (event) {
+ const context = event.context,
+ shape = context.shape
+
+ if (!hasPrimaryModifier(event) || !contextPad.isOpen(shape)) {
+ return
+ }
+
+ const entries = contextPad.getEntries(shape)
+
+ if (entries.replace) {
+ entries.replace.action.click(event, shape)
+ }
+ })
+}
+
+ContextPadProvider.$inject = [
+ 'config.contextPad',
+ 'injector',
+ 'eventBus',
+ 'contextPad',
+ 'modeling',
+ 'elementFactory',
+ 'connect',
+ 'create',
+ 'popupMenu',
+ 'canvas',
+ 'rules',
+ 'translate',
+ 'elementRegistry'
+]
+
+ContextPadProvider.prototype.getContextPadEntries = function (element) {
+ const contextPad = this._contextPad,
+ modeling = this._modeling,
+ elementFactory = this._elementFactory,
+ connect = this._connect,
+ create = this._create,
+ popupMenu = this._popupMenu,
+ canvas = this._canvas,
+ rules = this._rules,
+ autoPlace = this._autoPlace,
+ translate = this._translate
+
+ const actions = {}
+
+ if (element.type === 'label') {
+ return actions
+ }
+
+ const businessObject = element.businessObject
+
+ function startConnect(event, element) {
+ connect.start(event, element)
+ }
+
+ function removeElement() {
+ modeling.removeElements([element])
+ }
+
+ function getReplaceMenuPosition(element) {
+ const Y_OFFSET = 5
+
+ const diagramContainer = canvas.getContainer(),
+ pad = contextPad.getPad(element).html
+
+ const diagramRect = diagramContainer.getBoundingClientRect(),
+ padRect = pad.getBoundingClientRect()
+
+ const top = padRect.top - diagramRect.top
+ const left = padRect.left - diagramRect.left
+
+ const pos = {
+ x: left,
+ y: top + padRect.height + Y_OFFSET
+ }
+
+ return pos
+ }
+
+ /**
+ * Create an append action
+ *
+ * @param {string} type
+ * @param {string} className
+ * @param {string} [title]
+ * @param {Object} [options]
+ *
+ * @return {Object} descriptor
+ */
+ function appendAction(type, className, title, options) {
+ if (typeof title !== 'string') {
+ options = title
+ title = translate('Append {type}', { type: type.replace(/^bpmn:/, '') })
+ }
+
+ function appendStart(event, element) {
+ const shape = elementFactory.createShape(assign({ type: type }, options))
+ create.start(event, shape, {
+ source: element
+ })
+ }
+
+ const append = autoPlace
+ ? function (event, element) {
+ const shape = elementFactory.createShape(assign({ type: type }, options))
+
+ autoPlace.append(element, shape)
+ }
+ : appendStart
+
+ return {
+ group: 'model',
+ className: className,
+ title: title,
+ action: {
+ dragstart: appendStart,
+ click: append
+ }
+ }
+ }
+
+ function splitLaneHandler(count) {
+ return function (event, element) {
+ // actual split
+ modeling.splitLane(element, count)
+
+ // refresh context pad after split to
+ // get rid of split icons
+ contextPad.open(element, true)
+ }
+ }
+
+ if (isAny(businessObject, ['bpmn:Lane', 'bpmn:Participant']) && isExpanded(businessObject)) {
+ const childLanes = getChildLanes(element)
+
+ assign(actions, {
+ 'lane-insert-above': {
+ group: 'lane-insert-above',
+ className: 'bpmn-icon-lane-insert-above',
+ title: translate('Add Lane above'),
+ action: {
+ click: function (event, element) {
+ modeling.addLane(element, 'top')
+ }
+ }
+ }
+ })
+
+ if (childLanes.length < 2) {
+ if (element.height >= 120) {
+ assign(actions, {
+ 'lane-divide-two': {
+ group: 'lane-divide',
+ className: 'bpmn-icon-lane-divide-two',
+ title: translate('Divide into two Lanes'),
+ action: {
+ click: splitLaneHandler(2)
+ }
+ }
+ })
+ }
+
+ if (element.height >= 180) {
+ assign(actions, {
+ 'lane-divide-three': {
+ group: 'lane-divide',
+ className: 'bpmn-icon-lane-divide-three',
+ title: translate('Divide into three Lanes'),
+ action: {
+ click: splitLaneHandler(3)
+ }
+ }
+ })
+ }
+ }
+
+ assign(actions, {
+ 'lane-insert-below': {
+ group: 'lane-insert-below',
+ className: 'bpmn-icon-lane-insert-below',
+ title: translate('Add Lane below'),
+ action: {
+ click: function (event, element) {
+ modeling.addLane(element, 'bottom')
+ }
+ }
+ }
+ })
+ }
+
+ if (is(businessObject, 'bpmn:FlowNode')) {
+ if (is(businessObject, 'bpmn:EventBasedGateway')) {
+ assign(actions, {
+ 'append.receive-task': appendAction(
+ 'bpmn:ReceiveTask',
+ 'bpmn-icon-receive-task',
+ translate('Append ReceiveTask')
+ ),
+ 'append.message-intermediate-event': appendAction(
+ 'bpmn:IntermediateCatchEvent',
+ 'bpmn-icon-intermediate-event-catch-message',
+ translate('Append MessageIntermediateCatchEvent'),
+ { eventDefinitionType: 'bpmn:MessageEventDefinition' }
+ ),
+ 'append.timer-intermediate-event': appendAction(
+ 'bpmn:IntermediateCatchEvent',
+ 'bpmn-icon-intermediate-event-catch-timer',
+ translate('Append TimerIntermediateCatchEvent'),
+ { eventDefinitionType: 'bpmn:TimerEventDefinition' }
+ ),
+ 'append.condition-intermediate-event': appendAction(
+ 'bpmn:IntermediateCatchEvent',
+ 'bpmn-icon-intermediate-event-catch-condition',
+ translate('Append ConditionIntermediateCatchEvent'),
+ { eventDefinitionType: 'bpmn:ConditionalEventDefinition' }
+ ),
+ 'append.signal-intermediate-event': appendAction(
+ 'bpmn:IntermediateCatchEvent',
+ 'bpmn-icon-intermediate-event-catch-signal',
+ translate('Append SignalIntermediateCatchEvent'),
+ { eventDefinitionType: 'bpmn:SignalEventDefinition' }
+ )
+ })
+ } else if (
+ isEventType(businessObject, 'bpmn:BoundaryEvent', 'bpmn:CompensateEventDefinition')
+ ) {
+ assign(actions, {
+ 'append.compensation-activity': appendAction(
+ 'bpmn:Task',
+ 'bpmn-icon-task',
+ translate('Append compensation activity'),
+ {
+ isForCompensation: true
+ }
+ )
+ })
+ } else if (
+ !is(businessObject, 'bpmn:EndEvent') &&
+ !businessObject.isForCompensation &&
+ !isEventType(businessObject, 'bpmn:IntermediateThrowEvent', 'bpmn:LinkEventDefinition') &&
+ !isEventSubProcess(businessObject)
+ ) {
+ assign(actions, {
+ 'append.end-event': appendAction(
+ 'bpmn:EndEvent',
+ 'bpmn-icon-end-event-none',
+ translate('Append EndEvent')
+ ),
+ 'append.gateway': appendAction(
+ 'bpmn:ExclusiveGateway',
+ 'bpmn-icon-gateway-none',
+ translate('Append Gateway')
+ ),
+ 'append.append-task': appendAction(
+ 'bpmn:UserTask',
+ 'bpmn-icon-user-task',
+ translate('Append Task')
+ ),
+ 'append.intermediate-event': appendAction(
+ 'bpmn:IntermediateThrowEvent',
+ 'bpmn-icon-intermediate-event-none',
+ translate('Append Intermediate/Boundary Event')
+ )
+ })
+ }
+ }
+
+ if (!popupMenu.isEmpty(element, 'bpmn-replace')) {
+ // Replace menu entry
+ assign(actions, {
+ replace: {
+ group: 'edit',
+ className: 'bpmn-icon-screw-wrench',
+ title: '修改类型',
+ action: {
+ click: function (event, element) {
+ const position = assign(getReplaceMenuPosition(element), {
+ cursor: { x: event.x, y: event.y }
+ })
+
+ popupMenu.open(element, 'bpmn-replace', position)
+ }
+ }
+ }
+ })
+ }
+
+ if (
+ isAny(businessObject, [
+ 'bpmn:FlowNode',
+ 'bpmn:InteractionNode',
+ 'bpmn:DataObjectReference',
+ 'bpmn:DataStoreReference'
+ ])
+ ) {
+ assign(actions, {
+ 'append.text-annotation': appendAction('bpmn:TextAnnotation', 'bpmn-icon-text-annotation'),
+
+ connect: {
+ group: 'connect',
+ className: 'bpmn-icon-connection-multi',
+ title: translate(
+ 'Connect using ' +
+ (businessObject.isForCompensation ? '' : 'Sequence/MessageFlow or ') +
+ 'Association'
+ ),
+ action: {
+ click: startConnect,
+ dragstart: startConnect
+ }
+ }
+ })
+ }
+
+ if (isAny(businessObject, ['bpmn:DataObjectReference', 'bpmn:DataStoreReference'])) {
+ assign(actions, {
+ connect: {
+ group: 'connect',
+ className: 'bpmn-icon-connection-multi',
+ title: translate('Connect using DataInputAssociation'),
+ action: {
+ click: startConnect,
+ dragstart: startConnect
+ }
+ }
+ })
+ }
+
+ if (is(businessObject, 'bpmn:Group')) {
+ assign(actions, {
+ 'append.text-annotation': appendAction('bpmn:TextAnnotation', 'bpmn-icon-text-annotation')
+ })
+ }
+
+ // delete element entry, only show if allowed by rules
+ let deleteAllowed = rules.allowed('elements.delete', { elements: [element] })
+
+ if (isArray(deleteAllowed)) {
+ // was the element returned as a deletion candidate?
+ deleteAllowed = deleteAllowed[0] === element
+ }
+
+ if (deleteAllowed) {
+ assign(actions, {
+ delete: {
+ group: 'edit',
+ className: 'bpmn-icon-trash',
+ title: translate('Remove'),
+ action: {
+ click: removeElement
+ }
+ }
+ })
+ }
+
+ return actions
+}
+
+// helpers /////////
+
+function isEventType(eventBo, type, definition) {
+ const isType = eventBo.$instanceOf(type)
+ let isDefinition = false
+
+ const definitions = eventBo.eventDefinitions || []
+ forEach(definitions, function (def) {
+ if (def.$type === definition) {
+ isDefinition = true
+ }
+ })
+
+ return isType && isDefinition
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js
new file mode 100644
index 0000000..80009ef
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js
@@ -0,0 +1,6 @@
+import CustomContextPadProvider from './contentPadProvider'
+
+export default {
+ __init__: ['contextPadProvider'],
+ contextPadProvider: ['type', CustomContextPadProvider]
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js
new file mode 100644
index 0000000..f3bc894
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js
@@ -0,0 +1,24 @@
+export default (key, name, type) => {
+ if (!type) type = 'camunda'
+ const TYPE_TARGET = {
+ activiti: 'http://activiti.org/bpmn',
+ camunda: 'http://bpmn.io/schema/bpmn',
+ flowable: 'http://flowable.org/bpmn'
+ }
+ return `
+
+
+
+
+
+
+
+`
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json
new file mode 100644
index 0000000..94ba8f6
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json
@@ -0,0 +1,1004 @@
+{
+ "name": "Activiti",
+ "uri": "http://activiti.org/bpmn",
+ "prefix": "activiti",
+ "xml": {
+ "tagAlias": "lowerCase"
+ },
+ "associations": [],
+ "types": [
+ {
+ "name": "Definitions",
+ "isAbstract": true,
+ "extends": ["bpmn:Definitions"],
+ "properties": [
+ {
+ "name": "diagramRelationId",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "InOutBinding",
+ "superClass": ["Element"],
+ "isAbstract": true,
+ "properties": [
+ {
+ "name": "source",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "sourceExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "target",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "businessKey",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "local",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "variables",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "In",
+ "superClass": ["InOutBinding"],
+ "meta": {
+ "allowedIn": ["bpmn:CallActivity"]
+ }
+ },
+ {
+ "name": "Out",
+ "superClass": ["InOutBinding"],
+ "meta": {
+ "allowedIn": ["bpmn:CallActivity"]
+ }
+ },
+ {
+ "name": "AsyncCapable",
+ "isAbstract": true,
+ "extends": ["bpmn:Activity", "bpmn:Gateway", "bpmn:Event"],
+ "properties": [
+ {
+ "name": "async",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "asyncBefore",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "asyncAfter",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "exclusive",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": true
+ }
+ ]
+ },
+ {
+ "name": "JobPriorized",
+ "isAbstract": true,
+ "extends": ["bpmn:Process", "activiti:AsyncCapable"],
+ "properties": [
+ {
+ "name": "jobPriority",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "SignalEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:SignalEventDefinition"],
+ "properties": [
+ {
+ "name": "async",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ }
+ ]
+ },
+ {
+ "name": "ErrorEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:ErrorEventDefinition"],
+ "properties": [
+ {
+ "name": "errorCodeVariable",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "errorMessageVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Error",
+ "isAbstract": true,
+ "extends": ["bpmn:Error"],
+ "properties": [
+ {
+ "name": "activiti:errorMessage",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "PotentialStarter",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "resourceAssignmentExpression",
+ "type": "bpmn:ResourceAssignmentExpression"
+ }
+ ]
+ },
+ {
+ "name": "FormSupported",
+ "isAbstract": true,
+ "extends": ["bpmn:StartEvent", "bpmn:UserTask"],
+ "properties": [
+ {
+ "name": "formHandlerClass",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "formKey",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "TemplateSupported",
+ "isAbstract": true,
+ "extends": ["bpmn:Process", "bpmn:FlowElement"],
+ "properties": [
+ {
+ "name": "modelerTemplate",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Initiator",
+ "isAbstract": true,
+ "extends": ["bpmn:StartEvent"],
+ "properties": [
+ {
+ "name": "initiator",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ScriptTask",
+ "isAbstract": true,
+ "extends": ["bpmn:ScriptTask"],
+ "properties": [
+ {
+ "name": "resultVariable",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Process",
+ "isAbstract": true,
+ "extends": ["bpmn:Process"],
+ "properties": [
+ {
+ "name": "candidateStarterGroups",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateStarterUsers",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "versionTag",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "historyTimeToLive",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "isStartableInTasklist",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": true
+ },
+ {
+ "name": "executionListener",
+ "isAbstract": true,
+ "type": "Expression"
+ }
+ ]
+ },
+ {
+ "name": "EscalationEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:EscalationEventDefinition"],
+ "properties": [
+ {
+ "name": "escalationCodeVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "FormalExpression",
+ "isAbstract": true,
+ "extends": ["bpmn:FormalExpression"],
+ "properties": [
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "multiinstance_type",
+ "superClass": ["Element"]
+ },
+ {
+ "name": "multiinstance_condition",
+ "superClass": ["Element"]
+ },
+ {
+ "name": "Assignable",
+ "extends": ["bpmn:UserTask"],
+ "properties": [
+ {
+ "name": "assignee",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateUsers",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateGroups",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "dueDate",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "followUpDate",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "priority",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "multiinstance_condition",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateStrategy",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateParam",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "CallActivity",
+ "extends": ["bpmn:CallActivity"],
+ "properties": [
+ {
+ "name": "calledElementBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "calledElementVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "calledElementVersionTag",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "calledElementTenantId",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseRef",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "caseVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseTenantId",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableMappingClass",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableMappingDelegateExpression",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ServiceTaskLike",
+ "extends": [
+ "bpmn:ServiceTask",
+ "bpmn:BusinessRuleTask",
+ "bpmn:SendTask",
+ "bpmn:MessageEventDefinition"
+ ],
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resultVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "DmnCapable",
+ "extends": ["bpmn:BusinessRuleTask"],
+ "properties": [
+ {
+ "name": "decisionRef",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "decisionRefBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "decisionRefVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "mapDecisionResult",
+ "isAttr": true,
+ "type": "String",
+ "default": "resultList"
+ },
+ {
+ "name": "decisionRefTenantId",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ExternalCapable",
+ "extends": ["activiti:ServiceTaskLike"],
+ "properties": [
+ {
+ "name": "type",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "topic",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "TaskPriorized",
+ "extends": ["bpmn:Process", "activiti:ExternalCapable"],
+ "properties": [
+ {
+ "name": "taskPriority",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Properties",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["*"]
+ },
+ "properties": [
+ {
+ "name": "values",
+ "type": "Property",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Property",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "value",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "Connector",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["activiti:ServiceTaskLike"]
+ },
+ "properties": [
+ {
+ "name": "inputOutput",
+ "type": "InputOutput"
+ },
+ {
+ "name": "connectorId",
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "InputOutput",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:FlowNode", "activiti:Connector"]
+ },
+ "properties": [
+ {
+ "name": "inputOutput",
+ "type": "InputOutput"
+ },
+ {
+ "name": "connectorId",
+ "type": "String"
+ },
+ {
+ "name": "inputParameters",
+ "isMany": true,
+ "type": "InputParameter"
+ },
+ {
+ "name": "outputParameters",
+ "isMany": true,
+ "type": "OutputParameter"
+ }
+ ]
+ },
+ {
+ "name": "InputOutputParameter",
+ "properties": [
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ },
+ {
+ "name": "definition",
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "InputOutputParameterDefinition",
+ "isAbstract": true
+ },
+ {
+ "name": "List",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "items",
+ "isMany": true,
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "Map",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "entries",
+ "isMany": true,
+ "type": "Entry"
+ }
+ ]
+ },
+ {
+ "name": "Entry",
+ "properties": [
+ {
+ "name": "key",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ },
+ {
+ "name": "definition",
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "Value",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "id",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Script",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "scriptFormat",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Field",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": [
+ "activiti:ServiceTaskLike",
+ "activiti:ExecutionListener",
+ "activiti:TaskListener"
+ ]
+ },
+ "properties": [
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "expression",
+ "type": "String"
+ },
+ {
+ "name": "stringValue",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "string",
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "InputParameter",
+ "superClass": ["InputOutputParameter"]
+ },
+ {
+ "name": "OutputParameter",
+ "superClass": ["InputOutputParameter"]
+ },
+ {
+ "name": "Collectable",
+ "isAbstract": true,
+ "extends": ["bpmn:MultiInstanceLoopCharacteristics"],
+ "superClass": ["activiti:AsyncCapable"],
+ "properties": [
+ {
+ "name": "collection",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "elementVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "FailedJobRetryTimeCycle",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["activiti:AsyncCapable", "bpmn:MultiInstanceLoopCharacteristics"]
+ },
+ "properties": [
+ {
+ "name": "body",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ExecutionListener",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": [
+ "bpmn:Task",
+ "bpmn:ServiceTask",
+ "bpmn:UserTask",
+ "bpmn:BusinessRuleTask",
+ "bpmn:ScriptTask",
+ "bpmn:ReceiveTask",
+ "bpmn:ManualTask",
+ "bpmn:ExclusiveGateway",
+ "bpmn:SequenceFlow",
+ "bpmn:ParallelGateway",
+ "bpmn:InclusiveGateway",
+ "bpmn:EventBasedGateway",
+ "bpmn:StartEvent",
+ "bpmn:IntermediateCatchEvent",
+ "bpmn:IntermediateThrowEvent",
+ "bpmn:EndEvent",
+ "bpmn:BoundaryEvent",
+ "bpmn:CallActivity",
+ "bpmn:SubProcess",
+ "bpmn:Process"
+ ]
+ },
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "event",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "script",
+ "type": "Script"
+ },
+ {
+ "name": "fields",
+ "type": "Field",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "TaskListener",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "event",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "script",
+ "type": "Script"
+ },
+ {
+ "name": "fields",
+ "type": "Field",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "FormProperty",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "type",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "required",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "readable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "writable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "variable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "expression",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "datePattern",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "default",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "values",
+ "type": "Value",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "FormProperty",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "label",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "type",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "datePattern",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "defaultValue",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "properties",
+ "type": "Properties"
+ },
+ {
+ "name": "validation",
+ "type": "Validation"
+ },
+ {
+ "name": "values",
+ "type": "Value",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Validation",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "constraints",
+ "type": "Constraint",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Constraint",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "config",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "ConditionalEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:ConditionalEventDefinition"],
+ "properties": [
+ {
+ "name": "variableName",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableEvent",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ }
+ ],
+ "emumerations": []
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json
new file mode 100644
index 0000000..8322561
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json
@@ -0,0 +1,1020 @@
+{
+ "name": "Camunda",
+ "uri": "http://camunda.org/schema/1.0/bpmn",
+ "prefix": "camunda",
+ "xml": {
+ "tagAlias": "lowerCase"
+ },
+ "associations": [],
+ "types": [
+ {
+ "name": "Definitions",
+ "isAbstract": true,
+ "extends": ["bpmn:Definitions"],
+ "properties": [
+ {
+ "name": "diagramRelationId",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "InOutBinding",
+ "superClass": ["Element"],
+ "isAbstract": true,
+ "properties": [
+ {
+ "name": "source",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "sourceExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "target",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "businessKey",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "local",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "variables",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "In",
+ "superClass": ["InOutBinding"],
+ "meta": {
+ "allowedIn": ["bpmn:CallActivity", "bpmn:SignalEventDefinition"]
+ }
+ },
+ {
+ "name": "Out",
+ "superClass": ["InOutBinding"],
+ "meta": {
+ "allowedIn": ["bpmn:CallActivity"]
+ }
+ },
+ {
+ "name": "AsyncCapable",
+ "isAbstract": true,
+ "extends": ["bpmn:Activity", "bpmn:Gateway", "bpmn:Event"],
+ "properties": [
+ {
+ "name": "async",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "asyncBefore",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "asyncAfter",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "exclusive",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": true
+ }
+ ]
+ },
+ {
+ "name": "JobPriorized",
+ "isAbstract": true,
+ "extends": ["bpmn:Process", "camunda:AsyncCapable"],
+ "properties": [
+ {
+ "name": "jobPriority",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "SignalEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:SignalEventDefinition"],
+ "properties": [
+ {
+ "name": "async",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ }
+ ]
+ },
+ {
+ "name": "ErrorEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:ErrorEventDefinition"],
+ "properties": [
+ {
+ "name": "errorCodeVariable",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "errorMessageVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Error",
+ "isAbstract": true,
+ "extends": ["bpmn:Error"],
+ "properties": [
+ {
+ "name": "camunda:errorMessage",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "PotentialStarter",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "resourceAssignmentExpression",
+ "type": "bpmn:ResourceAssignmentExpression"
+ }
+ ]
+ },
+ {
+ "name": "FormSupported",
+ "isAbstract": true,
+ "extends": ["bpmn:StartEvent", "bpmn:UserTask"],
+ "properties": [
+ {
+ "name": "formHandlerClass",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "formKey",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "TemplateSupported",
+ "isAbstract": true,
+ "extends": ["bpmn:Process", "bpmn:FlowElement"],
+ "properties": [
+ {
+ "name": "modelerTemplate",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "modelerTemplateVersion",
+ "isAttr": true,
+ "type": "Integer"
+ }
+ ]
+ },
+ {
+ "name": "Initiator",
+ "isAbstract": true,
+ "extends": ["bpmn:StartEvent"],
+ "properties": [
+ {
+ "name": "initiator",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ScriptTask",
+ "isAbstract": true,
+ "extends": ["bpmn:ScriptTask"],
+ "properties": [
+ {
+ "name": "resultVariable",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Process",
+ "isAbstract": true,
+ "extends": ["bpmn:Process"],
+ "properties": [
+ {
+ "name": "candidateStarterGroups",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateStarterUsers",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "versionTag",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "historyTimeToLive",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "isStartableInTasklist",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": true
+ }
+ ]
+ },
+ {
+ "name": "EscalationEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:EscalationEventDefinition"],
+ "properties": [
+ {
+ "name": "escalationCodeVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "FormalExpression",
+ "isAbstract": true,
+ "extends": ["bpmn:FormalExpression"],
+ "properties": [
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Assignable",
+ "extends": ["bpmn:UserTask"],
+ "properties": [
+ {
+ "name": "assignee",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateUsers",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateGroups",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "dueDate",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "followUpDate",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "priority",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateStrategy",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateParam",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "CallActivity",
+ "extends": ["bpmn:CallActivity"],
+ "properties": [
+ {
+ "name": "calledElementBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "calledElementVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "calledElementVersionTag",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "calledElementTenantId",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseRef",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "caseVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseTenantId",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableMappingClass",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableMappingDelegateExpression",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ServiceTaskLike",
+ "extends": [
+ "bpmn:ServiceTask",
+ "bpmn:BusinessRuleTask",
+ "bpmn:SendTask",
+ "bpmn:MessageEventDefinition"
+ ],
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resultVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "DmnCapable",
+ "extends": ["bpmn:BusinessRuleTask"],
+ "properties": [
+ {
+ "name": "decisionRef",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "decisionRefBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "decisionRefVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "mapDecisionResult",
+ "isAttr": true,
+ "type": "String",
+ "default": "resultList"
+ },
+ {
+ "name": "decisionRefTenantId",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ExternalCapable",
+ "extends": ["camunda:ServiceTaskLike"],
+ "properties": [
+ {
+ "name": "type",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "topic",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "TaskPriorized",
+ "extends": ["bpmn:Process", "camunda:ExternalCapable"],
+ "properties": [
+ {
+ "name": "taskPriority",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Properties",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["*"]
+ },
+ "properties": [
+ {
+ "name": "values",
+ "type": "Property",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Property",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "value",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "Connector",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["camunda:ServiceTaskLike"]
+ },
+ "properties": [
+ {
+ "name": "inputOutput",
+ "type": "InputOutput"
+ },
+ {
+ "name": "connectorId",
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "InputOutput",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:FlowNode", "camunda:Connector"]
+ },
+ "properties": [
+ {
+ "name": "inputOutput",
+ "type": "InputOutput"
+ },
+ {
+ "name": "connectorId",
+ "type": "String"
+ },
+ {
+ "name": "inputParameters",
+ "isMany": true,
+ "type": "InputParameter"
+ },
+ {
+ "name": "outputParameters",
+ "isMany": true,
+ "type": "OutputParameter"
+ }
+ ]
+ },
+ {
+ "name": "InputOutputParameter",
+ "properties": [
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ },
+ {
+ "name": "definition",
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "InputOutputParameterDefinition",
+ "isAbstract": true
+ },
+ {
+ "name": "List",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "items",
+ "isMany": true,
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "Map",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "entries",
+ "isMany": true,
+ "type": "Entry"
+ }
+ ]
+ },
+ {
+ "name": "Entry",
+ "properties": [
+ {
+ "name": "key",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ },
+ {
+ "name": "definition",
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "Value",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "id",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Script",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "scriptFormat",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Field",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": [
+ "camunda:ServiceTaskLike",
+ "camunda:ExecutionListener",
+ "camunda:TaskListener"
+ ]
+ },
+ "properties": [
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "expression",
+ "type": "String"
+ },
+ {
+ "name": "stringValue",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "string",
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "InputParameter",
+ "superClass": ["InputOutputParameter"]
+ },
+ {
+ "name": "OutputParameter",
+ "superClass": ["InputOutputParameter"]
+ },
+ {
+ "name": "Collectable",
+ "isAbstract": true,
+ "extends": ["bpmn:MultiInstanceLoopCharacteristics"],
+ "superClass": ["camunda:AsyncCapable"],
+ "properties": [
+ {
+ "name": "collection",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "elementVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "FailedJobRetryTimeCycle",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["camunda:AsyncCapable", "bpmn:MultiInstanceLoopCharacteristics"]
+ },
+ "properties": [
+ {
+ "name": "body",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ExecutionListener",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": [
+ "bpmn:Task",
+ "bpmn:ServiceTask",
+ "bpmn:UserTask",
+ "bpmn:BusinessRuleTask",
+ "bpmn:ScriptTask",
+ "bpmn:ReceiveTask",
+ "bpmn:ManualTask",
+ "bpmn:ExclusiveGateway",
+ "bpmn:SequenceFlow",
+ "bpmn:ParallelGateway",
+ "bpmn:InclusiveGateway",
+ "bpmn:EventBasedGateway",
+ "bpmn:StartEvent",
+ "bpmn:IntermediateCatchEvent",
+ "bpmn:IntermediateThrowEvent",
+ "bpmn:EndEvent",
+ "bpmn:BoundaryEvent",
+ "bpmn:CallActivity",
+ "bpmn:SubProcess",
+ "bpmn:Process"
+ ]
+ },
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "event",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "script",
+ "type": "Script"
+ },
+ {
+ "name": "fields",
+ "type": "Field",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "TaskListener",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "event",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "script",
+ "type": "Script"
+ },
+ {
+ "name": "fields",
+ "type": "Field",
+ "isMany": true
+ },
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "eventDefinitions",
+ "type": "bpmn:TimerEventDefinition",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "FormProperty",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "type",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "required",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "readable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "writable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "variable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "expression",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "datePattern",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "default",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "values",
+ "type": "Value",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "FormData",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "fields",
+ "type": "FormField",
+ "isMany": true
+ },
+ {
+ "name": "businessKey",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "FormField",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "label",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "type",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "datePattern",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "defaultValue",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "properties",
+ "type": "Properties"
+ },
+ {
+ "name": "validation",
+ "type": "Validation"
+ },
+ {
+ "name": "values",
+ "type": "Value",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Validation",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "constraints",
+ "type": "Constraint",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Constraint",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "config",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "ConditionalEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:ConditionalEventDefinition"],
+ "properties": [
+ {
+ "name": "variableName",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableEvents",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ }
+ ],
+ "emumerations": []
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json
new file mode 100644
index 0000000..130b594
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json
@@ -0,0 +1,1483 @@
+{
+ "name": "Flowable",
+ "uri": "http://flowable.org/bpmn",
+ "prefix": "flowable",
+ "xml": {
+ "tagAlias": "lowerCase"
+ },
+ "associations": [],
+ "types": [
+ {
+ "name": "InOutBinding",
+ "superClass": ["Element"],
+ "isAbstract": true,
+ "properties": [
+ {
+ "name": "source",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "sourceExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "target",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "businessKey",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "local",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "variables",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "In",
+ "superClass": ["InOutBinding"],
+ "meta": {
+ "allowedIn": ["bpmn:CallActivity"]
+ }
+ },
+ {
+ "name": "Out",
+ "superClass": ["InOutBinding"],
+ "meta": {
+ "allowedIn": ["bpmn:CallActivity"]
+ }
+ },
+ {
+ "name": "AsyncCapable",
+ "isAbstract": true,
+ "extends": ["bpmn:Activity", "bpmn:Gateway", "bpmn:Event"],
+ "properties": [
+ {
+ "name": "async",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "asyncBefore",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "asyncAfter",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "exclusive",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": true
+ }
+ ]
+ },
+ {
+ "name": "JobPriorized",
+ "isAbstract": true,
+ "extends": ["bpmn:Process", "flowable:AsyncCapable"],
+ "properties": [
+ {
+ "name": "jobPriority",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "SignalEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:SignalEventDefinition"],
+ "properties": [
+ {
+ "name": "async",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ }
+ ]
+ },
+ {
+ "name": "ErrorEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:ErrorEventDefinition"],
+ "properties": [
+ {
+ "name": "errorCodeVariable",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "errorMessageVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Error",
+ "isAbstract": true,
+ "extends": ["bpmn:Error"],
+ "properties": [
+ {
+ "name": "flowable:errorMessage",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "PotentialStarter",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "resourceAssignmentExpression",
+ "type": "bpmn:ResourceAssignmentExpression"
+ }
+ ]
+ },
+ {
+ "name": "FormSupported",
+ "isAbstract": true,
+ "extends": ["bpmn:StartEvent", "bpmn:UserTask"],
+ "properties": [
+ {
+ "name": "formHandlerClass",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "formKey",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "formType",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "formReadOnly",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": false
+ },
+ {
+ "name": "formInit",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": true
+ }
+ ]
+ },
+ {
+ "name": "TemplateSupported",
+ "isAbstract": true,
+ "extends": ["bpmn:Process", "bpmn:FlowElement"],
+ "properties": [
+ {
+ "name": "modelerTemplate",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Initiator",
+ "isAbstract": true,
+ "extends": ["bpmn:StartEvent"],
+ "properties": [
+ {
+ "name": "initiator",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ScriptTask",
+ "isAbstract": true,
+ "extends": ["bpmn:ScriptTask"],
+ "properties": [
+ {
+ "name": "resultVariable",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Process",
+ "isAbstract": true,
+ "extends": ["bpmn:Process"],
+ "properties": [
+ {
+ "name": "candidateStarterGroups",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateStarterUsers",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "versionTag",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "historyTimeToLive",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "isStartableInTasklist",
+ "isAttr": true,
+ "type": "Boolean",
+ "default": true
+ }
+ ]
+ },
+ {
+ "name": "EscalationEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:EscalationEventDefinition"],
+ "properties": [
+ {
+ "name": "escalationCodeVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "FormalExpression",
+ "isAbstract": true,
+ "extends": ["bpmn:FormalExpression"],
+ "properties": [
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Assignable",
+ "extends": ["bpmn:UserTask"],
+ "properties": [
+ {
+ "name": "assignee",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateUsers",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateGroups",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "dueDate",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "followUpDate",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "priority",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateStrategy",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "candidateParam",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Assignee",
+ "supperClass": "Element",
+ "meta": {
+ "allowedIn": ["*"]
+ },
+ "properties": [
+ {
+ "name": "label",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "viewId",
+ "type": "Number",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "CallActivity",
+ "extends": ["bpmn:CallActivity"],
+ "properties": [
+ {
+ "name": "calledElementBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "calledElementVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "calledElementVersionTag",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "calledElementTenantId",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseRef",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "caseVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "caseTenantId",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableMappingClass",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableMappingDelegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "calledElementType",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "processInstanceName",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "inheritBusinessKey",
+ "isAttr": true,
+ "type": "Boolean"
+ },
+ {
+ "name": "businessKey",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "inheritVariables",
+ "isAttr": true,
+ "type": "Boolean"
+ }
+ ]
+ },
+ {
+ "name": "ServiceTaskLike",
+ "extends": [
+ "bpmn:ServiceTask",
+ "bpmn:BusinessRuleTask",
+ "bpmn:SendTask",
+ "bpmn:MessageEventDefinition"
+ ],
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resultVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "DmnCapable",
+ "extends": ["bpmn:BusinessRuleTask"],
+ "properties": [
+ {
+ "name": "decisionRef",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "decisionRefBinding",
+ "isAttr": true,
+ "type": "String",
+ "default": "latest"
+ },
+ {
+ "name": "decisionRefVersion",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "mapDecisionResult",
+ "isAttr": true,
+ "type": "String",
+ "default": "resultList"
+ },
+ {
+ "name": "decisionRefTenantId",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ExternalCapable",
+ "extends": ["flowable:ServiceTaskLike"],
+ "properties": [
+ {
+ "name": "type",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "topic",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "TaskPriorized",
+ "extends": ["bpmn:Process", "flowable:ExternalCapable"],
+ "properties": [
+ {
+ "name": "taskPriority",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Properties",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["*"]
+ },
+ "properties": [
+ {
+ "name": "values",
+ "type": "Property",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Property",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "value",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "Button",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "code",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "isHide",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "next",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "sort",
+ "type": "Integer",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "Assignee",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "type",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "value",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "condition",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "operationType",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "sort",
+ "type": "Integer",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "Connector",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["flowable:ServiceTaskLike"]
+ },
+ "properties": [
+ {
+ "name": "inputOutput",
+ "type": "InputOutput"
+ },
+ {
+ "name": "connectorId",
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "InputOutput",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:FlowNode", "flowable:Connector"]
+ },
+ "properties": [
+ {
+ "name": "inputOutput",
+ "type": "InputOutput"
+ },
+ {
+ "name": "connectorId",
+ "type": "String"
+ },
+ {
+ "name": "inputParameters",
+ "isMany": true,
+ "type": "InputParameter"
+ },
+ {
+ "name": "outputParameters",
+ "isMany": true,
+ "type": "OutputParameter"
+ }
+ ]
+ },
+ {
+ "name": "InputOutputParameter",
+ "properties": [
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ },
+ {
+ "name": "definition",
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "InputOutputParameterDefinition",
+ "isAbstract": true
+ },
+ {
+ "name": "List",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "items",
+ "isMany": true,
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "Map",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "entries",
+ "isMany": true,
+ "type": "Entry"
+ }
+ ]
+ },
+ {
+ "name": "Entry",
+ "properties": [
+ {
+ "name": "key",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ },
+ {
+ "name": "definition",
+ "type": "InputOutputParameterDefinition"
+ }
+ ]
+ },
+ {
+ "name": "Value",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "id",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Script",
+ "superClass": ["InputOutputParameterDefinition"],
+ "properties": [
+ {
+ "name": "scriptFormat",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "resource",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "value",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Field",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": [
+ "flowable:ServiceTaskLike",
+ "flowable:ExecutionListener",
+ "flowable:TaskListener"
+ ]
+ },
+ "properties": [
+ {
+ "name": "name",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "expression",
+ "type": "String"
+ },
+ {
+ "name": "stringValue",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "string",
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ChildField",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "type",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "required",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "readable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "writable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "variable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "expression",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "datePattern",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "default",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "values",
+ "type": "Value",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "InputParameter",
+ "superClass": ["InputOutputParameter"]
+ },
+ {
+ "name": "OutputParameter",
+ "superClass": ["InputOutputParameter"]
+ },
+ {
+ "name": "Collectable",
+ "isAbstract": true,
+ "extends": ["bpmn:MultiInstanceLoopCharacteristics"],
+ "superClass": ["flowable:AsyncCapable"],
+ "properties": [
+ {
+ "name": "collection",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "elementVariable",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "FailedJobRetryTimeCycle",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["flowable:AsyncCapable", "bpmn:MultiInstanceLoopCharacteristics"]
+ },
+ "properties": [
+ {
+ "name": "body",
+ "isBody": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ExecutionListener",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": [
+ "bpmn:Task",
+ "bpmn:ServiceTask",
+ "bpmn:UserTask",
+ "bpmn:BusinessRuleTask",
+ "bpmn:ScriptTask",
+ "bpmn:ReceiveTask",
+ "bpmn:ManualTask",
+ "bpmn:ExclusiveGateway",
+ "bpmn:SequenceFlow",
+ "bpmn:ParallelGateway",
+ "bpmn:InclusiveGateway",
+ "bpmn:EventBasedGateway",
+ "bpmn:StartEvent",
+ "bpmn:IntermediateCatchEvent",
+ "bpmn:IntermediateThrowEvent",
+ "bpmn:EndEvent",
+ "bpmn:BoundaryEvent",
+ "bpmn:CallActivity",
+ "bpmn:SubProcess",
+ "bpmn:Process"
+ ]
+ },
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "event",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "script",
+ "type": "Script"
+ },
+ {
+ "name": "fields",
+ "type": "Field",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "TaskListener",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "expression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "class",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "delegateExpression",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "event",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "script",
+ "type": "Script"
+ },
+ {
+ "name": "fields",
+ "type": "Field",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "FormProperty",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "type",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "required",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "readable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "writable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "variable",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "expression",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "datePattern",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "default",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "values",
+ "type": "Value",
+ "isMany": true
+ },
+ {
+ "name": "children",
+ "type": "ChildField",
+ "isMany": true
+ },
+ {
+ "name": "extensionElements",
+ "type": "bpmn:ExtensionElements",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "FormData",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "fields",
+ "type": "FormField",
+ "isMany": true
+ },
+ {
+ "name": "businessKey",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "FormField",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "label",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "type",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "datePattern",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "defaultValue",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "properties",
+ "type": "Properties"
+ },
+ {
+ "name": "validation",
+ "type": "Validation"
+ },
+ {
+ "name": "values",
+ "type": "Value",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Validation",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "constraints",
+ "type": "Constraint",
+ "isMany": true
+ }
+ ]
+ },
+ {
+ "name": "Constraint",
+ "superClass": ["Element"],
+ "properties": [
+ {
+ "name": "name",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "config",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "ConditionalEventDefinition",
+ "isAbstract": true,
+ "extends": ["bpmn:ConditionalEventDefinition"],
+ "properties": [
+ {
+ "name": "variableName",
+ "isAttr": true,
+ "type": "String"
+ },
+ {
+ "name": "variableEvent",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "Condition",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:SequenceFlow"]
+ },
+ "properties": [
+ {
+ "name": "id",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "field",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "compare",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "value",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "logic",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "sort",
+ "type": "Integer",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "AssignStartUserHandlerType",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:StartEvent", "bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Integer",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "RejectHandlerType",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Integer",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "RejectReturnTaskId",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "String",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "AssignEmptyHandlerType",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Integer",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "AssignEmptyUserIds",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "String",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "ButtonsSetting",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "flowable:id",
+ "type": "Integer",
+ "isAttr": true
+ },
+ {
+ "name": "flowable:enable",
+ "type": "Boolean",
+ "isAttr": true
+ },
+ {
+ "name": "flowable:displayName",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "FieldsPermission",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "flowable:field",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "flowable:title",
+ "type": "String",
+ "isAttr": true
+ },
+ {
+ "name": "flowable:permission",
+ "type": "String",
+ "isAttr": true
+ }
+ ]
+ },
+ {
+ "name": "BoundaryEventType",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:BoundaryEvent"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Integer",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "TimeoutHandlerType",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:BoundaryEvent"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Integer",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "ApproveType",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Integer",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "ApproveMethod",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Integer",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "CandidateStrategy",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Integer",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "CandidateParam",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "String",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "SignEnable",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Boolean",
+ "isBody": true
+ }
+ ]
+ },
+ {
+ "name": "SkipExpression",
+ "extends": ["bpmn:UserTask"],
+ "properties": [
+ {
+ "name": "skipExpression",
+ "isAttr": true,
+ "type": "String"
+ }
+ ]
+ },
+ {
+ "name": "ReasonRequire",
+ "superClass": ["Element"],
+ "meta": {
+ "allowedIn": ["bpmn:UserTask"]
+ },
+ "properties": [
+ {
+ "name": "value",
+ "type": "Boolean",
+ "isBody": true
+ }
+ ]
+ }
+ ],
+ "emumerations": []
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js
new file mode 100644
index 0000000..56ef38a
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js
@@ -0,0 +1,83 @@
+'use strict'
+
+import { some } from 'min-dash'
+
+// const some = require('min-dash').some
+// const some = some
+
+const ALLOWED_TYPES = {
+ FailedJobRetryTimeCycle: [
+ 'bpmn:StartEvent',
+ 'bpmn:BoundaryEvent',
+ 'bpmn:IntermediateCatchEvent',
+ 'bpmn:Activity'
+ ],
+ Connector: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'],
+ Field: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent']
+}
+
+function is(element, type) {
+ return element && typeof element.$instanceOf === 'function' && element.$instanceOf(type)
+}
+
+function exists(element) {
+ return element && element.length
+}
+
+function includesType(collection, type) {
+ return (
+ exists(collection) &&
+ some(collection, function (element) {
+ return is(element, type)
+ })
+ )
+}
+
+function anyType(element, types) {
+ return some(types, function (type) {
+ return is(element, type)
+ })
+}
+
+function isAllowed(propName, propDescriptor, newElement) {
+ const name = propDescriptor.name,
+ types = ALLOWED_TYPES[name.replace(/activiti:/, '')]
+
+ return name === propName && anyType(newElement, types)
+}
+
+function ActivitiModdleExtension(eventBus) {
+ eventBus.on(
+ 'property.clone',
+ function (context) {
+ const newElement = context.newElement,
+ propDescriptor = context.propertyDescriptor
+
+ this.canCloneProperty(newElement, propDescriptor)
+ },
+ this
+ )
+}
+
+ActivitiModdleExtension.$inject = ['eventBus']
+
+ActivitiModdleExtension.prototype.canCloneProperty = function (newElement, propDescriptor) {
+ if (isAllowed('activiti:FailedJobRetryTimeCycle', propDescriptor, newElement)) {
+ return (
+ includesType(newElement.eventDefinitions, 'bpmn:TimerEventDefinition') ||
+ includesType(newElement.eventDefinitions, 'bpmn:SignalEventDefinition') ||
+ is(newElement.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')
+ )
+ }
+
+ if (isAllowed('activiti:Connector', propDescriptor, newElement)) {
+ return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition')
+ }
+
+ if (isAllowed('activiti:Field', propDescriptor, newElement)) {
+ return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition')
+ }
+}
+
+// module.exports = ActivitiModdleExtension;
+export default ActivitiModdleExtension
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js
new file mode 100644
index 0000000..c22ca34
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js
@@ -0,0 +1,11 @@
+/*
+ * @author igdianov
+ * address https://github.com/igdianov/activiti-bpmn-moddle
+ * */
+
+import activitiExtension from './activitiExtension'
+
+export default {
+ __init__: ['ActivitiModdleExtension'],
+ ActivitiModdleExtension: ['type', activitiExtension]
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js
new file mode 100644
index 0000000..b8c37a5
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js
@@ -0,0 +1,151 @@
+'use strict'
+
+import { isFunction, isObject, some } from 'min-dash'
+
+// const isFunction = isFunction,
+// isObject = isObject,
+// some = some
+// const isFunction = require('min-dash').isFunction,
+// isObject = require('min-dash').isObject,
+// some = require('min-dash').some
+
+const WILDCARD = '*'
+
+function CamundaModdleExtension(eventBus) {
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
+ const self = this
+
+ eventBus.on('moddleCopy.canCopyProperty', function (context) {
+ const property = context.property,
+ parent = context.parent
+
+ return self.canCopyProperty(property, parent)
+ })
+}
+
+CamundaModdleExtension.$inject = ['eventBus']
+
+/**
+ * Check wether to disallow copying property.
+ */
+CamundaModdleExtension.prototype.canCopyProperty = function (property, parent) {
+ // (1) check wether property is allowed in parent
+ if (isObject(property) && !isAllowedInParent(property, parent)) {
+ return false
+ }
+
+ // (2) check more complex scenarios
+
+ if (is(property, 'camunda:InputOutput') && !this.canHostInputOutput(parent)) {
+ return false
+ }
+
+ if (isAny(property, ['camunda:Connector', 'camunda:Field']) && !this.canHostConnector(parent)) {
+ return false
+ }
+
+ if (is(property, 'camunda:In') && !this.canHostIn(parent)) {
+ return false
+ }
+}
+
+CamundaModdleExtension.prototype.canHostInputOutput = function (parent) {
+ // allowed in camunda:Connector
+ const connector = getParent(parent, 'camunda:Connector')
+
+ if (connector) {
+ return true
+ }
+
+ // special rules inside bpmn:FlowNode
+ const flowNode = getParent(parent, 'bpmn:FlowNode')
+
+ if (!flowNode) {
+ return false
+ }
+
+ if (isAny(flowNode, ['bpmn:StartEvent', 'bpmn:Gateway', 'bpmn:BoundaryEvent'])) {
+ return false
+ }
+
+ return !(is(flowNode, 'bpmn:SubProcess') && flowNode.get('triggeredByEvent'))
+}
+
+CamundaModdleExtension.prototype.canHostConnector = function (parent) {
+ const serviceTaskLike = getParent(parent, 'camunda:ServiceTaskLike')
+
+ if (is(serviceTaskLike, 'bpmn:MessageEventDefinition')) {
+ // only allow on throw and end events
+ return getParent(parent, 'bpmn:IntermediateThrowEvent') || getParent(parent, 'bpmn:EndEvent')
+ }
+
+ return true
+}
+
+CamundaModdleExtension.prototype.canHostIn = function (parent) {
+ const callActivity = getParent(parent, 'bpmn:CallActivity')
+
+ if (callActivity) {
+ return true
+ }
+
+ const signalEventDefinition = getParent(parent, 'bpmn:SignalEventDefinition')
+
+ if (signalEventDefinition) {
+ // only allow on throw and end events
+ return getParent(parent, 'bpmn:IntermediateThrowEvent') || getParent(parent, 'bpmn:EndEvent')
+ }
+
+ return true
+}
+
+// module.exports = CamundaModdleExtension;
+export default CamundaModdleExtension
+
+// helpers //////////
+
+function is(element, type) {
+ return element && isFunction(element.$instanceOf) && element.$instanceOf(type)
+}
+
+function isAny(element, types) {
+ return some(types, function (t) {
+ return is(element, t)
+ })
+}
+
+function getParent(element, type) {
+ if (!type) {
+ return element.$parent
+ }
+
+ if (is(element, type)) {
+ return element
+ }
+
+ if (!element.$parent) {
+ return
+ }
+
+ return getParent(element.$parent, type)
+}
+
+function isAllowedInParent(property, parent) {
+ // (1) find property descriptor
+ const descriptor = property.$type && property.$model.getTypeDescriptor(property.$type)
+
+ const allowedIn = descriptor && descriptor.meta && descriptor.meta.allowedIn
+
+ if (!allowedIn || isWildcard(allowedIn)) {
+ return true
+ }
+
+ // (2) check wether property has parent of allowed type
+ return some(allowedIn, function (type) {
+ return getParent(parent, type)
+ })
+}
+
+function isWildcard(allowedIn) {
+ return allowedIn.indexOf(WILDCARD) !== -1
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js
new file mode 100644
index 0000000..1da1bc7
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js
@@ -0,0 +1,8 @@
+'use strict'
+
+import extension from './extension'
+
+export default {
+ __init__: ['camundaModdleExtension'],
+ camundaModdleExtension: ['type', extension]
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js
new file mode 100644
index 0000000..3dcea67
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js
@@ -0,0 +1,83 @@
+'use strict'
+
+import { some } from 'min-dash'
+
+// const some = some
+// const some = require('min-dash').some
+
+const ALLOWED_TYPES = {
+ FailedJobRetryTimeCycle: [
+ 'bpmn:StartEvent',
+ 'bpmn:BoundaryEvent',
+ 'bpmn:IntermediateCatchEvent',
+ 'bpmn:Activity'
+ ],
+ Connector: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent'],
+ Field: ['bpmn:EndEvent', 'bpmn:IntermediateThrowEvent']
+}
+
+function is(element, type) {
+ return element && typeof element.$instanceOf === 'function' && element.$instanceOf(type)
+}
+
+function exists(element) {
+ return element && element.length
+}
+
+function includesType(collection, type) {
+ return (
+ exists(collection) &&
+ some(collection, function (element) {
+ return is(element, type)
+ })
+ )
+}
+
+function anyType(element, types) {
+ return some(types, function (type) {
+ return is(element, type)
+ })
+}
+
+function isAllowed(propName, propDescriptor, newElement) {
+ const name = propDescriptor.name,
+ types = ALLOWED_TYPES[name.replace(/flowable:/, '')]
+
+ return name === propName && anyType(newElement, types)
+}
+
+function FlowableModdleExtension(eventBus) {
+ eventBus.on(
+ 'property.clone',
+ function (context) {
+ const newElement = context.newElement,
+ propDescriptor = context.propertyDescriptor
+
+ this.canCloneProperty(newElement, propDescriptor)
+ },
+ this
+ )
+}
+
+FlowableModdleExtension.$inject = ['eventBus']
+
+FlowableModdleExtension.prototype.canCloneProperty = function (newElement, propDescriptor) {
+ if (isAllowed('flowable:FailedJobRetryTimeCycle', propDescriptor, newElement)) {
+ return (
+ includesType(newElement.eventDefinitions, 'bpmn:TimerEventDefinition') ||
+ includesType(newElement.eventDefinitions, 'bpmn:SignalEventDefinition') ||
+ is(newElement.loopCharacteristics, 'bpmn:MultiInstanceLoopCharacteristics')
+ )
+ }
+
+ if (isAllowed('flowable:Connector', propDescriptor, newElement)) {
+ return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition')
+ }
+
+ if (isAllowed('flowable:Field', propDescriptor, newElement)) {
+ return includesType(newElement.eventDefinitions, 'bpmn:MessageEventDefinition')
+ }
+}
+
+// module.exports = FlowableModdleExtension;
+export default FlowableModdleExtension
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js
new file mode 100644
index 0000000..6d59b67
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js
@@ -0,0 +1,10 @@
+/*
+ * @author igdianov
+ * address https://github.com/igdianov/activiti-bpmn-moddle
+ * */
+import flowableExtension from './flowableExtension'
+
+export default {
+ __init__: ['FlowableModdleExtension'],
+ FlowableModdleExtension: ['type', flowableExtension]
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js
new file mode 100644
index 0000000..788e4d1
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js
@@ -0,0 +1,233 @@
+import PaletteProvider from 'bpmn-js/lib/features/palette/PaletteProvider'
+import { assign } from 'min-dash'
+
+export default function CustomPalette(
+ palette,
+ create,
+ elementFactory,
+ spaceTool,
+ lassoTool,
+ handTool,
+ globalConnect,
+ translate
+) {
+ PaletteProvider.call(
+ this,
+ palette,
+ create,
+ elementFactory,
+ spaceTool,
+ lassoTool,
+ handTool,
+ globalConnect,
+ translate,
+ 2000
+ )
+}
+
+const F = function () {} // 核心,利用空对象作为中介;
+F.prototype = PaletteProvider.prototype // 核心,将父类的原型赋值给空对象F;
+
+// 利用中介函数重写原型链方法
+F.prototype.getPaletteEntries = function () {
+ const actions = {},
+ create = this._create,
+ elementFactory = this._elementFactory,
+ spaceTool = this._spaceTool,
+ lassoTool = this._lassoTool,
+ handTool = this._handTool,
+ globalConnect = this._globalConnect,
+ translate = this._translate
+
+ function createAction(type, group, className, title, options) {
+ function createListener(event) {
+ const shape = elementFactory.createShape(assign({ type: type }, options))
+
+ if (options) {
+ shape.businessObject.di.isExpanded = options.isExpanded
+ }
+
+ create.start(event, shape)
+ }
+
+ const shortType = type.replace(/^bpmn:/, '')
+
+ return {
+ group: group,
+ className: className,
+ title: title || translate('Create {type}', { type: shortType }),
+ action: {
+ dragstart: createListener,
+ click: createListener
+ }
+ }
+ }
+
+ function createSubprocess(event) {
+ const subProcess = elementFactory.createShape({
+ type: 'bpmn:SubProcess',
+ x: 0,
+ y: 0,
+ isExpanded: true
+ })
+
+ const startEvent = elementFactory.createShape({
+ type: 'bpmn:StartEvent',
+ x: 40,
+ y: 82,
+ parent: subProcess
+ })
+
+ create.start(event, [subProcess, startEvent], {
+ hints: {
+ autoSelect: [startEvent]
+ }
+ })
+ }
+
+ function createParticipant(event) {
+ create.start(event, elementFactory.createParticipantShape())
+ }
+
+ assign(actions, {
+ 'hand-tool': {
+ group: 'tools',
+ className: 'bpmn-icon-hand-tool',
+ title: '激活抓手工具',
+ // title: translate("Activate the hand tool"),
+ action: {
+ click: function (event) {
+ handTool.activateHand(event)
+ }
+ }
+ },
+ 'lasso-tool': {
+ group: 'tools',
+ className: 'bpmn-icon-lasso-tool',
+ title: translate('Activate the lasso tool'),
+ action: {
+ click: function (event) {
+ lassoTool.activateSelection(event)
+ }
+ }
+ },
+ 'space-tool': {
+ group: 'tools',
+ className: 'bpmn-icon-space-tool',
+ title: translate('Activate the create/remove space tool'),
+ action: {
+ click: function (event) {
+ spaceTool.activateSelection(event)
+ }
+ }
+ },
+ 'global-connect-tool': {
+ group: 'tools',
+ className: 'bpmn-icon-connection-multi',
+ title: translate('Activate the global connect tool'),
+ action: {
+ click: function (event) {
+ globalConnect.toggle(event)
+ }
+ }
+ },
+ 'tool-separator': {
+ group: 'tools',
+ separator: true
+ },
+ 'create.start-event': createAction(
+ 'bpmn:StartEvent',
+ 'event',
+ 'bpmn-icon-start-event-none',
+ translate('Create StartEvent')
+ ),
+ 'create.intermediate-event': createAction(
+ 'bpmn:IntermediateThrowEvent',
+ 'event',
+ 'bpmn-icon-intermediate-event-none',
+ translate('Create Intermediate/Boundary Event')
+ ),
+ 'create.end-event': createAction(
+ 'bpmn:EndEvent',
+ 'event',
+ 'bpmn-icon-end-event-none',
+ translate('Create EndEvent')
+ ),
+ 'create.exclusive-gateway': createAction(
+ 'bpmn:ExclusiveGateway',
+ 'gateway',
+ 'bpmn-icon-gateway-none',
+ translate('Create Gateway')
+ ),
+ 'create.user-task': createAction(
+ 'bpmn:UserTask',
+ 'activity',
+ 'bpmn-icon-user-task',
+ translate('Create User Task')
+ ),
+ 'create.call-activity': createAction(
+ 'bpmn:CallActivity',
+ 'activity',
+ 'bpmn-icon-call-activity',
+ translate('Create Call Activity')
+ ),
+ 'create.service-task': createAction(
+ 'bpmn:ServiceTask',
+ 'activity',
+ 'bpmn-icon-service',
+ translate('Create Service Task')
+ ),
+ 'create.data-object': createAction(
+ 'bpmn:DataObjectReference',
+ 'data-object',
+ 'bpmn-icon-data-object',
+ translate('Create DataObjectReference')
+ ),
+ 'create.data-store': createAction(
+ 'bpmn:DataStoreReference',
+ 'data-store',
+ 'bpmn-icon-data-store',
+ translate('Create DataStoreReference')
+ ),
+ 'create.subprocess-expanded': {
+ group: 'activity',
+ className: 'bpmn-icon-subprocess-expanded',
+ title: translate('Create expanded SubProcess'),
+ action: {
+ dragstart: createSubprocess,
+ click: createSubprocess
+ }
+ },
+ 'create.participant-expanded': {
+ group: 'collaboration',
+ className: 'bpmn-icon-participant',
+ title: translate('Create Pool/Participant'),
+ action: {
+ dragstart: createParticipant,
+ click: createParticipant
+ }
+ },
+ 'create.group': createAction(
+ 'bpmn:Group',
+ 'artifact',
+ 'bpmn-icon-group',
+ translate('Create Group')
+ )
+ })
+
+ return actions
+}
+
+CustomPalette.$inject = [
+ 'palette',
+ 'create',
+ 'elementFactory',
+ 'spaceTool',
+ 'lassoTool',
+ 'handTool',
+ 'globalConnect',
+ 'translate'
+]
+
+CustomPalette.prototype = new F() // 核心,将 F的实例赋值给子类;
+CustomPalette.prototype.constructor = CustomPalette // 修复子类CustomPalette的构造器指向,防止原型链的混乱;
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js
new file mode 100644
index 0000000..8e4f3ac
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js
@@ -0,0 +1,22 @@
+// import PaletteModule from "diagram-js/lib/features/palette";
+// import CreateModule from "diagram-js/lib/features/create";
+// import SpaceToolModule from "diagram-js/lib/features/space-tool";
+// import LassoToolModule from "diagram-js/lib/features/lasso-tool";
+// import HandToolModule from "diagram-js/lib/features/hand-tool";
+// import GlobalConnectModule from "diagram-js/lib/features/global-connect";
+// import translate from "diagram-js/lib/i18n/translate";
+//
+// import PaletteProvider from "./paletteProvider";
+//
+// export default {
+// __depends__: [PaletteModule, CreateModule, SpaceToolModule, LassoToolModule, HandToolModule, GlobalConnectModule, translate],
+// __init__: ["paletteProvider"],
+// paletteProvider: ["type", PaletteProvider]
+// };
+
+import CustomPalette from './CustomPalette'
+
+export default {
+ __init__: ['paletteProvider'],
+ paletteProvider: ['type', CustomPalette]
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js
new file mode 100644
index 0000000..304875c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js
@@ -0,0 +1,219 @@
+import { assign } from 'min-dash'
+
+/**
+ * A palette provider for BPMN 2.0 elements.
+ */
+export default function PaletteProvider(
+ palette,
+ create,
+ elementFactory,
+ spaceTool,
+ lassoTool,
+ handTool,
+ globalConnect,
+ translate
+) {
+ this._palette = palette
+ this._create = create
+ this._elementFactory = elementFactory
+ this._spaceTool = spaceTool
+ this._lassoTool = lassoTool
+ this._handTool = handTool
+ this._globalConnect = globalConnect
+ this._translate = translate
+
+ palette.registerProvider(this)
+}
+
+PaletteProvider.$inject = [
+ 'palette',
+ 'create',
+ 'elementFactory',
+ 'spaceTool',
+ 'lassoTool',
+ 'handTool',
+ 'globalConnect',
+ 'translate'
+]
+
+PaletteProvider.prototype.getPaletteEntries = function () {
+ const actions = {},
+ create = this._create,
+ elementFactory = this._elementFactory,
+ spaceTool = this._spaceTool,
+ lassoTool = this._lassoTool,
+ handTool = this._handTool,
+ globalConnect = this._globalConnect,
+ translate = this._translate
+
+ function createAction(type, group, className, title, options) {
+ function createListener(event) {
+ const shape = elementFactory.createShape(assign({ type: type }, options))
+
+ if (options) {
+ shape.businessObject.di.isExpanded = options.isExpanded
+ }
+
+ create.start(event, shape)
+ }
+
+ const shortType = type.replace(/^bpmn:/, '')
+
+ return {
+ group: group,
+ className: className,
+ title: title || translate('Create {type}', { type: shortType }),
+ action: {
+ dragstart: createListener,
+ click: createListener
+ }
+ }
+ }
+
+ function createSubprocess(event) {
+ const subProcess = elementFactory.createShape({
+ type: 'bpmn:SubProcess',
+ x: 0,
+ y: 0,
+ isExpanded: true
+ })
+
+ const startEvent = elementFactory.createShape({
+ type: 'bpmn:StartEvent',
+ x: 40,
+ y: 82,
+ parent: subProcess
+ })
+
+ create.start(event, [subProcess, startEvent], {
+ hints: {
+ autoSelect: [startEvent]
+ }
+ })
+ }
+
+ function createParticipant(event) {
+ create.start(event, elementFactory.createParticipantShape())
+ }
+
+ assign(actions, {
+ 'hand-tool': {
+ group: 'tools',
+ className: 'bpmn-icon-hand-tool',
+ title: translate('Activate the hand tool'),
+ action: {
+ click: function (event) {
+ handTool.activateHand(event)
+ }
+ }
+ },
+ 'lasso-tool': {
+ group: 'tools',
+ className: 'bpmn-icon-lasso-tool',
+ title: translate('Activate the lasso tool'),
+ action: {
+ click: function (event) {
+ lassoTool.activateSelection(event)
+ }
+ }
+ },
+ 'space-tool': {
+ group: 'tools',
+ className: 'bpmn-icon-space-tool',
+ title: translate('Activate the create/remove space tool'),
+ action: {
+ click: function (event) {
+ spaceTool.activateSelection(event)
+ }
+ }
+ },
+ 'global-connect-tool': {
+ group: 'tools',
+ className: 'bpmn-icon-connection-multi',
+ title: translate('Activate the global connect tool'),
+ action: {
+ click: function (event) {
+ globalConnect.toggle(event)
+ }
+ }
+ },
+ 'tool-separator': {
+ group: 'tools',
+ separator: true
+ },
+ 'create.start-event': createAction(
+ 'bpmn:StartEvent',
+ 'event',
+ 'bpmn-icon-start-event-none',
+ translate('Create StartEvent')
+ ),
+ 'create.intermediate-event': createAction(
+ 'bpmn:IntermediateThrowEvent',
+ 'event',
+ 'bpmn-icon-intermediate-event-none',
+ translate('Create Intermediate/Boundary Event')
+ ),
+ 'create.end-event': createAction(
+ 'bpmn:EndEvent',
+ 'event',
+ 'bpmn-icon-end-event-none',
+ translate('Create EndEvent')
+ ),
+ 'create.exclusive-gateway': createAction(
+ 'bpmn:ExclusiveGateway',
+ 'gateway',
+ 'bpmn-icon-gateway-none',
+ translate('Create Gateway')
+ ),
+ 'create.user-task': createAction(
+ 'bpmn:UserTask',
+ 'activity',
+ 'bpmn-icon-user-task',
+ translate('Create User Task')
+ ),
+ 'create.service-task': createAction(
+ 'bpmn:ServiceTask',
+ 'activity',
+ 'bpmn-icon-service',
+ translate('Create Service Task')
+ ),
+ 'create.data-object': createAction(
+ 'bpmn:DataObjectReference',
+ 'data-object',
+ 'bpmn-icon-data-object',
+ translate('Create DataObjectReference')
+ ),
+ 'create.data-store': createAction(
+ 'bpmn:DataStoreReference',
+ 'data-store',
+ 'bpmn-icon-data-store',
+ translate('Create DataStoreReference')
+ ),
+ 'create.subprocess-expanded': {
+ group: 'activity',
+ className: 'bpmn-icon-subprocess-expanded',
+ title: translate('Create expanded SubProcess'),
+ action: {
+ dragstart: createSubprocess,
+ click: createSubprocess
+ }
+ },
+ 'create.participant-expanded': {
+ group: 'collaboration',
+ className: 'bpmn-icon-participant',
+ title: translate('Create Pool/Participant'),
+ action: {
+ dragstart: createParticipant,
+ click: createParticipant
+ }
+ },
+ 'create.group': createAction(
+ 'bpmn:Group',
+ 'artifact',
+ 'bpmn-icon-group',
+ translate('Create Group')
+ )
+ })
+
+ return actions
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js
new file mode 100644
index 0000000..c1b99e1
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js
@@ -0,0 +1,44 @@
+// import translations from "./zh";
+//
+// export default function customTranslate(template, replacements) {
+// replacements = replacements || {};
+//
+// // Translate
+// template = translations[template] || template;
+//
+// // Replace
+// return template.replace(/{([^}]+)}/g, function(_, key) {
+// let str = replacements[key];
+// if (
+// translations[replacements[key]] !== null &&
+// translations[replacements[key]] !== "undefined"
+// ) {
+// // eslint-disable-next-line no-mixed-spaces-and-tabs
+// str = translations[replacements[key]];
+// // eslint-disable-next-line no-mixed-spaces-and-tabs
+// }
+// return str || "{" + key + "}";
+// });
+// }
+
+export default function customTranslate(translations) {
+ return function (template, replacements) {
+ replacements = replacements || {}
+ // Translate
+ template = translations[template] || template
+
+ // Replace
+ return template.replace(/{([^}]+)}/g, function (_, key) {
+ let str = replacements[key]
+ if (
+ translations[replacements[key]] !== null &&
+ translations[replacements[key]] !== undefined
+ ) {
+ // eslint-disable-next-line no-mixed-spaces-and-tabs
+ str = translations[replacements[key]]
+ // eslint-disable-next-line no-mixed-spaces-and-tabs
+ }
+ return str || '{' + key + '}'
+ })
+ }
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js
new file mode 100644
index 0000000..cb92041
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js
@@ -0,0 +1,242 @@
+/**
+ * This is a sample file that should be replaced with the actual translation.
+ *
+ * Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available
+ * translations and labels to translate.
+ */
+export default {
+ // 添加部分
+ 'Append EndEvent': '追加结束事件',
+ 'Append Gateway': '追加网关',
+ 'Append Task': '追加任务',
+ 'Append Intermediate/Boundary Event': '追加中间抛出事件/边界事件',
+
+ 'Activate the global connect tool': '激活全局连接工具',
+ 'Append {type}': '添加 {type}',
+ 'Add Lane above': '在上面添加道',
+ 'Divide into two Lanes': '分割成两个道',
+ 'Divide into three Lanes': '分割成三个道',
+ 'Add Lane below': '在下面添加道',
+ 'Append compensation activity': '追加补偿活动',
+ 'Change type': '修改类型',
+ 'Connect using Association': '使用关联连接',
+ 'Connect using Sequence/MessageFlow or Association': '使用顺序/消息流或者关联连接',
+ 'Connect using DataInputAssociation': '使用数据输入关联连接',
+ Remove: '移除',
+ 'Activate the hand tool': '激活抓手工具',
+ 'Activate the lasso tool': '激活套索工具',
+ 'Activate the create/remove space tool': '激活创建/删除空间工具',
+ 'Create expanded SubProcess': '创建扩展子过程',
+ 'Create IntermediateThrowEvent/BoundaryEvent': '创建中间抛出事件/边界事件',
+ 'Create Pool/Participant': '创建池/参与者',
+ 'Parallel Multi Instance': '并行多重事件',
+ 'Sequential Multi Instance': '时序多重事件',
+ DataObjectReference: '数据对象参考',
+ DataStoreReference: '数据存储参考',
+ Loop: '循环',
+ 'Ad-hoc': '即席',
+ 'Create {type}': '创建 {type}',
+ Task: '任务',
+ 'Send Task': '发送任务',
+ 'Receive Task': '接收任务',
+ 'User Task': '用户任务',
+ 'Manual Task': '手工任务',
+ 'Business Rule Task': '业务规则任务',
+ 'Service Task': '服务任务',
+ 'Script Task': '脚本任务',
+ 'Call Activity': '调用活动',
+ 'Sub Process (collapsed)': '子流程(折叠的)',
+ 'Sub Process (expanded)': '子流程(展开的)',
+ 'Start Event': '开始事件',
+ StartEvent: '开始事件',
+ 'Intermediate Throw Event': '中间事件',
+ 'End Event': '结束事件',
+ EndEvent: '结束事件',
+ 'Create StartEvent': '创建开始事件',
+ 'Create EndEvent': '创建结束事件',
+ 'Create Task': '创建任务',
+ 'Create User Task': '创建用户任务',
+ 'Create Call Activity': '创建调用活动',
+ 'Create Service Task': '创建服务任务',
+ 'Create Gateway': '创建网关',
+ 'Create DataObjectReference': '创建数据对象',
+ 'Create DataStoreReference': '创建数据存储',
+ 'Create Group': '创建分组',
+ 'Create Intermediate/Boundary Event': '创建中间/边界事件',
+ 'Message Start Event': '消息开始事件',
+ 'Timer Start Event': '定时开始事件',
+ 'Conditional Start Event': '条件开始事件',
+ 'Signal Start Event': '信号开始事件',
+ 'Error Start Event': '错误开始事件',
+ 'Escalation Start Event': '升级开始事件',
+ 'Compensation Start Event': '补偿开始事件',
+ 'Message Start Event (non-interrupting)': '消息开始事件(非中断)',
+ 'Timer Start Event (non-interrupting)': '定时开始事件(非中断)',
+ 'Conditional Start Event (non-interrupting)': '条件开始事件(非中断)',
+ 'Signal Start Event (non-interrupting)': '信号开始事件(非中断)',
+ 'Escalation Start Event (non-interrupting)': '升级开始事件(非中断)',
+ 'Message Intermediate Catch Event': '消息中间捕获事件',
+ 'Message Intermediate Throw Event': '消息中间抛出事件',
+ 'Timer Intermediate Catch Event': '定时中间捕获事件',
+ 'Escalation Intermediate Throw Event': '升级中间抛出事件',
+ 'Conditional Intermediate Catch Event': '条件中间捕获事件',
+ 'Link Intermediate Catch Event': '链接中间捕获事件',
+ 'Link Intermediate Throw Event': '链接中间抛出事件',
+ 'Compensation Intermediate Throw Event': '补偿中间抛出事件',
+ 'Signal Intermediate Catch Event': '信号中间捕获事件',
+ 'Signal Intermediate Throw Event': '信号中间抛出事件',
+ 'Message End Event': '消息结束事件',
+ 'Escalation End Event': '定时结束事件',
+ 'Error End Event': '错误结束事件',
+ 'Cancel End Event': '取消结束事件',
+ 'Compensation End Event': '补偿结束事件',
+ 'Signal End Event': '信号结束事件',
+ 'Terminate End Event': '终止结束事件',
+ 'Message Boundary Event': '消息边界事件',
+ 'Message Boundary Event (non-interrupting)': '消息边界事件(非中断)',
+ 'Timer Boundary Event': '定时边界事件',
+ 'Timer Boundary Event (non-interrupting)': '定时边界事件(非中断)',
+ 'Escalation Boundary Event': '升级边界事件',
+ 'Escalation Boundary Event (non-interrupting)': '升级边界事件(非中断)',
+ 'Conditional Boundary Event': '条件边界事件',
+ 'Conditional Boundary Event (non-interrupting)': '条件边界事件(非中断)',
+ 'Error Boundary Event': '错误边界事件',
+ 'Cancel Boundary Event': '取消边界事件',
+ 'Signal Boundary Event': '信号边界事件',
+ 'Signal Boundary Event (non-interrupting)': '信号边界事件(非中断)',
+ 'Compensation Boundary Event': '补偿边界事件',
+ 'Exclusive Gateway': '互斥网关',
+ 'Parallel Gateway': '并行网关',
+ 'Inclusive Gateway': '相容网关',
+ 'Complex Gateway': '复杂网关',
+ 'Event based Gateway': '事件网关',
+ Transaction: '转运',
+ 'Sub Process': '子流程',
+ 'Event Sub Process': '事件子流程',
+ 'Collapsed Pool': '折叠池',
+ 'Expanded Pool': '展开池',
+
+ // Errors
+ 'no parent for {element} in {parent}': '在{parent}里,{element}没有父类',
+ 'no shape type specified': '没有指定的形状类型',
+ 'flow elements must be children of pools/participants': '流元素必须是池/参与者的子类',
+ 'out of bounds release': 'out of bounds release',
+ 'more than {count} child lanes': '子道大于{count} ',
+ 'element required': '元素不能为空',
+ 'diagram not part of bpmn:Definitions': '流程图不符合bpmn规范',
+ 'no diagram to display': '没有可展示的流程图',
+ 'no process or collaboration to display': '没有可展示的流程/协作',
+ 'element {element} referenced by {referenced}#{property} not yet drawn':
+ '由{referenced}#{property}引用的{element}元素仍未绘制',
+ 'already rendered {element}': '{element} 已被渲染',
+ 'failed to import {element}': '导入{element}失败',
+ //属性面板的参数
+ Id: '编号',
+ Name: '名称',
+ General: '常规',
+ Details: '详情',
+ 'Message Name': '消息名称',
+ Message: '消息',
+ Initiator: '创建者',
+ 'Asynchronous Continuations': '持续异步',
+ 'Asynchronous Before': '异步前',
+ 'Asynchronous After': '异步后',
+ 'Job Configuration': '工作配置',
+ Exclusive: '排除',
+ 'Job Priority': '工作优先级',
+ 'Retry Time Cycle': '重试时间周期',
+ Documentation: '文档',
+ 'Element Documentation': '元素文档',
+ 'History Configuration': '历史配置',
+ 'History Time To Live': '历史的生存时间',
+ Forms: '表单',
+ 'Form Key': '表单key',
+ 'Form Fields': '表单字段',
+ 'Business Key': '业务key',
+ 'Form Field': '表单字段',
+ ID: '编号',
+ Type: '类型',
+ Label: '名称',
+ 'Default Value': '默认值',
+ 'Default Flow': '默认流转路径',
+ 'Conditional Flow': '条件流转路径',
+ 'Sequence Flow': '普通流转路径',
+ Validation: '校验',
+ 'Add Constraint': '添加约束',
+ Config: '配置',
+ Properties: '属性',
+ 'Add Property': '添加属性',
+ Value: '值',
+ Listeners: '监听器',
+ 'Execution Listener': '执行监听',
+ 'Event Type': '事件类型',
+ 'Listener Type': '监听器类型',
+ 'Java Class': 'Java类',
+ Expression: '表达式',
+ 'Must provide a value': '必须提供一个值',
+ 'Delegate Expression': '代理表达式',
+ Script: '脚本',
+ 'Script Format': '脚本格式',
+ 'Script Type': '脚本类型',
+ 'Inline Script': '内联脚本',
+ 'External Script': '外部脚本',
+ Resource: '资源',
+ 'Field Injection': '字段注入',
+ Extensions: '扩展',
+ 'Input/Output': '输入/输出',
+ 'Input Parameters': '输入参数',
+ 'Output Parameters': '输出参数',
+ Parameters: '参数',
+ 'Output Parameter': '输出参数',
+ 'Timer Definition Type': '定时器定义类型',
+ 'Timer Definition': '定时器定义',
+ Date: '日期',
+ Duration: '持续',
+ Cycle: '循环',
+ Signal: '信号',
+ 'Signal Name': '信号名称',
+ Escalation: '升级',
+ Error: '错误',
+ 'Link Name': '链接名称',
+ Condition: '条件名称',
+ 'Variable Name': '变量名称',
+ 'Variable Event': '变量事件',
+ 'Specify more than one variable change event as a comma separated list.':
+ '多个变量事件以逗号隔开',
+ 'Wait for Completion': '等待完成',
+ 'Activity Ref': '活动参考',
+ 'Version Tag': '版本标签',
+ Executable: '可执行文件',
+ 'External Task Configuration': '扩展任务配置',
+ 'Task Priority': '任务优先级',
+ External: '外部',
+ Connector: '连接器',
+ 'Must configure Connector': '必须配置连接器',
+ 'Connector Id': '连接器编号',
+ Implementation: '实现方式',
+ 'Field Injections': '字段注入',
+ Fields: '字段',
+ 'Result Variable': '结果变量',
+ Topic: '主题',
+ 'Configure Connector': '配置连接器',
+ 'Input Parameter': '输入参数',
+ Assignee: '代理人',
+ 'Candidate Users': '候选用户',
+ 'Candidate Groups': '候选组',
+ 'Due Date': '到期时间',
+ 'Follow Up Date': '跟踪日期',
+ Priority: '优先级',
+ 'The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)':
+ '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00',
+ 'The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)':
+ '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00',
+ Variables: '变量',
+ 'Candidate Starter Configuration': '候选人起动器配置',
+ 'Candidate Starter Groups': '候选人起动器组',
+ 'This maps to the process definition key.': '这映射到流程定义键。',
+ 'Candidate Starter Users': '候选人起动器的用户',
+ 'Specify more than one user as a comma separated list.': '指定多个用户作为逗号分隔的列表。',
+ 'Tasklist Configuration': 'Tasklist配置',
+ Startable: '启动',
+ 'Specify more than one group as a comma separated list.': '指定多个组作为逗号分隔的列表。'
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/index.ts b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/index.ts
new file mode 100644
index 0000000..ce44a3c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/index.ts
@@ -0,0 +1,11 @@
+import MyProcessDesigner from './designer'
+import MyProcessPenal from './penal'
+import MyProcessViewer from './designer/index2'
+
+import './theme/index.scss'
+import 'bpmn-js/dist/assets/diagram-js.css'
+import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
+import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
+import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
+
+export { MyProcessDesigner, MyProcessPenal, MyProcessViewer }
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue
new file mode 100644
index 0000000..ba97d96
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue
new file mode 100644
index 0000000..ff08dd3
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue
@@ -0,0 +1,258 @@
+
+
+
+
+
+
+
+ 常规
+
+
+
+ 消息与信号
+
+
+
+ 流转条件
+
+
+
+ 表单
+
+
+
+ {{ getTaskCollapseItemName(elementType) }}
+
+
+
+ 多人审批方式
+
+
+
+ 执行监听器
+
+
+
+ 任务监听器
+
+
+
+ 扩展属性
+
+
+
+ 其他
+
+
+
+ 自定义配置
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue
new file mode 100644
index 0000000..3172338
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue
new file mode 100644
index 0000000..f9cb9ac
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue
new file mode 100644
index 0000000..ca46b27
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue
@@ -0,0 +1,252 @@
+
+
+ 审批人超时未处理时
+
+
+
+
+
+
+
+
+
+ 当超过
+
+ updateTimeModdle()"
+ />
+
+
+
+
+ 未处理
+
+
+ updateTimeModdle()"
+ />
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue
new file mode 100644
index 0000000..3c748ff
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue
@@ -0,0 +1,688 @@
+
+
+
+
审批类型
+
+
+
+ {{ item.label }}
+
+
+
+
+
审批人拒绝时
+
+
+
+
+
+
+
+
+
+
+
+
审批人为空时
+
+
+
+
+
+
+
+
+
+
+
+
审批人与提交人为同一人时
+
+
+
+
+
操作按钮
+
+
+
字段权限
+
+
+
字段名称
+
+ 只读
+ 可编辑
+ 隐藏
+
+
+
+
{{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
是否需要签名
+
+
+
+
+
审批意见
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/data.ts b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/data.ts
new file mode 100644
index 0000000..a45355e
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/custom-config/data.ts
@@ -0,0 +1,13 @@
+import UserTaskCustomConfig from './components/UserTaskCustomConfig.vue'
+import BoundaryEventTimer from './components/BoundaryEventTimer.vue'
+
+export const CustomConfigMap = {
+ UserTask: {
+ name: '用户任务',
+ componet: UserTaskCustomConfig
+ },
+ BoundaryEventTimerEventDefinition: {
+ name: '定时边界事件(非中断)',
+ componet: BoundaryEventTimer
+ }
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue
new file mode 100644
index 0000000..304630d
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue
new file mode 100644
index 0000000..3bb7d66
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue
@@ -0,0 +1,478 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/index.js
new file mode 100644
index 0000000..7fa5617
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/index.js
@@ -0,0 +1,7 @@
+import MyPropertiesPanel from './PropertiesPanel.vue'
+
+MyPropertiesPanel.install = function (Vue) {
+ Vue.component(MyPropertiesPanel.name, MyPropertiesPanel)
+}
+
+export default MyPropertiesPanel
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue
new file mode 100644
index 0000000..de5445c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue
@@ -0,0 +1,448 @@
+
+
+
+
+
+
+
+
+ 编辑
+
+ 移除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 注入字段:
+
+
+
+
+
+
+
+
+
+ 编辑
+
+ 移除
+
+
+
+
+
+ 取 消
+ 保 存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取 消
+ 确 定
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue
new file mode 100644
index 0000000..21088ab
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue
new file mode 100644
index 0000000..76e0c80
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue
@@ -0,0 +1,491 @@
+
+
+
+
+
+
+
+
+
+ 编辑
+
+ 移除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 注入字段:
+ 添加字段
+
+
+
+
+
+
+
+
+ 编辑
+
+ 移除
+
+
+
+
+
+ 取 消
+ 保 存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取 消
+ 确 定
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/template.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/template.js
new file mode 100644
index 0000000..430dc64
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/template.js
@@ -0,0 +1,178 @@
+export const template = (isTaskListener) => {
+ return `
+
+
+
+
+
+
+
+ 编辑
+
+ 移除
+
+
+
+
+ 添加监听器
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${
+ isTaskListener
+ ? "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ '' +
+ '' +
+ "" +
+ "" +
+ ''
+ : ''
+ }
+
+
+
+ 注入字段:
+ 添加字段
+
+
+
+
+
+
+
+
+ 编辑
+
+ 移除
+
+
+
+
+
+ 取 消
+ 保 存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取 消
+ 确 定
+
+
+
+ `
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts
new file mode 100644
index 0000000..b4eb1d2
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts
@@ -0,0 +1,89 @@
+// 初始化表单数据
+export function initListenerForm(listener) {
+ let self = {
+ ...listener
+ }
+ if (listener.script) {
+ self = {
+ ...listener,
+ ...listener.script,
+ scriptType: listener.script.resource ? 'externalScript' : 'inlineScript'
+ }
+ }
+ if (listener.event === 'timeout' && listener.eventDefinitions) {
+ if (listener.eventDefinitions.length) {
+ let k = ''
+ for (const key in listener.eventDefinitions[0]) {
+ console.log(listener.eventDefinitions, key)
+ if (key.indexOf('time') !== -1) {
+ k = key
+ self.eventDefinitionType = key.replace('time', '').toLowerCase()
+ }
+ }
+ console.log(k)
+ self.eventTimeDefinitions = listener.eventDefinitions[0][k].body
+ }
+ }
+ return self
+}
+
+export function initListenerType(listener) {
+ let listenerType
+ if (listener.class) listenerType = 'classListener'
+ if (listener.expression) listenerType = 'expressionListener'
+ if (listener.delegateExpression) listenerType = 'delegateExpressionListener'
+ if (listener.script) listenerType = 'scriptListener'
+ return {
+ ...JSON.parse(JSON.stringify(listener)),
+ ...(listener.script ?? {}),
+ listenerType: listenerType
+ }
+}
+
+/** 将 ProcessListenerDO 转换成 initListenerForm 想同的 Form 对象 */
+export function initListenerForm2(processListener) {
+ if (processListener.valueType === 'class') {
+ return {
+ listenerType: 'classListener',
+ class: processListener.value,
+ event: processListener.event,
+ fields: []
+ }
+ } else if (processListener.valueType === 'expression') {
+ return {
+ listenerType: 'expressionListener',
+ expression: processListener.value,
+ event: processListener.event,
+ fields: []
+ }
+ } else if (processListener.valueType === 'delegateExpression') {
+ return {
+ listenerType: 'delegateExpressionListener',
+ delegateExpression: processListener.value,
+ event: processListener.event,
+ fields: []
+ }
+ }
+ throw new Error('未知的监听器类型')
+}
+
+export const listenerType = {
+ classListener: 'Java 类',
+ expressionListener: '表达式',
+ delegateExpressionListener: '代理表达式',
+ scriptListener: '脚本'
+}
+
+export const eventType = {
+ create: '创建',
+ assignment: '指派',
+ complete: '完成',
+ delete: '删除',
+ update: '更新',
+ timeout: '超时'
+}
+
+export const fieldType = {
+ string: '字符串',
+ expression: '表达式'
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue
new file mode 100644
index 0000000..99ee6f8
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue
@@ -0,0 +1,421 @@
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+ 除了UserTask以外节点的多实例待实现
+
+
+
+
+ 依次审批
+ 会签
+ 或签
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue
new file mode 100644
index 0000000..05532c6
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue
new file mode 100644
index 0000000..7bf4f0e
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+
+
+ 编辑
+
+
+
+ 移除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取 消
+ 确 定
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue
new file mode 100644
index 0000000..f38f31c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue
@@ -0,0 +1,113 @@
+
+
+
+ 消息列表
+
+
+
+
+
+
+
+
+ 信号列表
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取 消
+ 保 存
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue
new file mode 100644
index 0000000..3a71b4c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/data.ts b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/data.ts
new file mode 100644
index 0000000..805c9ac
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/data.ts
@@ -0,0 +1,36 @@
+import UserTask from './task-components/UserTask.vue'
+import ServiceTask from './task-components/ServiceTask.vue'
+import ScriptTask from './task-components/ScriptTask.vue'
+import ReceiveTask from './task-components/ReceiveTask.vue'
+import CallActivity from './task-components/CallActivity.vue'
+
+export const installedComponent = {
+ UserTask: {
+ name: '用户任务',
+ component: UserTask
+ },
+ ServiceTask: {
+ name: '服务任务',
+ component: ServiceTask
+ },
+ ScriptTask: {
+ name: '脚本任务',
+ component: ScriptTask
+ },
+ ReceiveTask: {
+ name: '接收任务',
+ component: ReceiveTask
+ },
+ CallActivity: {
+ name: '调用活动',
+ component: CallActivity
+ }
+}
+
+export const getTaskCollapseItemName = (elementType) => {
+ return installedComponent[elementType].name
+}
+
+export const isTaskCollapseItemShow = (elementType) => {
+ return installedComponent[elementType]
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue
new file mode 100644
index 0000000..6d8268b
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue
@@ -0,0 +1,280 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 输入参数
+
+
+
+
+
+
+
+
+ 编辑
+
+
+
+ 移除
+
+
+
+
+
+
+
+
+
+ 输出参数
+
+
+
+
+
+
+
+
+ 编辑
+
+
+
+ 移除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取 消
+ 确 定
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue
new file mode 100644
index 0000000..a038e69
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue
new file mode 100644
index 0000000..83ed24e
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 确 认
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue
new file mode 100644
index 0000000..683fef3
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue
new file mode 100644
index 0000000..2f9c535
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue
new file mode 100644
index 0000000..81088cc
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue
@@ -0,0 +1,469 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/element-variables.scss b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/element-variables.scss
new file mode 100644
index 0000000..0646f8e
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/element-variables.scss
@@ -0,0 +1,70 @@
+/* 改变主题色变量 */
+$--color-primary: #1890ff;
+$--color-danger: #ff4d4f;
+
+/* 改变 icon 字体路径变量,必需 */
+$--font-path: '~element-ui/lib/theme-chalk/fonts';
+
+@use '~element-ui/packages/theme-chalk/src/index';
+
+.el-table td,
+.el-table th {
+ color: #333;
+}
+.el-drawer__header {
+ padding: 16px 16px 8px 16px;
+ margin: 0;
+ line-height: 24px;
+ font-size: 18px;
+ color: #303133;
+ box-sizing: border-box;
+ border-bottom: 1px solid #e8e8e8;
+}
+div[class^='el-drawer']:focus,
+span:focus {
+ outline: none;
+}
+.el-drawer__body {
+ box-sizing: border-box;
+ padding: 16px;
+ width: 100%;
+ overflow-y: auto;
+}
+
+.el-dialog {
+ margin-top: 50vh !important;
+ transform: translateY(-50%);
+ overflow: hidden;
+}
+.el-dialog__wrapper {
+ overflow: hidden;
+ max-height: 100vh;
+}
+.el-dialog__header {
+ padding: 16px 16px 8px 16px;
+ box-sizing: border-box;
+ border-bottom: 1px solid #e8e8e8;
+}
+.el-dialog__body {
+ padding: 16px;
+ max-height: 80vh;
+ box-sizing: border-box;
+ overflow-y: auto;
+}
+.el-dialog__footer {
+ padding: 16px;
+ box-sizing: border-box;
+ border-top: 1px solid #e8e8e8;
+}
+.el-dialog__close {
+ font-weight: 600;
+}
+.el-select {
+ width: 100%;
+}
+.el-divider:not(.el-divider--horizontal) {
+ margin: 0 8px;
+}
+.el-divider.el-divider--horizontal {
+ margin: 16px 0;
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/index.scss b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/index.scss
new file mode 100644
index 0000000..2404760
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/index.scss
@@ -0,0 +1,117 @@
+@use './process-designer.scss';
+@use './process-panel.scss';
+
+$success-color: #4eb819;
+$primary-color: #409EFF;
+$danger-color: #F56C6C;
+$cancel-color: #909399;
+
+.process-viewer {
+ position: relative;
+ border: 1px solid #EFEFEF;
+ background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+') repeat!important;
+
+ .success-arrow {
+ fill: $success-color;
+ stroke: $success-color;
+ }
+
+ .success-conditional {
+ fill: white;
+ stroke: $success-color;
+ }
+
+ .success.djs-connection {
+ .djs-visual path {
+ stroke: $success-color!important;
+ //marker-end: url(#sequenceflow-end-white-success)!important;
+ }
+ }
+
+ .success.djs-connection.condition-expression {
+ .djs-visual path {
+ //marker-start: url(#conditional-flow-marker-white-success)!important;
+ }
+ }
+
+ .success.djs-shape {
+ .djs-visual rect {
+ stroke: $success-color!important;
+ fill: $success-color!important;
+ fill-opacity: 0.15!important;
+ }
+
+ .djs-visual polygon {
+ stroke: $success-color!important;
+ }
+
+ .djs-visual path:nth-child(2) {
+ stroke: $success-color!important;
+ fill: $success-color!important;
+ }
+
+ .djs-visual circle {
+ stroke: $success-color!important;
+ fill: $success-color!important;
+ fill-opacity: 0.15!important;
+ }
+ }
+
+ .primary.djs-shape {
+ .djs-visual rect {
+ stroke: $primary-color!important;
+ fill: $primary-color!important;
+ fill-opacity: 0.15!important;
+ }
+
+ .djs-visual polygon {
+ stroke: $primary-color!important;
+ }
+
+ .djs-visual circle {
+ stroke: $primary-color!important;
+ fill: $primary-color!important;
+ fill-opacity: 0.15!important;
+ }
+ }
+
+ .danger.djs-shape {
+ .djs-visual rect {
+ stroke: $danger-color!important;
+ fill: $danger-color!important;
+ fill-opacity: 0.15!important;
+ }
+
+ .djs-visual polygon {
+ stroke: $danger-color!important;
+ }
+
+ .djs-visual circle {
+ stroke: $danger-color!important;
+ fill: $danger-color!important;
+ fill-opacity: 0.15!important;
+ }
+ }
+
+ .cancel.djs-shape {
+ .djs-visual rect {
+ stroke: $cancel-color!important;
+ fill: $cancel-color!important;
+ fill-opacity: 0.15!important;
+ }
+
+ .djs-visual polygon {
+ stroke: $cancel-color!important;
+ }
+
+ .djs-visual circle {
+ stroke: $cancel-color!important;
+ fill: $cancel-color!important;
+ fill-opacity: 0.15!important;
+ }
+ }
+}
+
+.process-viewer .djs-tooltip-container, .process-viewer .djs-overlay-container, .process-viewer .djs-palette {
+ display: none;
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/process-designer.scss b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/process-designer.scss
new file mode 100644
index 0000000..bca0258
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/process-designer.scss
@@ -0,0 +1,159 @@
+@use 'bpmn-js-token-simulation/assets/css/bpmn-js-token-simulation.css';
+
+// 边框被 token-simulation 样式覆盖了
+.djs-palette {
+ background: var(--palette-background-color);
+ border: solid 1px var(--palette-border-color) !important;
+ border-radius: 2px;
+}
+
+.my-process-designer {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
+ .my-process-designer__header {
+ width: 100%;
+ min-height: 36px;
+ .el-button {
+ text-align: center;
+ }
+ .el-button-group {
+ margin: 4px;
+ }
+ .el-tooltip__popper {
+ .el-button {
+ width: 100%;
+ text-align: left;
+ padding-left: 8px;
+ padding-right: 8px;
+ }
+ .el-button:hover {
+ background: rgba(64, 158, 255, 0.8);
+ color: #ffffff;
+ }
+ }
+ .align {
+ position: relative;
+ i {
+ &:after {
+ content: '|';
+ position: absolute;
+ // transform: rotate(90deg) translate(200%, 60%);
+ transform: rotate(180deg) translate(271%, -10%);
+ }
+ }
+ }
+ .align.align-left i {
+ transform: rotate(90deg);
+ }
+ .align.align-right i {
+ transform: rotate(-90deg);
+ }
+ .align.align-top i {
+ transform: rotate(180deg);
+ }
+ .align.align-bottom i {
+ transform: rotate(0deg);
+ }
+ .align.align-center i {
+ transform: rotate(0deg);
+ &:after {
+ // transform: rotate(90deg) translate(0, 60%);
+ transform: rotate(0deg) translate(-0%, -5%);
+ }
+ }
+ .align.align-middle i {
+ transform: rotate(-90deg);
+ &:after {
+ // transform: rotate(90deg) translate(0, 60%);
+ transform: rotate(0deg) translate(0, -10%);
+ }
+ }
+ }
+ .my-process-designer__container {
+ display: inline-flex;
+ width: 100%;
+ flex: 1;
+ .my-process-designer__canvas {
+ flex: 1;
+ height: 100%;
+ position: relative;
+ background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+')
+ repeat !important;
+ div.toggle-mode {
+ display: none;
+ }
+ }
+ .my-process-designer__property-panel {
+ height: 100%;
+ overflow: scroll;
+ overflow-y: auto;
+ z-index: 10;
+ * {
+ box-sizing: border-box;
+ }
+ }
+ // svg {
+ // width: 100%;
+ // height: 100%;
+ // min-height: 100%;
+ // overflow: hidden;
+ // }
+ }
+}
+
+//侧边栏配置
+// .djs-palette .two-column .open {
+.open {
+ // .djs-palette.open {
+ .djs-palette-entries {
+ div[class^='bpmn-icon-']:before,
+ div[class*='bpmn-icon-']:before {
+ line-height: unset;
+ }
+ div.entry {
+ position: relative;
+ }
+ div.entry:hover {
+ &::after {
+ width: max-content;
+ content: attr(title);
+ vertical-align: text-bottom;
+ position: absolute;
+ right: -10px;
+ top: 0;
+ bottom: 0;
+ overflow: hidden;
+ transform: translateX(100%);
+ font-size: 0.5em;
+ display: inline-block;
+ text-decoration: inherit;
+ font-variant: normal;
+ text-transform: none;
+ background: #fafafa;
+ box-shadow: 0 0 6px #eeeeee;
+ border: 1px solid #cccccc;
+ box-sizing: border-box;
+ padding: 0 16px;
+ border-radius: 4px;
+ z-index: 100;
+ }
+ }
+ }
+}
+pre {
+ margin: 0;
+ height: 100%;
+ overflow: hidden;
+ max-height: calc(80vh - 32px);
+ overflow-y: auto;
+}
+.hljs {
+ word-break: break-word;
+ white-space: pre-wrap;
+}
+.hljs * {
+ font-family: Consolas, Monaco, monospace;
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/process-panel.scss b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/process-panel.scss
new file mode 100644
index 0000000..f840cdd
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/theme/process-panel.scss
@@ -0,0 +1,107 @@
+.process-panel__container {
+ box-sizing: border-box;
+ padding: 0 8px;
+ border-left: 1px solid #eeeeee;
+ box-shadow: 0 0 8px #cccccc;
+ max-height: 100%;
+ overflow-y: scroll;
+}
+.panel-tab__title {
+ font-weight: 600;
+ padding: 0 8px;
+ font-size: 1.1em;
+ line-height: 1.2em;
+ i {
+ margin-right: 8px;
+ font-size: 1.2em;
+ }
+}
+.panel-tab__content {
+ width: 100%;
+ box-sizing: border-box;
+ border-top: 1px solid #eeeeee;
+ padding: 8px 16px;
+ .panel-tab__content--title {
+ display: flex;
+ justify-content: space-between;
+ padding-bottom: 8px;
+ span {
+ flex: 1;
+ text-align: left;
+ }
+ }
+}
+.element-property {
+ width: 100%;
+ display: flex;
+ align-items: flex-start;
+ margin: 8px 0;
+ .element-property__label {
+ display: block;
+ width: 90px;
+ text-align: right;
+ overflow: hidden;
+ padding-right: 12px;
+ line-height: 32px;
+ font-size: 14px;
+ box-sizing: border-box;
+ }
+ .element-property__value {
+ flex: 1;
+ line-height: 32px;
+ }
+ .el-form-item {
+ width: 100%;
+ margin-bottom: 0;
+ padding-bottom: 18px;
+ }
+}
+.list-property {
+ flex-direction: column;
+ .element-listener-item {
+ width: 100%;
+ display: inline-grid;
+ grid-template-columns: 16px auto 32px 32px;
+ grid-column-gap: 8px;
+ }
+ .element-listener-item + .element-listener-item {
+ margin-top: 8px;
+ }
+}
+.listener-filed__title {
+ display: inline-flex;
+ width: 100%;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 0;
+ span {
+ width: 200px;
+ text-align: left;
+ font-size: 14px;
+ }
+ i {
+ margin-right: 8px;
+ }
+}
+.element-drawer__button {
+ margin-top: 8px;
+ width: 100%;
+ display: inline-flex;
+ justify-content: space-around;
+}
+.element-drawer__button > .el-button {
+ width: 100%;
+}
+
+.el-collapse-item__content {
+ padding-bottom: 0;
+}
+.el-input.is-disabled .el-input__inner {
+ color: #999999;
+}
+.el-form-item.el-form-item--mini {
+ margin-bottom: 0;
+ & + .el-form-item {
+ margin-top: 16px;
+ }
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/utils.ts b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/utils.ts
new file mode 100644
index 0000000..8996788
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/package/utils.ts
@@ -0,0 +1,78 @@
+import { toRaw } from 'vue'
+const bpmnInstances = () => (window as any)?.bpmnInstances
+// 创建监听器实例
+export function createListenerObject(options, isTask, prefix) {
+ debugger
+ const listenerObj = Object.create(null)
+ listenerObj.event = options.event
+ isTask && (listenerObj.id = options.id) // 任务监听器特有的 id 字段
+ switch (options.listenerType) {
+ case 'scriptListener':
+ listenerObj.script = createScriptObject(options, prefix)
+ break
+ case 'expressionListener':
+ listenerObj.expression = options.expression
+ break
+ case 'delegateExpressionListener':
+ listenerObj.delegateExpression = options.delegateExpression
+ break
+ default:
+ listenerObj.class = options.class
+ }
+ // 注入字段
+ if (options.fields) {
+ listenerObj.fields = options.fields.map((field) => {
+ return createFieldObject(field, prefix)
+ })
+ }
+ // 任务监听器的 定时器 设置
+ if (isTask && options.event === 'timeout' && !!options.eventDefinitionType) {
+ const timeDefinition = bpmnInstances().moddle.create('bpmn:FormalExpression', {
+ body: options.eventTimeDefinitions
+ })
+ const TimerEventDefinition = bpmnInstances().moddle.create('bpmn:TimerEventDefinition', {
+ id: `TimerEventDefinition_${uuid(8)}`,
+ [`time${options.eventDefinitionType.replace(/^\S/, (s) => s.toUpperCase())}`]: timeDefinition
+ })
+ listenerObj.eventDefinitions = [TimerEventDefinition]
+ }
+ return bpmnInstances().moddle.create(
+ `${prefix}:${isTask ? 'TaskListener' : 'ExecutionListener'}`,
+ listenerObj
+ )
+}
+
+// 创建 监听器的注入字段 实例
+export function createFieldObject(option, prefix) {
+ const { name, fieldType, string, expression } = option
+ const fieldConfig = fieldType === 'string' ? { name, string } : { name, expression }
+ return bpmnInstances().moddle.create(`${prefix}:Field`, fieldConfig)
+}
+
+// 创建脚本实例
+export function createScriptObject(options, prefix) {
+ const { scriptType, scriptFormat, value, resource } = options
+ const scriptConfig =
+ scriptType === 'inlineScript' ? { scriptFormat, value } : { scriptFormat, resource }
+ return bpmnInstances().moddle.create(`${prefix}:Script`, scriptConfig)
+}
+
+// 更新元素扩展属性
+export function updateElementExtensions(element, extensionList) {
+ const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
+ values: extensionList
+ })
+ bpmnInstances().modeling.updateProperties(toRaw(element), {
+ extensionElements: extensions
+ })
+}
+
+// 创建一个id
+export function uuid(length = 8, chars?) {
+ let result = ''
+ const charsString = chars || '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ for (let i = length; i > 0; --i) {
+ result += charsString[Math.floor(Math.random() * charsString.length)]
+ }
+ return result
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/highlight/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/highlight/index.js
new file mode 100644
index 0000000..5df38c9
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/highlight/index.js
@@ -0,0 +1,5 @@
+const hljs = require('highlight.js/lib/core')
+hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml'))
+hljs.registerLanguage('json', require('highlight.js/lib/languages/json'))
+
+module.exports = hljs
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js
new file mode 100644
index 0000000..e876031
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js
@@ -0,0 +1,14 @@
+import BpmnRenderer from 'bpmn-js/lib/draw/BpmnRenderer'
+
+export default function CustomRenderer(config, eventBus, styles, pathMap, canvas, textRenderer) {
+ BpmnRenderer.call(this, config, eventBus, styles, pathMap, canvas, textRenderer, 2000)
+
+ this.handlers['label'] = function () {
+ return null
+ }
+}
+
+const F = function () {} // 核心,利用空对象作为中介;
+F.prototype = BpmnRenderer.prototype // 核心,将父类的原型赋值给空对象F;
+CustomRenderer.prototype = new F() // 核心,将 F的实例赋值给子类;
+CustomRenderer.prototype.constructor = CustomRenderer // 修复子类CustomRenderer的构造器指向,防止原型链的混乱;
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js
new file mode 100644
index 0000000..79d8bd0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js
@@ -0,0 +1,6 @@
+import CustomRenderer from './CustomRenderer'
+
+export default {
+ __init__: ['customRenderer'],
+ customRenderer: ['type', CustomRenderer]
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js
new file mode 100644
index 0000000..9fa1d14
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js
@@ -0,0 +1,16 @@
+import BpmnRules from 'bpmn-js/lib/features/rules/BpmnRules'
+import inherits from 'inherits'
+
+export default function CustomRules(eventBus) {
+ BpmnRules.call(this, eventBus)
+}
+
+inherits(CustomRules, BpmnRules)
+
+CustomRules.prototype.canDrop = function () {
+ return false
+}
+
+CustomRules.prototype.canMove = function () {
+ return false
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/rules/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/rules/index.js
new file mode 100644
index 0000000..12cf05a
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/modules/rules/index.js
@@ -0,0 +1,6 @@
+import CustomRules from './CustomRules'
+
+export default {
+ __init__: ['customRules'],
+ customRules: ['type', CustomRules]
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/translations.ts b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/translations.ts
new file mode 100644
index 0000000..5f9b9a5
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/translations.ts
@@ -0,0 +1,25 @@
+/**
+ * This is a sample file that should be replaced with the actual translation.
+ *
+ * Checkout https://github.com/bpmn-io/bpmn-js-i18n for a list of available
+ * translations and labels to translate.
+ */
+export default {
+ 'Exclusive Gateway': 'Exklusives Gateway',
+ 'Parallel Gateway': 'Paralleles Gateway',
+ 'Inclusive Gateway': 'Inklusives Gateway',
+ 'Complex Gateway': 'Komplexes Gateway',
+ 'Event based Gateway': 'Ereignis-basiertes Gateway',
+ 'Message Start Event': '消息启动事件',
+ 'Timer Start Event': '定时启动事件',
+ 'Conditional Start Event': '条件启动事件',
+ 'Signal Start Event': '信号启动事件',
+ 'Error Start Event': '错误启动事件',
+ 'Escalation Start Event': '升级启动事件',
+ 'Compensation Start Event': '补偿启动事件',
+ 'Message Start Event (non-interrupting)': '消息启动事件 (非中断)',
+ 'Timer Start Event (non-interrupting)': '定时启动事件 (非中断)',
+ 'Conditional Start Event (non-interrupting)': '条件启动事件 (非中断)',
+ 'Signal Start Event (non-interrupting)': '信号启动事件 (非中断)',
+ 'Escalation Start Event (non-interrupting)': '升级启动事件 (非中断)'
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js
new file mode 100644
index 0000000..bb71d44
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js
@@ -0,0 +1,39 @@
+//outside.js
+
+const ctx = '@@clickoutsideContext'
+
+export default {
+ bind(el, binding, vnode) {
+ const ele = el
+ const documentHandler = (e) => {
+ if (!vnode.context || ele.contains(e.target)) {
+ return false
+ }
+ // 调用指令回调
+ if (binding.expression) {
+ vnode.context[el[ctx].methodName](e)
+ } else {
+ el[ctx].bindingFn(e)
+ }
+ }
+ // 将方法添加到ele
+ ele[ctx] = {
+ documentHandler,
+ methodName: binding.expression,
+ bindingFn: binding.value
+ }
+
+ setTimeout(() => {
+ document.addEventListener('touchstart', documentHandler) // 为document绑定事件
+ })
+ },
+ update(el, binding) {
+ const ele = el
+ ele[ctx].methodName = binding.expression
+ ele[ctx].bindingFn = binding.value
+ },
+ unbind(el) {
+ document.removeEventListener('touchstart', el[ctx].documentHandler) // 解绑
+ delete el[ctx]
+ }
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/index.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/index.js
new file mode 100644
index 0000000..7d970ec
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/index.js
@@ -0,0 +1,10 @@
+export function debounce(fn, delay = 500) {
+ let timer
+ return function (...args) {
+ if (timer) {
+ clearTimeout(timer)
+ timer = null
+ }
+ timer = setTimeout(fn.bind(this, ...args), delay)
+ }
+}
diff --git a/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/xml2json.js b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/xml2json.js
new file mode 100644
index 0000000..fe1a52f
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/bpmnProcessDesigner/src/utils/xml2json.js
@@ -0,0 +1,50 @@
+function xmlStr2XmlObj(xmlStr) {
+ let xmlObj = {}
+ if (document.all) {
+ const xmlDom = new window.ActiveXObject('Microsoft.XMLDOM')
+ xmlDom.loadXML(xmlStr)
+ xmlObj = xmlDom
+ } else {
+ xmlObj = new DOMParser().parseFromString(xmlStr, 'text/xml')
+ }
+ return xmlObj
+}
+
+function xml2json(xml) {
+ try {
+ let obj = {}
+ if (xml.children.length > 0) {
+ for (let i = 0; i < xml.children.length; i++) {
+ const item = xml.children.item(i)
+ const nodeName = item.nodeName
+ if (typeof obj[nodeName] == 'undefined') {
+ obj[nodeName] = xml2json(item)
+ } else {
+ if (typeof obj[nodeName].push == 'undefined') {
+ const old = obj[nodeName]
+ obj[nodeName] = []
+ obj[nodeName].push(old)
+ }
+ obj[nodeName].push(xml2json(item))
+ }
+ }
+ } else {
+ obj = xml.textContent
+ }
+ return obj
+ } catch (e) {
+ console.log(e.message)
+ }
+}
+
+function xmlObj2json(xml) {
+ const xmlObj = xmlStr2XmlObj(xml)
+ console.log(xmlObj)
+ let jsonObj = {}
+ if (xmlObj.childNodes.length > 0) {
+ jsonObj = xml2json(xmlObj)
+ }
+ return jsonObj
+}
+
+export default xmlObj2json
diff --git a/marketing-ui/admin-ui/src/components/index.ts b/marketing-ui/admin-ui/src/components/index.ts
new file mode 100644
index 0000000..4d030c3
--- /dev/null
+++ b/marketing-ui/admin-ui/src/components/index.ts
@@ -0,0 +1,6 @@
+import type { App } from 'vue'
+import { Icon } from './Icon'
+
+export const setupGlobCom = (app: App): void => {
+ app.component('Icon', Icon)
+}
diff --git a/marketing-ui/admin-ui/src/config/axios/config.ts b/marketing-ui/admin-ui/src/config/axios/config.ts
new file mode 100644
index 0000000..8116508
--- /dev/null
+++ b/marketing-ui/admin-ui/src/config/axios/config.ts
@@ -0,0 +1,28 @@
+const config: {
+ base_url: string
+ result_code: number | string
+ default_headers: AxiosHeaders
+ request_timeout: number
+} = {
+ /**
+ * api请求基础路径
+ */
+ base_url: import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL,
+ /**
+ * 接口成功返回状态码
+ */
+ result_code: 200,
+
+ /**
+ * 接口请求超时时间
+ */
+ request_timeout: 30000,
+
+ /**
+ * 默认接口请求类型
+ * 可选值:application/x-www-form-urlencoded multipart/form-data
+ */
+ default_headers: 'application/json'
+}
+
+export { config }
diff --git a/marketing-ui/admin-ui/src/config/axios/errorCode.ts b/marketing-ui/admin-ui/src/config/axios/errorCode.ts
new file mode 100644
index 0000000..94d719f
--- /dev/null
+++ b/marketing-ui/admin-ui/src/config/axios/errorCode.ts
@@ -0,0 +1,6 @@
+export default {
+ '401': '认证失败,无法访问系统资源',
+ '403': '当前操作没有权限',
+ '404': '访问资源不存在',
+ default: '系统未知错误,请反馈给管理员'
+}
diff --git a/marketing-ui/admin-ui/src/config/axios/index.ts b/marketing-ui/admin-ui/src/config/axios/index.ts
new file mode 100644
index 0000000..07719a2
--- /dev/null
+++ b/marketing-ui/admin-ui/src/config/axios/index.ts
@@ -0,0 +1,47 @@
+import { service } from './service'
+
+import { config } from './config'
+
+const { default_headers } = config
+
+const request = (option: any) => {
+ const { headersType, headers, ...otherOption } = option
+ return service({
+ ...otherOption,
+ headers: {
+ 'Content-Type': headersType || default_headers,
+ ...headers
+ }
+ })
+}
+export default {
+ get: async (option: any) => {
+ const res = await request({ method: 'GET', ...option })
+ return res.data as unknown as T
+ },
+ post: async (option: any) => {
+ const res = await request({ method: 'POST', ...option })
+ return res.data as unknown as T
+ },
+ postOriginal: async (option: any) => {
+ const res = await request({ method: 'POST', ...option })
+ return res
+ },
+ delete: async (option: any) => {
+ const res = await request({ method: 'DELETE', ...option })
+ return res.data as unknown as T
+ },
+ put: async (option: any) => {
+ const res = await request({ method: 'PUT', ...option })
+ return res.data as unknown as T
+ },
+ download: async (option: any) => {
+ const res = await request({ method: 'GET', responseType: 'blob', ...option })
+ return res as unknown as Promise
+ },
+ upload: async (option: any) => {
+ option.headersType = 'multipart/form-data'
+ const res = await request({ method: 'POST', ...option })
+ return res as unknown as Promise
+ }
+}
diff --git a/marketing-ui/admin-ui/src/config/axios/service.ts b/marketing-ui/admin-ui/src/config/axios/service.ts
new file mode 100644
index 0000000..bf234da
--- /dev/null
+++ b/marketing-ui/admin-ui/src/config/axios/service.ts
@@ -0,0 +1,219 @@
+import axios, { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
+
+import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
+import qs from 'qs'
+import { config } from '@/config/axios/config'
+import { getAccessToken, getRefreshToken, removeToken, setToken } from '@/utils/auth'
+import errorCode from './errorCode'
+
+import { resetRouter } from '@/router'
+import { deleteUserCache } from '@/hooks/web/useCache'
+
+const { result_code, base_url, request_timeout } = config
+
+// 需要忽略的提示。忽略后,自动 Promise.reject('error')
+const ignoreMsgs = [
+ '无效的刷新令牌', // 刷新令牌被删除时,不用提示
+ '刷新令牌已过期' // 使用刷新令牌,刷新获取新的访问令牌时,结果因为过期失败,此时需要忽略。否则,会导致继续 401,无法跳转到登出界面
+]
+// 是否显示重新登录
+export const isRelogin = { show: false }
+// Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现
+// 请求队列
+let requestList: any[] = []
+// 是否正在刷新中
+let isRefreshToken = false
+// 请求白名单,无须token的接口
+const whiteList: string[] = ['/login', '/refresh-token']
+
+// 创建axios实例
+const service: AxiosInstance = axios.create({
+ baseURL: base_url, // api 的 base_url
+ timeout: request_timeout, // 请求超时时间
+ withCredentials: false, // 禁用 Cookie 等信息
+ // 自定义参数序列化函数
+ paramsSerializer: (params) => {
+ return qs.stringify(params, { allowDots: true })
+ }
+})
+
+// request拦截器
+service.interceptors.request.use(
+ (config: InternalAxiosRequestConfig) => {
+ // 是否需要设置 token
+ let isToken = (config!.headers || {}).isToken === false
+ whiteList.some((v) => {
+ if (config.url && config.url.indexOf(v) > -1) {
+ return (isToken = false)
+ }
+ })
+ if (getAccessToken() && !isToken) {
+ config.headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token
+ }
+
+ const method = config.method?.toUpperCase()
+ // 防止 GET 请求缓存
+ if (method === 'GET') {
+ config.headers['Cache-Control'] = 'no-cache'
+ config.headers['Pragma'] = 'no-cache'
+ }
+ // 自定义参数序列化函数
+ else if (method === 'POST') {
+ const contentType = config.headers['Content-Type'] || config.headers['content-type']
+ if (contentType === 'application/x-www-form-urlencoded') {
+ if (config.data && typeof config.data !== 'string') {
+ config.data = qs.stringify(config.data)
+ }
+ }
+ }
+ return config
+ },
+ (error: AxiosError) => {
+ // Do something with request error
+ console.log(error) // for debug
+ return Promise.reject(error)
+ }
+)
+
+// response 拦截器
+service.interceptors.response.use(
+ async (response: AxiosResponse) => {
+ let { data } = response
+ const config = response.config
+ if (!data) {
+ // 返回“[HTTP]请求没有返回值”;
+ throw new Error()
+ }
+ const { t } = useI18n()
+ // 未设置状态码则默认成功状态
+ // 二进制数据则直接返回,例如说 Excel 导出
+ if (
+ response.request.responseType === 'blob' ||
+ response.request.responseType === 'arraybuffer'
+ ) {
+ // 注意:如果导出的响应为 json,说明可能失败了,不直接返回进行下载
+ if (response.data.type !== 'application/json') {
+ return response.data
+ }
+ data = await new Response(response.data).json()
+ }
+ const code = data.code || result_code
+ // 获取错误信息
+ const msg = data.msg || errorCode[code] || errorCode['default']
+ if (ignoreMsgs.indexOf(msg) !== -1) {
+ // 如果是忽略的错误码,直接返回 msg 异常
+ return Promise.reject(msg)
+ } else if (code === 401) {
+ // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
+ if (!isRefreshToken) {
+ isRefreshToken = true
+ // 1. 如果获取不到刷新令牌,则只能执行登出操作
+ if (!getRefreshToken()) {
+ return handleAuthorized()
+ }
+ // 2. 进行刷新访问令牌
+ try {
+ const refreshTokenRes = await refreshToken()
+ // 2.1 刷新成功,则回放队列的请求 + 当前请求
+ setToken((await refreshTokenRes).data.data)
+ config.headers!.Authorization = 'Bearer ' + getAccessToken()
+ requestList.forEach((cb: any) => {
+ cb()
+ })
+ requestList = []
+ return service(config)
+ } catch (e) {
+ // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
+ // 2.2 刷新失败,只回放队列的请求
+ requestList.forEach((cb: any) => {
+ cb()
+ })
+ // 提示是否要登出。即不回放当前请求!不然会形成递归
+ return handleAuthorized()
+ } finally {
+ requestList = []
+ isRefreshToken = false
+ }
+ } else {
+ // 添加到队列,等待刷新获取到新的令牌
+ return new Promise((resolve) => {
+ requestList.push(() => {
+ config.headers!.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
+ resolve(service(config))
+ })
+ })
+ }
+ } else if (code === 500) {
+ ElMessage.error(t('sys.api.errMsg500'))
+ return Promise.reject(new Error(msg))
+ } else if (code === 901) {
+ ElMessage.error({
+ offset: 300,
+ dangerouslyUseHTMLString: true,
+ message:
+ '' +
+ t('sys.api.errMsg901') +
+ '
' +
+ '
' +
+ '5 分钟搭建本地环境
'
+ })
+ return Promise.reject(new Error(msg))
+ } else if (code !== 200) {
+ if (msg === '无效的刷新令牌') {
+ // hard coding:忽略这个提示,直接登出
+ console.log(msg)
+ return handleAuthorized()
+ } else {
+ ElNotification.error({ title: msg })
+ }
+ return Promise.reject('error')
+ } else {
+ return data
+ }
+ },
+ (error: AxiosError) => {
+ console.log('err' + error) // for debug
+ let { message } = error
+ const { t } = useI18n()
+ if (message === 'Network Error') {
+ message = t('sys.api.errorMessage')
+ } else if (message.includes('timeout')) {
+ message = t('sys.api.apiTimeoutMessage')
+ } else if (message.includes('Request failed with status code')) {
+ message = t('sys.api.apiRequestFailed') + message.substr(message.length - 3)
+ }
+ ElMessage.error(message)
+ return Promise.reject(error)
+ }
+)
+
+const refreshToken = async () => {
+ return await axios.post(base_url + '/system/auth/refresh-token?refreshToken=' + getRefreshToken())
+}
+const handleAuthorized = () => {
+ const { t } = useI18n()
+ if (!isRelogin.show) {
+ // 如果已经到登录页面则不进行弹窗提示
+ if (window.location.href.includes('login')) {
+ return
+ }
+ isRelogin.show = true
+ ElMessageBox.confirm(t('sys.api.timeoutMessage'), t('common.confirmTitle'), {
+ showCancelButton: false,
+ closeOnClickModal: false,
+ showClose: false,
+ closeOnPressEscape: false,
+ confirmButtonText: t('login.relogin'),
+ type: 'warning'
+ }).then(() => {
+ resetRouter() // 重置静态路由表
+ deleteUserCache() // 删除用户缓存
+ removeToken()
+ isRelogin.show = false
+ // 干掉token后再走一次路由让它过router.beforeEach的校验
+ window.location.href = window.location.href
+ })
+ }
+ return Promise.reject(t('sys.api.timeoutMessage'))
+}
+export { service }
diff --git a/marketing-ui/admin-ui/src/directives/index.ts b/marketing-ui/admin-ui/src/directives/index.ts
new file mode 100644
index 0000000..1b99988
--- /dev/null
+++ b/marketing-ui/admin-ui/src/directives/index.ts
@@ -0,0 +1,24 @@
+import type { App } from 'vue'
+import { hasRole } from './permission/hasRole'
+import { hasPermi } from './permission/hasPermi'
+
+/**
+ * 导出指令:v-xxx
+ * @methods hasRole 用户权限,用法: v-hasRole
+ * @methods hasPermi 按钮权限,用法: v-hasPermi
+ */
+export const setupAuth = (app: App) => {
+ hasRole(app)
+ hasPermi(app)
+}
+
+/**
+ * 导出指令:v-mountedFocus
+ */
+export const setupMountedFocus = (app: App) => {
+ app.directive('mountedFocus', {
+ mounted(el) {
+ el.focus()
+ }
+ })
+}
diff --git a/marketing-ui/admin-ui/src/directives/permission/hasPermi.ts b/marketing-ui/admin-ui/src/directives/permission/hasPermi.ts
new file mode 100644
index 0000000..90cd025
--- /dev/null
+++ b/marketing-ui/admin-ui/src/directives/permission/hasPermi.ts
@@ -0,0 +1,31 @@
+import type { App } from 'vue'
+import { useUserStore } from '@/store/modules/user'
+
+const { t } = useI18n() // 国际化
+
+/** 判断权限的指令 directive */
+export function hasPermi(app: App) {
+ app.directive('hasPermi', (el, binding) => {
+ const { value } = binding
+
+ if (value && value instanceof Array && value.length > 0) {
+ const hasPermissions = hasPermission(value)
+
+ if (!hasPermissions) {
+ el.parentNode && el.parentNode.removeChild(el)
+ }
+ } else {
+ throw new Error(t('permission.hasPermission'))
+ }
+ })
+}
+
+/** 判断权限的方法 function */
+const userStore = useUserStore()
+const all_permission = '*:*:*'
+export const hasPermission = (permission: string[]) => {
+ return (
+ userStore.permissions.has(all_permission) ||
+ permission.some((permission) => userStore.permissions.has(permission))
+ )
+}
diff --git a/marketing-ui/admin-ui/src/directives/permission/hasRole.ts b/marketing-ui/admin-ui/src/directives/permission/hasRole.ts
new file mode 100644
index 0000000..a512811
--- /dev/null
+++ b/marketing-ui/admin-ui/src/directives/permission/hasRole.ts
@@ -0,0 +1,28 @@
+import type { App } from 'vue'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+
+const { t } = useI18n() // 国际化
+
+export function hasRole(app: App) {
+ app.directive('hasRole', (el, binding) => {
+ const { wsCache } = useCache()
+ const { value } = binding
+ const super_admin = 'super_admin'
+ const userInfo = wsCache.get(CACHE_KEY.USER)
+ const roles = userInfo?.roles || []
+
+ if (value && value instanceof Array && value.length > 0) {
+ const roleFlag = value
+
+ const hasRole = roles.some((role: string) => {
+ return super_admin === role || roleFlag.includes(role)
+ })
+
+ if (!hasRole) {
+ el.parentNode && el.parentNode.removeChild(el)
+ }
+ } else {
+ throw new Error(t('permission.hasRole'))
+ }
+ })
+}
diff --git a/marketing-ui/admin-ui/src/hooks/event/useScrollTo.ts b/marketing-ui/admin-ui/src/hooks/event/useScrollTo.ts
new file mode 100644
index 0000000..92aec87
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/event/useScrollTo.ts
@@ -0,0 +1,60 @@
+export interface ScrollToParams {
+ el: HTMLElement
+ to: number
+ position: string
+ duration?: number
+ callback?: () => void
+}
+
+const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
+ t /= d / 2
+ if (t < 1) {
+ return (c / 2) * t * t + b
+ }
+ t--
+ return (-c / 2) * (t * (t - 2) - 1) + b
+}
+const move = (el: HTMLElement, position: string, amount: number) => {
+ el[position] = amount
+}
+
+export function useScrollTo({
+ el,
+ position = 'scrollLeft',
+ to,
+ duration = 500,
+ callback
+}: ScrollToParams) {
+ const isActiveRef = ref(false)
+ const start = el[position]
+ const change = to - start
+ const increment = 20
+ let currentTime = 0
+
+ function animateScroll() {
+ if (!unref(isActiveRef)) {
+ return
+ }
+ currentTime += increment
+ const val = easeInOutQuad(currentTime, start, change, duration)
+ move(el, position, val)
+ if (currentTime < duration && unref(isActiveRef)) {
+ requestAnimationFrame(animateScroll)
+ } else {
+ if (callback) {
+ callback()
+ }
+ }
+ }
+
+ function run() {
+ isActiveRef.value = true
+ animateScroll()
+ }
+
+ function stop() {
+ isActiveRef.value = false
+ }
+
+ return { start: run, stop }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useCache.ts b/marketing-ui/admin-ui/src/hooks/web/useCache.ts
new file mode 100644
index 0000000..cc1207b
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useCache.ts
@@ -0,0 +1,38 @@
+/**
+ * 配置浏览器本地存储的方式,可直接存储对象数组。
+ */
+
+import WebStorageCache from 'web-storage-cache'
+
+type CacheType = 'localStorage' | 'sessionStorage'
+
+export const CACHE_KEY = {
+ // 用户相关
+ ROLE_ROUTERS: 'roleRouters',
+ USER: 'user',
+ // 系统设置
+ IS_DARK: 'isDark',
+ LANG: 'lang',
+ THEME: 'theme',
+ LAYOUT: 'layout',
+ DICT_CACHE: 'dictCache',
+ // 登录表单
+ LoginForm: 'loginForm'
+}
+
+export const useCache = (type: CacheType = 'localStorage') => {
+ const wsCache: WebStorageCache = new WebStorageCache({
+ storage: type
+ })
+
+ return {
+ wsCache
+ }
+}
+
+export const deleteUserCache = () => {
+ const { wsCache } = useCache()
+ wsCache.delete(CACHE_KEY.USER)
+ wsCache.delete(CACHE_KEY.ROLE_ROUTERS)
+ // 注意,不要清理 LoginForm 登录表单
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useConfigGlobal.ts b/marketing-ui/admin-ui/src/hooks/web/useConfigGlobal.ts
new file mode 100644
index 0000000..afb3db3
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useConfigGlobal.ts
@@ -0,0 +1,9 @@
+import { ConfigGlobalTypes } from '@/types/configGlobal'
+
+export const useConfigGlobal = () => {
+ const configGlobal = inject('configGlobal', {}) as ConfigGlobalTypes
+
+ return {
+ configGlobal
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useCrudSchemas.ts b/marketing-ui/admin-ui/src/hooks/web/useCrudSchemas.ts
new file mode 100644
index 0000000..458b57e
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useCrudSchemas.ts
@@ -0,0 +1,326 @@
+import { reactive } from 'vue'
+import { AxiosPromise } from 'axios'
+import { findIndex } from '@/utils'
+import { eachTree, filter, treeMap } from '@/utils/tree'
+import { getBoolDictOptions, getDictOptions, getIntDictOptions } from '@/utils/dict'
+
+import { FormSchema } from '@/types/form'
+import { TableColumn } from '@/types/table'
+import { DescriptionsSchema } from '@/types/descriptions'
+import { ComponentOptions, ComponentProps } from '@/types/components'
+import { DictTag } from '@/components/DictTag'
+import { cloneDeep, merge } from 'lodash-es'
+
+export type CrudSchema = Omit & {
+ isSearch?: boolean // 是否在查询显示
+ search?: CrudSearchParams // 查询的详细配置
+ isTable?: boolean // 是否在列表显示
+ table?: CrudTableParams // 列表的详细配置
+ isForm?: boolean // 是否在表单显示
+ form?: CrudFormParams // 表单的详细配置
+ isDetail?: boolean // 是否在详情显示
+ detail?: CrudDescriptionsParams // 详情的详细配置
+ children?: CrudSchema[]
+ dictType?: string // 字典类型
+ dictClass?: 'string' | 'number' | 'boolean' // 字典数据类型 string | number | boolean
+}
+
+type CrudSearchParams = {
+ // 是否显示在查询项
+ show?: boolean
+ // 接口
+ api?: () => Promise
+ // 搜索字段
+ field?: string
+} & Omit
+
+type CrudTableParams = {
+ // 是否显示表头
+ show?: boolean
+ // 列宽配置
+ width?: number | string
+ // 列是否固定在左侧或者右侧
+ fixed?: 'left' | 'right'
+} & Omit
+type CrudFormParams = {
+ // 是否显示表单项
+ show?: boolean
+ // 接口
+ api?: () => Promise
+} & Omit
+
+type CrudDescriptionsParams = {
+ // 是否显示表单项
+ show?: boolean
+} & Omit
+
+interface AllSchemas {
+ searchSchema: FormSchema[]
+ tableColumns: TableColumn[]
+ formSchema: FormSchema[]
+ detailSchema: DescriptionsSchema[]
+}
+
+const { t } = useI18n()
+
+// 过滤所有结构
+export const useCrudSchemas = (
+ crudSchema: CrudSchema[]
+): {
+ allSchemas: AllSchemas
+} => {
+ // 所有结构数据
+ const allSchemas = reactive({
+ searchSchema: [],
+ tableColumns: [],
+ formSchema: [],
+ detailSchema: []
+ })
+
+ const searchSchema = filterSearchSchema(crudSchema, allSchemas)
+ allSchemas.searchSchema = searchSchema || []
+
+ const tableColumns = filterTableSchema(crudSchema)
+ allSchemas.tableColumns = tableColumns || []
+
+ const formSchema = filterFormSchema(crudSchema, allSchemas)
+ allSchemas.formSchema = formSchema
+
+ const detailSchema = filterDescriptionsSchema(crudSchema)
+ allSchemas.detailSchema = detailSchema
+
+ return {
+ allSchemas
+ }
+}
+
+// 过滤 Search 结构
+const filterSearchSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => {
+ const searchSchema: FormSchema[] = []
+
+ // 获取字典列表队列
+ const searchRequestTask: Array<() => Promise> = []
+ eachTree(crudSchema, (schemaItem: CrudSchema) => {
+ // 判断是否显示
+ if (schemaItem?.isSearch || schemaItem.search?.show) {
+ let component = schemaItem?.search?.component || 'Input'
+ const options: ComponentOptions[] = []
+ let comonentProps: ComponentProps = {}
+ if (schemaItem.dictType) {
+ const allOptions: ComponentOptions = { label: '全部', value: '' }
+ options.push(allOptions)
+ getDictOptions(schemaItem.dictType).forEach((dict) => {
+ options.push(dict)
+ })
+ comonentProps = {
+ options: options
+ }
+ if (!schemaItem.search?.component) component = 'Select'
+ }
+
+ // updated by AKing: 解决了当使用默认的dict选项时,form中事件不能触发的问题
+ const searchSchemaItem = merge(
+ {
+ // 默认为 input
+ component,
+ ...schemaItem.search,
+ field: schemaItem.field,
+ label: schemaItem.search?.label || schemaItem.label
+ },
+ { componentProps: comonentProps }
+ )
+ if (searchSchemaItem.api) {
+ searchRequestTask.push(async () => {
+ const res = await (searchSchemaItem.api as () => AxiosPromise)()
+ if (res) {
+ const index = findIndex(allSchemas.searchSchema, (v: FormSchema) => {
+ return v.field === searchSchemaItem.field
+ })
+ if (index !== -1) {
+ allSchemas.searchSchema[index]!.componentProps!.options = filterOptions(
+ res,
+ searchSchemaItem.componentProps.optionsAlias?.labelField
+ )
+ }
+ }
+ })
+ }
+ // 删除不必要的字段
+ delete searchSchemaItem.show
+
+ searchSchema.push(searchSchemaItem)
+ }
+ })
+ for (const task of searchRequestTask) {
+ task()
+ }
+ return searchSchema
+}
+
+// 过滤 table 结构
+const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => {
+ const tableColumns = treeMap(crudSchema, {
+ conversion: (schema: CrudSchema) => {
+ if (schema?.isTable !== false && schema?.table?.show !== false) {
+ // add by 芋艿:增加对 dict 字典数据的支持
+ if (!schema.formatter && schema.dictType) {
+ schema.formatter = (_: Recordable, __: TableColumn, cellValue: any) => {
+ return h(DictTag, {
+ type: schema.dictType!, // ! 表示一定不为空
+ value: cellValue
+ })
+ }
+ }
+ return {
+ ...schema.table,
+ ...schema
+ }
+ }
+ }
+ })
+
+ // 第一次过滤会有 undefined 所以需要二次过滤
+ return filter(tableColumns as TableColumn[], (data) => {
+ if (data.children === void 0) {
+ delete data.children
+ }
+ return !!data.field
+ })
+}
+
+// 过滤 form 结构
+const filterFormSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => {
+ const formSchema: FormSchema[] = []
+
+ // 获取字典列表队列
+ const formRequestTask: Array<() => Promise> = []
+
+ eachTree(crudSchema, (schemaItem: CrudSchema) => {
+ // 判断是否显示
+ if (schemaItem?.isForm !== false && schemaItem?.form?.show !== false) {
+ let component = schemaItem?.form?.component || 'Input'
+ let defaultValue: any = ''
+ if (schemaItem.form?.value) {
+ defaultValue = schemaItem.form?.value
+ } else {
+ if (component === 'InputNumber') {
+ defaultValue = 0
+ }
+ }
+ let comonentProps: ComponentProps = {}
+ if (schemaItem.dictType) {
+ const options: ComponentOptions[] = []
+ if (schemaItem.dictClass && schemaItem.dictClass === 'number') {
+ getIntDictOptions(schemaItem.dictType).forEach((dict) => {
+ options.push(dict)
+ })
+ } else if (schemaItem.dictClass && schemaItem.dictClass === 'boolean') {
+ getBoolDictOptions(schemaItem.dictType).forEach((dict) => {
+ options.push(dict)
+ })
+ } else {
+ getDictOptions(schemaItem.dictType).forEach((dict) => {
+ options.push(dict)
+ })
+ }
+ comonentProps = {
+ options: options
+ }
+ if (!(schemaItem.form && schemaItem.form.component)) component = 'Select'
+ }
+
+ // updated by AKing: 解决了当使用默认的dict选项时,form中事件不能触发的问题
+ const formSchemaItem = merge(
+ {
+ // 默认为 input
+ component,
+ value: defaultValue,
+ ...schemaItem.form,
+ field: schemaItem.field,
+ label: schemaItem.form?.label || schemaItem.label
+ },
+ { componentProps: comonentProps }
+ )
+
+ if (formSchemaItem.api) {
+ formRequestTask.push(async () => {
+ const res = await (formSchemaItem.api as () => AxiosPromise)()
+ if (res) {
+ const index = findIndex(allSchemas.formSchema, (v: FormSchema) => {
+ return v.field === formSchemaItem.field
+ })
+ if (index !== -1) {
+ allSchemas.formSchema[index]!.componentProps!.options = filterOptions(
+ res,
+ formSchemaItem.componentProps.optionsAlias?.labelField
+ )
+ }
+ }
+ })
+ }
+
+ // 删除不必要的字段
+ delete formSchemaItem.show
+
+ formSchema.push(formSchemaItem)
+ }
+ })
+
+ for (const task of formRequestTask) {
+ task()
+ }
+ return formSchema
+}
+
+// 过滤 descriptions 结构
+const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[] => {
+ const descriptionsSchema: FormSchema[] = []
+
+ eachTree(crudSchema, (schemaItem: CrudSchema) => {
+ // 判断是否显示
+ if (schemaItem?.isDetail !== false && schemaItem.detail?.show !== false) {
+ const descriptionsSchemaItem = {
+ ...schemaItem.detail,
+ field: schemaItem.field,
+ label: schemaItem.detail?.label || schemaItem.label
+ }
+ if (schemaItem.dictType) {
+ descriptionsSchemaItem.dictType = schemaItem.dictType
+ }
+ if (schemaItem.detail?.dateFormat || schemaItem.formatter == 'formatDate') {
+ // 优先使用 detail 下的配置,如果没有默认为 YYYY-MM-DD HH:mm:ss
+ descriptionsSchemaItem.dateFormat = schemaItem?.detail?.dateFormat
+ ? schemaItem?.detail?.dateFormat
+ : 'YYYY-MM-DD HH:mm:ss'
+ }
+
+ // 删除不必要的字段
+ delete descriptionsSchemaItem.show
+
+ descriptionsSchema.push(descriptionsSchemaItem)
+ }
+ })
+
+ return descriptionsSchema
+}
+
+// 给options添加国际化
+const filterOptions = (options: Recordable, labelField?: string) => {
+ return options?.map((v: Recordable) => {
+ if (labelField) {
+ v['labelField'] = t(v.labelField)
+ } else {
+ v['label'] = t(v.label)
+ }
+ return v
+ })
+}
+
+// 将 tableColumns 指定 fields 放到最前面
+export const sortTableColumns = (tableColumns: TableColumn[], field: string) => {
+ const fieldIndex = tableColumns.findIndex((item) => item.field === field)
+ const fieldColumn = cloneDeep(tableColumns[fieldIndex])
+ tableColumns.splice(fieldIndex, 1)
+ // 添加到开头
+ tableColumns.unshift(fieldColumn)
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useDesign.ts b/marketing-ui/admin-ui/src/hooks/web/useDesign.ts
new file mode 100644
index 0000000..8ee3b38
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useDesign.ts
@@ -0,0 +1,18 @@
+import variables from '@/styles/global.module.scss'
+
+export const useDesign = () => {
+ const scssVariables = variables
+
+ /**
+ * @param scope 类名
+ * @returns 返回空间名-类名
+ */
+ const getPrefixCls = (scope: string) => {
+ return `${scssVariables.namespace}-${scope}`
+ }
+
+ return {
+ variables: scssVariables,
+ getPrefixCls
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useEmitt.ts b/marketing-ui/admin-ui/src/hooks/web/useEmitt.ts
new file mode 100644
index 0000000..d4efea7
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useEmitt.ts
@@ -0,0 +1,22 @@
+import mitt from 'mitt'
+
+interface Option {
+ name: string // 事件名称
+ callback: Fn // 回调
+}
+
+const emitter = mitt()
+
+export const useEmitt = (option?: Option) => {
+ if (option) {
+ emitter.on(option.name, option.callback)
+
+ onBeforeUnmount(() => {
+ emitter.off(option.name)
+ })
+ }
+
+ return {
+ emitter
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useForm.ts b/marketing-ui/admin-ui/src/hooks/web/useForm.ts
new file mode 100644
index 0000000..53a8a94
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useForm.ts
@@ -0,0 +1,94 @@
+import type { Form, FormExpose } from '@/components/Form'
+import type { ElForm } from 'element-plus'
+import type { FormProps } from '@/components/Form/src/types'
+import { FormSchema, FormSetPropsType } from '@/types/form'
+
+export const useForm = (props?: FormProps) => {
+ // From实例
+ const formRef = ref()
+
+ // ElForm实例
+ const elFormRef = ref>()
+
+ /**
+ * @param ref Form实例
+ * @param elRef ElForm实例
+ */
+ const register = (ref: typeof Form & FormExpose, elRef: ComponentRef) => {
+ formRef.value = ref
+ elFormRef.value = elRef
+ }
+
+ const getForm = async () => {
+ await nextTick()
+ const form = unref(formRef)
+ if (!form) {
+ console.error('The form is not registered. Please use the register method to register')
+ }
+ return form
+ }
+
+ // 一些内置的方法
+ const methods: {
+ setProps: (props: Recordable) => void
+ setValues: (data: Recordable) => void
+ getFormData: () => Promise
+ setSchema: (schemaProps: FormSetPropsType[]) => void
+ addSchema: (formSchema: FormSchema, index?: number) => void
+ delSchema: (field: string) => void
+ } = {
+ setProps: async (props: FormProps = {}) => {
+ const form = await getForm()
+ form?.setProps(props)
+ if (props.model) {
+ form?.setValues(props.model)
+ }
+ },
+
+ setValues: async (data: Recordable) => {
+ const form = await getForm()
+ form?.setValues(data)
+ },
+
+ /**
+ * @param schemaProps 需要设置的schemaProps
+ */
+ setSchema: async (schemaProps: FormSetPropsType[]) => {
+ const form = await getForm()
+ form?.setSchema(schemaProps)
+ },
+
+ /**
+ * @param formSchema 需要新增数据
+ * @param index 在哪里新增
+ */
+ addSchema: async (formSchema: FormSchema, index?: number) => {
+ const form = await getForm()
+ form?.addSchema(formSchema, index)
+ },
+
+ /**
+ * @param field 删除哪个数据
+ */
+ delSchema: async (field: string) => {
+ const form = await getForm()
+ form?.delSchema(field)
+ },
+
+ /**
+ * @returns form data
+ */
+ getFormData: async (): Promise => {
+ const form = await getForm()
+ return form?.formModel as T
+ }
+ }
+
+ props && methods.setProps(props)
+
+ return {
+ register,
+ elFormRef,
+ methods
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useGuide.ts b/marketing-ui/admin-ui/src/hooks/web/useGuide.ts
new file mode 100644
index 0000000..7fd2fb0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useGuide.ts
@@ -0,0 +1,49 @@
+import { Config, driver } from 'driver.js'
+import 'driver.js/dist/driver.css'
+import { useDesign } from '@/hooks/web/useDesign'
+import { useI18n } from '@/hooks/web/useI18n'
+
+const { t } = useI18n()
+
+const { variables } = useDesign()
+
+export const useGuide = (options?: Config) => {
+ const driverObj = driver(
+ options || {
+ showProgress: true,
+ nextBtnText: t('common.nextLabel'),
+ prevBtnText: t('common.prevLabel'),
+ doneBtnText: t('common.doneLabel'),
+ steps: [
+ {
+ element: `#${variables.namespace}-menu`,
+ popover: {
+ title: t('common.menu'),
+ description: t('common.menuDes'),
+ side: 'right'
+ }
+ },
+ {
+ element: `#${variables.namespace}-tool-header`,
+ popover: {
+ title: t('common.tool'),
+ description: t('common.toolDes'),
+ side: 'left'
+ }
+ },
+ {
+ element: `#${variables.namespace}-tags-view`,
+ popover: {
+ title: t('common.tagsView'),
+ description: t('common.tagsViewDes'),
+ side: 'bottom'
+ }
+ }
+ ]
+ }
+ )
+
+ return {
+ ...driverObj
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useI18n.ts b/marketing-ui/admin-ui/src/hooks/web/useI18n.ts
new file mode 100644
index 0000000..d1ab70f
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useI18n.ts
@@ -0,0 +1,53 @@
+import { i18n } from '@/plugins/vueI18n'
+
+type I18nGlobalTranslation = {
+ (key: string): string
+ (key: string, locale: string): string
+ (key: string, locale: string, list: unknown[]): string
+ (key: string, locale: string, named: Record): string
+ (key: string, list: unknown[]): string
+ (key: string, named: Record): string
+}
+
+type I18nTranslationRestParameters = [string, any]
+
+const getKey = (namespace: string | undefined, key: string) => {
+ if (!namespace) {
+ return key
+ }
+ if (key.startsWith(namespace)) {
+ return key
+ }
+ return `${namespace}.${key}`
+}
+
+export const useI18n = (
+ namespace?: string
+): {
+ t: I18nGlobalTranslation
+} => {
+ const normalFn = {
+ t: (key: string) => {
+ return getKey(namespace, key)
+ }
+ }
+
+ if (!i18n) {
+ return normalFn
+ }
+
+ const { t, ...methods } = i18n.global
+
+ const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => {
+ if (!key) return ''
+ if (!key.includes('.') && !namespace) return key
+ //@ts-ignore
+ return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters))
+ }
+ return {
+ ...methods,
+ t: tFn
+ }
+}
+
+export const t = (key: string) => key
diff --git a/marketing-ui/admin-ui/src/hooks/web/useIcon.ts b/marketing-ui/admin-ui/src/hooks/web/useIcon.ts
new file mode 100644
index 0000000..3500204
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useIcon.ts
@@ -0,0 +1,8 @@
+import { h } from 'vue'
+import type { VNode } from 'vue'
+import { Icon } from '@/components/Icon'
+import { IconTypes } from '@/types/icon'
+
+export const useIcon = (props: IconTypes): VNode => {
+ return h(Icon, props)
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useLocale.ts b/marketing-ui/admin-ui/src/hooks/web/useLocale.ts
new file mode 100644
index 0000000..c65070e
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useLocale.ts
@@ -0,0 +1,35 @@
+import { i18n } from '@/plugins/vueI18n'
+import { useLocaleStoreWithOut } from '@/store/modules/locale'
+import { setHtmlPageLang } from '@/plugins/vueI18n/helper'
+
+const setI18nLanguage = (locale: LocaleType) => {
+ const localeStore = useLocaleStoreWithOut()
+
+ if (i18n.mode === 'legacy') {
+ i18n.global.locale = locale
+ } else {
+ ;(i18n.global.locale as any).value = locale
+ }
+ localeStore.setCurrentLocale({
+ lang: locale
+ })
+ setHtmlPageLang(locale)
+}
+
+export const useLocale = () => {
+ // Switching the language will change the locale of useI18n
+ // And submit to configuration modification
+ const changeLocale = async (locale: LocaleType) => {
+ const globalI18n = i18n.global
+
+ const langModule = await import(`../../locales/${locale}.ts`)
+
+ globalI18n.setLocaleMessage(locale, langModule.default)
+
+ setI18nLanguage(locale)
+ }
+
+ return {
+ changeLocale
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useMessage.ts b/marketing-ui/admin-ui/src/hooks/web/useMessage.ts
new file mode 100644
index 0000000..ac2b552
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useMessage.ts
@@ -0,0 +1,95 @@
+import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
+import { useI18n } from './useI18n'
+export const useMessage = () => {
+ const { t } = useI18n()
+ return {
+ // 消息提示
+ info(content: string) {
+ ElMessage.info(content)
+ },
+ // 错误消息
+ error(content: string) {
+ ElMessage.error(content)
+ },
+ // 成功消息
+ success(content: string) {
+ ElMessage.success(content)
+ },
+ // 警告消息
+ warning(content: string) {
+ ElMessage.warning(content)
+ },
+ // 弹出提示
+ alert(content: string) {
+ ElMessageBox.alert(content, t('common.confirmTitle'))
+ },
+ // 错误提示
+ alertError(content: string) {
+ ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'error' })
+ },
+ // 成功提示
+ alertSuccess(content: string) {
+ ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'success' })
+ },
+ // 警告提示
+ alertWarning(content: string) {
+ ElMessageBox.alert(content, t('common.confirmTitle'), { type: 'warning' })
+ },
+ // 通知提示
+ notify(content: string) {
+ ElNotification.info(content)
+ },
+ // 错误通知
+ notifyError(content: string) {
+ ElNotification.error(content)
+ },
+ // 成功通知
+ notifySuccess(content: string) {
+ ElNotification.success(content)
+ },
+ // 警告通知
+ notifyWarning(content: string) {
+ ElNotification.warning(content)
+ },
+ // 确认窗体
+ confirm(content: string, tip?: string) {
+ return ElMessageBox.confirm(content, tip ? tip : t('common.confirmTitle'), {
+ confirmButtonText: t('common.ok'),
+ cancelButtonText: t('common.cancel'),
+ type: 'warning'
+ })
+ },
+ // 删除窗体
+ delConfirm(content?: string, tip?: string) {
+ return ElMessageBox.confirm(
+ content ? content : t('common.delMessage'),
+ tip ? tip : t('common.confirmTitle'),
+ {
+ confirmButtonText: t('common.ok'),
+ cancelButtonText: t('common.cancel'),
+ type: 'warning'
+ }
+ )
+ },
+ // 导出窗体
+ exportConfirm(content?: string, tip?: string) {
+ return ElMessageBox.confirm(
+ content ? content : t('common.exportMessage'),
+ tip ? tip : t('common.confirmTitle'),
+ {
+ confirmButtonText: t('common.ok'),
+ cancelButtonText: t('common.cancel'),
+ type: 'warning'
+ }
+ )
+ },
+ // 提交内容
+ prompt(content: string, tip: string) {
+ return ElMessageBox.prompt(content, tip, {
+ confirmButtonText: t('common.ok'),
+ cancelButtonText: t('common.cancel'),
+ type: 'warning'
+ })
+ }
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useNProgress.ts b/marketing-ui/admin-ui/src/hooks/web/useNProgress.ts
new file mode 100644
index 0000000..6d8c0b9
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useNProgress.ts
@@ -0,0 +1,33 @@
+import { useCssVar } from '@vueuse/core'
+import type { NProgressOptions } from 'nprogress'
+import NProgress from 'nprogress'
+import 'nprogress/nprogress.css'
+
+const primaryColor = useCssVar('--el-color-primary', document.documentElement)
+
+export const useNProgress = () => {
+ NProgress.configure({ showSpinner: false } as NProgressOptions)
+
+ const initColor = async () => {
+ await nextTick()
+ const bar = document.getElementById('nprogress')?.getElementsByClassName('bar')[0] as ElRef
+ if (bar) {
+ bar.style.background = unref(primaryColor.value)
+ }
+ }
+
+ initColor()
+
+ const start = () => {
+ NProgress.start()
+ }
+
+ const done = () => {
+ NProgress.done()
+ }
+
+ return {
+ start,
+ done
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useNetwork.ts b/marketing-ui/admin-ui/src/hooks/web/useNetwork.ts
new file mode 100644
index 0000000..66fa446
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useNetwork.ts
@@ -0,0 +1,21 @@
+import { ref, onBeforeUnmount } from 'vue'
+
+const useNetwork = () => {
+ const online = ref(true)
+
+ const updateNetwork = () => {
+ online.value = navigator.onLine
+ }
+
+ window.addEventListener('online', updateNetwork)
+ window.addEventListener('offline', updateNetwork)
+
+ onBeforeUnmount(() => {
+ window.removeEventListener('online', updateNetwork)
+ window.removeEventListener('offline', updateNetwork)
+ })
+
+ return { online }
+}
+
+export { useNetwork }
diff --git a/marketing-ui/admin-ui/src/hooks/web/useNow.ts b/marketing-ui/admin-ui/src/hooks/web/useNow.ts
new file mode 100644
index 0000000..09d3176
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useNow.ts
@@ -0,0 +1,60 @@
+import { dateUtil } from '@/utils/dateUtil'
+import { reactive, toRefs } from 'vue'
+import { tryOnMounted, tryOnUnmounted } from '@vueuse/core'
+
+export const useNow = (immediate = true) => {
+ let timer: IntervalHandle
+
+ const state = reactive({
+ year: 0,
+ month: 0,
+ week: '',
+ day: 0,
+ hour: '',
+ minute: '',
+ second: 0,
+ meridiem: ''
+ })
+
+ const update = () => {
+ const now = dateUtil()
+
+ const h = now.format('HH')
+ const m = now.format('mm')
+ const s = now.get('s')
+
+ state.year = now.get('y')
+ state.month = now.get('M') + 1
+ state.week = '星期' + ['日', '一', '二', '三', '四', '五', '六'][now.day()]
+ state.day = now.get('date')
+ state.hour = h
+ state.minute = m
+ state.second = s
+
+ state.meridiem = now.format('A')
+ }
+
+ function start() {
+ update()
+ clearInterval(timer)
+ timer = setInterval(() => update(), 1000)
+ }
+
+ function stop() {
+ clearInterval(timer)
+ }
+
+ tryOnMounted(() => {
+ immediate && start()
+ })
+
+ tryOnUnmounted(() => {
+ stop()
+ })
+
+ return {
+ ...toRefs(state),
+ start,
+ stop
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/usePageLoading.ts b/marketing-ui/admin-ui/src/hooks/web/usePageLoading.ts
new file mode 100644
index 0000000..bb89457
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/usePageLoading.ts
@@ -0,0 +1,18 @@
+import { useAppStoreWithOut } from '@/store/modules/app'
+
+const appStore = useAppStoreWithOut()
+
+export const usePageLoading = () => {
+ const loadStart = () => {
+ appStore.setPageLoading(true)
+ }
+
+ const loadDone = () => {
+ appStore.setPageLoading(false)
+ }
+
+ return {
+ loadStart,
+ loadDone
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useTable.ts b/marketing-ui/admin-ui/src/hooks/web/useTable.ts
new file mode 100644
index 0000000..361dd67
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useTable.ts
@@ -0,0 +1,223 @@
+import download from '@/utils/download'
+import { Table, TableExpose } from '@/components/Table'
+import { ElMessage, ElMessageBox, ElTable } from 'element-plus'
+import { computed, nextTick, reactive, ref, unref, watch } from 'vue'
+import type { TableProps } from '@/components/Table/src/types'
+
+import { TableSetPropsType } from '@/types/table'
+
+const { t } = useI18n()
+interface ResponseType {
+ list: T[]
+ total?: number
+}
+
+interface UseTableConfig {
+ getListApi: (option: any) => Promise
+ delListApi?: (option: any) => Promise
+ exportListApi?: (option: any) => Promise
+ // 返回数据格式配置
+ response?: ResponseType
+ // 默认传递的参数
+ defaultParams?: Recordable
+ props?: TableProps
+}
+
+interface TableObject {
+ pageSize: number
+ currentPage: number
+ total: number
+ tableList: T[]
+ params: any
+ loading: boolean
+ exportLoading: boolean
+ currentRow: Nullable
+}
+
+export const useTable = (config?: UseTableConfig) => {
+ const tableObject = reactive>({
+ // 页数
+ pageSize: 10,
+ // 当前页
+ currentPage: 1,
+ // 总条数
+ total: 10,
+ // 表格数据
+ tableList: [],
+ // AxiosConfig 配置
+ params: {
+ ...(config?.defaultParams || {})
+ },
+ // 加载中
+ loading: true,
+ // 导出加载中
+ exportLoading: false,
+ // 当前行的数据
+ currentRow: null
+ })
+
+ const paramsObj = computed(() => {
+ return {
+ ...tableObject.params,
+ pageSize: tableObject.pageSize,
+ pageNo: tableObject.currentPage
+ }
+ })
+
+ watch(
+ () => tableObject.currentPage,
+ () => {
+ methods.getList()
+ }
+ )
+
+ watch(
+ () => tableObject.pageSize,
+ () => {
+ // 当前页不为1时,修改页数后会导致多次调用getList方法
+ if (tableObject.currentPage === 1) {
+ methods.getList()
+ } else {
+ tableObject.currentPage = 1
+ methods.getList()
+ }
+ }
+ )
+
+ // Table实例
+ const tableRef = ref()
+
+ // ElTable实例
+ const elTableRef = ref>()
+
+ const register = (ref: typeof Table & TableExpose, elRef: ComponentRef) => {
+ tableRef.value = ref
+ elTableRef.value = elRef
+ }
+
+ const getTable = async () => {
+ await nextTick()
+ const table = unref(tableRef)
+ if (!table) {
+ console.error('The table is not registered. Please use the register method to register')
+ }
+ return table
+ }
+
+ const delData = async (ids: string | number | string[] | number[]) => {
+ let idsLength = 1
+ if (ids instanceof Array) {
+ idsLength = ids.length
+ await Promise.all(
+ ids.map(async (id: string | number) => {
+ await (config?.delListApi && config?.delListApi(id))
+ })
+ )
+ } else {
+ await (config?.delListApi && config?.delListApi(ids))
+ }
+ ElMessage.success(t('common.delSuccess'))
+
+ // 计算出临界点
+ tableObject.currentPage =
+ tableObject.total % tableObject.pageSize === idsLength || tableObject.pageSize === 1
+ ? tableObject.currentPage > 1
+ ? tableObject.currentPage - 1
+ : tableObject.currentPage
+ : tableObject.currentPage
+ await methods.getList()
+ }
+
+ const methods = {
+ getList: async () => {
+ tableObject.loading = true
+ const res = await config?.getListApi(unref(paramsObj)).finally(() => {
+ tableObject.loading = false
+ })
+ if (res) {
+ tableObject.tableList = (res as unknown as ResponseType).list
+ tableObject.total = (res as unknown as ResponseType).total ?? 0
+ }
+ },
+ setProps: async (props: TableProps = {}) => {
+ const table = await getTable()
+ table?.setProps(props)
+ },
+ setColumn: async (columnProps: TableSetPropsType[]) => {
+ const table = await getTable()
+ table?.setColumn(columnProps)
+ },
+ getSelections: async () => {
+ const table = await getTable()
+ return (table?.selections || []) as T[]
+ },
+ // 与Search组件结合
+ setSearchParams: (data: Recordable) => {
+ tableObject.params = Object.assign(tableObject.params, {
+ pageSize: tableObject.pageSize,
+ pageNo: 1,
+ ...data
+ })
+ // 页码不等于1时更新页码重新获取数据,页码等于1时重新获取数据
+ if (tableObject.currentPage !== 1) {
+ tableObject.currentPage = 1
+ } else {
+ methods.getList()
+ }
+ },
+ // 删除数据
+ delList: async (
+ ids: string | number | string[] | number[],
+ multiple: boolean,
+ message = true
+ ) => {
+ const tableRef = await getTable()
+ if (multiple) {
+ if (!tableRef?.selections.length) {
+ ElMessage.warning(t('common.delNoData'))
+ return
+ }
+ }
+ if (message) {
+ ElMessageBox.confirm(t('common.delMessage'), t('common.confirmTitle'), {
+ confirmButtonText: t('common.ok'),
+ cancelButtonText: t('common.cancel'),
+ type: 'warning'
+ }).then(async () => {
+ await delData(ids)
+ })
+ } else {
+ await delData(ids)
+ }
+ },
+ // 导出列表
+ exportList: async (fileName: string) => {
+ tableObject.exportLoading = true
+ ElMessageBox.confirm(t('common.exportMessage'), t('common.confirmTitle'), {
+ confirmButtonText: t('common.ok'),
+ cancelButtonText: t('common.cancel'),
+ type: 'warning'
+ })
+ .then(async () => {
+ const res = await config?.exportListApi?.(unref(paramsObj) as unknown as T)
+ if (res) {
+ download.excel(res as unknown as Blob, fileName)
+ }
+ })
+ .finally(() => {
+ tableObject.exportLoading = false
+ })
+ }
+ }
+
+ config?.props && methods.setProps(config.props)
+
+ return {
+ register,
+ elTableRef,
+ tableObject,
+ methods,
+ // add by 芋艿:返回 tableMethods 属性,和 tableObject 更统一
+ tableMethods: methods
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useTagsView.ts b/marketing-ui/admin-ui/src/hooks/web/useTagsView.ts
new file mode 100644
index 0000000..31eadb0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useTagsView.ts
@@ -0,0 +1,63 @@
+import { useTagsViewStoreWithOut } from '@/store/modules/tagsView'
+import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router'
+import { computed, nextTick, unref } from 'vue'
+
+export const useTagsView = () => {
+ const tagsViewStore = useTagsViewStoreWithOut()
+
+ const { replace, currentRoute } = useRouter()
+
+ const selectedTag = computed(() => tagsViewStore.getSelectedTag)
+
+ const closeAll = (callback?: Fn) => {
+ tagsViewStore.delAllViews()
+ callback?.()
+ }
+
+ const closeLeft = (callback?: Fn) => {
+ tagsViewStore.delLeftViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
+ callback?.()
+ }
+
+ const closeRight = (callback?: Fn) => {
+ tagsViewStore.delRightViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
+ callback?.()
+ }
+
+ const closeOther = (callback?: Fn) => {
+ tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
+ callback?.()
+ }
+
+ const closeCurrent = (view?: RouteLocationNormalizedLoaded, callback?: Fn) => {
+ if (view?.meta?.affix) return
+ tagsViewStore.delView(view || unref(currentRoute))
+
+ callback?.()
+ }
+
+ const refreshPage = async (view?: RouteLocationNormalizedLoaded, callback?: Fn) => {
+ tagsViewStore.delCachedView()
+ const { path, query } = view || unref(currentRoute)
+ await nextTick()
+ replace({
+ path: '/redirect' + path,
+ query: query
+ })
+ callback?.()
+ }
+
+ const setTitle = (title: string, path?: string) => {
+ tagsViewStore.setTitle(title, path)
+ }
+
+ return {
+ closeAll,
+ closeLeft,
+ closeRight,
+ closeOther,
+ closeCurrent,
+ refreshPage,
+ setTitle
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useTimeAgo.ts b/marketing-ui/admin-ui/src/hooks/web/useTimeAgo.ts
new file mode 100644
index 0000000..a6da281
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useTimeAgo.ts
@@ -0,0 +1,49 @@
+import { useTimeAgo as useTimeAgoCore, UseTimeAgoMessages } from '@vueuse/core'
+import { useLocaleStoreWithOut } from '@/store/modules/locale'
+
+const TIME_AGO_MESSAGE_MAP: {
+ 'zh-CN': UseTimeAgoMessages
+ en: UseTimeAgoMessages
+} = {
+ // @ts-ignore
+ 'zh-CN': {
+ justNow: '刚刚',
+ past: (n) => (n.match(/\d/) ? `${n}前` : n),
+ future: (n) => (n.match(/\d/) ? `${n}后` : n),
+ month: (n, past) => (n === 1 ? (past ? '上个月' : '下个月') : `${n} 个月`),
+ year: (n, past) => (n === 1 ? (past ? '去年' : '明年') : `${n} 年`),
+ day: (n, past) => (n === 1 ? (past ? '昨天' : '明天') : `${n} 天`),
+ week: (n, past) => (n === 1 ? (past ? '上周' : '下周') : `${n} 周`),
+ hour: (n) => `${n} 小时`,
+ minute: (n) => `${n} 分钟`,
+ second: (n) => `${n} 秒`
+ },
+ // @ts-ignore
+ en: {
+ justNow: 'just now',
+ past: (n) => (n.match(/\d/) ? `${n} ago` : n),
+ future: (n) => (n.match(/\d/) ? `in ${n}` : n),
+ month: (n, past) =>
+ n === 1 ? (past ? 'last month' : 'next month') : `${n} month${n > 1 ? 's' : ''}`,
+ year: (n, past) =>
+ n === 1 ? (past ? 'last year' : 'next year') : `${n} year${n > 1 ? 's' : ''}`,
+ day: (n, past) => (n === 1 ? (past ? 'yesterday' : 'tomorrow') : `${n} day${n > 1 ? 's' : ''}`),
+ week: (n, past) =>
+ n === 1 ? (past ? 'last week' : 'next week') : `${n} week${n > 1 ? 's' : ''}`,
+ hour: (n) => `${n} hour${n > 1 ? 's' : ''}`,
+ minute: (n) => `${n} minute${n > 1 ? 's' : ''}`,
+ second: (n) => `${n} second${n > 1 ? 's' : ''}`
+ }
+}
+
+export const useTimeAgo = (time: Date | number | string) => {
+ const localeStore = useLocaleStoreWithOut()
+
+ const currentLocale = computed(() => localeStore.getCurrentLocale)
+
+ const timeAgo = useTimeAgoCore(time, {
+ messages: TIME_AGO_MESSAGE_MAP[unref(currentLocale).lang]
+ })
+
+ return timeAgo
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useTitle.ts b/marketing-ui/admin-ui/src/hooks/web/useTitle.ts
new file mode 100644
index 0000000..020a9b7
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useTitle.ts
@@ -0,0 +1,24 @@
+import { watch, ref } from 'vue'
+import { isString } from '@/utils/is'
+import { useAppStoreWithOut } from '@/store/modules/app'
+
+const appStore = useAppStoreWithOut()
+
+export const useTitle = (newTitle?: string) => {
+ const { t } = useI18n()
+ const title = ref(
+ newTitle ? `${appStore.getTitle} - ${t(newTitle as string)}` : appStore.getTitle
+ )
+
+ watch(
+ title,
+ (n, o) => {
+ if (isString(n) && n !== o && document) {
+ document.title = n
+ }
+ },
+ { immediate: true }
+ )
+
+ return title
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useValidator.ts b/marketing-ui/admin-ui/src/hooks/web/useValidator.ts
new file mode 100644
index 0000000..151e35b
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useValidator.ts
@@ -0,0 +1,60 @@
+import { useI18n } from '@/hooks/web/useI18n'
+import { FormItemRule } from 'element-plus'
+
+const { t } = useI18n()
+
+interface LengthRange {
+ min: number
+ max: number
+ message?: string
+}
+
+export const useValidator = () => {
+ const required = (message?: string): FormItemRule => {
+ return {
+ required: true,
+ message: message || t('common.required')
+ }
+ }
+
+ const lengthRange = (options: LengthRange): FormItemRule => {
+ const { min, max, message } = options
+
+ return {
+ min,
+ max,
+ message: message || t('common.lengthRange', { min, max })
+ }
+ }
+
+ const notSpace = (message?: string): FormItemRule => {
+ return {
+ validator: (_, val, callback) => {
+ if (val?.indexOf(' ') !== -1) {
+ callback(new Error(message || t('common.notSpace')))
+ } else {
+ callback()
+ }
+ }
+ }
+ }
+
+ const notSpecialCharacters = (message?: string): FormItemRule => {
+ return {
+ validator: (_, val, callback) => {
+ if (/[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/gi.test(val)) {
+ callback(new Error(message || t('common.notSpecialCharacters')))
+ } else {
+ callback()
+ }
+ }
+ }
+ }
+
+ return {
+ required,
+ lengthRange,
+ notSpace,
+ notSpecialCharacters
+ }
+}
diff --git a/marketing-ui/admin-ui/src/hooks/web/useWatermark.ts b/marketing-ui/admin-ui/src/hooks/web/useWatermark.ts
new file mode 100644
index 0000000..4a31359
--- /dev/null
+++ b/marketing-ui/admin-ui/src/hooks/web/useWatermark.ts
@@ -0,0 +1,55 @@
+const domSymbol = Symbol('watermark-dom')
+
+export function useWatermark(appendEl: HTMLElement | null = document.body) {
+ let func: Fn = () => {}
+ const id = domSymbol.toString()
+ const clear = () => {
+ const domId = document.getElementById(id)
+ if (domId) {
+ const el = appendEl
+ el && el.removeChild(domId)
+ }
+ window.removeEventListener('resize', func)
+ }
+ const createWatermark = (str: string) => {
+ clear()
+
+ const can = document.createElement('canvas')
+ can.width = 300
+ can.height = 240
+
+ const cans = can.getContext('2d')
+ if (cans) {
+ cans.rotate((-20 * Math.PI) / 120)
+ cans.font = '15px Vedana'
+ cans.fillStyle = 'rgba(0, 0, 0, 0.15)'
+ cans.textAlign = 'left'
+ cans.textBaseline = 'middle'
+ cans.fillText(str, can.width / 20, can.height)
+ }
+
+ const div = document.createElement('div')
+ div.id = id
+ div.style.pointerEvents = 'none'
+ div.style.top = '0px'
+ div.style.left = '0px'
+ div.style.position = 'absolute'
+ div.style.zIndex = '100000000'
+ div.style.width = document.documentElement.clientWidth + 'px'
+ div.style.height = document.documentElement.clientHeight + 'px'
+ div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat'
+ const el = appendEl
+ el && el.appendChild(div)
+ return id
+ }
+
+ function setWatermark(str: string) {
+ createWatermark(str)
+ func = () => {
+ createWatermark(str)
+ }
+ window.addEventListener('resize', func)
+ }
+
+ return { setWatermark, clear }
+}
diff --git a/marketing-ui/admin-ui/src/layout/Layout.vue b/marketing-ui/admin-ui/src/layout/Layout.vue
new file mode 100644
index 0000000..d15025c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/Layout.vue
@@ -0,0 +1,75 @@
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/AppView.vue b/marketing-ui/admin-ui/src/layout/components/AppView.vue
new file mode 100644
index 0000000..df720a1
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/AppView.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Breadcrumb/index.ts b/marketing-ui/admin-ui/src/layout/components/Breadcrumb/index.ts
new file mode 100644
index 0000000..93ffe70
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Breadcrumb/index.ts
@@ -0,0 +1,3 @@
+import Breadcrumb from './src/Breadcrumb.vue'
+
+export { Breadcrumb }
diff --git a/marketing-ui/admin-ui/src/layout/components/Breadcrumb/src/Breadcrumb.vue b/marketing-ui/admin-ui/src/layout/components/Breadcrumb/src/Breadcrumb.vue
new file mode 100644
index 0000000..80770a8
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Breadcrumb/src/Breadcrumb.vue
@@ -0,0 +1,130 @@
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Breadcrumb/src/helper.ts b/marketing-ui/admin-ui/src/layout/components/Breadcrumb/src/helper.ts
new file mode 100644
index 0000000..fb3ec19
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Breadcrumb/src/helper.ts
@@ -0,0 +1,31 @@
+import { pathResolve } from '@/utils/routerHelper'
+import type { RouteMeta } from 'vue-router'
+
+export const filterBreadcrumb = (
+ routes: AppRouteRecordRaw[],
+ parentPath = ''
+): AppRouteRecordRaw[] => {
+ const res: AppRouteRecordRaw[] = []
+
+ for (const route of routes) {
+ const meta = route?.meta as RouteMeta
+ if (meta.hidden && !meta.canTo) {
+ continue
+ }
+
+ const data: AppRouteRecordRaw =
+ !meta.alwaysShow && route.children?.length === 1
+ ? { ...route.children[0], path: pathResolve(route.path, route.children[0].path) }
+ : { ...route }
+
+ data.path = pathResolve(parentPath, data.path)
+
+ if (data.children) {
+ data.children = filterBreadcrumb(data.children, data.path)
+ }
+ if (data) {
+ res.push(data)
+ }
+ }
+ return res
+}
diff --git a/marketing-ui/admin-ui/src/layout/components/Collapse/index.ts b/marketing-ui/admin-ui/src/layout/components/Collapse/index.ts
new file mode 100644
index 0000000..73f65a3
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Collapse/index.ts
@@ -0,0 +1,3 @@
+import Collapse from './src/Collapse.vue'
+
+export { Collapse }
diff --git a/marketing-ui/admin-ui/src/layout/components/Collapse/src/Collapse.vue b/marketing-ui/admin-ui/src/layout/components/Collapse/src/Collapse.vue
new file mode 100644
index 0000000..a8fc7ee
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Collapse/src/Collapse.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/ContextMenu/index.ts b/marketing-ui/admin-ui/src/layout/components/ContextMenu/index.ts
new file mode 100644
index 0000000..2a7c1f0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/ContextMenu/index.ts
@@ -0,0 +1,10 @@
+import ContextMenu from './src/ContextMenu.vue'
+import { ElDropdown } from 'element-plus'
+import type { RouteLocationNormalizedLoaded } from 'vue-router'
+
+export interface ContextMenuExpose {
+ elDropdownMenuRef: ComponentRef
+ tagItem: RouteLocationNormalizedLoaded
+}
+
+export { ContextMenu }
diff --git a/marketing-ui/admin-ui/src/layout/components/ContextMenu/src/ContextMenu.vue b/marketing-ui/admin-ui/src/layout/components/ContextMenu/src/ContextMenu.vue
new file mode 100644
index 0000000..90eea4c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/ContextMenu/src/ContextMenu.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+ {{ t(item.label) }}
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Footer/index.ts b/marketing-ui/admin-ui/src/layout/components/Footer/index.ts
new file mode 100644
index 0000000..bd052e0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Footer/index.ts
@@ -0,0 +1,3 @@
+import Footer from './src/Footer.vue'
+
+export { Footer }
diff --git a/marketing-ui/admin-ui/src/layout/components/Footer/src/Footer.vue b/marketing-ui/admin-ui/src/layout/components/Footer/src/Footer.vue
new file mode 100644
index 0000000..98ce7e5
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Footer/src/Footer.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/LocaleDropdown/index.ts b/marketing-ui/admin-ui/src/layout/components/LocaleDropdown/index.ts
new file mode 100644
index 0000000..d02e640
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/LocaleDropdown/index.ts
@@ -0,0 +1,3 @@
+import LocaleDropdown from './src/LocaleDropdown.vue'
+
+export { LocaleDropdown }
diff --git a/marketing-ui/admin-ui/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue b/marketing-ui/admin-ui/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue
new file mode 100644
index 0000000..95132db
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/LocaleDropdown/src/LocaleDropdown.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Logo/index.ts b/marketing-ui/admin-ui/src/layout/components/Logo/index.ts
new file mode 100644
index 0000000..1c4224c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Logo/index.ts
@@ -0,0 +1,3 @@
+import Logo from './src/Logo.vue'
+
+export { Logo }
diff --git a/marketing-ui/admin-ui/src/layout/components/Logo/src/Logo.vue b/marketing-ui/admin-ui/src/layout/components/Logo/src/Logo.vue
new file mode 100644
index 0000000..d241130
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Logo/src/Logo.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Menu/index.ts b/marketing-ui/admin-ui/src/layout/components/Menu/index.ts
new file mode 100644
index 0000000..a6ec696
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Menu/index.ts
@@ -0,0 +1,3 @@
+import Menu from './src/Menu.vue'
+
+export { Menu }
diff --git a/marketing-ui/admin-ui/src/layout/components/Menu/src/Menu.vue b/marketing-ui/admin-ui/src/layout/components/Menu/src/Menu.vue
new file mode 100644
index 0000000..94a1da4
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Menu/src/Menu.vue
@@ -0,0 +1,272 @@
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Menu/src/components/useRenderMenuItem.tsx b/marketing-ui/admin-ui/src/layout/components/Menu/src/components/useRenderMenuItem.tsx
new file mode 100644
index 0000000..301313f
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Menu/src/components/useRenderMenuItem.tsx
@@ -0,0 +1,50 @@
+import { ElSubMenu, ElMenuItem } from 'element-plus'
+import { hasOneShowingChild } from '../helper'
+import { isUrl } from '@/utils/is'
+import { useRenderMenuTitle } from './useRenderMenuTitle'
+import { pathResolve } from '@/utils/routerHelper'
+
+const { renderMenuTitle } = useRenderMenuTitle()
+
+export const useRenderMenuItem = () =>
+ // allRouters: AppRouteRecordRaw[] = [],
+ {
+ const renderMenuItem = (routers: AppRouteRecordRaw[], parentPath = '/') => {
+ return routers
+ .filter((v) => !v.meta?.hidden)
+ .map((v) => {
+ const meta = v.meta ?? {}
+ const { oneShowingChild, onlyOneChild } = hasOneShowingChild(v.children, v)
+ const fullPath = isUrl(v.path) ? v.path : pathResolve(parentPath, v.path) // getAllParentPath(allRouters, v.path).join('/')
+
+ if (
+ oneShowingChild &&
+ (!onlyOneChild?.children || onlyOneChild?.noShowingChildren) &&
+ !meta?.alwaysShow
+ ) {
+ return (
+
+ {{
+ default: () => renderMenuTitle(onlyOneChild ? onlyOneChild?.meta : meta)
+ }}
+
+ )
+ } else {
+ return (
+
+ {{
+ title: () => renderMenuTitle(meta),
+ default: () => renderMenuItem(v.children!, fullPath)
+ }}
+
+ )
+ }
+ })
+ }
+
+ return {
+ renderMenuItem
+ }
+ }
diff --git a/marketing-ui/admin-ui/src/layout/components/Menu/src/components/useRenderMenuTitle.tsx b/marketing-ui/admin-ui/src/layout/components/Menu/src/components/useRenderMenuTitle.tsx
new file mode 100644
index 0000000..8941d9d
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Menu/src/components/useRenderMenuTitle.tsx
@@ -0,0 +1,27 @@
+import type { RouteMeta } from 'vue-router'
+import { Icon } from '@/components/Icon'
+import { useI18n } from '@/hooks/web/useI18n'
+
+export const useRenderMenuTitle = () => {
+ const renderMenuTitle = (meta: RouteMeta) => {
+ const { t } = useI18n()
+ const { title = 'Please set title', icon } = meta
+
+ return icon ? (
+ <>
+
+
+ >
+ ) : (
+
+ )
+ }
+
+ return {
+ renderMenuTitle
+ }
+}
diff --git a/marketing-ui/admin-ui/src/layout/components/Menu/src/helper.ts b/marketing-ui/admin-ui/src/layout/components/Menu/src/helper.ts
new file mode 100644
index 0000000..c26f5f4
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Menu/src/helper.ts
@@ -0,0 +1,54 @@
+import type { RouteMeta } from 'vue-router'
+import { findPath } from '@/utils/tree'
+
+type OnlyOneChildType = AppRouteRecordRaw & { noShowingChildren?: boolean }
+
+interface HasOneShowingChild {
+ oneShowingChild?: boolean
+ onlyOneChild?: OnlyOneChildType
+}
+
+export const getAllParentPath = (treeData: T[], path: string) => {
+ const menuList = findPath(treeData, (n) => n.path === path) as AppRouteRecordRaw[]
+ return (menuList || []).map((item) => item.path)
+}
+
+export const hasOneShowingChild = (
+ children: AppRouteRecordRaw[] = [],
+ parent: AppRouteRecordRaw
+): HasOneShowingChild => {
+ const onlyOneChild = ref()
+
+ const showingChildren = children.filter((v) => {
+ const meta = (v.meta ?? {}) as RouteMeta
+ if (meta.hidden) {
+ return false
+ } else {
+ // Temp set(will be used if only has one showing child)
+ onlyOneChild.value = v
+ return true
+ }
+ })
+
+ // When there is only one child router, the child router is displayed by default
+ if (showingChildren.length === 1) {
+ return {
+ oneShowingChild: true,
+ onlyOneChild: unref(onlyOneChild)
+ }
+ }
+
+ // Show parent if there are no child router to display
+ if (!showingChildren.length) {
+ onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
+ return {
+ oneShowingChild: true,
+ onlyOneChild: unref(onlyOneChild)
+ }
+ }
+
+ return {
+ oneShowingChild: false,
+ onlyOneChild: unref(onlyOneChild)
+ }
+}
diff --git a/marketing-ui/admin-ui/src/layout/components/Screenfull/index.ts b/marketing-ui/admin-ui/src/layout/components/Screenfull/index.ts
new file mode 100644
index 0000000..faec2d8
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Screenfull/index.ts
@@ -0,0 +1,3 @@
+import Screenfull from './src/Screenfull.vue'
+
+export { Screenfull }
diff --git a/marketing-ui/admin-ui/src/layout/components/Screenfull/src/Screenfull.vue b/marketing-ui/admin-ui/src/layout/components/Screenfull/src/Screenfull.vue
new file mode 100644
index 0000000..4c045f2
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Screenfull/src/Screenfull.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Setting/index.ts b/marketing-ui/admin-ui/src/layout/components/Setting/index.ts
new file mode 100644
index 0000000..b64c9ad
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Setting/index.ts
@@ -0,0 +1,3 @@
+import Setting from './src/Setting.vue'
+
+export { Setting }
diff --git a/marketing-ui/admin-ui/src/layout/components/Setting/src/Setting.vue b/marketing-ui/admin-ui/src/layout/components/Setting/src/Setting.vue
new file mode 100644
index 0000000..2973674
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Setting/src/Setting.vue
@@ -0,0 +1,302 @@
+
+
+
+
+
+
+
+
+
+ {{ t('setting.projectSetting') }}
+
+
+
+
+ {{ t('setting.theme') }}
+
+
+
+ {{ t('setting.layout') }}
+
+
+
+ {{ t('setting.systemTheme') }}
+
+
+
+ {{ t('setting.headerTheme') }}
+
+
+
+
+ {{ t('setting.menuTheme') }}
+
+
+
+
+
+ {{ t('setting.interfaceDisplay') }}
+
+
+
+
+ {{ t('setting.copy') }}
+
+
+
+ {{ t('setting.clearAndReset') }}
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Setting/src/components/ColorRadioPicker.vue b/marketing-ui/admin-ui/src/layout/components/Setting/src/components/ColorRadioPicker.vue
new file mode 100644
index 0000000..fcc5e75
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Setting/src/components/ColorRadioPicker.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Setting/src/components/InterfaceDisplay.vue b/marketing-ui/admin-ui/src/layout/components/Setting/src/components/InterfaceDisplay.vue
new file mode 100644
index 0000000..3ba5c6b
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Setting/src/components/InterfaceDisplay.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+ {{ t('setting.breadcrumb') }}
+
+
+
+
+ {{ t('setting.breadcrumbIcon') }}
+
+
+
+
+ {{ t('setting.hamburgerIcon') }}
+
+
+
+
+ {{ t('setting.screenfullIcon') }}
+
+
+
+
+ {{ t('setting.sizeIcon') }}
+
+
+
+
+ {{ t('setting.localeIcon') }}
+
+
+
+
+ {{ t('setting.messageIcon') }}
+
+
+
+
+ {{ t('setting.tagsView') }}
+
+
+
+
+ {{ t('setting.tagsViewImmerse') }}
+
+
+
+
+ {{ t('setting.tagsViewIcon') }}
+
+
+
+
+ {{ t('setting.logo') }}
+
+
+
+
+ {{ t('setting.uniqueOpened') }}
+
+
+
+
+ {{ t('setting.fixedHeader') }}
+
+
+
+
+ {{ t('setting.footer') }}
+
+
+
+
+ {{ t('setting.greyMode') }}
+
+
+
+
+ {{ t('setting.fixedMenu') }}
+
+
+
+
+ {{ t('watermark.watermark') }}
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/Setting/src/components/LayoutRadioPicker.vue b/marketing-ui/admin-ui/src/layout/components/Setting/src/components/LayoutRadioPicker.vue
new file mode 100644
index 0000000..801686c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/Setting/src/components/LayoutRadioPicker.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/SizeDropdown/index.ts b/marketing-ui/admin-ui/src/layout/components/SizeDropdown/index.ts
new file mode 100644
index 0000000..516488d
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/SizeDropdown/index.ts
@@ -0,0 +1,3 @@
+import SizeDropdown from './src/SizeDropdown.vue'
+
+export { SizeDropdown }
diff --git a/marketing-ui/admin-ui/src/layout/components/SizeDropdown/src/SizeDropdown.vue b/marketing-ui/admin-ui/src/layout/components/SizeDropdown/src/SizeDropdown.vue
new file mode 100644
index 0000000..3e15224
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/SizeDropdown/src/SizeDropdown.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+ {{ t(`size.${item}`) }}
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/TabMenu/index.ts b/marketing-ui/admin-ui/src/layout/components/TabMenu/index.ts
new file mode 100644
index 0000000..b5fd71c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/TabMenu/index.ts
@@ -0,0 +1,3 @@
+import TabMenu from './src/TabMenu.vue'
+
+export { TabMenu }
diff --git a/marketing-ui/admin-ui/src/layout/components/TabMenu/src/TabMenu.vue b/marketing-ui/admin-ui/src/layout/components/TabMenu/src/TabMenu.vue
new file mode 100644
index 0000000..efad6a6
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/TabMenu/src/TabMenu.vue
@@ -0,0 +1,240 @@
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/TabMenu/src/helper.ts b/marketing-ui/admin-ui/src/layout/components/TabMenu/src/helper.ts
new file mode 100644
index 0000000..cce3932
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/TabMenu/src/helper.ts
@@ -0,0 +1,51 @@
+import { getAllParentPath } from '@/layout/components/Menu/src/helper'
+import type { RouteMeta } from 'vue-router'
+import { isUrl } from '@/utils/is'
+import { cloneDeep } from 'lodash-es'
+
+export type TabMapTypes = {
+ [key: string]: string[]
+}
+
+export const tabPathMap = reactive({})
+
+export const initTabMap = (routes: AppRouteRecordRaw[]) => {
+ for (const v of routes) {
+ const meta = (v.meta ?? {}) as RouteMeta
+ if (!meta?.hidden) {
+ tabPathMap[v.path] = []
+ }
+ }
+}
+
+export const filterMenusPath = (
+ routes: AppRouteRecordRaw[],
+ allRoutes: AppRouteRecordRaw[]
+): AppRouteRecordRaw[] => {
+ const res: AppRouteRecordRaw[] = []
+ for (const v of routes) {
+ let data: Nullable = null
+ const meta = (v.meta ?? {}) as RouteMeta
+ if (!meta.hidden || meta.canTo) {
+ const allParentPath = getAllParentPath(allRoutes, v.path)
+
+ const fullPath = isUrl(v.path) ? v.path : allParentPath.join('/')
+
+ data = cloneDeep(v)
+ data.path = fullPath
+ if (v.children && data) {
+ data.children = filterMenusPath(v.children, allRoutes)
+ }
+
+ if (data) {
+ res.push(data)
+ }
+
+ if (allParentPath.length && Reflect.has(tabPathMap, allParentPath[0])) {
+ tabPathMap[allParentPath[0]].push(fullPath)
+ }
+ }
+ }
+
+ return res
+}
diff --git a/marketing-ui/admin-ui/src/layout/components/TagsView/index.ts b/marketing-ui/admin-ui/src/layout/components/TagsView/index.ts
new file mode 100644
index 0000000..30e604a
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/TagsView/index.ts
@@ -0,0 +1,3 @@
+import TagsView from './src/TagsView.vue'
+
+export { TagsView }
diff --git a/marketing-ui/admin-ui/src/layout/components/TagsView/src/TagsView.vue b/marketing-ui/admin-ui/src/layout/components/TagsView/src/TagsView.vue
new file mode 100644
index 0000000..af492ba
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/TagsView/src/TagsView.vue
@@ -0,0 +1,651 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/TagsView/src/helper.ts b/marketing-ui/admin-ui/src/layout/components/TagsView/src/helper.ts
new file mode 100644
index 0000000..22f6a50
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/TagsView/src/helper.ts
@@ -0,0 +1,21 @@
+import type { RouteMeta, RouteLocationNormalizedLoaded } from 'vue-router'
+import { pathResolve } from '@/utils/routerHelper'
+
+export const filterAffixTags = (routes: AppRouteRecordRaw[], parentPath = '') => {
+ let tags: RouteLocationNormalizedLoaded[] = []
+ routes.forEach((route) => {
+ const meta = route.meta as RouteMeta
+ const tagPath = pathResolve(parentPath, route.path)
+ if (meta?.affix) {
+ tags.push({ ...route, path: tagPath, fullPath: tagPath } as RouteLocationNormalizedLoaded)
+ }
+ if (route.children) {
+ const tempTags: RouteLocationNormalizedLoaded[] = filterAffixTags(route.children, tagPath)
+ if (tempTags.length >= 1) {
+ tags = [...tags, ...tempTags]
+ }
+ }
+ })
+
+ return tags
+}
diff --git a/marketing-ui/admin-ui/src/layout/components/ThemeSwitch/index.ts b/marketing-ui/admin-ui/src/layout/components/ThemeSwitch/index.ts
new file mode 100644
index 0000000..823a276
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/ThemeSwitch/index.ts
@@ -0,0 +1,3 @@
+import ThemeSwitch from './src/ThemeSwitch.vue'
+
+export { ThemeSwitch }
diff --git a/marketing-ui/admin-ui/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue b/marketing-ui/admin-ui/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue
new file mode 100644
index 0000000..39a8cfd
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/ThemeSwitch/src/ThemeSwitch.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/ToolHeader.vue b/marketing-ui/admin-ui/src/layout/components/ToolHeader.vue
new file mode 100644
index 0000000..d742503
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/ToolHeader.vue
@@ -0,0 +1,88 @@
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/UserInfo/index.ts b/marketing-ui/admin-ui/src/layout/components/UserInfo/index.ts
new file mode 100644
index 0000000..c3a34ab
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/UserInfo/index.ts
@@ -0,0 +1,3 @@
+import UserInfo from './src/UserInfo.vue'
+
+export { UserInfo }
diff --git a/marketing-ui/admin-ui/src/layout/components/UserInfo/src/UserInfo.vue b/marketing-ui/admin-ui/src/layout/components/UserInfo/src/UserInfo.vue
new file mode 100644
index 0000000..64abaea
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/UserInfo/src/UserInfo.vue
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('common.profile') }}
+
+
+
+
+
+
+ {{ t('common.loginOut') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/UserInfo/src/components/LockDialog.vue b/marketing-ui/admin-ui/src/layout/components/UserInfo/src/components/LockDialog.vue
new file mode 100644
index 0000000..7257be1
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/UserInfo/src/components/LockDialog.vue
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/UserInfo/src/components/LockPage.vue b/marketing-ui/admin-ui/src/layout/components/UserInfo/src/components/LockPage.vue
new file mode 100644
index 0000000..27d0a43
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/UserInfo/src/components/LockPage.vue
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+ {{ t('lock.unlock') }}
+
+
+
+
+ {{ hour }}
+
+ {{ meridiem }}
+
+
+
+ {{ minute }}
+
+
+
+
+
+
+
![]()
+
+ {{ userName }}
+
+
+
+
+ {{ t('lock.message') }}
+
+
+
+ {{ t('common.back') }}
+
+
+ {{ t('lock.backToLogin') }}
+
+
+ {{ t('lock.entrySystem') }}
+
+
+
+
+
+
+
+
+ {{ hour }}:{{ minute }} {{ meridiem }}
+
+
{{ year }}/{{ month }}/{{ day }} {{ week }}
+
+
+
+
+
diff --git a/marketing-ui/admin-ui/src/layout/components/useRenderLayout.tsx b/marketing-ui/admin-ui/src/layout/components/useRenderLayout.tsx
new file mode 100644
index 0000000..a631aa0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/layout/components/useRenderLayout.tsx
@@ -0,0 +1,294 @@
+import { computed } from 'vue'
+import { useAppStore } from '@/store/modules/app'
+import { Menu } from '@/layout/components/Menu'
+import { TabMenu } from '@/layout/components/TabMenu'
+import { TagsView } from '@/layout/components/TagsView'
+import { Logo } from '@/layout/components/Logo'
+import AppView from './AppView.vue'
+import ToolHeader from './ToolHeader.vue'
+import { ElScrollbar } from 'element-plus'
+import { useDesign } from '@/hooks/web/useDesign'
+
+const { getPrefixCls } = useDesign()
+
+const prefixCls = getPrefixCls('layout')
+
+const appStore = useAppStore()
+
+const pageLoading = computed(() => appStore.getPageLoading)
+
+// 标签页
+const tagsView = computed(() => appStore.getTagsView)
+
+// 菜单折叠
+const collapse = computed(() => appStore.getCollapse)
+
+// logo
+const logo = computed(() => appStore.logo)
+
+// 固定头部
+const fixedHeader = computed(() => appStore.getFixedHeader)
+
+// 是否是移动端
+const mobile = computed(() => appStore.getMobile)
+
+// 固定菜单
+const fixedMenu = computed(() => appStore.getFixedMenu)
+
+export const useRenderLayout = () => {
+ const renderClassic = () => {
+ return (
+ <>
+
+ {logo.value ? (
+
+ ) : undefined}
+
+
+
+
+
+
+
+ {tagsView.value ? (
+
+ ) : undefined}
+
+
+
+
+
+ >
+ )
+ }
+
+ const renderTopLeft = () => {
+ return (
+ <>
+
+
+
+
+
+ {tagsView.value ? (
+
+ ) : undefined}
+
+
+
+
+
+ >
+ )
+ }
+
+ const renderTop = () => {
+ return (
+ <>
+
+ {logo.value ? : undefined}
+
+
+
+
+
+ {tagsView.value ? (
+
+ ) : undefined}
+
+
+
+
+ >
+ )
+ }
+
+ const renderCutMenu = () => {
+ return (
+ <>
+
+
+
+
+
+ {tagsView.value ? (
+
+ ) : undefined}
+
+
+
+
+
+ >
+ )
+ }
+
+ return {
+ renderClassic,
+ renderTopLeft,
+ renderTop,
+ renderCutMenu
+ }
+}
diff --git a/marketing-ui/admin-ui/src/locales/en.ts b/marketing-ui/admin-ui/src/locales/en.ts
new file mode 100644
index 0000000..505cfd8
--- /dev/null
+++ b/marketing-ui/admin-ui/src/locales/en.ts
@@ -0,0 +1,460 @@
+export default {
+ common: {
+ inputText: 'Please input',
+ selectText: 'Please select',
+ startTimeText: 'Start time',
+ endTimeText: 'End time',
+ login: 'Login',
+ required: 'This is required',
+ loginOut: 'Login out',
+ document: 'Document',
+ profile: 'User Center',
+ reminder: 'Reminder',
+ loginOutMessage: 'Exit the system?',
+ back: 'Back',
+ ok: 'OK',
+ save: 'Save',
+ cancel: 'Cancel',
+ close: 'Close',
+ reload: 'Reload current',
+ success: 'Success',
+ closeTab: 'Close current',
+ closeTheLeftTab: 'Close left',
+ closeTheRightTab: 'Close right',
+ closeOther: 'Close other',
+ closeAll: 'Close all',
+ prevLabel: 'Prev',
+ nextLabel: 'Next',
+ skipLabel: 'Jump',
+ doneLabel: 'End',
+ menu: 'Menu',
+ menuDes: 'Menu bar rendered in routed structure',
+ collapse: 'Collapse',
+ collapseDes: 'Expand and zoom the menu bar',
+ tagsView: 'Tags view',
+ tagsViewDes: 'Used to record routing history',
+ tool: 'Tool',
+ toolDes: 'Used to set up custom systems',
+ query: 'Query',
+ reset: 'Reset',
+ shrink: 'Put away',
+ expand: 'Expand',
+ confirmTitle: 'System Hint',
+ exportMessage: 'Whether to confirm export data item?',
+ importMessage: 'Whether to confirm import data item?',
+ createSuccess: 'Create Success',
+ updateSuccess: 'Update Success',
+ delMessage: 'Delete the selected data?',
+ delDataMessage: 'Delete the data?',
+ delNoData: 'Please select the data to delete',
+ delSuccess: 'Deleted successfully',
+ index: 'Index',
+ status: 'Status',
+ createTime: 'Create Time',
+ updateTime: 'Update Time',
+ copy: 'Copy',
+ copySuccess: 'Copy Success',
+ copyError: 'Copy Error'
+ },
+ lock: {
+ lockScreen: 'Lock screen',
+ lock: 'Lock',
+ lockPassword: 'Lock screen password',
+ unlock: 'Click to unlock',
+ backToLogin: 'Back to login',
+ entrySystem: 'Entry the system',
+ placeholder: 'Please enter the lock screen password',
+ message: 'Lock screen password error'
+ },
+ error: {
+ noPermission: `Sorry, you don't have permission to access this page.`,
+ pageError: 'Sorry, the page you visited does not exist.',
+ networkError: 'Sorry, the server reported an error.',
+ returnToHome: 'Return to home'
+ },
+ permission: {
+ hasPermission: `Please set the operation permission label value`,
+ hasRole: `Please set the role permission tag value`
+ },
+ setting: {
+ projectSetting: 'Project setting',
+ theme: 'Theme',
+ layout: 'Layout',
+ systemTheme: 'System theme',
+ menuTheme: 'Menu theme',
+ interfaceDisplay: 'Interface display',
+ breadcrumb: 'Breadcrumb',
+ breadcrumbIcon: 'Breadcrumb icon',
+ collapseMenu: 'Collapse menu',
+ hamburgerIcon: 'Hamburger icon',
+ screenfullIcon: 'Screenfull icon',
+ sizeIcon: 'Size icon',
+ localeIcon: 'Locale icon',
+ messageIcon: 'Message icon',
+ tagsView: 'Tags view',
+ logo: 'Logo',
+ greyMode: 'Grey mode',
+ fixedHeader: 'Fixed header',
+ headerTheme: 'Header theme',
+ cutMenu: 'Cut Menu',
+ copy: 'Copy',
+ clearAndReset: 'Clear cache and reset',
+ copySuccess: 'Copy success',
+ copyFailed: 'Copy failed',
+ footer: 'Footer',
+ uniqueOpened: 'Unique opened',
+ tagsViewIcon: 'Tags view icon',
+ reExperienced: 'Please exit the login experience again',
+ fixedMenu: 'Fixed menu'
+ },
+ size: {
+ default: 'Default',
+ large: 'Large',
+ small: 'Small'
+ },
+ login: {
+ welcome: 'Welcome to the system',
+ message: 'Backstage management system',
+ tenantname: 'TenantName',
+ username: 'Username',
+ password: 'Password',
+ code: 'verification code',
+ login: 'Sign in',
+ relogin: 'Sign in again',
+ otherLogin: 'Sign in with',
+ register: 'Register',
+ checkPassword: 'Confirm password',
+ remember: 'Remember me',
+ hasUser: 'Existing account? Go to login',
+ forgetPassword: 'Forget password?',
+ tenantNamePlaceholder: 'Please Enter Tenant Name',
+ usernamePlaceholder: 'Please Enter Username',
+ passwordPlaceholder: 'Please Enter Password',
+ codePlaceholder: 'Please Enter Verification Code',
+ mobileTitle: 'Mobile sign in',
+ mobileNumber: 'Mobile Number',
+ mobileNumberPlaceholder: 'Plaease Enter Mobile Number',
+ backLogin: 'back',
+ getSmsCode: 'Get SMS Code',
+ btnMobile: 'Mobile sign in',
+ btnQRCode: 'QR code sign in',
+ qrcode: 'Scan the QR code to log in',
+ btnRegister: 'Sign up',
+ SmsSendMsg: 'code has been sent',
+ resetPassword: "Reset Password",
+ resetPasswordSuccess: "Reset Password Success",
+ invalidTenantName:"Invalid Tenant Name"
+ },
+ captcha: {
+ verification: 'Please complete security verification',
+ slide: 'Swipe right to complete verification',
+ point: 'Please click',
+ success: 'Verification succeeded',
+ fail: 'verification failed'
+ },
+ router: {
+ login: 'Login',
+ home: 'Home',
+ analysis: 'Analysis',
+ workplace: 'Workplace'
+ },
+ analysis: {
+ newUser: 'New user',
+ unreadInformation: 'Unread information',
+ transactionAmount: 'Transaction amount',
+ totalShopping: 'Total Shopping',
+ monthlySales: 'Monthly sales',
+ userAccessSource: 'User access source',
+ january: 'January',
+ february: 'February',
+ march: 'March',
+ april: 'April',
+ may: 'May',
+ june: 'June',
+ july: 'July',
+ august: 'August',
+ september: 'September',
+ october: 'October',
+ november: 'November',
+ december: 'December',
+ estimate: 'Estimate',
+ actual: 'Actual',
+ directAccess: 'Airect access',
+ mailMarketing: 'Mail marketing',
+ allianceAdvertising: 'Alliance advertising',
+ videoAdvertising: 'Video advertising',
+ searchEngines: 'Search engines',
+ weeklyUserActivity: 'Weekly user activity',
+ activeQuantity: 'Active quantity',
+ monday: 'Monday',
+ tuesday: 'Tuesday',
+ wednesday: 'Wednesday',
+ thursday: 'Thursday',
+ friday: 'Friday',
+ saturday: 'Saturday',
+ sunday: 'Sunday'
+ },
+ workplace: {
+ welcome: 'Hello',
+ happyDay: 'Wish you happy every day!',
+ toady: `It's sunny today`,
+ notice: 'Announcement',
+ project: 'Project',
+ access: 'Project access',
+ toDo: 'To do',
+ introduction: 'A serious introduction',
+ shortcutOperation: 'Quick entry',
+ operation: 'Operation',
+ index: 'Index',
+ personal: 'Personal',
+ team: 'Team',
+ quote: 'Quote',
+ contribution: 'Contribution',
+ hot: 'Hot',
+ yield: 'Yield',
+ dynamic: 'Dynamic',
+ push: 'push',
+ follow: 'Follow'
+ },
+ form: {
+ input: 'Input',
+ inputNumber: 'InputNumber',
+ default: 'Default',
+ icon: 'Icon',
+ mixed: 'Mixed',
+ textarea: 'Textarea',
+ slot: 'Slot',
+ position: 'Position',
+ autocomplete: 'Autocomplete',
+ select: 'Select',
+ selectGroup: 'Select Group',
+ selectV2: 'SelectV2',
+ cascader: 'Cascader',
+ switch: 'Switch',
+ rate: 'Rate',
+ colorPicker: 'Color Picker',
+ transfer: 'Transfer',
+ render: 'Render',
+ radio: 'Radio',
+ button: 'Button',
+ checkbox: 'Checkbox',
+ slider: 'Slider',
+ datePicker: 'Date Picker',
+ shortcuts: 'Shortcuts',
+ today: 'Today',
+ yesterday: 'Yesterday',
+ aWeekAgo: 'A week ago',
+ week: 'Week',
+ year: 'Year',
+ month: 'Month',
+ dates: 'Dates',
+ daterange: 'Date Range',
+ monthrange: 'Month Range',
+ dateTimePicker: 'DateTimePicker',
+ dateTimerange: 'Datetime Range',
+ timePicker: 'Time Picker',
+ timeSelect: 'Time Select',
+ inputPassword: 'input Password',
+ passwordStrength: 'Password Strength',
+ operate: 'operate',
+ change: 'Change',
+ restore: 'Restore',
+ disabled: 'Disabled',
+ disablement: 'Disablement',
+ delete: 'Delete',
+ add: 'Add',
+ setValue: 'Set value',
+ resetValue: 'Reset value',
+ set: 'Set',
+ subitem: 'Subitem',
+ formValidation: 'Form validation',
+ verifyReset: 'Verify reset',
+ remark: 'Remark'
+ },
+ watermark: {
+ watermark: 'Watermark'
+ },
+ table: {
+ table: 'Table',
+ index: 'Index',
+ title: 'Title',
+ author: 'Author',
+ createTime: 'Create time',
+ action: 'Action',
+ pagination: 'pagination',
+ reserveIndex: 'Reserve index',
+ restoreIndex: 'Restore index',
+ showSelections: 'Show selections',
+ hiddenSelections: 'Restore selections',
+ showExpandedRows: 'Show expanded rows',
+ hiddenExpandedRows: 'Hidden expanded rows',
+ header: 'Header'
+ },
+ action: {
+ create: 'Create',
+ add: 'Add',
+ del: 'Delete',
+ delete: 'Delete',
+ edit: 'Edit',
+ update: 'Update',
+ preview: 'Preview',
+ more: 'More',
+ sync: 'Sync',
+ save: 'Save',
+ detail: 'Detail',
+ export: 'Export',
+ import: 'Import',
+ generate: 'Generate',
+ logout: 'Login Out',
+ test: 'Test',
+ typeCreate: 'Dict Type Create',
+ typeUpdate: 'Dict Type Eidt',
+ dataCreate: 'Dict Data Create',
+ dataUpdate: 'Dict Data Eidt',
+ fileUpload: 'File Upload'
+ },
+ dialog: {
+ dialog: 'Dialog',
+ open: 'Open',
+ close: 'Close'
+ },
+ sys: {
+ api: {
+ operationFailed: 'Operation failed',
+ errorTip: 'Error Tip',
+ errorMessage: 'The operation failed, the system is abnormal!',
+ timeoutMessage: 'Login timed out, please log in again!',
+ apiTimeoutMessage: 'The interface request timed out, please refresh the page and try again!',
+ apiRequestFailed: 'The interface request failed, please try again later!',
+ networkException: 'network anomaly',
+ networkExceptionMsg:
+ 'Please check if your network connection is normal! The network is abnormal',
+
+ errMsg401: 'The user does not have permission (token, user name, password error)!',
+ errMsg403: 'The user is authorized, but access is forbidden!',
+ errMsg404: 'Network request error, the resource was not found!',
+ errMsg405: 'Network request error, request method not allowed!',
+ errMsg408: 'Network request timed out!',
+ errMsg500: 'Server error, please contact the administrator!',
+ errMsg501: 'The network is not implemented!',
+ errMsg502: 'Network Error!',
+ errMsg503: 'The service is unavailable, the server is temporarily overloaded or maintained!',
+ errMsg504: 'Network timeout!',
+ errMsg505: 'The http version does not support the request!',
+ errMsg901: 'Demo mode, no write operations are possible!'
+ },
+ app: {
+ logoutTip: 'Reminder',
+ logoutMessage: 'Confirm to exit the system?',
+ menuLoading: 'Menu loading...'
+ },
+ exception: {
+ backLogin: 'Back Login',
+ backHome: 'Back Home',
+ subTitle403: "Sorry, you don't have access to this page.",
+ subTitle404: 'Sorry, the page you visited does not exist.',
+ subTitle500: 'Sorry, the server is reporting an error.',
+ noDataTitle: 'No data on the current page.',
+ networkErrorTitle: 'Network Error',
+ networkErrorSubTitle:
+ 'Sorry, Your network connection has been disconnected, please check your network!'
+ },
+ lock: {
+ unlock: 'Click to unlock',
+ alert: 'Lock screen password error',
+ backToLogin: 'Back to login',
+ entry: 'Enter the system',
+ placeholder: 'Please enter the lock screen password or user password'
+ },
+ login: {
+ backSignIn: 'Back sign in',
+ mobileSignInFormTitle: 'Mobile sign in',
+ qrSignInFormTitle: 'Qr code sign in',
+ signInFormTitle: 'Sign in',
+ signUpFormTitle: 'Sign up',
+ forgetFormTitle: 'Reset password',
+
+ signInTitle: 'Backstage management system',
+ signInDesc: 'Enter your personal details and get started!',
+ policy: 'I agree to the xxx Privacy Policy',
+ scanSign: `scanning the code to complete the login`,
+
+ loginButton: 'Sign in',
+ registerButton: 'Sign up',
+ rememberMe: 'Remember me',
+ forgetPassword: 'Forget Password?',
+ otherSignIn: 'Sign in with',
+
+ // notify
+ loginSuccessTitle: 'Login successful',
+ loginSuccessDesc: 'Welcome back',
+
+ // placeholder
+ accountPlaceholder: 'Please input username',
+ passwordPlaceholder: 'Please input password',
+ smsPlaceholder: 'Please input sms code',
+ mobilePlaceholder: 'Please input mobile',
+ policyPlaceholder: 'Register after checking',
+ diffPwd: 'The two passwords are inconsistent',
+
+ userName: 'Username',
+ password: 'Password',
+ confirmPassword: 'Confirm Password',
+ email: 'Email',
+ smsCode: 'SMS code',
+ mobile: 'Mobile'
+ }
+ },
+ profile: {
+ user: {
+ title: 'Personal Information',
+ username: 'User Name',
+ nickname: 'Nick Name',
+ mobile: 'Phone Number',
+ email: 'User Mail',
+ dept: 'Department',
+ posts: 'Position',
+ roles: 'Own Role',
+ sex: 'Sex',
+ man: 'Man',
+ woman: 'Woman',
+ createTime: 'Created Date'
+ },
+ info: {
+ title: 'Basic Information',
+ basicInfo: 'Basic Information',
+ resetPwd: 'Reset Password',
+ userSocial: 'Social Information'
+ },
+ rules: {
+ nickname: 'Please Enter User Nickname',
+ mail: 'Please Input The Email Address',
+ truemail: 'Please Input The Correct Email Address',
+ phone: 'Please Enter The Phone Number',
+ truephone: 'Please Enter The Correct Phone Number'
+ },
+ password: {
+ oldPassword: 'Old PassWord',
+ newPassword: 'New Password',
+ confirmPassword: 'Confirm Password',
+ oldPwdMsg: 'Please Enter Old Password',
+ newPwdMsg: 'Please Enter New Password',
+ cfPwdMsg: 'Please Enter Confirm Password',
+ diffPwd: 'The Passwords Entered Twice No Match'
+ }
+ },
+ cropper: {
+ selectImage: 'Select Image',
+ uploadSuccess: 'Uploaded success!',
+ modalTitle: 'Avatar upload',
+ okText: 'Confirm and upload',
+ btn_reset: 'Reset',
+ btn_rotate_left: 'Counterclockwise rotation',
+ btn_rotate_right: 'Clockwise rotation',
+ btn_scale_x: 'Flip horizontal',
+ btn_scale_y: 'Flip vertical',
+ btn_zoom_in: 'Zoom in',
+ btn_zoom_out: 'Zoom out',
+ preview: 'Preivew'
+ }
+}
diff --git a/marketing-ui/admin-ui/src/locales/zh-CN.ts b/marketing-ui/admin-ui/src/locales/zh-CN.ts
new file mode 100644
index 0000000..130d565
--- /dev/null
+++ b/marketing-ui/admin-ui/src/locales/zh-CN.ts
@@ -0,0 +1,456 @@
+export default {
+ common: {
+ inputText: '请输入',
+ selectText: '请选择',
+ startTimeText: '开始时间',
+ endTimeText: '结束时间',
+ login: '登录',
+ required: '该项为必填项',
+ loginOut: '退出系统',
+ document: '项目文档',
+ profile: '个人中心',
+ reminder: '温馨提示',
+ loginOutMessage: '是否退出本系统?',
+ back: '返回',
+ ok: '确定',
+ save: '保存',
+ cancel: '取消',
+ close: '关闭',
+ reload: '重新加载',
+ success: '成功',
+ closeTab: '关闭标签页',
+ closeTheLeftTab: '关闭左侧标签页',
+ closeTheRightTab: '关闭右侧标签页',
+ closeOther: '关闭其他标签页',
+ closeAll: '关闭全部标签页',
+ prevLabel: '上一步',
+ nextLabel: '下一步',
+ skipLabel: '跳过',
+ doneLabel: '结束',
+ menu: '菜单',
+ menuDes: '以路由的结构渲染的菜单栏',
+ collapse: '展开缩收',
+ collapseDes: '展开和缩放菜单栏',
+ tagsView: '标签页',
+ tagsViewDes: '用于记录路由历史记录',
+ tool: '工具',
+ toolDes: '用于设置定制系统',
+ query: '查询',
+ reset: '重置',
+ shrink: '收起',
+ expand: '展开',
+ confirmTitle: '系统提示',
+ exportMessage: '是否确认导出数据项?',
+ importMessage: '是否确认导入数据项?',
+ createSuccess: '新增成功',
+ updateSuccess: '修改成功',
+ delMessage: '是否删除所选中数据?',
+ delDataMessage: '是否删除数据?',
+ delNoData: '请选择需要删除的数据',
+ delSuccess: '删除成功',
+ index: '序号',
+ status: '状态',
+ createTime: '创建时间',
+ updateTime: '更新时间',
+ copy: '复制',
+ copySuccess: '复制成功',
+ copyError: '复制失败'
+ },
+ lock: {
+ lockScreen: '锁定屏幕',
+ lock: '锁定',
+ lockPassword: '锁屏密码',
+ unlock: '点击解锁',
+ backToLogin: '返回登录',
+ entrySystem: '进入系统',
+ placeholder: '请输入锁屏密码',
+ message: '锁屏密码错误'
+ },
+ error: {
+ noPermission: `抱歉,您无权访问此页面。`,
+ pageError: '抱歉,您访问的页面不存在。',
+ networkError: '抱歉,服务器报告错误。',
+ returnToHome: '返回首页'
+ },
+ permission: {
+ hasPermission: `请设置操作权限标签值`,
+ hasRole: `请设置角色权限标签值`
+ },
+ setting: {
+ projectSetting: '项目配置',
+ theme: '主题',
+ layout: '布局',
+ systemTheme: '系统主题',
+ menuTheme: '菜单主题',
+ interfaceDisplay: '界面显示',
+ breadcrumb: '面包屑',
+ breadcrumbIcon: '面包屑图标',
+ collapseMenu: '折叠菜单',
+ hamburgerIcon: '折叠图标',
+ screenfullIcon: '全屏图标',
+ sizeIcon: '尺寸图标',
+ localeIcon: '多语言图标',
+ messageIcon: '消息图标',
+ tagsView: '标签页',
+ tagsViewImmerse: '标签页沉浸',
+ logo: '标志',
+ greyMode: '灰色模式',
+ fixedHeader: '固定头部',
+ headerTheme: '头部主题',
+ cutMenu: '切割菜单',
+ copy: '拷贝',
+ clearAndReset: '清除缓存并且重置',
+ copySuccess: '拷贝成功',
+ copyFailed: '拷贝失败',
+ footer: '页脚',
+ uniqueOpened: '菜单手风琴',
+ tagsViewIcon: '标签页图标',
+ reExperienced: '请重新退出登录体验',
+ fixedMenu: '固定菜单'
+ },
+ size: {
+ default: '默认',
+ large: '大',
+ small: '小'
+ },
+ login: {
+ welcome: '欢迎使用本系统',
+ message: '开箱即用的中后台管理系统',
+ tenantname: '租户名称',
+ username: '用户名',
+ password: '密码',
+ code: '验证码',
+ login: '登录',
+ relogin: '重新登录',
+ otherLogin: '其他登录方式',
+ register: '注册',
+ checkPassword: '确认密码',
+ remember: '记住我',
+ hasUser: '已有账号?去登录',
+ forgetPassword: '忘记密码?',
+ tenantNamePlaceholder: '请输入租户名称',
+ usernamePlaceholder: '请输入用户名',
+ passwordPlaceholder: '请输入密码',
+ codePlaceholder: '请输入验证码',
+ mobileTitle: '手机登录',
+ mobileNumber: '手机号码',
+ mobileNumberPlaceholder: '请输入手机号码',
+ backLogin: '返回',
+ getSmsCode: '获取验证码',
+ btnMobile: '手机登录',
+ btnQRCode: '二维码登录',
+ qrcode: '扫描二维码登录',
+ btnRegister: '注册',
+ SmsSendMsg: '验证码已发送',
+ resetPassword: "重置密码",
+ resetPasswordSuccess: "重置密码成功",
+ invalidTenantName: "无效的租户名称"
+ },
+ captcha: {
+ verification: '请完成安全验证',
+ slide: '向右滑动完成验证',
+ point: '请依次点击',
+ success: '验证成功',
+ fail: '验证失败'
+ },
+ router: {
+ login: '登录',
+ socialLogin: '社交登录',
+ home: '首页',
+ analysis: '分析页',
+ workplace: '工作台'
+ },
+ analysis: {
+ newUser: '新增用户',
+ unreadInformation: '未读消息',
+ transactionAmount: '成交金额',
+ totalShopping: '购物总量',
+ monthlySales: '每月销售额',
+ userAccessSource: '用户访问来源',
+ january: '一月',
+ february: '二月',
+ march: '三月',
+ april: '四月',
+ may: '五月',
+ june: '六月',
+ july: '七月',
+ august: '八月',
+ september: '九月',
+ october: '十月',
+ november: '十一月',
+ december: '十二月',
+ estimate: '预计',
+ actual: '实际',
+ directAccess: '直接访问',
+ mailMarketing: '邮件营销',
+ allianceAdvertising: '联盟广告',
+ videoAdvertising: '视频广告',
+ searchEngines: '搜索引擎',
+ weeklyUserActivity: '每周用户活跃量',
+ activeQuantity: '活跃量',
+ monday: '周一',
+ tuesday: '周二',
+ wednesday: '周三',
+ thursday: '周四',
+ friday: '周五',
+ saturday: '周六',
+ sunday: '周日'
+ },
+ workplace: {
+ welcome: '你好',
+ happyDay: '祝你开心每一天!',
+ toady: '今日晴',
+ notice: '通知公告',
+ project: '项目数',
+ access: '项目访问',
+ toDo: '待办',
+ introduction: '一个正经的简介',
+ shortcutOperation: '快捷入口',
+ operation: '操作',
+ index: '指数',
+ personal: '个人',
+ team: '团队',
+ quote: '引用',
+ contribution: '贡献',
+ hot: '热度',
+ yield: '产量',
+ dynamic: '动态',
+ push: '推送',
+ follow: '关注'
+ },
+ form: {
+ input: '输入框',
+ inputNumber: '数字输入框',
+ default: '默认',
+ icon: '图标',
+ mixed: '复合型',
+ textarea: '多行文本',
+ slot: '插槽',
+ position: '位置',
+ autocomplete: '自动补全',
+ select: '选择器',
+ selectGroup: '选项分组',
+ selectV2: '虚拟列表选择器',
+ cascader: '级联选择器',
+ switch: '开关',
+ rate: '评分',
+ colorPicker: '颜色选择器',
+ transfer: '穿梭框',
+ render: '渲染器',
+ radio: '单选框',
+ button: '按钮',
+ checkbox: '多选框',
+ slider: '滑块',
+ datePicker: '日期选择器',
+ shortcuts: '快捷选项',
+ today: '今天',
+ yesterday: '昨天',
+ aWeekAgo: '一周前',
+ week: '周',
+ year: '年',
+ month: '月',
+ dates: '日期',
+ daterange: '日期范围',
+ monthrange: '月份范围',
+ dateTimePicker: '日期时间选择器',
+ dateTimerange: '日期时间范围',
+ timePicker: '时间选择器',
+ timeSelect: '时间选择',
+ inputPassword: '密码输入框',
+ passwordStrength: '密码强度',
+ operate: '操作',
+ change: '更改',
+ restore: '还原',
+ disabled: '禁用',
+ disablement: '解除禁用',
+ delete: '删除',
+ add: '添加',
+ setValue: '设置值',
+ resetValue: '重置值',
+ set: '设置',
+ subitem: '子项',
+ formValidation: '表单验证',
+ verifyReset: '验证重置',
+ remark: '备注'
+ },
+ watermark: {
+ watermark: '水印'
+ },
+ table: {
+ table: '表格',
+ index: '序号',
+ title: '标题',
+ author: '作者',
+ createTime: '创建时间',
+ action: '操作',
+ pagination: '分页',
+ reserveIndex: '叠加序号',
+ restoreIndex: '还原序号',
+ showSelections: '显示多选',
+ hiddenSelections: '隐藏多选',
+ showExpandedRows: '显示展开行',
+ hiddenExpandedRows: '隐藏展开行',
+ header: '头部'
+ },
+ action: {
+ create: '新增',
+ add: '新增',
+ del: '删除',
+ delete: '删除',
+ edit: '编辑',
+ update: '编辑',
+ preview: '预览',
+ more: '更多',
+ sync: '同步',
+ save: '保存',
+ detail: '详情',
+ export: '导出',
+ import: '导入',
+ generate: '生成',
+ logout: '强制退出',
+ test: '测试',
+ typeCreate: '字典类型新增',
+ typeUpdate: '字典类型编辑',
+ dataCreate: '字典数据新增',
+ dataUpdate: '字典数据编辑'
+ },
+ dialog: {
+ dialog: '弹窗',
+ open: '打开',
+ close: '关闭'
+ },
+ sys: {
+ api: {
+ operationFailed: '操作失败',
+ errorTip: '错误提示',
+ errorMessage: '操作失败,系统异常!',
+ timeoutMessage: '登录超时,请重新登录!',
+ apiTimeoutMessage: '接口请求超时,请刷新页面重试!',
+ apiRequestFailed: '请求出错,请稍候重试',
+ networkException: '网络异常',
+ networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!',
+ errMsg401: '用户没有权限(令牌、用户名、密码错误)!',
+ errMsg403: '用户得到授权,但是访问是被禁止的。!',
+ errMsg404: '网络请求错误,未找到该资源!',
+ errMsg405: '网络请求错误,请求方法未允许!',
+ errMsg408: '网络请求超时!',
+ errMsg500: '服务器错误,请联系管理员!',
+ errMsg501: '网络未实现!',
+ errMsg502: '网络错误!',
+ errMsg503: '服务不可用,服务器暂时过载或维护!',
+ errMsg504: '网络超时!',
+ errMsg505: 'http版本不支持该请求!',
+ errMsg901: '演示模式,无法进行写操作!'
+ },
+ app: {
+ logoutTip: '温馨提醒',
+ logoutMessage: '是否确认退出系统?',
+ menuLoading: '菜单加载中...'
+ },
+ exception: {
+ backLogin: '返回登录',
+ backHome: '返回首页',
+ subTitle403: '抱歉,您无权访问此页面。',
+ subTitle404: '抱歉,您访问的页面不存在。',
+ subTitle500: '抱歉,服务器报告错误。',
+ noDataTitle: '当前页无数据',
+ networkErrorTitle: '网络错误',
+ networkErrorSubTitle: '抱歉,您的网络连接已断开,请检查您的网络!'
+ },
+ lock: {
+ unlock: '点击解锁',
+ alert: '锁屏密码错误',
+ backToLogin: '返回登录',
+ entry: '进入系统',
+ placeholder: '请输入锁屏密码或者用户密码'
+ },
+ login: {
+ backSignIn: '返回',
+ signInFormTitle: '登录',
+ ssoFormTitle: '三方授权',
+ mobileSignInFormTitle: '手机登录',
+ qrSignInFormTitle: '二维码登录',
+ signUpFormTitle: '注册',
+ forgetFormTitle: '重置密码',
+ signInTitle: '开箱即用的中后台管理系统',
+ signInDesc: '输入您的个人详细信息开始使用!',
+ policy: '我同意xxx隐私政策',
+ scanSign: `扫码后点击"确认",即可完成登录`,
+ loginButton: '登录',
+ registerButton: '注册',
+ rememberMe: '记住我',
+ forgetPassword: '忘记密码?',
+ otherSignIn: '其他登录方式',
+ // notify
+ loginSuccessTitle: '登录成功',
+ loginSuccessDesc: '欢迎回来',
+ // placeholder
+ accountPlaceholder: '请输入账号',
+ passwordPlaceholder: '请输入密码',
+ smsPlaceholder: '请输入验证码',
+ mobilePlaceholder: '请输入手机号码',
+ policyPlaceholder: '勾选后才能注册',
+ diffPwd: '两次输入密码不一致',
+ userName: '账号',
+ password: '密码',
+ confirmPassword: '确认密码',
+ email: '邮箱',
+ smsCode: '短信验证码',
+ mobile: '手机号码'
+ }
+ },
+ profile: {
+ user: {
+ title: '个人信息',
+ username: '用户名称',
+ nickname: '用户昵称',
+ mobile: '手机号码',
+ email: '用户邮箱',
+ dept: '所属部门',
+ posts: '所属岗位',
+ roles: '所属角色',
+ sex: '性别',
+ man: '男',
+ woman: '女',
+ createTime: '创建日期'
+ },
+ info: {
+ title: '基本信息',
+ basicInfo: '基本资料',
+ resetPwd: '修改密码',
+ userSocial: '社交信息'
+ },
+ rules: {
+ nickname: '请输入用户昵称',
+ mail: '请输入邮箱地址',
+ truemail: '请输入正确的邮箱地址',
+ phone: '请输入正确的手机号码',
+ truephone: '请输入正确的手机号码'
+ },
+ password: {
+ oldPassword: '旧密码',
+ newPassword: '新密码',
+ confirmPassword: '确认密码',
+ oldPwdMsg: '请输入旧密码',
+ newPwdMsg: '请输入新密码',
+ cfPwdMsg: '请输入确认密码',
+ pwdRules: '长度在 6 到 20 个字符',
+ diffPwd: '两次输入密码不一致'
+ }
+ },
+ cropper: {
+ selectImage: '选择图片',
+ uploadSuccess: '上传成功',
+ modalTitle: '头像上传',
+ okText: '确认并上传',
+ btn_reset: '重置',
+ btn_rotate_left: '逆时针旋转',
+ btn_rotate_right: '顺时针旋转',
+ btn_scale_x: '水平翻转',
+ btn_scale_y: '垂直翻转',
+ btn_zoom_in: '放大',
+ btn_zoom_out: '缩小',
+ preview: '预览'
+ },
+ 'OAuth 2.0': 'OAuth 2.0' // 避免菜单名是 OAuth 2.0 时,一直 warn 报错
+}
diff --git a/marketing-ui/admin-ui/src/main.ts b/marketing-ui/admin-ui/src/main.ts
new file mode 100644
index 0000000..874f766
--- /dev/null
+++ b/marketing-ui/admin-ui/src/main.ts
@@ -0,0 +1,74 @@
+// 引入unocss css
+import '@/plugins/unocss'
+
+// 导入全局的svg图标
+import '@/plugins/svgIcon'
+
+// 初始化多语言
+import { setupI18n } from '@/plugins/vueI18n'
+
+// 引入状态管理
+import { setupStore } from '@/store'
+
+// 全局组件
+import { setupGlobCom } from '@/components'
+
+// 引入 element-plus
+import { setupElementPlus } from '@/plugins/elementPlus'
+
+// 引入 form-create
+import { setupFormCreate } from '@/plugins/formCreate'
+
+// 引入全局样式
+import '@/styles/index.scss'
+
+// 引入动画
+import '@/plugins/animate.css'
+
+// 路由
+import router, { setupRouter } from '@/router'
+
+// 指令
+import { setupAuth, setupMountedFocus } from '@/directives'
+
+import { createApp } from 'vue'
+
+import App from './App.vue'
+
+import './permission'
+
+import '@/plugins/tongji' // 百度统计
+import Logger from '@/utils/Logger'
+
+import VueDOMPurifyHTML from 'vue-dompurify-html' // 解决v-html 的安全隐患
+
+// 创建实例
+const setupAll = async () => {
+ const app = createApp(App)
+
+ await setupI18n(app)
+
+ setupStore(app)
+
+ setupGlobCom(app)
+
+ setupElementPlus(app)
+
+ setupFormCreate(app)
+
+ setupRouter(app)
+
+ // directives 指令
+ setupAuth(app)
+ setupMountedFocus(app)
+
+ await router.isReady()
+
+ app.use(VueDOMPurifyHTML)
+
+ app.mount('#app')
+}
+
+setupAll()
+
+Logger.prettyPrimary(`欢迎使用`, import.meta.env.VITE_APP_TITLE)
diff --git a/marketing-ui/admin-ui/src/permission.ts b/marketing-ui/admin-ui/src/permission.ts
new file mode 100644
index 0000000..b04bc3c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/permission.ts
@@ -0,0 +1,106 @@
+import router from './router'
+import type { RouteRecordRaw } from 'vue-router'
+import { isRelogin } from '@/config/axios/service'
+import { getAccessToken } from '@/utils/auth'
+import { useTitle } from '@/hooks/web/useTitle'
+import { useNProgress } from '@/hooks/web/useNProgress'
+import { usePageLoading } from '@/hooks/web/usePageLoading'
+import { useDictStoreWithOut } from '@/store/modules/dict'
+import { useUserStoreWithOut } from '@/store/modules/user'
+import { usePermissionStoreWithOut } from '@/store/modules/permission'
+
+const { start, done } = useNProgress()
+
+const { loadStart, loadDone } = usePageLoading()
+
+const parseURL = (
+ url: string | null | undefined
+): { basePath: string; paramsObject: { [key: string]: string } } => {
+ // 如果输入为 null 或 undefined,返回空字符串和空对象
+ if (url == null) {
+ return { basePath: '', paramsObject: {} }
+ }
+
+ // 找到问号 (?) 的位置,它之前是基础路径,之后是查询参数
+ const questionMarkIndex = url.indexOf('?')
+ let basePath = url
+ const paramsObject: { [key: string]: string } = {}
+
+ // 如果找到了问号,说明有查询参数
+ if (questionMarkIndex !== -1) {
+ // 获取 basePath
+ basePath = url.substring(0, questionMarkIndex)
+
+ // 从 URL 中获取查询字符串部分
+ const queryString = url.substring(questionMarkIndex + 1)
+
+ // 使用 URLSearchParams 遍历参数
+ const searchParams = new URLSearchParams(queryString)
+ searchParams.forEach((value, key) => {
+ // 封装进 paramsObject 对象
+ paramsObject[key] = value
+ })
+ }
+
+ // 返回 basePath 和 paramsObject
+ return { basePath, paramsObject }
+}
+
+// 路由不重定向白名单
+const whiteList = [
+ '/login',
+ '/social-login',
+ '/auth-redirect',
+ '/bind',
+ '/register',
+ '/oauthLogin/gitee'
+]
+
+// 路由加载前
+router.beforeEach(async (to, from, next) => {
+ start()
+ loadStart()
+ if (getAccessToken()) {
+ if (to.path === '/login') {
+ next({ path: '/' })
+ } else {
+ // 获取所有字典
+ const dictStore = useDictStoreWithOut()
+ const userStore = useUserStoreWithOut()
+ const permissionStore = usePermissionStoreWithOut()
+ if (!dictStore.getIsSetDict) {
+ await dictStore.setDictMap()
+ }
+ if (!userStore.getIsSetUser) {
+ isRelogin.show = true
+ await userStore.setUserInfoAction()
+ isRelogin.show = false
+ // 后端过滤菜单
+ await permissionStore.generateRoutes()
+ permissionStore.getAddRouters.forEach((route) => {
+ router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表
+ })
+ const redirectPath = from.query.redirect || to.path
+ // 修复跳转时不带参数的问题
+ const redirect = decodeURIComponent(redirectPath as string)
+ const { paramsObject: query } = parseURL(redirect)
+ const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect, query }
+ next(nextData)
+ } else {
+ next()
+ }
+ }
+ } else {
+ if (whiteList.indexOf(to.path) !== -1) {
+ next()
+ } else {
+ next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
+ }
+ }
+})
+
+router.afterEach((to) => {
+ useTitle(to?.meta?.title as string)
+ done() // 结束Progress
+ loadDone()
+})
diff --git a/marketing-ui/admin-ui/src/plugins/animate.css/index.ts b/marketing-ui/admin-ui/src/plugins/animate.css/index.ts
new file mode 100644
index 0000000..3e93451
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/animate.css/index.ts
@@ -0,0 +1 @@
+import 'animate.css'
diff --git a/marketing-ui/admin-ui/src/plugins/echarts/index.ts b/marketing-ui/admin-ui/src/plugins/echarts/index.ts
new file mode 100644
index 0000000..18d05aa
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/echarts/index.ts
@@ -0,0 +1,49 @@
+import * as echarts from 'echarts/core'
+
+import {
+ BarChart,
+ FunnelChart,
+ GaugeChart,
+ LineChart,
+ MapChart,
+ PictorialBarChart,
+ PieChart,
+ RadarChart
+} from 'echarts/charts'
+
+import {
+ AriaComponent,
+ GridComponent,
+ LegendComponent,
+ ParallelComponent,
+ PolarComponent,
+ TitleComponent,
+ ToolboxComponent,
+ TooltipComponent,
+ VisualMapComponent
+} from 'echarts/components'
+
+import { CanvasRenderer } from 'echarts/renderers'
+
+echarts.use([
+ LegendComponent,
+ TitleComponent,
+ TooltipComponent,
+ ToolboxComponent,
+ GridComponent,
+ PolarComponent,
+ AriaComponent,
+ ParallelComponent,
+ VisualMapComponent,
+ BarChart,
+ LineChart,
+ PieChart,
+ MapChart,
+ CanvasRenderer,
+ PictorialBarChart,
+ RadarChart,
+ GaugeChart,
+ FunnelChart
+])
+
+export default echarts
diff --git a/marketing-ui/admin-ui/src/plugins/elementPlus/index.ts b/marketing-ui/admin-ui/src/plugins/elementPlus/index.ts
new file mode 100644
index 0000000..0ae2a8b
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/elementPlus/index.ts
@@ -0,0 +1,17 @@
+import type { App } from 'vue'
+// 需要全局引入一些组件,如ElScrollbar,不然一些下拉项样式有问题
+import { ElLoading, ElScrollbar, ElButton } from 'element-plus'
+
+const plugins = [ElLoading]
+
+const components = [ElScrollbar, ElButton]
+
+export const setupElementPlus = (app: App) => {
+ plugins.forEach((plugin) => {
+ app.use(plugin)
+ })
+
+ components.forEach((component) => {
+ app.component(component.name, component)
+ })
+}
diff --git a/marketing-ui/admin-ui/src/plugins/formCreate/index.ts b/marketing-ui/admin-ui/src/plugins/formCreate/index.ts
new file mode 100644
index 0000000..07d2c51
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/formCreate/index.ts
@@ -0,0 +1,133 @@
+import type { App } from 'vue'
+// 👇使用 form-create 需额外全局引入 element plus 组件
+import {
+ // ElAutocomplete,
+ // ElButton,
+ // ElCascader,
+ // ElCheckbox,
+ // ElCheckboxButton,
+ // ElCheckboxGroup,
+ // ElCol,
+ // ElColorPicker,
+ // ElDatePicker,
+ // ElDialog,
+ // ElForm,
+ // ElInput,
+ // ElInputNumber,
+ // ElPopover,
+ // ElRadio,
+ // ElRadioButton,
+ // ElRadioGroup,
+ // ElRate,
+ // ElRow,
+ // ElSelect,
+ // ElSlider,
+ // ElSwitch,
+ // ElTimePicker,
+ // ElTooltip,
+ // ElTree,
+ // ElUpload,
+ // ElIcon,
+ // ElProgress,
+ // 以上会由 @form-create/element-ui/auto-import 自动引入
+ ElAlert,
+ ElTransfer,
+ ElAside,
+ ElContainer,
+ ElDivider,
+ ElHeader,
+ ElMain,
+ ElPopconfirm,
+ ElTable,
+ ElTableColumn,
+ ElTabPane,
+ ElTabs,
+ ElDropdown,
+ ElDropdownMenu,
+ ElDropdownItem,
+ ElBadge,
+ ElTag,
+ ElText,
+ ElMenu,
+ ElMenuItem,
+ ElFooter,
+ ElMessage,
+ ElCollapse,
+ ElCollapseItem,
+ ElCard,
+ // ElFormItem,
+ // ElOption
+} from 'element-plus'
+import FcDesigner from '@form-create/designer'
+import formCreate from '@form-create/element-ui'
+import install from '@form-create/element-ui/auto-import'
+
+//======================= 自定义组件 =======================
+import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
+import { useApiSelect } from '@/components/FormCreate'
+import { Editor } from '@/components/Editor'
+import DictSelect from '@/components/FormCreate/src/components/DictSelect.vue'
+
+const UserSelect = useApiSelect({
+ name: 'UserSelect',
+ labelField: 'nickname',
+ valueField: 'id',
+ url: '/system/user/simple-list'
+})
+const DeptSelect = useApiSelect({
+ name: 'DeptSelect',
+ labelField: 'name',
+ valueField: 'id',
+ url: '/system/dept/simple-list'
+})
+const ApiSelect = useApiSelect({
+ name: 'ApiSelect'
+})
+
+const components = [
+ ElAlert,
+ ElTransfer,
+ ElAside,
+ ElContainer,
+ ElDivider,
+ ElHeader,
+ ElMain,
+ ElPopconfirm,
+ ElTable,
+ ElTableColumn,
+ ElTabPane,
+ ElTabs,
+ ElDropdown,
+ ElDropdownMenu,
+ ElDropdownItem,
+ ElBadge,
+ ElTag,
+ ElText,
+ ElMenu,
+ ElMenuItem,
+ ElFooter,
+ ElMessage,
+ // ElFormItem,
+ // ElOption,
+ UploadImg,
+ UploadImgs,
+ UploadFile,
+ DictSelect,
+ UserSelect,
+ DeptSelect,
+ ApiSelect,
+ Editor,
+ ElCollapse,
+ ElCollapseItem,
+ ElCard,
+]
+
+// 参考 http://www.form-create.com/v3/element-ui/auto-import.html 文档
+export const setupFormCreate = (app: App) => {
+ components.forEach((component) => {
+ app.component(component.name, component)
+ })
+ formCreate.use(install)
+ app.use(formCreate)
+ app.use(FcDesigner)
+}
diff --git a/marketing-ui/admin-ui/src/plugins/svgIcon/index.ts b/marketing-ui/admin-ui/src/plugins/svgIcon/index.ts
new file mode 100644
index 0000000..b5b7f70
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/svgIcon/index.ts
@@ -0,0 +1,3 @@
+import 'virtual:svg-icons-register'
+
+import '@purge-icons/generated'
diff --git a/marketing-ui/admin-ui/src/plugins/tongji/index.ts b/marketing-ui/admin-ui/src/plugins/tongji/index.ts
new file mode 100644
index 0000000..ec261a1
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/tongji/index.ts
@@ -0,0 +1,23 @@
+import router from '@/router'
+
+// 用于 router push
+window._hmt = window._hmt || []
+// HM_ID
+const HM_ID = import.meta.env.VITE_APP_BAIDU_CODE
+;(function () {
+ // 有值的时候,才开启
+ if (!HM_ID) {
+ return
+ }
+ const hm = document.createElement('script')
+ hm.src = 'https://hm.baidu.com/hm.js?' + HM_ID
+ const s = document.getElementsByTagName('script')[0]
+ s.parentNode.insertBefore(hm, s)
+})()
+
+router.afterEach(function (to) {
+ if (!HM_ID) {
+ return
+ }
+ _hmt.push(['_trackPageview', to.fullPath])
+})
diff --git a/marketing-ui/admin-ui/src/plugins/unocss/index.ts b/marketing-ui/admin-ui/src/plugins/unocss/index.ts
new file mode 100644
index 0000000..d366b5a
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/unocss/index.ts
@@ -0,0 +1 @@
+import 'virtual:uno.css'
diff --git a/marketing-ui/admin-ui/src/plugins/vueI18n/helper.ts b/marketing-ui/admin-ui/src/plugins/vueI18n/helper.ts
new file mode 100644
index 0000000..da6bc8c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/vueI18n/helper.ts
@@ -0,0 +1,3 @@
+export const setHtmlPageLang = (locale: LocaleType) => {
+ document.querySelector('html')?.setAttribute('lang', locale)
+}
diff --git a/marketing-ui/admin-ui/src/plugins/vueI18n/index.ts b/marketing-ui/admin-ui/src/plugins/vueI18n/index.ts
new file mode 100644
index 0000000..f845b13
--- /dev/null
+++ b/marketing-ui/admin-ui/src/plugins/vueI18n/index.ts
@@ -0,0 +1,42 @@
+import type { App } from 'vue'
+import { createI18n } from 'vue-i18n'
+import { useLocaleStoreWithOut } from '@/store/modules/locale'
+import type { I18n, I18nOptions } from 'vue-i18n'
+import { setHtmlPageLang } from './helper'
+
+export let i18n: ReturnType
+
+const createI18nOptions = async (): Promise => {
+ const localeStore = useLocaleStoreWithOut()
+ const locale = localeStore.getCurrentLocale
+ const localeMap = localeStore.getLocaleMap
+ const defaultLocal = await import(`../../locales/${locale.lang}.ts`)
+ const message = defaultLocal.default ?? {}
+
+ setHtmlPageLang(locale.lang)
+
+ localeStore.setCurrentLocale({
+ lang: locale.lang
+ // elLocale: elLocal
+ })
+
+ return {
+ legacy: false,
+ locale: locale.lang,
+ fallbackLocale: locale.lang,
+ messages: {
+ [locale.lang]: message
+ },
+ availableLocales: localeMap.map((v) => v.lang),
+ sync: true,
+ silentTranslationWarn: true,
+ missingWarn: false,
+ silentFallbackWarn: true
+ }
+}
+
+export const setupI18n = async (app: App) => {
+ const options = await createI18nOptions()
+ i18n = createI18n(options) as I18n
+ app.use(i18n)
+}
diff --git a/marketing-ui/admin-ui/src/router/index.ts b/marketing-ui/admin-ui/src/router/index.ts
new file mode 100644
index 0000000..b818421
--- /dev/null
+++ b/marketing-ui/admin-ui/src/router/index.ts
@@ -0,0 +1,28 @@
+import type { App } from 'vue'
+import type { RouteRecordRaw } from 'vue-router'
+import { createRouter, createWebHistory } from 'vue-router'
+import remainingRouter from './modules/remaining'
+
+// 创建路由实例
+const router = createRouter({
+ history: createWebHistory(import.meta.env.VITE_BASE_PATH), // createWebHashHistory URL带#,createWebHistory URL不带#
+ strict: true,
+ routes: remainingRouter as RouteRecordRaw[],
+ scrollBehavior: () => ({ left: 0, top: 0 })
+})
+
+export const resetRouter = (): void => {
+ const resetWhiteNameList = ['Redirect', 'Login', 'NoFind', 'Root']
+ router.getRoutes().forEach((route) => {
+ const { name } = route
+ if (name && !resetWhiteNameList.includes(name as string)) {
+ router.hasRoute(name) && router.removeRoute(name)
+ }
+ })
+}
+
+export const setupRouter = (app: App) => {
+ app.use(router)
+}
+
+export default router
diff --git a/marketing-ui/admin-ui/src/router/modules/remaining.ts b/marketing-ui/admin-ui/src/router/modules/remaining.ts
new file mode 100644
index 0000000..5d8277c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/router/modules/remaining.ts
@@ -0,0 +1,293 @@
+import { Layout } from '@/utils/routerHelper'
+
+const { t } = useI18n()
+/**
+ * redirect: noredirect 当设置 noredirect 的时候该路由在面包屑导航中不可被点击
+ * name:'router-name' 设定路由的名字,一定要填写不然使用时会出现各种问题
+ * meta : {
+ hidden: true 当设置 true 的时候该路由不会再侧边栏出现 如404,login等页面(默认 false)
+
+ alwaysShow: true 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式,
+ 只有一个时,会将那个子路由当做根路由显示在侧边栏,
+ 若你想不管路由下面的 children 声明的个数都显示你的根路由,
+ 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,
+ 一直显示根路由(默认 false)
+
+ title: 'title' 设置该路由在侧边栏和面包屑中展示的名字
+
+ icon: 'svg-name' 设置该路由的图标
+
+ noCache: true 如果设置为true,则不会被 缓存(默认 false)
+
+ breadcrumb: false 如果设置为false,则不会在breadcrumb面包屑中显示(默认 true)
+
+ affix: true 如果设置为true,则会一直固定在tag项中(默认 false)
+
+ noTagsView: true 如果设置为true,则不会出现在tag中(默认 false)
+
+ activeMenu: '/dashboard' 显示高亮的路由路径
+
+ followAuth: '/dashboard' 跟随哪个路由进行权限过滤
+
+ canTo: true 设置为true即使hidden为true,也依然可以进行路由跳转(默认 false)
+ }
+ **/
+const remainingRouter: AppRouteRecordRaw[] = [
+ {
+ path: '/redirect',
+ component: Layout,
+ name: 'Redirect',
+ children: [
+ {
+ path: '/redirect/:path(.*)',
+ name: 'Redirect',
+ component: () => import('@/views/Redirect/Redirect.vue'),
+ meta: {}
+ }
+ ],
+ meta: {
+ hidden: true,
+ noTagsView: true
+ }
+ },
+ {
+ path: '/',
+ component: Layout,
+ redirect: '/index',
+ name: 'Home',
+ meta: {},
+ children: [
+ {
+ path: 'index',
+ component: () => import('@/views/Home/Index.vue'),
+ name: 'Index',
+ meta: {
+ title: t('router.home'),
+ icon: 'ep:home-filled',
+ noCache: false,
+ affix: true
+ }
+ }
+ ]
+ },
+ {
+ path: '/user',
+ component: Layout,
+ name: 'UserInfo',
+ meta: {
+ hidden: true
+ },
+ children: [
+ {
+ path: 'profile',
+ component: () => import('@/views/Profile/Index.vue'),
+ name: 'Profile',
+ meta: {
+ canTo: true,
+ hidden: true,
+ noTagsView: false,
+ icon: 'ep:user',
+ title: t('common.profile')
+ }
+ }
+ ]
+ },
+ {
+ path: '/dict',
+ component: Layout,
+ name: 'dict',
+ meta: {
+ hidden: true
+ },
+ children: [
+ {
+ path: 'type/data/:dictType',
+ component: () => import('@/views/system/dict/data/index.vue'),
+ name: 'SystemDictData',
+ meta: {
+ title: '字典数据',
+ noCache: true,
+ hidden: true,
+ canTo: true,
+ icon: '',
+ activeMenu: '/system/dict'
+ }
+ }
+ ]
+ },
+
+ {
+ path: '/codegen',
+ component: Layout,
+ name: 'CodegenEdit',
+ meta: {
+ hidden: true
+ },
+ children: [
+ {
+ path: 'edit',
+ component: () => import('@/views/infra/codegen/EditTable.vue'),
+ name: 'InfraCodegenEditTable',
+ meta: {
+ noCache: true,
+ hidden: true,
+ canTo: true,
+ icon: 'ep:edit',
+ title: '修改生成配置',
+ activeMenu: 'infra/codegen/index'
+ }
+ }
+ ]
+ },
+ {
+ path: '/job',
+ component: Layout,
+ name: 'JobL',
+ meta: {
+ hidden: true
+ },
+ children: [
+ {
+ path: 'job-log',
+ component: () => import('@/views/infra/job/logger/index.vue'),
+ name: 'InfraJobLog',
+ meta: {
+ noCache: true,
+ hidden: true,
+ canTo: true,
+ icon: 'ep:edit',
+ title: '调度日志',
+ activeMenu: 'infra/job/index'
+ }
+ }
+ ]
+ },
+ {
+ path: '/login',
+ component: () => import('@/views/Login/Login.vue'),
+ name: 'Login',
+ meta: {
+ hidden: true,
+ title: t('router.login'),
+ noTagsView: true
+ }
+ },
+ {
+ path: '/sso',
+ component: () => import('@/views/Login/Login.vue'),
+ name: 'SSOLogin',
+ meta: {
+ hidden: true,
+ title: t('router.login'),
+ noTagsView: true
+ }
+ },
+ {
+ path: '/social-login',
+ component: () => import('@/views/Login/SocialLogin.vue'),
+ name: 'SocialLogin',
+ meta: {
+ hidden: true,
+ title: t('router.socialLogin'),
+ noTagsView: true
+ }
+ },
+ {
+ path: '/403',
+ component: () => import('@/views/Error/403.vue'),
+ name: 'NoAccess',
+ meta: {
+ hidden: true,
+ title: '403',
+ noTagsView: true
+ }
+ },
+ {
+ path: '/404',
+ component: () => import('@/views/Error/404.vue'),
+ name: 'NoFound',
+ meta: {
+ hidden: true,
+ title: '404',
+ noTagsView: true
+ }
+ },
+ {
+ path: '/500',
+ component: () => import('@/views/Error/500.vue'),
+ name: 'Error',
+ meta: {
+ hidden: true,
+ title: '500',
+ noTagsView: true
+ }
+ },
+ {
+ path: '/bpm',
+ component: Layout,
+ name: 'bpm',
+ meta: {
+ hidden: true
+ },
+ children: [
+ ]
+ },
+ {
+ path: '/templateinfo',
+ component: Layout,
+ name: 'templateinfo',
+ meta: {
+ hidden: true
+ },
+ children: [
+ {
+ path: 'templatebindinginfo',
+ component: () => import('@/views/domesticsms/templateinfo/templatebindinginfo/index.vue'),
+ name: 'templatebindinginfo',
+ meta: {
+ noCache: true,
+ hidden: true,
+ canTo: true,
+ icon: 'ep:edit',
+ title: '渠道绑定信息',
+ activeMenu: 'domesticsms/templateinfo/index'
+ }
+ }
+ ]
+ },
+ {
+ path: '/internationaltemplateinfo',
+ component: Layout,
+ name: 'internationaltemplateinfo',
+ meta: {
+ hidden: true
+ },
+ children: [
+ {
+ path: 'templatebindinginfo',
+ component: () => import('@/views/internationalsms/templateinfo/templatebindinginfo/index.vue'),
+ name: 'internationaltemplatebindinginfo',
+ meta: {
+ noCache: true,
+ hidden: true,
+ canTo: true,
+ icon: 'ep:edit',
+ title: '渠道绑定信息',
+ activeMenu: 'internationalsms/templateinfo/index'
+ }
+ }
+ ]
+ },
+ {
+ path: '/:pathMatch(.*)*',
+ component: () => import('@/views/Error/404.vue'),
+ name: '',
+ meta: {
+ title: '404',
+ hidden: true,
+ breadcrumb: false
+ }
+ }
+ ]
+
+export default remainingRouter
diff --git a/marketing-ui/admin-ui/src/store/index.ts b/marketing-ui/admin-ui/src/store/index.ts
new file mode 100644
index 0000000..63f0045
--- /dev/null
+++ b/marketing-ui/admin-ui/src/store/index.ts
@@ -0,0 +1,12 @@
+import type { App } from 'vue'
+import { createPinia } from 'pinia'
+import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
+
+const store = createPinia()
+store.use(piniaPluginPersistedstate)
+
+export const setupStore = (app: App) => {
+ app.use(store)
+}
+
+export { store }
diff --git a/marketing-ui/admin-ui/src/store/modules/app.ts b/marketing-ui/admin-ui/src/store/modules/app.ts
new file mode 100644
index 0000000..be48daa
--- /dev/null
+++ b/marketing-ui/admin-ui/src/store/modules/app.ts
@@ -0,0 +1,282 @@
+import { defineStore } from 'pinia'
+import { store } from '../index'
+import { humpToUnderline, setCssVar } from '@/utils'
+import { ElMessage } from 'element-plus'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+import { ElementPlusSize } from '@/types/elementPlus'
+import { LayoutType } from '@/types/layout'
+import { ThemeTypes } from '@/types/theme'
+
+const { wsCache } = useCache()
+
+interface AppState {
+ breadcrumb: boolean
+ breadcrumbIcon: boolean
+ collapse: boolean
+ uniqueOpened: boolean
+ hamburger: boolean
+ screenfull: boolean
+ search: boolean
+ size: boolean
+ locale: boolean
+ message: boolean
+ tagsView: boolean
+ tagsViewImmerse: boolean
+ tagsViewIcon: boolean
+ logo: boolean
+ fixedHeader: boolean
+ greyMode: boolean
+ pageLoading: boolean
+ layout: LayoutType
+ title: string
+ userInfo: string
+ isDark: boolean
+ currentSize: ElementPlusSize
+ sizeMap: ElementPlusSize[]
+ mobile: boolean
+ footer: boolean
+ theme: ThemeTypes
+ fixedMenu: boolean
+}
+
+export const useAppStore = defineStore('app', {
+ state: (): AppState => {
+ return {
+ userInfo: 'userInfo', // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突
+ sizeMap: ['default', 'large', 'small'],
+ mobile: false, // 是否是移动端
+ title: import.meta.env.VITE_APP_TITLE, // 标题
+ pageLoading: false, // 路由跳转loading
+
+ breadcrumb: true, // 面包屑
+ breadcrumbIcon: true, // 面包屑图标
+ collapse: false, // 折叠菜单
+ uniqueOpened: true, // 是否只保持一个子菜单的展开
+ hamburger: true, // 折叠图标
+ screenfull: true, // 全屏图标
+ search: true, // 搜索图标
+ size: true, // 尺寸图标
+ locale: true, // 多语言图标
+ message: true, // 消息图标
+ tagsView: true, // 标签页
+ tagsViewImmerse: false, // 标签页沉浸
+ tagsViewIcon: true, // 是否显示标签图标
+ logo: true, // logo
+ fixedHeader: true, // 固定toolheader
+ footer: true, // 显示页脚
+ greyMode: false, // 是否开始灰色模式,用于特殊悼念日
+ fixedMenu: wsCache.get('fixedMenu') || false, // 是否固定菜单
+
+ layout: wsCache.get(CACHE_KEY.LAYOUT) || 'classic', // layout布局
+ isDark: wsCache.get(CACHE_KEY.IS_DARK) || false, // 是否是暗黑模式
+ currentSize: wsCache.get('default') || 'default', // 组件尺寸
+ theme: wsCache.get(CACHE_KEY.THEME) || {
+ // 主题色
+ elColorPrimary: '#409eff',
+ // 左侧菜单边框颜色
+ leftMenuBorderColor: 'inherit',
+ // 左侧菜单背景颜色
+ leftMenuBgColor: '#001529',
+ // 左侧菜单浅色背景颜色
+ leftMenuBgLightColor: '#0f2438',
+ // 左侧菜单选中背景颜色
+ leftMenuBgActiveColor: 'var(--el-color-primary)',
+ // 左侧菜单收起选中背景颜色
+ leftMenuCollapseBgActiveColor: 'var(--el-color-primary)',
+ // 左侧菜单字体颜色
+ leftMenuTextColor: '#bfcbd9',
+ // 左侧菜单选中字体颜色
+ leftMenuTextActiveColor: '#fff',
+ // logo字体颜色
+ logoTitleTextColor: '#fff',
+ // logo边框颜色
+ logoBorderColor: 'inherit',
+ // 头部背景颜色
+ topHeaderBgColor: '#fff',
+ // 头部字体颜色
+ topHeaderTextColor: 'inherit',
+ // 头部悬停颜色
+ topHeaderHoverColor: '#f6f6f6',
+ // 头部边框颜色
+ topToolBorderColor: '#eee'
+ }
+ }
+ },
+ getters: {
+ getBreadcrumb(): boolean {
+ return this.breadcrumb
+ },
+ getBreadcrumbIcon(): boolean {
+ return this.breadcrumbIcon
+ },
+ getCollapse(): boolean {
+ return this.collapse
+ },
+ getUniqueOpened(): boolean {
+ return this.uniqueOpened
+ },
+ getHamburger(): boolean {
+ return this.hamburger
+ },
+ getScreenfull(): boolean {
+ return this.screenfull
+ },
+ getSize(): boolean {
+ return this.size
+ },
+ getLocale(): boolean {
+ return this.locale
+ },
+ getTagsView(): boolean {
+ return this.tagsView
+ },
+ getTagsViewImmerse(): boolean {
+ return this.tagsViewImmerse
+ },
+ getTagsViewIcon(): boolean {
+ return this.tagsViewIcon
+ },
+ getLogo(): boolean {
+ return this.logo
+ },
+ getFixedHeader(): boolean {
+ return this.fixedHeader
+ },
+ getGreyMode(): boolean {
+ return this.greyMode
+ },
+ getFixedMenu(): boolean {
+ return this.fixedMenu
+ },
+ getPageLoading(): boolean {
+ return this.pageLoading
+ },
+ getLayout(): LayoutType {
+ return this.layout
+ },
+ getTitle(): string {
+ return this.title
+ },
+ getUserInfo(): string {
+ return this.userInfo
+ },
+ getIsDark(): boolean {
+ return this.isDark
+ },
+ getCurrentSize(): ElementPlusSize {
+ return this.currentSize
+ },
+ getSizeMap(): ElementPlusSize[] {
+ return this.sizeMap
+ },
+ getMobile(): boolean {
+ return this.mobile
+ },
+ getTheme(): ThemeTypes {
+ return this.theme
+ },
+ getFooter(): boolean {
+ return this.footer
+ }
+ },
+ actions: {
+ setBreadcrumb(breadcrumb: boolean) {
+ this.breadcrumb = breadcrumb
+ },
+ setBreadcrumbIcon(breadcrumbIcon: boolean) {
+ this.breadcrumbIcon = breadcrumbIcon
+ },
+ setCollapse(collapse: boolean) {
+ this.collapse = collapse
+ },
+ setUniqueOpened(uniqueOpened: boolean) {
+ this.uniqueOpened = uniqueOpened
+ },
+ setHamburger(hamburger: boolean) {
+ this.hamburger = hamburger
+ },
+ setScreenfull(screenfull: boolean) {
+ this.screenfull = screenfull
+ },
+ setSize(size: boolean) {
+ this.size = size
+ },
+ setLocale(locale: boolean) {
+ this.locale = locale
+ },
+ setMessage(message: boolean) {
+ this.message = message
+ },
+ setTagsView(tagsView: boolean) {
+ this.tagsView = tagsView
+ },
+ setTagsViewImmerse(tagsViewImmerse: boolean) {
+ this.tagsViewImmerse = tagsViewImmerse
+ },
+ setTagsViewIcon(tagsViewIcon: boolean) {
+ this.tagsViewIcon = tagsViewIcon
+ },
+ setLogo(logo: boolean) {
+ this.logo = logo
+ },
+ setFixedHeader(fixedHeader: boolean) {
+ this.fixedHeader = fixedHeader
+ },
+ setGreyMode(greyMode: boolean) {
+ this.greyMode = greyMode
+ },
+ setFixedMenu(fixedMenu: boolean) {
+ wsCache.set('fixedMenu', fixedMenu)
+ this.fixedMenu = fixedMenu
+ },
+ setPageLoading(pageLoading: boolean) {
+ this.pageLoading = pageLoading
+ },
+ setLayout(layout: LayoutType) {
+ if (this.mobile && layout !== 'classic') {
+ ElMessage.warning('移动端模式下不支持切换其他布局')
+ return
+ }
+ this.layout = layout
+ wsCache.set(CACHE_KEY.LAYOUT, this.layout)
+ },
+ setTitle(title: string) {
+ this.title = title
+ },
+ setIsDark(isDark: boolean) {
+ this.isDark = isDark
+ if (this.isDark) {
+ document.documentElement.classList.add('dark')
+ document.documentElement.classList.remove('light')
+ } else {
+ document.documentElement.classList.add('light')
+ document.documentElement.classList.remove('dark')
+ }
+ wsCache.set(CACHE_KEY.IS_DARK, this.isDark)
+ },
+ setCurrentSize(currentSize: ElementPlusSize) {
+ this.currentSize = currentSize
+ wsCache.set('currentSize', this.currentSize)
+ },
+ setMobile(mobile: boolean) {
+ this.mobile = mobile
+ },
+ setTheme(theme: ThemeTypes) {
+ this.theme = Object.assign(this.theme, theme)
+ wsCache.set(CACHE_KEY.THEME, this.theme)
+ },
+ setCssVarTheme() {
+ for (const key in this.theme) {
+ setCssVar(`--${humpToUnderline(key)}`, this.theme[key])
+ }
+ },
+ setFooter(footer: boolean) {
+ this.footer = footer
+ }
+ },
+ persist: false
+})
+
+export const useAppStoreWithOut = () => {
+ return useAppStore(store)
+}
diff --git a/marketing-ui/admin-ui/src/store/modules/dict.ts b/marketing-ui/admin-ui/src/store/modules/dict.ts
new file mode 100644
index 0000000..e239fb0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/store/modules/dict.ts
@@ -0,0 +1,104 @@
+import { defineStore } from 'pinia'
+import { store } from '../index'
+// @ts-ignore
+import { DictDataVO } from '@/api/system/dict/types'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+const { wsCache } = useCache('sessionStorage')
+import { getSimpleDictDataList } from '@/api/system/dict/dict.data'
+
+export interface DictValueType {
+ value: any
+ label: string
+ clorType?: string
+ cssClass?: string
+}
+export interface DictTypeType {
+ dictType: string
+ dictValue: DictValueType[]
+}
+export interface DictState {
+ dictMap: Map
+ isSetDict: boolean
+}
+
+export const useDictStore = defineStore('dict', {
+ state: (): DictState => ({
+ dictMap: new Map(),
+ isSetDict: false
+ }),
+ getters: {
+ getDictMap(): Recordable {
+ const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE)
+ if (dictMap) {
+ this.dictMap = dictMap
+ }
+ return this.dictMap
+ },
+ getIsSetDict(): boolean {
+ return this.isSetDict
+ }
+ },
+ actions: {
+ async setDictMap() {
+ const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE)
+ if (dictMap) {
+ this.dictMap = dictMap
+ this.isSetDict = true
+ } else {
+ const res = await getSimpleDictDataList()
+ // 设置数据
+ const dictDataMap = new Map()
+ res.forEach((dictData: DictDataVO) => {
+ // 获得 dictType 层级
+ const enumValueObj = dictDataMap[dictData.dictType]
+ if (!enumValueObj) {
+ dictDataMap[dictData.dictType] = []
+ }
+ // 处理 dictValue 层级
+ dictDataMap[dictData.dictType].push({
+ value: dictData.value,
+ label: dictData.label,
+ colorType: dictData.colorType,
+ cssClass: dictData.cssClass
+ })
+ })
+ this.dictMap = dictDataMap
+ this.isSetDict = true
+ wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 }) // 60 秒 过期
+ }
+ },
+ getDictByType(type: string) {
+ if (!this.isSetDict) {
+ this.setDictMap()
+ }
+ return this.dictMap[type]
+ },
+ async resetDict() {
+ wsCache.delete(CACHE_KEY.DICT_CACHE)
+ const res = await getSimpleDictDataList()
+ // 设置数据
+ const dictDataMap = new Map()
+ res.forEach((dictData: DictDataVO) => {
+ // 获得 dictType 层级
+ const enumValueObj = dictDataMap[dictData.dictType]
+ if (!enumValueObj) {
+ dictDataMap[dictData.dictType] = []
+ }
+ // 处理 dictValue 层级
+ dictDataMap[dictData.dictType].push({
+ value: dictData.value,
+ label: dictData.label,
+ colorType: dictData.colorType,
+ cssClass: dictData.cssClass
+ })
+ })
+ this.dictMap = dictDataMap
+ this.isSetDict = true
+ wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 }) // 60 秒 过期
+ }
+ }
+})
+
+export const useDictStoreWithOut = () => {
+ return useDictStore(store)
+}
diff --git a/marketing-ui/admin-ui/src/store/modules/locale.ts b/marketing-ui/admin-ui/src/store/modules/locale.ts
new file mode 100644
index 0000000..1fc772a
--- /dev/null
+++ b/marketing-ui/admin-ui/src/store/modules/locale.ts
@@ -0,0 +1,59 @@
+import { defineStore } from 'pinia'
+import { store } from '../index'
+import zhCn from 'element-plus/es/locale/lang/zh-cn'
+import en from 'element-plus/es/locale/lang/en'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+import { LocaleDropdownType } from '@/types/localeDropdown'
+
+const { wsCache } = useCache()
+
+const elLocaleMap = {
+ 'zh-CN': zhCn,
+ en: en
+}
+interface LocaleState {
+ currentLocale: LocaleDropdownType
+ localeMap: LocaleDropdownType[]
+}
+
+export const useLocaleStore = defineStore('locales', {
+ state: (): LocaleState => {
+ return {
+ currentLocale: {
+ lang: wsCache.get(CACHE_KEY.LANG) || 'zh-CN',
+ elLocale: elLocaleMap[wsCache.get(CACHE_KEY.LANG) || 'zh-CN']
+ },
+ // 多语言
+ localeMap: [
+ {
+ lang: 'zh-CN',
+ name: '简体中文'
+ },
+ {
+ lang: 'en',
+ name: 'English'
+ }
+ ]
+ }
+ },
+ getters: {
+ getCurrentLocale(): LocaleDropdownType {
+ return this.currentLocale
+ },
+ getLocaleMap(): LocaleDropdownType[] {
+ return this.localeMap
+ }
+ },
+ actions: {
+ setCurrentLocale(localeMap: LocaleDropdownType) {
+ // this.locale = Object.assign(this.locale, localeMap)
+ this.currentLocale.lang = localeMap?.lang
+ this.currentLocale.elLocale = elLocaleMap[localeMap?.lang]
+ wsCache.set(CACHE_KEY.LANG, localeMap?.lang)
+ }
+ }
+})
+
+export const useLocaleStoreWithOut = () => {
+ return useLocaleStore(store)
+}
diff --git a/marketing-ui/admin-ui/src/store/modules/lock.ts b/marketing-ui/admin-ui/src/store/modules/lock.ts
new file mode 100644
index 0000000..68ae1d7
--- /dev/null
+++ b/marketing-ui/admin-ui/src/store/modules/lock.ts
@@ -0,0 +1,48 @@
+import { defineStore } from 'pinia'
+import { store } from '@/store'
+
+interface lockInfo {
+ isLock?: boolean
+ password?: string
+}
+
+interface LockState {
+ lockInfo: lockInfo
+}
+
+export const useLockStore = defineStore('lock', {
+ state: (): LockState => {
+ return {
+ lockInfo: {
+ // isLock: false, // 是否锁定屏幕
+ // password: '' // 锁屏密码
+ }
+ }
+ },
+ getters: {
+ getLockInfo(): lockInfo {
+ return this.lockInfo
+ }
+ },
+ actions: {
+ setLockInfo(lockInfo: lockInfo) {
+ this.lockInfo = lockInfo
+ },
+ resetLockInfo() {
+ this.lockInfo = {}
+ },
+ unLock(password: string) {
+ if (this.lockInfo?.password === password) {
+ this.resetLockInfo()
+ return true
+ } else {
+ return false
+ }
+ }
+ },
+ persist: true
+})
+
+export const useLockStoreWithOut = () => {
+ return useLockStore(store)
+}
diff --git a/marketing-ui/admin-ui/src/store/modules/permission.ts b/marketing-ui/admin-ui/src/store/modules/permission.ts
new file mode 100644
index 0000000..2ff8111
--- /dev/null
+++ b/marketing-ui/admin-ui/src/store/modules/permission.ts
@@ -0,0 +1,71 @@
+import { defineStore } from 'pinia'
+import { store } from '@/store'
+import { cloneDeep } from 'lodash-es'
+import remainingRouter from '@/router/modules/remaining'
+import { flatMultiLevelRoutes, generateRoute } from '@/utils/routerHelper'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+
+const { wsCache } = useCache()
+
+export interface PermissionState {
+ routers: AppRouteRecordRaw[]
+ addRouters: AppRouteRecordRaw[]
+ menuTabRouters: AppRouteRecordRaw[]
+}
+
+export const usePermissionStore = defineStore('permission', {
+ state: (): PermissionState => ({
+ routers: [],
+ addRouters: [],
+ menuTabRouters: []
+ }),
+ getters: {
+ getRouters(): AppRouteRecordRaw[] {
+ return this.routers
+ },
+ getAddRouters(): AppRouteRecordRaw[] {
+ return flatMultiLevelRoutes(cloneDeep(this.addRouters))
+ },
+ getMenuTabRouters(): AppRouteRecordRaw[] {
+ return this.menuTabRouters
+ }
+ },
+ actions: {
+ async generateRoutes(): Promise {
+ return new Promise(async (resolve) => {
+ // 获得菜单列表,它在登录的时候,setUserInfoAction 方法中已经进行获取
+ let res: AppCustomRouteRecordRaw[] = []
+ const roleRouters = wsCache.get(CACHE_KEY.ROLE_ROUTERS)
+ if (roleRouters) {
+ res = roleRouters as AppCustomRouteRecordRaw[]
+ }
+ const routerMap: AppRouteRecordRaw[] = generateRoute(res)
+ // 动态路由,404一定要放到最后面
+ // preschooler:vue-router@4以后已支持静态404路由,此处可不再追加
+ this.addRouters = routerMap.concat([
+ {
+ path: '/:path(.*)*',
+ // redirect: '/404',
+ component: () => import('@/views/Error/404.vue'),
+ name: '404Page',
+ meta: {
+ hidden: true,
+ breadcrumb: false
+ }
+ }
+ ])
+ // 渲染菜单的所有路由
+ this.routers = cloneDeep(remainingRouter).concat(routerMap)
+ resolve()
+ })
+ },
+ setMenuTabRouters(routers: AppRouteRecordRaw[]): void {
+ this.menuTabRouters = routers
+ }
+ },
+ persist: false
+})
+
+export const usePermissionStoreWithOut = () => {
+ return usePermissionStore(store)
+}
diff --git a/marketing-ui/admin-ui/src/store/modules/tagsView.ts b/marketing-ui/admin-ui/src/store/modules/tagsView.ts
new file mode 100644
index 0000000..2b2d817
--- /dev/null
+++ b/marketing-ui/admin-ui/src/store/modules/tagsView.ts
@@ -0,0 +1,177 @@
+import router from '@/router'
+import type { RouteLocationNormalizedLoaded } from 'vue-router'
+import { getRawRoute } from '@/utils/routerHelper'
+import { defineStore } from 'pinia'
+import { store } from '../index'
+import { findIndex } from '@/utils'
+import { useUserStoreWithOut } from './user'
+
+export interface TagsViewState {
+ visitedViews: RouteLocationNormalizedLoaded[]
+ cachedViews: Set
+ selectedTag?: RouteLocationNormalizedLoaded
+}
+
+export const useTagsViewStore = defineStore('tagsView', {
+ state: (): TagsViewState => ({
+ visitedViews: [],
+ cachedViews: new Set(),
+ selectedTag: undefined
+ }),
+ getters: {
+ getVisitedViews(): RouteLocationNormalizedLoaded[] {
+ return this.visitedViews
+ },
+ getCachedViews(): string[] {
+ return Array.from(this.cachedViews)
+ },
+ getSelectedTag(): RouteLocationNormalizedLoaded | undefined {
+ return this.selectedTag
+ }
+ },
+ actions: {
+ // 新增缓存和tag
+ addView(view: RouteLocationNormalizedLoaded): void {
+ this.addVisitedView(view)
+ this.addCachedView()
+ },
+ // 新增tag
+ addVisitedView(view: RouteLocationNormalizedLoaded) {
+ if (this.visitedViews.some((v) => v.fullPath === view.fullPath)) return
+ if (view.meta?.noTagsView) return
+ const visitedView = Object.assign({}, view, { title: view.meta?.title || 'no-name' })
+
+ if (visitedView.meta) {
+ const titleSuffixList: string[] = []
+ this.visitedViews.forEach((v) => {
+ if (v.path === visitedView.path && v.meta?.title === visitedView.meta?.title) {
+ titleSuffixList.push(v.meta?.titleSuffix || '1')
+ }
+ })
+ if (titleSuffixList.length) {
+ let titleSuffix = 1
+ while (titleSuffixList.includes(`${titleSuffix}`)) {
+ titleSuffix += 1
+ }
+ visitedView.meta.titleSuffix = titleSuffix === 1 ? undefined : `${titleSuffix}`
+ }
+ }
+
+ this.visitedViews.push(visitedView)
+ },
+ // 新增缓存
+ addCachedView() {
+ const cacheMap: Set = new Set()
+ for (const v of this.visitedViews) {
+ const item = getRawRoute(v)
+ const needCache = !item.meta?.noCache
+ if (!needCache) {
+ continue
+ }
+ const name = item.name as string
+ cacheMap.add(name)
+ }
+ if (Array.from(this.cachedViews).sort().toString() === Array.from(cacheMap).sort().toString())
+ return
+ this.cachedViews = cacheMap
+ },
+ // 删除某个
+ delView(view: RouteLocationNormalizedLoaded) {
+ this.delVisitedView(view)
+ this.delCachedView()
+ },
+ // 删除tag
+ delVisitedView(view: RouteLocationNormalizedLoaded) {
+ for (const [i, v] of this.visitedViews.entries()) {
+ if (v.fullPath === view.fullPath) {
+ this.visitedViews.splice(i, 1)
+ break
+ }
+ }
+ },
+ // 删除缓存
+ delCachedView() {
+ const route = router.currentRoute.value
+ const index = findIndex(this.getCachedViews, (v) => v === route.name)
+ if (index > -1) {
+ this.cachedViews.delete(this.getCachedViews[index])
+ }
+ },
+ // 删除所有缓存和tag
+ delAllViews() {
+ this.delAllVisitedViews()
+ this.delCachedView()
+ },
+ // 删除所有tag
+ delAllVisitedViews() {
+ const userStore = useUserStoreWithOut()
+
+ // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix)
+ this.visitedViews = userStore.getUser
+ ? this.visitedViews.filter((tag) => tag?.meta?.affix)
+ : []
+ },
+ // 删除其他
+ delOthersViews(view: RouteLocationNormalizedLoaded) {
+ this.delOthersVisitedViews(view)
+ this.addCachedView()
+ },
+ // 删除其他tag
+ delOthersVisitedViews(view: RouteLocationNormalizedLoaded) {
+ this.visitedViews = this.visitedViews.filter((v) => {
+ return v?.meta?.affix || v.fullPath === view.fullPath
+ })
+ },
+ // 删除左侧
+ delLeftViews(view: RouteLocationNormalizedLoaded) {
+ const index = findIndex(
+ this.visitedViews,
+ (v) => v.fullPath === view.fullPath
+ )
+ if (index > -1) {
+ this.visitedViews = this.visitedViews.filter((v, i) => {
+ return v?.meta?.affix || v.fullPath === view.fullPath || i > index
+ })
+ this.addCachedView()
+ }
+ },
+ // 删除右侧
+ delRightViews(view: RouteLocationNormalizedLoaded) {
+ const index = findIndex(
+ this.visitedViews,
+ (v) => v.fullPath === view.fullPath
+ )
+ if (index > -1) {
+ this.visitedViews = this.visitedViews.filter((v, i) => {
+ return v?.meta?.affix || v.fullPath === view.fullPath || i < index
+ })
+ this.addCachedView()
+ }
+ },
+ updateVisitedView(view: RouteLocationNormalizedLoaded) {
+ for (let v of this.visitedViews) {
+ if (v.fullPath === view.fullPath) {
+ v = Object.assign(v, view)
+ break
+ }
+ }
+ },
+ // 设置当前选中的 tag
+ setSelectedTag(tag: RouteLocationNormalizedLoaded) {
+ this.selectedTag = tag
+ },
+ setTitle(title: string, path?: string) {
+ for (const v of this.visitedViews) {
+ if (v.path === (path ?? this.selectedTag?.path)) {
+ v.meta.title = title
+ break
+ }
+ }
+ }
+ },
+ persist: false
+})
+
+export const useTagsViewStoreWithOut = () => {
+ return useTagsViewStore(store)
+}
diff --git a/marketing-ui/admin-ui/src/store/modules/user.ts b/marketing-ui/admin-ui/src/store/modules/user.ts
new file mode 100644
index 0000000..c3920c7
--- /dev/null
+++ b/marketing-ui/admin-ui/src/store/modules/user.ts
@@ -0,0 +1,103 @@
+import { store } from '@/store'
+import { defineStore } from 'pinia'
+import { getAccessToken, removeToken } from '@/utils/auth'
+import { CACHE_KEY, useCache, deleteUserCache } from '@/hooks/web/useCache'
+import { getInfo, loginOut } from '@/api/login'
+
+const { wsCache } = useCache()
+
+interface UserVO {
+ id: number
+ avatar: string
+ nickname: string
+ deptId: number
+}
+
+interface UserInfoVO {
+ // USER 缓存
+ permissions: Set
+ roles: string[]
+ isSetUser: boolean
+ user: UserVO
+}
+
+export const useUserStore = defineStore('admin-user', {
+ state: (): UserInfoVO => ({
+ permissions: new Set(),
+ roles: [],
+ isSetUser: false,
+ user: {
+ id: 0,
+ avatar: '',
+ nickname: '',
+ deptId: 0
+ }
+ }),
+ getters: {
+ getPermissions(): Set {
+ return this.permissions
+ },
+ getRoles(): string[] {
+ return this.roles
+ },
+ getIsSetUser(): boolean {
+ return this.isSetUser
+ },
+ getUser(): UserVO {
+ return this.user
+ }
+ },
+ actions: {
+ async setUserInfoAction() {
+ if (!getAccessToken()) {
+ this.resetState()
+ return null
+ }
+ let userInfo = wsCache.get(CACHE_KEY.USER)
+ if (!userInfo) {
+ userInfo = await getInfo()
+ }
+ this.permissions = new Set(userInfo.permissions)
+ this.roles = userInfo.roles
+ this.user = userInfo.user
+ this.isSetUser = true
+ wsCache.set(CACHE_KEY.USER, userInfo)
+ wsCache.set(CACHE_KEY.ROLE_ROUTERS, userInfo.menus)
+ },
+ async setUserAvatarAction(avatar: string) {
+ const userInfo = wsCache.get(CACHE_KEY.USER)
+ // NOTE: 是否需要像`setUserInfoAction`一样判断`userInfo != null`
+ this.user.avatar = avatar
+ userInfo.user.avatar = avatar
+ wsCache.set(CACHE_KEY.USER, userInfo)
+ },
+ async setUserNicknameAction(nickname: string) {
+ const userInfo = wsCache.get(CACHE_KEY.USER)
+ // NOTE: 是否需要像`setUserInfoAction`一样判断`userInfo != null`
+ this.user.nickname = nickname
+ userInfo.user.nickname = nickname
+ wsCache.set(CACHE_KEY.USER, userInfo)
+ },
+ async loginOut() {
+ await loginOut()
+ removeToken()
+ deleteUserCache() // 删除用户缓存
+ this.resetState()
+ },
+ resetState() {
+ this.permissions = new Set()
+ this.roles = []
+ this.isSetUser = false
+ this.user = {
+ id: 0,
+ avatar: '',
+ nickname: '',
+ deptId: 0
+ }
+ }
+ }
+})
+
+export const useUserStoreWithOut = () => {
+ return useUserStore(store)
+}
diff --git a/marketing-ui/admin-ui/src/styles/FormCreate/fonts/fontello.woff b/marketing-ui/admin-ui/src/styles/FormCreate/fonts/fontello.woff
new file mode 100644
index 0000000..1e00f49
Binary files /dev/null and b/marketing-ui/admin-ui/src/styles/FormCreate/fonts/fontello.woff differ
diff --git a/marketing-ui/admin-ui/src/styles/FormCreate/index.scss b/marketing-ui/admin-ui/src/styles/FormCreate/index.scss
new file mode 100644
index 0000000..bb62000
--- /dev/null
+++ b/marketing-ui/admin-ui/src/styles/FormCreate/index.scss
@@ -0,0 +1,22 @@
+// 使用字体图标来源 https://fontello.com/
+
+@font-face {
+ font-family: 'fc-icon';
+ src: url('@/styles/FormCreate/fonts/fontello.woff') format('woff');
+}
+
+.icon-doc-text:before {
+ content: '\f0f6';
+}
+
+.icon-server:before {
+ content: '\f233';
+}
+
+.icon-address-card-o:before {
+ content: '\f2bc';
+}
+
+.icon-user-o:before {
+ content: '\f2c0';
+}
diff --git a/marketing-ui/admin-ui/src/styles/global.module.scss b/marketing-ui/admin-ui/src/styles/global.module.scss
new file mode 100644
index 0000000..af793f0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/styles/global.module.scss
@@ -0,0 +1,6 @@
+@use './variables.scss' as *;
+// 导出变量
+:export {
+ namespace: $namespace;
+ elNamespace: $elNamespace;
+}
diff --git a/marketing-ui/admin-ui/src/styles/index.scss b/marketing-ui/admin-ui/src/styles/index.scss
new file mode 100644
index 0000000..7607941
--- /dev/null
+++ b/marketing-ui/admin-ui/src/styles/index.scss
@@ -0,0 +1,37 @@
+@use './var.css';
+@use './FormCreate/index.scss';
+@use './theme.scss';
+@use 'element-plus/theme-chalk/dark/css-vars.css';
+
+.reset-margin [class*='el-icon'] + span {
+ margin-left: 2px !important;
+}
+
+// 解决抽屉弹出时,body宽度变化的问题
+.el-popup-parent--hidden {
+ width: 100% !important;
+}
+
+// 解决表格内容超过表格总宽度后,横向滚动条前端顶不到表格边缘的问题
+.el-scrollbar__bar {
+ display: flex;
+ justify-content: flex-start;
+}
+
+/* nprogress 适配 element-plus 的主题色 */
+#nprogress {
+ & .bar {
+ background-color: var(--el-color-primary) !important;
+ }
+
+ & .peg {
+ box-shadow:
+ 0 0 10px var(--el-color-primary),
+ 0 0 5px var(--el-color-primary) !important;
+ }
+
+ & .spinner-icon {
+ border-top-color: var(--el-color-primary);
+ border-left-color: var(--el-color-primary);
+ }
+}
diff --git a/marketing-ui/admin-ui/src/styles/theme.scss b/marketing-ui/admin-ui/src/styles/theme.scss
new file mode 100644
index 0000000..39b03b3
--- /dev/null
+++ b/marketing-ui/admin-ui/src/styles/theme.scss
@@ -0,0 +1,6 @@
+// .text-color {
+// color: var(--el-text-color-regular);
+// }
+// .dark .dark\:text-color {
+// color: rgba(255, 255, 255, var(--dark-text-color));
+// }
diff --git a/marketing-ui/admin-ui/src/styles/var.css b/marketing-ui/admin-ui/src/styles/var.css
new file mode 100644
index 0000000..44f9405
--- /dev/null
+++ b/marketing-ui/admin-ui/src/styles/var.css
@@ -0,0 +1,74 @@
+:root {
+ --login-bg-color: #293146;
+
+ --left-menu-max-width: 200px;
+
+ --left-menu-min-width: 64px;
+
+ --left-menu-bg-color: #001529;
+
+ --left-menu-bg-light-color: #0f2438;
+
+ --left-menu-bg-active-color: var(--el-color-primary);
+
+ --left-menu-text-color: #bfcbd9;
+
+ --left-menu-text-active-color: #fff;
+
+ --left-menu-collapse-bg-active-color: var(--el-color-primary);
+ /* left menu end */
+
+ /* logo start */
+ --logo-height: 50px;
+
+ --logo-title-text-color: #fff;
+ /* logo end */
+
+ /* header start */
+ --top-header-bg-color: '#fff';
+
+ --top-header-text-color: 'inherit';
+
+ --top-header-hover-color: #f6f6f6;
+
+ --top-tool-height: var(--logo-height);
+
+ --top-tool-p-x: 0;
+
+ --tags-view-height: 35px;
+ /* header start */
+
+ /* tab menu start */
+ --tab-menu-max-width: 80px;
+
+ --tab-menu-min-width: 30px;
+
+ --tab-menu-collapse-height: 36px;
+ /* tab menu end */
+
+ --app-content-padding: 20px;
+
+ --app-content-bg-color: #f5f7f9;
+
+ --app-footer-height: 50px;
+
+ --transition-time-02: 0.2s;
+}
+
+.dark {
+ --app-content-bg-color: var(--el-bg-color);
+}
+
+html,
+body {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+*,
+:after,
+:before {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
diff --git a/marketing-ui/admin-ui/src/styles/variables.scss b/marketing-ui/admin-ui/src/styles/variables.scss
new file mode 100644
index 0000000..00b66f1
--- /dev/null
+++ b/marketing-ui/admin-ui/src/styles/variables.scss
@@ -0,0 +1,4 @@
+// 命名空间
+$namespace: v;
+// el命名空间
+$elNamespace: el;
diff --git a/marketing-ui/admin-ui/src/types/auto-components.d.ts b/marketing-ui/admin-ui/src/types/auto-components.d.ts
new file mode 100644
index 0000000..0f4ef16
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/auto-components.d.ts
@@ -0,0 +1,179 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// Generated by unplugin-vue-components
+// Read more: https://github.com/vuejs/core/pull/3399
+export {}
+
+declare module 'vue' {
+ export interface GlobalComponents {
+ AppLinkInput: typeof import('./../components/AppLinkInput/index.vue')['default']
+ AppLinkSelectDialog: typeof import('./../components/AppLinkInput/AppLinkSelectDialog.vue')['default']
+ Backtop: typeof import('./../components/Backtop/src/Backtop.vue')['default']
+ BoundaryEventTimer: typeof import('./../components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue')['default']
+ CallActivity: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue')['default']
+ CardTitle: typeof import('./../components/Card/src/CardTitle.vue')['default']
+ ChildProcessNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/ChildProcessNode.vue')['default']
+ ChildProcessNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/ChildProcessNodeConfig.vue')['default']
+ ColorInput: typeof import('./../components/ColorInput/index.vue')['default']
+ ComponentContainer: typeof import('./../components/DiyEditor/components/ComponentContainer.vue')['default']
+ ComponentContainerProperty: typeof import('./../components/DiyEditor/components/ComponentContainerProperty.vue')['default']
+ ComponentLibrary: typeof import('./../components/DiyEditor/components/ComponentLibrary.vue')['default']
+ Condition: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue')['default']
+ ConditionDialog: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/components/ConditionDialog.vue')['default']
+ ConditionNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue')['default']
+ ConfigGlobal: typeof import('./../components/ConfigGlobal/src/ConfigGlobal.vue')['default']
+ ContentDetailWrap: typeof import('./../components/ContentDetailWrap/src/ContentDetailWrap.vue')['default']
+ ContentWrap: typeof import('./../components/ContentWrap/src/ContentWrap.vue')['default']
+ CopperModal: typeof import('./../components/Cropper/src/CopperModal.vue')['default']
+ CopyTaskNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue')['default']
+ CopyTaskNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue')['default']
+ CountTo: typeof import('./../components/CountTo/src/CountTo.vue')['default']
+ Crontab: typeof import('./../components/Crontab/src/Crontab.vue')['default']
+ Cropper: typeof import('./../components/Cropper/src/Cropper.vue')['default']
+ CropperAvatar: typeof import('./../components/Cropper/src/CropperAvatar.vue')['default']
+ DelayTimerNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue')['default']
+ DelayTimerNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue')['default']
+ DeptSelectForm: typeof import('./../components/DeptSelectForm/index.vue')['default']
+ Descriptions: typeof import('./../components/Descriptions/src/Descriptions.vue')['default']
+ DescriptionsItemLabel: typeof import('./../components/Descriptions/src/DescriptionsItemLabel.vue')['default']
+ Dialog: typeof import('./../components/Dialog/src/Dialog.vue')['default']
+ DictSelect: typeof import('./../components/FormCreate/src/components/DictSelect.vue')['default']
+ DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default']
+ DiyEditor: typeof import('./../components/DiyEditor/index.vue')['default']
+ DocAlert: typeof import('./../components/DocAlert/index.vue')['default']
+ Draggable: typeof import('./../components/Draggable/index.vue')['default']
+ Echart: typeof import('./../components/Echart/src/Echart.vue')['default']
+ Editor: typeof import('./../components/Editor/src/Editor.vue')['default']
+ ElAlert: typeof import('element-plus/es')['ElAlert']
+ ElAutoResizer: typeof import('element-plus/es')['ElAutoResizer']
+ ElAvatar: typeof import('element-plus/es')['ElAvatar']
+ ElButton: typeof import('element-plus/es')['ElButton']
+ ElCard: typeof import('element-plus/es')['ElCard']
+ ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
+ ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
+ ElCol: typeof import('element-plus/es')['ElCol']
+ ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+ ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
+ ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
+ ElDialog: typeof import('element-plus/es')['ElDialog']
+ ElDivider: typeof import('element-plus/es')['ElDivider']
+ ElDrawer: typeof import('element-plus/es')['ElDrawer']
+ ElDropdown: typeof import('element-plus/es')['ElDropdown']
+ ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
+ ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
+ ElementBaseInfo: typeof import('./../components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue')['default']
+ ElementCustomConfig: typeof import('./../components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue')['default']
+ ElementForm: typeof import('./../components/bpmnProcessDesigner/package/penal/form/ElementForm.vue')['default']
+ ElementListeners: typeof import('./../components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue')['default']
+ ElementMultiInstance: typeof import('./../components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue')['default']
+ ElementOtherConfig: typeof import('./../components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue')['default']
+ ElementProperties: typeof import('./../components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue')['default']
+ ElementTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/ElementTask.vue')['default']
+ ElForm: typeof import('element-plus/es')['ElForm']
+ ElFormItem: typeof import('element-plus/es')['ElFormItem']
+ ElIcon: typeof import('element-plus/es')['ElIcon']
+ ElImage: typeof import('element-plus/es')['ElImage']
+ ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
+ ElInput: typeof import('element-plus/es')['ElInput']
+ ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
+ ElLink: typeof import('element-plus/es')['ElLink']
+ ElOption: typeof import('element-plus/es')['ElOption']
+ ElPagination: typeof import('element-plus/es')['ElPagination']
+ ElPopover: typeof import('element-plus/es')['ElPopover']
+ ElRadio: typeof import('element-plus/es')['ElRadio']
+ ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
+ ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
+ ElRow: typeof import('element-plus/es')['ElRow']
+ ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
+ ElSelect: typeof import('element-plus/es')['ElSelect']
+ ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
+ ElSpace: typeof import('element-plus/es')['ElSpace']
+ ElSwitch: typeof import('element-plus/es')['ElSwitch']
+ ElTable: typeof import('element-plus/es')['ElTable']
+ ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+ ElTableV2: typeof import('element-plus/es')['ElTableV2']
+ ElTabPane: typeof import('element-plus/es')['ElTabPane']
+ ElTabs: typeof import('element-plus/es')['ElTabs']
+ ElTag: typeof import('element-plus/es')['ElTag']
+ ElTimeline: typeof import('element-plus/es')['ElTimeline']
+ ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
+ ElTooltip: typeof import('element-plus/es')['ElTooltip']
+ ElTree: typeof import('element-plus/es')['ElTree']
+ ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
+ ElUpload: typeof import('element-plus/es')['ElUpload']
+ EndEventNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue')['default']
+ Error: typeof import('./../components/Error/src/Error.vue')['default']
+ ExclusiveNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue')['default']
+ FlowCondition: typeof import('./../components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue')['default']
+ Form: typeof import('./../components/Form/src/Form.vue')['default']
+ Highlight: typeof import('./../components/Highlight/src/Highlight.vue')['default']
+ HttpRequestParamSetting: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/components/HttpRequestParamSetting.vue')['default']
+ HttpRequestSetting: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/components/HttpRequestSetting.vue')['default']
+ Icon: typeof import('./../components/Icon/src/Icon.vue')['default']
+ IconSelect: typeof import('./../components/Icon/src/IconSelect.vue')['default']
+ IFrame: typeof import('./../components/IFrame/src/IFrame.vue')['default']
+ ImageViewer: typeof import('./../components/ImageViewer/src/ImageViewer.vue')['default']
+ InclusiveNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue')['default']
+ Infotip: typeof import('./../components/Infotip/src/Infotip.vue')['default']
+ InputPassword: typeof import('./../components/InputPassword/src/InputPassword.vue')['default']
+ InputWithColor: typeof import('./../components/InputWithColor/index.vue')['default']
+ MagicCubeEditor: typeof import('./../components/MagicCubeEditor/index.vue')['default']
+ MarkdownView: typeof import('./../components/MarkdownView/index.vue')['default']
+ NodeHandler: typeof import('./../components/SimpleProcessDesignerV2/src/NodeHandler.vue')['default']
+ OperateLogV2: typeof import('./../components/OperateLogV2/src/OperateLogV2.vue')['default']
+ Pagination: typeof import('./../components/Pagination/index.vue')['default']
+ ParallelNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue')['default']
+ ProcessDesigner: typeof import('./../components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue')['default']
+ ProcessExpressionDialog: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ProcessExpressionDialog.vue')['default']
+ ProcessListenerDialog: typeof import('./../components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue')['default']
+ ProcessNodeTree: typeof import('./../components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue')['default']
+ ProcessPalette: typeof import('./../components/bpmnProcessDesigner/package/palette/ProcessPalette.vue')['default']
+ ProcessViewer: typeof import('./../components/bpmnProcessDesigner/package/designer/ProcessViewer.vue')['default']
+ PropertiesPanel: typeof import('./../components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue')['default']
+ Qrcode: typeof import('./../components/Qrcode/src/Qrcode.vue')['default']
+ ReceiveTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue')['default']
+ RouterLink: typeof import('vue-router')['RouterLink']
+ RouterNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/RouterNode.vue')['default']
+ RouterNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue')['default']
+ RouterSearch: typeof import('./../components/RouterSearch/index.vue')['default']
+ RouterView: typeof import('vue-router')['RouterView']
+ ScriptTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue')['default']
+ Search: typeof import('./../components/Search/src/Search.vue')['default']
+ ServiceTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ServiceTask.vue')['default']
+ ShortcutDateRangePicker: typeof import('./../components/ShortcutDateRangePicker/index.vue')['default']
+ SignalAndMessage: typeof import('./../components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue')['default']
+ SimpleProcessDesigner: typeof import('./../components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue')['default']
+ SimpleProcessModel: typeof import('./../components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue')['default']
+ SimpleProcessViewer: typeof import('./../components/SimpleProcessDesignerV2/src/SimpleProcessViewer.vue')['default']
+ StartUserNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue')['default']
+ StartUserNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue')['default']
+ Sticky: typeof import('./../components/Sticky/src/Sticky.vue')['default']
+ SummaryCard: typeof import('./../components/SummaryCard/index.vue')['default']
+ Table: typeof import('./../components/Table/src/Table.vue')['default']
+ TableSelectForm: typeof import('./../components/Table/src/TableSelectForm.vue')['default']
+ Tinyflow: typeof import('./../components/Tinyflow/Tinyflow.vue')['default']
+ Tooltip: typeof import('./../components/Tooltip/src/Tooltip.vue')['default']
+ TriggerNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/TriggerNode.vue')['default']
+ TriggerNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/TriggerNodeConfig.vue')['default']
+ UploadFile: typeof import('./../components/UploadFile/src/UploadFile.vue')['default']
+ UploadImg: typeof import('./../components/UploadFile/src/UploadImg.vue')['default']
+ UploadImgs: typeof import('./../components/UploadFile/src/UploadImgs.vue')['default']
+ UserSelectForm: typeof import('./../components/UserSelectForm/index.vue')['default']
+ UserTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue')['default']
+ UserTaskCustomConfig: typeof import('./../components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue')['default']
+ UserTaskListener: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/components/UserTaskListener.vue')['default']
+ UserTaskListeners: typeof import('./../components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue')['default']
+ UserTaskNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue')['default']
+ UserTaskNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue')['default']
+ Verify: typeof import('./../components/Verifition/src/Verify.vue')['default']
+ VerifyPoints: typeof import('./../components/Verifition/src/Verify/VerifyPoints.vue')['default']
+ VerifySlide: typeof import('./../components/Verifition/src/Verify/VerifySlide.vue')['default']
+ VerticalButtonGroup: typeof import('./../components/VerticalButtonGroup/index.vue')['default']
+ XButton: typeof import('./../components/XButton/src/XButton.vue')['default']
+ XTextButton: typeof import('./../components/XButton/src/XTextButton.vue')['default']
+ }
+ export interface ComponentCustomProperties {
+ vLoading: typeof import('element-plus/es')['ElLoadingDirective']
+ }
+}
diff --git a/marketing-ui/admin-ui/src/types/configGlobal.d.ts b/marketing-ui/admin-ui/src/types/configGlobal.d.ts
new file mode 100644
index 0000000..f6d7b3c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/configGlobal.d.ts
@@ -0,0 +1,4 @@
+import { ElementPlusSize } from './elementPlus'
+export interface ConfigGlobalTypes {
+ size?: ElementPlusSize
+}
diff --git a/marketing-ui/admin-ui/src/types/contextMenu.d.ts b/marketing-ui/admin-ui/src/types/contextMenu.d.ts
new file mode 100644
index 0000000..0738d0e
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/contextMenu.d.ts
@@ -0,0 +1,7 @@
+export type contextMenuSchema = {
+ disabled?: boolean
+ divided?: boolean
+ icon?: string
+ label: string
+ command?: (item: contextMenuSchema) => void
+}
diff --git a/marketing-ui/admin-ui/src/types/descriptions.d.ts b/marketing-ui/admin-ui/src/types/descriptions.d.ts
new file mode 100644
index 0000000..af6d68c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/descriptions.d.ts
@@ -0,0 +1,14 @@
+export interface DescriptionsSchema {
+ span?: number // 占多少分
+ field: string // 字段名
+ label?: string // label名
+ mappedField?: string // 字段映射
+ width?: string | number
+ minWidth?: string | number
+ align?: 'left' | 'center' | 'right'
+ labelAlign?: 'left' | 'center' | 'right'
+ className?: string
+ labelClassName?: string
+ dateFormat?: string // add by 星语:支持时间的格式化
+ dictType?: string // add by 星语:支持 dict 字典数据
+}
diff --git a/marketing-ui/admin-ui/src/types/elementPlus.d.ts b/marketing-ui/admin-ui/src/types/elementPlus.d.ts
new file mode 100644
index 0000000..2c6b76e
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/elementPlus.d.ts
@@ -0,0 +1,3 @@
+export type ElementPlusSize = 'default' | 'small' | 'large'
+
+export type ElementPlusInfoType = 'success' | 'info' | 'warning' | 'danger'
diff --git a/marketing-ui/admin-ui/src/types/form.d.ts b/marketing-ui/admin-ui/src/types/form.d.ts
new file mode 100644
index 0000000..980c8cc
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/form.d.ts
@@ -0,0 +1,44 @@
+import type { CSSProperties } from 'vue'
+import { ColProps, ComponentProps, ComponentName } from '@/types/components'
+import type { AxiosPromise } from 'axios'
+
+export type FormSetPropsType = {
+ field: string
+ path: string
+ value: any
+}
+
+export type FormValueType = string | number | string[] | number[] | boolean | undefined | null
+
+export type FormItemProps = {
+ labelWidth?: string | number
+ required?: boolean
+ rules?: Recordable
+ error?: string
+ showMessage?: boolean
+ inlineMessage?: boolean
+ style?: CSSProperties
+}
+
+export type FormSchema = {
+ // 唯一值
+ field: string
+ // 标题
+ label?: string
+ // 提示
+ labelMessage?: string
+ // col组件属性
+ colProps?: ColProps
+ // 表单组件属性,slots对应的是表单组件的插槽,规则:${field}-xxx,具体可以查看element-plus文档
+ componentProps?: { slots?: Recordable } & ComponentProps
+ // formItem组件属性
+ formItemProps?: FormItemProps
+ // 渲染的组件
+ component?: ComponentName
+ // 初始值
+ value?: FormValueType
+ // 是否隐藏
+ hidden?: boolean
+ // 远程加载下拉项
+ api?: () => AxiosPromise
+}
diff --git a/marketing-ui/admin-ui/src/types/icon.d.ts b/marketing-ui/admin-ui/src/types/icon.d.ts
new file mode 100644
index 0000000..d1ffcdb
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/icon.d.ts
@@ -0,0 +1,5 @@
+export interface IconTypes {
+ size?: number
+ color?: string
+ icon: string
+}
diff --git a/marketing-ui/admin-ui/src/types/infoTip.d.ts b/marketing-ui/admin-ui/src/types/infoTip.d.ts
new file mode 100644
index 0000000..6eff083
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/infoTip.d.ts
@@ -0,0 +1,4 @@
+export interface TipSchema {
+ label: string
+ keys?: string[]
+}
diff --git a/marketing-ui/admin-ui/src/types/layout.d.ts b/marketing-ui/admin-ui/src/types/layout.d.ts
new file mode 100644
index 0000000..cad3e2a
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/layout.d.ts
@@ -0,0 +1 @@
+export type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu'
diff --git a/marketing-ui/admin-ui/src/types/localeDropdown.d.ts b/marketing-ui/admin-ui/src/types/localeDropdown.d.ts
new file mode 100644
index 0000000..c749dce
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/localeDropdown.d.ts
@@ -0,0 +1,10 @@
+export interface Language {
+ el: Recordable
+ name: string
+}
+
+export interface LocaleDropdownType {
+ lang: LocaleType
+ name?: string
+ elLocale?: Language
+}
diff --git a/marketing-ui/admin-ui/src/types/qrcode.d.ts b/marketing-ui/admin-ui/src/types/qrcode.d.ts
new file mode 100644
index 0000000..86cdf0b
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/qrcode.d.ts
@@ -0,0 +1,9 @@
+export interface QrcodeLogo {
+ src?: string
+ logoSize?: number
+ bgColor?: string
+ borderSize?: number
+ crossOrigin?: string
+ borderRadius?: number
+ logoRadius?: number
+}
diff --git a/marketing-ui/admin-ui/src/types/table.d.ts b/marketing-ui/admin-ui/src/types/table.d.ts
new file mode 100644
index 0000000..9cb4205
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/table.d.ts
@@ -0,0 +1,44 @@
+export type TableColumn = {
+ field: string
+ label?: string
+ width?: number | string
+ fixed?: 'left' | 'right'
+ children?: TableColumn[]
+} & Recordable
+
+export type VxeTableColumn = {
+ field: string
+ title?: string
+ children?: TableColumn[]
+} & Recordable
+
+export type TableSlotDefault = {
+ row: Recordable
+ column: TableColumn
+ $index: number
+} & Recordable
+
+export interface Pagination {
+ small?: boolean
+ background?: boolean
+ pageSize?: number
+ defaultPageSize?: number
+ total?: number
+ pageCount?: number
+ pagerCount?: number
+ currentPage?: number
+ defaultCurrentPage?: number
+ layout?: string
+ pageSizes?: number[]
+ popperClass?: string
+ prevText?: string
+ nextText?: string
+ disabled?: boolean
+ hideOnSinglePage?: boolean
+}
+
+export interface TableSetPropsType {
+ field: string
+ path: string
+ value: any
+}
diff --git a/marketing-ui/admin-ui/src/types/theme.d.ts b/marketing-ui/admin-ui/src/types/theme.d.ts
new file mode 100644
index 0000000..ad649b0
--- /dev/null
+++ b/marketing-ui/admin-ui/src/types/theme.d.ts
@@ -0,0 +1,16 @@
+export type ThemeTypes = {
+ elColorPrimary?: string
+ leftMenuBorderColor?: string
+ leftMenuBgColor?: string
+ leftMenuBgLightColor?: string
+ leftMenuBgActiveColor?: string
+ leftMenuCollapseBgActiveColor?: string
+ leftMenuTextColor?: string
+ leftMenuTextActiveColor?: string
+ logoTitleTextColor?: string
+ logoBorderColor?: string
+ topHeaderBgColor?: string
+ topHeaderTextColor?: string
+ topHeaderHoverColor?: string
+ topToolBorderColor?: string
+}
diff --git a/marketing-ui/admin-ui/src/utils/Logger.ts b/marketing-ui/admin-ui/src/utils/Logger.ts
new file mode 100644
index 0000000..ca58df2
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/Logger.ts
@@ -0,0 +1,100 @@
+const isArray = function (obj: any): boolean {
+ return Object.prototype.toString.call(obj) === '[object Array]'
+}
+
+const Logger = () => {}
+
+Logger.typeColor = function (type: string) {
+ let color = ''
+ switch (type) {
+ case 'primary':
+ color = '#2d8cf0'
+ break
+ case 'success':
+ color = '#19be6b'
+ break
+ case 'info':
+ color = '#909399'
+ break
+ case 'warn':
+ color = '#ff9900'
+ break
+ case 'error':
+ color = '#f03f14'
+ break
+ default:
+ color = '#35495E'
+ break
+ }
+ return color
+}
+
+Logger.print = function (type = 'default', text: any, back = false) {
+ if (typeof text === 'object') {
+ // 如果是對象則調用打印對象方式
+ isArray(text) ? console.table(text) : console.dir(text)
+ return
+ }
+ if (back) {
+ // 如果是打印帶背景圖的
+ console.log(
+ `%c ${text} `,
+ `background:${Logger.typeColor(type)}; padding: 2px; border-radius: 4px; color: #fff;`
+ )
+ } else {
+ console.log(
+ `%c ${text} `,
+ `border: 1px solid ${Logger.typeColor(type)};
+ padding: 2px; border-radius: 4px;
+ color: ${Logger.typeColor(type)};`
+ )
+ }
+}
+
+Logger.printBack = function (type = 'primary', text) {
+ this.print(type, text, true)
+}
+
+Logger.pretty = function (type = 'primary', title, text) {
+ if (typeof text === 'object') {
+ console.group('Console Group', title)
+ console.log(
+ `%c ${title}`,
+ `background:${Logger.typeColor(type)};border:1px solid ${Logger.typeColor(type)};
+ padding: 1px; border-radius: 4px; color: #fff;`
+ )
+ isArray(text) ? console.table(text) : console.dir(text)
+ console.groupEnd()
+ return
+ }
+ console.log(
+ `%c ${title} %c ${text} %c`,
+ `background:${Logger.typeColor(type)};border:1px solid ${Logger.typeColor(type)};
+ padding: 1px; border-radius: 4px 0 0 4px; color: #fff;`,
+ `border:1px solid ${Logger.typeColor(type)};
+ padding: 1px; border-radius: 0 4px 4px 0; color: ${Logger.typeColor(type)};`,
+ 'background:transparent'
+ )
+}
+
+Logger.prettyPrimary = function (title, ...text) {
+ text.forEach((t) => this.pretty('primary', title, t))
+}
+
+Logger.prettySuccess = function (title, ...text) {
+ text.forEach((t) => this.pretty('success', title, t))
+}
+
+Logger.prettyWarn = function (title, ...text) {
+ text.forEach((t) => this.pretty('warn', title, t))
+}
+
+Logger.prettyError = function (title, ...text) {
+ text.forEach((t) => this.pretty('error', title, t))
+}
+
+Logger.prettyInfo = function (title, ...text) {
+ text.forEach((t) => this.pretty('info', title, t))
+}
+
+export default Logger
diff --git a/marketing-ui/admin-ui/src/utils/auth.ts b/marketing-ui/admin-ui/src/utils/auth.ts
new file mode 100644
index 0000000..daeb3fa
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/auth.ts
@@ -0,0 +1,63 @@
+import { useCache, CACHE_KEY } from '@/hooks/web/useCache'
+import { TokenType } from '@/api/login/types'
+import { decrypt, encrypt } from '@/utils/jsencrypt'
+
+const { wsCache } = useCache()
+
+const AccessTokenKey = 'ACCESS_TOKEN'
+const RefreshTokenKey = 'REFRESH_TOKEN'
+
+// 获取token
+export const getAccessToken = () => {
+ // 此处与TokenKey相同,此写法解决初始化时Cookies中不存在TokenKey报错
+ const accessToken = wsCache.get(AccessTokenKey)
+ return accessToken ? accessToken : wsCache.get('ACCESS_TOKEN')
+}
+
+// 刷新token
+export const getRefreshToken = () => {
+ return wsCache.get(RefreshTokenKey)
+}
+
+// 设置token
+export const setToken = (token: TokenType) => {
+ wsCache.set(RefreshTokenKey, token.refreshToken)
+ wsCache.set(AccessTokenKey, token.accessToken)
+}
+
+// 删除token
+export const removeToken = () => {
+ wsCache.delete(AccessTokenKey)
+ wsCache.delete(RefreshTokenKey)
+}
+
+/** 格式化token(jwt格式) */
+export const formatToken = (token: string): string => {
+ return 'Bearer ' + token
+}
+// ========== 账号相关 ==========
+
+export type LoginFormType = {
+ tenantName: string
+ username: string
+ password: string
+ rememberMe: boolean
+}
+
+export const getLoginForm = () => {
+ const loginForm: LoginFormType = wsCache.get(CACHE_KEY.LoginForm)
+ if (loginForm) {
+ loginForm.password = decrypt(loginForm.password) as string
+ }
+ return loginForm
+}
+
+export const setLoginForm = (loginForm: LoginFormType) => {
+ loginForm.password = encrypt(loginForm.password) as string
+ wsCache.set(CACHE_KEY.LoginForm, loginForm, { exp: 30 * 24 * 60 * 60 })
+}
+
+export const removeLoginForm = () => {
+ wsCache.delete(CACHE_KEY.LoginForm)
+}
+
diff --git a/marketing-ui/admin-ui/src/utils/color.ts b/marketing-ui/admin-ui/src/utils/color.ts
new file mode 100644
index 0000000..13424e5
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/color.ts
@@ -0,0 +1,174 @@
+/**
+ * 判断是否 十六进制颜色值.
+ * 输入形式可为 #fff000 #f00
+ *
+ * @param String color 十六进制颜色值
+ * @return Boolean
+ */
+export const isHexColor = (color: string) => {
+ const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/
+ return reg.test(color)
+}
+
+/**
+ * RGB 颜色值转换为 十六进制颜色值.
+ * r, g, 和 b 需要在 [0, 255] 范围内
+ *
+ * @return String 类似#ff00ff
+ * @param r
+ * @param g
+ * @param b
+ */
+export const rgbToHex = (r: number, g: number, b: number) => {
+ // tslint:disable-next-line:no-bitwise
+ const hex = ((r << 16) | (g << 8) | b).toString(16)
+ return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex
+}
+
+/**
+ * Transform a HEX color to its RGB representation
+ * @param {string} hex The color to transform
+ * @returns The RGB representation of the passed color
+ */
+export const hexToRGB = (hex: string, opacity?: number) => {
+ let sHex = hex.toLowerCase()
+ if (isHexColor(hex)) {
+ if (sHex.length === 4) {
+ let sColorNew = '#'
+ for (let i = 1; i < 4; i += 1) {
+ sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1))
+ }
+ sHex = sColorNew
+ }
+ const sColorChange: number[] = []
+ for (let i = 1; i < 7; i += 2) {
+ sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2)))
+ }
+ return opacity
+ ? 'RGBA(' + sColorChange.join(',') + ',' + opacity + ')'
+ : 'RGB(' + sColorChange.join(',') + ')'
+ }
+ return sHex
+}
+
+export const colorIsDark = (color: string) => {
+ if (!isHexColor(color)) return
+ const [r, g, b] = hexToRGB(color)
+ .replace(/(?:\(|\)|rgb|RGB)*/g, '')
+ .split(',')
+ .map((item) => Number(item))
+ return r * 0.299 + g * 0.578 + b * 0.114 < 192
+}
+
+/**
+ * Darkens a HEX color given the passed percentage
+ * @param {string} color The color to process
+ * @param {number} amount The amount to change the color by
+ * @returns {string} The HEX representation of the processed color
+ */
+export const darken = (color: string, amount: number) => {
+ color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color
+ amount = Math.trunc((255 * amount) / 100)
+ return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight(
+ color.substring(2, 4),
+ amount
+ )}${subtractLight(color.substring(4, 6), amount)}`
+}
+
+/**
+ * Lightens a 6 char HEX color according to the passed percentage
+ * @param {string} color The color to change
+ * @param {number} amount The amount to change the color by
+ * @returns {string} The processed color represented as HEX
+ */
+export const lighten = (color: string, amount: number) => {
+ color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color
+ amount = Math.trunc((255 * amount) / 100)
+ return `#${addLight(color.substring(0, 2), amount)}${addLight(
+ color.substring(2, 4),
+ amount
+ )}${addLight(color.substring(4, 6), amount)}`
+}
+
+/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */
+/**
+ * Sums the passed percentage to the R, G or B of a HEX color
+ * @param {string} color The color to change
+ * @param {number} amount The amount to change the color by
+ * @returns {string} The processed part of the color
+ */
+const addLight = (color: string, amount: number) => {
+ const cc = parseInt(color, 16) + amount
+ const c = cc > 255 ? 255 : cc
+ return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`
+}
+
+/**
+ * Calculates luminance of an rgb color
+ * @param {number} r red
+ * @param {number} g green
+ * @param {number} b blue
+ */
+const luminanace = (r: number, g: number, b: number) => {
+ const a = [r, g, b].map((v) => {
+ v /= 255
+ return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)
+ })
+ return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722
+}
+
+/**
+ * Calculates contrast between two rgb colors
+ * @param {string} rgb1 rgb color 1
+ * @param {string} rgb2 rgb color 2
+ */
+const contrast = (rgb1: string[], rgb2: number[]) => {
+ return (
+ (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
+ (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05)
+ )
+}
+
+/**
+ * Determines what the best text color is (black or white) based con the contrast with the background
+ * @param hexColor - Last selected color by the user
+ */
+export const calculateBestTextColor = (hexColor: string) => {
+ const rgbColor = hexToRGB(hexColor.substring(1))
+ const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0])
+
+ return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF'
+}
+
+/**
+ * Subtracts the indicated percentage to the R, G or B of a HEX color
+ * @param {string} color The color to change
+ * @param {number} amount The amount to change the color by
+ * @returns {string} The processed part of the color
+ */
+const subtractLight = (color: string, amount: number) => {
+ const cc = parseInt(color, 16) - amount
+ const c = cc < 0 ? 0 : cc
+ return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`
+}
+
+// 预设颜色
+export const PREDEFINE_COLORS = [
+ '#ff4500',
+ '#ff8c00',
+ '#ffd700',
+ '#90ee90',
+ '#00ced1',
+ '#1e90ff',
+ '#c71585',
+ '#409EFF',
+ '#909399',
+ '#C0C4CC',
+ '#b7390b',
+ '#ff7800',
+ '#fad400',
+ '#5b8c5f',
+ '#00babd',
+ '#1f73c3',
+ '#711f57'
+]
diff --git a/marketing-ui/admin-ui/src/utils/constants.ts b/marketing-ui/admin-ui/src/utils/constants.ts
new file mode 100644
index 0000000..f673bdc
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/constants.ts
@@ -0,0 +1,465 @@
+/**
+ * Created by 芋道源码
+ *
+ * 枚举类
+ */
+
+// ========== COMMON 模块 ==========
+// 全局通用状态枚举
+export const CommonStatusEnum = {
+ ENABLE: 0, // 开启
+ DISABLE: 1 // 禁用
+}
+
+// 全局用户类型枚举
+export const UserTypeEnum = {
+ MEMBER: 1, // 会员
+ ADMIN: 2 // 管理员
+}
+
+// ========== SYSTEM 模块 ==========
+/**
+ * 菜单的类型枚举
+ */
+export const SystemMenuTypeEnum = {
+ DIR: 1, // 目录
+ MENU: 2, // 菜单
+ BUTTON: 3 // 按钮
+}
+
+/**
+ * 角色的类型枚举
+ */
+export const SystemRoleTypeEnum = {
+ SYSTEM: 1, // 内置角色
+ CUSTOM: 2 // 自定义角色
+}
+
+/**
+ * 数据权限的范围枚举
+ */
+export const SystemDataScopeEnum = {
+ ALL: 1, // 全部数据权限
+ DEPT_CUSTOM: 2, // 指定部门数据权限
+ DEPT_ONLY: 3, // 部门数据权限
+ DEPT_AND_CHILD: 4, // 部门及以下数据权限
+ DEPT_SELF: 5 // 仅本人数据权限
+}
+
+/**
+ * 用户的社交平台的类型枚举
+ */
+export const SystemUserSocialTypeEnum = {
+ DINGTALK: {
+ title: '钉钉',
+ type: 20,
+ source: 'dingtalk',
+ img: 'https://s1.ax1x.com/2022/05/22/OzMDRs.png'
+ },
+ WECHAT_ENTERPRISE: {
+ title: '企业微信',
+ type: 30,
+ source: 'wechat_enterprise',
+ img: 'https://s1.ax1x.com/2022/05/22/OzMrzn.png'
+ }
+}
+
+// ========== INFRA 模块 ==========
+/**
+ * 代码生成模板类型
+ */
+export const InfraCodegenTemplateTypeEnum = {
+ CRUD: 1, // 基础 CRUD
+ TREE: 2, // 树形 CRUD
+ SUB: 3 // 主子表 CRUD
+}
+
+/**
+ * 任务状态的枚举
+ */
+export const InfraJobStatusEnum = {
+ INIT: 0, // 初始化中
+ NORMAL: 1, // 运行中
+ STOP: 2 // 暂停运行
+}
+
+/**
+ * API 异常数据的处理状态
+ */
+export const InfraApiErrorLogProcessStatusEnum = {
+ INIT: 0, // 未处理
+ DONE: 1, // 已处理
+ IGNORE: 2 // 已忽略
+}
+
+// ========== PAY 模块 ==========
+/**
+ * 支付渠道枚举
+ */
+export const PayChannelEnum = {
+ WX_PUB: {
+ code: 'wx_pub',
+ name: '微信 JSAPI 支付'
+ },
+ WX_LITE: {
+ code: 'wx_lite',
+ name: '微信小程序支付'
+ },
+ WX_APP: {
+ code: 'wx_app',
+ name: '微信 APP 支付'
+ },
+ WX_NATIVE: {
+ code: 'wx_native',
+ name: '微信 Native 支付'
+ },
+ WX_WAP: {
+ code: 'wx_wap',
+ name: '微信 WAP 网站支付'
+ },
+ WX_BAR: {
+ code: 'wx_bar',
+ name: '微信条码支付'
+ },
+ ALIPAY_PC: {
+ code: 'alipay_pc',
+ name: '支付宝 PC 网站支付'
+ },
+ ALIPAY_WAP: {
+ code: 'alipay_wap',
+ name: '支付宝 WAP 网站支付'
+ },
+ ALIPAY_APP: {
+ code: 'alipay_app',
+ name: '支付宝 APP 支付'
+ },
+ ALIPAY_QR: {
+ code: 'alipay_qr',
+ name: '支付宝扫码支付'
+ },
+ ALIPAY_BAR: {
+ code: 'alipay_bar',
+ name: '支付宝条码支付'
+ },
+ WALLET: {
+ code: 'wallet',
+ name: '钱包支付'
+ },
+ MOCK: {
+ code: 'mock',
+ name: '模拟支付'
+ }
+}
+
+/**
+ * 支付的展示模式每局
+ */
+export const PayDisplayModeEnum = {
+ URL: {
+ mode: 'url'
+ },
+ IFRAME: {
+ mode: 'iframe'
+ },
+ FORM: {
+ mode: 'form'
+ },
+ QR_CODE: {
+ mode: 'qr_code'
+ },
+ APP: {
+ mode: 'app'
+ }
+}
+
+/**
+ * 支付类型枚举
+ */
+export const PayType = {
+ WECHAT: 'WECHAT',
+ ALIPAY: 'ALIPAY',
+ MOCK: 'MOCK'
+}
+
+/**
+ * 支付订单状态枚举
+ */
+export const PayOrderStatusEnum = {
+ WAITING: {
+ status: 0,
+ name: '未支付'
+ },
+ SUCCESS: {
+ status: 10,
+ name: '已支付'
+ },
+ CLOSED: {
+ status: 20,
+ name: '未支付'
+ }
+}
+
+// ========== MALL - 商品模块 ==========
+/**
+ * 商品 SPU 状态
+ */
+export const ProductSpuStatusEnum = {
+ RECYCLE: {
+ status: -1,
+ name: '回收站'
+ },
+ DISABLE: {
+ status: 0,
+ name: '下架'
+ },
+ ENABLE: {
+ status: 1,
+ name: '上架'
+ }
+}
+
+// ========== MALL - 营销模块 ==========
+/**
+ * 优惠劵模板的有限期类型的枚举
+ */
+export const CouponTemplateValidityTypeEnum = {
+ DATE: {
+ type: 1,
+ name: '固定日期可用'
+ },
+ TERM: {
+ type: 2,
+ name: '领取之后可用'
+ }
+}
+
+/**
+ * 优惠劵模板的领取方式的枚举
+ */
+export const CouponTemplateTakeTypeEnum = {
+ USER: {
+ type: 1,
+ name: '直接领取'
+ },
+ ADMIN: {
+ type: 2,
+ name: '指定发放'
+ },
+ REGISTER: {
+ type: 3,
+ name: '新人券'
+ }
+}
+
+/**
+ * 营销的商品范围枚举
+ */
+export const PromotionProductScopeEnum = {
+ ALL: {
+ scope: 1,
+ name: '通用劵'
+ },
+ SPU: {
+ scope: 2,
+ name: '商品劵'
+ },
+ CATEGORY: {
+ scope: 3,
+ name: '品类劵'
+ }
+}
+
+/**
+ * 营销的条件类型枚举
+ */
+export const PromotionConditionTypeEnum = {
+ PRICE: {
+ type: 10,
+ name: '满 N 元'
+ },
+ COUNT: {
+ type: 20,
+ name: '满 N 件'
+ }
+}
+
+/**
+ * 优惠类型枚举
+ */
+export const PromotionDiscountTypeEnum = {
+ PRICE: {
+ type: 1,
+ name: '满减'
+ },
+ PERCENT: {
+ type: 2,
+ name: '折扣'
+ }
+}
+
+// ========== MALL - 交易模块 ==========
+/**
+ * 分销关系绑定模式枚举
+ */
+export const BrokerageBindModeEnum = {
+ ANYTIME: {
+ mode: 1,
+ name: '首次绑定'
+ },
+ REGISTER: {
+ mode: 2,
+ name: '注册绑定'
+ },
+ OVERRIDE: {
+ mode: 3,
+ name: '覆盖绑定'
+ }
+}
+/**
+ * 分佣模式枚举
+ */
+export const BrokerageEnabledConditionEnum = {
+ ALL: {
+ condition: 1,
+ name: '人人分销'
+ },
+ ADMIN: {
+ condition: 2,
+ name: '指定分销'
+ }
+}
+/**
+ * 佣金记录业务类型枚举
+ */
+export const BrokerageRecordBizTypeEnum = {
+ ORDER: {
+ type: 1,
+ name: '获得推广佣金'
+ },
+ WITHDRAW: {
+ type: 2,
+ name: '提现申请'
+ }
+}
+/**
+ * 佣金提现状态枚举
+ */
+export const BrokerageWithdrawStatusEnum = {
+ AUDITING: {
+ status: 0,
+ name: '审核中'
+ },
+ AUDIT_SUCCESS: {
+ status: 10,
+ name: '审核通过'
+ },
+ AUDIT_FAIL: {
+ status: 20,
+ name: '审核不通过'
+ },
+ WITHDRAW_SUCCESS: {
+ status: 11,
+ name: '提现成功'
+ },
+ WITHDRAW_FAIL: {
+ status: 21,
+ name: '提现失败'
+ }
+}
+/**
+ * 佣金提现类型枚举
+ */
+export const BrokerageWithdrawTypeEnum = {
+ WALLET: {
+ type: 1,
+ name: '钱包'
+ },
+ BANK: {
+ type: 2,
+ name: '银行卡'
+ },
+ WECHAT: {
+ type: 3,
+ name: '微信'
+ },
+ ALIPAY: {
+ type: 4,
+ name: '支付宝'
+ }
+}
+
+/**
+ * 配送方式枚举
+ */
+export const DeliveryTypeEnum = {
+ EXPRESS: {
+ type: 1,
+ name: '快递发货'
+ },
+ PICK_UP: {
+ type: 2,
+ name: '到店自提'
+ }
+}
+/**
+ * 交易订单 - 状态
+ */
+export const TradeOrderStatusEnum = {
+ UNPAID: {
+ status: 0,
+ name: '待支付'
+ },
+ UNDELIVERED: {
+ status: 10,
+ name: '待发货'
+ },
+ DELIVERED: {
+ status: 20,
+ name: '已发货'
+ },
+ COMPLETED: {
+ status: 30,
+ name: '已完成'
+ },
+ CANCELED: {
+ status: 40,
+ name: '已取消'
+ }
+}
+
+// ========== ERP - 企业资源计划 ==========
+
+export const ErpBizType = {
+ PURCHASE_ORDER: 10,
+ PURCHASE_IN: 11,
+ PURCHASE_RETURN: 12,
+ SALE_ORDER: 20,
+ SALE_OUT: 21,
+ SALE_RETURN: 22
+}
+
+// ========== BPM 模块 ==========
+
+export const BpmModelType = {
+ BPMN: 10, // BPMN 设计器
+ SIMPLE: 20 // 简易设计器
+}
+
+export const BpmModelFormType = {
+ NORMAL: 10, // 流程表单
+ CUSTOM: 20 // 业务表单
+}
+
+export const BpmProcessInstanceStatus = {
+ NOT_START: -1, // 未开始
+ RUNNING: 1, // 审批中
+ APPROVE: 2, // 审批通过
+ REJECT: 3, // 审批不通过
+ CANCEL: 4 // 已取消
+}
+
+export const BpmAutoApproveType = {
+ NONE: 0, // 不自动通过
+ APPROVE_ALL: 1, // 仅审批一次,后续重复的审批节点均自动通过
+ APPROVE_SEQUENT: 2, // 仅针对连续审批的节点自动通过
+}
diff --git a/marketing-ui/admin-ui/src/utils/dateUtil.ts b/marketing-ui/admin-ui/src/utils/dateUtil.ts
new file mode 100644
index 0000000..316b870
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/dateUtil.ts
@@ -0,0 +1,18 @@
+/**
+ * Independent time operation tool to facilitate subsequent switch to dayjs
+ */
+// TODO 芋艿:【锁屏】可能后面删除掉
+import dayjs from 'dayjs'
+
+const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
+const DATE_FORMAT = 'YYYY-MM-DD'
+
+export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FORMAT): string {
+ return dayjs(date).format(format)
+}
+
+export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string {
+ return dayjs(date).format(format)
+}
+
+export const dateUtil = dayjs
diff --git a/marketing-ui/admin-ui/src/utils/dict.ts b/marketing-ui/admin-ui/src/utils/dict.ts
new file mode 100644
index 0000000..083c1ef
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/dict.ts
@@ -0,0 +1,158 @@
+/**
+ * 数据字典工具类
+ */
+import { useDictStoreWithOut } from '@/store/modules/dict'
+import { ElementPlusInfoType } from '@/types/elementPlus'
+
+const dictStore = useDictStoreWithOut()
+
+/**
+ * 获取 dictType 对应的数据字典数组
+ *
+ * @param dictType 数据类型
+ * @returns {*|Array} 数据字典数组
+ */
+export interface DictDataType {
+ dictType: string
+ label: string
+ value: string | number | boolean
+ colorType: ElementPlusInfoType | ''
+ cssClass: string
+}
+
+export interface NumberDictDataType extends DictDataType {
+ value: number
+}
+
+export interface StringDictDataType extends DictDataType {
+ value: string
+}
+
+export const getDictOptions = (dictType: string) => {
+ return dictStore.getDictByType(dictType) || []
+}
+
+export const getIntDictOptions = (dictType: string): NumberDictDataType[] => {
+ // 获得通用的 DictDataType 列表
+ const dictOptions: DictDataType[] = getDictOptions(dictType)
+ // 转换成 number 类型的 NumberDictDataType 类型
+ // why 需要特殊转换:避免 IDEA 在 v-for="dict in getIntDictOptions(...)" 时,el-option 的 key 会告警
+ const dictOption: NumberDictDataType[] = []
+ dictOptions.forEach((dict: DictDataType) => {
+ dictOption.push({
+ ...dict,
+ value: parseInt(dict.value + '')
+ })
+ })
+ return dictOption
+}
+
+export const getStrDictOptions = (dictType: string) => {
+ // 获得通用的 DictDataType 列表
+ const dictOptions: DictDataType[] = getDictOptions(dictType)
+ // 转换成 string 类型的 StringDictDataType 类型
+ // why 需要特殊转换:避免 IDEA 在 v-for="dict in getStrDictOptions(...)" 时,el-option 的 key 会告警
+ const dictOption: StringDictDataType[] = []
+ dictOptions.forEach((dict: DictDataType) => {
+ dictOption.push({
+ ...dict,
+ value: dict.value + ''
+ })
+ })
+ return dictOption
+}
+
+export const getBoolDictOptions = (dictType: string) => {
+ const dictOption: DictDataType[] = []
+ const dictOptions: DictDataType[] = getDictOptions(dictType)
+ dictOptions.forEach((dict: DictDataType) => {
+ dictOption.push({
+ ...dict,
+ value: dict.value + '' === 'true'
+ })
+ })
+ return dictOption
+}
+
+/**
+ * 获取指定字典类型的指定值对应的字典对象
+ * @param dictType 字典类型
+ * @param value 字典值
+ * @return DictDataType 字典对象
+ */
+export const getDictObj = (dictType: string, value: any): DictDataType | undefined => {
+ const dictOptions: DictDataType[] = getDictOptions(dictType)
+ for (const dict of dictOptions) {
+ if (dict.value === value + '') {
+ return dict
+ }
+ }
+}
+
+/**
+ * 获得字典数据的文本展示
+ *
+ * @param dictType 字典类型
+ * @param value 字典数据的值
+ * @return 字典名称
+ */
+export const getDictLabel = (dictType: string, value: any): string => {
+ const dictOptions: DictDataType[] = getDictOptions(dictType)
+ const dictLabel = ref('')
+ dictOptions.forEach((dict: DictDataType) => {
+ if (dict.value === value + '') {
+ dictLabel.value = dict.label
+ }
+ })
+ return dictLabel.value
+}
+
+export enum DICT_TYPE {
+ USER_TYPE = 'user_type',
+ COMMON_STATUS = 'common_status',
+ TERMINAL = 'terminal', // 终端
+ DATE_INTERVAL = 'date_interval', // 数据间隔
+
+ // ========== SYSTEM 模块 ==========
+ SYSTEM_USER_SEX = 'system_user_sex',
+ SYSTEM_MENU_TYPE = 'system_menu_type',
+ SYSTEM_ROLE_TYPE = 'system_role_type',
+ SYSTEM_DATA_SCOPE = 'system_data_scope',
+ SYSTEM_NOTICE_TYPE = 'system_notice_type',
+ SYSTEM_LOGIN_TYPE = 'system_login_type',
+ SYSTEM_LOGIN_RESULT = 'system_login_result',
+ SYSTEM_SMS_CHANNEL_CODE = 'system_sms_channel_code',
+ SYSTEM_SMS_TEMPLATE_TYPE = 'system_sms_template_type',
+ SYSTEM_SMS_SEND_STATUS = 'system_sms_send_status',
+ SYSTEM_SMS_RECEIVE_STATUS = 'system_sms_receive_status',
+ SYSTEM_OAUTH2_GRANT_TYPE = 'system_oauth2_grant_type',
+ SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status',
+ SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type',
+ SYSTEM_SOCIAL_TYPE = 'system_social_type',
+
+ // ========== INFRA 模块 ==========
+ INFRA_BOOLEAN_STRING = 'infra_boolean_string',
+ INFRA_JOB_STATUS = 'infra_job_status',
+ INFRA_JOB_LOG_STATUS = 'infra_job_log_status',
+ INFRA_API_ERROR_LOG_PROCESS_STATUS = 'infra_api_error_log_process_status',
+ INFRA_CONFIG_TYPE = 'infra_config_type',
+ INFRA_CODEGEN_TEMPLATE_TYPE = 'infra_codegen_template_type',
+ INFRA_CODEGEN_FRONT_TYPE = 'infra_codegen_front_type',
+ INFRA_CODEGEN_SCENE = 'infra_codegen_scene',
+ INFRA_FILE_STORAGE = 'infra_file_storage',
+ INFRA_OPERATE_TYPE = 'infra_operate_type',
+
+ // ========== AI - 人工智能模块 ==========
+ AI_PLATFORM = 'ai_platform', // AI 平台
+ AI_MODEL_TYPE = 'ai_model_type', // AI 模型类型
+ AI_IMAGE_STATUS = 'ai_image_status', // AI 图片状态
+ AI_MUSIC_STATUS = 'ai_music_status', // AI 音乐状态
+ AI_GENERATE_MODE = 'ai_generate_mode', // AI 生成模式
+ AI_WRITE_TYPE = 'ai_write_type', // AI 写作类型
+ AI_WRITE_LENGTH = 'ai_write_length', // AI 写作长度
+ AI_WRITE_FORMAT = 'ai_write_format', // AI 写作格式
+ AI_WRITE_TONE = 'ai_write_tone', // AI 写作语气
+ AI_WRITE_LANGUAGE = 'ai_write_language', // AI 写作语言
+
+
+}
diff --git a/marketing-ui/admin-ui/src/utils/domUtils.ts b/marketing-ui/admin-ui/src/utils/domUtils.ts
new file mode 100644
index 0000000..dbc1989
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/domUtils.ts
@@ -0,0 +1,289 @@
+import { isServer } from './is'
+const ieVersion = isServer ? 0 : Number((document as any).documentMode)
+const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g
+const MOZ_HACK_REGEXP = /^moz([A-Z])/
+
+export interface ViewportOffsetResult {
+ left: number
+ top: number
+ right: number
+ bottom: number
+ rightIncludeBody: number
+ bottomIncludeBody: number
+}
+
+/* istanbul ignore next */
+const trim = function (string: string) {
+ return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '')
+}
+
+/* istanbul ignore next */
+const camelCase = function (name: string) {
+ return name
+ .replace(SPECIAL_CHARS_REGEXP, function (_, __, letter, offset) {
+ return offset ? letter.toUpperCase() : letter
+ })
+ .replace(MOZ_HACK_REGEXP, 'Moz$1')
+}
+
+/* istanbul ignore next */
+export function hasClass(el: Element, cls: string) {
+ if (!el || !cls) return false
+ if (cls.indexOf(' ') !== -1) {
+ throw new Error('className should not contain space.')
+ }
+ if (el.classList) {
+ return el.classList.contains(cls)
+ } else {
+ return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1
+ }
+}
+
+/* istanbul ignore next */
+export function addClass(el: Element, cls: string) {
+ if (!el) return
+ let curClass = el.className
+ const classes = (cls || '').split(' ')
+
+ for (let i = 0, j = classes.length; i < j; i++) {
+ const clsName = classes[i]
+ if (!clsName) continue
+
+ if (el.classList) {
+ el.classList.add(clsName)
+ } else if (!hasClass(el, clsName)) {
+ curClass += ' ' + clsName
+ }
+ }
+ if (!el.classList) {
+ el.className = curClass
+ }
+}
+
+/* istanbul ignore next */
+export function removeClass(el: Element, cls: string) {
+ if (!el || !cls) return
+ const classes = cls.split(' ')
+ let curClass = ' ' + el.className + ' '
+
+ for (let i = 0, j = classes.length; i < j; i++) {
+ const clsName = classes[i]
+ if (!clsName) continue
+
+ if (el.classList) {
+ el.classList.remove(clsName)
+ } else if (hasClass(el, clsName)) {
+ curClass = curClass.replace(' ' + clsName + ' ', ' ')
+ }
+ }
+ if (!el.classList) {
+ el.className = trim(curClass)
+ }
+}
+
+export function getBoundingClientRect(element: Element): DOMRect | number {
+ if (!element || !element.getBoundingClientRect) {
+ return 0
+ }
+ return element.getBoundingClientRect()
+}
+
+/**
+ * 获取当前元素的left、top偏移
+ * left:元素最左侧距离文档左侧的距离
+ * top:元素最顶端距离文档顶端的距离
+ * right:元素最右侧距离文档右侧的距离
+ * bottom:元素最底端距离文档底端的距离
+ * rightIncludeBody:元素最左侧距离文档右侧的距离
+ * bottomIncludeBody:元素最底端距离文档最底部的距离
+ *
+ * @description:
+ */
+export function getViewportOffset(element: Element): ViewportOffsetResult {
+ const doc = document.documentElement
+
+ const docScrollLeft = doc.scrollLeft
+ const docScrollTop = doc.scrollTop
+ const docClientLeft = doc.clientLeft
+ const docClientTop = doc.clientTop
+
+ const pageXOffset = window.pageXOffset
+ const pageYOffset = window.pageYOffset
+
+ const box = getBoundingClientRect(element)
+
+ const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect
+
+ const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0)
+ const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0)
+ const offsetLeft = retLeft + pageXOffset
+ const offsetTop = rectTop + pageYOffset
+
+ const left = offsetLeft - scrollLeft
+ const top = offsetTop - scrollTop
+
+ const clientWidth = window.document.documentElement.clientWidth
+ const clientHeight = window.document.documentElement.clientHeight
+ return {
+ left: left,
+ top: top,
+ right: clientWidth - rectWidth - left,
+ bottom: clientHeight - rectHeight - top,
+ rightIncludeBody: clientWidth - left,
+ bottomIncludeBody: clientHeight - top
+ }
+}
+
+/* istanbul ignore next */
+export const on = function (
+ element: HTMLElement | Document | Window,
+ event: string,
+ handler: EventListenerOrEventListenerObject
+): void {
+ if (element && event && handler) {
+ element.addEventListener(event, handler, false)
+ }
+}
+
+/* istanbul ignore next */
+export const off = function (
+ element: HTMLElement | Document | Window,
+ event: string,
+ handler: any
+): void {
+ if (element && event && handler) {
+ element.removeEventListener(event, handler, false)
+ }
+}
+
+/* istanbul ignore next */
+export const once = function (el: HTMLElement, event: string, fn: EventListener): void {
+ const listener = function (this: any, ...args: unknown[]) {
+ if (fn) {
+ // @ts-ignore
+ fn.apply(this, args)
+ }
+ off(el, event, listener)
+ }
+ on(el, event, listener)
+}
+
+/* istanbul ignore next */
+export const getStyle =
+ ieVersion < 9
+ ? function (element: Element | any, styleName: string) {
+ if (isServer) return
+ if (!element || !styleName) return null
+ styleName = camelCase(styleName)
+ if (styleName === 'float') {
+ styleName = 'styleFloat'
+ }
+ try {
+ switch (styleName) {
+ case 'opacity':
+ try {
+ return element.filters.item('alpha').opacity / 100
+ } catch (e) {
+ return 1.0
+ }
+ default:
+ return element.style[styleName] || element.currentStyle
+ ? element.currentStyle[styleName]
+ : null
+ }
+ } catch (e) {
+ return element.style[styleName]
+ }
+ }
+ : function (element: Element | any, styleName: string) {
+ if (isServer) return
+ if (!element || !styleName) return null
+ styleName = camelCase(styleName)
+ if (styleName === 'float') {
+ styleName = 'cssFloat'
+ }
+ try {
+ const computed = (document as any).defaultView.getComputedStyle(element, '')
+ return element.style[styleName] || computed ? computed[styleName] : null
+ } catch (e) {
+ return element.style[styleName]
+ }
+ }
+
+/* istanbul ignore next */
+export function setStyle(element: Element | any, styleName: any, value: any) {
+ if (!element || !styleName) return
+
+ if (typeof styleName === 'object') {
+ for (const prop in styleName) {
+ if (Object.prototype.hasOwnProperty.call(styleName, prop)) {
+ setStyle(element, prop, styleName[prop])
+ }
+ }
+ } else {
+ styleName = camelCase(styleName)
+ if (styleName === 'opacity' && ieVersion < 9) {
+ element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')'
+ } else {
+ element.style[styleName] = value
+ }
+ }
+}
+
+/* istanbul ignore next */
+export const isScroll = (el: Element, vertical: any) => {
+ if (isServer) return
+
+ const determinedDirection = vertical !== null || vertical !== undefined
+ const overflow = determinedDirection
+ ? vertical
+ ? getStyle(el, 'overflow-y')
+ : getStyle(el, 'overflow-x')
+ : getStyle(el, 'overflow')
+
+ return overflow.match(/(scroll|auto)/)
+}
+
+/* istanbul ignore next */
+export const getScrollContainer = (el: Element, vertical?: any) => {
+ if (isServer) return
+
+ let parent: any = el
+ while (parent) {
+ if ([window, document, document.documentElement].includes(parent)) {
+ return window
+ }
+ if (isScroll(parent, vertical)) {
+ return parent
+ }
+ parent = parent.parentNode
+ }
+
+ return parent
+}
+
+/* istanbul ignore next */
+export const isInContainer = (el: Element, container: any) => {
+ if (isServer || !el || !container) return false
+
+ const elRect = el.getBoundingClientRect()
+ let containerRect
+
+ if ([window, document, document.documentElement, null, undefined].includes(container)) {
+ containerRect = {
+ top: 0,
+ right: window.innerWidth,
+ bottom: window.innerHeight,
+ left: 0
+ }
+ } else {
+ containerRect = container.getBoundingClientRect()
+ }
+
+ return (
+ elRect.top < containerRect.bottom &&
+ elRect.bottom > containerRect.top &&
+ elRect.right > containerRect.left &&
+ elRect.left < containerRect.right
+ )
+}
diff --git a/marketing-ui/admin-ui/src/utils/download.ts b/marketing-ui/admin-ui/src/utils/download.ts
new file mode 100644
index 0000000..32fc624
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/download.ts
@@ -0,0 +1,100 @@
+const download0 = (data: Blob, fileName: string, mineType: string) => {
+ // 创建 blob
+ const blob = new Blob([data], { type: mineType })
+ // 创建 href 超链接,点击进行下载
+ window.URL = window.URL || window.webkitURL
+ const href = URL.createObjectURL(blob)
+ const downA = document.createElement('a')
+ downA.href = href
+ downA.download = fileName
+ downA.click()
+ // 销毁超连接
+ window.URL.revokeObjectURL(href)
+}
+
+const download = {
+ // 下载 Excel 方法
+ excel: (data: Blob, fileName: string) => {
+ download0(data, fileName, 'application/vnd.ms-excel')
+ },
+ // 下载 Word 方法
+ word: (data: Blob, fileName: string) => {
+ download0(data, fileName, 'application/msword')
+ },
+ // 下载 Zip 方法
+ zip: (data: Blob, fileName: string) => {
+ download0(data, fileName, 'application/zip')
+ },
+ // 下载 Html 方法
+ html: (data: Blob, fileName: string) => {
+ download0(data, fileName, 'text/html')
+ },
+ // 下载 Markdown 方法
+ markdown: (data: Blob, fileName: string) => {
+ download0(data, fileName, 'text/markdown')
+ },
+ // 下载 Json 方法
+ json: (data: Blob, fileName: string) => {
+ download0(data, fileName, 'application/json')
+ },
+ // 下载图片(允许跨域)
+ image: ({
+ url,
+ canvasWidth,
+ canvasHeight,
+ drawWithImageSize = true
+ }: {
+ url: string
+ canvasWidth?: number // 指定画布宽度
+ canvasHeight?: number // 指定画布高度
+ drawWithImageSize?: boolean // 将图片绘制在画布上时带上图片的宽高值, 默认是要带上的
+ }) => {
+ const image = new Image()
+ // image.setAttribute('crossOrigin', 'anonymous')
+ image.src = url
+ image.onload = () => {
+ const canvas = document.createElement('canvas')
+ canvas.width = canvasWidth || image.width
+ canvas.height = canvasHeight || image.height
+ const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
+ ctx?.clearRect(0, 0, canvas.width, canvas.height)
+ if (drawWithImageSize) {
+ ctx.drawImage(image, 0, 0, image.width, image.height)
+ } else {
+ ctx.drawImage(image, 0, 0)
+ }
+ const url = canvas.toDataURL('image/png')
+ const a = document.createElement('a')
+ a.href = url
+ a.download = 'image.png'
+ a.click()
+ }
+ },
+ base64ToFile: (base64: any, fileName: string) => {
+ // 将base64按照 , 进行分割 将前缀 与后续内容分隔开
+ const data = base64.split(',')
+ // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
+ const type = data[0].match(/:(.*?);/)[1]
+ // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
+ const suffix = type.split('/')[1]
+ // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出
+ const bstr = window.atob(data[1])
+ // 获取解码结果字符串的长度
+ let n = bstr.length
+ // 根据解码结果字符串的长度创建一个等长的整形数字数组
+ // 但在创建时 所有元素初始值都为 0
+ const u8arr = new Uint8Array(n)
+ // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
+ while (n--) {
+ // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
+ u8arr[n] = bstr.charCodeAt(n)
+ }
+
+ // 将File文件对象返回给方法的调用者
+ return new File([u8arr], `${fileName}.${suffix}`, {
+ type: type
+ })
+ }
+}
+
+export default download
diff --git a/marketing-ui/admin-ui/src/utils/filt.ts b/marketing-ui/admin-ui/src/utils/filt.ts
new file mode 100644
index 0000000..b1a7b2c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/filt.ts
@@ -0,0 +1,157 @@
+export const openWindow = (
+ url: string,
+ opt?: {
+ target?: '_self' | '_blank' | string
+ noopener?: boolean
+ noreferrer?: boolean
+ }
+) => {
+ const { target = '__blank', noopener = true, noreferrer = true } = opt || {}
+ const feature: string[] = []
+
+ noopener && feature.push('noopener=yes')
+ noreferrer && feature.push('noreferrer=yes')
+
+ window.open(url, target, feature.join(','))
+}
+
+/**
+ * @description: base64 to blob
+ */
+export const dataURLtoBlob = (base64Buf: string): Blob => {
+ const arr = base64Buf.split(',')
+ const typeItem = arr[0]
+ const mime = typeItem.match(/:(.*?);/)![1]
+ const bstr = window.atob(arr[1])
+ let n = bstr.length
+ const u8arr = new Uint8Array(n)
+ while (n--) {
+ u8arr[n] = bstr.charCodeAt(n)
+ }
+ return new Blob([u8arr], { type: mime })
+}
+
+/**
+ * img url to base64
+ * @param url
+ */
+export const urlToBase64 = (url: string, mineType?: string): Promise => {
+ return new Promise((resolve, reject) => {
+ let canvas = document.createElement('CANVAS') as Nullable
+ const ctx = canvas!.getContext('2d')
+
+ const img = new Image()
+ img.crossOrigin = ''
+ img.onload = function () {
+ if (!canvas || !ctx) {
+ return reject()
+ }
+ canvas.height = img.height
+ canvas.width = img.width
+ ctx.drawImage(img, 0, 0)
+ const dataURL = canvas.toDataURL(mineType || 'image/png')
+ canvas = null
+ resolve(dataURL)
+ }
+ img.src = url
+ })
+}
+
+/**
+ * Download online pictures
+ * @param url
+ * @param filename
+ * @param mime
+ * @param bom
+ */
+export const downloadByOnlineUrl = (
+ url: string,
+ filename: string,
+ mime?: string,
+ bom?: BlobPart
+) => {
+ urlToBase64(url).then((base64) => {
+ downloadByBase64(base64, filename, mime, bom)
+ })
+}
+
+/**
+ * Download pictures based on base64
+ * @param buf
+ * @param filename
+ * @param mime
+ * @param bom
+ */
+export const downloadByBase64 = (buf: string, filename: string, mime?: string, bom?: BlobPart) => {
+ const base64Buf = dataURLtoBlob(buf)
+ downloadByData(base64Buf, filename, mime, bom)
+}
+
+/**
+ * Download according to the background interface file stream
+ * @param {*} data
+ * @param {*} filename
+ * @param {*} mime
+ * @param {*} bom
+ */
+export const downloadByData = (data: BlobPart, filename: string, mime?: string, bom?: BlobPart) => {
+ const blobData = typeof bom !== 'undefined' ? [bom, data] : [data]
+ const blob = new Blob(blobData, { type: mime || 'application/octet-stream' })
+
+ const blobURL = window.URL.createObjectURL(blob)
+ const tempLink = document.createElement('a')
+ tempLink.style.display = 'none'
+ tempLink.href = blobURL
+ tempLink.setAttribute('download', filename)
+ if (typeof tempLink.download === 'undefined') {
+ tempLink.setAttribute('target', '_blank')
+ }
+ document.body.appendChild(tempLink)
+ tempLink.click()
+ document.body.removeChild(tempLink)
+ window.URL.revokeObjectURL(blobURL)
+}
+
+/**
+ * Download file according to file address
+ * @param {*} sUrl
+ */
+export const downloadByUrl = ({
+ url,
+ target = '_blank',
+ fileName
+}: {
+ url: string
+ target?: '_self' | '_blank'
+ fileName?: string
+}): boolean => {
+ const isChrome = window.navigator.userAgent.toLowerCase().indexOf('chrome') > -1
+ const isSafari = window.navigator.userAgent.toLowerCase().indexOf('safari') > -1
+
+ if (/(iP)/g.test(window.navigator.userAgent)) {
+ console.error('Your browser does not support download!')
+ return false
+ }
+ if (isChrome || isSafari) {
+ const link = document.createElement('a')
+ link.href = url
+ link.target = target
+
+ if (link.download !== undefined) {
+ link.download = fileName || url.substring(url.lastIndexOf('/') + 1, url.length)
+ }
+
+ if (document.createEvent) {
+ const e = document.createEvent('MouseEvents')
+ e.initEvent('click', true, true)
+ link.dispatchEvent(e)
+ return true
+ }
+ }
+ if (url.indexOf('?') === -1) {
+ url += '?download'
+ }
+
+ openWindow(url, { target })
+ return true
+}
diff --git a/marketing-ui/admin-ui/src/utils/formCreate.ts b/marketing-ui/admin-ui/src/utils/formCreate.ts
new file mode 100644
index 0000000..d56e512
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/formCreate.ts
@@ -0,0 +1,58 @@
+/**
+ * 针对 https://github.com/xaboy/form-create-designer 封装的工具类
+ */
+
+// 编码表单 Conf
+export const encodeConf = (designerRef: object) => {
+ // @ts-ignore
+ return JSON.stringify(designerRef.value.getOption())
+}
+
+// 编码表单 Fields
+export const encodeFields = (designerRef: object) => {
+ // @ts-ignore
+ const rule = JSON.parse(designerRef.value.getJson())
+ const fields: string[] = []
+ rule.forEach((item) => {
+ fields.push(JSON.stringify(item))
+ })
+ return fields
+}
+
+// 解码表单 Fields
+export const decodeFields = (fields: string[]) => {
+ const rule: object[] = []
+ fields.forEach((item) => {
+ rule.push(JSON.parse(item))
+ })
+ return rule
+}
+
+// 设置表单的 Conf 和 Fields,适用 FcDesigner 场景
+export const setConfAndFields = (designerRef: object, conf: string, fields: string) => {
+ // @ts-ignore
+ designerRef.value.setOption(JSON.parse(conf))
+ // @ts-ignore
+ designerRef.value.setRule(decodeFields(fields))
+}
+
+// 设置表单的 Conf 和 Fields,适用 form-create 场景
+export const setConfAndFields2 = (
+ detailPreview: object,
+ conf: string,
+ fields: string[],
+ value?: object
+) => {
+ if (isRef(detailPreview)) {
+ // @ts-ignore
+ detailPreview = detailPreview.value
+ }
+ // @ts-ignore
+ detailPreview.option = JSON.parse(conf)
+ // @ts-ignore
+ detailPreview.rule = decodeFields(fields)
+ if (value) {
+ // @ts-ignore
+ detailPreview.value = value
+ }
+}
diff --git a/marketing-ui/admin-ui/src/utils/formRules.ts b/marketing-ui/admin-ui/src/utils/formRules.ts
new file mode 100644
index 0000000..2989867
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/formRules.ts
@@ -0,0 +1,7 @@
+const { t } = useI18n()
+
+// 必填项
+export const required = {
+ required: true,
+ message: t('common.required')
+}
diff --git a/marketing-ui/admin-ui/src/utils/formatTime.ts b/marketing-ui/admin-ui/src/utils/formatTime.ts
new file mode 100644
index 0000000..2b08495
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/formatTime.ts
@@ -0,0 +1,356 @@
+import dayjs from 'dayjs'
+import type { TableColumnCtx } from 'element-plus'
+
+/**
+ * 日期快捷选项适用于 el-date-picker
+ */
+export const defaultShortcuts = [
+ {
+ text: '今天',
+ value: () => {
+ return new Date()
+ }
+ },
+ {
+ text: '昨天',
+ value: () => {
+ const date = new Date()
+ date.setTime(date.getTime() - 3600 * 1000 * 24)
+ return [date, date]
+ }
+ },
+ {
+ text: '最近七天',
+ value: () => {
+ const date = new Date()
+ date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+ return [date, new Date()]
+ }
+ },
+ {
+ text: '最近 30 天',
+ value: () => {
+ const date = new Date()
+ date.setTime(date.getTime() - 3600 * 1000 * 24 * 30)
+ return [date, new Date()]
+ }
+ },
+ {
+ text: '本月',
+ value: () => {
+ const date = new Date()
+ date.setDate(1) // 设置为当前月的第一天
+ return [date, new Date()]
+ }
+ },
+ {
+ text: '今年',
+ value: () => {
+ const date = new Date()
+ return [new Date(`${date.getFullYear()}-01-01`), date]
+ }
+ }
+]
+
+/**
+ * 时间日期转换
+ * @param date 当前时间,new Date() 格式
+ * @param format 需要转换的时间格式字符串
+ * @description format 字符串随意,如 `YYYY-MM、YYYY-MM-DD`
+ * @description format 季度:"YYYY-MM-DD HH:mm:ss QQQQ"
+ * @description format 星期:"YYYY-MM-DD HH:mm:ss WWW"
+ * @description format 几周:"YYYY-MM-DD HH:mm:ss ZZZ"
+ * @description format 季度 + 星期 + 几周:"YYYY-MM-DD HH:mm:ss WWW QQQQ ZZZ"
+ * @returns 返回拼接后的时间字符串
+ */
+export function formatDate(date: Date | number | string, format?: string): string {
+ // 日期不存在,则返回空
+ if (!date) {
+ return ''
+ }
+ // 日期存在,则进行格式化
+ return date ? dayjs(date).format(format ?? 'YYYY-MM-DD HH:mm:ss') : ''
+}
+
+/**
+ * 获取当前的日期+时间
+ */
+export function getNowDateTime() {
+ return dayjs()
+}
+
+/**
+ * 获取当前日期是第几周
+ * @param dateTime 当前传入的日期值
+ * @returns 返回第几周数字值
+ */
+export function getWeek(dateTime: Date): number {
+ const temptTime = new Date(dateTime.getTime())
+ // 周几
+ const weekday = temptTime.getDay() || 7
+ // 周1+5天=周六
+ temptTime.setDate(temptTime.getDate() - weekday + 1 + 5)
+ let firstDay = new Date(temptTime.getFullYear(), 0, 1)
+ const dayOfWeek = firstDay.getDay()
+ let spendDay = 1
+ if (dayOfWeek != 0) spendDay = 7 - dayOfWeek + 1
+ firstDay = new Date(temptTime.getFullYear(), 0, 1 + spendDay)
+ const d = Math.ceil((temptTime.valueOf() - firstDay.valueOf()) / 86400000)
+ return Math.ceil(d / 7)
+}
+
+/**
+ * 将时间转换为 `几秒前`、`几分钟前`、`几小时前`、`几天前`
+ * @param param 当前时间,new Date() 格式或者字符串时间格式
+ * @param format 需要转换的时间格式字符串
+ * @description param 10秒: 10 * 1000
+ * @description param 1分: 60 * 1000
+ * @description param 1小时: 60 * 60 * 1000
+ * @description param 24小时:60 * 60 * 24 * 1000
+ * @description param 3天: 60 * 60* 24 * 1000 * 3
+ * @returns 返回拼接后的时间字符串
+ */
+export function formatPast(param: string | Date, format = 'YYYY-MM-DD HH:mm:ss'): string {
+ // 传入格式处理、存储转换值
+ let t: any, s: number
+ // 获取js 时间戳
+ let time: number = new Date().getTime()
+ // 是否是对象
+ typeof param === 'string' || 'object' ? (t = new Date(param).getTime()) : (t = param)
+ // 当前时间戳 - 传入时间戳
+ time = Number.parseInt(`${time - t}`)
+ if (time < 10000) {
+ // 10秒内
+ return '刚刚'
+ } else if (time < 60000 && time >= 10000) {
+ // 超过10秒少于1分钟内
+ s = Math.floor(time / 1000)
+ return `${s}秒前`
+ } else if (time < 3600000 && time >= 60000) {
+ // 超过1分钟少于1小时
+ s = Math.floor(time / 60000)
+ return `${s}分钟前`
+ } else if (time < 86400000 && time >= 3600000) {
+ // 超过1小时少于24小时
+ s = Math.floor(time / 3600000)
+ return `${s}小时前`
+ } else if (time < 259200000 && time >= 86400000) {
+ // 超过1天少于3天内
+ s = Math.floor(time / 86400000)
+ return `${s}天前`
+ } else {
+ // 超过3天
+ const date = typeof param === 'string' || 'object' ? new Date(param) : param
+ return formatDate(date, format)
+ }
+}
+
+/**
+ * 时间问候语
+ * @param param 当前时间,new Date() 格式
+ * @description param 调用 `formatAxis(new Date())` 输出 `上午好`
+ * @returns 返回拼接后的时间字符串
+ */
+export function formatAxis(param: Date): string {
+ const hour: number = new Date(param).getHours()
+ if (hour < 6) return '凌晨好'
+ else if (hour < 9) return '早上好'
+ else if (hour < 12) return '上午好'
+ else if (hour < 14) return '中午好'
+ else if (hour < 17) return '下午好'
+ else if (hour < 19) return '傍晚好'
+ else if (hour < 22) return '晚上好'
+ else return '夜里好'
+}
+
+/**
+ * 将毫秒,转换成时间字符串。例如说,xx 分钟
+ *
+ * @param ms 毫秒
+ * @returns {string} 字符串
+ */
+export function formatPast2(ms: number): string {
+ const day = Math.floor(ms / (24 * 60 * 60 * 1000))
+ const hour = Math.floor(ms / (60 * 60 * 1000) - day * 24)
+ const minute = Math.floor(ms / (60 * 1000) - day * 24 * 60 - hour * 60)
+ const second = Math.floor(ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60)
+ if (day > 0) {
+ return day + ' 天' + hour + ' 小时 ' + minute + ' 分钟'
+ }
+ if (hour > 0) {
+ return hour + ' 小时 ' + minute + ' 分钟'
+ }
+ if (minute > 0) {
+ return minute + ' 分钟'
+ }
+ if (second > 0) {
+ return second + ' 秒'
+ } else {
+ return 0 + ' 秒'
+ }
+}
+
+/**
+ * element plus 的时间 Formatter 实现,使用 YYYY-MM-DD HH:mm:ss 格式
+ *
+ * @param row 行数据
+ * @param column 字段
+ * @param cellValue 字段值
+ */
+export function dateFormatter(_row: any, _column: TableColumnCtx, cellValue: any): string {
+ return cellValue ? formatDate(cellValue) : ''
+}
+
+/**
+ * 专门处理定时时间的格式化函数,确保正确处理毫秒级时间戳
+ *
+ * @param row 行数据
+ * @param column 字段
+ * @param cellValue 字段值
+ */
+export function attimeFormatter(_row: any, _column: TableColumnCtx, cellValue: any): string {
+ if (!cellValue) {
+ return ''
+ }
+
+ // 确保传入的是数字类型的时间戳
+ const timestamp = typeof cellValue === 'string' ? parseInt(cellValue, 10) : cellValue
+
+ // 检查是否是毫秒级时间戳(13位数字)
+ if (Number.isInteger(timestamp) && timestamp.toString().length === 13) {
+ return dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')
+ }
+
+ // 其他情况使用默认格式化
+ return formatDate(cellValue)
+}
+
+/**
+ * element plus 的时间 Formatter 实现,使用 YYYY-MM-DD 格式
+ *
+ * @param row 行数据
+ * @param column 字段
+ * @param cellValue 字段值
+ */
+export function dateFormatter2(_row: any, _column: TableColumnCtx, cellValue: any): string {
+ return cellValue ? formatDate(cellValue, 'YYYY-MM-DD') : ''
+}
+
+/**
+ * 设置起始日期,时间为00:00:00
+ * @param param 传入日期
+ * @returns 带时间00:00:00的日期
+ */
+export function beginOfDay(param: Date): Date {
+ return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 0, 0, 0)
+}
+
+/**
+ * 设置结束日期,时间为23:59:59
+ * @param param 传入日期
+ * @returns 带时间23:59:59的日期
+ */
+export function endOfDay(param: Date): Date {
+ return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 23, 59, 59)
+}
+
+/**
+ * 计算两个日期间隔天数
+ * @param param1 日期1
+ * @param param2 日期2
+ */
+export function betweenDay(param1: Date, param2: Date): number {
+ param1 = convertDate(param1)
+ param2 = convertDate(param2)
+ // 计算差值
+ return Math.floor((param2.getTime() - param1.getTime()) / (24 * 3600 * 1000))
+}
+
+/**
+ * 日期计算
+ * @param param1 日期
+ * @param param2 添加的时间
+ */
+export function addTime(param1: Date, param2: number): Date {
+ param1 = convertDate(param1)
+ return new Date(param1.getTime() + param2)
+}
+
+/**
+ * 日期转换
+ * @param param 日期
+ */
+export function convertDate(param: Date | string): Date {
+ if (typeof param === 'string') {
+ return new Date(param)
+ }
+ return param
+}
+
+/**
+ * 指定的两个日期, 是否为同一天
+ * @param a 日期 A
+ * @param b 日期 B
+ */
+export function isSameDay(a: dayjs.ConfigType, b: dayjs.ConfigType): boolean {
+ if (!a || !b) return false
+
+ const aa = dayjs(a)
+ const bb = dayjs(b)
+ return aa.year() == bb.year() && aa.month() == bb.month() && aa.day() == bb.day()
+}
+
+/**
+ * 获取一天的开始时间、截止时间
+ * @param date 日期
+ * @param days 天数
+ */
+export function getDayRange(
+ date: dayjs.ConfigType,
+ days: number
+): [dayjs.ConfigType, dayjs.ConfigType] {
+ const day = dayjs(date).add(days, 'd')
+ return getDateRange(day, day)
+}
+
+/**
+ * 获取最近7天的开始时间、截止时间
+ */
+export function getLast7Days(): [dayjs.ConfigType, dayjs.ConfigType] {
+ const lastWeekDay = dayjs().subtract(7, 'd')
+ const yesterday = dayjs().subtract(1, 'd')
+ return getDateRange(lastWeekDay, yesterday)
+}
+
+/**
+ * 获取最近30天的开始时间、截止时间
+ */
+export function getLast30Days(): [dayjs.ConfigType, dayjs.ConfigType] {
+ const lastMonthDay = dayjs().subtract(30, 'd')
+ const yesterday = dayjs().subtract(1, 'd')
+ return getDateRange(lastMonthDay, yesterday)
+}
+
+/**
+ * 获取最近1年的开始时间、截止时间
+ */
+export function getLast1Year(): [dayjs.ConfigType, dayjs.ConfigType] {
+ const lastYearDay = dayjs().subtract(1, 'y')
+ const yesterday = dayjs().subtract(1, 'd')
+ return getDateRange(lastYearDay, yesterday)
+}
+
+/**
+ * 获取指定日期的开始时间、截止时间
+ * @param beginDate 开始日期
+ * @param endDate 截止日期
+ */
+export function getDateRange(
+ beginDate: dayjs.ConfigType,
+ endDate: dayjs.ConfigType
+): [string, string] {
+ return [
+ dayjs(beginDate).startOf('d').format('YYYY-MM-DD HH:mm:ss'),
+ dayjs(endDate).endOf('d').format('YYYY-MM-DD HH:mm:ss')
+ ]
+}
diff --git a/marketing-ui/admin-ui/src/utils/formatter.ts b/marketing-ui/admin-ui/src/utils/formatter.ts
new file mode 100644
index 0000000..8777f32
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/formatter.ts
@@ -0,0 +1,7 @@
+import { floatToFixed2 } from '@/utils'
+
+// 格式化金额【分转元】
+// @ts-ignore
+export const fenToYuanFormat = (_, __, cellValue: any, ___) => {
+ return `¥${floatToFixed2(cellValue)}`
+}
diff --git a/marketing-ui/admin-ui/src/utils/index.ts b/marketing-ui/admin-ui/src/utils/index.ts
new file mode 100644
index 0000000..5951d58
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/index.ts
@@ -0,0 +1,553 @@
+import { toNumber } from 'lodash-es'
+
+/**
+ *
+ * @param component 需要注册的组件
+ * @param alias 组件别名
+ * @returns any
+ */
+export const withInstall = (component: T, alias?: string) => {
+ const comp = component as any
+ comp.install = (app: any) => {
+ app.component(comp.name || comp.displayName, component)
+ if (alias) {
+ app.config.globalProperties[alias] = component
+ }
+ }
+ return component as T & Plugin
+}
+
+/**
+ * @param str 需要转下划线的驼峰字符串
+ * @returns 字符串下划线
+ */
+export const humpToUnderline = (str: string): string => {
+ return str.replace(/([A-Z])/g, '-$1').toLowerCase()
+}
+
+/**
+ * @param str 需要转驼峰的下划线字符串
+ * @returns 字符串驼峰
+ */
+export const underlineToHump = (str: string): string => {
+ if (!str) return ''
+ return str.replace(/\-(\w)/g, (_, letter: string) => {
+ return letter.toUpperCase()
+ })
+}
+
+/**
+ * 驼峰转横杠
+ */
+export const humpToDash = (str: string): string => {
+ return str.replace(/([A-Z])/g, '-$1').toLowerCase()
+}
+
+export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
+ dom.style.setProperty(prop, val)
+}
+
+/**
+ * 查找数组对象的某个下标
+ * @param {Array} ary 查找的数组
+ * @param {Functon} fn 判断的方法
+ */
+// eslint-disable-next-line
+export const findIndex = (ary: Array, fn: Fn): number => {
+ if (ary.findIndex) {
+ return ary.findIndex(fn)
+ }
+ let index = -1
+ ary.some((item: T, i: number, ary: Array) => {
+ const ret: T = fn(item, i, ary)
+ if (ret) {
+ index = i
+ return ret
+ }
+ })
+ return index
+}
+
+export const trim = (str: string) => {
+ return str.replace(/(^\s*)|(\s*$)/g, '')
+}
+
+/**
+ * @param {Date | number | string} time 需要转换的时间
+ * @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
+ */
+export function formatTime(time: Date | number | string, fmt: string) {
+ if (!time) return ''
+ else {
+ const date = new Date(time)
+ const o = {
+ 'M+': date.getMonth() + 1,
+ 'd+': date.getDate(),
+ 'H+': date.getHours(),
+ 'm+': date.getMinutes(),
+ 's+': date.getSeconds(),
+ 'q+': Math.floor((date.getMonth() + 3) / 3),
+ S: date.getMilliseconds()
+ }
+ if (/(y+)/.test(fmt)) {
+ fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
+ }
+ for (const k in o) {
+ if (new RegExp('(' + k + ')').test(fmt)) {
+ fmt = fmt.replace(
+ RegExp.$1,
+ RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
+ )
+ }
+ }
+ return fmt
+ }
+}
+
+/**
+ * 生成随机字符串
+ */
+export function toAnyString() {
+ const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => {
+ const r: number = (Math.random() * 16) | 0
+ const v: number = c === 'x' ? r : (r & 0x3) | 0x8
+ return v.toString()
+ })
+ return str
+}
+
+/**
+ * 生成指定长度的随机字符串
+ *
+ * @param length 字符串长度
+ */
+export function generateRandomStr(length: number): string {
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+ let result = ''
+ for (let i = 0; i < length; i++) {
+ result += chars.charAt(Math.floor(Math.random() * chars.length))
+ }
+ return result
+}
+
+/**
+ * 根据支持的文件类型生成 accept 属性值
+ *
+ * @param supportedFileTypes 支持的文件类型数组,如 ['PDF', 'DOC', 'DOCX']
+ * @returns 用于文件上传组件 accept 属性的字符串
+ */
+export const generateAcceptedFileTypes = (supportedFileTypes: string[]): string => {
+ const allowedExtensions = supportedFileTypes.map((ext) => ext.toLowerCase())
+ const mimeTypes: string[] = []
+
+ // 添加常见的 MIME 类型映射
+ if (allowedExtensions.includes('txt')) {
+ mimeTypes.push('text/plain')
+ }
+ if (allowedExtensions.includes('pdf')) {
+ mimeTypes.push('application/pdf')
+ }
+ if (allowedExtensions.includes('html') || allowedExtensions.includes('htm')) {
+ mimeTypes.push('text/html')
+ }
+ if (allowedExtensions.includes('csv')) {
+ mimeTypes.push('text/csv')
+ }
+ if (allowedExtensions.includes('xlsx') || allowedExtensions.includes('xls')) {
+ mimeTypes.push('application/vnd.ms-excel')
+ mimeTypes.push('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+ }
+ if (allowedExtensions.includes('docx') || allowedExtensions.includes('doc')) {
+ mimeTypes.push('application/msword')
+ mimeTypes.push('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
+ }
+ if (allowedExtensions.includes('pptx') || allowedExtensions.includes('ppt')) {
+ mimeTypes.push('application/vnd.ms-powerpoint')
+ mimeTypes.push('application/vnd.openxmlformats-officedocument.presentationml.presentation')
+ }
+ if (allowedExtensions.includes('xml')) {
+ mimeTypes.push('application/xml')
+ mimeTypes.push('text/xml')
+ }
+ if (allowedExtensions.includes('md') || allowedExtensions.includes('markdown')) {
+ mimeTypes.push('text/markdown')
+ }
+ if (allowedExtensions.includes('epub')) {
+ mimeTypes.push('application/epub+zip')
+ }
+ if (allowedExtensions.includes('eml')) {
+ mimeTypes.push('message/rfc822')
+ }
+ if (allowedExtensions.includes('msg')) {
+ mimeTypes.push('application/vnd.ms-outlook')
+ }
+
+ // 添加文件扩展名
+ const extensions = allowedExtensions.map((ext) => `.${ext}`)
+
+ return [...mimeTypes, ...extensions].join(',')
+}
+
+/**
+ * 首字母大写
+ */
+export function firstUpperCase(str: string) {
+ return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase())
+}
+
+export const generateUUID = () => {
+ if (typeof crypto === 'object') {
+ if (typeof crypto.randomUUID === 'function') {
+ return crypto.randomUUID()
+ }
+ if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
+ const callback = (c: any) => {
+ const num = Number(c)
+ return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(
+ 16
+ )
+ }
+ return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback)
+ }
+ }
+ let timestamp = new Date().getTime()
+ let performanceNow =
+ (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
+ let random = Math.random() * 16
+ if (timestamp > 0) {
+ random = (timestamp + random) % 16 | 0
+ timestamp = Math.floor(timestamp / 16)
+ } else {
+ random = (performanceNow + random) % 16 | 0
+ performanceNow = Math.floor(performanceNow / 16)
+ }
+ return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16)
+ })
+}
+
+/**
+ * element plus 的文件大小 Formatter 实现
+ *
+ * @param row 行数据
+ * @param column 字段
+ * @param cellValue 字段值
+ */
+// @ts-ignore
+export const fileSizeFormatter = (row, column, cellValue) => {
+ const fileSize = cellValue
+ const unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+ const srcSize = parseFloat(fileSize)
+ const index = Math.floor(Math.log(srcSize) / Math.log(1024))
+ const size = srcSize / Math.pow(1024, index)
+ const sizeStr = size.toFixed(2) //保留的小数位数
+ return sizeStr + ' ' + unitArr[index]
+}
+
+/**
+ * 将值复制到目标对象,且以目标对象属性为准,例:target: {a:1} source:{a:2,b:3} 结果为:{a:2}
+ * @param target 目标对象
+ * @param source 源对象
+ */
+export const copyValueToTarget = (target: any, source: any) => {
+ const newObj = Object.assign({}, target, source)
+ // 删除多余属性
+ Object.keys(newObj).forEach((key) => {
+ // 如果不是target中的属性则删除
+ if (Object.keys(target).indexOf(key) === -1) {
+ delete newObj[key]
+ }
+ })
+ // 更新目标对象值
+ Object.assign(target, newObj)
+}
+
+/**
+ * 获取链接的参数值
+ * @param key 参数键名
+ * @param urlStr 链接地址,默认为当前浏览器的地址
+ */
+export const getUrlValue = (key: string, urlStr: string = location.href): string => {
+ if (!urlStr || !key) return ''
+ const url = new URL(decodeURIComponent(urlStr))
+ return url.searchParams.get(key) ?? ''
+}
+
+/**
+ * 获取链接的参数值(值类型)
+ * @param key 参数键名
+ * @param urlStr 链接地址,默认为当前浏览器的地址
+ */
+export const getUrlNumberValue = (key: string, urlStr: string = location.href): number => {
+ return toNumber(getUrlValue(key, urlStr))
+}
+
+/**
+ * 构建排序字段
+ * @param prop 字段名称
+ * @param order 顺序
+ */
+export const buildSortingField = ({ prop, order }) => {
+ return { field: prop, order: order === 'ascending' ? 'asc' : 'desc' }
+}
+
+// ========== NumberUtils 数字方法 ==========
+
+/**
+ * 数组求和
+ *
+ * @param values 数字数组
+ * @return 求和结果,默认为 0
+ */
+export const getSumValue = (values: number[]): number => {
+ return values.reduce((prev, curr) => {
+ const value = Number(curr)
+ if (!Number.isNaN(value)) {
+ return prev + curr
+ } else {
+ return prev
+ }
+ }, 0)
+}
+
+// ========== 通用金额方法 ==========
+
+/**
+ * 将一个整数转换为分数保留两位小数
+ * @param num
+ */
+export const formatToFraction = (num: number | string | undefined): string => {
+ if (typeof num === 'undefined') return '0.00'
+ const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
+ return (parsedNumber / 100.0).toFixed(2)
+}
+
+/**
+ * 将一个数转换为 1.00 这样
+ * 数据呈现的时候使用
+ *
+ * @param num 整数
+ */
+// TODO @芋艿:看看怎么融合掉
+export const floatToFixed2 = (num: number | string | undefined): string => {
+ let str = '0.00'
+ if (typeof num === 'undefined') {
+ return str
+ }
+ const f = formatToFraction(num)
+ const decimalPart = f.toString().split('.')[1]
+ const len = decimalPart ? decimalPart.length : 0
+ switch (len) {
+ case 0:
+ str = f.toString() + '.00'
+ break
+ case 1:
+ str = f.toString() + '0'
+ break
+ case 2:
+ str = f.toString()
+ break
+ }
+ return str
+}
+
+/**
+ * 将一个分数转换为整数
+ * @param num
+ */
+// TODO @芋艿:看看怎么融合掉
+export const convertToInteger = (num: number | string | undefined): number => {
+ if (typeof num === 'undefined') return 0
+ const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
+ // TODO 分转元后还有小数则四舍五入
+ return Math.round(parsedNumber * 100)
+}
+
+/**
+ * 元转分
+ */
+export const yuanToFen = (amount: string | number): number => {
+ return convertToInteger(amount)
+}
+
+/**
+ * 分转元
+ */
+export const fenToYuan = (price: string | number): string => {
+ return formatToFraction(price)
+}
+
+/**
+ * 计算环比
+ *
+ * @param value 当前数值
+ * @param reference 对比数值
+ */
+export const calculateRelativeRate = (value?: number, reference?: number) => {
+ // 防止除0
+ if (!reference || reference == 0) return 0
+
+ return ((100 * ((value || 0) - reference)) / reference).toFixed(0)
+}
+
+// ========== ERP 专属方法 ==========
+
+const ERP_COUNT_DIGIT = 3
+const ERP_PRICE_DIGIT = 2
+
+/**
+ * 【ERP】格式化 Input 数字
+ *
+ * 例如说:库存数量
+ *
+ * @param num 数量
+ * @package digit 保留的小数位数
+ * @return 格式化后的数量
+ */
+export const erpNumberFormatter = (num: number | string | undefined, digit: number) => {
+ if (num == null) {
+ return ''
+ }
+ if (typeof num === 'string') {
+ num = parseFloat(num)
+ }
+ // 如果非 number,则直接返回空串
+ if (isNaN(num)) {
+ return ''
+ }
+ return num.toFixed(digit)
+}
+
+/**
+ * 【ERP】格式化数量,保留三位小数
+ *
+ * 例如说:库存数量
+ *
+ * @param num 数量
+ * @return 格式化后的数量
+ */
+export const erpCountInputFormatter = (num: number | string | undefined) => {
+ return erpNumberFormatter(num, ERP_COUNT_DIGIT)
+}
+
+// noinspection JSCommentMatchesSignature
+/**
+ * 【ERP】格式化数量,保留三位小数
+ *
+ * @param cellValue 数量
+ * @return 格式化后的数量
+ */
+export const erpCountTableColumnFormatter = (_, __, cellValue: any, ___) => {
+ return erpNumberFormatter(cellValue, ERP_COUNT_DIGIT)
+}
+
+/**
+ * 【ERP】格式化金额,保留二位小数
+ *
+ * 例如说:库存数量
+ *
+ * @param num 数量
+ * @return 格式化后的数量
+ */
+export const erpPriceInputFormatter = (num: number | string | undefined) => {
+ return erpNumberFormatter(num, ERP_PRICE_DIGIT)
+}
+
+// noinspection JSCommentMatchesSignature
+/**
+ * 【ERP】格式化金额,保留二位小数
+ *
+ * @param cellValue 数量
+ * @return 格式化后的数量
+ */
+export const erpPriceTableColumnFormatter = (_, __, cellValue: any, ___) => {
+ return erpNumberFormatter(cellValue, ERP_PRICE_DIGIT)
+}
+
+/**
+ * 【ERP】价格计算,四舍五入保留两位小数
+ *
+ * @param price 价格
+ * @param count 数量
+ * @return 总价格。如果有任一为空,则返回 undefined
+ */
+export const erpPriceMultiply = (price: number, count: number) => {
+ if (price == null || count == null) {
+ return undefined
+ }
+ return parseFloat((price * count).toFixed(ERP_PRICE_DIGIT))
+}
+
+/**
+ * 【ERP】百分比计算,四舍五入保留两位小数
+ *
+ * 如果 total 为 0,则返回 0
+ *
+ * @param value 当前值
+ * @param total 总值
+ */
+export const erpCalculatePercentage = (value: number, total: number) => {
+ if (total === 0) return 0
+ return ((value / total) * 100).toFixed(2)
+}
+
+/**
+ * 适配 echarts map 的地名
+ *
+ * @param areaName 地区名称
+ */
+export const areaReplace = (areaName: string) => {
+ if (!areaName) {
+ return areaName
+ }
+ return areaName
+ .replace('维吾尔自治区', '')
+ .replace('壮族自治区', '')
+ .replace('回族自治区', '')
+ .replace('自治区', '')
+ .replace('省', '')
+}
+
+/**
+ * 解析 JSON 字符串
+ *
+ * @param str
+ */
+export function jsonParse(str: string) {
+ try {
+ return JSON.parse(str)
+ } catch (e) {
+ console.warn(`str[${str}] 不是一个 JSON 字符串`)
+ return str
+ }
+}
+
+/**
+ * 截取字符串
+ *
+ * @param name
+ * @param start
+ * @param end
+ */
+
+export const sliceName = (name: string, start: number, end: number) => {
+ if (name.length > end) {
+ return name.slice(start, end)
+ }
+ return name
+}
+
+/**
+ * 截取字符串
+ *
+ * @param str 字符串
+ * @param start 开始位置
+ * @param end 结束位置
+ */
+
+export const subString = (str: string, start: number, end: number) => {
+ if (str.length > end) {
+ return str.slice(start, end)
+ }
+ return str
+}
diff --git a/marketing-ui/admin-ui/src/utils/is.ts b/marketing-ui/admin-ui/src/utils/is.ts
new file mode 100644
index 0000000..24d7191
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/is.ts
@@ -0,0 +1,118 @@
+// copy to vben-admin
+
+const toString = Object.prototype.toString
+
+export const is = (val: unknown, type: string) => {
+ return toString.call(val) === `[object ${type}]`
+}
+
+export const isDef = (val?: T): val is T => {
+ return typeof val !== 'undefined'
+}
+
+export const isUnDef = (val?: T): val is T => {
+ return !isDef(val)
+}
+
+export const isObject = (val: any): val is Record => {
+ return val !== null && is(val, 'Object')
+}
+
+export const isEmpty = (val: any): boolean => {
+ if (val === null || val === undefined || typeof val === 'undefined') {
+ return true
+ }
+ if (isArray(val) || isString(val)) {
+ return val.length === 0
+ }
+
+ if (val instanceof Map || val instanceof Set) {
+ return val.size === 0
+ }
+
+ if (isObject(val)) {
+ return Object.keys(val).length === 0
+ }
+
+ return false
+}
+
+export const isDate = (val: unknown): val is Date => {
+ return is(val, 'Date')
+}
+
+export const isNull = (val: unknown): val is null => {
+ return val === null
+}
+
+export const isNullAndUnDef = (val: unknown): val is null | undefined => {
+ return isUnDef(val) && isNull(val)
+}
+
+export const isNullOrUnDef = (val: unknown): val is null | undefined => {
+ return isUnDef(val) || isNull(val)
+}
+
+export const isNumber = (val: unknown): val is number => {
+ return is(val, 'Number')
+}
+
+export const isPromise = (val: unknown): val is Promise => {
+ return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch)
+}
+
+export const isString = (val: unknown): val is string => {
+ return is(val, 'String')
+}
+
+export const isFunction = (val: unknown): val is Function => {
+ return typeof val === 'function'
+}
+
+export const isBoolean = (val: unknown): val is boolean => {
+ return is(val, 'Boolean')
+}
+
+export const isRegExp = (val: unknown): val is RegExp => {
+ return is(val, 'RegExp')
+}
+
+export const isArray = (val: any): val is Array => {
+ return val && Array.isArray(val)
+}
+
+export const isWindow = (val: any): val is Window => {
+ return typeof window !== 'undefined' && is(val, 'Window')
+}
+
+export const isElement = (val: unknown): val is Element => {
+ return isObject(val) && !!val.tagName
+}
+
+export const isMap = (val: unknown): val is Map => {
+ return is(val, 'Map')
+}
+
+export const isServer = typeof window === 'undefined'
+
+export const isClient = !isServer
+
+export const isUrl = (path: string): boolean => {
+ // fix:修复hash路由无法跳转的问题
+ const reg =
+ /(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%#\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/
+ return reg.test(path)
+}
+
+export const isDark = (): boolean => {
+ return window.matchMedia('(prefers-color-scheme: dark)').matches
+}
+
+// 是否是图片链接
+export const isImgPath = (path: string): boolean => {
+ return /(https?:\/\/|data:image\/).*?\.(png|jpg|jpeg|gif|svg|webp|ico)/gi.test(path)
+}
+
+export const isEmptyVal = (val: any): boolean => {
+ return val === '' || val === null || val === undefined
+}
diff --git a/marketing-ui/admin-ui/src/utils/jsencrypt.ts b/marketing-ui/admin-ui/src/utils/jsencrypt.ts
new file mode 100644
index 0000000..374d5f6
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/jsencrypt.ts
@@ -0,0 +1,31 @@
+import { JSEncrypt } from 'jsencrypt'
+
+// 密钥对生成 http://web.chacuo.net/netrsakeypair
+
+const publicKey =
+ 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
+ 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
+
+const privateKey =
+ 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
+ '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
+ 'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
+ 'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
+ 'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
+ 'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
+ 'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
+ 'UP8iWi1Qw0Y='
+
+// 加密
+export const encrypt = (txt: string) => {
+ const encryptor = new JSEncrypt()
+ encryptor.setPublicKey(publicKey) // 设置公钥
+ return encryptor.encrypt(txt) // 对数据进行加密
+}
+
+// 解密
+export const decrypt = (txt: string) => {
+ const encryptor = new JSEncrypt()
+ encryptor.setPrivateKey(privateKey) // 设置私钥
+ return encryptor.decrypt(txt) // 对数据进行解密
+}
diff --git a/marketing-ui/admin-ui/src/utils/permission.ts b/marketing-ui/admin-ui/src/utils/permission.ts
new file mode 100644
index 0000000..4138173
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/permission.ts
@@ -0,0 +1,36 @@
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+import {hasPermission} from "@/directives/permission/hasPermi";
+
+
+const { t } = useI18n() // 国际化
+
+/**
+ * 字符权限校验
+ * @param {Array} value 校验值
+ * @returns {Boolean}
+ */
+export function checkPermi(permission: string[]) {
+ return hasPermission(permission)
+}
+
+/**
+ * 角色权限校验
+ * @param {string[]} value 校验值
+ * @returns {Boolean}
+ */
+export function checkRole(value: string[]) {
+ if (value && value instanceof Array && value.length > 0) {
+ const { wsCache } = useCache()
+ const permissionRoles = value
+ const super_admin = 'super_admin'
+ const userInfo = wsCache.get(CACHE_KEY.USER)
+ const roles = userInfo?.roles || []
+ const hasRole = roles.some((role: string) => {
+ return super_admin === role || permissionRoles.includes(role)
+ })
+ return !!hasRole
+ } else {
+ console.error(t('permission.hasRole'))
+ return false
+ }
+}
diff --git a/marketing-ui/admin-ui/src/utils/propTypes.ts b/marketing-ui/admin-ui/src/utils/propTypes.ts
new file mode 100644
index 0000000..863f55c
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/propTypes.ts
@@ -0,0 +1,24 @@
+import { VueTypeValidableDef, VueTypesInterface, createTypes, toValidableType } from 'vue-types'
+import { CSSProperties } from 'vue'
+
+type PropTypes = VueTypesInterface & {
+ readonly style: VueTypeValidableDef
+}
+const newPropTypes = createTypes({
+ func: undefined,
+ bool: undefined,
+ string: undefined,
+ number: undefined,
+ object: undefined,
+ integer: undefined
+}) as PropTypes
+
+class propTypes extends newPropTypes {
+ static get style() {
+ return toValidableType('style', {
+ type: [String, Object]
+ })
+ }
+}
+
+export { propTypes }
diff --git a/marketing-ui/admin-ui/src/utils/routerHelper.ts b/marketing-ui/admin-ui/src/utils/routerHelper.ts
new file mode 100644
index 0000000..7a87bd7
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/routerHelper.ts
@@ -0,0 +1,256 @@
+import type { RouteLocationNormalized, Router, RouteRecordNormalized } from 'vue-router'
+import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
+import { isUrl } from '@/utils/is'
+import { cloneDeep, omit } from 'lodash-es'
+import qs from 'qs'
+
+const modules = import.meta.glob('../views/**/*.{vue,tsx}')
+/**
+ * 注册一个异步组件
+ * @param componentPath 例:/bpm/oa/leave/detail
+ */
+export const registerComponent = (componentPath: string) => {
+ for (const item in modules) {
+ if (item.includes(componentPath)) {
+ // 使用异步组件的方式来动态加载组件
+ // @ts-ignore
+ return defineAsyncComponent(modules[item])
+ }
+ }
+}
+/* Layout */
+export const Layout = () => import('@/layout/Layout.vue')
+
+export const getParentLayout = () => {
+ return () =>
+ new Promise((resolve) => {
+ resolve({
+ name: 'ParentLayout'
+ })
+ })
+}
+
+// 按照路由中meta下的rank等级升序来排序路由
+export const ascending = (arr: any[]) => {
+ arr.forEach((v) => {
+ if (v?.meta?.rank === null) v.meta.rank = undefined
+ if (v?.meta?.rank === 0) {
+ if (v.name !== 'home' && v.path !== '/') {
+ console.warn('rank only the home page can be 0')
+ }
+ }
+ })
+ return arr.sort((a: { meta: { rank: number } }, b: { meta: { rank: number } }) => {
+ return a?.meta?.rank - b?.meta?.rank
+ })
+}
+
+export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => {
+ if (!route) return route
+ const { matched, ...opt } = route
+ return {
+ ...opt,
+ matched: (matched
+ ? matched.map((item) => ({
+ meta: item.meta,
+ name: item.name,
+ path: item.path
+ }))
+ : undefined) as RouteRecordNormalized[]
+ }
+}
+
+// 后端控制路由生成
+export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecordRaw[] => {
+ const res: AppRouteRecordRaw[] = []
+ const modulesRoutesKeys = Object.keys(modules)
+ for (const route of routes) {
+ // 1. 生成 meta 菜单元数据
+ const meta = {
+ title: route.name,
+ icon: route.icon,
+ hidden: !route.visible,
+ noCache: !route.keepAlive,
+ alwaysShow:
+ route.children &&
+ route.children.length > 0 &&
+ (route.alwaysShow !== undefined ? route.alwaysShow : true)
+ } as any
+ // 特殊逻辑:如果后端配置的 MenuDO.component 包含 ?,则表示需要传递参数
+ // 此时,我们需要解析参数,并且将参数放到 meta.query 中
+ // 这样,后续在 Vue 文件中,可以通过 const { currentRoute } = useRouter() 中,通过 meta.query 获取到参数
+ if (route.component && route.component.indexOf('?') > -1) {
+ const query = route.component.split('?')[1]
+ route.component = route.component.split('?')[0]
+ meta.query = qs.parse(query)
+ }
+
+ // 2. 生成 data(AppRouteRecordRaw)
+ // 路由地址转首字母大写驼峰,作为路由名称,适配keepAlive
+ let data: AppRouteRecordRaw = {
+ path:
+ route.path.indexOf('?') > -1 && !isUrl(route.path) ? route.path.split('?')[0] : route.path, // 注意,需要排除 http 这种 url,避免它带 ? 参数被截取掉
+ name:
+ route.componentName && route.componentName.length > 0
+ ? route.componentName
+ : toCamelCase(route.path, true),
+ redirect: route.redirect,
+ meta: meta
+ }
+ //处理顶级非目录路由
+ if (!route.children && route.parentId == 0 && route.component) {
+ data.component = Layout
+ data.meta = {
+ hidden: meta.hidden,
+ }
+ data.name = toCamelCase(route.path, true) + 'Parent'
+ data.redirect = ''
+ meta.alwaysShow = true
+ const childrenData: AppRouteRecordRaw = {
+ path: '',
+ name:
+ route.componentName && route.componentName.length > 0
+ ? route.componentName
+ : toCamelCase(route.path, true),
+ redirect: route.redirect,
+ meta: meta
+ }
+ const index = route?.component
+ ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component))
+ : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path))
+ childrenData.component = modules[modulesRoutesKeys[index]]
+ data.children = [childrenData]
+ } else {
+ // 目录
+ if (route.children?.length) {
+ data.component = Layout
+ data.redirect = getRedirect(route.path, route.children)
+ // 外链
+ } else if (isUrl(route.path)) {
+ data = {
+ path: '/external-link',
+ component: Layout,
+ meta: {
+ name: route.name
+ },
+ children: [data]
+ } as AppRouteRecordRaw
+ // 菜单
+ } else {
+ // 对后端传component组件路径和不传做兼容(如果后端传component组件路径,那么path可以随便写,如果不传,component组件路径会根path保持一致)
+ const index = route?.component
+ ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component))
+ : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path))
+ data.component = modules[modulesRoutesKeys[index]]
+ }
+ if (route.children) {
+ data.children = generateRoute(route.children)
+ }
+ }
+ res.push(data as AppRouteRecordRaw)
+ }
+ return res
+}
+export const getRedirect = (parentPath: string, children: AppCustomRouteRecordRaw[]) => {
+ if (!children || children.length == 0) {
+ return parentPath
+ }
+ const path = generateRoutePath(parentPath, children[0].path)
+ // 递归子节点
+ if (children[0].children) return getRedirect(path, children[0].children)
+}
+const generateRoutePath = (parentPath: string, path: string) => {
+ if (parentPath.endsWith('/')) {
+ parentPath = parentPath.slice(0, -1) // 移除默认的 /
+ }
+ if (!path.startsWith('/')) {
+ path = '/' + path
+ }
+ return parentPath + path
+}
+export const pathResolve = (parentPath: string, path: string) => {
+ if (isUrl(path)) return path
+ const childPath = path.startsWith('/') || !path ? path : `/${path}`
+ return `${parentPath}${childPath}`.replace(/\/\//g, '/')
+}
+
+// 路由降级
+export const flatMultiLevelRoutes = (routes: AppRouteRecordRaw[]) => {
+ const modules: AppRouteRecordRaw[] = cloneDeep(routes)
+ for (let index = 0; index < modules.length; index++) {
+ const route = modules[index]
+ if (!isMultipleRoute(route)) {
+ continue
+ }
+ promoteRouteLevel(route)
+ }
+ return modules
+}
+
+// 层级是否大于2
+const isMultipleRoute = (route: AppRouteRecordRaw) => {
+ if (!route || !Reflect.has(route, 'children') || !route.children?.length) {
+ return false
+ }
+
+ const children = route.children
+
+ let flag = false
+ for (let index = 0; index < children.length; index++) {
+ const child = children[index]
+ if (child.children?.length) {
+ flag = true
+ break
+ }
+ }
+ return flag
+}
+
+// 生成二级路由
+const promoteRouteLevel = (route: AppRouteRecordRaw) => {
+ let router: Router | null = createRouter({
+ routes: [route as RouteRecordRaw],
+ history: createWebHashHistory()
+ })
+
+ const routes = router.getRoutes()
+ addToChildren(routes, route.children || [], route)
+ router = null
+
+ route.children = route.children?.map((item) => omit(item, 'children'))
+}
+
+// 添加所有子菜单
+const addToChildren = (
+ routes: RouteRecordNormalized[],
+ children: AppRouteRecordRaw[],
+ routeModule: AppRouteRecordRaw
+) => {
+ for (let index = 0; index < children.length; index++) {
+ const child = children[index]
+ const route = routes.find((item) => item.name === child.name)
+ if (!route) {
+ continue
+ }
+ routeModule.children = routeModule.children || []
+ if (!routeModule.children.find((item) => item.name === route.name)) {
+ routeModule.children?.push(route as unknown as AppRouteRecordRaw)
+ }
+ if (child.children?.length) {
+ addToChildren(routes, child.children, routeModule)
+ }
+ }
+}
+const toCamelCase = (str: string, upperCaseFirst: boolean) => {
+ str = (str || '')
+ .replace(/-(.)/g, function (group1: string) {
+ return group1.toUpperCase()
+ })
+ .replaceAll('-', '')
+
+ if (upperCaseFirst && str) {
+ str = str.charAt(0).toUpperCase() + str.slice(1)
+ }
+
+ return str
+}
diff --git a/marketing-ui/admin-ui/src/utils/tree.ts b/marketing-ui/admin-ui/src/utils/tree.ts
new file mode 100644
index 0000000..e5db503
--- /dev/null
+++ b/marketing-ui/admin-ui/src/utils/tree.ts
@@ -0,0 +1,403 @@
+interface TreeHelperConfig {
+ id: string
+ children: string
+ pid: string
+}
+
+const DEFAULT_CONFIG: TreeHelperConfig = {
+ id: 'id',
+ children: 'children',
+ pid: 'pid'
+}
+export const defaultProps = {
+ children: 'children',
+ label: 'name',
+ value: 'id',
+ isLeaf: 'leaf',
+ emitPath: false // 用于 cascader 组件:在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值
+}
+
+const getConfig = (config: Partial) => Object.assign({}, DEFAULT_CONFIG, config)
+
+// tree from list
+export const listToTree =