sa2kit 1.6.64 → 1.6.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/legacy/core/index.js +24 -12
- package/dist/auth/legacy/core/index.js.map +1 -1
- package/dist/auth/legacy/core/index.mjs +24 -12
- package/dist/auth/legacy/core/index.mjs.map +1 -1
- package/dist/auth/legacy/index.js +30 -12
- package/dist/auth/legacy/index.js.map +1 -1
- package/dist/auth/legacy/index.mjs +30 -12
- package/dist/auth/legacy/index.mjs.map +1 -1
- package/dist/auth/legacy/logic/index.js +24 -12
- package/dist/auth/legacy/logic/index.js.map +1 -1
- package/dist/auth/legacy/logic/index.mjs +24 -12
- package/dist/auth/legacy/logic/index.mjs.map +1 -1
- package/dist/auth/legacy/miniapp/index.js +24 -12
- package/dist/auth/legacy/miniapp/index.js.map +1 -1
- package/dist/auth/legacy/miniapp/index.mjs +24 -12
- package/dist/auth/legacy/miniapp/index.mjs.map +1 -1
- package/dist/auth/legacy/routes/index.d.mts +3 -0
- package/dist/auth/legacy/routes/index.d.ts +3 -0
- package/dist/auth/legacy/routes/index.js +8 -1
- package/dist/auth/legacy/routes/index.js.map +1 -1
- package/dist/auth/legacy/routes/index.mjs +8 -1
- package/dist/auth/legacy/routes/index.mjs.map +1 -1
- package/dist/auth/legacy/server/index.js +8 -1
- package/dist/auth/legacy/server/index.js.map +1 -1
- package/dist/auth/legacy/server/index.mjs +8 -1
- package/dist/auth/legacy/server/index.mjs.map +1 -1
- package/dist/auth/legacy/ui/miniapp/index.js.map +1 -1
- package/dist/auth/legacy/ui/miniapp/index.mjs.map +1 -1
- package/dist/auth/legacy/ui/web/index.js +6 -0
- package/dist/auth/legacy/ui/web/index.js.map +1 -1
- package/dist/auth/legacy/ui/web/index.mjs +6 -0
- package/dist/auth/legacy/ui/web/index.mjs.map +1 -1
- package/dist/auth/legacy/web/index.js +30 -12
- package/dist/auth/legacy/web/index.js.map +1 -1
- package/dist/auth/legacy/web/index.mjs +30 -12
- package/dist/auth/legacy/web/index.mjs.map +1 -1
- package/dist/showmasterpiece/index.js +30 -12
- package/dist/showmasterpiece/index.js.map +1 -1
- package/dist/showmasterpiece/index.mjs +30 -12
- package/dist/showmasterpiece/index.mjs.map +1 -1
- package/dist/showmasterpiece/ui/web/index.js +30 -12
- package/dist/showmasterpiece/ui/web/index.js.map +1 -1
- package/dist/showmasterpiece/ui/web/index.mjs +30 -12
- package/dist/showmasterpiece/ui/web/index.mjs.map +1 -1
- package/dist/showmasterpiece/web/index.js +30 -12
- package/dist/showmasterpiece/web/index.js.map +1 -1
- package/dist/showmasterpiece/web/index.mjs +30 -12
- package/dist/showmasterpiece/web/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/legacy/contexts/AuthContext.tsx","../../../src/auth/legacy/utils/authUtils.ts","../../../src/auth/legacy/components/ForgotPasswordModal.tsx","../../../src/auth/legacy/components/LoginModal.tsx","../../../src/auth/legacy/components/AuthGuard.tsx","../../../src/auth/legacy/components/RegisterModal.tsx","../../../src/auth/legacy/components/UserMenu.tsx","../../../src/auth/legacy/types/index.ts"],"names":["createContext","useState","useRef","useCallback","useEffect","React","useContext","error","X","Phone","Lock","EyeOff","Eye","createPortal","User","LogOut","LogIn","UserRole"],"mappings":";;;;;;;;;;;AAOA,IAAM,WAAA,GAAcA,qBAA2C,MAAS,CAAA;AAEjE,SAAS,YAAA,CAAa,EAAE,QAAA,EAAS,EAAkC;AACxE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIC,gBAAsB,IAAI,CAAA;AAClD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,gBAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAC5D,EAAA,MAAM,YAAA,GAAeC,cAAO,IAAI,CAAA;AAGhC,EAAA,MAAM,YAAA,GAAeC,kBAAA,CAAY,CAAC,OAAA,KAAwB;AACxD,IAAA,IAAI,aAAa,OAAA,EAAS;AACxB,MAAA,OAAA,EAAQ;AAAA,IACV;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,eAAA,GAAkBA,mBAAY,YAAY;AAC9C,IAAA,OAAA,CAAQ,IAAI,iEAA4B,CAAA;AACxC,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,oBAAoB,CAAA;AACjD,MAAA,OAAA,CAAQ,GAAA,CAAI,2EAAA,EAA8B,QAAA,CAAS,MAAM,CAAA;AAEzD,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,OAAA,CAAQ,GAAA,CAAI,6EAA8B,IAAI,CAAA;AAE9C,MAAA,YAAA,CAAa,MAAM;AACjB,QAAA,IAAI,IAAA,CAAK,KAAA,IAAS,IAAA,CAAK,IAAA,EAAM;AAC3B,UAAA,OAAA,CAAQ,GAAA,CAAI,0EAAA,EAA+B,IAAA,CAAK,IAAI,CAAA;AACpD,UAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,UAAA,kBAAA,CAAmB,IAAI,CAAA;AAAA,QACzB,CAAA,MAAO;AACL,UAAA,OAAA,CAAQ,GAAA,CAAI,4DAAA,EAA2B,IAAA,CAAK,OAAO,CAAA;AACnD,UAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,UAAA,kBAAA,CAAmB,KAAK,CAAA;AAAA,QAC1B;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB,CAAC,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,iEAA4B,KAAK,CAAA;AAC/C,MAAA,YAAA,CAAa,MAAM;AACjB,QAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,QAAA,kBAAA,CAAmB,KAAK,CAAA;AACxB,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB,CAAC,CAAA;AAAA,IACH;AAAA,EACF,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAGjB,EAAA,MAAM,KAAA,GAAQA,kBAAA,CAAY,OAAO,WAAA,KAA8B;AAC7D,IAAA,OAAA,CAAQ,IAAI,qDAA0B,CAAA;AACtC,IAAA,OAAA,CAAQ,GAAA,CAAI,qDAA0B,EAAE,KAAA,EAAO,YAAY,KAAA,EAAO,QAAA,EAAU,OAAO,CAAA;AAEnF,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,IAAI,oFAA0C,CAAA;AACtD,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,iBAAA,EAAmB;AAAA,QAC9C,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,QAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,WAAW;AAAA,OACjC,CAAA;AAED,MAAA,OAAA,CAAQ,GAAA,CAAI,2EAAA,EAA8B,QAAA,CAAS,MAAM,CAAA;AACzD,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,OAAA,CAAQ,GAAA,CAAI,qDAA0B,IAAI,CAAA;AAE1C,MAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,IAAA,EAAM;AAC7B,QAAA,OAAA,CAAQ,IAAI,iGAAgC,CAAA;AAC5C,QAAA,OAAA,CAAQ,GAAA,CAAI,mDAAA,EAA0B,IAAA,CAAK,IAAI,CAAA;AAG/C,QAAA,OAAA,CAAQ,IAAI,yDAAA,EAA2B;AAAA,UACrC,WAAA,EAAa,OAAO,CAAA,EAAG,IAAA,CAAK,QAAQ,oBAAK,CAAA,EAAA,EAAK,IAAA,CAAK,KAAK,CAAA,CAAA,CAAA,GAAM,IAAA;AAAA,UAC9D,sBAAA,EAAwB,eAAA;AAAA,UACxB,cAAA,EAAgB;AAAA,SACjB,CAAA;AAGD,QAAA,OAAA,CAAQ,IAAI,6EAA8B,CAAA;AAC1C,QAAA,YAAA,CAAa,MAAM;AACjB,UAAA,OAAA,CAAQ,GAAA,CAAI,+DAAA,EAA4B,IAAA,CAAK,IAAI,CAAA;AACjD,UAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,UAAA,OAAA,CAAQ,IAAI,gFAAiC,CAAA;AAC7C,UAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,UAAA,OAAA,CAAQ,IAAI,iFAAkC,CAAA;AAC9C,UAAA,UAAA,CAAW,KAAK,CAAA;AAChB,UAAA,OAAA,CAAQ,IAAI,uEAA0B,CAAA;AAAA,QACxC,CAAC,CAAA;AAGD,QAAA,UAAA,CAAW,MAAM;AACf,UAAA,OAAA,CAAQ,IAAI,wHAAA,EAAwC;AAAA,YAClD,MAAM,IAAA,CAAK,IAAA;AAAA,YACX,eAAA,EAAiB;AAAA,WAClB,CAAA;AAAA,QACH,GAAG,CAAC,CAAA;AAEJ,QAAA,OAAA,CAAQ,IAAI,8DAAyB,CAAA;AACrC,QAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,KAAK,IAAA,EAAK;AAAA,MAC1C,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,GAAA,CAAI,gDAAA,EAAyB,IAAA,CAAK,OAAO,CAAA;AACjD,QAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,MACjD;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,qDAA0B,KAAK,CAAA;AAC7C,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,8DAAA,EAAa;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,IAAA,EAAM,eAAA,EAAiB,OAAO,CAAC,CAAA;AAGjD,EAAA,MAAM,QAAA,GAAWA,kBAAA,CAAY,OAAO,QAAA,KAA8B;AAChE,IAAA,OAAA,CAAQ,IAAI,qDAA0B,CAAA;AACtC,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,oBAAA,EAAsB;AAAA,QACjD,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,QAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,QAAQ;AAAA,OAC9B,CAAA;AAED,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,OAAA,CAAQ,GAAA,CAAI,qDAA0B,IAAI,CAAA;AAE1C,MAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,IAAA,EAAM;AAC7B,QAAA,OAAA,CAAQ,IAAI,iGAAgC,CAAA;AAG5C,QAAA,YAAA,CAAa,MAAM;AACjB,UAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,UAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,UAAA,UAAA,CAAW,KAAK,CAAA;AAAA,QAClB,CAAC,CAAA;AAED,QAAA,OAAA,CAAQ,IAAI,0EAA2B,CAAA;AACvC,QAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,KAAK,IAAA,EAAK;AAAA,MAC1C,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,GAAA,CAAI,gDAAA,EAAyB,IAAA,CAAK,OAAO,CAAA;AACjD,QAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,MACjD;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,qDAA0B,KAAK,CAAA;AAC7C,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,8DAAA,EAAa;AAAA,IACjD;AAAA,EACF,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAGjB,EAAA,MAAM,MAAA,GAASA,mBAAY,YAAY;AACrC,IAAA,OAAA,CAAQ,IAAI,qDAA0B,CAAA;AACtC,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,CAAM,kBAAA,EAAoB,EAAE,MAAA,EAAQ,QAAQ,CAAA;AAClD,MAAA,YAAA,CAAa,MAAM;AACjB,QAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,QAAA,kBAAA,CAAmB,KAAK,CAAA;AAAA,MAC1B,CAAC,CAAA;AACD,MAAA,OAAA,CAAQ,IAAI,2FAA+B,CAAA;AAAA,IAC7C,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,qDAA0B,KAAK,CAAA;AAAA,IAC/C;AAAA,EACF,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAGjB,EAAA,MAAM,WAAA,GAAcA,mBAAY,MAAM;AACpC,IAAA,OAAA,CAAQ,IAAI,iEAA4B,CAAA;AACxC,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,eAAA,EAAgB;AAAA,EAClB,CAAA,EAAG,CAAC,eAAe,CAAC,CAAA;AAGpB,EAAAC,gBAAA,CAAU,MAAM;AACd,IAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,IAAA,OAAO,MAAM;AACX,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AAAA,IACzB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAAA,gBAAA,CAAU,MAAM;AACd,IAAA,OAAA,CAAQ,IAAI,kFAA8B,CAAA;AAC1C,IAAA,eAAA,EAAgB;AAAA,EAClB,CAAA,EAAG,CAAC,eAAe,CAAC,CAAA;AAGpB,EAAAA,gBAAA,CAAU,MAAM;AACd,IAAA,OAAA,CAAQ,IAAI,+DAAA,EAA4B;AAAA,MACtC,eAAA;AAAA,MACA,IAAA,EAAM,OAAO,CAAA,EAAG,IAAA,CAAK,QAAQ,oBAAK,CAAA,EAAA,EAAK,IAAA,CAAK,KAAK,CAAA,CAAA,CAAA,GAAM,IAAA;AAAA,MACvD;AAAA,KACD,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,eAAA,EAAiB,IAAA,EAAM,OAAO,CAAC,CAAA;AAEnC,EAAA,MAAM,KAAA,GAAyB;AAAA,IAC7B,IAAA;AAAA,IACA,OAAA;AAAA,IACA,eAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,uBACEC,uBAAA,CAAA,aAAA,CAAC,WAAA,CAAY,QAAA,EAAZ,EAAqB,SACnB,QACH,CAAA;AAEJ;AAEO,SAAS,OAAA,GAAyB;AACvC,EAAA,MAAM,OAAA,GAAUC,kBAAW,WAAW,CAAA;AACtC,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,EAC/D;AACA,EAAA,OAAO,OAAA;AACT;;;ACpNO,SAAS,oBAAoB,KAAA,EAAwB;AAC1D,EAAA,OAAO,eAAA,CAAgB,KAAK,KAAK,CAAA;AACnC;AAKO,SAAS,iBAAiB,QAAA,EAAwD;AACvF,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,sCAAA,EAAS;AAAA,EAC3C;AAEA,EAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,6CAAA,EAAW;AAAA,EAC7C;AAEA,EAAA,OAAO,EAAE,OAAO,IAAA,EAAK;AACvB;AAKO,SAAS,oBAAA,GAA+B;AAE7C,EAAA,OAAO,IAAA,CAAK,QAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,SAAA,CAAU,CAAC,CAAA,GACtC,IAAA,CAAK,GAAA,GAAM,QAAA,CAAS,EAAE,IACtB,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,CAAA,CAAE,SAAA,CAAU,CAAC,CAAA;AAC/C;AAKO,SAAS,QAAQ,IAAA,EAA4B;AAClD,EAAA,OAAO,MAAM,IAAA,KAAS,OAAA;AACxB;AAKO,SAAS,aAAa,IAAA,EAA4B;AACvD,EAAA,OAAO,MAAM,QAAA,KAAa,IAAA;AAC5B;AAKO,SAAS,mBAAmB,IAAA,EAAoB;AACrD,EAAA,OAAO,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,KAAA,IAAS,0BAAA;AACpC;AAKO,SAAS,sBAAA,CAAuB,OAAe,EAAA,EAAU;AAC9D,EAAA,OAAO,IAAI,KAAK,IAAA,CAAK,GAAA,KAAQ,IAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAI,CAAA;AACzD;AAKO,SAAS,iBAAiB,SAAA,EAA0B;AACzD,EAAA,uBAAO,IAAI,IAAA,EAAK,GAAI,IAAI,KAAK,SAAS,CAAA;AACxC;AC3De,SAAR,mBAAA,CAAqC,EAAE,MAAA,EAAQ,OAAA,EAAS,WAAU,EAA6B;AACpG,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIL,eAAAA,CAAS;AAAA,IACvC,KAAA,EAAO,EAAA;AAAA,IACP,WAAA,EAAa,EAAA;AAAA,IACb,eAAA,EAAiB,EAAA;AAAA,IACjB,gBAAA,EAAkB;AAAA,GACnB,CAAA;AACD,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIA,gBAAS,KAAK,CAAA;AACtD,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAIA,gBAAS,KAAK,CAAA;AACpE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,gBAAS,EAAE,CAAA;AACrC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,gBAAS,CAAC,CAAA;AAC5C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAG5C,EAAAG,iBAAU,MAAM;AACd,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,iBAAA,GAAoB,CAAC,CAAA,KAA2C;AACpE,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,CAAA,CAAE,MAAA;AAC1B,IAAA,WAAA,CAAY,CAAA,IAAA,MAAS,EAAE,GAAG,IAAA,EAAM,CAAC,IAAI,GAAG,OAAM,CAAE,CAAA;AAChD,IAAA,IAAI,KAAA,WAAgB,EAAE,CAAA;AAAA,EACxB,CAAA;AAEA,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,IAAI,CAAC,QAAA,CAAS,KAAA,IAAS,CAAC,QAAA,CAAS,WAAA,IAAe,CAAC,QAAA,CAAS,eAAA,IAAmB,CAAC,QAAA,CAAS,gBAAA,EAAkB;AACvG,MAAA,QAAA,CAAS,4CAAS,CAAA;AAClB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,CAAC,mBAAA,CAAoB,QAAA,CAAS,KAAK,CAAA,EAAG;AACxC,MAAA,QAAA,CAAS,oEAAa,CAAA;AACtB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,kBAAA,GAAqB,gBAAA,CAAiB,QAAA,CAAS,WAAW,CAAA;AAChE,IAAA,IAAI,CAAC,mBAAmB,KAAA,EAAO;AAC7B,MAAA,QAAA,CAAS,kBAAA,CAAmB,WAAW,sCAAQ,CAAA;AAC/C,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,QAAA,CAAS,WAAA,KAAgB,QAAA,CAAS,eAAA,EAAiB;AACrD,MAAA,QAAA,CAAS,8DAAY,CAAA;AACrB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,CAAC,SAAA,CAAU,IAAA,CAAK,QAAA,CAAS,gBAAgB,CAAA,EAAG;AAC9C,MAAA,QAAA,CAAS,yDAAY,CAAA;AACrB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,iBAAiB,YAAY;AACjC,IAAA,IAAI,CAAC,SAAS,KAAA,EAAO;AACnB,MAAA,QAAA,CAAS,sCAAQ,CAAA;AACjB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,mBAAA,CAAoB,QAAA,CAAS,KAAK,CAAA,EAAG;AACxC,MAAA,QAAA,CAAS,oEAAa,CAAA;AACtB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,QAAA,CAAS,EAAE,CAAA;AAEX,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,kCAAA,EAAoC;AAAA,QAC/D,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,QAC9C,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,QAAA,CAAS,OAAO;AAAA,OAC/C,CAAA;AAED,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,IAAI,KAAK,OAAA,EAAS;AAEhB,QAAA,YAAA,CAAa,EAAE,CAAA;AACf,QAAA,MAAM,KAAA,GAAQ,YAAY,MAAM;AAC9B,UAAA,YAAA,CAAa,CAAA,IAAA,KAAQ;AACnB,YAAA,IAAI,QAAQ,CAAA,EAAG;AACb,cAAA,aAAA,CAAc,KAAK,CAAA;AACnB,cAAA,OAAO,CAAA;AAAA,YACT;AACA,YAAA,OAAO,IAAA,GAAO,CAAA;AAAA,UAChB,CAAC,CAAA;AAAA,QACH,GAAG,GAAI,CAAA;AAGP,QAAA,OAAA,CAAQ,IAAI,mDAAW,CAAA;AAAA,MACzB,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,IAAA,CAAK,WAAW,4CAAS,CAAA;AAAA,MACpC;AAAA,IACF,SAASG,MAAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,+CAAYA,MAAK,CAAA;AAC/B,MAAA,QAAA,CAAS,gFAAe,CAAA;AAAA,IAC1B,CAAA,SAAE;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,OAAO,CAAA,KAAuB;AACjD,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,UAAA,CAAW,IAAI,CAAA;AAEf,IAAA,IAAI;AACF,MAAA,IAAI,CAAC,cAAa,EAAG;AACnB,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,0BAAA,EAA4B;AAAA,QACvD,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,QAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,UACnB,OAAO,QAAA,CAAS,KAAA;AAAA,UAChB,aAAa,QAAA,CAAS,WAAA;AAAA,UACtB,kBAAkB,QAAA,CAAS;AAAA,SAC5B;AAAA,OACF,CAAA;AAED,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,IAAI,KAAK,OAAA,EAAS;AAChB,QAAA,SAAA,EAAU;AAAA,MACZ,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,IAAA,CAAK,WAAW,sCAAQ,CAAA;AAAA,MACnC;AAAA,IACF,SAASA,MAAAA,EAAO;AACd,MAAA,QAAA,CAAS,0EAAc,CAAA;AAAA,IACzB,CAAA,SAAE;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAqB,CAAC,CAAA,KAAwB;AAClD,IAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,aAAA,EAAe;AAChC,MAAA,OAAA,EAAQ;AAAA,IACV;AAAA,EACF,CAAA;AAEA,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,OAAA,EAAS,OAAO,IAAA;AAEhC,EAAA,MAAM,YAAA,mBACJF,uBAAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,kIAAA;AAAA,MACV,KAAA,EAAO,EAAE,MAAA,EAAQ,CAAA,EAAE;AAAA,MACnB,OAAA,EAAS;AAAA,KAAA;AAAA,oBAETA,uBAAAA,CAAA,aAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,2FAAA;AAAA,QACV,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,eAAA;AAAgB,OAAA;AAAA,sBAGlCA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,6QAAA;AAAA,UACV,OAAA,EAAS;AAAA,SAAA;AAAA,wBAETA,uBAAAA,CAAA,aAAA,CAACG,aAAA,EAAA,EAAE,MAAM,EAAA,EAAI;AAAA,OACf;AAAA,sBAGAH,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,WAAU,qDAAA,EAAA,kBACbA,wBAAA,aAAA,CAAC,IAAA,EAAA,EAAG,WAAU,2CAAA,EAAA,EAA4C,0BAAI,mBAC9DA,uBAAAA,CAAA,cAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uBAAA,EAAA,EAAwB,sFAAc,CACrD,CAAA;AAAA,sBAGAA,uBAAAA,CAAA,aAAA,CAAC,UAAK,QAAA,EAAU,YAAA,EAAc,WAAU,KAAA,EAAA,kBAEtCA,uBAAAA,CAAA,aAAA,CAAC,SAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAAC,WAAM,OAAA,EAAQ,OAAA,EAAQ,SAAA,EAAU,gDAAA,EAAA,EAAiD,oBAElF,CAAA,kBACAA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4BAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAACI,qBAAM,IAAA,EAAM,EAAA,EAAI,WAAU,yDAAA,EAA0D,CAAA,kBACrFJ,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,OAAA;AAAA,UACH,IAAA,EAAK,OAAA;AAAA,UACL,IAAA,EAAK,KAAA;AAAA,UACL,OAAO,QAAA,CAAS,KAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,sCAAA;AAAA,UACZ,SAAA,EAAU,gSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OAEd,CACF,CAAA,kBAGAA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAAC,OAAA,EAAA,EAAM,SAAQ,kBAAA,EAAmB,SAAA,EAAU,gDAAA,EAAA,EAAiD,oBAE7F,CAAA,kBACAA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,kBAAA;AAAA,UACH,IAAA,EAAK,kBAAA;AAAA,UACL,IAAA,EAAK,MAAA;AAAA,UACL,OAAO,QAAA,CAAS,gBAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,sCAAA;AAAA,UACZ,SAAA,EAAU,gSAAA;AAAA,UACV,QAAA,EAAU,OAAA;AAAA,UACV,SAAA,EAAW;AAAA;AAAA,OACb,kBACAA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,8OAAA;AAAA,UACV,OAAA,EAAS,cAAA;AAAA,UACT,QAAA,EAAU,WAAW,SAAA,GAAY;AAAA,SAAA;AAAA,QAEhC,SAAA,GAAY,CAAA,GAAI,CAAA,EAAG,SAAS,CAAA,wBAAA,CAAA,GAAS;AAAA,OAE1C,CACF,CAAA,kBAGAA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAAC,OAAA,EAAA,EAAM,OAAA,EAAQ,eAAc,SAAA,EAAU,gDAAA,EAAA,EAAiD,oBAExF,CAAA,kBACAA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDACbA,uBAAAA,CAAA,aAAA,CAACK,gBAAA,EAAA,EAAK,MAAM,EAAA,EAAI,SAAA,EAAU,yDAAA,EAA0D,CAAA,kBACpFL,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,aAAA;AAAA,UACH,IAAA,EAAK,aAAA;AAAA,UACL,IAAA,EAAM,eAAe,MAAA,GAAS,UAAA;AAAA,UAC9B,OAAO,QAAA,CAAS,WAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,sCAAA;AAAA,UACZ,SAAA,EAAU,sSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OACZ,kBACAA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,4OAAA;AAAA,UACV,OAAA,EAAS,MAAM,eAAA,CAAgB,CAAC,YAAY,CAAA;AAAA,UAC5C,QAAA,EAAU;AAAA,SAAA;AAAA,QAET,YAAA,mBAAeA,uBAAAA,CAAA,aAAA,CAACM,kBAAA,EAAA,EAAO,IAAA,EAAM,EAAA,EAAI,CAAA,mBAAKN,uBAAAA,CAAA,aAAA,CAACO,eAAA,EAAA,EAAI,MAAM,EAAA,EAAI;AAAA,OAE1D,CACF,CAAA,kBAGAP,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAAC,OAAA,EAAA,EAAM,OAAA,EAAQ,mBAAkB,SAAA,EAAU,gDAAA,EAAA,EAAiD,0BAE5F,CAAA,kBACAA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDACbA,uBAAAA,CAAA,aAAA,CAACK,gBAAA,EAAA,EAAK,MAAM,EAAA,EAAI,SAAA,EAAU,yDAAA,EAA0D,CAAA,kBACpFL,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,iBAAA;AAAA,UACH,IAAA,EAAK,iBAAA;AAAA,UACL,IAAA,EAAM,sBAAsB,MAAA,GAAS,UAAA;AAAA,UACrC,OAAO,QAAA,CAAS,eAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,kDAAA;AAAA,UACZ,SAAA,EAAU,sSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OACZ,kBACAA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,4OAAA;AAAA,UACV,OAAA,EAAS,MAAM,sBAAA,CAAuB,CAAC,mBAAmB,CAAA;AAAA,UAC1D,QAAA,EAAU;AAAA,SAAA;AAAA,QAET,mBAAA,mBAAsBA,uBAAAA,CAAA,aAAA,CAACM,kBAAA,EAAA,EAAO,IAAA,EAAM,EAAA,EAAI,CAAA,mBAAKN,uBAAAA,CAAA,aAAA,CAACO,eAAA,EAAA,EAAI,MAAM,EAAA,EAAI;AAAA,OAEjE,CACF,CAAA,EAGC,KAAA,oBACCP,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0FAAA,EAAA,EACZ,KACH,CAAA,kBAIFA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,qZAAA;AAAA,UACV,QAAA,EAAU;AAAA,SAAA;AAAA,QAET,UAAU,uBAAA,GAAW;AAAA,OAE1B;AAAA;AACF,GACF;AAIF,EAAA,OAAOQ,qBAAA,CAAa,YAAA,EAAc,QAAA,CAAS,IAAI,CAAA;AACjD;;;AClSe,SAAR,WAA4B,EAAE,MAAA,EAAQ,OAAA,EAAS,SAAA,EAAW,oBAAmB,EAAoB;AACtG,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,OAAA,EAAQ;AAC1B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIZ,eAAAA,CAAS;AAAA,IACvC,KAAA,EAAO,EAAA;AAAA,IACP,QAAA,EAAU;AAAA,GACX,CAAA;AACD,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIA,gBAAS,KAAK,CAAA;AACtD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,gBAAS,EAAE,CAAA;AACrC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,kBAAA,EAAoB,qBAAqB,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAClE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAG5C,EAAAG,iBAAU,MAAM;AACd,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,eAAA,GAAkB,CAAC,IAAA,KAA2B;AAClD,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,EAAe;AAC1C,MAAA,MAAM,QAAA,GAAW;AAAA,QACf,KAAA,EAAO,EAAE,KAAA,EAAO,aAAA,EAAe,UAAU,aAAA,EAAc;AAAA,QACvD,IAAA,EAAM,EAAE,KAAA,EAAO,aAAA,EAAe,UAAU,YAAA;AAAa,OACvD;AACA,MAAA,WAAA,CAAY,QAAA,CAAS,IAAI,CAAC,CAAA;AAC1B,MAAA,QAAA,CAAS,EAAE,CAAA;AAAA,IACb;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,iBAAA,GAAoB,CAAC,CAAA,KAA2C;AACpE,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,CAAA,CAAE,MAAA;AAC1B,IAAA,WAAA,CAAY,CAAA,IAAA,MAAS,EAAE,GAAG,IAAA,EAAM,CAAC,IAAI,GAAG,OAAM,CAAE,CAAA;AAChD,IAAA,IAAI,KAAA,WAAgB,EAAE,CAAA;AAAA,EACxB,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,OAAO,CAAA,KAAuB;AACjD,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,UAAA,CAAW,IAAI,CAAA;AAEf,IAAA,OAAA,CAAQ,IAAI,kDAAiC,CAAA;AAE7C,IAAA,IAAI;AAEF,MAAA,IAAI,CAAC,QAAA,CAAS,KAAA,IAAS,CAAC,SAAS,QAAA,EAAU;AACzC,QAAA,OAAA,CAAQ,IAAI,0FAA8B,CAAA;AAC1C,QAAA,QAAA,CAAS,4CAAS,CAAA;AAClB,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,mBAAA,CAAoB,QAAA,CAAS,KAAK,CAAA,EAAG;AACxC,QAAA,OAAA,CAAQ,IAAI,sGAAgC,CAAA;AAC5C,QAAA,QAAA,CAAS,wDAAW,CAAA;AACpB,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,IAAI,0DAAuB,CAAA;AACnC,MAAA,OAAA,CAAQ,IAAI,8DAAA,EAA2B;AAAA,QACrC,OAAO,QAAA,CAAS,KAAA;AAAA,QAChB,QAAA,EAAU;AAAA,OACX,CAAA;AAED,MAAA,OAAA,CAAQ,IAAI,oEAAyC,CAAA;AAGrD,MAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,QAAQ,CAAA;AAEnC,MAAA,OAAA,CAAQ,GAAA,CAAI,oEAAyC,MAAM,CAAA;AAE3D,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,OAAA,CAAQ,IAAI,wFAAsC,CAAA;AAClD,QAAA,OAAA,CAAQ,GAAA,CAAI,gFAAA,EAA8B,MAAA,CAAO,IAAI,CAAA;AAGrD,QAAA,UAAA,CAAW,MAAM;AACf,UAAA,OAAA,CAAQ,IAAI,4DAAiC,CAAA;AAC7C,UAAA,SAAA,EAAU;AACV,UAAA,OAAA,CAAQ,IAAI,2DAAgC,CAAA;AAAA,QAC9C,GAAG,GAAG,CAAA;AAAA,MAER,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,GAAA,CAAI,+CAAA,EAAwB,MAAA,CAAO,OAAO,CAAA;AAClD,QAAA,QAAA,CAAS,MAAA,CAAO,WAAW,0BAAM,CAAA;AAAA,MACnC;AAAA,IACF,SAASG,MAAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,oDAAyBA,MAAK,CAAA;AAC5C,MAAA,QAAA,CAAS,8DAAY,CAAA;AAAA,IACvB,CAAA,SAAE;AACA,MAAA,OAAA,CAAQ,IAAI,oFAAoD,CAAA;AAChE,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAqB,CAAC,CAAA,KAAwB;AAClD,IAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,aAAA,EAAe;AAChC,MAAA,OAAA,EAAQ;AAAA,IACV;AAAA,EACF,CAAA;AAEA,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,OAAA,EAAS,OAAO,IAAA;AAEhC,EAAA,MAAM,+BACJF,uBAAAA,CAAA,cAAAA,uBAAAA,CAAA,QAAA,EAAA,IAAA,kBAEEA,uBAAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,kIAAA;AAAA,MACV,KAAA,EAAO,EAAE,MAAA,EAAQ,CAAA,EAAE;AAAA,MACnB,OAAA,EAAS;AAAA,KAAA;AAAA,oBAGTA,uBAAAA,CAAA,aAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,2FAAA;AAAA,QACV,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,eAAA;AAAgB,OAAA;AAAA,sBAGlCA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,6QAAA;AAAA,UACV,OAAA,EAAS;AAAA,SAAA;AAAA,wBAETA,uBAAAA,CAAA,aAAA,CAACG,aAAAA,EAAA,EAAE,MAAM,EAAA,EAAI;AAAA,OACf;AAAA,sBAGAH,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,WAAU,qDAAA,EAAA,kBACbA,wBAAA,aAAA,CAAC,IAAA,EAAA,EAAG,WAAU,2CAAA,EAAA,EAA4C,0BAAI,mBAC9DA,uBAAAA,CAAA,cAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uBAAA,EAAA,EAAwB,oEAAW,CAClD,CAAA;AAAA,MAGC,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,oBACxBA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDAAA,EAAA,kBACbA,uBAAAA,CAAA,cAAC,GAAA,EAAA,EAAE,SAAA,EAAU,yCAAA,EAAA,EAA0C,wDAAS,CAAA,kBAChEA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,YAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,MAAM,eAAA,CAAgB,OAAO,CAAA;AAAA,UACtC,SAAA,EAAU;AAAA,SAAA;AAAA,QACX;AAAA,OAED,kBACAA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,MAAM,eAAA,CAAgB,MAAM,CAAA;AAAA,UACrC,SAAA,EAAU;AAAA,SAAA;AAAA,QACX;AAAA,OAGH,CACF,CAAA;AAAA,sBAIFA,uBAAAA,CAAA,aAAA,CAAC,UAAK,QAAA,EAAU,YAAA,EAAc,WAAU,KAAA,EAAA,kBAEtCA,uBAAAA,CAAA,aAAA,CAAC,SAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAAC,WAAM,OAAA,EAAQ,OAAA,EAAQ,SAAA,EAAU,gDAAA,EAAA,EAAiD,oBAElF,CAAA,kBACAA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4BAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAACS,oBAAK,IAAA,EAAM,EAAA,EAAI,WAAU,yDAAA,EAA0D,CAAA,kBACpFT,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,OAAA;AAAA,UACH,IAAA,EAAK,OAAA;AAAA,UACL,IAAA,EAAK,KAAA;AAAA,UACL,OAAO,QAAA,CAAS,KAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,sCAAA;AAAA,UACZ,SAAA,EAAU,gSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OAEd,CACF,CAAA,kBAGAA,uBAAAA,CAAA,cAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,wBAAA,aAAA,CAAC,OAAA,EAAA,EAAM,OAAA,EAAQ,UAAA,EAAW,WAAU,gDAAA,EAAA,EAAiD,cAErF,CAAA,kBACAA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAACK,gBAAAA,EAAA,EAAK,MAAM,EAAA,EAAI,SAAA,EAAU,yDAAA,EAA0D,CAAA,kBACpFL,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,UAAA;AAAA,UACH,IAAA,EAAK,UAAA;AAAA,UACL,IAAA,EAAM,eAAe,MAAA,GAAS,UAAA;AAAA,UAC9B,OAAO,QAAA,CAAS,QAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,gCAAA;AAAA,UACZ,SAAA,EAAU,sSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OACZ,kBACAA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,4OAAA;AAAA,UACV,OAAA,EAAS,MAAM,eAAA,CAAgB,CAAC,YAAY,CAAA;AAAA,UAC5C,QAAA,EAAU;AAAA,SAAA;AAAA,QAET,YAAA,mBAAeA,uBAAAA,CAAA,aAAA,CAACM,oBAAA,EAAO,IAAA,EAAM,EAAA,EAAI,CAAA,mBAAKN,uBAAAA,CAAA,aAAA,CAACO,eAAAA,EAAA,EAAI,MAAM,EAAA,EAAI;AAAA,OAE1D,CACF,CAAA,kBAGAP,uBAAAA,CAAA,cAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,MAAM,qBAAA,CAAsB,IAAI,CAAA;AAAA,UACzC,SAAA,EAAU;AAAA,SAAA;AAAA,QACX;AAAA,OAGH,CAAA,EAGC,KAAA,oBACCA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0FAAA,EAAA,EACZ,KACH,CAAA,kBAIFA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,qZAAA;AAAA,UACV,QAAA,EAAU;AAAA,SAAA;AAAA,QAET,UAAU,uBAAA,GAAW;AAAA,SAIvB,kBAAA,oBACCA,uBAAAA,CAAA,aAAA,CAAC,SAAI,SAAA,EAAU,gDAAA,EAAA,kBACbA,uBAAAA,CAAA,cAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gCAA6B,sCAAM,CAAA,kBACnDA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,kBAAA;AAAA,UACT,SAAA,EAAU;AAAA,SAAA;AAAA,QACX;AAAA,OAGH,CAEJ;AAAA;AACF,GACF,kBAGAA,uBAAAA,CAAA,aAAA;AAAA,IAAC,mBAAA;AAAA,IAAA;AAAA,MACC,MAAA,EAAQ,kBAAA;AAAA,MACR,OAAA,EAAS,MAAM,qBAAA,CAAsB,KAAK,CAAA;AAAA,MAC1C,WAAW,MAAM;AACf,QAAA,qBAAA,CAAsB,KAAK,CAAA;AAC3B,QAAA,SAAA,EAAU;AAAA,MACZ;AAAA;AAAA,GAEJ,CAAA;AAIF,EAAA,OAAOQ,qBAAAA,CAAa,YAAA,EAAc,QAAA,CAAS,IAAI,CAAA;AACjD;;;ACtQe,SAAR,SAAA,CAA2B;AAAA,EAChC,QAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,GAAc;AAChB,CAAA,EAAmB;AACjB,EAAA,MAAM,EAAE,eAAA,EAAiB,OAAA,EAAS,WAAA,KAAgB,OAAA,EAAQ;AAC1D,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIZ,gBAAS,KAAK,CAAA;AAE1D,EAAAG,iBAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,IAAW,WAAA,IAAe,CAAC,eAAA,EAAiB;AAC/C,MAAA,iBAAA,CAAkB,IAAI,CAAA;AAAA,IACxB;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,EAAS,WAAA,EAAa,eAAe,CAAC,CAAA;AAG1C,EAAA,MAAM,qBAAqB,MAAM;AAC/B,IAAA,WAAA,EAAY;AACZ,IAAA,iBAAA,CAAkB,KAAK,CAAA;AAAA,EACzB,CAAA;AAGA,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBACEC,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO;AAAA,MACV,OAAA,EAAS,MAAA;AAAA,MACT,UAAA,EAAY,QAAA;AAAA,MACZ,cAAA,EAAgB,QAAA;AAAA,MAChB,SAAA,EAAW,OAAA;AAAA,MACX,KAAA,EAAO,SAAA;AAAA,MACP,aAAA,EAAe,QAAA;AAAA,MACf,GAAA,EAAK;AAAA,KACP,EAAA,kBACEA,uBAAAA,CAAA,aAAA,CAAC,SAAI,KAAA,EAAO;AAAA,MACV,KAAA,EAAO,MAAA;AAAA,MACP,MAAA,EAAQ,MAAA;AAAA,MACR,MAAA,EAAQ,mBAAA;AAAA,MACR,SAAA,EAAW,mBAAA;AAAA,MACX,YAAA,EAAc,KAAA;AAAA,MACd,SAAA,EAAW;AAAA,OACV,CAAA,kBACHA,wBAAA,aAAA,CAAC,KAAA,EAAA,IAAA,EAAI,yCAAS,CAChB,CAAA;AAAA,EAEJ;AAGA,EAAA,IAAI,WAAA,IAAe,CAAC,eAAA,EAAiB;AACnC,IAAA,uBACEA,uBAAAA,CAAA,aAAA,CAAAA,uBAAAA,CAAA,QAAA,EAAA,IAAA,EACG,4BACCA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO;AAAA,MACV,OAAA,EAAS,MAAA;AAAA,MACT,UAAA,EAAY,QAAA;AAAA,MACZ,cAAA,EAAgB,QAAA;AAAA,MAChB,SAAA,EAAW,OAAA;AAAA,MACX,KAAA,EAAO,SAAA;AAAA,MACP,aAAA,EAAe,QAAA;AAAA,MACf,GAAA,EAAK,MAAA;AAAA,MACL,OAAA,EAAS,MAAA;AAAA,MACT,SAAA,EAAW;AAAA,KACb,EAAA,kBACEA,uBAAAA,CAAA,aAAA,CAAC,SAAI,KAAA,EAAO;AAAA,MACV,QAAA,EAAU,MAAA;AAAA,MACV,OAAA,EAAS;AAAA,SACR,WAEH,CAAA,kBACAA,uBAAAA,CAAA,aAAA,CAAC,SAAI,KAAA,EAAO;AAAA,MACV,QAAA,EAAU,MAAA;AAAA,MACV,UAAA,EAAY;AAAA,SACX,8DAEH,CAAA,kBACAA,uBAAAA,CAAA,aAAA,CAAC,SAAI,KAAA,EAAO;AAAA,MACV,QAAA,EAAU,MAAA;AAAA,MACV,OAAA,EAAS;AAAA,KACX,EAAA,EAAG,oEAEH,CACF,CAAA,kBAEFA,uBAAAA,CAAA,aAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAQ,cAAA;AAAA,QACR,OAAA,EAAS,MAAM,iBAAA,CAAkB,KAAK,CAAA;AAAA,QACtC,SAAA,EAAW;AAAA;AAAA,KAEf,CAAA;AAAA,EAEJ;AAGA,EAAA,uBAAOA,uBAAAA,CAAA,aAAA,CAAAA,uBAAAA,CAAA,gBAAG,QAAS,CAAA;AACrB;AC9Fe,SAAR,cAA+B,EAAE,MAAA,EAAQ,OAAA,EAAS,SAAA,EAAW,iBAAgB,EAAuB;AACzG,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,OAAA,EAAQ;AAC7B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIJ,eAAAA,CAAS;AAAA,IACvC,KAAA,EAAO,EAAA;AAAA,IACP,QAAA,EAAU,EAAA;AAAA,IACV,eAAA,EAAiB,EAAA;AAAA,IACjB,IAAA,EAAM;AAAA,GACP,CAAA;AACD,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIA,gBAAS,KAAK,CAAA;AACtD,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAIA,gBAAS,KAAK,CAAA;AACpE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,gBAAS,EAAE,CAAA;AACrC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAG5C,EAAAG,iBAAU,MAAM;AACd,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,iBAAA,GAAoB,CAAC,CAAA,KAA2C;AACpE,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,CAAA,CAAE,MAAA;AAC1B,IAAA,WAAA,CAAY,CAAA,IAAA,MAAS,EAAE,GAAG,IAAA,EAAM,CAAC,IAAI,GAAG,OAAM,CAAE,CAAA;AAChD,IAAA,IAAI,KAAA,WAAgB,EAAE,CAAA;AAAA,EACxB,CAAA;AAEA,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,IAAI,CAAC,SAAS,KAAA,IAAS,CAAC,SAAS,QAAA,IAAY,CAAC,SAAS,eAAA,EAAiB;AACtE,MAAA,QAAA,CAAS,4CAAS,CAAA;AAClB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,CAAC,mBAAA,CAAoB,QAAA,CAAS,KAAK,CAAA,EAAG;AACxC,MAAA,QAAA,CAAS,oEAAa,CAAA;AACtB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,kBAAA,GAAqB,gBAAA,CAAiB,QAAA,CAAS,QAAQ,CAAA;AAC7D,IAAA,IAAI,CAAC,mBAAmB,KAAA,EAAO;AAC7B,MAAA,QAAA,CAAS,kBAAA,CAAmB,WAAW,sCAAQ,CAAA;AAC/C,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAI,QAAA,CAAS,QAAA,KAAa,QAAA,CAAS,eAAA,EAAiB;AAClD,MAAA,QAAA,CAAS,8DAAY,CAAA;AACrB,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,OAAO,CAAA,KAAuB;AACjD,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,UAAA,CAAW,IAAI,CAAA;AAEf,IAAA,IAAI;AACF,MAAA,IAAI,CAAC,cAAa,EAAG;AACnB,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,IAAI,iEAAA,EAA8B;AAAA,QACxC,OAAO,QAAA,CAAS,KAAA;AAAA,QAChB,IAAA,EAAM,SAAS,IAAA,IAAQ,oBAAA;AAAA,QACvB,QAAA,EAAU;AAAA,OACX,CAAA;AAGD,MAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS;AAAA,QAC5B,OAAO,QAAA,CAAS,KAAA;AAAA,QAChB,UAAU,QAAA,CAAS,QAAA;AAAA,QACnB,IAAA,EAAM,SAAS,IAAA,IAAQ,KAAA;AAAA,OACxB,CAAA;AAED,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,OAAA,CAAQ,IAAI,iDAAwB,CAAA;AACpC,QAAA,SAAA,EAAU;AAAA,MACZ,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,GAAA,CAAI,kDAAA,EAA2B,MAAA,CAAO,OAAO,CAAA;AACrD,QAAA,QAAA,CAAS,MAAA,CAAO,WAAW,0BAAM,CAAA;AAAA,MACnC;AAAA,IACF,SAASG,MAAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,uDAA4BA,MAAK,CAAA;AAC/C,MAAA,QAAA,CAAS,8DAAY,CAAA;AAAA,IACvB,CAAA,SAAE;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAqB,CAAC,CAAA,KAAwB;AAClD,IAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,aAAA,EAAe;AAChC,MAAA,OAAA,EAAQ;AAAA,IACV;AAAA,EACF,CAAA;AAEA,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,OAAA,EAAS,OAAO,IAAA;AAEhC,EAAA,MAAM,YAAA,mBACJF,uBAAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,kIAAA;AAAA,MACV,KAAA,EAAO,EAAE,MAAA,EAAQ,CAAA,EAAE;AAAA,MACnB,OAAA,EAAS;AAAA,KAAA;AAAA,oBAETA,uBAAAA,CAAA,aAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,2FAAA;AAAA,QACV,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,eAAA;AAAgB,OAAA;AAAA,sBAGlCA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,6QAAA;AAAA,UACV,OAAA,EAAS;AAAA,SAAA;AAAA,wBAETA,uBAAAA,CAAA,aAAA,CAACG,aAAAA,EAAA,EAAE,MAAM,EAAA,EAAI;AAAA,OACf;AAAA,sBAGAH,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,WAAU,qDAAA,EAAA,kBACbA,wBAAA,aAAA,CAAC,IAAA,EAAA,EAAG,WAAU,2CAAA,EAAA,EAA4C,0BAAI,mBAC9DA,uBAAAA,CAAA,cAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uBAAA,EAAA,EAAwB,oEAAW,CAClD,CAAA;AAAA,sBAGAA,uBAAAA,CAAA,aAAA,CAAC,UAAK,QAAA,EAAU,YAAA,EAAc,WAAU,KAAA,EAAA,kBAEtCA,uBAAAA,CAAA,aAAA,CAAC,SAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAAC,WAAM,OAAA,EAAQ,OAAA,EAAQ,SAAA,EAAU,gDAAA,EAAA,EAAiD,sBAElF,CAAA,kBACAA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,WAAU,4BAAA,EAAA,kBACbA,wBAAA,aAAA,CAACI,iBAAAA,EAAA,EAAM,IAAA,EAAM,EAAA,EAAI,WAAU,yDAAA,EAA0D,CAAA,kBACrFJ,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,OAAA;AAAA,UACH,IAAA,EAAK,OAAA;AAAA,UACL,IAAA,EAAK,KAAA;AAAA,UACL,OAAO,QAAA,CAAS,KAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,sCAAA;AAAA,UACZ,SAAA,EAAU,gSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OAEd,CACF,CAAA,kBAGAA,uBAAAA,CAAA,cAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,wBAAA,aAAA,CAAC,OAAA,EAAA,EAAM,OAAA,EAAQ,MAAA,EAAO,WAAU,gDAAA,EAAA,EAAiD,cAEjF,CAAA,kBACAA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAACS,gBAAAA,EAAA,EAAK,MAAM,EAAA,EAAI,SAAA,EAAU,yDAAA,EAA0D,CAAA,kBACpFT,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,MAAA;AAAA,UACH,IAAA,EAAK,MAAA;AAAA,UACL,IAAA,EAAK,MAAA;AAAA,UACL,OAAO,QAAA,CAAS,IAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,wDAAA;AAAA,UACZ,SAAA,EAAU,gSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OAEd,CACF,CAAA,kBAGAA,uBAAAA,CAAA,cAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,wBAAA,aAAA,CAAC,OAAA,EAAA,EAAM,OAAA,EAAQ,UAAA,EAAW,WAAU,gDAAA,EAAA,EAAiD,gBAErF,CAAA,kBACAA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAACK,gBAAAA,EAAA,EAAK,MAAM,EAAA,EAAI,SAAA,EAAU,yDAAA,EAA0D,CAAA,kBACpFL,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,UAAA;AAAA,UACH,IAAA,EAAK,UAAA;AAAA,UACL,IAAA,EAAM,eAAe,MAAA,GAAS,UAAA;AAAA,UAC9B,OAAO,QAAA,CAAS,QAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,+DAAA;AAAA,UACZ,SAAA,EAAU,sSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OACZ,kBACAA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,4OAAA;AAAA,UACV,OAAA,EAAS,MAAM,eAAA,CAAgB,CAAC,YAAY,CAAA;AAAA,UAC5C,QAAA,EAAU;AAAA,SAAA;AAAA,QAET,YAAA,mBAAeA,uBAAAA,CAAA,aAAA,CAACM,oBAAA,EAAO,IAAA,EAAM,EAAA,EAAI,CAAA,mBAAKN,uBAAAA,CAAA,aAAA,CAACO,eAAAA,EAAA,EAAI,MAAM,EAAA,EAAI;AAAA,OAE1D,CACF,CAAA,kBAGAP,uBAAAA,CAAA,cAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAA,kBACbA,wBAAA,aAAA,CAAC,OAAA,EAAA,EAAM,OAAA,EAAQ,iBAAA,EAAkB,WAAU,gDAAA,EAAA,EAAiD,4BAE5F,CAAA,kBACAA,wBAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAACK,gBAAAA,EAAA,EAAK,MAAM,EAAA,EAAI,SAAA,EAAU,yDAAA,EAA0D,CAAA,kBACpFL,uBAAAA,CAAA,aAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,iBAAA;AAAA,UACH,IAAA,EAAK,iBAAA;AAAA,UACL,IAAA,EAAM,sBAAsB,MAAA,GAAS,UAAA;AAAA,UACrC,OAAO,QAAA,CAAS,eAAA;AAAA,UAChB,QAAA,EAAU,iBAAA;AAAA,UACV,WAAA,EAAY,4CAAA;AAAA,UACZ,SAAA,EAAU,sSAAA;AAAA,UACV,QAAA,EAAU;AAAA;AAAA,OACZ,kBACAA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,4OAAA;AAAA,UACV,OAAA,EAAS,MAAM,sBAAA,CAAuB,CAAC,mBAAmB,CAAA;AAAA,UAC1D,QAAA,EAAU;AAAA,SAAA;AAAA,QAET,mBAAA,mBAAsBA,uBAAAA,CAAA,aAAA,CAACM,oBAAA,EAAO,IAAA,EAAM,EAAA,EAAI,CAAA,mBAAKN,uBAAAA,CAAA,aAAA,CAACO,eAAAA,EAAA,EAAI,MAAM,EAAA,EAAI;AAAA,OAEjE,CACF,CAAA,EAGC,KAAA,oBACCP,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0FAAA,EAAA,EACZ,KACH,CAAA,kBAIFA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,qZAAA;AAAA,UACV,QAAA,EAAU;AAAA,SAAA;AAAA,QAET,UAAU,uBAAA,GAAW;AAAA,SAIvB,eAAA,oBACCA,uBAAAA,CAAA,aAAA,CAAC,SAAI,SAAA,EAAU,gDAAA,EAAA,kBACbA,uBAAAA,CAAA,cAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gCAA6B,gCAAK,CAAA,kBAClDA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,eAAA;AAAA,UACT,SAAA,EAAU;AAAA,SAAA;AAAA,QACX;AAAA,OAGH,CAEJ;AAAA;AACF,GACF;AAIF,EAAA,OAAOQ,qBAAAA,CAAa,YAAA,EAAc,QAAA,CAAS,IAAI,CAAA;AACjD;;;AC9Pe,SAAR,SAA0B,EAAE,eAAA,GAAkB,EAAC,EAAG,WAAU,EAAkB;AACnF,EAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,MAAA,KAAW,OAAA,EAAQ;AAClD,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIZ,gBAAS,KAAK,CAAA;AAC1C,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAC1D,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAGhE,EAAA,MAAM,aAAa,MAAM;AACvB,IAAA,SAAA,CAAU,CAAC,MAAM,CAAA;AAAA,EACnB,CAAA;AAGA,EAAA,MAAM,eAAA,GAAkB,CAAC,CAAA,KAAwB;AAC/C,IAAA,CAAA,CAAE,eAAA,EAAgB;AAAA,EACpB,CAAA;AAGA,EAAA,MAAM,qBAAA,GAAwB,CAAC,IAAA,KAAc;AAC3C,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,6EAAA,EAA4B,IAAA,CAAK,KAAK,CAAA,CAAE,CAAA;AACpD,IAAA,IAAA,CAAK,OAAA,EAAQ;AACb,IAAA,SAAA,CAAU,KAAK,CAAA;AAAA,EACjB,CAAA;AAGA,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,OAAA,CAAQ,IAAI,iEAAuB,CAAA;AACnC,IAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,IAAA,SAAA,CAAU,KAAK,CAAA;AAAA,EACjB,CAAA;AAGA,EAAA,MAAM,iBAAiB,MAAM;AAC3B,IAAA,OAAA,CAAQ,IAAI,iEAAuB,CAAA;AACnC,IAAA,oBAAA,CAAqB,IAAI,CAAA;AACzB,IAAA,SAAA,CAAU,KAAK,CAAA;AAAA,EACjB,CAAA;AAGA,EAAA,MAAM,eAAe,YAAY;AAC/B,IAAA,OAAA,CAAQ,IAAI,6EAAyB,CAAA;AACrC,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,EAAO;AACb,MAAA,OAAA,CAAQ,IAAI,wDAAqB,CAAA;AAAA,IACnC,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,yCAAW,KAAK,CAAA;AAAA,IAChC;AACA,IAAA,SAAA,CAAU,KAAK,CAAA;AAAA,EACjB,CAAA;AAGA,EAAA,MAAM,oBAAoB,MAAM;AAC9B,IAAA,OAAA,CAAQ,IAAI,6EAAyB,CAAA;AACrC,IAAA,OAAA,CAAQ,IAAI,uDAAA,EAA8B;AAAA,MACxC,IAAA,EAAM,OAAO,CAAA,EAAG,IAAA,CAAK,QAAQ,oBAAK,CAAA,EAAA,EAAK,IAAA,CAAK,KAAK,CAAA,CAAA,CAAA,GAAM,IAAA;AAAA,MACvD;AAAA,KACD,CAAA;AAGD,IAAA,iBAAA,CAAkB,KAAK,CAAA;AACvB,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAE1B,IAAA,OAAA,CAAQ,IAAI,2GAAgC,CAAA;AAG5C,IAAA,UAAA,CAAW,MAAM;AACf,MAAA,OAAA,CAAQ,IAAI,4DAAA,EAAyB;AAAA,QACnC,IAAA,EAAM,OAAO,CAAA,EAAG,IAAA,CAAK,QAAQ,oBAAK,CAAA,EAAA,EAAK,IAAA,CAAK,KAAK,CAAA,CAAA,CAAA,GAAM,IAAA;AAAA,QACvD;AAAA,OACD,CAAA;AAAA,IACH,GAAG,GAAG,CAAA;AAAA,EACR,CAAA;AAGA,EAAA,MAAM,yBAAyB,MAAM;AACnC,IAAA,OAAA,CAAQ,IAAI,uEAAwB,CAAA;AACpC,IAAA,iBAAA,CAAkB,KAAK,CAAA;AACvB,IAAA,oBAAA,CAAqB,IAAI,CAAA;AAAA,EAC3B,CAAA;AAGA,EAAA,MAAM,sBAAsB,MAAM;AAChC,IAAA,OAAA,CAAQ,IAAI,uEAAwB,CAAA;AACpC,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,IAAA,iBAAA,CAAkB,IAAI,CAAA;AAAA,EACxB,CAAA;AAGA,EAAA,MAAM,4BAA4B,MAAM;AACtC,IAAA,OAAO,eAAA,CAAgB,OAAO,CAAA,IAAA,KAAQ;AAEpC,MAAA,IAAI,IAAA,CAAK,gBAAgB,IAAA,EAAM;AAC7B,QAAA,OAAO,eAAA;AAAA,MACT;AAEA,MAAA,IAAI,IAAA,CAAK,gBAAgB,KAAA,EAAO;AAC9B,QAAA,OAAO,CAAC,eAAA;AAAA,MACV;AAEA,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH,CAAA;AAGA,EAAAI,uBAAAA,CAAM,UAAU,MAAM;AACpB,IAAA,MAAM,oBAAoB,MAAM;AAC9B,MAAA,SAAA,CAAU,KAAK,CAAA;AAAA,IACjB,CAAA;AAEA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,QAAA,CAAS,gBAAA,CAAiB,SAAS,iBAAiB,CAAA;AAAA,IACtD;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,SAAS,iBAAiB,CAAA;AAAA,IACzD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,MAAM,yBAAyB,yBAAA,EAA0B;AAEzD,EAAA,uBACEA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,yBAAyB,SAAA,IAAa,EAAE,CAAA,CAAA,EAAA,kBAEtDA,uBAAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,oQAAA;AAAA,MACV,OAAA,EAAS;AAAA,KAAA;AAAA,oBAETA,uBAAAA,CAAA,aAAA,CAACS,gBAAAA,EAAA,EAAK,MAAM,EAAA,EAAI,CAAA;AAAA,IACf,eAAA,IAAmB,IAAA,oBAClBT,uBAAAA,CAAA,aAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+DAAA,EAAA,EACb,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,KACrB;AAAA,GAEJ,EAGC,MAAA,oBACCA,uBAAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,4MAAA;AAAA,MACV,OAAA,EAAS;AAAA,KAAA;AAAA,IAER,eAAA,IAAmB,IAAA;AAAA;AAAA,sBAElBA,uBAAAA,CAAA,aAAA,CAAAA,uBAAAA,CAAA,QAAA,EAAA,IAAA,kBACEA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iCAAA,EAAA,kBACbA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2FAAA,EAAA,EACZ,IAAA,CAAK,IAAA,IAAQ,gCAChB,CAAA,kBACAA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6EAAA,EAAA,EACZ,IAAA,CAAK,KACR,CAAA,kBACAA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mCAAA,EAAA,EACZ,IAAA,CAAK,IAAA,KAAS,OAAA,GAAU,oBAAA,GAAQ,0BACnC,CACF,CAAA,EAGC,sBAAA,CAAuB,MAAA,GAAS,CAAA,oBAC/BA,uBAAAA,CAAA,aAAA,CAAAA,uBAAAA,CAAA,QAAA,EAAA,IAAA,kBACEA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EAAyB,CAAA,EACvC,sBAAA,CAAuB,GAAA,CAAI,CAAC,IAAA,KAAS;AACpC,QAAA,MAAM,gBAAgB,IAAA,CAAK,IAAA;AAC3B,QAAA,uBACEA,uBAAAA,CAAA,aAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,KAAK,IAAA,CAAK,EAAA;AAAA,YACV,SAAA,EAAU,+QAAA;AAAA,YACV,OAAA,EAAS,MAAM,qBAAA,CAAsB,IAAI;AAAA,WAAA;AAAA,UAExC,iCAAiBA,uBAAAA,CAAA,aAAA,CAAC,aAAA,EAAA,EAAc,MAAM,EAAA,EAAI,CAAA;AAAA,0BAC3CA,uBAAAA,CAAA,aAAA,CAAC,MAAA,EAAA,IAAA,EAAM,KAAK,KAAM;AAAA,SACpB;AAAA,MAEJ,CAAC,CACH,CAAA,kBAGFA,uBAAAA,CAAA,aAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EAAyB,CAAA,kBAExCA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,yRAAA;AAAA,UACV,OAAA,EAAS;AAAA,SAAA;AAAA,wBAETA,uBAAAA,CAAA,aAAA,CAACU,kBAAA,EAAA,EAAO,MAAM,EAAA,EAAI,CAAA;AAAA,wBAClBV,uBAAAA,CAAA,aAAA,CAAC,MAAA,EAAA,IAAA,EAAK,0BAAI;AAAA,OAEd;AAAA;AAAA;AAAA,sBAGAA,uBAAAA,CAAA,aAAA,CAAAA,uBAAAA,CAAA,QAAA,EAAA,IAAA,kBACEA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,+QAAA;AAAA,UACV,OAAA,EAAS;AAAA,SAAA;AAAA,wBAETA,uBAAAA,CAAA,aAAA,CAACW,iBAAA,EAAA,EAAM,MAAM,EAAA,EAAI,CAAA;AAAA,wBACjBX,uBAAAA,CAAA,aAAA,CAAC,MAAA,EAAA,IAAA,EAAK,cAAE;AAAA,OACV,kBACAA,uBAAAA,CAAA,aAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,+QAAA;AAAA,UACV,OAAA,EAAS;AAAA,SAAA;AAAA,wBAETA,uBAAAA,CAAA,aAAA,CAACS,gBAAAA,EAAA,EAAK,MAAM,EAAA,EAAI,CAAA;AAAA,wBAChBT,uBAAAA,CAAA,aAAA,CAAC,MAAA,EAAA,IAAA,EAAK,cAAE;AAAA,SAIT,sBAAA,CAAuB,MAAA,GAAS,qBAC/BA,uBAAAA,CAAA,cAAAA,uBAAAA,CAAA,QAAA,EAAA,IAAA,kBACEA,uBAAAA,CAAA,aAAA,CAAC,SAAI,SAAA,EAAU,wBAAA,EAAyB,GACvC,sBAAA,CAAuB,GAAA,CAAI,CAAC,IAAA,KAAS;AACpC,QAAA,MAAM,gBAAgB,IAAA,CAAK,IAAA;AAC3B,QAAA,uBACEA,uBAAAA,CAAA,aAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,KAAK,IAAA,CAAK,EAAA;AAAA,YACV,SAAA,EAAU,+QAAA;AAAA,YACV,OAAA,EAAS,MAAM,qBAAA,CAAsB,IAAI;AAAA,WAAA;AAAA,UAExC,iCAAiBA,uBAAAA,CAAA,aAAA,CAAC,aAAA,EAAA,EAAc,MAAM,EAAA,EAAI,CAAA;AAAA,0BAC3CA,uBAAAA,CAAA,aAAA,CAAC,MAAA,EAAA,IAAA,EAAM,KAAK,KAAM;AAAA,SACpB;AAAA,MAEJ,CAAC,CACH,CAEJ;AAAA;AAAA,GAEJ,kBAIFA,uBAAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,MAAA,EAAQ,cAAA;AAAA,MACR,OAAA,EAAS,MAAM,iBAAA,CAAkB,KAAK,CAAA;AAAA,MACtC,SAAA,EAAW,iBAAA;AAAA,MACX,kBAAA,EAAoB;AAAA;AAAA,GACtB,kBAGAA,uBAAAA,CAAA,aAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,MAAA,EAAQ,iBAAA;AAAA,MACR,OAAA,EAAS,MAAM,oBAAA,CAAqB,KAAK,CAAA;AAAA,MACzC,SAAA,EAAW,iBAAA;AAAA,MACX,eAAA,EAAiB;AAAA;AAAA,GAErB,CAAA;AAEJ;;;AC9DO,IAAK,QAAA,qBAAAY,SAAAA,KAAL;AACL,EAAAA,UAAA,MAAA,CAAA,GAAO,MAAA;AACP,EAAAA,UAAA,OAAA,CAAA,GAAQ,OAAA;AAFE,EAAA,OAAAA,SAAAA;AAAA,CAAA,EAAA,QAAA,IAAA,EAAA","file":"index.js","sourcesContent":["'use client';\n\nimport React, { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';\nimport type { User, UseAuthReturn, LoginRequest, RegisterRequest } from '../types';\n\ninterface AuthContextType extends UseAuthReturn {}\n\nconst AuthContext = createContext<AuthContextType | undefined>(undefined);\n\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\n const [user, setUser] = useState<User | null>(null);\n const [loading, setLoading] = useState(true);\n const [isAuthenticated, setIsAuthenticated] = useState(false);\n const isMountedRef = useRef(true);\n\n // 安全的状态更新函数\n const safeSetState = useCallback((updater: () => void) => {\n if (isMountedRef.current) {\n updater();\n }\n }, []);\n\n // 验证会话\n const validateSession = useCallback(async () => {\n console.log('🔍 [AuthContext] 开始验证会话...');\n try {\n const response = await fetch('/api/auth/validate');\n console.log('📡 [AuthContext] 会话验证响应状态:', response.status);\n \n const data = await response.json();\n console.log('📄 [AuthContext] 会话验证响应数据:', data);\n \n safeSetState(() => {\n if (data.valid && data.user) {\n console.log('✅ [AuthContext] 会话验证成功, 用户:', data.user);\n setUser(data.user);\n setIsAuthenticated(true);\n } else {\n console.log('❌ [AuthContext] 会话验证失败:', data.message);\n setUser(null);\n setIsAuthenticated(false);\n }\n setLoading(false);\n });\n } catch (error) {\n console.error('💥 [AuthContext] 会话验证异常:', error);\n safeSetState(() => {\n setUser(null);\n setIsAuthenticated(false);\n setLoading(false);\n });\n }\n }, [safeSetState]);\n\n // 登录\n const login = useCallback(async (credentials: LoginRequest) => {\n console.log('🔑 [AuthContext] 开始登录...');\n console.log('📝 [AuthContext] 登录凭据:', { phone: credentials.phone, password: '***' });\n \n try {\n console.log('📤 [AuthContext] 发送登录请求到 /api/auth/login');\n const response = await fetch('/api/auth/login', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(credentials),\n });\n\n console.log('📡 [AuthContext] 收到响应,状态码:', response.status);\n const data = await response.json();\n console.log('📄 [AuthContext] 响应数据:', data);\n\n if (data.success && data.user) {\n console.log('✅ [AuthContext] 登录成功, 开始更新全局状态');\n console.log('👤 [AuthContext] 用户数据:', data.user);\n \n // 记录当前状态\n console.log('📊 [AuthContext] 更新前状态:', {\n currentUser: user ? `${user.name || '未设置'} (${user.phone})` : null,\n currentIsAuthenticated: isAuthenticated,\n currentLoading: loading\n });\n \n // 使用同步的状态更新确保立即生效\n console.log('🔄 [AuthContext] 执行全局状态更新...');\n safeSetState(() => {\n console.log('🔄 [AuthContext] 正在设置用户:', data.user);\n setUser(data.user);\n console.log('🔄 [AuthContext] 正在设置认证状态: true');\n setIsAuthenticated(true);\n console.log('🔄 [AuthContext] 正在设置加载状态: false');\n setLoading(false);\n console.log('✅ [AuthContext] 全局状态更新完成');\n });\n \n // 等待下一个事件循环后输出确认日志\n setTimeout(() => {\n console.log('🎉 [AuthContext] 延迟确认 - 全局登录状态应该已更新:', {\n user: data.user,\n isAuthenticated: true\n });\n }, 0);\n \n console.log('🚀 [AuthContext] 返回成功结果');\n return { success: true, user: data.user };\n } else {\n console.log('❌ [AuthContext] 登录失败:', data.message);\n return { success: false, message: data.message };\n }\n } catch (error) {\n console.error('💥 [AuthContext] 登录异常:', error);\n return { success: false, message: '登录失败,请稍后重试' };\n }\n }, [safeSetState, user, isAuthenticated, loading]);\n\n // 注册\n const register = useCallback(async (userData: RegisterRequest) => {\n console.log('📝 [AuthContext] 开始注册...');\n try {\n const response = await fetch('/api/auth/register', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(userData),\n });\n\n const data = await response.json();\n console.log('📡 [AuthContext] 注册响应:', data);\n\n if (data.success && data.user) {\n console.log('✅ [AuthContext] 注册成功, 立即更新全局状态');\n \n // 使用同步的状态更新确保立即生效\n safeSetState(() => {\n setUser(data.user);\n setIsAuthenticated(true);\n setLoading(false);\n });\n \n console.log('🚀 [AuthContext] 返回注册成功结果');\n return { success: true, user: data.user };\n } else {\n console.log('❌ [AuthContext] 注册失败:', data.message);\n return { success: false, message: data.message };\n }\n } catch (error) {\n console.error('💥 [AuthContext] 注册异常:', error);\n return { success: false, message: '注册失败,请稍后重试' };\n }\n }, [safeSetState]);\n\n // 登出\n const logout = useCallback(async () => {\n console.log('🚪 [AuthContext] 开始登出...');\n try {\n await fetch('/api/auth/logout', { method: 'POST' });\n safeSetState(() => {\n setUser(null);\n setIsAuthenticated(false);\n });\n console.log('✅ [AuthContext] 登出成功, 全局状态已清除');\n } catch (error) {\n console.error('💥 [AuthContext] 登出失败:', error);\n }\n }, [safeSetState]);\n\n // 刷新用户信息\n const refreshUser = useCallback(() => {\n console.log('🔄 [AuthContext] 刷新用户信息...');\n setLoading(true);\n validateSession();\n }, [validateSession]);\n\n // 组件挂载/卸载管理\n useEffect(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n // 初始化时验证会话\n useEffect(() => {\n console.log('🚀 [AuthContext] 初始化, 开始验证会话');\n validateSession();\n }, [validateSession]);\n\n // 状态变化监控(用于调试)\n useEffect(() => {\n console.log('📊 [AuthContext] 全局状态变化:', {\n isAuthenticated,\n user: user ? `${user.name || '未设置'} (${user.phone})` : null,\n loading\n });\n }, [isAuthenticated, user, loading]);\n\n const value: AuthContextType = {\n user,\n loading,\n isAuthenticated,\n login,\n register,\n logout,\n refreshUser,\n };\n\n return (\n <AuthContext.Provider value={value}>\n {children}\n </AuthContext.Provider>\n );\n}\n\nexport function useAuth(): UseAuthReturn {\n const context = useContext(AuthContext);\n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n} ","import type { User } from '../types';\n\n/**\n * 验证手机号格式\n */\nexport function validatePhoneNumber(phone: string): boolean {\n return /^1[3-9]\\d{9}$/.test(phone);\n}\n\n/**\n * 验证密码强度(可扩展)\n */\nexport function validatePassword(password: string): { valid: boolean; message?: string } {\n if (!password) {\n return { valid: false, message: '密码不能为空' };\n }\n \n if (password.length < 6) {\n return { valid: false, message: '密码长度至少6位' };\n }\n \n return { valid: true };\n}\n\n/**\n * 生成安全的会话令牌\n */\nexport function generateSessionToken(): string {\n // 在实际环境中,应该使用更安全的随机数生成\n return Math.random().toString(36).substring(2) + \n Date.now().toString(36) + \n Math.random().toString(36).substring(2);\n}\n\n/**\n * 检查用户是否为管理员\n */\nexport function isAdmin(user: User | null): boolean {\n return user?.role === 'admin';\n}\n\n/**\n * 检查用户是否处于活跃状态\n */\nexport function isActiveUser(user: User | null): boolean {\n return user?.isActive === true;\n}\n\n/**\n * 格式化用户显示名称\n */\nexport function getUserDisplayName(user: User): string {\n return user.name || user.phone || '未知用户';\n}\n\n/**\n * 计算会话过期时间\n */\nexport function calculateSessionExpiry(days: number = 30): Date {\n return new Date(Date.now() + days * 24 * 60 * 60 * 1000);\n}\n\n/**\n * 检查会话是否过期\n */\nexport function isSessionExpired(expiresAt: Date): boolean {\n return new Date() > new Date(expiresAt);\n} ","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X, Phone, Lock, Eye, EyeOff } from 'lucide-react';\nimport { validatePhoneNumber, validatePassword } from '../utils/authUtils';\nimport type { ForgotPasswordModalProps } from '../types';\n\nexport default function ForgotPasswordModal({ isOpen, onClose, onSuccess }: ForgotPasswordModalProps) {\n const [formData, setFormData] = useState({\n phone: '',\n newPassword: '',\n confirmPassword: '',\n verificationCode: '',\n });\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const [countdown, setCountdown] = useState(0);\n const [mounted, setMounted] = useState(false);\n\n // 确保在客户端渲染\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target;\n setFormData(prev => ({ ...prev, [name]: value }));\n if (error) setError(''); // 清除错误信息\n };\n\n const validateForm = () => {\n if (!formData.phone || !formData.newPassword || !formData.confirmPassword || !formData.verificationCode) {\n setError('请填写完整信息');\n return false;\n }\n\n if (!validatePhoneNumber(formData.phone)) {\n setError('请输入正确的手机号格式');\n return false;\n }\n\n const passwordValidation = validatePassword(formData.newPassword);\n if (!passwordValidation.valid) {\n setError(passwordValidation.message || '密码格式错误');\n return false;\n }\n\n if (formData.newPassword !== formData.confirmPassword) {\n setError('两次输入的密码不一致');\n return false;\n }\n\n if (!/^\\d{6}$/.test(formData.verificationCode)) {\n setError('请输入6位数字验证码');\n return false;\n }\n\n return true;\n };\n\n const handleSendCode = async () => {\n if (!formData.phone) {\n setError('请输入手机号');\n return;\n }\n\n if (!validatePhoneNumber(formData.phone)) {\n setError('请输入正确的手机号格式');\n return;\n }\n\n try {\n setLoading(true);\n setError(''); // 清除之前的错误信息\n \n const response = await fetch('/api/auth/send-verification-code', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ phone: formData.phone }),\n });\n\n const data = await response.json();\n if (data.success) {\n // 开始倒计时\n setCountdown(60);\n const timer = setInterval(() => {\n setCountdown(prev => {\n if (prev <= 1) {\n clearInterval(timer);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n \n // 显示成功提示\n console.log('✅ 验证码发送成功');\n } else {\n setError(data.message || '发送验证码失败');\n }\n } catch (error) {\n console.error('发送验证码异常:', error);\n setError('发送验证码失败,请稍后重试');\n } finally {\n setLoading(false);\n }\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n\n try {\n if (!validateForm()) {\n return;\n }\n\n const response = await fetch('/api/auth/reset-password', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n phone: formData.phone,\n newPassword: formData.newPassword,\n verificationCode: formData.verificationCode,\n }),\n });\n\n const data = await response.json();\n if (data.success) {\n onSuccess();\n } else {\n setError(data.message || '重置密码失败');\n }\n } catch (error) {\n setError('重置密码失败,请稍后重试');\n } finally {\n setLoading(false);\n }\n };\n\n const handleOverlayClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n if (!isOpen || !mounted) return null;\n\n const modalContent = (\n <div \n className=\"fixed top-0 left-0 right-0 bottom-0 w-screen h-screen bg-black/50 backdrop-blur-sm flex items-center justify-center z-[9999] p-4\"\n style={{ margin: 0 }}\n onClick={handleOverlayClick}\n >\n <div \n className=\"bg-white rounded-2xl shadow-xl w-full max-w-[420px] max-h-[90vh] overflow-y-auto relative\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* 关闭按钮 */}\n <button \n className=\"absolute top-5 right-5 bg-transparent border-none text-gray-500 cursor-pointer p-2 rounded-lg transition-all hover:bg-gray-100 hover:text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 min-w-9 min-h-9 flex items-center justify-center\"\n onClick={onClose}\n >\n <X size={20} />\n </button>\n\n {/* 标题 */}\n <div className=\"px-6 pt-6 pb-4 text-center border-b border-gray-100\">\n <h2 className=\"text-2xl font-semibold text-gray-800 mb-2\">重置密码</h2>\n <p className=\"text-gray-500 text-sm\">请输入手机号和验证码重置密码</p>\n </div>\n\n {/* 重置密码表单 */}\n <form onSubmit={handleSubmit} className=\"p-6\">\n {/* 手机号输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"phone\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 手机号\n </label>\n <div className=\"relative flex items-center\">\n <Phone size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"phone\"\n name=\"phone\"\n type=\"tel\"\n value={formData.phone}\n onChange={handleInputChange}\n placeholder=\"请输入手机号\"\n className=\"w-full py-3 px-4 pl-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n </div>\n </div>\n\n {/* 验证码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"verificationCode\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 验证码\n </label>\n <div className=\"relative flex items-center\">\n <input\n id=\"verificationCode\"\n name=\"verificationCode\"\n type=\"text\"\n value={formData.verificationCode}\n onChange={handleInputChange}\n placeholder=\"请输入验证码\"\n className=\"w-full py-3 px-4 pr-28 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n maxLength={6}\n />\n <button\n type=\"button\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 bg-transparent border-none text-blue-500 text-sm font-medium cursor-pointer px-2 py-1 rounded transition-all whitespace-nowrap hover:bg-blue-50 disabled:text-gray-400 disabled:cursor-not-allowed\"\n onClick={handleSendCode}\n disabled={loading || countdown > 0}\n >\n {countdown > 0 ? `${countdown}秒后重试` : '发送验证码'}\n </button>\n </div>\n </div>\n\n {/* 新密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"newPassword\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 新密码\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"newPassword\"\n name=\"newPassword\"\n type={showPassword ? 'text' : 'password'}\n value={formData.newPassword}\n onChange={handleInputChange}\n placeholder=\"请输入新密码\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowPassword(!showPassword)}\n disabled={loading}\n >\n {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 确认密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"confirmPassword\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 确认密码\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type={showConfirmPassword ? 'text' : 'password'}\n value={formData.confirmPassword}\n onChange={handleInputChange}\n placeholder=\"请再次输入新密码\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\n disabled={loading}\n >\n {showConfirmPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 错误信息 */}\n {error && (\n <div className=\"text-red-500 text-sm my-4 p-3 bg-red-50 border border-red-200 rounded-lg leading-relaxed\">\n {error}\n </div>\n )}\n\n {/* 提交按钮 */}\n <button\n type=\"submit\"\n className=\"w-full bg-blue-500 text-white border-none py-3.5 px-6 rounded-lg text-base font-medium cursor-pointer transition-all mt-2 min-h-[52px] hover:bg-blue-600 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-blue-500/30 active:translate-y-0 disabled:bg-gray-400 disabled:cursor-not-allowed disabled:transform-none disabled:shadow-none focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2\"\n disabled={loading}\n >\n {loading ? '提交中...' : '重置密码'}\n </button>\n </form>\n </div>\n </div>\n );\n\n // 使用 Portal 渲染到 body,避免父组件样式影响\n return createPortal(modalContent, document.body);\n}\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X, User, Lock, Eye, EyeOff } from 'lucide-react';\nimport { useAuth } from '../contexts/AuthContext';\nimport { validatePhoneNumber } from '../utils/authUtils';\nimport type { LoginModalProps } from '../types';\nimport ForgotPasswordModal from './ForgotPasswordModal';\n\n/**\n * 登录模态框组件\n * 提供用户登录界面和逻辑\n */\nexport default function LoginModal({ isOpen, onClose, onSuccess, onSwitchToRegister }: LoginModalProps) {\n const { login } = useAuth();\n const [formData, setFormData] = useState({\n phone: '',\n password: '',\n });\n const [showPassword, setShowPassword] = useState(false);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const [showForgotPassword, setShowForgotPassword] = useState(false);\n const [mounted, setMounted] = useState(false);\n\n // 确保在客户端渲染\n useEffect(() => {\n setMounted(true);\n }, []);\n\n // 开发环境快速填充\n const fillDemoAccount = (type: 'admin' | 'user') => {\n if (process.env.NODE_ENV === 'development') {\n const accounts = {\n admin: { phone: '13800138000', password: 'admin123456' },\n user: { phone: '13900139000', password: 'test123456' }\n };\n setFormData(accounts[type]);\n setError('');\n }\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target;\n setFormData(prev => ({ ...prev, [name]: value }));\n if (error) setError(''); // 清除错误信息\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n\n console.log('🔄 [LoginModal] handleSubmit 开始');\n\n try {\n // 前端验证\n if (!formData.phone || !formData.password) {\n console.log('❌ [LoginModal] 前端验证失败: 信息不完整');\n setError('请填写完整信息');\n return;\n }\n\n if (!validatePhoneNumber(formData.phone)) {\n console.log('❌ [LoginModal] 前端验证失败: 手机号格式错误');\n setError('请输入正确的手机号');\n return;\n }\n\n console.log('✅ [LoginModal] 前端验证通过');\n console.log('🔑 [LoginModal] 提交登录表单:', { \n phone: formData.phone, \n password: '***' \n });\n\n console.log('📞 [LoginModal] 准备调用 useAuth.login()...');\n \n // 使用useAuth的login方法\n const result = await login(formData);\n \n console.log('📡 [LoginModal] useAuth.login() 返回结果:', result);\n\n if (result.success) {\n console.log('✅ [LoginModal] 登录成功,准备调用 onSuccess()');\n console.log('👤 [LoginModal] 登录成功的用户信息:', result.user);\n \n // 短暂延迟确保状态已更新\n setTimeout(() => {\n console.log('🎯 [LoginModal] 调用 onSuccess 回调');\n onSuccess();\n console.log('🏁 [LoginModal] onSuccess 调用完成');\n }, 100);\n \n } else {\n console.log('❌ [LoginModal] 登录失败:', result.message);\n setError(result.message || '登录失败');\n }\n } catch (error) {\n console.error('💥 [LoginModal] 登录异常:', error);\n setError('登录失败,请稍后重试');\n } finally {\n console.log('🔚 [LoginModal] handleSubmit 结束,设置 loading = false');\n setLoading(false);\n }\n };\n\n const handleOverlayClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n if (!isOpen || !mounted) return null;\n\n const modalContent = (\n <>\n {/* 遮罩层 */}\n <div \n className=\"fixed top-0 left-0 right-0 bottom-0 w-screen h-screen bg-black/50 backdrop-blur-sm flex items-center justify-center z-[9999] p-4\"\n style={{ margin: 0 }}\n onClick={handleOverlayClick}\n >\n {/* 模态框主体 */}\n <div \n className=\"bg-white rounded-2xl shadow-xl w-full max-w-[420px] max-h-[90vh] overflow-y-auto relative\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* 关闭按钮 */}\n <button \n className=\"absolute top-5 right-5 bg-transparent border-none text-gray-500 cursor-pointer p-2 rounded-lg transition-all hover:bg-gray-100 hover:text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 min-w-9 min-h-9 flex items-center justify-center\"\n onClick={onClose}\n >\n <X size={20} />\n </button>\n\n {/* 标题 */}\n <div className=\"px-6 pt-6 pb-4 text-center border-b border-gray-100\">\n <h2 className=\"text-2xl font-semibold text-gray-800 mb-2\">用户登录</h2>\n <p className=\"text-gray-500 text-sm\">请输入您的手机号和密码</p>\n </div>\n\n {/* 开发环境快捷登录 */}\n {process.env.NODE_ENV === 'development' && (\n <div className=\"px-6 py-4 bg-amber-50 border-b border-gray-100\">\n <p className=\"text-xs text-amber-800 font-medium mb-2\">开发环境快捷登录:</p>\n <div className=\"flex gap-2\">\n <button \n type=\"button\" \n onClick={() => fillDemoAccount('admin')} \n className=\"px-3 py-1.5 text-xs bg-amber-400 text-amber-900 border-none rounded-md cursor-pointer transition-all font-medium hover:bg-amber-500\"\n >\n 管理员账号\n </button>\n <button \n type=\"button\" \n onClick={() => fillDemoAccount('user')} \n className=\"px-3 py-1.5 text-xs bg-amber-400 text-amber-900 border-none rounded-md cursor-pointer transition-all font-medium hover:bg-amber-500\"\n >\n 用户账号\n </button>\n </div>\n </div>\n )}\n\n {/* 登录表单 */}\n <form onSubmit={handleSubmit} className=\"p-6\">\n {/* 手机号输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"phone\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 手机号\n </label>\n <div className=\"relative flex items-center\">\n <User size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"phone\"\n name=\"phone\"\n type=\"tel\"\n value={formData.phone}\n onChange={handleInputChange}\n placeholder=\"请输入手机号\"\n className=\"w-full py-3 px-4 pl-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n </div>\n </div>\n\n {/* 密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"password\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 密码\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"password\"\n name=\"password\"\n type={showPassword ? 'text' : 'password'}\n value={formData.password}\n onChange={handleInputChange}\n placeholder=\"请输入密码\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowPassword(!showPassword)}\n disabled={loading}\n >\n {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 忘记密码链接 */}\n <div className=\"text-right -mt-2 mb-4\">\n <button\n type=\"button\"\n onClick={() => setShowForgotPassword(true)}\n className=\"bg-transparent border-none text-blue-500 cursor-pointer text-sm font-medium underline px-1 py-0.5 rounded transition-all hover:text-blue-600 hover:bg-blue-50 hover:no-underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n 忘记密码?\n </button>\n </div>\n\n {/* 错误信息 */}\n {error && (\n <div className=\"text-red-500 text-sm my-4 p-3 bg-red-50 border border-red-200 rounded-lg leading-relaxed\">\n {error}\n </div>\n )}\n\n {/* 提交按钮 */}\n <button\n type=\"submit\"\n className=\"w-full bg-blue-500 text-white border-none py-3.5 px-6 rounded-lg text-base font-medium cursor-pointer transition-all mt-2 min-h-[52px] hover:bg-blue-600 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-blue-500/30 active:translate-y-0 disabled:bg-gray-400 disabled:cursor-not-allowed disabled:transform-none disabled:shadow-none focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2\"\n disabled={loading}\n >\n {loading ? '登录中...' : '登录'}\n </button>\n\n {/* 注册链接 */}\n {onSwitchToRegister && (\n <div className=\"text-center mt-5 pt-4 border-t border-gray-100\">\n <span className=\"text-gray-500 text-sm mr-1\">还没有账号?</span>\n <button \n type=\"button\" \n onClick={onSwitchToRegister} \n className=\"bg-transparent border-none text-blue-500 cursor-pointer text-sm font-medium underline px-1 py-0.5 rounded transition-all hover:text-blue-600 hover:bg-blue-50 hover:no-underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n 立即注册\n </button>\n </div>\n )}\n </form>\n </div>\n </div>\n\n {/* 忘记密码模态框 */}\n <ForgotPasswordModal\n isOpen={showForgotPassword}\n onClose={() => setShowForgotPassword(false)}\n onSuccess={() => {\n setShowForgotPassword(false);\n onSuccess();\n }}\n />\n </>\n );\n\n // 使用 Portal 渲染到 body,避免父组件样式影响\n return createPortal(modalContent, document.body);\n}\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { useAuth } from '../contexts/AuthContext';\nimport LoginModal from './LoginModal';\nimport type { AuthGuardProps } from '../types';\n\n/**\n * 认证守卫组件\n * 保护需要登录的页面和组件\n */\nexport default function AuthGuard({ \n children, \n fallback,\n requireAuth = true \n}: AuthGuardProps) {\n const { isAuthenticated, loading, refreshUser } = useAuth();\n const [showLoginModal, setShowLoginModal] = useState(false);\n\n useEffect(() => {\n if (!loading && requireAuth && !isAuthenticated) {\n setShowLoginModal(true);\n }\n }, [loading, requireAuth, isAuthenticated]);\n\n // 登录成功后的处理\n const handleLoginSuccess = () => {\n refreshUser();\n setShowLoginModal(false);\n };\n\n // 如果正在加载,显示加载状态\n if (loading) {\n return (\n <div style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '200px',\n color: '#6b7280',\n flexDirection: 'column',\n gap: '12px'\n }}>\n <div style={{\n width: '32px',\n height: '32px',\n border: '3px solid #e5e7eb',\n borderTop: '3px solid #3b82f6',\n borderRadius: '50%',\n animation: 'spin 1s linear infinite'\n }}></div>\n <div>验证登录状态...</div>\n </div>\n );\n }\n\n // 如果需要认证但未登录,显示登录模态框\n if (requireAuth && !isAuthenticated) {\n return (\n <>\n {fallback || (\n <div style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '200px',\n color: '#6b7280',\n flexDirection: 'column',\n gap: '16px',\n padding: '24px',\n textAlign: 'center'\n }}>\n <div style={{\n fontSize: '48px',\n opacity: 0.5\n }}>\n 🔒\n </div>\n <div style={{\n fontSize: '18px',\n fontWeight: '500'\n }}>\n 请先登录以访问此页面\n </div>\n <div style={{\n fontSize: '14px',\n opacity: 0.7\n }}>\n 登录后即可查看相关内容\n </div>\n </div>\n )}\n <LoginModal\n isOpen={showLoginModal}\n onClose={() => setShowLoginModal(false)}\n onSuccess={handleLoginSuccess}\n />\n </>\n );\n }\n\n // 已认证或不需要认证,显示子组件\n return <>{children}</>;\n} ","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X, User, Lock, Phone, Eye, EyeOff } from 'lucide-react';\nimport { useAuth } from '../contexts/AuthContext';\nimport { validatePhoneNumber, validatePassword } from '../utils/authUtils';\nimport type { RegisterModalProps } from '../types';\n\nexport default function RegisterModal({ isOpen, onClose, onSuccess, onSwitchToLogin }: RegisterModalProps) {\n const { register } = useAuth();\n const [formData, setFormData] = useState({\n phone: '',\n password: '',\n confirmPassword: '',\n name: '',\n });\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const [mounted, setMounted] = useState(false);\n\n // 确保在客户端渲染\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target;\n setFormData(prev => ({ ...prev, [name]: value }));\n if (error) setError(''); // 清除错误信息\n };\n\n const validateForm = () => {\n if (!formData.phone || !formData.password || !formData.confirmPassword) {\n setError('请填写必要信息');\n return false;\n }\n\n if (!validatePhoneNumber(formData.phone)) {\n setError('请输入正确的手机号格式');\n return false;\n }\n\n const passwordValidation = validatePassword(formData.password);\n if (!passwordValidation.valid) {\n setError(passwordValidation.message || '密码格式错误');\n return false;\n }\n\n if (formData.password !== formData.confirmPassword) {\n setError('两次输入的密码不一致');\n return false;\n }\n\n return true;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n\n try {\n if (!validateForm()) {\n return;\n }\n\n console.log('📝 [RegisterModal] 提交注册表单:', { \n phone: formData.phone, \n name: formData.name || '未设置',\n password: '***' \n });\n\n // 使用useAuth的register方法\n const result = await register({\n phone: formData.phone,\n password: formData.password,\n name: formData.name || undefined,\n });\n\n if (result.success) {\n console.log('✅ [RegisterModal] 注册成功');\n onSuccess();\n } else {\n console.log('❌ [RegisterModal] 注册失败:', result.message);\n setError(result.message || '注册失败');\n }\n } catch (error) {\n console.error('💥 [RegisterModal] 注册异常:', error);\n setError('注册失败,请稍后重试');\n } finally {\n setLoading(false);\n }\n };\n\n const handleOverlayClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n if (!isOpen || !mounted) return null;\n\n const modalContent = (\n <div \n className=\"fixed top-0 left-0 right-0 bottom-0 w-screen h-screen bg-black/50 backdrop-blur-sm flex items-center justify-center z-[9999] p-4\"\n style={{ margin: 0 }}\n onClick={handleOverlayClick}\n >\n <div \n className=\"bg-white rounded-2xl shadow-xl w-full max-w-[420px] max-h-[90vh] overflow-y-auto relative\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* 关闭按钮 */}\n <button \n className=\"absolute top-5 right-5 bg-transparent border-none text-gray-500 cursor-pointer p-2 rounded-lg transition-all hover:bg-gray-100 hover:text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 min-w-9 min-h-9 flex items-center justify-center\"\n onClick={onClose}\n >\n <X size={20} />\n </button>\n\n {/* 标题 */}\n <div className=\"px-6 pt-6 pb-4 text-center border-b border-gray-100\">\n <h2 className=\"text-2xl font-semibold text-gray-800 mb-2\">用户注册</h2>\n <p className=\"text-gray-500 text-sm\">请填写以下信息创建账户</p>\n </div>\n\n {/* 注册表单 */}\n <form onSubmit={handleSubmit} className=\"p-6\">\n {/* 手机号输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"phone\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 手机号 *\n </label>\n <div className=\"relative flex items-center\">\n <Phone size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"phone\"\n name=\"phone\"\n type=\"tel\"\n value={formData.phone}\n onChange={handleInputChange}\n placeholder=\"请输入手机号\"\n className=\"w-full py-3 px-4 pl-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n </div>\n </div>\n\n {/* 姓名输入(可选) */}\n <div className=\"mb-5\">\n <label htmlFor=\"name\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 姓名\n </label>\n <div className=\"relative flex items-center\">\n <User size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"name\"\n name=\"name\"\n type=\"text\"\n value={formData.name}\n onChange={handleInputChange}\n placeholder=\"请输入姓名(可选)\"\n className=\"w-full py-3 px-4 pl-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n </div>\n </div>\n\n {/* 密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"password\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 密码 *\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"password\"\n name=\"password\"\n type={showPassword ? 'text' : 'password'}\n value={formData.password}\n onChange={handleInputChange}\n placeholder=\"请输入密码(至少6位)\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowPassword(!showPassword)}\n disabled={loading}\n >\n {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 确认密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"confirmPassword\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 确认密码 *\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type={showConfirmPassword ? 'text' : 'password'}\n value={formData.confirmPassword}\n onChange={handleInputChange}\n placeholder=\"请再次输入密码\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\n disabled={loading}\n >\n {showConfirmPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 错误信息 */}\n {error && (\n <div className=\"text-red-500 text-sm my-4 p-3 bg-red-50 border border-red-200 rounded-lg leading-relaxed\">\n {error}\n </div>\n )}\n\n {/* 提交按钮 */}\n <button\n type=\"submit\"\n className=\"w-full bg-blue-500 text-white border-none py-3.5 px-6 rounded-lg text-base font-medium cursor-pointer transition-all mt-2 min-h-[52px] hover:bg-blue-600 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-blue-500/30 active:translate-y-0 disabled:bg-gray-400 disabled:cursor-not-allowed disabled:transform-none disabled:shadow-none focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2\"\n disabled={loading}\n >\n {loading ? '注册中...' : '注册'}\n </button>\n\n {/* 登录链接 */}\n {onSwitchToLogin && (\n <div className=\"text-center mt-5 pt-4 border-t border-gray-100\">\n <span className=\"text-gray-500 text-sm mr-1\">已有账号?</span>\n <button \n type=\"button\" \n onClick={onSwitchToLogin} \n className=\"bg-transparent border-none text-blue-500 cursor-pointer text-sm font-medium underline px-1 py-0.5 rounded transition-all hover:text-blue-600 hover:bg-blue-50 hover:no-underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n 立即登录\n </button>\n </div>\n )}\n </form>\n </div>\n </div>\n );\n\n // 使用 Portal 渲染到 body,避免父组件样式影响\n return createPortal(modalContent, document.body);\n}\n","'use client';\n\nimport React, { useState } from 'react';\nimport { LogOut, LogIn, User } from 'lucide-react';\nimport { useAuth } from '../contexts/AuthContext';\nimport LoginModal from './LoginModal';\nimport RegisterModal from './RegisterModal';\nimport type { UserMenuProps } from '../types';\n\nexport default function UserMenu({ customMenuItems = [], className }: UserMenuProps) {\n const { user, isAuthenticated, logout } = useAuth();\n const [isOpen, setIsOpen] = useState(false);\n const [showLoginModal, setShowLoginModal] = useState(false);\n const [showRegisterModal, setShowRegisterModal] = useState(false);\n\n // 切换菜单显示\n const toggleMenu = () => {\n setIsOpen(!isOpen);\n };\n\n // 点击菜单外部时关闭菜单\n const handleMenuClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n };\n\n // 处理自定义菜单项点击\n const handleCustomMenuClick = (item: any) => {\n console.log(`🔧 [UserMenu] 自定义菜单项被点击: ${item.label}`);\n item.onClick();\n setIsOpen(false);\n };\n\n // 处理登录\n const handleLogin = () => {\n console.log('🔑 [UserMenu] 登录按钮被点击');\n setShowLoginModal(true);\n setIsOpen(false);\n };\n\n // 处理注册\n const handleRegister = () => {\n console.log('📝 [UserMenu] 注册按钮被点击');\n setShowRegisterModal(true);\n setIsOpen(false);\n };\n\n // 处理退出登录\n const handleLogout = async () => {\n console.log('🚪 [UserMenu] 退出登录按钮被点击');\n try {\n await logout();\n console.log('✅ [UserMenu] 退出登录成功');\n } catch (error) {\n console.error('退出登录失败:', error);\n }\n setIsOpen(false);\n };\n\n // 登录成功后的处理\n const handleAuthSuccess = () => {\n console.log('🎉 [UserMenu] 认证成功回调被调用');\n console.log('👤 [UserMenu] 当前useAuth状态:', {\n user: user ? `${user.name || '未设置'} (${user.phone})` : null,\n isAuthenticated\n });\n \n // useAuth hook会自动更新状态,这里不需要手动处理\n setShowLoginModal(false);\n setShowRegisterModal(false);\n \n console.log('✅ [UserMenu] 认证成功处理完成 - 模态框已关闭');\n \n // 延迟检查状态\n setTimeout(() => {\n console.log('🔍 [UserMenu] 延迟状态检查:', {\n user: user ? `${user.name || '未设置'} (${user.phone})` : null,\n isAuthenticated\n });\n }, 500);\n };\n\n // 从登录切换到注册\n const handleSwitchToRegister = () => {\n console.log('🔄 [UserMenu] 从登录切换到注册');\n setShowLoginModal(false);\n setShowRegisterModal(true);\n };\n\n // 从注册切换到登录\n const handleSwitchToLogin = () => {\n console.log('🔄 [UserMenu] 从注册切换到登录');\n setShowRegisterModal(false);\n setShowLoginModal(true);\n };\n\n // 过滤自定义菜单项:根据登录状态和requireAuth属性\n const getVisibleCustomMenuItems = () => {\n return customMenuItems.filter(item => {\n // 如果设置了requireAuth为true,只有登录后才显示\n if (item.requireAuth === true) {\n return isAuthenticated;\n }\n // 如果设置了requireAuth为false,只有未登录才显示\n if (item.requireAuth === false) {\n return !isAuthenticated;\n }\n // 如果没有设置requireAuth,总是显示\n return true;\n });\n };\n\n // 全局点击处理(关闭菜单)\n React.useEffect(() => {\n const handleGlobalClick = () => {\n setIsOpen(false);\n };\n\n if (isOpen) {\n document.addEventListener('click', handleGlobalClick);\n }\n\n return () => {\n document.removeEventListener('click', handleGlobalClick);\n };\n }, [isOpen]);\n\n const visibleCustomMenuItems = getVisibleCustomMenuItems();\n\n return (\n <div className={`relative inline-block ${className || ''}`}>\n {/* 用户头像/图标 */}\n <button \n className=\"flex items-center gap-2 px-3 py-2 bg-slate-50 text-slate-500 border border-slate-200 rounded-lg cursor-pointer transition-all min-w-11 min-h-11 text-sm font-medium hover:bg-slate-200 hover:text-slate-800 focus:outline-none focus:ring-2 focus:ring-blue-500/10\"\n onClick={toggleMenu}\n >\n <User size={24} />\n {isAuthenticated && user && (\n <span className=\"max-w-[120px] overflow-hidden text-ellipsis whitespace-nowrap\">\n {user.name || user.phone}\n </span>\n )}\n </button>\n\n {/* 下拉菜单 */}\n {isOpen && (\n <div \n className=\"absolute top-[calc(100%+0.5rem)] right-0 z-[1000] min-w-[200px] bg-white border border-slate-200 rounded-xl shadow-lg max-h-[90vh] overflow-y-auto p-2 animate-in slide-in-from-top-2 fade-in duration-200\"\n onClick={handleMenuClick}\n >\n {isAuthenticated && user ? (\n // 已登录状态的菜单\n <>\n <div className=\"p-3 mb-2 bg-slate-50 rounded-lg\">\n <div className=\"text-sm font-semibold text-slate-800 mb-1 overflow-hidden text-ellipsis whitespace-nowrap\">\n {user.name || '未设置名称'}\n </div>\n <div className=\"text-xs text-slate-500 mb-1 overflow-hidden text-ellipsis whitespace-nowrap\">\n {user.phone}\n </div>\n <div className=\"text-xs text-blue-500 font-medium\">\n {user.role === 'admin' ? '管理员' : '普通用户'}\n </div>\n </div>\n \n {/* 自定义菜单项 */}\n {visibleCustomMenuItems.length > 0 && (\n <>\n <div className=\"h-px bg-slate-200 my-2\"></div>\n {visibleCustomMenuItems.map((item) => {\n const IconComponent = item.icon;\n return (\n <button \n key={item.id}\n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-slate-100 hover:text-slate-800 focus:outline-none focus:bg-slate-100 focus:ring-2 focus:ring-blue-500/10\"\n onClick={() => handleCustomMenuClick(item)}\n >\n {IconComponent && <IconComponent size={16} />}\n <span>{item.label}</span>\n </button>\n );\n })}\n </>\n )}\n \n <div className=\"h-px bg-slate-200 my-2\"></div>\n \n <button \n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-red-50 hover:text-red-600 focus:outline-none focus:bg-red-50 focus:text-red-600 focus:ring-2 focus:ring-red-500/10\"\n onClick={handleLogout}\n >\n <LogOut size={16} />\n <span>退出登录</span>\n </button>\n </>\n ) : (\n // 未登录状态的菜单\n <>\n <button \n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-slate-100 hover:text-slate-800 focus:outline-none focus:bg-slate-100 focus:ring-2 focus:ring-blue-500/10\"\n onClick={handleLogin}\n >\n <LogIn size={16} />\n <span>登录</span>\n </button>\n <button \n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-slate-100 hover:text-slate-800 focus:outline-none focus:bg-slate-100 focus:ring-2 focus:ring-blue-500/10\"\n onClick={handleRegister}\n >\n <User size={16} />\n <span>注册</span>\n </button>\n \n {/* 未登录状态的自定义菜单项 */}\n {visibleCustomMenuItems.length > 0 && (\n <>\n <div className=\"h-px bg-slate-200 my-2\"></div>\n {visibleCustomMenuItems.map((item) => {\n const IconComponent = item.icon;\n return (\n <button \n key={item.id}\n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-slate-100 hover:text-slate-800 focus:outline-none focus:bg-slate-100 focus:ring-2 focus:ring-blue-500/10\"\n onClick={() => handleCustomMenuClick(item)}\n >\n {IconComponent && <IconComponent size={16} />}\n <span>{item.label}</span>\n </button>\n );\n })}\n </>\n )}\n </>\n )}\n </div>\n )}\n\n {/* 登录模态框 */}\n <LoginModal\n isOpen={showLoginModal}\n onClose={() => setShowLoginModal(false)}\n onSuccess={handleAuthSuccess}\n onSwitchToRegister={handleSwitchToRegister}\n />\n\n {/* 注册模态框 */}\n <RegisterModal\n isOpen={showRegisterModal}\n onClose={() => setShowRegisterModal(false)}\n onSuccess={handleAuthSuccess}\n onSwitchToLogin={handleSwitchToLogin}\n />\n </div>\n );\n}\n","// ===== 用户相关类型 =====\n\n/**\n * 用户信息接口\n */\nexport interface User {\n id: number;\n phone: string;\n name?: string | null;\n email?: string | null;\n role: string;\n isActive: boolean;\n lastLoginAt?: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * 用户会话接口\n */\nexport interface UserSession {\n id: number;\n userId: number;\n sessionToken: string;\n expiresAt: Date;\n createdAt: Date;\n}\n\n// ===== 请求/响应类型 =====\n\n/**\n * 登录请求接口\n */\nexport interface LoginRequest {\n phone: string;\n password: string;\n}\n\n/**\n * 注册请求接口\n */\nexport interface RegisterRequest {\n phone: string;\n password: string;\n name?: string;\n}\n\n/**\n * 登录响应接口\n */\nexport interface LoginResponse {\n success: boolean;\n message: string;\n user?: User;\n sessionToken?: string;\n}\n\n/**\n * 注册响应接口\n */\nexport interface RegisterResponse {\n success: boolean;\n message: string;\n user?: User;\n sessionToken?: string;\n}\n\n/**\n * 会话验证响应接口\n */\nexport interface SessionValidationResponse {\n valid: boolean;\n user?: User;\n message?: string;\n}\n\n/**\n * 会话验证结果接口\n */\nexport interface SessionValidation {\n valid: boolean;\n user?: User;\n}\n\n// ===== 组件Props类型 =====\n\n/**\n * 登录模态框Props\n */\nexport interface LoginModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess: () => void;\n onSwitchToRegister?: () => void;\n}\n\n/**\n * 注册模态框Props\n */\nexport interface RegisterModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess: () => void;\n onSwitchToLogin?: () => void;\n}\n\n/**\n * 认证守卫Props\n */\nexport interface AuthGuardProps {\n children: React.ReactNode;\n fallback?: React.ReactNode;\n requireAuth?: boolean;\n}\n\n/**\n * 自定义菜单项接口\n */\nexport interface CustomMenuItem {\n id: string;\n label: string;\n icon?: React.ComponentType<any>;\n onClick: () => void;\n requireAuth?: boolean; // 是否需要登录才显示\n}\n\n/**\n * 用户菜单Props\n */\nexport interface UserMenuProps {\n customMenuItems?: CustomMenuItem[]; // 自定义菜单项\n className?: string; // 自定义样式类名\n}\n\n/**\n * 忘记密码模态框Props\n */\nexport interface ForgotPasswordModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess: () => void;\n}\n\n// ===== Hook返回类型 =====\n\n/**\n * useAuth Hook返回值类型\n */\nexport interface UseAuthReturn {\n user: User | null;\n loading: boolean;\n isAuthenticated: boolean;\n login: (credentials: LoginRequest) => Promise<{ success: boolean; user?: User; message?: string }>;\n register: (userData: RegisterRequest) => Promise<{ success: boolean; user?: User; message?: string }>;\n logout: () => Promise<void>;\n refreshUser: () => void;\n}\n\n// ===== 服务相关类型 =====\n\n/**\n * 认证服务接口\n */\nexport interface AuthService {\n verifyPassword(phone: string, password: string): Promise<User | null>;\n createUser(phone: string, password: string, name?: string): Promise<User>;\n createSession(userId: number): Promise<UserSession>;\n validateSession(sessionToken: string): Promise<SessionValidation>;\n deleteSession(sessionToken: string): Promise<void>;\n deleteUserSessions(userId: number): Promise<void>;\n updateLastLogin(userId: number): Promise<void>;\n cleanupExpiredSessions(): Promise<void>;\n getUserByPhone(phone: string): Promise<User | null>;\n sendVerificationCode(phone: string): Promise<string>;\n verifyCode(phone: string, code: string): Promise<boolean>;\n resetPassword(phone: string, newPassword: string): Promise<void>;\n cleanupExpiredVerificationCodes(): Promise<void>;\n}\n\n// ===== 工具函数类型 =====\n\n/**\n * API权限验证函数类型\n */\nexport type ValidateApiAuth = (request: Request) => Promise<User | null>;\n\n// ===== 常量类型 =====\n\n/**\n * 用户角色枚举\n */\nexport enum UserRole {\n USER = 'user',\n ADMIN = 'admin'\n}\n\n/**\n * 会话配置\n */\nexport interface SessionConfig {\n maxAge: number; // 会话最大存活时间(秒)\n cookieName: string; // Cookie名称\n secure: boolean; // 是否使用安全Cookie\n httpOnly: boolean; // 是否仅HTTP访问\n sameSite: 'strict' | 'lax' | 'none'; // SameSite策略\n} "]}
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/legacy/contexts/AuthContext.tsx","../../../src/auth/legacy/utils/authUtils.ts","../../../src/auth/legacy/components/ForgotPasswordModal.tsx","../../../src/auth/legacy/components/LoginModal.tsx","../../../src/auth/legacy/components/AuthGuard.tsx","../../../src/auth/legacy/components/RegisterModal.tsx","../../../src/auth/legacy/components/UserMenu.tsx","../../../src/auth/legacy/types/index.ts"],"names":["createContext","useState","useRef","useCallback","useEffect","React","useContext","error","X","Phone","Lock","EyeOff","Eye","createPortal","User","LogOut","LogIn","UserRole"],"mappings":"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","file":"index.js","sourcesContent":["'use client';\n\nimport React, { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';\nimport type { User, UseAuthReturn, LoginRequest, RegisterRequest } from '../types';\n\ninterface AuthContextType extends UseAuthReturn {}\n\nconst AuthContext = createContext<AuthContextType | undefined>(undefined);\n\nfunction extractUser(data: any): User | null {\n return data?.user ?? data?.data?.user ?? null;\n}\n\nfunction extractValid(data: any): boolean {\n if (typeof data?.valid === 'boolean') return data.valid;\n if (typeof data?.data?.valid === 'boolean') return data.data.valid;\n return false;\n}\n\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\n const [user, setUser] = useState<User | null>(null);\n const [loading, setLoading] = useState(true);\n const [isAuthenticated, setIsAuthenticated] = useState(false);\n const isMountedRef = useRef(true);\n\n // 安全的状态更新函数\n const safeSetState = useCallback((updater: () => void) => {\n if (isMountedRef.current) {\n updater();\n }\n }, []);\n\n // 验证会话\n const validateSession = useCallback(async () => {\n console.log('🔍 [AuthContext] 开始验证会话...');\n try {\n const response = await fetch('/api/auth/validate');\n console.log('📡 [AuthContext] 会话验证响应状态:', response.status);\n \n const data = await response.json();\n console.log('📄 [AuthContext] 会话验证响应数据:', data);\n const resolvedUser = extractUser(data);\n const resolvedValid = extractValid(data);\n \n safeSetState(() => {\n if (resolvedValid && resolvedUser) {\n console.log('✅ [AuthContext] 会话验证成功, 用户:', resolvedUser);\n setUser(resolvedUser);\n setIsAuthenticated(true);\n } else {\n console.log('❌ [AuthContext] 会话验证失败:', data.message);\n setUser(null);\n setIsAuthenticated(false);\n }\n setLoading(false);\n });\n } catch (error) {\n console.error('💥 [AuthContext] 会话验证异常:', error);\n safeSetState(() => {\n setUser(null);\n setIsAuthenticated(false);\n setLoading(false);\n });\n }\n }, [safeSetState]);\n\n // 登录\n const login = useCallback(async (credentials: LoginRequest) => {\n console.log('🔑 [AuthContext] 开始登录...');\n console.log('📝 [AuthContext] 登录凭据:', { phone: credentials.phone, password: '***' });\n \n try {\n console.log('📤 [AuthContext] 发送登录请求到 /api/auth/login');\n const response = await fetch('/api/auth/login', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(credentials),\n });\n\n console.log('📡 [AuthContext] 收到响应,状态码:', response.status);\n const data = await response.json();\n console.log('📄 [AuthContext] 响应数据:', data);\n const resolvedUser = extractUser(data);\n\n if (data.success && resolvedUser) {\n console.log('✅ [AuthContext] 登录成功, 开始更新全局状态');\n console.log('👤 [AuthContext] 用户数据:', resolvedUser);\n \n // 记录当前状态\n console.log('📊 [AuthContext] 更新前状态:', {\n currentUser: user ? `${user.name || '未设置'} (${user.phone})` : null,\n currentIsAuthenticated: isAuthenticated,\n currentLoading: loading\n });\n \n // 使用同步的状态更新确保立即生效\n console.log('🔄 [AuthContext] 执行全局状态更新...');\n safeSetState(() => {\n console.log('🔄 [AuthContext] 正在设置用户:', resolvedUser);\n setUser(resolvedUser);\n console.log('🔄 [AuthContext] 正在设置认证状态: true');\n setIsAuthenticated(true);\n console.log('🔄 [AuthContext] 正在设置加载状态: false');\n setLoading(false);\n console.log('✅ [AuthContext] 全局状态更新完成');\n });\n \n // 等待下一个事件循环后输出确认日志\n setTimeout(() => {\n console.log('🎉 [AuthContext] 延迟确认 - 全局登录状态应该已更新:', {\n user: resolvedUser,\n isAuthenticated: true\n });\n }, 0);\n \n console.log('🚀 [AuthContext] 返回成功结果');\n return { success: true, user: resolvedUser };\n } else {\n console.log('❌ [AuthContext] 登录失败:', data.message);\n return { success: false, message: data.message };\n }\n } catch (error) {\n console.error('💥 [AuthContext] 登录异常:', error);\n return { success: false, message: '登录失败,请稍后重试' };\n }\n }, [safeSetState, user, isAuthenticated, loading]);\n\n // 注册\n const register = useCallback(async (userData: RegisterRequest) => {\n console.log('📝 [AuthContext] 开始注册...');\n try {\n const response = await fetch('/api/auth/register', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(userData),\n });\n\n const data = await response.json();\n console.log('📡 [AuthContext] 注册响应:', data);\n const resolvedUser = extractUser(data);\n\n if (data.success && resolvedUser) {\n console.log('✅ [AuthContext] 注册成功, 立即更新全局状态');\n \n // 使用同步的状态更新确保立即生效\n safeSetState(() => {\n setUser(resolvedUser);\n setIsAuthenticated(true);\n setLoading(false);\n });\n \n console.log('🚀 [AuthContext] 返回注册成功结果');\n return { success: true, user: resolvedUser };\n } else {\n console.log('❌ [AuthContext] 注册失败:', data.message);\n return { success: false, message: data.message };\n }\n } catch (error) {\n console.error('💥 [AuthContext] 注册异常:', error);\n return { success: false, message: '注册失败,请稍后重试' };\n }\n }, [safeSetState]);\n\n // 登出\n const logout = useCallback(async () => {\n console.log('🚪 [AuthContext] 开始登出...');\n try {\n await fetch('/api/auth/logout', { method: 'POST' });\n safeSetState(() => {\n setUser(null);\n setIsAuthenticated(false);\n });\n console.log('✅ [AuthContext] 登出成功, 全局状态已清除');\n } catch (error) {\n console.error('💥 [AuthContext] 登出失败:', error);\n }\n }, [safeSetState]);\n\n // 刷新用户信息\n const refreshUser = useCallback(() => {\n console.log('🔄 [AuthContext] 刷新用户信息...');\n setLoading(true);\n validateSession();\n }, [validateSession]);\n\n // 组件挂载/卸载管理\n useEffect(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n // 初始化时验证会话\n useEffect(() => {\n console.log('🚀 [AuthContext] 初始化, 开始验证会话');\n validateSession();\n }, [validateSession]);\n\n // 状态变化监控(用于调试)\n useEffect(() => {\n console.log('📊 [AuthContext] 全局状态变化:', {\n isAuthenticated,\n user: user ? `${user.name || '未设置'} (${user.phone})` : null,\n loading\n });\n }, [isAuthenticated, user, loading]);\n\n const value: AuthContextType = {\n user,\n loading,\n isAuthenticated,\n login,\n register,\n logout,\n refreshUser,\n };\n\n return (\n <AuthContext.Provider value={value}>\n {children}\n </AuthContext.Provider>\n );\n}\n\nexport function useAuth(): UseAuthReturn {\n const context = useContext(AuthContext);\n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n} \n","import type { User } from '../types';\n\n/**\n * 验证手机号格式\n */\nexport function validatePhoneNumber(phone: string): boolean {\n return /^1[3-9]\\d{9}$/.test(phone);\n}\n\n/**\n * 验证密码强度(可扩展)\n */\nexport function validatePassword(password: string): { valid: boolean; message?: string } {\n if (!password) {\n return { valid: false, message: '密码不能为空' };\n }\n \n if (password.length < 6) {\n return { valid: false, message: '密码长度至少6位' };\n }\n \n return { valid: true };\n}\n\n/**\n * 生成安全的会话令牌\n */\nexport function generateSessionToken(): string {\n // 在实际环境中,应该使用更安全的随机数生成\n return Math.random().toString(36).substring(2) + \n Date.now().toString(36) + \n Math.random().toString(36).substring(2);\n}\n\n/**\n * 检查用户是否为管理员\n */\nexport function isAdmin(user: User | null): boolean {\n return user?.role === 'admin';\n}\n\n/**\n * 检查用户是否处于活跃状态\n */\nexport function isActiveUser(user: User | null): boolean {\n return user?.isActive === true;\n}\n\n/**\n * 格式化用户显示名称\n */\nexport function getUserDisplayName(user: User): string {\n return user.name || user.phone || '未知用户';\n}\n\n/**\n * 计算会话过期时间\n */\nexport function calculateSessionExpiry(days: number = 30): Date {\n return new Date(Date.now() + days * 24 * 60 * 60 * 1000);\n}\n\n/**\n * 检查会话是否过期\n */\nexport function isSessionExpired(expiresAt: Date): boolean {\n return new Date() > new Date(expiresAt);\n} ","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X, Phone, Lock, Eye, EyeOff } from 'lucide-react';\nimport { validatePhoneNumber, validatePassword } from '../utils/authUtils';\nimport type { ForgotPasswordModalProps } from '../types';\n\nexport default function ForgotPasswordModal({ isOpen, onClose, onSuccess }: ForgotPasswordModalProps) {\n const [formData, setFormData] = useState({\n phone: '',\n newPassword: '',\n confirmPassword: '',\n verificationCode: '',\n });\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const [countdown, setCountdown] = useState(0);\n const [mounted, setMounted] = useState(false);\n\n // 确保在客户端渲染\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target;\n setFormData(prev => ({ ...prev, [name]: value }));\n if (error) setError(''); // 清除错误信息\n };\n\n const validateForm = () => {\n if (!formData.phone || !formData.newPassword || !formData.confirmPassword || !formData.verificationCode) {\n setError('请填写完整信息');\n return false;\n }\n\n if (!validatePhoneNumber(formData.phone)) {\n setError('请输入正确的手机号格式');\n return false;\n }\n\n const passwordValidation = validatePassword(formData.newPassword);\n if (!passwordValidation.valid) {\n setError(passwordValidation.message || '密码格式错误');\n return false;\n }\n\n if (formData.newPassword !== formData.confirmPassword) {\n setError('两次输入的密码不一致');\n return false;\n }\n\n if (!/^\\d{6}$/.test(formData.verificationCode)) {\n setError('请输入6位数字验证码');\n return false;\n }\n\n return true;\n };\n\n const handleSendCode = async () => {\n if (!formData.phone) {\n setError('请输入手机号');\n return;\n }\n\n if (!validatePhoneNumber(formData.phone)) {\n setError('请输入正确的手机号格式');\n return;\n }\n\n try {\n setLoading(true);\n setError(''); // 清除之前的错误信息\n \n const response = await fetch('/api/auth/send-verification-code', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ phone: formData.phone }),\n });\n\n const data = await response.json();\n if (data.success) {\n // 开始倒计时\n setCountdown(60);\n const timer = setInterval(() => {\n setCountdown(prev => {\n if (prev <= 1) {\n clearInterval(timer);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n \n // 显示成功提示\n console.log('✅ 验证码发送成功');\n } else {\n setError(data.message || '发送验证码失败');\n }\n } catch (error) {\n console.error('发送验证码异常:', error);\n setError('发送验证码失败,请稍后重试');\n } finally {\n setLoading(false);\n }\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n\n try {\n if (!validateForm()) {\n return;\n }\n\n const response = await fetch('/api/auth/reset-password', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n phone: formData.phone,\n newPassword: formData.newPassword,\n verificationCode: formData.verificationCode,\n }),\n });\n\n const data = await response.json();\n if (data.success) {\n onSuccess();\n } else {\n setError(data.message || '重置密码失败');\n }\n } catch (error) {\n setError('重置密码失败,请稍后重试');\n } finally {\n setLoading(false);\n }\n };\n\n const handleOverlayClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n if (!isOpen || !mounted) return null;\n\n const modalContent = (\n <div \n className=\"fixed top-0 left-0 right-0 bottom-0 w-screen h-screen bg-black/50 backdrop-blur-sm flex items-center justify-center z-[9999] p-4\"\n style={{ margin: 0 }}\n onClick={handleOverlayClick}\n >\n <div \n className=\"bg-white rounded-2xl shadow-xl w-full max-w-[420px] max-h-[90vh] overflow-y-auto relative\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* 关闭按钮 */}\n <button \n className=\"absolute top-5 right-5 bg-transparent border-none text-gray-500 cursor-pointer p-2 rounded-lg transition-all hover:bg-gray-100 hover:text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 min-w-9 min-h-9 flex items-center justify-center\"\n onClick={onClose}\n >\n <X size={20} />\n </button>\n\n {/* 标题 */}\n <div className=\"px-6 pt-6 pb-4 text-center border-b border-gray-100\">\n <h2 className=\"text-2xl font-semibold text-gray-800 mb-2\">重置密码</h2>\n <p className=\"text-gray-500 text-sm\">请输入手机号和验证码重置密码</p>\n </div>\n\n {/* 重置密码表单 */}\n <form onSubmit={handleSubmit} className=\"p-6\">\n {/* 手机号输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"phone\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 手机号\n </label>\n <div className=\"relative flex items-center\">\n <Phone size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"phone\"\n name=\"phone\"\n type=\"tel\"\n value={formData.phone}\n onChange={handleInputChange}\n placeholder=\"请输入手机号\"\n className=\"w-full py-3 px-4 pl-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n </div>\n </div>\n\n {/* 验证码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"verificationCode\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 验证码\n </label>\n <div className=\"relative flex items-center\">\n <input\n id=\"verificationCode\"\n name=\"verificationCode\"\n type=\"text\"\n value={formData.verificationCode}\n onChange={handleInputChange}\n placeholder=\"请输入验证码\"\n className=\"w-full py-3 px-4 pr-28 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n maxLength={6}\n />\n <button\n type=\"button\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 bg-transparent border-none text-blue-500 text-sm font-medium cursor-pointer px-2 py-1 rounded transition-all whitespace-nowrap hover:bg-blue-50 disabled:text-gray-400 disabled:cursor-not-allowed\"\n onClick={handleSendCode}\n disabled={loading || countdown > 0}\n >\n {countdown > 0 ? `${countdown}秒后重试` : '发送验证码'}\n </button>\n </div>\n </div>\n\n {/* 新密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"newPassword\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 新密码\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"newPassword\"\n name=\"newPassword\"\n type={showPassword ? 'text' : 'password'}\n value={formData.newPassword}\n onChange={handleInputChange}\n placeholder=\"请输入新密码\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowPassword(!showPassword)}\n disabled={loading}\n >\n {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 确认密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"confirmPassword\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 确认密码\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type={showConfirmPassword ? 'text' : 'password'}\n value={formData.confirmPassword}\n onChange={handleInputChange}\n placeholder=\"请再次输入新密码\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\n disabled={loading}\n >\n {showConfirmPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 错误信息 */}\n {error && (\n <div className=\"text-red-500 text-sm my-4 p-3 bg-red-50 border border-red-200 rounded-lg leading-relaxed\">\n {error}\n </div>\n )}\n\n {/* 提交按钮 */}\n <button\n type=\"submit\"\n className=\"w-full bg-blue-500 text-white border-none py-3.5 px-6 rounded-lg text-base font-medium cursor-pointer transition-all mt-2 min-h-[52px] hover:bg-blue-600 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-blue-500/30 active:translate-y-0 disabled:bg-gray-400 disabled:cursor-not-allowed disabled:transform-none disabled:shadow-none focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2\"\n disabled={loading}\n >\n {loading ? '提交中...' : '重置密码'}\n </button>\n </form>\n </div>\n </div>\n );\n\n // 使用 Portal 渲染到 body,避免父组件样式影响\n return createPortal(modalContent, document.body);\n}\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X, User, Lock, Eye, EyeOff } from 'lucide-react';\nimport { useAuth } from '../contexts/AuthContext';\nimport { validatePhoneNumber } from '../utils/authUtils';\nimport type { LoginModalProps } from '../types';\nimport ForgotPasswordModal from './ForgotPasswordModal';\n\n/**\n * 登录模态框组件\n * 提供用户登录界面和逻辑\n */\nexport default function LoginModal({ isOpen, onClose, onSuccess, onSwitchToRegister }: LoginModalProps) {\n const { login } = useAuth();\n const [formData, setFormData] = useState({\n phone: '',\n password: '',\n });\n const [showPassword, setShowPassword] = useState(false);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const [showForgotPassword, setShowForgotPassword] = useState(false);\n const [mounted, setMounted] = useState(false);\n\n // 确保在客户端渲染\n useEffect(() => {\n setMounted(true);\n }, []);\n\n // 开发环境快速填充\n const fillDemoAccount = (type: 'admin' | 'user') => {\n if (process.env.NODE_ENV === 'development') {\n const accounts = {\n admin: { phone: '13800138000', password: 'admin123456' },\n user: { phone: '13900139000', password: 'test123456' }\n };\n setFormData(accounts[type]);\n setError('');\n }\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target;\n setFormData(prev => ({ ...prev, [name]: value }));\n if (error) setError(''); // 清除错误信息\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n\n console.log('🔄 [LoginModal] handleSubmit 开始');\n\n try {\n // 前端验证\n if (!formData.phone || !formData.password) {\n console.log('❌ [LoginModal] 前端验证失败: 信息不完整');\n setError('请填写完整信息');\n return;\n }\n\n if (!validatePhoneNumber(formData.phone)) {\n console.log('❌ [LoginModal] 前端验证失败: 手机号格式错误');\n setError('请输入正确的手机号');\n return;\n }\n\n console.log('✅ [LoginModal] 前端验证通过');\n console.log('🔑 [LoginModal] 提交登录表单:', { \n phone: formData.phone, \n password: '***' \n });\n\n console.log('📞 [LoginModal] 准备调用 useAuth.login()...');\n \n // 使用useAuth的login方法\n const result = await login(formData);\n \n console.log('📡 [LoginModal] useAuth.login() 返回结果:', result);\n\n if (result.success) {\n console.log('✅ [LoginModal] 登录成功,准备调用 onSuccess()');\n console.log('👤 [LoginModal] 登录成功的用户信息:', result.user);\n \n // 短暂延迟确保状态已更新\n setTimeout(() => {\n console.log('🎯 [LoginModal] 调用 onSuccess 回调');\n onSuccess();\n console.log('🏁 [LoginModal] onSuccess 调用完成');\n }, 100);\n \n } else {\n console.log('❌ [LoginModal] 登录失败:', result.message);\n setError(result.message || '登录失败');\n }\n } catch (error) {\n console.error('💥 [LoginModal] 登录异常:', error);\n setError('登录失败,请稍后重试');\n } finally {\n console.log('🔚 [LoginModal] handleSubmit 结束,设置 loading = false');\n setLoading(false);\n }\n };\n\n const handleOverlayClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n if (!isOpen || !mounted) return null;\n\n const modalContent = (\n <>\n {/* 遮罩层 */}\n <div \n className=\"fixed top-0 left-0 right-0 bottom-0 w-screen h-screen bg-black/50 backdrop-blur-sm flex items-center justify-center z-[9999] p-4\"\n style={{ margin: 0 }}\n onClick={handleOverlayClick}\n >\n {/* 模态框主体 */}\n <div \n className=\"bg-white rounded-2xl shadow-xl w-full max-w-[420px] max-h-[90vh] overflow-y-auto relative\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* 关闭按钮 */}\n <button \n className=\"absolute top-5 right-5 bg-transparent border-none text-gray-500 cursor-pointer p-2 rounded-lg transition-all hover:bg-gray-100 hover:text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 min-w-9 min-h-9 flex items-center justify-center\"\n onClick={onClose}\n >\n <X size={20} />\n </button>\n\n {/* 标题 */}\n <div className=\"px-6 pt-6 pb-4 text-center border-b border-gray-100\">\n <h2 className=\"text-2xl font-semibold text-gray-800 mb-2\">用户登录</h2>\n <p className=\"text-gray-500 text-sm\">请输入您的手机号和密码</p>\n </div>\n\n {/* 开发环境快捷登录 */}\n {process.env.NODE_ENV === 'development' && (\n <div className=\"px-6 py-4 bg-amber-50 border-b border-gray-100\">\n <p className=\"text-xs text-amber-800 font-medium mb-2\">开发环境快捷登录:</p>\n <div className=\"flex gap-2\">\n <button \n type=\"button\" \n onClick={() => fillDemoAccount('admin')} \n className=\"px-3 py-1.5 text-xs bg-amber-400 text-amber-900 border-none rounded-md cursor-pointer transition-all font-medium hover:bg-amber-500\"\n >\n 管理员账号\n </button>\n <button \n type=\"button\" \n onClick={() => fillDemoAccount('user')} \n className=\"px-3 py-1.5 text-xs bg-amber-400 text-amber-900 border-none rounded-md cursor-pointer transition-all font-medium hover:bg-amber-500\"\n >\n 用户账号\n </button>\n </div>\n </div>\n )}\n\n {/* 登录表单 */}\n <form onSubmit={handleSubmit} className=\"p-6\">\n {/* 手机号输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"phone\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 手机号\n </label>\n <div className=\"relative flex items-center\">\n <User size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"phone\"\n name=\"phone\"\n type=\"tel\"\n autoComplete=\"tel\"\n value={formData.phone}\n onChange={handleInputChange}\n placeholder=\"请输入手机号\"\n className=\"w-full py-3 px-4 pl-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n </div>\n </div>\n\n {/* 密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"password\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 密码\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"password\"\n name=\"password\"\n type={showPassword ? 'text' : 'password'}\n autoComplete=\"current-password\"\n value={formData.password}\n onChange={handleInputChange}\n placeholder=\"请输入密码\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowPassword(!showPassword)}\n disabled={loading}\n >\n {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 忘记密码链接 */}\n <div className=\"text-right -mt-2 mb-4\">\n <button\n type=\"button\"\n onClick={() => setShowForgotPassword(true)}\n className=\"bg-transparent border-none text-blue-500 cursor-pointer text-sm font-medium underline px-1 py-0.5 rounded transition-all hover:text-blue-600 hover:bg-blue-50 hover:no-underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n 忘记密码?\n </button>\n </div>\n\n {/* 错误信息 */}\n {error && (\n <div className=\"text-red-500 text-sm my-4 p-3 bg-red-50 border border-red-200 rounded-lg leading-relaxed\">\n {error}\n </div>\n )}\n\n {/* 提交按钮 */}\n <button\n type=\"submit\"\n className=\"w-full bg-blue-500 text-white border-none py-3.5 px-6 rounded-lg text-base font-medium cursor-pointer transition-all mt-2 min-h-[52px] hover:bg-blue-600 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-blue-500/30 active:translate-y-0 disabled:bg-gray-400 disabled:cursor-not-allowed disabled:transform-none disabled:shadow-none focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2\"\n disabled={loading}\n >\n {loading ? '登录中...' : '登录'}\n </button>\n\n {/* 注册链接 */}\n {onSwitchToRegister && (\n <div className=\"text-center mt-5 pt-4 border-t border-gray-100\">\n <span className=\"text-gray-500 text-sm mr-1\">还没有账号?</span>\n <button \n type=\"button\" \n onClick={onSwitchToRegister} \n className=\"bg-transparent border-none text-blue-500 cursor-pointer text-sm font-medium underline px-1 py-0.5 rounded transition-all hover:text-blue-600 hover:bg-blue-50 hover:no-underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n 立即注册\n </button>\n </div>\n )}\n </form>\n </div>\n </div>\n\n {/* 忘记密码模态框 */}\n <ForgotPasswordModal\n isOpen={showForgotPassword}\n onClose={() => setShowForgotPassword(false)}\n onSuccess={() => {\n setShowForgotPassword(false);\n onSuccess();\n }}\n />\n </>\n );\n\n // 使用 Portal 渲染到 body,避免父组件样式影响\n return createPortal(modalContent, document.body);\n}\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { useAuth } from '../contexts/AuthContext';\nimport LoginModal from './LoginModal';\nimport type { AuthGuardProps } from '../types';\n\n/**\n * 认证守卫组件\n * 保护需要登录的页面和组件\n */\nexport default function AuthGuard({ \n children, \n fallback,\n requireAuth = true \n}: AuthGuardProps) {\n const { isAuthenticated, loading, refreshUser } = useAuth();\n const [showLoginModal, setShowLoginModal] = useState(false);\n\n useEffect(() => {\n if (!loading && requireAuth && !isAuthenticated) {\n setShowLoginModal(true);\n }\n }, [loading, requireAuth, isAuthenticated]);\n\n // 登录成功后的处理\n const handleLoginSuccess = () => {\n refreshUser();\n setShowLoginModal(false);\n };\n\n // 如果正在加载,显示加载状态\n if (loading) {\n return (\n <div style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '200px',\n color: '#6b7280',\n flexDirection: 'column',\n gap: '12px'\n }}>\n <div style={{\n width: '32px',\n height: '32px',\n border: '3px solid #e5e7eb',\n borderTop: '3px solid #3b82f6',\n borderRadius: '50%',\n animation: 'spin 1s linear infinite'\n }}></div>\n <div>验证登录状态...</div>\n </div>\n );\n }\n\n // 如果需要认证但未登录,显示登录模态框\n if (requireAuth && !isAuthenticated) {\n return (\n <>\n {fallback || (\n <div style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minHeight: '200px',\n color: '#6b7280',\n flexDirection: 'column',\n gap: '16px',\n padding: '24px',\n textAlign: 'center'\n }}>\n <div style={{\n fontSize: '48px',\n opacity: 0.5\n }}>\n 🔒\n </div>\n <div style={{\n fontSize: '18px',\n fontWeight: '500'\n }}>\n 请先登录以访问此页面\n </div>\n <div style={{\n fontSize: '14px',\n opacity: 0.7\n }}>\n 登录后即可查看相关内容\n </div>\n </div>\n )}\n <LoginModal\n isOpen={showLoginModal}\n onClose={() => setShowLoginModal(false)}\n onSuccess={handleLoginSuccess}\n />\n </>\n );\n }\n\n // 已认证或不需要认证,显示子组件\n return <>{children}</>;\n} ","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X, User, Lock, Phone, Eye, EyeOff } from 'lucide-react';\nimport { useAuth } from '../contexts/AuthContext';\nimport { validatePhoneNumber, validatePassword } from '../utils/authUtils';\nimport type { RegisterModalProps } from '../types';\n\nexport default function RegisterModal({ isOpen, onClose, onSuccess, onSwitchToLogin }: RegisterModalProps) {\n const { register } = useAuth();\n const [formData, setFormData] = useState({\n phone: '',\n password: '',\n confirmPassword: '',\n name: '',\n });\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n const [mounted, setMounted] = useState(false);\n\n // 确保在客户端渲染\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target;\n setFormData(prev => ({ ...prev, [name]: value }));\n if (error) setError(''); // 清除错误信息\n };\n\n const validateForm = () => {\n if (!formData.phone || !formData.password || !formData.confirmPassword) {\n setError('请填写必要信息');\n return false;\n }\n\n if (!validatePhoneNumber(formData.phone)) {\n setError('请输入正确的手机号格式');\n return false;\n }\n\n const passwordValidation = validatePassword(formData.password);\n if (!passwordValidation.valid) {\n setError(passwordValidation.message || '密码格式错误');\n return false;\n }\n\n if (formData.password !== formData.confirmPassword) {\n setError('两次输入的密码不一致');\n return false;\n }\n\n return true;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError('');\n setLoading(true);\n\n try {\n if (!validateForm()) {\n return;\n }\n\n console.log('📝 [RegisterModal] 提交注册表单:', { \n phone: formData.phone, \n name: formData.name || '未设置',\n password: '***' \n });\n\n // 使用useAuth的register方法\n const result = await register({\n phone: formData.phone,\n password: formData.password,\n name: formData.name || undefined,\n });\n\n if (result.success) {\n console.log('✅ [RegisterModal] 注册成功');\n onSuccess();\n } else {\n console.log('❌ [RegisterModal] 注册失败:', result.message);\n setError(result.message || '注册失败');\n }\n } catch (error) {\n console.error('💥 [RegisterModal] 注册异常:', error);\n setError('注册失败,请稍后重试');\n } finally {\n setLoading(false);\n }\n };\n\n const handleOverlayClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n if (!isOpen || !mounted) return null;\n\n const modalContent = (\n <div \n className=\"fixed top-0 left-0 right-0 bottom-0 w-screen h-screen bg-black/50 backdrop-blur-sm flex items-center justify-center z-[9999] p-4\"\n style={{ margin: 0 }}\n onClick={handleOverlayClick}\n >\n <div \n className=\"bg-white rounded-2xl shadow-xl w-full max-w-[420px] max-h-[90vh] overflow-y-auto relative\"\n onClick={(e) => e.stopPropagation()}\n >\n {/* 关闭按钮 */}\n <button \n className=\"absolute top-5 right-5 bg-transparent border-none text-gray-500 cursor-pointer p-2 rounded-lg transition-all hover:bg-gray-100 hover:text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 min-w-9 min-h-9 flex items-center justify-center\"\n onClick={onClose}\n >\n <X size={20} />\n </button>\n\n {/* 标题 */}\n <div className=\"px-6 pt-6 pb-4 text-center border-b border-gray-100\">\n <h2 className=\"text-2xl font-semibold text-gray-800 mb-2\">用户注册</h2>\n <p className=\"text-gray-500 text-sm\">请填写以下信息创建账户</p>\n </div>\n\n {/* 注册表单 */}\n <form onSubmit={handleSubmit} className=\"p-6\">\n {/* 手机号输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"phone\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 手机号 *\n </label>\n <div className=\"relative flex items-center\">\n <Phone size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"phone\"\n name=\"phone\"\n type=\"tel\"\n autoComplete=\"tel\"\n value={formData.phone}\n onChange={handleInputChange}\n placeholder=\"请输入手机号\"\n className=\"w-full py-3 px-4 pl-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n </div>\n </div>\n\n {/* 姓名输入(可选) */}\n <div className=\"mb-5\">\n <label htmlFor=\"name\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 姓名\n </label>\n <div className=\"relative flex items-center\">\n <User size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"name\"\n name=\"name\"\n type=\"text\"\n autoComplete=\"name\"\n value={formData.name}\n onChange={handleInputChange}\n placeholder=\"请输入姓名(可选)\"\n className=\"w-full py-3 px-4 pl-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n </div>\n </div>\n\n {/* 密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"password\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 密码 *\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"password\"\n name=\"password\"\n type={showPassword ? 'text' : 'password'}\n autoComplete=\"new-password\"\n value={formData.password}\n onChange={handleInputChange}\n placeholder=\"请输入密码(至少6位)\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowPassword(!showPassword)}\n disabled={loading}\n >\n {showPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 确认密码输入 */}\n <div className=\"mb-5\">\n <label htmlFor=\"confirmPassword\" className=\"block mb-1.5 text-sm font-medium text-gray-700\">\n 确认密码 *\n </label>\n <div className=\"relative flex items-center\">\n <Lock size={18} className=\"absolute left-4 text-gray-400 z-[1] pointer-events-none\" />\n <input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type={showConfirmPassword ? 'text' : 'password'}\n autoComplete=\"new-password\"\n value={formData.confirmPassword}\n onChange={handleInputChange}\n placeholder=\"请再次输入密码\"\n className=\"w-full py-3 px-4 pl-12 pr-12 border-2 border-gray-200 rounded-lg text-base transition-all box-border min-h-12 bg-white focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/10 placeholder:text-gray-400 disabled:bg-gray-50 disabled:text-gray-500 disabled:cursor-not-allowed\"\n disabled={loading}\n />\n <button\n type=\"button\"\n className=\"absolute right-4 bg-transparent border-none text-gray-400 cursor-pointer p-1 rounded transition-all flex items-center justify-center min-w-6 min-h-6 hover:text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\n disabled={loading}\n >\n {showConfirmPassword ? <EyeOff size={18} /> : <Eye size={18} />}\n </button>\n </div>\n </div>\n\n {/* 错误信息 */}\n {error && (\n <div className=\"text-red-500 text-sm my-4 p-3 bg-red-50 border border-red-200 rounded-lg leading-relaxed\">\n {error}\n </div>\n )}\n\n {/* 提交按钮 */}\n <button\n type=\"submit\"\n className=\"w-full bg-blue-500 text-white border-none py-3.5 px-6 rounded-lg text-base font-medium cursor-pointer transition-all mt-2 min-h-[52px] hover:bg-blue-600 hover:-translate-y-0.5 hover:shadow-lg hover:shadow-blue-500/30 active:translate-y-0 disabled:bg-gray-400 disabled:cursor-not-allowed disabled:transform-none disabled:shadow-none focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2\"\n disabled={loading}\n >\n {loading ? '注册中...' : '注册'}\n </button>\n\n {/* 登录链接 */}\n {onSwitchToLogin && (\n <div className=\"text-center mt-5 pt-4 border-t border-gray-100\">\n <span className=\"text-gray-500 text-sm mr-1\">已有账号?</span>\n <button \n type=\"button\" \n onClick={onSwitchToLogin} \n className=\"bg-transparent border-none text-blue-500 cursor-pointer text-sm font-medium underline px-1 py-0.5 rounded transition-all hover:text-blue-600 hover:bg-blue-50 hover:no-underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n 立即登录\n </button>\n </div>\n )}\n </form>\n </div>\n </div>\n );\n\n // 使用 Portal 渲染到 body,避免父组件样式影响\n return createPortal(modalContent, document.body);\n}\n","'use client';\n\nimport React, { useState } from 'react';\nimport { LogOut, LogIn, User } from 'lucide-react';\nimport { useAuth } from '../contexts/AuthContext';\nimport LoginModal from './LoginModal';\nimport RegisterModal from './RegisterModal';\nimport type { UserMenuProps } from '../types';\n\nexport default function UserMenu({ customMenuItems = [], className }: UserMenuProps) {\n const { user, isAuthenticated, logout } = useAuth();\n const [isOpen, setIsOpen] = useState(false);\n const [showLoginModal, setShowLoginModal] = useState(false);\n const [showRegisterModal, setShowRegisterModal] = useState(false);\n\n // 切换菜单显示\n const toggleMenu = () => {\n setIsOpen(!isOpen);\n };\n\n // 点击菜单外部时关闭菜单\n const handleMenuClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n };\n\n // 处理自定义菜单项点击\n const handleCustomMenuClick = (item: any) => {\n console.log(`🔧 [UserMenu] 自定义菜单项被点击: ${item.label}`);\n item.onClick();\n setIsOpen(false);\n };\n\n // 处理登录\n const handleLogin = () => {\n console.log('🔑 [UserMenu] 登录按钮被点击');\n setShowLoginModal(true);\n setIsOpen(false);\n };\n\n // 处理注册\n const handleRegister = () => {\n console.log('📝 [UserMenu] 注册按钮被点击');\n setShowRegisterModal(true);\n setIsOpen(false);\n };\n\n // 处理退出登录\n const handleLogout = async () => {\n console.log('🚪 [UserMenu] 退出登录按钮被点击');\n try {\n await logout();\n console.log('✅ [UserMenu] 退出登录成功');\n } catch (error) {\n console.error('退出登录失败:', error);\n }\n setIsOpen(false);\n };\n\n // 登录成功后的处理\n const handleAuthSuccess = () => {\n console.log('🎉 [UserMenu] 认证成功回调被调用');\n console.log('👤 [UserMenu] 当前useAuth状态:', {\n user: user ? `${user.name || '未设置'} (${user.phone})` : null,\n isAuthenticated\n });\n \n // useAuth hook会自动更新状态,这里不需要手动处理\n setShowLoginModal(false);\n setShowRegisterModal(false);\n \n console.log('✅ [UserMenu] 认证成功处理完成 - 模态框已关闭');\n \n // 延迟检查状态\n setTimeout(() => {\n console.log('🔍 [UserMenu] 延迟状态检查:', {\n user: user ? `${user.name || '未设置'} (${user.phone})` : null,\n isAuthenticated\n });\n }, 500);\n };\n\n // 从登录切换到注册\n const handleSwitchToRegister = () => {\n console.log('🔄 [UserMenu] 从登录切换到注册');\n setShowLoginModal(false);\n setShowRegisterModal(true);\n };\n\n // 从注册切换到登录\n const handleSwitchToLogin = () => {\n console.log('🔄 [UserMenu] 从注册切换到登录');\n setShowRegisterModal(false);\n setShowLoginModal(true);\n };\n\n // 过滤自定义菜单项:根据登录状态和requireAuth属性\n const getVisibleCustomMenuItems = () => {\n return customMenuItems.filter(item => {\n // 如果设置了requireAuth为true,只有登录后才显示\n if (item.requireAuth === true) {\n return isAuthenticated;\n }\n // 如果设置了requireAuth为false,只有未登录才显示\n if (item.requireAuth === false) {\n return !isAuthenticated;\n }\n // 如果没有设置requireAuth,总是显示\n return true;\n });\n };\n\n // 全局点击处理(关闭菜单)\n React.useEffect(() => {\n const handleGlobalClick = () => {\n setIsOpen(false);\n };\n\n if (isOpen) {\n document.addEventListener('click', handleGlobalClick);\n }\n\n return () => {\n document.removeEventListener('click', handleGlobalClick);\n };\n }, [isOpen]);\n\n const visibleCustomMenuItems = getVisibleCustomMenuItems();\n\n return (\n <div className={`relative inline-block ${className || ''}`}>\n {/* 用户头像/图标 */}\n <button \n className=\"flex items-center gap-2 px-3 py-2 bg-slate-50 text-slate-500 border border-slate-200 rounded-lg cursor-pointer transition-all min-w-11 min-h-11 text-sm font-medium hover:bg-slate-200 hover:text-slate-800 focus:outline-none focus:ring-2 focus:ring-blue-500/10\"\n onClick={toggleMenu}\n >\n <User size={24} />\n {isAuthenticated && user && (\n <span className=\"max-w-[120px] overflow-hidden text-ellipsis whitespace-nowrap\">\n {user.name || user.phone}\n </span>\n )}\n </button>\n\n {/* 下拉菜单 */}\n {isOpen && (\n <div \n className=\"absolute top-[calc(100%+0.5rem)] right-0 z-[1000] min-w-[200px] bg-white border border-slate-200 rounded-xl shadow-lg max-h-[90vh] overflow-y-auto p-2 animate-in slide-in-from-top-2 fade-in duration-200\"\n onClick={handleMenuClick}\n >\n {isAuthenticated && user ? (\n // 已登录状态的菜单\n <>\n <div className=\"p-3 mb-2 bg-slate-50 rounded-lg\">\n <div className=\"text-sm font-semibold text-slate-800 mb-1 overflow-hidden text-ellipsis whitespace-nowrap\">\n {user.name || '未设置名称'}\n </div>\n <div className=\"text-xs text-slate-500 mb-1 overflow-hidden text-ellipsis whitespace-nowrap\">\n {user.phone}\n </div>\n <div className=\"text-xs text-blue-500 font-medium\">\n {user.role === 'admin' ? '管理员' : '普通用户'}\n </div>\n </div>\n \n {/* 自定义菜单项 */}\n {visibleCustomMenuItems.length > 0 && (\n <>\n <div className=\"h-px bg-slate-200 my-2\"></div>\n {visibleCustomMenuItems.map((item) => {\n const IconComponent = item.icon;\n return (\n <button \n key={item.id}\n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-slate-100 hover:text-slate-800 focus:outline-none focus:bg-slate-100 focus:ring-2 focus:ring-blue-500/10\"\n onClick={() => handleCustomMenuClick(item)}\n >\n {IconComponent && <IconComponent size={16} />}\n <span>{item.label}</span>\n </button>\n );\n })}\n </>\n )}\n \n <div className=\"h-px bg-slate-200 my-2\"></div>\n \n <button \n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-red-50 hover:text-red-600 focus:outline-none focus:bg-red-50 focus:text-red-600 focus:ring-2 focus:ring-red-500/10\"\n onClick={handleLogout}\n >\n <LogOut size={16} />\n <span>退出登录</span>\n </button>\n </>\n ) : (\n // 未登录状态的菜单\n <>\n <button \n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-slate-100 hover:text-slate-800 focus:outline-none focus:bg-slate-100 focus:ring-2 focus:ring-blue-500/10\"\n onClick={handleLogin}\n >\n <LogIn size={16} />\n <span>登录</span>\n </button>\n <button \n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-slate-100 hover:text-slate-800 focus:outline-none focus:bg-slate-100 focus:ring-2 focus:ring-blue-500/10\"\n onClick={handleRegister}\n >\n <User size={16} />\n <span>注册</span>\n </button>\n \n {/* 未登录状态的自定义菜单项 */}\n {visibleCustomMenuItems.length > 0 && (\n <>\n <div className=\"h-px bg-slate-200 my-2\"></div>\n {visibleCustomMenuItems.map((item) => {\n const IconComponent = item.icon;\n return (\n <button \n key={item.id}\n className=\"flex items-center gap-3 w-full p-3 bg-transparent border-none rounded-lg text-gray-700 text-sm font-medium cursor-pointer transition-all text-left min-h-11 hover:bg-slate-100 hover:text-slate-800 focus:outline-none focus:bg-slate-100 focus:ring-2 focus:ring-blue-500/10\"\n onClick={() => handleCustomMenuClick(item)}\n >\n {IconComponent && <IconComponent size={16} />}\n <span>{item.label}</span>\n </button>\n );\n })}\n </>\n )}\n </>\n )}\n </div>\n )}\n\n {/* 登录模态框 */}\n <LoginModal\n isOpen={showLoginModal}\n onClose={() => setShowLoginModal(false)}\n onSuccess={handleAuthSuccess}\n onSwitchToRegister={handleSwitchToRegister}\n />\n\n {/* 注册模态框 */}\n <RegisterModal\n isOpen={showRegisterModal}\n onClose={() => setShowRegisterModal(false)}\n onSuccess={handleAuthSuccess}\n onSwitchToLogin={handleSwitchToLogin}\n />\n </div>\n );\n}\n","// ===== 用户相关类型 =====\n\n/**\n * 用户信息接口\n */\nexport interface User {\n id: number;\n phone: string;\n name?: string | null;\n email?: string | null;\n role: string;\n isActive: boolean;\n lastLoginAt?: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * 用户会话接口\n */\nexport interface UserSession {\n id: number;\n userId: number;\n sessionToken: string;\n expiresAt: Date;\n createdAt: Date;\n}\n\n// ===== 请求/响应类型 =====\n\n/**\n * 登录请求接口\n */\nexport interface LoginRequest {\n phone: string;\n password: string;\n}\n\n/**\n * 注册请求接口\n */\nexport interface RegisterRequest {\n phone: string;\n password: string;\n name?: string;\n}\n\n/**\n * 登录响应接口\n */\nexport interface LoginResponse {\n success: boolean;\n message: string;\n user?: User;\n sessionToken?: string;\n}\n\n/**\n * 注册响应接口\n */\nexport interface RegisterResponse {\n success: boolean;\n message: string;\n user?: User;\n sessionToken?: string;\n}\n\n/**\n * 会话验证响应接口\n */\nexport interface SessionValidationResponse {\n valid: boolean;\n user?: User;\n message?: string;\n}\n\n/**\n * 会话验证结果接口\n */\nexport interface SessionValidation {\n valid: boolean;\n user?: User;\n}\n\n// ===== 组件Props类型 =====\n\n/**\n * 登录模态框Props\n */\nexport interface LoginModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess: () => void;\n onSwitchToRegister?: () => void;\n}\n\n/**\n * 注册模态框Props\n */\nexport interface RegisterModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess: () => void;\n onSwitchToLogin?: () => void;\n}\n\n/**\n * 认证守卫Props\n */\nexport interface AuthGuardProps {\n children: React.ReactNode;\n fallback?: React.ReactNode;\n requireAuth?: boolean;\n}\n\n/**\n * 自定义菜单项接口\n */\nexport interface CustomMenuItem {\n id: string;\n label: string;\n icon?: React.ComponentType<any>;\n onClick: () => void;\n requireAuth?: boolean; // 是否需要登录才显示\n}\n\n/**\n * 用户菜单Props\n */\nexport interface UserMenuProps {\n customMenuItems?: CustomMenuItem[]; // 自定义菜单项\n className?: string; // 自定义样式类名\n}\n\n/**\n * 忘记密码模态框Props\n */\nexport interface ForgotPasswordModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess: () => void;\n}\n\n// ===== Hook返回类型 =====\n\n/**\n * useAuth Hook返回值类型\n */\nexport interface UseAuthReturn {\n user: User | null;\n loading: boolean;\n isAuthenticated: boolean;\n login: (credentials: LoginRequest) => Promise<{ success: boolean; user?: User; message?: string }>;\n register: (userData: RegisterRequest) => Promise<{ success: boolean; user?: User; message?: string }>;\n logout: () => Promise<void>;\n refreshUser: () => void;\n}\n\n// ===== 服务相关类型 =====\n\n/**\n * 认证服务接口\n */\nexport interface AuthService {\n verifyPassword(phone: string, password: string): Promise<User | null>;\n createUser(phone: string, password: string, name?: string): Promise<User>;\n createSession(userId: number): Promise<UserSession>;\n validateSession(sessionToken: string): Promise<SessionValidation>;\n deleteSession(sessionToken: string): Promise<void>;\n deleteUserSessions(userId: number): Promise<void>;\n updateLastLogin(userId: number): Promise<void>;\n cleanupExpiredSessions(): Promise<void>;\n getUserByPhone(phone: string): Promise<User | null>;\n sendVerificationCode(phone: string): Promise<string>;\n verifyCode(phone: string, code: string): Promise<boolean>;\n resetPassword(phone: string, newPassword: string): Promise<void>;\n cleanupExpiredVerificationCodes(): Promise<void>;\n}\n\n// ===== 工具函数类型 =====\n\n/**\n * API权限验证函数类型\n */\nexport type ValidateApiAuth = (request: Request) => Promise<User | null>;\n\n// ===== 常量类型 =====\n\n/**\n * 用户角色枚举\n */\nexport enum UserRole {\n USER = 'user',\n ADMIN = 'admin'\n}\n\n/**\n * 会话配置\n */\nexport interface SessionConfig {\n maxAge: number; // 会话最大存活时间(秒)\n cookieName: string; // Cookie名称\n secure: boolean; // 是否使用安全Cookie\n httpOnly: boolean; // 是否仅HTTP访问\n sameSite: 'strict' | 'lax' | 'none'; // SameSite策略\n} "]}
|