diff --git a/Cunkebao/dist/.vite/manifest.json b/Cunkebao/dist/.vite/manifest.json index aa2b3d0b..fabab32f 100644 --- a/Cunkebao/dist/.vite/manifest.json +++ b/Cunkebao/dist/.vite/manifest.json @@ -1,50 +1,50 @@ { - "_charts-DKSCc2_C.js": { - "file": "assets/charts-DKSCc2_C.js", + "_charts-BjEBSMrK.js": { + "file": "assets/charts-BjEBSMrK.js", "name": "charts", "imports": [ - "_ui-DhAz00L0.js", - "_vendor-2vc8h_ct.js" + "_ui-CiJ_pikt.js", + "_vendor-BPPoWDlG.js" + ] + }, + "_ui-CiJ_pikt.js": { + "file": "assets/ui-CiJ_pikt.js", + "name": "ui", + "imports": [ + "_vendor-BPPoWDlG.js" + ], + "css": [ + "assets/ui-D0C0OGrH.css" ] }, "_ui-D0C0OGrH.css": { "file": "assets/ui-D0C0OGrH.css", "src": "_ui-D0C0OGrH.css" }, - "_ui-DhAz00L0.js": { - "file": "assets/ui-DhAz00L0.js", - "name": "ui", - "imports": [ - "_vendor-2vc8h_ct.js" - ], - "css": [ - "assets/ui-D0C0OGrH.css" - ] - }, - "_utils-6WF66_dS.js": { - "file": "assets/utils-6WF66_dS.js", + "_utils-DiZV3oaL.js": { + "file": "assets/utils-DiZV3oaL.js", "name": "utils", "imports": [ - "_vendor-2vc8h_ct.js" + "_vendor-BPPoWDlG.js" ] }, - "_vendor-2vc8h_ct.js": { - "file": "assets/vendor-2vc8h_ct.js", + "_vendor-BPPoWDlG.js": { + "file": "assets/vendor-BPPoWDlG.js", "name": "vendor" }, "index.html": { - "file": "assets/index-BdCPAYQ7.js", + "file": "assets/index-BesOjMPu.js", "name": "index", "src": "index.html", "isEntry": true, "imports": [ - "_vendor-2vc8h_ct.js", - "_utils-6WF66_dS.js", - "_ui-DhAz00L0.js", - "_charts-DKSCc2_C.js" + "_vendor-BPPoWDlG.js", + "_utils-DiZV3oaL.js", + "_ui-CiJ_pikt.js", + "_charts-BjEBSMrK.js" ], "css": [ - "assets/index-ChiFk16x.css" + "assets/index-677RgwmW.css" ] } } \ No newline at end of file diff --git a/Cunkebao/dist/assets/vendor-2vc8h_ct.js b/Cunkebao/dist/assets/vendor-2vc8h_ct.js deleted file mode 100644 index b4ee0b98..00000000 --- a/Cunkebao/dist/assets/vendor-2vc8h_ct.js +++ /dev/null @@ -1,59 +0,0 @@ -function Js(o,c){for(var a=0;av[g]})}}}return Object.freeze(Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}))}var gp=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function qs(o){return o&&o.__esModule&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o}var Ti={exports:{}},Y={};/** - * @license React - * react.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var js;function fd(){if(js)return Y;js=1;var o=Symbol.for("react.element"),c=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),v=Symbol.for("react.strict_mode"),g=Symbol.for("react.profiler"),w=Symbol.for("react.provider"),C=Symbol.for("react.context"),N=Symbol.for("react.forward_ref"),P=Symbol.for("react.suspense"),T=Symbol.for("react.memo"),A=Symbol.for("react.lazy"),R=Symbol.iterator;function W(p){return p===null||typeof p!="object"?null:(p=R&&p[R]||p["@@iterator"],typeof p=="function"?p:null)}var re={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},b=Object.assign,B={};function U(p,k,K){this.props=p,this.context=k,this.refs=B,this.updater=K||re}U.prototype.isReactComponent={},U.prototype.setState=function(p,k){if(typeof p!="object"&&typeof p!="function"&&p!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,p,k,"setState")},U.prototype.forceUpdate=function(p){this.updater.enqueueForceUpdate(this,p,"forceUpdate")};function le(){}le.prototype=U.prototype;function ue(p,k,K){this.props=p,this.context=k,this.refs=B,this.updater=K||re}var ee=ue.prototype=new le;ee.constructor=ue,b(ee,U.prototype),ee.isPureReactComponent=!0;var ie=Array.isArray,Ee=Object.prototype.hasOwnProperty,Me={current:null},Fe={key:!0,ref:!0,__self:!0,__source:!0};function Ze(p,k,K){var X,Z={},J=null,oe=null;if(k!=null)for(X in k.ref!==void 0&&(oe=k.ref),k.key!==void 0&&(J=""+k.key),k)Ee.call(k,X)&&!Fe.hasOwnProperty(X)&&(Z[X]=k[X]);var te=arguments.length-2;if(te===1)Z.children=K;else if(1>>1,k=z[p];if(0>>1;pg(Z,M))Jg(oe,Z)?(z[p]=oe,z[J]=M,p=J):(z[p]=Z,z[X]=M,p=X);else if(Jg(oe,M))z[p]=oe,z[J]=M,p=J;else break e}}return H}function g(z,H){var M=z.sortIndex-H.sortIndex;return M!==0?M:z.id-H.id}if(typeof performance=="object"&&typeof performance.now=="function"){var w=performance;o.unstable_now=function(){return w.now()}}else{var C=Date,N=C.now();o.unstable_now=function(){return C.now()-N}}var P=[],T=[],A=1,R=null,W=3,re=!1,b=!1,B=!1,U=typeof setTimeout=="function"?setTimeout:null,le=typeof clearTimeout=="function"?clearTimeout:null,ue=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function ee(z){for(var H=a(T);H!==null;){if(H.callback===null)v(T);else if(H.startTime<=z)v(T),H.sortIndex=H.expirationTime,c(P,H);else break;H=a(T)}}function ie(z){if(B=!1,ee(z),!b)if(a(P)!==null)b=!0,je(Ee);else{var H=a(T);H!==null&&me(ie,H.startTime-z)}}function Ee(z,H){b=!1,B&&(B=!1,le(Ze),Ze=-1),re=!0;var M=W;try{for(ee(H),R=a(P);R!==null&&(!(R.expirationTime>H)||z&&!Gt());){var p=R.callback;if(typeof p=="function"){R.callback=null,W=R.priorityLevel;var k=p(R.expirationTime<=H);H=o.unstable_now(),typeof k=="function"?R.callback=k:R===a(P)&&v(P),ee(H)}else v(P);R=a(P)}if(R!==null)var K=!0;else{var X=a(T);X!==null&&me(ie,X.startTime-H),K=!1}return K}finally{R=null,W=M,re=!1}}var Me=!1,Fe=null,Ze=-1,Nt=5,gt=-1;function Gt(){return!(o.unstable_now()-gtz||125p?(z.sortIndex=M,c(T,z),a(P)===null&&z===a(T)&&(B?(le(Ze),Ze=-1):B=!0,me(ie,M-p))):(z.sortIndex=k,c(P,z),b||re||(b=!0,je(Ee))),z},o.unstable_shouldYield=Gt,o.unstable_wrapCallback=function(z){var H=W;return function(){var M=W;W=H;try{return z.apply(this,arguments)}finally{W=M}}}}(Ii)),Ii}var As;function pd(){return As||(As=1,Mi.exports=dd()),Mi.exports}/** - * @license React - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var $s;function hd(){if($s)return We;$s=1;var o=bs(),c=pd();function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),P=Object.prototype.hasOwnProperty,T=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,A={},R={};function W(e){return P.call(R,e)?!0:P.call(A,e)?!1:T.test(e)?R[e]=!0:(A[e]=!0,!1)}function re(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function b(e,t,n,r){if(t===null||typeof t>"u"||re(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function B(e,t,n,r,l,u,i){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=l,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=u,this.removeEmptyString=i}var U={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){U[e]=new B(e,0,!1,e,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];U[t]=new B(t,1,!1,e[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(e){U[e]=new B(e,2,!1,e.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){U[e]=new B(e,2,!1,e,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){U[e]=new B(e,3,!1,e.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(e){U[e]=new B(e,3,!0,e,null,!1,!1)}),["capture","download"].forEach(function(e){U[e]=new B(e,4,!1,e,null,!1,!1)}),["cols","rows","size","span"].forEach(function(e){U[e]=new B(e,6,!1,e,null,!1,!1)}),["rowSpan","start"].forEach(function(e){U[e]=new B(e,5,!1,e.toLowerCase(),null,!1,!1)});var le=/[\-:]([a-z])/g;function ue(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(le,ue);U[t]=new B(t,1,!1,e,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(le,ue);U[t]=new B(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(le,ue);U[t]=new B(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(e){U[e]=new B(e,1,!1,e.toLowerCase(),null,!1,!1)}),U.xlinkHref=new B("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(e){U[e]=new B(e,1,!1,e.toLowerCase(),null,!0,!0)});function ee(e,t,n,r){var l=U.hasOwnProperty(t)?U[t]:null;(l!==null?l.type!==0:r||!(2s||l[i]!==u[s]){var f=` -`+l[i].replace(" at new "," at ");return e.displayName&&f.includes("")&&(f=f.replace("",e.displayName)),f}while(1<=i&&0<=s);break}}}finally{K=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?k(e):""}function Z(e){switch(e.tag){case 5:return k(e.type);case 16:return k("Lazy");case 13:return k("Suspense");case 19:return k("SuspenseList");case 0:case 2:case 15:return e=X(e.type,!1),e;case 11:return e=X(e.type.render,!1),e;case 1:return e=X(e.type,!0),e;default:return""}}function J(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case Fe:return"Fragment";case Me:return"Portal";case Nt:return"Profiler";case Ze:return"StrictMode";case He:return"Suspense";case rt:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Gt:return(e.displayName||"Context")+".Consumer";case gt:return(e._context.displayName||"Context")+".Provider";case ft:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case dt:return t=e.displayName||null,t!==null?t:J(e.type)||"Memo";case je:t=e._payload,e=e._init;try{return J(e(t))}catch{}}return null}function oe(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return J(t);case 8:return t===Ze?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function te(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function fe(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function Qe(e){var t=fe(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var l=n.get,u=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return l.call(this)},set:function(i){r=""+i,u.call(this,i)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(i){r=""+i},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Pr(e){e._valueTracker||(e._valueTracker=Qe(e))}function Vi(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=fe(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function Nr(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Ul(e,t){var n=t.checked;return M({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function Wi(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=te(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function Hi(e,t){t=t.checked,t!=null&&ee(e,"checked",t,!1)}function Bl(e,t){Hi(e,t);var n=te(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Al(e,t.type,n):t.hasOwnProperty("defaultValue")&&Al(e,t.type,te(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function Qi(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function Al(e,t,n){(t!=="number"||Nr(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var jn=Array.isArray;function dn(e,t,n,r){if(e=e.options,t){t={};for(var l=0;l"+t.valueOf().toString()+"",t=Rr.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function Un(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var Bn={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},hc=["Webkit","ms","Moz","O"];Object.keys(Bn).forEach(function(e){hc.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),Bn[t]=Bn[e]})});function Ji(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||Bn.hasOwnProperty(e)&&Bn[e]?(""+t).trim():t+"px"}function qi(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,l=Ji(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,l):e[n]=l}}var mc=M({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Wl(e,t){if(t){if(mc[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(a(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(a(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(a(61))}if(t.style!=null&&typeof t.style!="object")throw Error(a(62))}}function Hl(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var Ql=null;function Kl(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var Yl=null,pn=null,hn=null;function bi(e){if(e=or(e)){if(typeof Yl!="function")throw Error(a(280));var t=e.stateNode;t&&(t=Jr(t),Yl(e.stateNode,e.type,t))}}function eo(e){pn?hn?hn.push(e):hn=[e]:pn=e}function to(){if(pn){var e=pn,t=hn;if(hn=pn=null,bi(e),t)for(e=0;e>>=0,e===0?32:31-(Pc(e)/Nc|0)|0}var Mr=64,Ir=4194304;function Wn(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function Dr(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,l=e.suspendedLanes,u=e.pingedLanes,i=n&268435455;if(i!==0){var s=i&~l;s!==0?r=Wn(s):(u&=i,u!==0&&(r=Wn(u)))}else i=n&~l,i!==0?r=Wn(i):u!==0&&(r=Wn(u));if(r===0)return 0;if(t!==0&&t!==r&&(t&l)===0&&(l=r&-r,u=t&-t,l>=u||l===16&&(u&4194240)!==0))return t;if((r&4)!==0&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Hn(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-lt(t),e[t]=n}function Tc(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=qn),Lo=" ",To=!1;function Oo(e,t){switch(e){case"keyup":return uf.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Mo(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var yn=!1;function af(e,t){switch(e){case"compositionend":return Mo(t);case"keypress":return t.which!==32?null:(To=!0,Lo);case"textInput":return e=t.data,e===Lo&&To?null:e;default:return null}}function sf(e,t){if(yn)return e==="compositionend"||!fu&&Oo(e,t)?(e=xo(),Ar=uu=Ot=null,yn=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Ao(n)}}function Vo(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Vo(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Wo(){for(var e=window,t=Nr();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=Nr(e.document)}return t}function hu(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function gf(e){var t=Wo(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&Vo(n.ownerDocument.documentElement,n)){if(r!==null&&hu(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var l=n.textContent.length,u=Math.min(r.start,l);r=r.end===void 0?u:Math.min(r.end,l),!e.extend&&u>r&&(l=r,r=u,u=l),l=$o(n,u);var i=$o(n,r);l&&i&&(e.rangeCount!==1||e.anchorNode!==l.node||e.anchorOffset!==l.offset||e.focusNode!==i.node||e.focusOffset!==i.offset)&&(t=t.createRange(),t.setStart(l.node,l.offset),e.removeAllRanges(),u>r?(e.addRange(t),e.extend(i.node,i.offset)):(t.setEnd(i.node,i.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,gn=null,mu=null,nr=null,vu=!1;function Ho(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;vu||gn==null||gn!==Nr(r)||(r=gn,"selectionStart"in r&&hu(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),nr&&tr(nr,r)||(nr=r,r=Xr(mu,"onSelect"),0Cn||(e.current=Ru[Cn],Ru[Cn]=null,Cn--)}function ae(e,t){Cn++,Ru[Cn]=e.current,e.current=t}var Ft={},Re=Dt(Ft),Ue=Dt(!1),qt=Ft;function xn(e,t){var n=e.type.contextTypes;if(!n)return Ft;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var l={},u;for(u in n)l[u]=t[u];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=l),l}function Be(e){return e=e.childContextTypes,e!=null}function qr(){ce(Ue),ce(Re)}function ua(e,t,n){if(Re.current!==Ft)throw Error(a(168));ae(Re,t),ae(Ue,n)}function ia(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var l in r)if(!(l in t))throw Error(a(108,oe(e)||"Unknown",l));return M({},n,r)}function br(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Ft,qt=Re.current,ae(Re,e),ae(Ue,Ue.current),!0}function oa(e,t,n){var r=e.stateNode;if(!r)throw Error(a(169));n?(e=ia(e,t,qt),r.__reactInternalMemoizedMergedChildContext=e,ce(Ue),ce(Re),ae(Re,e)):ce(Ue),ae(Ue,n)}var St=null,el=!1,zu=!1;function aa(e){St===null?St=[e]:St.push(e)}function Lf(e){el=!0,aa(e)}function jt(){if(!zu&&St!==null){zu=!0;var e=0,t=ne;try{var n=St;for(ne=1;e>=i,l-=i,kt=1<<32-lt(t)+l|n<Q?(_e=V,V=null):_e=V.sibling;var q=S(h,V,m[Q],_);if(q===null){V===null&&(V=_e);break}e&&V&&q.alternate===null&&t(h,V),d=u(q,d,Q),$===null?j=q:$.sibling=q,$=q,V=_e}if(Q===m.length)return n(h,V),de&&en(h,Q),j;if(V===null){for(;QQ?(_e=V,V=null):_e=V.sibling;var Kt=S(h,V,q.value,_);if(Kt===null){V===null&&(V=_e);break}e&&V&&Kt.alternate===null&&t(h,V),d=u(Kt,d,Q),$===null?j=Kt:$.sibling=Kt,$=Kt,V=_e}if(q.done)return n(h,V),de&&en(h,Q),j;if(V===null){for(;!q.done;Q++,q=m.next())q=x(h,q.value,_),q!==null&&(d=u(q,d,Q),$===null?j=q:$.sibling=q,$=q);return de&&en(h,Q),j}for(V=r(h,V);!q.done;Q++,q=m.next())q=L(V,h,Q,q.value,_),q!==null&&(e&&q.alternate!==null&&V.delete(q.key===null?Q:q.key),d=u(q,d,Q),$===null?j=q:$.sibling=q,$=q);return e&&V.forEach(function(cd){return t(h,cd)}),de&&en(h,Q),j}function ge(h,d,m,_){if(typeof m=="object"&&m!==null&&m.type===Fe&&m.key===null&&(m=m.props.children),typeof m=="object"&&m!==null){switch(m.$$typeof){case Ee:e:{for(var j=m.key,$=d;$!==null;){if($.key===j){if(j=m.type,j===Fe){if($.tag===7){n(h,$.sibling),d=l($,m.props.children),d.return=h,h=d;break e}}else if($.elementType===j||typeof j=="object"&&j!==null&&j.$$typeof===je&&ha(j)===$.type){n(h,$.sibling),d=l($,m.props),d.ref=ar(h,$,m),d.return=h,h=d;break e}n(h,$);break}else t(h,$);$=$.sibling}m.type===Fe?(d=sn(m.props.children,h.mode,_,m.key),d.return=h,h=d):(_=Rl(m.type,m.key,m.props,null,h.mode,_),_.ref=ar(h,d,m),_.return=h,h=_)}return i(h);case Me:e:{for($=m.key;d!==null;){if(d.key===$)if(d.tag===4&&d.stateNode.containerInfo===m.containerInfo&&d.stateNode.implementation===m.implementation){n(h,d.sibling),d=l(d,m.children||[]),d.return=h,h=d;break e}else{n(h,d);break}else t(h,d);d=d.sibling}d=Pi(m,h.mode,_),d.return=h,h=d}return i(h);case je:return $=m._init,ge(h,d,$(m._payload),_)}if(jn(m))return I(h,d,m,_);if(H(m))return F(h,d,m,_);ll(h,m)}return typeof m=="string"&&m!==""||typeof m=="number"?(m=""+m,d!==null&&d.tag===6?(n(h,d.sibling),d=l(d,m),d.return=h,h=d):(n(h,d),d=_i(m,h.mode,_),d.return=h,h=d),i(h)):n(h,d)}return ge}var Rn=ma(!0),va=ma(!1),ul=Dt(null),il=null,zn=null,Du=null;function Fu(){Du=zn=il=null}function ju(e){var t=ul.current;ce(ul),e._currentValue=t}function Uu(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Ln(e,t){il=e,Du=zn=null,e=e.dependencies,e!==null&&e.firstContext!==null&&((e.lanes&t)!==0&&(Ae=!0),e.firstContext=null)}function be(e){var t=e._currentValue;if(Du!==e)if(e={context:e,memoizedValue:t,next:null},zn===null){if(il===null)throw Error(a(308));zn=e,il.dependencies={lanes:0,firstContext:e}}else zn=zn.next=e;return t}var tn=null;function Bu(e){tn===null?tn=[e]:tn.push(e)}function ya(e,t,n,r){var l=t.interleaved;return l===null?(n.next=n,Bu(t)):(n.next=l.next,l.next=n),t.interleaved=n,Ct(e,r)}function Ct(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var Ut=!1;function Au(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function ga(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function xt(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Bt(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,(G&2)!==0){var l=r.pending;return l===null?t.next=t:(t.next=l.next,l.next=t),r.pending=t,Ct(e,n)}return l=r.interleaved,l===null?(t.next=t,Bu(r)):(t.next=l.next,l.next=t),r.interleaved=t,Ct(e,n)}function ol(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,eu(e,n)}}function wa(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var l=null,u=null;if(n=n.firstBaseUpdate,n!==null){do{var i={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};u===null?l=u=i:u=u.next=i,n=n.next}while(n!==null);u===null?l=u=t:u=u.next=t}else l=u=t;n={baseState:r.baseState,firstBaseUpdate:l,lastBaseUpdate:u,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function al(e,t,n,r){var l=e.updateQueue;Ut=!1;var u=l.firstBaseUpdate,i=l.lastBaseUpdate,s=l.shared.pending;if(s!==null){l.shared.pending=null;var f=s,y=f.next;f.next=null,i===null?u=y:i.next=y,i=f;var E=e.alternate;E!==null&&(E=E.updateQueue,s=E.lastBaseUpdate,s!==i&&(s===null?E.firstBaseUpdate=y:s.next=y,E.lastBaseUpdate=f))}if(u!==null){var x=l.baseState;i=0,E=y=f=null,s=u;do{var S=s.lane,L=s.eventTime;if((r&S)===S){E!==null&&(E=E.next={eventTime:L,lane:0,tag:s.tag,payload:s.payload,callback:s.callback,next:null});e:{var I=e,F=s;switch(S=t,L=n,F.tag){case 1:if(I=F.payload,typeof I=="function"){x=I.call(L,x,S);break e}x=I;break e;case 3:I.flags=I.flags&-65537|128;case 0:if(I=F.payload,S=typeof I=="function"?I.call(L,x,S):I,S==null)break e;x=M({},x,S);break e;case 2:Ut=!0}}s.callback!==null&&s.lane!==0&&(e.flags|=64,S=l.effects,S===null?l.effects=[s]:S.push(s))}else L={eventTime:L,lane:S,tag:s.tag,payload:s.payload,callback:s.callback,next:null},E===null?(y=E=L,f=x):E=E.next=L,i|=S;if(s=s.next,s===null){if(s=l.shared.pending,s===null)break;S=s,s=S.next,S.next=null,l.lastBaseUpdate=S,l.shared.pending=null}}while(!0);if(E===null&&(f=x),l.baseState=f,l.firstBaseUpdate=y,l.lastBaseUpdate=E,t=l.shared.interleaved,t!==null){l=t;do i|=l.lane,l=l.next;while(l!==t)}else u===null&&(l.shared.lanes=0);ln|=i,e.lanes=i,e.memoizedState=x}}function Sa(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=Qu.transition;Qu.transition={};try{e(!1),t()}finally{ne=n,Qu.transition=r}}function Ba(){return et().memoizedState}function If(e,t,n){var r=Wt(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},Aa(e))$a(t,n);else if(n=ya(e,t,n,r),n!==null){var l=De();ct(n,e,r,l),Va(n,t,r)}}function Df(e,t,n){var r=Wt(e),l={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(Aa(e))$a(t,l);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var i=t.lastRenderedState,s=u(i,n);if(l.hasEagerState=!0,l.eagerState=s,ut(s,i)){var f=t.interleaved;f===null?(l.next=l,Bu(t)):(l.next=f.next,f.next=l),t.interleaved=l;return}}catch{}finally{}n=ya(e,t,l,r),n!==null&&(l=De(),ct(n,e,r,l),Va(n,t,r))}}function Aa(e){var t=e.alternate;return e===he||t!==null&&t===he}function $a(e,t){dr=fl=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Va(e,t,n){if((n&4194240)!==0){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,eu(e,n)}}var hl={readContext:be,useCallback:ze,useContext:ze,useEffect:ze,useImperativeHandle:ze,useInsertionEffect:ze,useLayoutEffect:ze,useMemo:ze,useReducer:ze,useRef:ze,useState:ze,useDebugValue:ze,useDeferredValue:ze,useTransition:ze,useMutableSource:ze,useSyncExternalStore:ze,useId:ze,unstable_isNewReconciler:!1},Ff={readContext:be,useCallback:function(e,t){return vt().memoizedState=[e,t===void 0?null:t],e},useContext:be,useEffect:Ta,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,dl(4194308,4,Ia.bind(null,t,e),n)},useLayoutEffect:function(e,t){return dl(4194308,4,e,t)},useInsertionEffect:function(e,t){return dl(4,2,e,t)},useMemo:function(e,t){var n=vt();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=vt();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=If.bind(null,he,e),[r.memoizedState,e]},useRef:function(e){var t=vt();return e={current:e},t.memoizedState=e},useState:za,useDebugValue:qu,useDeferredValue:function(e){return vt().memoizedState=e},useTransition:function(){var e=za(!1),t=e[0];return e=Mf.bind(null,e[1]),vt().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=he,l=vt();if(de){if(n===void 0)throw Error(a(407));n=n()}else{if(n=t(),xe===null)throw Error(a(349));(rn&30)!==0||xa(r,t,n)}l.memoizedState=n;var u={value:n,getSnapshot:t};return l.queue=u,Ta(Pa.bind(null,r,u,e),[e]),r.flags|=2048,mr(9,_a.bind(null,r,u,n,t),void 0,null),n},useId:function(){var e=vt(),t=xe.identifierPrefix;if(de){var n=Et,r=kt;n=(r&~(1<<32-lt(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=pr++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=i.createElement(n,{is:r.is}):(e=i.createElement(n),n==="select"&&(i=e,r.multiple?i.multiple=!0:r.size&&(i.size=r.size))):e=i.createElementNS(e,n),e[ht]=t,e[ir]=r,as(e,t,!1,!1),t.stateNode=e;e:{switch(i=Hl(n,r),n){case"dialog":se("cancel",e),se("close",e),l=r;break;case"iframe":case"object":case"embed":se("load",e),l=r;break;case"video":case"audio":for(l=0;lDn&&(t.flags|=128,r=!0,vr(u,!1),t.lanes=4194304)}else{if(!r)if(e=sl(i),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),vr(u,!0),u.tail===null&&u.tailMode==="hidden"&&!i.alternate&&!de)return Le(t),null}else 2*ye()-u.renderingStartTime>Dn&&n!==1073741824&&(t.flags|=128,r=!0,vr(u,!1),t.lanes=4194304);u.isBackwards?(i.sibling=t.child,t.child=i):(n=u.last,n!==null?n.sibling=i:t.child=i,u.last=i)}return u.tail!==null?(t=u.tail,u.rendering=t,u.tail=t.sibling,u.renderingStartTime=ye(),t.sibling=null,n=pe.current,ae(pe,r?n&1|2:n&1),t):(Le(t),null);case 22:case 23:return Ei(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&(t.mode&1)!==0?(Ge&1073741824)!==0&&(Le(t),t.subtreeFlags&6&&(t.flags|=8192)):Le(t),null;case 24:return null;case 25:return null}throw Error(a(156,t.tag))}function Hf(e,t){switch(Tu(t),t.tag){case 1:return Be(t.type)&&qr(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Tn(),ce(Ue),ce(Re),Hu(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 5:return Vu(t),null;case 13:if(ce(pe),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(a(340));Nn()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return ce(pe),null;case 4:return Tn(),null;case 10:return ju(t.type._context),null;case 22:case 23:return Ei(),null;case 24:return null;default:return null}}var gl=!1,Te=!1,Qf=typeof WeakSet=="function"?WeakSet:Set,O=null;function Mn(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){ve(e,t,r)}else n.current=null}function ci(e,t,n){try{n()}catch(r){ve(e,t,r)}}var fs=!1;function Kf(e,t){if(Eu=Ur,e=Wo(),hu(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var l=r.anchorOffset,u=r.focusNode;r=r.focusOffset;try{n.nodeType,u.nodeType}catch{n=null;break e}var i=0,s=-1,f=-1,y=0,E=0,x=e,S=null;t:for(;;){for(var L;x!==n||l!==0&&x.nodeType!==3||(s=i+l),x!==u||r!==0&&x.nodeType!==3||(f=i+r),x.nodeType===3&&(i+=x.nodeValue.length),(L=x.firstChild)!==null;)S=x,x=L;for(;;){if(x===e)break t;if(S===n&&++y===l&&(s=i),S===u&&++E===r&&(f=i),(L=x.nextSibling)!==null)break;x=S,S=x.parentNode}x=L}n=s===-1||f===-1?null:{start:s,end:f}}else n=null}n=n||{start:0,end:0}}else n=null;for(Cu={focusedElem:e,selectionRange:n},Ur=!1,O=t;O!==null;)if(t=O,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,O=e;else for(;O!==null;){t=O;try{var I=t.alternate;if((t.flags&1024)!==0)switch(t.tag){case 0:case 11:case 15:break;case 1:if(I!==null){var F=I.memoizedProps,ge=I.memoizedState,h=t.stateNode,d=h.getSnapshotBeforeUpdate(t.elementType===t.type?F:ot(t.type,F),ge);h.__reactInternalSnapshotBeforeUpdate=d}break;case 3:var m=t.stateNode.containerInfo;m.nodeType===1?m.textContent="":m.nodeType===9&&m.documentElement&&m.removeChild(m.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(a(163))}}catch(_){ve(t,t.return,_)}if(e=t.sibling,e!==null){e.return=t.return,O=e;break}O=t.return}return I=fs,fs=!1,I}function yr(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var l=r=r.next;do{if((l.tag&e)===e){var u=l.destroy;l.destroy=void 0,u!==void 0&&ci(t,n,u)}l=l.next}while(l!==r)}}function wl(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function fi(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function ds(e){var t=e.alternate;t!==null&&(e.alternate=null,ds(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[ht],delete t[ir],delete t[Nu],delete t[Rf],delete t[zf])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function ps(e){return e.tag===5||e.tag===3||e.tag===4}function hs(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||ps(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function di(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Zr));else if(r!==4&&(e=e.child,e!==null))for(di(e,t,n),e=e.sibling;e!==null;)di(e,t,n),e=e.sibling}function pi(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(pi(e,t,n),e=e.sibling;e!==null;)pi(e,t,n),e=e.sibling}var Pe=null,at=!1;function At(e,t,n){for(n=n.child;n!==null;)ms(e,t,n),n=n.sibling}function ms(e,t,n){if(pt&&typeof pt.onCommitFiberUnmount=="function")try{pt.onCommitFiberUnmount(Or,n)}catch{}switch(n.tag){case 5:Te||Mn(n,t);case 6:var r=Pe,l=at;Pe=null,At(e,t,n),Pe=r,at=l,Pe!==null&&(at?(e=Pe,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):Pe.removeChild(n.stateNode));break;case 18:Pe!==null&&(at?(e=Pe,n=n.stateNode,e.nodeType===8?Pu(e.parentNode,n):e.nodeType===1&&Pu(e,n),Gn(e)):Pu(Pe,n.stateNode));break;case 4:r=Pe,l=at,Pe=n.stateNode.containerInfo,at=!0,At(e,t,n),Pe=r,at=l;break;case 0:case 11:case 14:case 15:if(!Te&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){l=r=r.next;do{var u=l,i=u.destroy;u=u.tag,i!==void 0&&((u&2)!==0||(u&4)!==0)&&ci(n,t,i),l=l.next}while(l!==r)}At(e,t,n);break;case 1:if(!Te&&(Mn(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(s){ve(n,t,s)}At(e,t,n);break;case 21:At(e,t,n);break;case 22:n.mode&1?(Te=(r=Te)||n.memoizedState!==null,At(e,t,n),Te=r):At(e,t,n);break;default:At(e,t,n)}}function vs(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new Qf),t.forEach(function(r){var l=td.bind(null,e,r);n.has(r)||(n.add(r),r.then(l,l))})}}function st(e,t){var n=t.deletions;if(n!==null)for(var r=0;rl&&(l=i),r&=~u}if(r=l,r=ye()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*Xf(r/1960))-r,10e?16:e,Vt===null)var r=!1;else{if(e=Vt,Vt=null,xl=0,(G&6)!==0)throw Error(a(331));var l=G;for(G|=4,O=e.current;O!==null;){var u=O,i=u.child;if((O.flags&16)!==0){var s=u.deletions;if(s!==null){for(var f=0;fye()-vi?on(e,0):mi|=n),Ve(e,t)}function zs(e,t){t===0&&((e.mode&1)===0?t=1:(t=Ir,Ir<<=1,(Ir&130023424)===0&&(Ir=4194304)));var n=De();e=Ct(e,t),e!==null&&(Hn(e,t,n),Ve(e,n))}function ed(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),zs(e,n)}function td(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,l=e.memoizedState;l!==null&&(n=l.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(a(314))}r!==null&&r.delete(t),zs(e,n)}var Ls;Ls=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||Ue.current)Ae=!0;else{if((e.lanes&n)===0&&(t.flags&128)===0)return Ae=!1,Vf(e,t,n);Ae=(e.flags&131072)!==0}else Ae=!1,de&&(t.flags&1048576)!==0&&sa(t,nl,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;yl(e,t),e=t.pendingProps;var l=xn(t,Re.current);Ln(t,n),l=Yu(null,t,r,e,l,n);var u=Xu();return t.flags|=1,typeof l=="object"&&l!==null&&typeof l.render=="function"&&l.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Be(r)?(u=!0,br(t)):u=!1,t.memoizedState=l.state!==null&&l.state!==void 0?l.state:null,Au(t),l.updater=ml,t.stateNode=l,l._reactInternals=t,ei(t,r,e,n),t=li(null,t,r,!0,u,n)):(t.tag=0,de&&u&&Lu(t),Ie(null,t,l,n),t=t.child),t;case 16:r=t.elementType;e:{switch(yl(e,t),e=t.pendingProps,l=r._init,r=l(r._payload),t.type=r,l=t.tag=rd(r),e=ot(r,e),l){case 0:t=ri(null,t,r,e,n);break e;case 1:t=ns(null,t,r,e,n);break e;case 11:t=Ja(null,t,r,e,n);break e;case 14:t=qa(null,t,r,ot(r.type,e),n);break e}throw Error(a(306,r,""))}return t;case 0:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:ot(r,l),ri(e,t,r,l,n);case 1:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:ot(r,l),ns(e,t,r,l,n);case 3:e:{if(rs(t),e===null)throw Error(a(387));r=t.pendingProps,u=t.memoizedState,l=u.element,ga(e,t),al(t,r,null,n);var i=t.memoizedState;if(r=i.element,u.isDehydrated)if(u={element:r,isDehydrated:!1,cache:i.cache,pendingSuspenseBoundaries:i.pendingSuspenseBoundaries,transitions:i.transitions},t.updateQueue.baseState=u,t.memoizedState=u,t.flags&256){l=On(Error(a(423)),t),t=ls(e,t,r,n,l);break e}else if(r!==l){l=On(Error(a(424)),t),t=ls(e,t,r,n,l);break e}else for(Xe=It(t.stateNode.containerInfo.firstChild),Ye=t,de=!0,it=null,n=va(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(Nn(),r===l){t=_t(e,t,n);break e}Ie(e,t,r,n)}t=t.child}return t;case 5:return ka(t),e===null&&Mu(t),r=t.type,l=t.pendingProps,u=e!==null?e.memoizedProps:null,i=l.children,xu(r,l)?i=null:u!==null&&xu(r,u)&&(t.flags|=32),ts(e,t),Ie(e,t,i,n),t.child;case 6:return e===null&&Mu(t),null;case 13:return us(e,t,n);case 4:return $u(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Rn(t,null,r,n):Ie(e,t,r,n),t.child;case 11:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:ot(r,l),Ja(e,t,r,l,n);case 7:return Ie(e,t,t.pendingProps,n),t.child;case 8:return Ie(e,t,t.pendingProps.children,n),t.child;case 12:return Ie(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,l=t.pendingProps,u=t.memoizedProps,i=l.value,ae(ul,r._currentValue),r._currentValue=i,u!==null)if(ut(u.value,i)){if(u.children===l.children&&!Ue.current){t=_t(e,t,n);break e}}else for(u=t.child,u!==null&&(u.return=t);u!==null;){var s=u.dependencies;if(s!==null){i=u.child;for(var f=s.firstContext;f!==null;){if(f.context===r){if(u.tag===1){f=xt(-1,n&-n),f.tag=2;var y=u.updateQueue;if(y!==null){y=y.shared;var E=y.pending;E===null?f.next=f:(f.next=E.next,E.next=f),y.pending=f}}u.lanes|=n,f=u.alternate,f!==null&&(f.lanes|=n),Uu(u.return,n,t),s.lanes|=n;break}f=f.next}}else if(u.tag===10)i=u.type===t.type?null:u.child;else if(u.tag===18){if(i=u.return,i===null)throw Error(a(341));i.lanes|=n,s=i.alternate,s!==null&&(s.lanes|=n),Uu(i,n,t),i=u.sibling}else i=u.child;if(i!==null)i.return=u;else for(i=u;i!==null;){if(i===t){i=null;break}if(u=i.sibling,u!==null){u.return=i.return,i=u;break}i=i.return}u=i}Ie(e,t,l.children,n),t=t.child}return t;case 9:return l=t.type,r=t.pendingProps.children,Ln(t,n),l=be(l),r=r(l),t.flags|=1,Ie(e,t,r,n),t.child;case 14:return r=t.type,l=ot(r,t.pendingProps),l=ot(r.type,l),qa(e,t,r,l,n);case 15:return ba(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,l=t.pendingProps,l=t.elementType===r?l:ot(r,l),yl(e,t),t.tag=1,Be(r)?(e=!0,br(t)):e=!1,Ln(t,n),Ha(t,r,l),ei(t,r,l,n),li(null,t,r,!0,e,n);case 19:return os(e,t,n);case 22:return es(e,t,n)}throw Error(a(156,t.tag))};function Ts(e,t){return so(e,t)}function nd(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function nt(e,t,n,r){return new nd(e,t,n,r)}function xi(e){return e=e.prototype,!(!e||!e.isReactComponent)}function rd(e){if(typeof e=="function")return xi(e)?1:0;if(e!=null){if(e=e.$$typeof,e===ft)return 11;if(e===dt)return 14}return 2}function Qt(e,t){var n=e.alternate;return n===null?(n=nt(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Rl(e,t,n,r,l,u){var i=2;if(r=e,typeof e=="function")xi(e)&&(i=1);else if(typeof e=="string")i=5;else e:switch(e){case Fe:return sn(n.children,l,u,t);case Ze:i=8,l|=8;break;case Nt:return e=nt(12,n,t,l|2),e.elementType=Nt,e.lanes=u,e;case He:return e=nt(13,n,t,l),e.elementType=He,e.lanes=u,e;case rt:return e=nt(19,n,t,l),e.elementType=rt,e.lanes=u,e;case me:return zl(n,l,u,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case gt:i=10;break e;case Gt:i=9;break e;case ft:i=11;break e;case dt:i=14;break e;case je:i=16,r=null;break e}throw Error(a(130,e==null?e:typeof e,""))}return t=nt(i,n,t,l),t.elementType=e,t.type=r,t.lanes=u,t}function sn(e,t,n,r){return e=nt(7,e,r,t),e.lanes=n,e}function zl(e,t,n,r){return e=nt(22,e,r,t),e.elementType=me,e.lanes=n,e.stateNode={isHidden:!1},e}function _i(e,t,n){return e=nt(6,e,null,t),e.lanes=n,e}function Pi(e,t,n){return t=nt(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function ld(e,t,n,r,l){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=bl(0),this.expirationTimes=bl(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=bl(0),this.identifierPrefix=r,this.onRecoverableError=l,this.mutableSourceEagerHydrationData=null}function Ni(e,t,n,r,l,u,i,s,f){return e=new ld(e,t,n,s,f),t===1?(t=1,u===!0&&(t|=8)):t=0,u=nt(3,null,null,t),e.current=u,u.stateNode=e,u.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Au(u),e}function ud(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(o)}catch(c){console.error(c)}}return o(),Oi.exports=hd(),Oi.exports}var D=bs();const vd=qs(D),yd=Js({__proto__:null,default:vd},[D]);var ec=md();const gd=qs(ec),wp=Js({__proto__:null,default:gd},[ec]);/** - * @remix-run/router v1.23.0 - * - * Copyright (c) Remix Software Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE.md file in the root directory of this source tree. - * - * @license MIT - */function Er(){return Er=Object.assign?Object.assign.bind():function(o){for(var c=1;c"u")throw new Error(c)}function tc(o,c){if(!o){typeof console<"u"&&console.warn(c);try{throw new Error(c)}catch{}}}function Sd(){return Math.random().toString(36).substr(2,8)}function Hs(o,c){return{usr:o.state,key:o.key,idx:c}}function Fi(o,c,a,v){return a===void 0&&(a=null),Er({pathname:typeof o=="string"?o:o.pathname,search:"",hash:""},typeof c=="string"?Cr(c):c,{state:a,key:c&&c.key||v||Sd()})}function Fl(o){let{pathname:c="/",search:a="",hash:v=""}=o;return a&&a!=="?"&&(c+=a.charAt(0)==="?"?a:"?"+a),v&&v!=="#"&&(c+=v.charAt(0)==="#"?v:"#"+v),c}function Cr(o){let c={};if(o){let a=o.indexOf("#");a>=0&&(c.hash=o.substr(a),o=o.substr(0,a));let v=o.indexOf("?");v>=0&&(c.search=o.substr(v),o=o.substr(0,v)),o&&(c.pathname=o)}return c}function kd(o,c,a,v){v===void 0&&(v={});let{window:g=document.defaultView,v5Compat:w=!1}=v,C=g.history,N=cn.Pop,P=null,T=A();T==null&&(T=0,C.replaceState(Er({},C.state,{idx:T}),""));function A(){return(C.state||{idx:null}).idx}function R(){N=cn.Pop;let U=A(),le=U==null?null:U-T;T=U,P&&P({action:N,location:B.location,delta:le})}function W(U,le){N=cn.Push;let ue=Fi(B.location,U,le);T=A()+1;let ee=Hs(ue,T),ie=B.createHref(ue);try{C.pushState(ee,"",ie)}catch(Ee){if(Ee instanceof DOMException&&Ee.name==="DataCloneError")throw Ee;g.location.assign(ie)}w&&P&&P({action:N,location:B.location,delta:1})}function re(U,le){N=cn.Replace;let ue=Fi(B.location,U,le);T=A();let ee=Hs(ue,T),ie=B.createHref(ue);C.replaceState(ee,"",ie),w&&P&&P({action:N,location:B.location,delta:0})}function b(U){let le=g.location.origin!=="null"?g.location.origin:g.location.href,ue=typeof U=="string"?U:Fl(U);return ue=ue.replace(/ $/,"%20"),Oe(le,"No window.location.(origin|href) available to create URL for href: "+ue),new URL(ue,le)}let B={get action(){return N},get location(){return o(g,C)},listen(U){if(P)throw new Error("A history only accepts one active listener");return g.addEventListener(Ws,R),P=U,()=>{g.removeEventListener(Ws,R),P=null}},createHref(U){return c(g,U)},createURL:b,encodeLocation(U){let le=b(U);return{pathname:le.pathname,search:le.search,hash:le.hash}},push:W,replace:re,go(U){return C.go(U)}};return B}var Qs;(function(o){o.data="data",o.deferred="deferred",o.redirect="redirect",o.error="error"})(Qs||(Qs={}));function Ed(o,c,a){return a===void 0&&(a="/"),Cd(o,c,a)}function Cd(o,c,a,v){let g=typeof c=="string"?Cr(c):c,w=Bi(g.pathname||"/",a);if(w==null)return null;let C=nc(o);xd(C);let N=null;for(let P=0;N==null&&P{let P={relativePath:N===void 0?w.path||"":N,caseSensitive:w.caseSensitive===!0,childrenIndex:C,route:w};P.relativePath.startsWith("/")&&(Oe(P.relativePath.startsWith(v),'Absolute route path "'+P.relativePath+'" nested under path '+('"'+v+'" is not valid. An absolute child route path ')+"must start with the combined path of all its parent routes."),P.relativePath=P.relativePath.slice(v.length));let T=Yt([v,P.relativePath]),A=a.concat(P);w.children&&w.children.length>0&&(Oe(w.index!==!0,"Index routes must not have child routes. Please remove "+('all child routes from route path "'+T+'".')),nc(w.children,c,A,T)),!(w.path==null&&!w.index)&&c.push({path:T,score:Td(T,w.index),routesMeta:A})};return o.forEach((w,C)=>{var N;if(w.path===""||!((N=w.path)!=null&&N.includes("?")))g(w,C);else for(let P of rc(w.path))g(w,C,P)}),c}function rc(o){let c=o.split("/");if(c.length===0)return[];let[a,...v]=c,g=a.endsWith("?"),w=a.replace(/\?$/,"");if(v.length===0)return g?[w,""]:[w];let C=rc(v.join("/")),N=[];return N.push(...C.map(P=>P===""?w:[w,P].join("/"))),g&&N.push(...C),N.map(P=>o.startsWith("/")&&P===""?"/":P)}function xd(o){o.sort((c,a)=>c.score!==a.score?a.score-c.score:Od(c.routesMeta.map(v=>v.childrenIndex),a.routesMeta.map(v=>v.childrenIndex)))}const _d=/^:[\w-]+$/,Pd=3,Nd=2,Rd=1,zd=10,Ld=-2,Ks=o=>o==="*";function Td(o,c){let a=o.split("/"),v=a.length;return a.some(Ks)&&(v+=Ld),c&&(v+=Nd),a.filter(g=>!Ks(g)).reduce((g,w)=>g+(_d.test(w)?Pd:w===""?Rd:zd),v)}function Od(o,c){return o.length===c.length&&o.slice(0,-1).every((v,g)=>v===c[g])?o[o.length-1]-c[c.length-1]:0}function Md(o,c,a){let{routesMeta:v}=o,g={},w="/",C=[];for(let N=0;N{let{paramName:W,isOptional:re}=A;if(W==="*"){let B=N[R]||"";C=w.slice(0,w.length-B.length).replace(/(.)\/+$/,"$1")}const b=N[R];return re&&!b?T[W]=void 0:T[W]=(b||"").replace(/%2F/g,"/"),T},{}),pathname:w,pathnameBase:C,pattern:o}}function Dd(o,c,a){c===void 0&&(c=!1),a===void 0&&(a=!0),tc(o==="*"||!o.endsWith("*")||o.endsWith("/*"),'Route path "'+o+'" will be treated as if it were '+('"'+o.replace(/\*$/,"/*")+'" because the `*` character must ')+"always follow a `/` in the pattern. To get rid of this warning, "+('please change the route path to "'+o.replace(/\*$/,"/*")+'".'));let v=[],g="^"+o.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(C,N,P)=>(v.push({paramName:N,isOptional:P!=null}),P?"/?([^\\/]+)?":"/([^\\/]+)"));return o.endsWith("*")?(v.push({paramName:"*"}),g+=o==="*"||o==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):a?g+="\\/*$":o!==""&&o!=="/"&&(g+="(?:(?=\\/|$))"),[new RegExp(g,c?void 0:"i"),v]}function Fd(o){try{return o.split("/").map(c=>decodeURIComponent(c).replace(/\//g,"%2F")).join("/")}catch(c){return tc(!1,'The URL path "'+o+'" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent '+("encoding ("+c+").")),o}}function Bi(o,c){if(c==="/")return o;if(!o.toLowerCase().startsWith(c.toLowerCase()))return null;let a=c.endsWith("/")?c.length-1:c.length,v=o.charAt(a);return v&&v!=="/"?null:o.slice(a)||"/"}function jd(o,c){c===void 0&&(c="/");let{pathname:a,search:v="",hash:g=""}=typeof o=="string"?Cr(o):o;return{pathname:a?a.startsWith("/")?a:Ud(a,c):c,search:$d(v),hash:Vd(g)}}function Ud(o,c){let a=c.replace(/\/+$/,"").split("/");return o.split("/").forEach(g=>{g===".."?a.length>1&&a.pop():g!=="."&&a.push(g)}),a.length>1?a.join("/"):"/"}function Di(o,c,a,v){return"Cannot include a '"+o+"' character in a manually specified "+("`to."+c+"` field ["+JSON.stringify(v)+"]. Please separate it out to the ")+("`to."+a+"` field. Alternatively you may provide the full path as ")+'a string in and the router will parse it for you.'}function Bd(o){return o.filter((c,a)=>a===0||c.route.path&&c.route.path.length>0)}function lc(o,c){let a=Bd(o);return c?a.map((v,g)=>g===a.length-1?v.pathname:v.pathnameBase):a.map(v=>v.pathnameBase)}function uc(o,c,a,v){v===void 0&&(v=!1);let g;typeof o=="string"?g=Cr(o):(g=Er({},o),Oe(!g.pathname||!g.pathname.includes("?"),Di("?","pathname","search",g)),Oe(!g.pathname||!g.pathname.includes("#"),Di("#","pathname","hash",g)),Oe(!g.search||!g.search.includes("#"),Di("#","search","hash",g)));let w=o===""||g.pathname==="",C=w?"/":g.pathname,N;if(C==null)N=a;else{let R=c.length-1;if(!v&&C.startsWith("..")){let W=C.split("/");for(;W[0]==="..";)W.shift(),R-=1;g.pathname=W.join("/")}N=R>=0?c[R]:"/"}let P=jd(g,N),T=C&&C!=="/"&&C.endsWith("/"),A=(w||C===".")&&a.endsWith("/");return!P.pathname.endsWith("/")&&(T||A)&&(P.pathname+="/"),P}const Yt=o=>o.join("/").replace(/\/\/+/g,"/"),Ad=o=>o.replace(/\/+$/,"").replace(/^\/*/,"/"),$d=o=>!o||o==="?"?"":o.startsWith("?")?o:"?"+o,Vd=o=>!o||o==="#"?"":o.startsWith("#")?o:"#"+o;function Wd(o){return o!=null&&typeof o.status=="number"&&typeof o.statusText=="string"&&typeof o.internal=="boolean"&&"data"in o}const ic=["post","put","patch","delete"];new Set(ic);const Hd=["get",...ic];new Set(Hd);/** - * React Router v6.30.1 - * - * Copyright (c) Remix Software Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE.md file in the root directory of this source tree. - * - * @license MIT - */function jl(){return jl=Object.assign?Object.assign.bind():function(o){for(var c=1;c{N.current=!0}),D.useCallback(function(T,A){if(A===void 0&&(A={}),!N.current)return;if(typeof T=="number"){v.go(T);return}let R=uc(T,JSON.parse(C),w,A.relative==="path");o==null&&c!=="/"&&(R.pathname=R.pathname==="/"?c:Yt([c,R.pathname])),(A.replace?v.replace:v.push)(R,A.state,A)},[c,v,C,w,o])}function Sp(){let{matches:o}=D.useContext(Xt),c=o[o.length-1];return c?c.params:{}}function cc(o,c){let{relative:a}=c===void 0?{}:c,{future:v}=D.useContext(fn),{matches:g}=D.useContext(Xt),{pathname:w}=_r(),C=JSON.stringify(lc(g,v.v7_relativeSplatPath));return D.useMemo(()=>uc(o,JSON.parse(C),w,a==="path"),[o,C,w,a])}function kp(o,c){return Xd(o)}function Xd(o,c,a,v){xr()||Oe(!1);let{navigator:g}=D.useContext(fn),{matches:w}=D.useContext(Xt),C=w[w.length-1],N=C?C.params:{};C&&C.pathname;let P=C?C.pathnameBase:"/";C&&C.route;let T=_r(),A;A=T;let R=A.pathname||"/",W=R;if(P!=="/"){let B=P.replace(/^\//,"").split("/");W="/"+R.replace(/^\//,"").split("/").slice(B.length).join("/")}let re=Ed(o,{pathname:W});return bd(re&&re.map(B=>Object.assign({},B,{params:Object.assign({},N,B.params),pathname:Yt([P,g.encodeLocation?g.encodeLocation(B.pathname).pathname:B.pathname]),pathnameBase:B.pathnameBase==="/"?P:Yt([P,g.encodeLocation?g.encodeLocation(B.pathnameBase).pathname:B.pathnameBase])})),w,a,v)}function Gd(){let o=rp(),c=Wd(o)?o.status+" "+o.statusText:o instanceof Error?o.message:JSON.stringify(o),a=o instanceof Error?o.stack:null,g={padding:"0.5rem",backgroundColor:"rgba(200,200,200, 0.5)"};return D.createElement(D.Fragment,null,D.createElement("h2",null,"Unexpected Application Error!"),D.createElement("h3",{style:{fontStyle:"italic"}},c),a?D.createElement("pre",{style:g},a):null,null)}const Zd=D.createElement(Gd,null);class Jd extends D.Component{constructor(c){super(c),this.state={location:c.location,revalidation:c.revalidation,error:c.error}}static getDerivedStateFromError(c){return{error:c}}static getDerivedStateFromProps(c,a){return a.location!==c.location||a.revalidation!=="idle"&&c.revalidation==="idle"?{error:c.error,location:c.location,revalidation:c.revalidation}:{error:c.error!==void 0?c.error:a.error,location:a.location,revalidation:c.revalidation||a.revalidation}}componentDidCatch(c,a){console.error("React Router caught the following error during render",c,a)}render(){return this.state.error!==void 0?D.createElement(Xt.Provider,{value:this.props.routeContext},D.createElement(oc.Provider,{value:this.state.error,children:this.props.component})):this.props.children}}function qd(o){let{routeContext:c,match:a,children:v}=o,g=D.useContext(Ai);return g&&g.static&&g.staticContext&&(a.route.errorElement||a.route.ErrorBoundary)&&(g.staticContext._deepestRenderedBoundaryId=a.route.id),D.createElement(Xt.Provider,{value:c},v)}function bd(o,c,a,v){var g;if(c===void 0&&(c=[]),a===void 0&&(a=null),v===void 0&&(v=null),o==null){var w;if(!a)return null;if(a.errors)o=a.matches;else if((w=v)!=null&&w.v7_partialHydration&&c.length===0&&!a.initialized&&a.matches.length>0)o=a.matches;else return null}let C=o,N=(g=a)==null?void 0:g.errors;if(N!=null){let A=C.findIndex(R=>R.route.id&&N?.[R.route.id]!==void 0);A>=0||Oe(!1),C=C.slice(0,Math.min(C.length,A+1))}let P=!1,T=-1;if(a&&v&&v.v7_partialHydration)for(let A=0;A=0?C=C.slice(0,T+1):C=[C[0]];break}}}return C.reduceRight((A,R,W)=>{let re,b=!1,B=null,U=null;a&&(re=N&&R.route.id?N[R.route.id]:void 0,B=R.route.errorElement||Zd,P&&(T<0&&W===0?(up("route-fallback"),b=!0,U=null):T===W&&(b=!0,U=R.route.hydrateFallbackElement||null)));let le=c.concat(C.slice(0,W+1)),ue=()=>{let ee;return re?ee=B:b?ee=U:R.route.Component?ee=D.createElement(R.route.Component,null):R.route.element?ee=R.route.element:ee=A,D.createElement(qd,{match:R,routeContext:{outlet:A,matches:le,isDataRoute:a!=null},children:ee})};return a&&(R.route.ErrorBoundary||R.route.errorElement||W===0)?D.createElement(Jd,{location:a.location,revalidation:a.revalidation,component:B,error:re,children:ue(),routeContext:{outlet:null,matches:le,isDataRoute:!0}}):ue()},null)}var fc=function(o){return o.UseBlocker="useBlocker",o.UseRevalidator="useRevalidator",o.UseNavigateStable="useNavigate",o}(fc||{}),dc=function(o){return o.UseBlocker="useBlocker",o.UseLoaderData="useLoaderData",o.UseActionData="useActionData",o.UseRouteError="useRouteError",o.UseNavigation="useNavigation",o.UseRouteLoaderData="useRouteLoaderData",o.UseMatches="useMatches",o.UseRevalidator="useRevalidator",o.UseNavigateStable="useNavigate",o.UseRouteId="useRouteId",o}(dc||{});function ep(o){let c=D.useContext(Ai);return c||Oe(!1),c}function tp(o){let c=D.useContext(Qd);return c||Oe(!1),c}function np(o){let c=D.useContext(Xt);return c||Oe(!1),c}function pc(o){let c=np(),a=c.matches[c.matches.length-1];return a.route.id||Oe(!1),a.route.id}function rp(){var o;let c=D.useContext(oc),a=tp(),v=pc();return c!==void 0?c:(o=a.errors)==null?void 0:o[v]}function lp(){let{router:o}=ep(fc.UseNavigateStable),c=pc(dc.UseNavigateStable),a=D.useRef(!1);return ac(()=>{a.current=!0}),D.useCallback(function(g,w){w===void 0&&(w={}),a.current&&(typeof g=="number"?o.navigate(g):o.navigate(g,jl({fromRouteId:c},w)))},[o,c])}const Ys={};function up(o,c,a){Ys[o]||(Ys[o]=!0)}function ip(o,c){o?.v7_startTransition,o?.v7_relativeSplatPath}function op(o){let{basename:c="/",children:a=null,location:v,navigationType:g=cn.Pop,navigator:w,static:C=!1,future:N}=o;xr()&&Oe(!1);let P=c.replace(/^\/*/,"/"),T=D.useMemo(()=>({basename:P,navigator:w,static:C,future:jl({v7_relativeSplatPath:!1},N)}),[P,N,w,C]);typeof v=="string"&&(v=Cr(v));let{pathname:A="/",search:R="",hash:W="",state:re=null,key:b="default"}=v,B=D.useMemo(()=>{let U=Bi(A,P);return U==null?null:{location:{pathname:U,search:R,hash:W,state:re,key:b},navigationType:g}},[P,A,R,W,re,b,g]);return B==null?null:D.createElement(fn.Provider,{value:T},D.createElement($i.Provider,{children:a,value:B}))}new Promise(()=>{});/** - * React Router DOM v6.30.1 - * - * Copyright (c) Remix Software Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE.md file in the root directory of this source tree. - * - * @license MIT - */function ji(){return ji=Object.assign?Object.assign.bind():function(o){for(var c=1;c=0)&&(a[g]=o[g]);return a}function sp(o){return!!(o.metaKey||o.altKey||o.ctrlKey||o.shiftKey)}function cp(o,c){return o.button===0&&(!c||c==="_self")&&!sp(o)}function Ui(o){return o===void 0&&(o=""),new URLSearchParams(typeof o=="string"||Array.isArray(o)||o instanceof URLSearchParams?o:Object.keys(o).reduce((c,a)=>{let v=o[a];return c.concat(Array.isArray(v)?v.map(g=>[a,g]):[[a,v]])},[]))}function fp(o,c){let a=Ui(o);return c&&c.forEach((v,g)=>{a.has(g)||c.getAll(g).forEach(w=>{a.append(g,w)})}),a}const dp=["onClick","relative","reloadDocument","replace","state","target","to","preventScrollReset","viewTransition"],pp="6";try{window.__reactRouterVersion=pp}catch{}const hp="startTransition",Xs=yd[hp];function Ep(o){let{basename:c,children:a,future:v,window:g}=o,w=D.useRef();w.current==null&&(w.current=wd({window:g,v5Compat:!0}));let C=w.current,[N,P]=D.useState({action:C.action,location:C.location}),{v7_startTransition:T}=v||{},A=D.useCallback(R=>{T&&Xs?Xs(()=>P(R)):P(R)},[P,T]);return D.useLayoutEffect(()=>C.listen(A),[C,A]),D.useEffect(()=>ip(v),[v]),D.createElement(op,{basename:c,children:a,location:N.location,navigationType:N.action,navigator:C,future:v})}const mp=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u",vp=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Cp=D.forwardRef(function(c,a){let{onClick:v,relative:g,reloadDocument:w,replace:C,state:N,target:P,to:T,preventScrollReset:A,viewTransition:R}=c,W=ap(c,dp),{basename:re}=D.useContext(fn),b,B=!1;if(typeof T=="string"&&vp.test(T)&&(b=T,mp))try{let ee=new URL(window.location.href),ie=T.startsWith("//")?new URL(ee.protocol+T):new URL(T),Ee=Bi(ie.pathname,re);ie.origin===ee.origin&&Ee!=null?T=Ee+ie.search+ie.hash:B=!0}catch{}let U=Kd(T,{relative:g}),le=yp(T,{replace:C,state:N,target:P,preventScrollReset:A,relative:g,viewTransition:R});function ue(ee){v&&v(ee),ee.defaultPrevented||le(ee)}return D.createElement("a",ji({},W,{href:b||U,onClick:B||w?v:ue,ref:a,target:P}))});var Gs;(function(o){o.UseScrollRestoration="useScrollRestoration",o.UseSubmit="useSubmit",o.UseSubmitFetcher="useSubmitFetcher",o.UseFetcher="useFetcher",o.useViewTransitionState="useViewTransitionState"})(Gs||(Gs={}));var Zs;(function(o){o.UseFetcher="useFetcher",o.UseFetchers="useFetchers",o.UseScrollRestoration="useScrollRestoration"})(Zs||(Zs={}));function yp(o,c){let{target:a,replace:v,state:g,preventScrollReset:w,relative:C,viewTransition:N}=c===void 0?{}:c,P=sc(),T=_r(),A=cc(o,{relative:C});return D.useCallback(R=>{if(cp(R,a)){R.preventDefault();let W=v!==void 0?v:Fl(T)===Fl(A);P(o,{replace:W,state:g,preventScrollReset:w,relative:C,viewTransition:N})}},[T,P,A,v,g,a,o,w,C,N])}function xp(o){let c=D.useRef(Ui(o)),a=D.useRef(!1),v=_r(),g=D.useMemo(()=>fp(v.search,a.current?null:c.current),[v.search]),w=sc(),C=D.useCallback((N,P)=>{const T=Ui(typeof N=="function"?N(g):N);a.current=!0,w("?"+T,P)},[w,g]);return[g,C]}export{Ep as B,Cp as L,vd as R,ec as a,md as b,gp as c,bs as d,gd as e,yd as f,qs as g,wp as h,Sp as i,xp as j,_r as k,kp as l,D as r,sc as u}; diff --git a/Cunkebao/dist/index.html b/Cunkebao/dist/index.html index 0b6673bb..16e6d604 100644 --- a/Cunkebao/dist/index.html +++ b/Cunkebao/dist/index.html @@ -11,13 +11,13 @@ - - - - - + + + + + - +
diff --git a/Cunkebao/package.json b/Cunkebao/package.json index 313741a1..0277589c 100644 --- a/Cunkebao/package.json +++ b/Cunkebao/package.json @@ -18,6 +18,7 @@ "react-router-dom": "^6.20.0", "react-window": "^1.8.11", "vconsole": "^3.15.1", + "xmldom": "^0.6.0", "zustand": "^5.0.6" }, "devDependencies": { diff --git a/Cunkebao/pnpm-lock.yaml b/Cunkebao/pnpm-lock.yaml index dda30990..818ed7d7 100644 --- a/Cunkebao/pnpm-lock.yaml +++ b/Cunkebao/pnpm-lock.yaml @@ -50,6 +50,9 @@ importers: vconsole: specifier: ^3.15.1 version: 3.15.1 + xmldom: + specifier: ^0.6.0 + version: 0.6.0 zustand: specifier: ^5.0.6 version: 5.0.7(@types/react@19.1.10)(react@18.3.1)(use-sync-external-store@1.5.0(react@18.3.1)) @@ -2355,6 +2358,10 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + xmldom@0.6.0: + resolution: {integrity: sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==} + engines: {node: '>=10.0.0'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -4974,6 +4981,8 @@ snapshots: wrappy@1.0.2: {} + xmldom@0.6.0: {} + yallist@3.1.1: {} yocto-queue@0.1.0: {} diff --git a/Cunkebao/public/assets/animal/发抖.png b/Cunkebao/public/assets/animal/发抖.png new file mode 100644 index 00000000..2bc6cf22 Binary files /dev/null and b/Cunkebao/public/assets/animal/发抖.png differ diff --git a/Cunkebao/public/assets/animal/猪头.png b/Cunkebao/public/assets/animal/猪头.png new file mode 100644 index 00000000..c14749ee Binary files /dev/null and b/Cunkebao/public/assets/animal/猪头.png differ diff --git a/Cunkebao/public/assets/animal/跳跳.png b/Cunkebao/public/assets/animal/跳跳.png new file mode 100644 index 00000000..ae1307aa Binary files /dev/null and b/Cunkebao/public/assets/animal/跳跳.png differ diff --git a/Cunkebao/public/assets/animal/转圈.png b/Cunkebao/public/assets/animal/转圈.png new file mode 100644 index 00000000..7aa3b5a5 Binary files /dev/null and b/Cunkebao/public/assets/animal/转圈.png differ diff --git a/Cunkebao/public/assets/blessing/庆祝.png b/Cunkebao/public/assets/blessing/庆祝.png new file mode 100644 index 00000000..6b3c6391 Binary files /dev/null and b/Cunkebao/public/assets/blessing/庆祝.png differ diff --git a/Cunkebao/public/assets/blessing/烟花.png b/Cunkebao/public/assets/blessing/烟花.png new file mode 100644 index 00000000..58d2848f Binary files /dev/null and b/Cunkebao/public/assets/blessing/烟花.png differ diff --git a/Cunkebao/public/assets/blessing/爆竹.png b/Cunkebao/public/assets/blessing/爆竹.png new file mode 100644 index 00000000..52ac8fb2 Binary files /dev/null and b/Cunkebao/public/assets/blessing/爆竹.png differ diff --git a/Cunkebao/public/assets/blessing/發.png b/Cunkebao/public/assets/blessing/發.png new file mode 100644 index 00000000..2af454cb Binary files /dev/null and b/Cunkebao/public/assets/blessing/發.png differ diff --git a/Cunkebao/public/assets/blessing/礼物.png b/Cunkebao/public/assets/blessing/礼物.png new file mode 100644 index 00000000..6082fbaf Binary files /dev/null and b/Cunkebao/public/assets/blessing/礼物.png differ diff --git a/Cunkebao/public/assets/blessing/福.png b/Cunkebao/public/assets/blessing/福.png new file mode 100644 index 00000000..d4a5b174 Binary files /dev/null and b/Cunkebao/public/assets/blessing/福.png differ diff --git a/Cunkebao/public/assets/blessing/红包.png b/Cunkebao/public/assets/blessing/红包.png new file mode 100644 index 00000000..28b9698d Binary files /dev/null and b/Cunkebao/public/assets/blessing/红包.png differ diff --git a/Cunkebao/public/assets/face/666.png b/Cunkebao/public/assets/face/666.png new file mode 100644 index 00000000..f947dc66 Binary files /dev/null and b/Cunkebao/public/assets/face/666.png differ diff --git a/Cunkebao/public/assets/face/Emm.png b/Cunkebao/public/assets/face/Emm.png new file mode 100644 index 00000000..8fb9370d Binary files /dev/null and b/Cunkebao/public/assets/face/Emm.png differ diff --git a/Cunkebao/public/assets/face/亲亲.png b/Cunkebao/public/assets/face/亲亲.png new file mode 100644 index 00000000..3190fa39 Binary files /dev/null and b/Cunkebao/public/assets/face/亲亲.png differ diff --git a/Cunkebao/public/assets/face/偷笑.png b/Cunkebao/public/assets/face/偷笑.png new file mode 100644 index 00000000..51836d13 Binary files /dev/null and b/Cunkebao/public/assets/face/偷笑.png differ diff --git a/Cunkebao/public/assets/face/傲慢.png b/Cunkebao/public/assets/face/傲慢.png new file mode 100644 index 00000000..cfd4cf55 Binary files /dev/null and b/Cunkebao/public/assets/face/傲慢.png differ diff --git a/Cunkebao/public/assets/face/再见.png b/Cunkebao/public/assets/face/再见.png new file mode 100644 index 00000000..8ef994b6 Binary files /dev/null and b/Cunkebao/public/assets/face/再见.png differ diff --git a/Cunkebao/public/assets/face/加油.png b/Cunkebao/public/assets/face/加油.png new file mode 100644 index 00000000..911ca554 Binary files /dev/null and b/Cunkebao/public/assets/face/加油.png differ diff --git a/Cunkebao/public/assets/face/发呆.png b/Cunkebao/public/assets/face/发呆.png new file mode 100644 index 00000000..e6e388f0 Binary files /dev/null and b/Cunkebao/public/assets/face/发呆.png differ diff --git a/Cunkebao/public/assets/face/发怒.png b/Cunkebao/public/assets/face/发怒.png new file mode 100644 index 00000000..c8cba000 Binary files /dev/null and b/Cunkebao/public/assets/face/发怒.png differ diff --git a/Cunkebao/public/assets/face/可怜.png b/Cunkebao/public/assets/face/可怜.png new file mode 100644 index 00000000..1e75cbb5 Binary files /dev/null and b/Cunkebao/public/assets/face/可怜.png differ diff --git a/Cunkebao/public/assets/face/右哼哼.png b/Cunkebao/public/assets/face/右哼哼.png new file mode 100644 index 00000000..e466e2ae Binary files /dev/null and b/Cunkebao/public/assets/face/右哼哼.png differ diff --git a/Cunkebao/public/assets/face/叹气.png b/Cunkebao/public/assets/face/叹气.png new file mode 100644 index 00000000..2840584d Binary files /dev/null and b/Cunkebao/public/assets/face/叹气.png differ diff --git a/Cunkebao/public/assets/face/吃瓜.png b/Cunkebao/public/assets/face/吃瓜.png new file mode 100644 index 00000000..64f72ade Binary files /dev/null and b/Cunkebao/public/assets/face/吃瓜.png differ diff --git a/Cunkebao/public/assets/face/吐.png b/Cunkebao/public/assets/face/吐.png new file mode 100644 index 00000000..b3e072ed Binary files /dev/null and b/Cunkebao/public/assets/face/吐.png differ diff --git a/Cunkebao/public/assets/face/呲牙.png b/Cunkebao/public/assets/face/呲牙.png new file mode 100644 index 00000000..abce5e0c Binary files /dev/null and b/Cunkebao/public/assets/face/呲牙.png differ diff --git a/Cunkebao/public/assets/face/咒骂.png b/Cunkebao/public/assets/face/咒骂.png new file mode 100644 index 00000000..0a8c0bf2 Binary files /dev/null and b/Cunkebao/public/assets/face/咒骂.png differ diff --git a/Cunkebao/public/assets/face/哇.png b/Cunkebao/public/assets/face/哇.png new file mode 100644 index 00000000..5d1c1796 Binary files /dev/null and b/Cunkebao/public/assets/face/哇.png differ diff --git a/Cunkebao/public/assets/face/嘘.png b/Cunkebao/public/assets/face/嘘.png new file mode 100644 index 00000000..a6700568 Binary files /dev/null and b/Cunkebao/public/assets/face/嘘.png differ diff --git a/Cunkebao/public/assets/face/嘿哈.png b/Cunkebao/public/assets/face/嘿哈.png new file mode 100644 index 00000000..d424a3f3 Binary files /dev/null and b/Cunkebao/public/assets/face/嘿哈.png differ diff --git a/Cunkebao/public/assets/face/囧.png b/Cunkebao/public/assets/face/囧.png new file mode 100644 index 00000000..fc7fbfc2 Binary files /dev/null and b/Cunkebao/public/assets/face/囧.png differ diff --git a/Cunkebao/public/assets/face/困.png b/Cunkebao/public/assets/face/困.png new file mode 100644 index 00000000..148c66fe Binary files /dev/null and b/Cunkebao/public/assets/face/困.png differ diff --git a/Cunkebao/public/assets/face/坏笑.png b/Cunkebao/public/assets/face/坏笑.png new file mode 100644 index 00000000..8585d822 Binary files /dev/null and b/Cunkebao/public/assets/face/坏笑.png differ diff --git a/Cunkebao/public/assets/face/大哭.png b/Cunkebao/public/assets/face/大哭.png new file mode 100644 index 00000000..3c648869 Binary files /dev/null and b/Cunkebao/public/assets/face/大哭.png differ diff --git a/Cunkebao/public/assets/face/天啊.png b/Cunkebao/public/assets/face/天啊.png new file mode 100644 index 00000000..67d1b970 Binary files /dev/null and b/Cunkebao/public/assets/face/天啊.png differ diff --git a/Cunkebao/public/assets/face/失望.png b/Cunkebao/public/assets/face/失望.png new file mode 100644 index 00000000..d38c8888 Binary files /dev/null and b/Cunkebao/public/assets/face/失望.png differ diff --git a/Cunkebao/public/assets/face/奸笑.png b/Cunkebao/public/assets/face/奸笑.png new file mode 100644 index 00000000..895c5917 Binary files /dev/null and b/Cunkebao/public/assets/face/奸笑.png differ diff --git a/Cunkebao/public/assets/face/好的.png b/Cunkebao/public/assets/face/好的.png new file mode 100644 index 00000000..7005ce98 Binary files /dev/null and b/Cunkebao/public/assets/face/好的.png differ diff --git a/Cunkebao/public/assets/face/委屈.png b/Cunkebao/public/assets/face/委屈.png new file mode 100644 index 00000000..b6491fd9 Binary files /dev/null and b/Cunkebao/public/assets/face/委屈.png differ diff --git a/Cunkebao/public/assets/face/害羞.png b/Cunkebao/public/assets/face/害羞.png new file mode 100644 index 00000000..50ec7868 Binary files /dev/null and b/Cunkebao/public/assets/face/害羞.png differ diff --git a/Cunkebao/public/assets/face/尴尬.png b/Cunkebao/public/assets/face/尴尬.png new file mode 100644 index 00000000..6d4900e2 Binary files /dev/null and b/Cunkebao/public/assets/face/尴尬.png differ diff --git a/Cunkebao/public/assets/face/得意.png b/Cunkebao/public/assets/face/得意.png new file mode 100644 index 00000000..0bac94b0 Binary files /dev/null and b/Cunkebao/public/assets/face/得意.png differ diff --git a/Cunkebao/public/assets/face/微笑.png b/Cunkebao/public/assets/face/微笑.png new file mode 100644 index 00000000..a3195d6e Binary files /dev/null and b/Cunkebao/public/assets/face/微笑.png differ diff --git a/Cunkebao/public/assets/face/快哭了.png b/Cunkebao/public/assets/face/快哭了.png new file mode 100644 index 00000000..f0558ba1 Binary files /dev/null and b/Cunkebao/public/assets/face/快哭了.png differ diff --git a/Cunkebao/public/assets/face/恐惧.png b/Cunkebao/public/assets/face/恐惧.png new file mode 100644 index 00000000..6e935b2a Binary files /dev/null and b/Cunkebao/public/assets/face/恐惧.png differ diff --git a/Cunkebao/public/assets/face/悠闲.png b/Cunkebao/public/assets/face/悠闲.png new file mode 100644 index 00000000..dd19c444 Binary files /dev/null and b/Cunkebao/public/assets/face/悠闲.png differ diff --git a/Cunkebao/public/assets/face/惊恐.png b/Cunkebao/public/assets/face/惊恐.png new file mode 100644 index 00000000..8bfda020 Binary files /dev/null and b/Cunkebao/public/assets/face/惊恐.png differ diff --git a/Cunkebao/public/assets/face/惊讶.png b/Cunkebao/public/assets/face/惊讶.png new file mode 100644 index 00000000..33feac55 Binary files /dev/null and b/Cunkebao/public/assets/face/惊讶.png differ diff --git a/Cunkebao/public/assets/face/愉快.png b/Cunkebao/public/assets/face/愉快.png new file mode 100644 index 00000000..a78c8e69 Binary files /dev/null and b/Cunkebao/public/assets/face/愉快.png differ diff --git a/Cunkebao/public/assets/face/憨笑.png b/Cunkebao/public/assets/face/憨笑.png new file mode 100644 index 00000000..b5548942 Binary files /dev/null and b/Cunkebao/public/assets/face/憨笑.png differ diff --git a/Cunkebao/public/assets/face/打脸.png b/Cunkebao/public/assets/face/打脸.png new file mode 100644 index 00000000..d12031aa Binary files /dev/null and b/Cunkebao/public/assets/face/打脸.png differ diff --git a/Cunkebao/public/assets/face/抓狂.png b/Cunkebao/public/assets/face/抓狂.png new file mode 100644 index 00000000..b4408379 Binary files /dev/null and b/Cunkebao/public/assets/face/抓狂.png differ diff --git a/Cunkebao/public/assets/face/抠鼻.png b/Cunkebao/public/assets/face/抠鼻.png new file mode 100644 index 00000000..e44adf69 Binary files /dev/null and b/Cunkebao/public/assets/face/抠鼻.png differ diff --git a/Cunkebao/public/assets/face/捂脸.png b/Cunkebao/public/assets/face/捂脸.png new file mode 100644 index 00000000..ea8a13cd Binary files /dev/null and b/Cunkebao/public/assets/face/捂脸.png differ diff --git a/Cunkebao/public/assets/face/撇嘴.png b/Cunkebao/public/assets/face/撇嘴.png new file mode 100644 index 00000000..937ae748 Binary files /dev/null and b/Cunkebao/public/assets/face/撇嘴.png differ diff --git a/Cunkebao/public/assets/face/擦汗.png b/Cunkebao/public/assets/face/擦汗.png new file mode 100644 index 00000000..b9256ad9 Binary files /dev/null and b/Cunkebao/public/assets/face/擦汗.png differ diff --git a/Cunkebao/public/assets/face/敲打.png b/Cunkebao/public/assets/face/敲打.png new file mode 100644 index 00000000..5eb4480c Binary files /dev/null and b/Cunkebao/public/assets/face/敲打.png differ diff --git a/Cunkebao/public/assets/face/无语.png b/Cunkebao/public/assets/face/无语.png new file mode 100644 index 00000000..443f9d69 Binary files /dev/null and b/Cunkebao/public/assets/face/无语.png differ diff --git a/Cunkebao/public/assets/face/旺柴.png b/Cunkebao/public/assets/face/旺柴.png new file mode 100644 index 00000000..02000fb2 Binary files /dev/null and b/Cunkebao/public/assets/face/旺柴.png differ diff --git a/Cunkebao/public/assets/face/晕.png b/Cunkebao/public/assets/face/晕.png new file mode 100644 index 00000000..8b0a5a28 Binary files /dev/null and b/Cunkebao/public/assets/face/晕.png differ diff --git a/Cunkebao/public/assets/face/机智.png b/Cunkebao/public/assets/face/机智.png new file mode 100644 index 00000000..999d4b56 Binary files /dev/null and b/Cunkebao/public/assets/face/机智.png differ diff --git a/Cunkebao/public/assets/face/汗.png b/Cunkebao/public/assets/face/汗.png new file mode 100644 index 00000000..3b940c55 Binary files /dev/null and b/Cunkebao/public/assets/face/汗.png differ diff --git a/Cunkebao/public/assets/face/流泪.png b/Cunkebao/public/assets/face/流泪.png new file mode 100644 index 00000000..bdfe6fc7 Binary files /dev/null and b/Cunkebao/public/assets/face/流泪.png differ diff --git a/Cunkebao/public/assets/face/生病.png b/Cunkebao/public/assets/face/生病.png new file mode 100644 index 00000000..39fdd919 Binary files /dev/null and b/Cunkebao/public/assets/face/生病.png differ diff --git a/Cunkebao/public/assets/face/疑问.png b/Cunkebao/public/assets/face/疑问.png new file mode 100644 index 00000000..c2bb9c97 Binary files /dev/null and b/Cunkebao/public/assets/face/疑问.png differ diff --git a/Cunkebao/public/assets/face/白眼.png b/Cunkebao/public/assets/face/白眼.png new file mode 100644 index 00000000..fa261a4e Binary files /dev/null and b/Cunkebao/public/assets/face/白眼.png differ diff --git a/Cunkebao/public/assets/face/皱眉.png b/Cunkebao/public/assets/face/皱眉.png new file mode 100644 index 00000000..123bf081 Binary files /dev/null and b/Cunkebao/public/assets/face/皱眉.png differ diff --git a/Cunkebao/public/assets/face/睡.png b/Cunkebao/public/assets/face/睡.png new file mode 100644 index 00000000..8b378481 Binary files /dev/null and b/Cunkebao/public/assets/face/睡.png differ diff --git a/Cunkebao/public/assets/face/破涕为笑.png b/Cunkebao/public/assets/face/破涕为笑.png new file mode 100644 index 00000000..447dcb65 Binary files /dev/null and b/Cunkebao/public/assets/face/破涕为笑.png differ diff --git a/Cunkebao/public/assets/face/社会社会.png b/Cunkebao/public/assets/face/社会社会.png new file mode 100644 index 00000000..e4a311b2 Binary files /dev/null and b/Cunkebao/public/assets/face/社会社会.png differ diff --git a/Cunkebao/public/assets/face/笑脸.png b/Cunkebao/public/assets/face/笑脸.png new file mode 100644 index 00000000..e3ac78d0 Binary files /dev/null and b/Cunkebao/public/assets/face/笑脸.png differ diff --git a/Cunkebao/public/assets/face/翻白眼.png b/Cunkebao/public/assets/face/翻白眼.png new file mode 100644 index 00000000..4ebf05dc Binary files /dev/null and b/Cunkebao/public/assets/face/翻白眼.png differ diff --git a/Cunkebao/public/assets/face/耶.png b/Cunkebao/public/assets/face/耶.png new file mode 100644 index 00000000..969fd94e Binary files /dev/null and b/Cunkebao/public/assets/face/耶.png differ diff --git a/Cunkebao/public/assets/face/脸红.png b/Cunkebao/public/assets/face/脸红.png new file mode 100644 index 00000000..92ba41d1 Binary files /dev/null and b/Cunkebao/public/assets/face/脸红.png differ diff --git a/Cunkebao/public/assets/face/色.png b/Cunkebao/public/assets/face/色.png new file mode 100644 index 00000000..630ae0ec Binary files /dev/null and b/Cunkebao/public/assets/face/色.png differ diff --git a/Cunkebao/public/assets/face/苦涩.png b/Cunkebao/public/assets/face/苦涩.png new file mode 100644 index 00000000..bf0dd647 Binary files /dev/null and b/Cunkebao/public/assets/face/苦涩.png differ diff --git a/Cunkebao/public/assets/face/衰.png b/Cunkebao/public/assets/face/衰.png new file mode 100644 index 00000000..47ed4719 Binary files /dev/null and b/Cunkebao/public/assets/face/衰.png differ diff --git a/Cunkebao/public/assets/face/裂开.png b/Cunkebao/public/assets/face/裂开.png new file mode 100644 index 00000000..626d4798 Binary files /dev/null and b/Cunkebao/public/assets/face/裂开.png differ diff --git a/Cunkebao/public/assets/face/让我看看.png b/Cunkebao/public/assets/face/让我看看.png new file mode 100644 index 00000000..c3fafee6 Binary files /dev/null and b/Cunkebao/public/assets/face/让我看看.png differ diff --git a/Cunkebao/public/assets/face/调皮.png b/Cunkebao/public/assets/face/调皮.png new file mode 100644 index 00000000..5aba419c Binary files /dev/null and b/Cunkebao/public/assets/face/调皮.png differ diff --git a/Cunkebao/public/assets/face/鄙视.png b/Cunkebao/public/assets/face/鄙视.png new file mode 100644 index 00000000..3d32430e Binary files /dev/null and b/Cunkebao/public/assets/face/鄙视.png differ diff --git a/Cunkebao/public/assets/face/闭嘴.png b/Cunkebao/public/assets/face/闭嘴.png new file mode 100644 index 00000000..d89f3507 Binary files /dev/null and b/Cunkebao/public/assets/face/闭嘴.png differ diff --git a/Cunkebao/public/assets/face/阴险.png b/Cunkebao/public/assets/face/阴险.png new file mode 100644 index 00000000..d37f39c1 Binary files /dev/null and b/Cunkebao/public/assets/face/阴险.png differ diff --git a/Cunkebao/public/assets/face/难过.png b/Cunkebao/public/assets/face/难过.png new file mode 100644 index 00000000..636ae7b8 Binary files /dev/null and b/Cunkebao/public/assets/face/难过.png differ diff --git a/Cunkebao/public/assets/face/骷髅.png b/Cunkebao/public/assets/face/骷髅.png new file mode 100644 index 00000000..f8835797 Binary files /dev/null and b/Cunkebao/public/assets/face/骷髅.png differ diff --git a/Cunkebao/public/assets/face/鼓掌.png b/Cunkebao/public/assets/face/鼓掌.png new file mode 100644 index 00000000..c6963bcc Binary files /dev/null and b/Cunkebao/public/assets/face/鼓掌.png differ diff --git a/Cunkebao/public/assets/gesture/OK.png b/Cunkebao/public/assets/gesture/OK.png new file mode 100644 index 00000000..2d0f6e5f Binary files /dev/null and b/Cunkebao/public/assets/gesture/OK.png differ diff --git a/Cunkebao/public/assets/gesture/勾引.png b/Cunkebao/public/assets/gesture/勾引.png new file mode 100644 index 00000000..28e3733e Binary files /dev/null and b/Cunkebao/public/assets/gesture/勾引.png differ diff --git a/Cunkebao/public/assets/gesture/合十.png b/Cunkebao/public/assets/gesture/合十.png new file mode 100644 index 00000000..eca2b73c Binary files /dev/null and b/Cunkebao/public/assets/gesture/合十.png differ diff --git a/Cunkebao/public/assets/gesture/弱.png b/Cunkebao/public/assets/gesture/弱.png new file mode 100644 index 00000000..be8b1a8d Binary files /dev/null and b/Cunkebao/public/assets/gesture/弱.png differ diff --git a/Cunkebao/public/assets/gesture/强.png b/Cunkebao/public/assets/gesture/强.png new file mode 100644 index 00000000..f81c624b Binary files /dev/null and b/Cunkebao/public/assets/gesture/强.png differ diff --git a/Cunkebao/public/assets/gesture/抱拳.png b/Cunkebao/public/assets/gesture/抱拳.png new file mode 100644 index 00000000..51d17dbd Binary files /dev/null and b/Cunkebao/public/assets/gesture/抱拳.png differ diff --git a/Cunkebao/public/assets/gesture/拥抱.png b/Cunkebao/public/assets/gesture/拥抱.png new file mode 100644 index 00000000..0bbcdb98 Binary files /dev/null and b/Cunkebao/public/assets/gesture/拥抱.png differ diff --git a/Cunkebao/public/assets/gesture/拳头.png b/Cunkebao/public/assets/gesture/拳头.png new file mode 100644 index 00000000..91c10e02 Binary files /dev/null and b/Cunkebao/public/assets/gesture/拳头.png differ diff --git a/Cunkebao/public/assets/gesture/握手.png b/Cunkebao/public/assets/gesture/握手.png new file mode 100644 index 00000000..9e6be93c Binary files /dev/null and b/Cunkebao/public/assets/gesture/握手.png differ diff --git a/Cunkebao/public/assets/gesture/胜利.png b/Cunkebao/public/assets/gesture/胜利.png new file mode 100644 index 00000000..2a54535a Binary files /dev/null and b/Cunkebao/public/assets/gesture/胜利.png differ diff --git a/Cunkebao/public/assets/other/便便.png b/Cunkebao/public/assets/other/便便.png new file mode 100644 index 00000000..9ee508fa Binary files /dev/null and b/Cunkebao/public/assets/other/便便.png differ diff --git a/Cunkebao/public/assets/other/凋谢.png b/Cunkebao/public/assets/other/凋谢.png new file mode 100644 index 00000000..b189bb9d Binary files /dev/null and b/Cunkebao/public/assets/other/凋谢.png differ diff --git a/Cunkebao/public/assets/other/咖啡.png b/Cunkebao/public/assets/other/咖啡.png new file mode 100644 index 00000000..91b7c79a Binary files /dev/null and b/Cunkebao/public/assets/other/咖啡.png differ diff --git a/Cunkebao/public/assets/other/啤酒.png b/Cunkebao/public/assets/other/啤酒.png new file mode 100644 index 00000000..81d40ba7 Binary files /dev/null and b/Cunkebao/public/assets/other/啤酒.png differ diff --git a/Cunkebao/public/assets/other/嘴唇.png b/Cunkebao/public/assets/other/嘴唇.png new file mode 100644 index 00000000..858e8547 Binary files /dev/null and b/Cunkebao/public/assets/other/嘴唇.png differ diff --git a/Cunkebao/public/assets/other/太阳.png b/Cunkebao/public/assets/other/太阳.png new file mode 100644 index 00000000..04578c43 Binary files /dev/null and b/Cunkebao/public/assets/other/太阳.png differ diff --git a/Cunkebao/public/assets/other/心碎.png b/Cunkebao/public/assets/other/心碎.png new file mode 100644 index 00000000..dc23ec82 Binary files /dev/null and b/Cunkebao/public/assets/other/心碎.png differ diff --git a/Cunkebao/public/assets/other/月亮.png b/Cunkebao/public/assets/other/月亮.png new file mode 100644 index 00000000..20ed34ef Binary files /dev/null and b/Cunkebao/public/assets/other/月亮.png differ diff --git a/Cunkebao/public/assets/other/炸弹.png b/Cunkebao/public/assets/other/炸弹.png new file mode 100644 index 00000000..9ece24cb Binary files /dev/null and b/Cunkebao/public/assets/other/炸弹.png differ diff --git a/Cunkebao/public/assets/other/爱心.png b/Cunkebao/public/assets/other/爱心.png new file mode 100644 index 00000000..aa9b744c Binary files /dev/null and b/Cunkebao/public/assets/other/爱心.png differ diff --git a/Cunkebao/public/assets/other/玫瑰.png b/Cunkebao/public/assets/other/玫瑰.png new file mode 100644 index 00000000..83cc3b27 Binary files /dev/null and b/Cunkebao/public/assets/other/玫瑰.png differ diff --git a/Cunkebao/public/assets/other/菜刀.png b/Cunkebao/public/assets/other/菜刀.png new file mode 100644 index 00000000..77c5a137 Binary files /dev/null and b/Cunkebao/public/assets/other/菜刀.png differ diff --git a/Cunkebao/public/assets/other/蛋糕.png b/Cunkebao/public/assets/other/蛋糕.png new file mode 100644 index 00000000..9a62501c Binary files /dev/null and b/Cunkebao/public/assets/other/蛋糕.png differ diff --git a/Cunkebao/src/api/common.ts b/Cunkebao/src/api/common.ts index 77a0e7de..d6147d80 100644 --- a/Cunkebao/src/api/common.ts +++ b/Cunkebao/src/api/common.ts @@ -1,4 +1,6 @@ -import request from "./request"; +import axios from "axios"; +import { useUserStore } from "@/store/module/user"; + /** * 通用文件上传方法(支持图片、文件) * @param {File} file - 要上传的文件对象 @@ -14,14 +16,22 @@ export async function uploadFile( const formData = new FormData(); formData.append("file", file); - // 使用 request 方法上传文件,设置正确的 Content-Type - const res = await request(uploadUrl, formData, "POST", { + // 获取用户token + const { token } = useUserStore.getState(); + + const fullUrl = `${(import.meta as any).env?.VITE_API_BASE_URL || "/api"}${uploadUrl}`; + + // 直接使用 axios 上传文件 + const response = await axios.post(fullUrl, formData, { headers: { - "Content-Type": "multipart/form-data", + Authorization: token ? `Bearer ${token}` : undefined, }, + timeout: 20000, }); - return res.url; + return response?.data?.data?.url || ""; } catch (e: any) { - throw new Error(e?.message || "文件上传失败"); + const errorMessage = + e.response?.data?.message || e.message || "文件上传失败"; + throw new Error(errorMessage); } } diff --git a/Cunkebao/src/components/AccountSelection/selectionPopup.tsx b/Cunkebao/src/components/AccountSelection/selectionPopup.tsx index f6d012a5..7f4fc98a 100644 --- a/Cunkebao/src/components/AccountSelection/selectionPopup.tsx +++ b/Cunkebao/src/components/AccountSelection/selectionPopup.tsx @@ -68,6 +68,32 @@ export default function SelectionPopup({ setTempSelectedOptions(next); }; + // 全选当前页 + const handleSelectAllCurrentPage = (checked: boolean) => { + if (readonly) return; + + if (checked) { + // 全选:添加当前页面所有未选中的账号 + const currentPageAccounts = accounts.filter( + account => !tempSelectedOptions.some(a => a.id === account.id), + ); + setTempSelectedOptions(prev => [...prev, ...currentPageAccounts]); + } else { + // 取消全选:移除当前页面的所有账号 + const currentPageAccountIds = accounts.map(a => a.id); + setTempSelectedOptions(prev => + prev.filter(a => !currentPageAccountIds.includes(a.id)), + ); + } + }; + + // 检查当前页是否全选 + const isCurrentPageAllSelected = + accounts.length > 0 && + accounts.every(account => + tempSelectedOptions.some(a => a.id === account.id), + ); + const handleConfirm = () => { if (onConfirm) { onConfirm(tempSelectedOptions); @@ -103,7 +129,7 @@ export default function SelectionPopup({ // 页码变化 useEffect(() => { - if (!visible || currentPage === 1) return; + if (!visible) return; fetchAccounts(currentPage, searchQuery); }, [currentPage, visible, searchQuery]); @@ -132,7 +158,6 @@ export default function SelectionPopup({ } footer={ onVisibleChange(false)} onConfirm={handleConfirm} + isAllSelected={isCurrentPageAllSelected} + onSelectAll={handleSelectAllCurrentPage} /> } > diff --git a/Cunkebao/src/components/ContentSelection/selectionPopup.tsx b/Cunkebao/src/components/ContentSelection/selectionPopup.tsx index 8adbf73c..e5ee7a31 100644 --- a/Cunkebao/src/components/ContentSelection/selectionPopup.tsx +++ b/Cunkebao/src/components/ContentSelection/selectionPopup.tsx @@ -137,6 +137,30 @@ const SelectionPopup: React.FC = ({ setTempSelectedOptions(newSelected); }; + // 全选当前页 + const handleSelectAllCurrentPage = (checked: boolean) => { + if (checked) { + // 全选:添加当前页面所有未选中的内容库 + const currentPageLibraries = libraries.filter( + library => !tempSelectedOptions.some(l => l.id === library.id), + ); + setTempSelectedOptions(prev => [...prev, ...currentPageLibraries]); + } else { + // 取消全选:移除当前页面的所有内容库 + const currentPageLibraryIds = libraries.map(l => l.id); + setTempSelectedOptions(prev => + prev.filter(l => !currentPageLibraryIds.includes(l.id)), + ); + } + }; + + // 检查当前页是否全选 + const isCurrentPageAllSelected = + libraries.length > 0 && + libraries.every(library => + tempSelectedOptions.some(l => l.id === library.id), + ); + // 确认选择 const handleConfirm = () => { // 用户点击确认时,才更新实际的selectedOptions @@ -204,7 +228,6 @@ const SelectionPopup: React.FC = ({ } footer={ = ({ onPageChange={handlePageChange} onCancel={onClose} onConfirm={handleConfirm} + isAllSelected={isCurrentPageAllSelected} + onSelectAll={handleSelectAllCurrentPage} /> } > diff --git a/Cunkebao/src/components/DeviceSelection/selectionPopup.tsx b/Cunkebao/src/components/DeviceSelection/selectionPopup.tsx index 32a75e07..7a839f70 100644 --- a/Cunkebao/src/components/DeviceSelection/selectionPopup.tsx +++ b/Cunkebao/src/components/DeviceSelection/selectionPopup.tsx @@ -120,6 +120,30 @@ const SelectionPopup: React.FC = ({ } }; + // 全选当前页 + const handleSelectAllCurrentPage = (checked: boolean) => { + if (checked) { + // 全选:添加当前页面所有未选中的设备 + const currentPageDevices = filteredDevices.filter( + device => !tempSelectedOptions.some(d => d.id === device.id), + ); + setTempSelectedOptions(prev => [...prev, ...currentPageDevices]); + } else { + // 取消全选:移除当前页面的所有设备 + const currentPageDeviceIds = filteredDevices.map(d => d.id); + setTempSelectedOptions(prev => + prev.filter(d => !currentPageDeviceIds.includes(d.id)), + ); + } + }; + + // 检查当前页是否全选 + const isCurrentPageAllSelected = + filteredDevices.length > 0 && + filteredDevices.every(device => + tempSelectedOptions.some(d => d.id === device.id), + ); + return ( = ({ } footer={ = ({ onSelect(tempSelectedOptions); onClose(); }} + isAllSelected={isCurrentPageAllSelected} + onSelectAll={handleSelectAllCurrentPage} /> } > diff --git a/Cunkebao/src/components/EmojiSeclection/EmojiPicker.css b/Cunkebao/src/components/EmojiSeclection/EmojiPicker.css new file mode 100644 index 00000000..cd70ffe3 --- /dev/null +++ b/Cunkebao/src/components/EmojiSeclection/EmojiPicker.css @@ -0,0 +1,167 @@ +/* 表情选择器容器 */ +.emoji-picker-container { + position: relative; + display: inline-block; +} + +/* 默认触发器按钮 */ +.emoji-picker-trigger { + background: none; + font-size: 16px; + padding: 5px; + cursor: pointer; + transition: all 0.2s ease; + border-radius: 5px; +} + +.emoji-picker-trigger:hover { + background-color: #e9e9e9; + border-color: #d0d0d0; +} + +/* 表情选择器面板 */ +.emoji-picker-panel { + position: absolute; + bottom: 100%; + left: 0; + z-index: 1000; + background: white; + border: 1px solid #e0e0e0; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + width: 320px; + max-height: 400px; + overflow: hidden; + margin-bottom: 4px; +} + +/* 分类标签栏 */ +.emoji-categories { + display: flex; + background-color: #f8f9fa; + border-bottom: 1px solid #e0e0e0; + padding: 8px; + gap: 4px; +} + +.category-btn { + background: none; + border: none; + padding: 8px 12px; + border-radius: 6px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.2s ease; + flex: 1; + text-align: center; +} + +.category-btn:hover { + background-color: #e9ecef; +} + +.category-btn.active { + background-color: #007bff; + color: white; +} + +/* 表情网格 */ +.emoji-grid { + display: grid; + grid-template-columns: repeat(8, 1fr); + gap: 4px; + padding: 12px; + max-height: 280px; + overflow-y: auto; +} + +/* 表情项 */ +.emoji-item { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.emoji-item:hover { + background-color: #f0f0f0; +} + +.emoji-image { + width: 24px; + height: 24px; + object-fit: contain; +} + +/* 空状态 */ +.emoji-empty { + text-align: center; + padding: 40px 20px; + color: #999; + font-size: 14px; +} + +/* 滚动条样式 */ +.emoji-grid::-webkit-scrollbar { + width: 6px; +} + +.emoji-grid::-webkit-scrollbar-track { + background: #f1f1f1; + border-radius: 3px; +} + +.emoji-grid::-webkit-scrollbar-thumb { + background: #c1c1c1; + border-radius: 3px; +} + +.emoji-grid::-webkit-scrollbar-thumb:hover { + background: #a8a8a8; +} + +/* 响应式设计 */ +@media (max-width: 480px) { + .emoji-picker-panel { + width: 280px; + } + + .emoji-grid { + grid-template-columns: repeat(7, 1fr); + } +} + +/* 深色模式支持 */ +@media (prefers-color-scheme: dark) { + .emoji-picker-panel { + background: #2d3748; + border-color: #4a5568; + color: white; + } + + .emoji-categories { + background-color: #1a202c; + border-bottom-color: #4a5568; + } + + .category-btn:hover { + background-color: #4a5568; + } + + .emoji-item:hover { + background-color: #4a5568; + } + + .emoji-picker-trigger { + border-color: #4a5568; + color: white; + } + + .emoji-picker-trigger:hover { + background-color: #4a5568; + } +} diff --git a/Cunkebao/src/components/EmojiSeclection/EmojiPicker.tsx b/Cunkebao/src/components/EmojiSeclection/EmojiPicker.tsx new file mode 100644 index 00000000..6b5f4932 --- /dev/null +++ b/Cunkebao/src/components/EmojiSeclection/EmojiPicker.tsx @@ -0,0 +1,115 @@ +import React, { useState, useRef, useEffect } from "react"; +import { EmojiCategory, EmojiInfo, getEmojisByCategory } from "./wechatEmoji"; +import "./EmojiPicker.css"; + +interface EmojiPickerProps { + onEmojiSelect: (emoji: EmojiInfo) => void; + trigger?: React.ReactNode; + className?: string; +} + +const EmojiPicker: React.FC = ({ + onEmojiSelect, + trigger, + className = "", +}) => { + const [isOpen, setIsOpen] = useState(false); + const [activeCategory, setActiveCategory] = useState( + EmojiCategory.FACE, + ); + const pickerRef = useRef(null); + + // 分类配置 + const categories = [ + { key: EmojiCategory.FACE, label: "😊", title: "人脸" }, + { key: EmojiCategory.GESTURE, label: "👋", title: "手势" }, + { key: EmojiCategory.ANIMAL, label: "🐷", title: "动物" }, + { key: EmojiCategory.BLESSING, label: "🎉", title: "祝福" }, + { key: EmojiCategory.OTHER, label: "❤️", title: "其他" }, + ]; + + // 获取当前分类的表情 + const currentEmojis = getEmojisByCategory(activeCategory); + + // 点击外部关闭 + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + pickerRef.current && + !pickerRef.current.contains(event.target as Node) + ) { + setIsOpen(false); + } + }; + + if (isOpen) { + document.addEventListener("mousedown", handleClickOutside); + } + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [isOpen]); + + // 处理表情选择 + const handleEmojiClick = (emoji: EmojiInfo) => { + onEmojiSelect(emoji); + setIsOpen(false); + }; + + // 默认触发器 + const defaultTrigger = 😊; + + return ( +
+ {/* 触发器 */} +
setIsOpen(!isOpen)}>{trigger || defaultTrigger}
+ + {/* 表情选择器面板 */} + {isOpen && ( +
+ {/* 分类标签 */} +
+ {categories.map(category => ( + + ))} +
+ + {/* 表情网格 */} +
+ {currentEmojis.map(emoji => ( +
handleEmojiClick(emoji)} + title={emoji.name} + > + {emoji.name} +
+ ))} +
+ + {/* 空状态 */} + {currentEmojis.length === 0 && ( +
暂无表情
+ )} +
+ )} +
+ ); +}; + +export default EmojiPicker; diff --git a/Cunkebao/src/components/EmojiSeclection/index.ts b/Cunkebao/src/components/EmojiSeclection/index.ts new file mode 100644 index 00000000..d4aa499f --- /dev/null +++ b/Cunkebao/src/components/EmojiSeclection/index.ts @@ -0,0 +1,18 @@ +// 导出主要组件 +export { default as EmojiPicker } from "./EmojiPicker"; + +// 导出表情数据和类型 +export { + EmojiCategory, + type EmojiInfo, + type EmojiName, + getAllEmojis, + getEmojisByCategory, + getEmojiInfo, + getEmojiPath, + searchEmojis, + EMOJI_CATEGORIES, +} from "./wechatEmoji"; + +// 默认导出 +export { default } from "./EmojiPicker"; diff --git a/Cunkebao/src/components/EmojiSeclection/wechatEmoji.ts b/Cunkebao/src/components/EmojiSeclection/wechatEmoji.ts new file mode 100644 index 00000000..5e2f3807 --- /dev/null +++ b/Cunkebao/src/components/EmojiSeclection/wechatEmoji.ts @@ -0,0 +1,858 @@ +/** + * 微信表情包 TypeScript 模块 + * 提供类型安全的表情访问和图片路径获取功能 + */ + +/** + * 表情类别枚举 + */ +export enum EmojiCategory { + /** 人脸表情 */ + FACE = "face", + /** 手势表情 */ + GESTURE = "gesture", + /** 动物表情 */ + ANIMAL = "animal", + /** 祝福表情 */ + BLESSING = "blessing", + /** 其他表情 */ + OTHER = "other", +} + +/** + * 表情信息接口 + */ +export interface EmojiInfo { + /** 表情名称 */ + name: string; + /** 表情类别 */ + category: EmojiCategory; + /** 图片文件路径 */ + path: string; + /** 英文名称(可选) */ + englishName?: string; +} + +/** + * 表情名称类型 + */ +export type EmojiName = + // 人脸表情 + | "微笑" + | "撇嘴" + | "色" + | "发呆" + | "得意" + | "流泪" + | "害羞" + | "闭嘴" + | "睡" + | "大哭" + | "尴尬" + | "发怒" + | "调皮" + | "呲牙" + | "惊讶" + | "难过" + | "囧" + | "抓狂" + | "吐" + | "偷笑" + | "愉快" + | "白眼" + | "傲慢" + | "困" + | "惊恐" + | "憨笑" + | "悠闲" + | "咒骂" + | "疑问" + | "嘘" + | "晕" + | "衰" + | "骷髅" + | "敲打" + | "再见" + | "擦汗" + | "抠鼻" + | "鼓掌" + | "坏笑" + | "右哼哼" + | "鄙视" + | "委屈" + | "快哭了" + | "阴险" + | "亲亲" + | "可怜" + | "笑脸" + | "生病" + | "脸红" + | "破涕为笑" + | "恐惧" + | "失望" + | "无语" + | "嘿哈" + | "捂脸" + | "机智" + | "皱眉" + | "耶" + | "吃瓜" + | "加油" + | "汗" + | "天啊" + | "Emm" + | "社会社会" + | "旺柴" + | "好的" + | "打脸" + | "哇" + | "翻白眼" + | "666" + | "让我看看" + | "叹气" + | "苦涩" + | "裂开" + | "奸笑" + // 手势表情 + | "握手" + | "胜利" + | "抱拳" + | "勾引" + | "拳头" + | "OK" + | "合十" + | "强" + | "拥抱" + | "弱" + // 动物表情 + | "猪头" + | "跳跳" + | "发抖" + | "转圈" + // 祝福表情 + | "庆祝" + | "礼物" + | "红包" + | "發" + | "福" + | "烟花" + | "爆竹" + // 其他表情 + | "嘴唇" + | "爱心" + | "心碎" + | "啤酒" + | "咖啡" + | "蛋糕" + | "凋谢" + | "菜刀" + | "炸弹" + | "便便" + | "太阳" + | "月亮" + | "玫瑰"; + +/** + * 表情数据映射 + * 将表情名称映射到完整的表情信息 + */ +const EMOJI_DATA: Record = { + // 人脸表情 + 微笑: { + name: "微笑", + category: EmojiCategory.FACE, + path: "/assets/face/微笑.png", + }, + 撇嘴: { + name: "撇嘴", + category: EmojiCategory.FACE, + path: "/assets/face/撇嘴.png", + }, + 色: { name: "色", category: EmojiCategory.FACE, path: "/assets/face/色.png" }, + 发呆: { + name: "发呆", + category: EmojiCategory.FACE, + path: "/assets/face/发呆.png", + }, + 得意: { + name: "得意", + category: EmojiCategory.FACE, + path: "/assets/face/得意.png", + }, + 流泪: { + name: "流泪", + category: EmojiCategory.FACE, + path: "/assets/face/流泪.png", + }, + 害羞: { + name: "害羞", + category: EmojiCategory.FACE, + path: "/assets/face/害羞.png", + }, + 闭嘴: { + name: "闭嘴", + category: EmojiCategory.FACE, + path: "/assets/face/闭嘴.png", + }, + 睡: { name: "睡", category: EmojiCategory.FACE, path: "/assets/face/睡.png" }, + 大哭: { + name: "大哭", + category: EmojiCategory.FACE, + path: "/assets/face/大哭.png", + }, + 尴尬: { + name: "尴尬", + category: EmojiCategory.FACE, + path: "/assets/face/尴尬.png", + }, + 发怒: { + name: "发怒", + category: EmojiCategory.FACE, + path: "/assets/face/发怒.png", + }, + 调皮: { + name: "调皮", + category: EmojiCategory.FACE, + path: "/assets/face/调皮.png", + }, + 呲牙: { + name: "呲牙", + category: EmojiCategory.FACE, + path: "/assets/face/呲牙.png", + }, + 惊讶: { + name: "惊讶", + category: EmojiCategory.FACE, + path: "/assets/face/惊讶.png", + }, + 难过: { + name: "难过", + category: EmojiCategory.FACE, + path: "/assets/face/难过.png", + }, + 囧: { name: "囧", category: EmojiCategory.FACE, path: "/assets/face/囧.png" }, + 抓狂: { + name: "抓狂", + category: EmojiCategory.FACE, + path: "/assets/face/抓狂.png", + }, + 吐: { name: "吐", category: EmojiCategory.FACE, path: "/assets/face/吐.png" }, + 偷笑: { + name: "偷笑", + category: EmojiCategory.FACE, + path: "/assets/face/偷笑.png", + }, + 愉快: { + name: "愉快", + category: EmojiCategory.FACE, + path: "/assets/face/愉快.png", + }, + 白眼: { + name: "白眼", + category: EmojiCategory.FACE, + path: "/assets/face/白眼.png", + }, + 傲慢: { + name: "傲慢", + category: EmojiCategory.FACE, + path: "/assets/face/傲慢.png", + }, + 困: { name: "困", category: EmojiCategory.FACE, path: "/assets/face/困.png" }, + 惊恐: { + name: "惊恐", + category: EmojiCategory.FACE, + path: "/assets/face/惊恐.png", + }, + 憨笑: { + name: "憨笑", + category: EmojiCategory.FACE, + path: "/assets/face/憨笑.png", + }, + 悠闲: { + name: "悠闲", + category: EmojiCategory.FACE, + path: "/assets/face/悠闲.png", + }, + 咒骂: { + name: "咒骂", + category: EmojiCategory.FACE, + path: "/assets/face/咒骂.png", + }, + 疑问: { + name: "疑问", + category: EmojiCategory.FACE, + path: "/assets/face/疑问.png", + }, + 嘘: { name: "嘘", category: EmojiCategory.FACE, path: "/assets/face/嘘.png" }, + 晕: { name: "晕", category: EmojiCategory.FACE, path: "/assets/face/晕.png" }, + 衰: { name: "衰", category: EmojiCategory.FACE, path: "/assets/face/衰.png" }, + 骷髅: { + name: "骷髅", + category: EmojiCategory.FACE, + path: "/assets/face/骷髅.png", + }, + 敲打: { + name: "敲打", + category: EmojiCategory.FACE, + path: "/assets/face/敲打.png", + }, + 再见: { + name: "再见", + category: EmojiCategory.FACE, + path: "/assets/face/再见.png", + }, + 擦汗: { + name: "擦汗", + category: EmojiCategory.FACE, + path: "/assets/face/擦汗.png", + }, + 抠鼻: { + name: "抠鼻", + category: EmojiCategory.FACE, + path: "/assets/face/抠鼻.png", + }, + 鼓掌: { + name: "鼓掌", + category: EmojiCategory.FACE, + path: "/assets/face/鼓掌.png", + }, + 坏笑: { + name: "坏笑", + category: EmojiCategory.FACE, + path: "/assets/face/坏笑.png", + }, + 右哼哼: { + name: "右哼哼", + category: EmojiCategory.FACE, + path: "/assets/face/右哼哼.png", + }, + 鄙视: { + name: "鄙视", + category: EmojiCategory.FACE, + path: "/assets/face/鄙视.png", + }, + 委屈: { + name: "委屈", + category: EmojiCategory.FACE, + path: "/assets/face/委屈.png", + }, + 快哭了: { + name: "快哭了", + category: EmojiCategory.FACE, + path: "/assets/face/快哭了.png", + }, + 阴险: { + name: "阴险", + category: EmojiCategory.FACE, + path: "/assets/face/阴险.png", + }, + 亲亲: { + name: "亲亲", + category: EmojiCategory.FACE, + path: "/assets/face/亲亲.png", + }, + 可怜: { + name: "可怜", + category: EmojiCategory.FACE, + path: "/assets/face/可怜.png", + }, + 笑脸: { + name: "笑脸", + category: EmojiCategory.FACE, + path: "/assets/face/笑脸.png", + }, + 生病: { + name: "生病", + category: EmojiCategory.FACE, + path: "/assets/face/生病.png", + }, + 脸红: { + name: "脸红", + category: EmojiCategory.FACE, + path: "/assets/face/脸红.png", + }, + 破涕为笑: { + name: "破涕为笑", + category: EmojiCategory.FACE, + path: "/assets/face/破涕为笑.png", + }, + 恐惧: { + name: "恐惧", + category: EmojiCategory.FACE, + path: "/assets/face/恐惧.png", + }, + 失望: { + name: "失望", + category: EmojiCategory.FACE, + path: "/assets/face/失望.png", + }, + 无语: { + name: "无语", + category: EmojiCategory.FACE, + path: "/assets/face/无语.png", + }, + 嘿哈: { + name: "嘿哈", + category: EmojiCategory.FACE, + path: "/assets/face/嘿哈.png", + }, + 捂脸: { + name: "捂脸", + category: EmojiCategory.FACE, + path: "/assets/face/捂脸.png", + }, + 机智: { + name: "机智", + category: EmojiCategory.FACE, + path: "/assets/face/机智.png", + }, + 皱眉: { + name: "皱眉", + category: EmojiCategory.FACE, + path: "/assets/face/皱眉.png", + }, + 耶: { name: "耶", category: EmojiCategory.FACE, path: "/assets/face/耶.png" }, + 吃瓜: { + name: "吃瓜", + category: EmojiCategory.FACE, + path: "/assets/face/吃瓜.png", + }, + 加油: { + name: "加油", + category: EmojiCategory.FACE, + path: "/assets/face/加油.png", + }, + + 汗: { name: "汗", category: EmojiCategory.FACE, path: "/assets/face/汗.png" }, + 天啊: { + name: "天啊", + category: EmojiCategory.FACE, + path: "/assets/face/天啊.png", + }, + Emm: { + name: "Emm", + category: EmojiCategory.FACE, + path: "/assets/face/Emm.png", + }, + 社会社会: { + name: "社会社会", + category: EmojiCategory.FACE, + path: "/assets/face/社会社会.png", + }, + 旺柴: { + name: "旺柴", + category: EmojiCategory.FACE, + path: "/assets/face/旺柴.png", + }, + 好的: { + name: "好的", + category: EmojiCategory.FACE, + path: "/assets/face/好的.png", + }, + 打脸: { + name: "打脸", + category: EmojiCategory.FACE, + path: "/assets/face/打脸.png", + }, + 哇: { name: "哇", category: EmojiCategory.FACE, path: "/assets/face/哇.png" }, + 翻白眼: { + name: "翻白眼", + category: EmojiCategory.FACE, + path: "/assets/face/翻白眼.png", + }, + "666": { + name: "666", + category: EmojiCategory.FACE, + path: "/assets/face/666.png", + }, + 让我看看: { + name: "让我看看", + category: EmojiCategory.FACE, + path: "/assets/face/让我看看.png", + }, + 叹气: { + name: "叹气", + category: EmojiCategory.FACE, + path: "/assets/face/叹气.png", + }, + 苦涩: { + name: "苦涩", + category: EmojiCategory.FACE, + path: "/assets/face/苦涩.png", + }, + 裂开: { + name: "裂开", + category: EmojiCategory.FACE, + path: "/assets/face/裂开.png", + }, + 奸笑: { + name: "奸笑", + category: EmojiCategory.FACE, + path: "/assets/face/奸笑.png", + }, + + // 手势表情 + 握手: { + name: "握手", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/握手.png", + }, + 胜利: { + name: "胜利", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/胜利.png", + }, + 抱拳: { + name: "抱拳", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/抱拳.png", + }, + 勾引: { + name: "勾引", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/勾引.png", + }, + 拳头: { + name: "拳头", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/拳头.png", + }, + OK: { + name: "OK", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/OK.png", + }, + 合十: { + name: "合十", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/合十.png", + }, + 强: { + name: "强", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/强.png", + }, + 拥抱: { + name: "拥抱", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/拥抱.png", + }, + 弱: { + name: "弱", + category: EmojiCategory.GESTURE, + path: "/assets/gesture/弱.png", + }, + + // 动物表情 + 猪头: { + name: "猪头", + category: EmojiCategory.ANIMAL, + path: "/assets/animal/猪头.png", + }, + 跳跳: { + name: "跳跳", + category: EmojiCategory.ANIMAL, + path: "/assets/animal/跳跳.png", + }, + 发抖: { + name: "发抖", + category: EmojiCategory.ANIMAL, + path: "/assets/animal/发抖.png", + }, + 转圈: { + name: "转圈", + category: EmojiCategory.ANIMAL, + path: "/assets/animal/转圈.png", + }, + + // 祝福表情 + 庆祝: { + name: "庆祝", + category: EmojiCategory.BLESSING, + path: "/assets/blessing/庆祝.png", + }, + 礼物: { + name: "礼物", + category: EmojiCategory.BLESSING, + path: "/assets/blessing/礼物.png", + }, + 红包: { + name: "红包", + category: EmojiCategory.BLESSING, + path: "/assets/blessing/红包.png", + }, + 發: { + name: "發", + category: EmojiCategory.BLESSING, + path: "/assets/blessing/發.png", + }, + 福: { + name: "福", + category: EmojiCategory.BLESSING, + path: "/assets/blessing/福.png", + }, + 烟花: { + name: "烟花", + category: EmojiCategory.BLESSING, + path: "/assets/blessing/烟花.png", + }, + 爆竹: { + name: "爆竹", + category: EmojiCategory.BLESSING, + path: "/assets/blessing/爆竹.png", + }, + + // 其他表情 + 嘴唇: { + name: "嘴唇", + category: EmojiCategory.OTHER, + path: "/assets/other/嘴唇.png", + }, + 爱心: { + name: "爱心", + category: EmojiCategory.OTHER, + path: "/assets/other/爱心.png", + }, + 心碎: { + name: "心碎", + category: EmojiCategory.OTHER, + path: "/assets/other/心碎.png", + }, + 啤酒: { + name: "啤酒", + category: EmojiCategory.OTHER, + path: "/assets/other/啤酒.png", + }, + 咖啡: { + name: "咖啡", + category: EmojiCategory.OTHER, + path: "/assets/other/咖啡.png", + }, + 蛋糕: { + name: "蛋糕", + category: EmojiCategory.OTHER, + path: "/assets/other/蛋糕.png", + }, + 凋谢: { + name: "凋谢", + category: EmojiCategory.OTHER, + path: "/assets/other/凋谢.png", + }, + 菜刀: { + name: "菜刀", + category: EmojiCategory.OTHER, + path: "/assets/other/菜刀.png", + }, + 炸弹: { + name: "炸弹", + category: EmojiCategory.OTHER, + path: "/assets/other/炸弹.png", + }, + 便便: { + name: "便便", + category: EmojiCategory.OTHER, + path: "/assets/other/便便.png", + }, + 太阳: { + name: "太阳", + category: EmojiCategory.OTHER, + path: "/assets/other/太阳.png", + }, + 月亮: { + name: "月亮", + category: EmojiCategory.OTHER, + path: "/assets/other/月亮.png", + }, + 玫瑰: { + name: "玫瑰", + category: EmojiCategory.OTHER, + path: "/assets/other/玫瑰.png", + }, +}; + +/** + * 获取所有表情数据的辅助函数 + */ +function getAllEmojiData(): EmojiInfo[] { + const result: EmojiInfo[] = []; + for (const key in EMOJI_DATA) { + if (Object.prototype.hasOwnProperty.call(EMOJI_DATA, key)) { + result.push(EMOJI_DATA[key as EmojiName]); + } + } + return result; +} + +/** + * 按类别分组的表情数据 + */ +export const EMOJI_CATEGORIES = { + [EmojiCategory.FACE]: getAllEmojiData().filter( + emoji => emoji.category === EmojiCategory.FACE, + ), + [EmojiCategory.GESTURE]: getAllEmojiData().filter( + emoji => emoji.category === EmojiCategory.GESTURE, + ), + [EmojiCategory.ANIMAL]: getAllEmojiData().filter( + emoji => emoji.category === EmojiCategory.ANIMAL, + ), + [EmojiCategory.BLESSING]: getAllEmojiData().filter( + emoji => emoji.category === EmojiCategory.BLESSING, + ), + [EmojiCategory.OTHER]: getAllEmojiData().filter( + emoji => emoji.category === EmojiCategory.OTHER, + ), +} as const; + +/** + * 获取表情图片路径 + * @param name 表情名称 + * @returns 图片路径,如果表情不存在则返回 null + * + * @example + * ```typescript + * const path = getEmojiPath('微笑'); // 'assets/face/微笑.png' + * const invalidPath = getEmojiPath('不存在'); // null + * ``` + */ +export function getEmojiPath(name: EmojiName): string | null { + const emoji = EMOJI_DATA[name]; + return emoji ? emoji.path : null; +} + +/** + * 获取表情信息 + * @param name 表情名称 + * @returns 表情信息对象,如果表情不存在则返回 null + * + * @example + * ```typescript + * const emoji = getEmojiInfo('微笑'); + * // { name: '微笑', category: EmojiCategory.FACE, path: 'assets/face/微笑.png' } + * ``` + */ +export function getEmojiInfo(name: EmojiName): EmojiInfo | null { + return EMOJI_DATA[name] || null; +} + +/** + * 根据类别获取表情列表 + * @param category 表情类别 + * @returns 该类别下的所有表情信息 + * + * @example + * ```typescript + * const faceEmojis = getEmojisByCategory(EmojiCategory.FACE); + * ``` + */ +export function getEmojisByCategory(category: EmojiCategory): EmojiInfo[] { + return EMOJI_CATEGORIES[category]; +} + +/** + * 获取所有表情信息 + * @returns 所有表情的信息数组 + * + * @example + * ```typescript + * const allEmojis = getAllEmojis(); + * console.log(`总共有 ${allEmojis.length} 个表情`); + * ``` + */ +export function getAllEmojis(): EmojiInfo[] { + return getAllEmojiData(); +} + +/** + * 搜索表情 + * @param keyword 搜索关键词 + * @returns 匹配的表情信息数组 + * + * @example + * ```typescript + * const results = searchEmojis('笑'); + * // 返回包含 '微笑', '偷笑', '坏笑' 等的表情 + * ``` + */ +export function searchEmojis(keyword: string): EmojiInfo[] { + return getAllEmojiData().filter(emoji => emoji.name.indexOf(keyword) !== -1); +} + +/** + * 检查表情是否存在 + * @param name 表情名称 + * @returns 是否存在该表情 + * + * @example + * ```typescript + * const exists = hasEmoji('微笑'); // true + * const notExists = hasEmoji('不存在的表情'); // false + * ``` + */ +export function hasEmoji(name: EmojiName): boolean { + return name in EMOJI_DATA; +} + +/** + * 获取表情名称列表 + * @param category 可选的类别筛选 + * @returns 表情名称数组 + * + * @example + * ```typescript + * const allNames = getEmojiNames(); + * const faceNames = getEmojiNames(EmojiCategory.FACE); + * ``` + */ +export function getEmojiNames(category?: EmojiCategory): string[] { + if (category) { + return getEmojisByCategory(category).map(emoji => emoji.name); + } + const names: string[] = []; + for (const key in EMOJI_DATA) { + if (Object.prototype.hasOwnProperty.call(EMOJI_DATA, key)) { + names.push(key); + } + } + return names; +} + +/** + * 随机获取表情 + * @param category 可选的类别筛选 + * @returns 随机表情信息 + * + * @example + * ```typescript + * const randomEmoji = getRandomEmoji(); + * const randomFaceEmoji = getRandomEmoji(EmojiCategory.FACE); + * ``` + */ +export function getRandomEmoji(category?: EmojiCategory): EmojiInfo { + const emojis = category ? getEmojisByCategory(category) : getAllEmojis(); + const randomIndex = Math.floor(Math.random() * emojis.length); + return emojis[randomIndex]; +} + +/** + * 默认导出对象,包含所有主要功能 + */ +const WeChatEmojis = { + // 枚举和类型 + EmojiCategory, + + // 数据 + EMOJI_CATEGORIES, + + // 工具函数 + getEmojiPath, + getEmojiInfo, + getEmojisByCategory, + getAllEmojis, + searchEmojis, + hasEmoji, + getEmojiNames, + getRandomEmoji, +} as const; + +export default WeChatEmojis; diff --git a/Cunkebao/src/components/FriendSelection/selectionPopup.tsx b/Cunkebao/src/components/FriendSelection/selectionPopup.tsx index eaa38692..71020104 100644 --- a/Cunkebao/src/components/FriendSelection/selectionPopup.tsx +++ b/Cunkebao/src/components/FriendSelection/selectionPopup.tsx @@ -85,6 +85,30 @@ const SelectionPopup: React.FC = ({ setTempSelectedOptions(newSelectedFriends); }; + // 全选当前页 + const handleSelectAllCurrentPage = (checked: boolean) => { + if (readonly) return; + + if (checked) { + // 全选:添加当前页面所有未选中的好友 + const currentPageFriends = friends.filter( + friend => !tempSelectedOptions.some(f => f.id === friend.id), + ); + setTempSelectedOptions(prev => [...prev, ...currentPageFriends]); + } else { + // 取消全选:移除当前页面的所有好友 + const currentPageFriendIds = friends.map(f => f.id); + setTempSelectedOptions(prev => + prev.filter(f => !currentPageFriendIds.includes(f.id)), + ); + } + }; + + // 检查当前页是否全选 + const isCurrentPageAllSelected = + friends.length > 0 && + friends.every(friend => tempSelectedOptions.some(f => f.id === friend.id)); + // 确认选择 const handleConfirm = () => { if (onConfirm) { @@ -123,7 +147,7 @@ const SelectionPopup: React.FC = ({ // 页码变化时请求数据(只在弹窗打开且页码不是1时执行) useEffect(() => { - if (!visible || currentPage === 1) return; // 弹窗关闭或第一页时不请求 + if (!visible) return; // 弹窗关闭或第一页时不请求 fetchFriends(currentPage, searchQuery); }, [currentPage, visible, searchQuery]); @@ -147,7 +171,6 @@ const SelectionPopup: React.FC = ({ } footer={ = ({ onPageChange={setCurrentPage} onCancel={() => onVisibleChange(false)} onConfirm={handleConfirm} + isAllSelected={isCurrentPageAllSelected} + onSelectAll={handleSelectAllCurrentPage} /> } > diff --git a/Cunkebao/src/components/GroupSelection/selectionPopup.tsx b/Cunkebao/src/components/GroupSelection/selectionPopup.tsx index c7237b17..dd5c9927 100644 --- a/Cunkebao/src/components/GroupSelection/selectionPopup.tsx +++ b/Cunkebao/src/components/GroupSelection/selectionPopup.tsx @@ -88,6 +88,30 @@ export default function SelectionPopup({ setTempSelectedOptions(newSelectedGroups); }; + // 全选当前页 + const handleSelectAllCurrentPage = (checked: boolean) => { + if (readonly) return; + + if (checked) { + // 全选:添加当前页面所有未选中的群组 + const currentPageGroups = groups.filter( + group => !tempSelectedOptions.some(g => g.id === group.id), + ); + setTempSelectedOptions(prev => [...prev, ...currentPageGroups]); + } else { + // 取消全选:移除当前页面的所有群组 + const currentPageGroupIds = groups.map(g => g.id); + setTempSelectedOptions(prev => + prev.filter(g => !currentPageGroupIds.includes(g.id)), + ); + } + }; + + // 检查当前页是否全选 + const isCurrentPageAllSelected = + groups.length > 0 && + groups.every(group => tempSelectedOptions.some(g => g.id === group.id)); + // 确认选择 const handleConfirm = () => { // 用户点击确认时,才更新实际的selectedOptions @@ -135,7 +159,7 @@ export default function SelectionPopup({ // 页码变化时请求数据(只在弹窗打开且页码不是1时执行) useEffect(() => { - if (!visible || currentPage === 1) return; + if (!visible) return; fetchGroups(currentPage, searchQuery); }, [currentPage, visible, searchQuery]); @@ -159,7 +183,6 @@ export default function SelectionPopup({ } footer={ onVisibleChange(false)} onConfirm={handleConfirm} + isAllSelected={isCurrentPageAllSelected} + onSelectAll={handleSelectAllCurrentPage} /> } > diff --git a/Cunkebao/src/components/MemberSelection/TwoColumnMemberSelection.module.scss b/Cunkebao/src/components/MemberSelection/TwoColumnMemberSelection.module.scss new file mode 100644 index 00000000..0ff3cbe4 --- /dev/null +++ b/Cunkebao/src/components/MemberSelection/TwoColumnMemberSelection.module.scss @@ -0,0 +1,154 @@ +.twoColumnModal { + .ant-modal-body { + padding: 0; + } +} + +.container { + display: flex; + height: 500px; + border: 1px solid #e8e8e8; +} + +.leftColumn { + flex: 1; + border-right: 1px solid #e8e8e8; + display: flex; + flex-direction: column; +} + +.rightColumn { + width: 300px; + display: flex; + flex-direction: column; + background: #fafafa; +} + +.searchWrapper { + padding: 16px; + border-bottom: 1px solid #e8e8e8; + + .ant-input { + border-radius: 6px; + } +} + +.memberList { + flex: 1; + overflow-y: auto; + padding: 8px 0; +} + +.memberItem { + display: flex; + align-items: center; + padding: 12px 16px; + cursor: pointer; + transition: background-color 0.2s; + + &:hover { + background-color: #f5f5f5; + } + + &.selected { + background-color: #e6f7ff; + } + + .ant-checkbox { + margin-right: 12px; + } +} + +.memberInfo { + margin-left: 12px; + flex: 1; +} + +.memberName { + font-size: 14px; + font-weight: 500; + color: #333; + margin-bottom: 2px; +} + +.memberId { + font-size: 12px; + color: #999; +} + +.selectedHeader { + padding: 16px; + border-bottom: 1px solid #e8e8e8; + font-weight: 500; + color: #333; + background: #fff; + display: flex; + align-items: center; + justify-content: space-between; +} + +.singleTip { + font-size: 12px; + color: #999; + font-weight: normal; +} + +.selectedList { + flex: 1; + overflow-y: auto; + padding: 8px 0; +} + +.selectedItem { + display: flex; + align-items: center; + padding: 8px 16px; + background: #fff; + margin: 4px 8px; + border-radius: 6px; + border: 1px solid #e8e8e8; +} + +.selectedInfo { + margin-left: 8px; + flex: 1; +} + +.selectedName { + font-size: 13px; + color: #333; +} + +.removeBtn { + color: #999; + font-size: 16px; + padding: 0; + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + + &:hover { + color: #ff4d4f; + background: #fff2f0; + } +} + +.empty { + display: flex; + align-items: center; + justify-content: center; + height: 100px; + color: #999; + font-size: 14px; +} + +.emptySelected { + display: flex; + align-items: center; + justify-content: center; + height: 100px; + color: #999; + font-size: 14px; +} \ No newline at end of file diff --git a/Cunkebao/src/components/MemberSelection/TwoColumnMemberSelection.tsx b/Cunkebao/src/components/MemberSelection/TwoColumnMemberSelection.tsx new file mode 100644 index 00000000..ef276a68 --- /dev/null +++ b/Cunkebao/src/components/MemberSelection/TwoColumnMemberSelection.tsx @@ -0,0 +1,185 @@ +import React, { useState } from 'react'; +import { Modal, Input, Avatar, Button, Checkbox } from 'antd'; +import { SearchOutlined } from '@ant-design/icons'; +import styles from './TwoColumnMemberSelection.module.scss'; + +interface Member { + id: string; + nickname: string; + avatar: string; +} + +interface TwoColumnMemberSelectionProps { + visible: boolean; + members: Member[]; + onCancel: () => void; + onConfirm: (selectedIds: string[]) => void; + title?: string; + allowMultiple?: boolean; +} + +const TwoColumnMemberSelection: React.FC = ({ + visible, + members, + onCancel, + onConfirm, + title = '选择成员', + allowMultiple = true, +}) => { + const [selectedMembers, setSelectedMembers] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + + // 过滤成员 + const filteredMembers = members.filter(member => + member.nickname.toLowerCase().includes(searchQuery.toLowerCase()) || + member.id.toLowerCase().includes(searchQuery.toLowerCase()) + ); + + // 处理搜索 + const handleSearch = (value: string) => { + setSearchQuery(value); + }; + + // 选择成员 + const handleSelectMember = (member: Member) => { + const isSelected = selectedMembers.some(m => m.id === member.id); + + if (allowMultiple) { + if (isSelected) { + setSelectedMembers(selectedMembers.filter(m => m.id !== member.id)); + } else { + setSelectedMembers([...selectedMembers, member]); + } + } else { + // 单选模式 + if (isSelected) { + setSelectedMembers([]); + } else { + setSelectedMembers([member]); + } + } + }; + + // 移除已选成员 + const handleRemoveMember = (memberId: string) => { + setSelectedMembers(selectedMembers.filter(m => m.id !== memberId)); + }; + + // 确认选择 + const handleConfirmSelection = () => { + const selectedIds = selectedMembers.map(m => m.id); + onConfirm(selectedIds); + setSelectedMembers([]); + setSearchQuery(''); + }; + + // 取消选择 + const handleCancelSelection = () => { + setSelectedMembers([]); + setSearchQuery(''); + onCancel(); + }; + + return ( + + 取消 + , + , + ]} + className={styles.twoColumnModal} + > +
+ {/* 左侧:成员列表 */} +
+
+ handleSearch(e.target.value)} + prefix={} + allowClear + /> +
+ +
+ {filteredMembers.length > 0 ? ( + filteredMembers.map(member => { + const isSelected = selectedMembers.some(m => m.id === member.id); + return ( +
handleSelectMember(member)} + > + + + {member.nickname?.charAt(0)} + +
+
{member.nickname}
+
{member.id}
+
+
+ ); + }) + ) : ( +
+ {searchQuery ? `没有找到包含"${searchQuery}"的成员` : '暂无成员'} +
+ )} +
+
+ + {/* 右侧:已选成员 */} +
+
+ 已选成员 ({selectedMembers.length}) + {!allowMultiple && (单选)} +
+ +
+ {selectedMembers.length > 0 ? ( + selectedMembers.map(member => ( +
+ + {member.nickname?.charAt(0)} + +
+
{member.nickname}
+
+ +
+ )) + ) : ( +
+ 暂无选择 +
+ )} +
+
+
+
+ ); +}; + +export default TwoColumnMemberSelection; \ No newline at end of file diff --git a/Cunkebao/src/components/MemberSelection/index.tsx b/Cunkebao/src/components/MemberSelection/index.tsx new file mode 100644 index 00000000..06c219b1 --- /dev/null +++ b/Cunkebao/src/components/MemberSelection/index.tsx @@ -0,0 +1,51 @@ +import React, { useState } from 'react'; +import { Modal, Checkbox, Avatar, List, Button } from 'antd'; + +interface MemberSelectionProps { + visible: boolean; + members: { id: string; nickname: string; avatar: string }[]; + onCancel: () => void; + onConfirm: (selectedIds: string[]) => void; +} + +const MemberSelection: React.FC = ({ visible, members, onCancel, onConfirm }) => { + const [selectedIds, setSelectedIds] = useState([]); + + const handleToggle = (id: string) => { + const newSelectedIds = selectedIds.includes(id) + ? selectedIds.filter(memberId => memberId !== id) + : [...selectedIds, id]; + setSelectedIds(newSelectedIds); + }; + + const handleConfirm = () => { + onConfirm(selectedIds); + setSelectedIds([]); + }; + + return ( + + ( + handleToggle(member.id)} style={{ cursor: 'pointer' }}> + } + title={member.nickname} + /> + + + )} + /> + + ); +}; + +export default MemberSelection; \ No newline at end of file diff --git a/Cunkebao/src/components/PlaceholderPage.tsx b/Cunkebao/src/components/PlaceholderPage.tsx index 4eec7f2f..69a8ddde 100644 --- a/Cunkebao/src/components/PlaceholderPage.tsx +++ b/Cunkebao/src/components/PlaceholderPage.tsx @@ -2,14 +2,12 @@ import React from "react"; import { NavBar, Button } from "antd-mobile"; import { PlusOutlined } from "@ant-design/icons"; import Layout from "@/components/Layout/Layout"; -import MeauMobile from "@/components/MeauMobile/MeauMoible"; interface PlaceholderPageProps { title: string; showBack?: boolean; showAddButton?: boolean; addButtonText?: string; - showFooter?: boolean; } const PlaceholderPage: React.FC = ({ @@ -17,13 +15,12 @@ const PlaceholderPage: React.FC = ({ showBack = true, showAddButton = false, addButtonText = "新建", - showFooter = true, }) => { return ( window.history.back() : undefined} left={ @@ -43,7 +40,6 @@ const PlaceholderPage: React.FC = ({ } /> } - footer={showFooter ? : undefined} >

{title}页面

diff --git a/Cunkebao/src/components/PoolSelection/selectionPopup.tsx b/Cunkebao/src/components/PoolSelection/selectionPopup.tsx index 1e59529c..20d08bec 100644 --- a/Cunkebao/src/components/PoolSelection/selectionPopup.tsx +++ b/Cunkebao/src/components/PoolSelection/selectionPopup.tsx @@ -96,6 +96,41 @@ export default function SelectionPopup({ } }; + // 全选当前页 + const handleSelectAllCurrentPage = (checked: boolean) => { + if (readonly) return; + + if (checked) { + // 全选:添加当前页面所有未选中的流量池包 + const currentPagePackages = poolPackages.filter( + packageItem => + !tempSelectedOptions.some(p => p.id === String(packageItem.id)), + ); + const newSelectionItems = currentPagePackages.map(item => ({ + id: String(item.id), + name: item.name, + description: item.description, + createTime: item.createTime, + num: item.num, + originalData: item, + })); + setTempSelectedOptions(prev => [...prev, ...newSelectionItems]); + } else { + // 取消全选:移除当前页面的所有流量池包 + const currentPagePackageIds = poolPackages.map(p => String(p.id)); + setTempSelectedOptions(prev => + prev.filter(p => !currentPagePackageIds.includes(p.id)), + ); + } + }; + + // 检查当前页是否全选 + const isCurrentPageAllSelected = + poolPackages.length > 0 && + poolPackages.every(packageItem => + tempSelectedOptions.some(p => p.id === String(packageItem.id)), + ); + // 确认选择 const handleConfirm = () => { if (onConfirm) { @@ -134,7 +169,7 @@ export default function SelectionPopup({ // 页码变化时请求数据(只在弹窗打开且页码不是1时执行) useEffect(() => { - if (!visible || currentPage === 1) return; + if (!visible) return; fetchPoolPackages(currentPage, searchQuery); }, [currentPage, visible, searchQuery]); @@ -158,7 +193,6 @@ export default function SelectionPopup({ } footer={ onVisibleChange(false)} onConfirm={handleConfirm} + isAllSelected={isCurrentPageAllSelected} + onSelectAll={handleSelectAllCurrentPage} /> } > diff --git a/Cunkebao/src/components/PopuLayout/footer.module.scss b/Cunkebao/src/components/PopuLayout/footer.module.scss index 2890e9ba..bd1286f0 100644 --- a/Cunkebao/src/components/PopuLayout/footer.module.scss +++ b/Cunkebao/src/components/PopuLayout/footer.module.scss @@ -9,7 +9,24 @@ .selectedCount { font-size: 14px; - color: #888; + color: #666; + display: flex; + align-items: center; + gap: 12px; +} + +.selectAllCheckbox { + margin-right: 0; + + .ant-checkbox-wrapper { + font-size: 14px; + } + + &.ant-checkbox-wrapper-disabled { + .ant-checkbox-disabled + span { + color: #d9d9d9; + } + } } .footerBtnGroup { diff --git a/Cunkebao/src/components/PopuLayout/footer.tsx b/Cunkebao/src/components/PopuLayout/footer.tsx index df10ffa2..60e562be 100644 --- a/Cunkebao/src/components/PopuLayout/footer.tsx +++ b/Cunkebao/src/components/PopuLayout/footer.tsx @@ -1,10 +1,9 @@ import React from "react"; -import { Button } from "antd"; +import { Button, Checkbox } from "antd"; import style from "./footer.module.scss"; import { ArrowLeftOutlined, ArrowRightOutlined } from "@ant-design/icons"; interface PopupFooterProps { - total: number; currentPage: number; totalPages: number; loading: boolean; @@ -12,10 +11,12 @@ interface PopupFooterProps { onPageChange: (page: number) => void; onCancel: () => void; onConfirm: () => void; + // 全选功能相关 + isAllSelected?: boolean; + onSelectAll?: (checked: boolean) => void; } const PopupFooter: React.FC = ({ - total, currentPage, totalPages, loading, @@ -23,12 +24,22 @@ const PopupFooter: React.FC = ({ onPageChange, onCancel, onConfirm, + isAllSelected = false, + onSelectAll, }) => { return ( <> {/* 分页栏 */}
-
总计 {total} 条记录
+
+ onSelectAll(e.target.checked)} + className={style.selectAllCheckbox} + > + 全选当前页 + +
, + , + ]} + className={styles.twoColumnModal} + > +
+ {/* 左侧:好友列表 */} +
+
+ { + const value = e.target.value; + setSearchQuery(value); // 立即更新显示 + handleSearch(value); // 防抖处理搜索 + }} + prefix={} + allowClear + /> +
+ +
+ {loading ? ( +
加载中...
+ ) : friends.length > 0 ? ( + // 使用 React.memo 优化列表项渲染 + friends.map(friend => { + const isSelected = selectedFriendsMap.has(friend.id); + return ( + + ); + }) + ) : ( +
+ {searchQuery + ? `没有找到包含"${searchQuery}"的好友` + : "暂无好友"} +
+ )} + + {hasMoreFriends && ( +
+ +
+ )} +
+
+ + {/* 右侧:已选好友 */} +
+
+ 已选联系人 ({selectedFriends.length}) +
+ +
+ {selectedFriends.length > 0 ? ( + selectedFriends.map(friend => ( +
+ + {friend.nickname?.charAt(0)} + +
+
{friend.nickname}
+
+ +
+ )) + ) : ( +
暂无选择
+ )} +
+
+
+ + ); +}; + +export default TwoColumnSelection; diff --git a/Cunkebao/src/components/Upload/AudioRecorder/index.tsx b/Cunkebao/src/components/Upload/AudioRecorder/index.tsx new file mode 100644 index 00000000..1bcc705e --- /dev/null +++ b/Cunkebao/src/components/Upload/AudioRecorder/index.tsx @@ -0,0 +1,411 @@ +import React, { useState, useRef, useCallback } from "react"; +import { Button, message, Modal } from "antd"; +import { + AudioOutlined, + PlayCircleOutlined, + PauseCircleOutlined, + SendOutlined, + DeleteOutlined, +} from "@ant-design/icons"; +import { uploadFile } from "@/api/common"; + +interface AudioRecorderProps { + onAudioUploaded: (audioData: { url: string; durationMs: number }) => void; + className?: string; + disabled?: boolean; + maxDuration?: number; // 最大录音时长(秒) +} + +type RecordingState = + | "idle" + | "recording" + | "recorded" + | "playing" + | "uploading"; + +const AudioRecorder: React.FC = ({ + onAudioUploaded, + className, + disabled = false, + maxDuration = 60, +}) => { + const [visible, setVisible] = useState(false); + const [state, setState] = useState("idle"); + const [recordingTime, setRecordingTime] = useState(0); + const [audioBlob, setAudioBlob] = useState(null); + const [audioUrl, setAudioUrl] = useState(""); + + const mediaRecorderRef = useRef(null); + const audioRef = useRef(null); + const timerRef = useRef(null); + const chunksRef = useRef([]); + + // 打开弹窗 + const openRecorder = () => { + setVisible(true); + }; + + // 关闭弹窗并重置状态 + const closeRecorder = () => { + if (state === "recording") { + stopRecording(); + } + if (state === "playing") { + pauseAudio(); + } + deleteRecording(); + setVisible(false); + }; + + // 开始录音 + const startRecording = useCallback(async () => { + try { + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + + // 尝试使用MP3格式,如果不支持则回退到WebM + const mp3Types = [ + "audio/mpeg", + "audio/mp3", + "audio/mpeg; codecs=mp3", + "audio/mp4", + "audio/mp4; codecs=mp4a.40.2", + ]; + + let mimeType = "audio/webm"; // 默认回退格式 + + // 检测并选择支持的MP3格式 + for (const type of mp3Types) { + if (MediaRecorder.isTypeSupported(type)) { + mimeType = type; + console.log(`使用音频格式: ${type}`); + break; + } + } + + if (mimeType === "audio/webm") { + console.log("浏览器不支持MP3格式,使用WebM格式"); + } + + const mediaRecorder = new MediaRecorder(stream, { mimeType }); + mediaRecorderRef.current = mediaRecorder; + chunksRef.current = []; + + mediaRecorder.ondataavailable = event => { + if (event.data.size > 0) { + chunksRef.current.push(event.data); + } + }; + + mediaRecorder.onstop = () => { + const blob = new Blob(chunksRef.current, { type: mimeType }); + setAudioBlob(blob); + const url = URL.createObjectURL(blob); + setAudioUrl(url); + setState("recorded"); + + // 停止所有音频轨道 + stream.getTracks().forEach(track => track.stop()); + }; + + mediaRecorder.start(); + setState("recording"); + setRecordingTime(0); + + // 开始计时 + timerRef.current = setInterval(() => { + setRecordingTime(prev => { + const newTime = prev + 1; + if (newTime >= maxDuration) { + stopRecording(); + } + return newTime; + }); + }, 1000); + } catch (error) { + console.error("录音失败:", error); + message.error("无法访问麦克风,请检查权限设置"); + } + }, [maxDuration]); + + // 停止录音 + const stopRecording = useCallback(() => { + if ( + mediaRecorderRef.current && + mediaRecorderRef.current.state === "recording" + ) { + mediaRecorderRef.current.stop(); + } + if (timerRef.current) { + clearInterval(timerRef.current); + timerRef.current = null; + } + }, []); + + // 播放录音 + const playAudio = useCallback(() => { + if (audioRef.current && audioUrl) { + audioRef.current.play(); + setState("playing"); + } + }, [audioUrl]); + + // 暂停播放 + const pauseAudio = useCallback(() => { + if (audioRef.current) { + audioRef.current.pause(); + setState("recorded"); + } + }, []); + + // 删除录音 + const deleteRecording = useCallback(() => { + if (audioUrl) { + URL.revokeObjectURL(audioUrl); + } + setAudioBlob(null); + setAudioUrl(""); + setRecordingTime(0); + setState("idle"); + }, [audioUrl]); + + // 发送录音 + const sendAudio = useCallback(async () => { + if (!audioBlob) return; + + try { + setState("uploading"); + + // 创建文件对象 + const timestamp = Date.now(); + const fileExtension = + audioBlob.type.includes("mp3") || + audioBlob.type.includes("mpeg") || + audioBlob.type.includes("mp4") + ? "mp3" + : "webm"; + const audioFile = new File( + [audioBlob], + `audio_${timestamp}.${fileExtension}`, + { + type: audioBlob.type, + }, + ); + + // 打印文件格式信息 + console.log("音频文件信息:", { + fileName: audioFile.name, + fileType: audioFile.type, + fileSize: audioFile.size, + fileExtension: fileExtension, + blobType: audioBlob.type, + }); + + // 上传文件 + const filePath = await uploadFile(audioFile); + + // 调用回调函数,传递音频URL和时长(毫秒) + onAudioUploaded({ + url: filePath, + durationMs: recordingTime * 1000, // 将秒转换为毫秒 + }); + + // 重置状态并关闭弹窗 + deleteRecording(); + setVisible(false); + message.success("语音发送成功"); + } catch (error) { + console.error("语音上传失败:", error); + message.error("语音发送失败,请重试"); + setState("recorded"); + } + }, [audioBlob, onAudioUploaded, deleteRecording]); + + // 格式化时间显示 + const formatTime = (seconds: number) => { + const mins = Math.floor(seconds / 60); + const secs = seconds % 60; + return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`; + }; + + // 渲染弹窗内容 + const renderModalContent = () => { + switch (state) { + case "idle": + return ( +
+
+ 点击下方按钮开始录音 +
+
+ ); + + case "recording": + return ( +
+
+
+ {formatTime(recordingTime)} +
+
+ 正在录音中... +
+
+ +
+ ); + + case "recorded": + case "playing": + return ( +
+
+
+ 录音时长: {formatTime(recordingTime)} +
+
+ {state === "playing" + ? "正在播放..." + : "录音完成,可以试听或发送"} +
+
+ +
+
+ +
+ +
+
+ ); + + case "uploading": + return ( +
+ +
+ ); + + default: + return null; + } + }; + + return ( + <> + -
- } - > -
-
e.preventDefault()} - autoComplete="off" - > -
- - setName(e.target.value)} - className={style["input"]} - /> -
- -
数据来源配置
-
- setSourceType(key as "friends" | "groups")} - className={style["tabs-bar"]} - > - - - - - - - -
- - - 关键词设置} - > -
- -