sa2kit 1.6.18 → 1.6.19
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/analytics/index.js +1 -1
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +1 -1
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/auth/components/index.js +1 -1
- package/dist/auth/components/index.js.map +1 -1
- package/dist/auth/components/index.mjs +1 -1
- package/dist/auth/components/index.mjs.map +1 -1
- package/dist/calendar/index.js +10 -10
- package/dist/calendar/index.js.map +1 -1
- package/dist/calendar/index.mjs +3 -3
- package/dist/calendar/index.mjs.map +1 -1
- package/dist/{chunk-FDHCX2BY.mjs → chunk-NQ4JDU24.mjs} +3 -3
- package/dist/chunk-NQ4JDU24.mjs.map +1 -0
- package/dist/{chunk-ASL3QC22.js → chunk-PXVELWYK.js} +3 -3
- package/dist/chunk-PXVELWYK.js.map +1 -0
- package/dist/index.js +114 -114
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -7
- package/dist/index.mjs.map +1 -1
- package/dist/mmd/index.d.mts +8 -11
- package/dist/mmd/index.d.ts +8 -11
- package/dist/mmd/index.js +562 -464
- package/dist/mmd/index.js.map +1 -1
- package/dist/mmd/index.mjs +563 -466
- package/dist/mmd/index.mjs.map +1 -1
- package/dist/universalExport/index.js +4 -4
- package/dist/universalExport/index.js.map +1 -1
- package/dist/universalExport/index.mjs +4 -4
- package/dist/universalExport/index.mjs.map +1 -1
- package/dist/universalFile/index.js +2 -2
- package/dist/universalFile/index.js.map +1 -1
- package/dist/universalFile/index.mjs +2 -2
- package/dist/universalFile/index.mjs.map +1 -1
- package/package.json +2 -1
- package/dist/chunk-ASL3QC22.js.map +0 -1
- package/dist/chunk-FDHCX2BY.mjs.map +0 -1
|
@@ -112,7 +112,7 @@ var DefaultContainer = ({ children }) => /* @__PURE__ */ React3__default.default
|
|
|
112
112
|
animationDelay: "4s"
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
)), /* @__PURE__ */ React3__default.default.createElement("div", { className: "relative z-10" }, children), /* @__PURE__ */ React3__default.default.createElement("style", { dangerouslySetInnerHTML: { __html: `
|
|
115
|
+
)), /* @__PURE__ */ React3__default.default.createElement("div", { className: "relative z-[10]" }, children), /* @__PURE__ */ React3__default.default.createElement("style", { dangerouslySetInnerHTML: { __html: `
|
|
116
116
|
@keyframes blob {
|
|
117
117
|
0%, 100% { transform: translate(0, 0) scale(1); }
|
|
118
118
|
25% { transform: translate(20px, -50px) scale(1.1); }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/components/LoginForm.tsx","../../../src/auth/components/RegisterForm.tsx","../../../src/auth/components/AdminLoginPage.tsx"],"names":["useAuth","useState","React","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Auth Components - LoginForm (Headless)\n * 无样式的登录表单组件\n */\n\nimport React, { useState } from 'react';\nimport { useAuth } from '../hooks';\nimport type { HeadlessLoginFormProps, LoginFormState } from './types';\n\n/**\n * Headless 登录表单组件\n *\n * 提供登录逻辑但不包含任何 UI 样式,\n * 使用 render props 模式让用户完全控制 UI\n *\n * @example\n * ```tsx\n * <LoginForm apiClient={apiClient}>\n * {({ email, password, loading, error, handleEmailChange, handlePasswordChange, handleSubmit }) => (\n * <form onSubmit={handleSubmit}>\n * <input\n * value={email}\n * onChange={(e) => handleEmailChange(e.target.value)}\n * />\n * <input\n * type=\"password\"\n * value={password}\n * onChange={(e) => handlePasswordChange(e.target.value)}\n * />\n * {error && <div>{error}</div>}\n * <button disabled={loading}>\n * {loading ? '登录中...' : '登录'}\n * </button>\n * </form>\n * )}\n * </LoginForm>\n * ```\n */\nexport function LoginForm({ apiClient, onSuccess, onError, children }: HeadlessLoginFormProps) {\n const { login, loading, error: authError, clearError } = useAuth(apiClient);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n\n const handleSubmit = async (e?: React.FormEvent) => {\n if (e) {\n e.preventDefault();\n }\n\n clearError();\n\n const result = await login(email, password);\n\n if (result.success) {\n // 登录成功后 user 会自动更新到 state\n const currentUser = apiClient.getUser();\n if (currentUser) {\n onSuccess?.(currentUser);\n }\n } else {\n onError?.(result.error || '登录失败');\n }\n };\n\n const state: LoginFormState = {\n email,\n password,\n loading,\n error: authError,\n handleEmailChange: setEmail,\n handlePasswordChange: setPassword,\n handleSubmit,\n };\n\n return <>{children(state)}</>;\n}\n\n","/**\n * Auth Components - RegisterForm (Headless)\n * 无样式的注册表单组件\n */\n\nimport React, { useState } from 'react';\nimport { useAuth } from '../hooks';\nimport type { HeadlessRegisterFormProps, RegisterFormState } from './types';\n\n/**\n * Headless 注册表单组件\n *\n * 提供注册逻辑但不包含任何 UI 样式,\n * 使用 render props 模式让用户完全控制 UI\n *\n * @example\n * ```tsx\n * <RegisterForm apiClient={apiClient}>\n * {({ email, password, username, loading, error, handleEmailChange, handlePasswordChange, handleUsernameChange, handleSubmit }) => (\n * <form onSubmit={handleSubmit}>\n * <input\n * value={email}\n * onChange={(e) => handleEmailChange(e.target.value)}\n * />\n * <input\n * value={username}\n * onChange={(e) => handleUsernameChange(e.target.value)}\n * />\n * <input\n * type=\"password\"\n * value={password}\n * onChange={(e) => handlePasswordChange(e.target.value)}\n * />\n * {error && <div>{error}</div>}\n * <button disabled={loading}>\n * {loading ? '注册中...' : '注册'}\n * </button>\n * </form>\n * )}\n * </RegisterForm>\n * ```\n */\nexport function RegisterForm({\n apiClient,\n onSuccess,\n onError,\n children,\n}: HeadlessRegisterFormProps) {\n const { register, loading, error: authError, clearError } = useAuth(apiClient);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [username, setUsername] = useState('');\n\n const handleSubmit = async (e?: React.FormEvent) => {\n if (e) {\n e.preventDefault();\n }\n\n clearError();\n\n // 基础验证\n if (!email || !password || !username) {\n const errorMsg = '请填写所有字段';\n onError?.(errorMsg);\n return;\n }\n\n if (password.length < 6) {\n const errorMsg = '密码长度至少为 6 位';\n onError?.(errorMsg);\n return;\n }\n\n const result = await register(email, password, username);\n\n if (result.success) {\n // 注册成功后 user 会自动更新到 state\n const currentUser = apiClient.getUser();\n if (currentUser) {\n onSuccess?.(currentUser);\n }\n } else {\n onError?.(result.error || '注册失败');\n }\n };\n\n const state: RegisterFormState = {\n email,\n password,\n username,\n loading,\n error: authError,\n handleEmailChange: setEmail,\n handlePasswordChange: setPassword,\n handleUsernameChange: setUsername,\n handleSubmit,\n };\n\n return <>{children(state)}</>;\n}\n\n","/**\n * Admin Login Page Component\n * 完整的管理后台登录页面组件\n *\n * 功能:\n * - 邮箱密码登录\n * - 开发环境测试账户自动填充\n * - Analytics 埋点集成\n * - 角色权限检查\n * - 响应式设计\n */\n\nimport React, { useState, useEffect } from 'react';\nimport { useAuth } from '../hooks';\nimport type { BaseApiClient } from '../client/base-api-client';\nimport type { User } from '../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AdminLoginPageProps {\n /**\n * API 客户端实例\n */\n apiClient: BaseApiClient;\n\n /**\n * 登录成功后的回调\n */\n onLoginSuccess?: (user: User) => void;\n\n /**\n * 登录失败的回调\n */\n onLoginError?: (error: string) => void;\n\n /**\n * 权限检查函数(可选)\n * 返回 true 表示有权限,false 表示无权限\n */\n checkPermission?: (user: User) => boolean;\n\n /**\n * 权限不足时的错误消息\n */\n permissionDeniedMessage?: string;\n\n /**\n * 开发环境配置\n */\n devConfig?: {\n /**\n * 是否启用开发模式功能(自动填充等)\n */\n enabled?: boolean;\n\n /**\n * 测试账户邮箱\n */\n testEmail?: string;\n\n /**\n * 测试账户密码\n */\n testPassword?: string;\n\n /**\n * 自动填充延迟(毫秒)\n */\n autoFillDelay?: number;\n };\n\n /**\n * 页面文本配置\n */\n texts?: {\n appName?: string;\n appDescription?: string;\n pageTitle?: string;\n pageSubtitle?: string;\n emailLabel?: string;\n emailPlaceholder?: string;\n passwordLabel?: string;\n passwordPlaceholder?: string;\n loginButton?: string;\n loggingInButton?: string;\n fillTestAccount?: string;\n copyCredentials?: string;\n devModeLabel?: string;\n testAccountInfo?: string;\n testAccountFilled?: string;\n footer?: string;\n };\n\n /**\n * Analytics 集成(可选)\n */\n analytics?: {\n /**\n * 页面访问埋点\n */\n trackPageView?: (data: Record<string, any>) => void;\n\n /**\n * 登录成功埋点\n */\n trackLoginSuccess?: (user: User) => void;\n\n /**\n * 登录失败埋点\n */\n trackLoginFailed?: (error: string, email: string) => void;\n\n /**\n * 权限拒绝埋点\n */\n trackPermissionDenied?: (user: User) => void;\n\n /**\n * 设置用户信息\n */\n setUser?: (user: { userId: string; email: string; role: string }) => void;\n };\n\n /**\n * UI 组件(可选,用于自定义样式)\n */\n components?: {\n Container?: React.ComponentType<{ children: React.ReactNode }>;\n Card?: React.ComponentType<{ children: React.ReactNode }>;\n Input?: React.ComponentType<any>;\n Button?: React.ComponentType<any>;\n Alert?: React.ComponentType<{ children: React.ReactNode }>;\n Badge?: React.ComponentType<{ children: React.ReactNode; variant?: string }>;\n };\n\n /**\n * className 配置(用于 Tailwind CSS)\n */\n classNames?: {\n container?: string;\n card?: string;\n header?: string;\n form?: string;\n input?: string;\n button?: string;\n alert?: string;\n };\n}\n\n// ============================================================================\n// Default Components (Tailwind CSS based) - Modern & Beautiful Design\n// ============================================================================\n\nconst DefaultContainer: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"min-h-screen bg-gradient-to-br from-indigo-100 via-purple-50 to-pink-100 flex items-center justify-center px-4 py-12 relative overflow-hidden\">\n {/* Animated background elements */}\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n <div\n className=\"absolute -top-40 -right-40 w-80 h-80 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n }}\n ></div>\n <div\n className=\"absolute -bottom-40 -left-40 w-80 h-80 bg-indigo-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n animationDelay: '2s',\n }}\n ></div>\n <div\n className=\"absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-80 h-80 bg-pink-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n animationDelay: '4s',\n }}\n ></div>\n </div>\n <div className=\"relative z-10\">\n {children}\n </div>\n <style dangerouslySetInnerHTML={{__html: `\n @keyframes blob {\n 0%, 100% { transform: translate(0, 0) scale(1); }\n 25% { transform: translate(20px, -50px) scale(1.1); }\n 50% { transform: translate(-20px, 20px) scale(0.9); }\n 75% { transform: translate(50px, 50px) scale(1.05); }\n }\n `}} />\n </div>\n);\n\nconst DefaultCard: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"w-full max-w-md bg-white/95 backdrop-blur-xl rounded-2xl shadow-2xl border border-white/20 overflow-hidden\">\n {children}\n </div>\n);\n\nconst DefaultInput: React.FC<any> = (props) => (\n <input\n {...props}\n className=\"w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200 placeholder-gray-400 text-gray-900 hover:border-gray-300\"\n />\n);\n\nconst DefaultButton: React.FC<any> = ({ children, disabled, type, ...props }) => (\n <button\n type={type || 'button'}\n disabled={disabled}\n {...props}\n className={`w-full bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-dashed border-blue-300 text-blue-700 hover:from-blue-100 hover:to-indigo-100 hover:border-blue-400 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 transform hover:scale-105 active:scale-95 ${\n disabled ? 'opacity-60 cursor-not-allowed hover:scale-100 hover:shadow-none' : 'block'}\n }`}\n style={{\n backgroundSize: '200% 100%',\n backgroundPosition: disabled ? '0% 0%' : '0% 0%',\n display: 'block',\n }}\n onMouseEnter={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundPosition = '100% 0%';\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundPosition = '0% 0%';\n }\n }}\n >\n {children}\n </button>\n);\n\nconst DefaultAlert: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"bg-red-50 border-l-4 border-red-500 text-red-700 px-4 py-3 rounded-lg relative flex items-start space-x-3 shadow-sm\">\n <svg className=\"w-5 h-5 text-red-500 mt-0.5 flex-shrink-0\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clipRule=\"evenodd\"/>\n </svg>\n <div className=\"flex-1 text-sm\">{children}</div>\n </div>\n);\n\nconst DefaultBadge: React.FC<{ children: React.ReactNode; variant?: string; className?: string }> = ({\n children,\n variant,\n className = '',\n}) => (\n <span\n className={`inline-flex items-center px-3 py-1.5 rounded-full text-xs font-semibold shadow-sm ${\n variant === 'dev'\n ? 'bg-gradient-to-r from-orange-400 to-amber-500 text-white border-0'\n : 'bg-gray-100 text-gray-700 border border-gray-200'\n } ${className}`}\n >\n {children}\n </span>\n);\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function AdminLoginPage(props: AdminLoginPageProps) {\n const {\n apiClient,\n onLoginSuccess,\n onLoginError,\n checkPermission,\n permissionDeniedMessage = '访问被拒绝:需要管理员权限',\n devConfig,\n texts = {},\n analytics,\n components,\n classNames = {},\n } = props;\n\n // Use custom or default components\n const Container = components?.Container || DefaultContainer;\n const Card = components?.Card || DefaultCard;\n const Input = components?.Input || DefaultInput;\n const Button = components?.Button || DefaultButton;\n const Alert = components?.Alert || DefaultAlert;\n const Badge = components?.Badge || DefaultBadge;\n\n // Default texts\n const t = {\n appName: texts.appName || 'LyricNote',\n appDescription: texts.appDescription || '智能歌词管理平台',\n pageTitle: texts.pageTitle || '管理员登录',\n pageSubtitle: texts.pageSubtitle || '请使用管理员账户登录系统',\n emailLabel: texts.emailLabel || '管理员邮箱',\n emailPlaceholder: texts.emailPlaceholder || 'admin@example.com',\n passwordLabel: texts.passwordLabel || '密码',\n passwordPlaceholder: texts.passwordPlaceholder || '请输入密码',\n loginButton: texts.loginButton || '登录管理后台',\n loggingInButton: texts.loggingInButton || '登录中...',\n fillTestAccount: texts.fillTestAccount || '填充测试账户',\n copyCredentials: texts.copyCredentials || '复制',\n devModeLabel: texts.devModeLabel || '开发环境',\n testAccountInfo: texts.testAccountInfo || '测试账户已填充,可直接登录',\n testAccountFilled: texts.testAccountFilled || '已自动填充测试账户信息',\n footer: texts.footer || '仅限管理员访问 • 系统安全保护',\n };\n\n // State\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [showPassword, setShowPassword] = useState(false);\n const [autoFilled, setAutoFilled] = useState(false);\n const [localError, setLocalError] = useState('');\n\n // Check if development mode\n const isDevelopment =\n devConfig?.enabled ??\n (typeof window !== 'undefined' &&\n (process.env.NODE_ENV === 'development' ||\n window.location.hostname === 'localhost' ||\n window.location.hostname === '127.0.0.1'));\n\n // Test account config\n const testEmail = devConfig?.testEmail || 'admin@example.com';\n const testPassword = devConfig?.testPassword || 'admin123';\n const autoFillDelay = devConfig?.autoFillDelay || 2000;\n\n // Use auth hook\n const { user, isLoggedIn, loading, error: authError, login, clearError } = useAuth(apiClient as any);\n\n const error = authError || localError;\n\n // Track page view\n useEffect(() => {\n if (typeof window !== 'undefined' && analytics?.trackPageView) {\n analytics.trackPageView({\n pageName: 'admin_login_page',\n pageUrl: window.location.pathname,\n });\n }\n }, [analytics]);\n\n // Auto-fill test account in development\n useEffect(() => {\n if (isDevelopment && !email && !password) {\n const timer = setTimeout(() => {\n if (!email && !password) {\n setEmail(testEmail);\n setPassword(testPassword);\n setAutoFilled(true);\n }\n }, autoFillDelay);\n\n return () => clearTimeout(timer);\n }\n return; // Explicit return for all code paths\n }, [isDevelopment, email, password, testEmail, testPassword, autoFillDelay]);\n\n // Check permission after login\n useEffect(() => {\n if (user && isLoggedIn) {\n // Check permission if provided\n if (checkPermission && !checkPermission(user)) {\n setLocalError(permissionDeniedMessage);\n analytics?.trackPermissionDenied?.(user);\n return;\n }\n\n // Track login success\n analytics?.trackLoginSuccess?.(user);\n analytics?.setUser?.({\n userId: user.id,\n email: user.email,\n role: user.role,\n });\n\n // Call success callback\n onLoginSuccess?.(user);\n }\n }, [user, isLoggedIn, checkPermission, permissionDeniedMessage, analytics, onLoginSuccess]);\n\n // Handle login submit\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setLocalError('');\n clearError();\n\n try {\n const result = await login(email, password);\n\n if (!result.success) {\n const errorMsg = result.error || '登录失败';\n setLocalError(errorMsg);\n analytics?.trackLoginFailed?.(errorMsg, email);\n onLoginError?.(errorMsg);\n }\n } catch (err) {\n const errorMsg = '登录失败:网络错误或服务器错误';\n setLocalError(errorMsg);\n analytics?.trackLoginFailed?.(errorMsg, email);\n onLoginError?.(errorMsg);\n }\n };\n\n // Fill test account\n const fillTestAccount = () => {\n setEmail(testEmail);\n setPassword(testPassword);\n setLocalError('');\n setAutoFilled(true);\n };\n\n // Copy test credentials\n const copyTestCredentials = async () => {\n const credentials = `邮箱: ${testEmail}\\n密码: ${testPassword}`;\n try {\n await navigator.clipboard.writeText(credentials);\n } catch (err) {\n console.warn('复制失败,请手动复制');\n }\n };\n\n return (\n <Container>\n <div className=\"w-full max-w-md\">\n {/* Login Form Card */}\n <Card>\n <div className=\"p-8\">\n {/* Title */}\n <div className=\"pb-8\">\n <h2 className=\"text-2xl font-bold text-center text-gray-800\">{t.pageTitle}</h2>\n </div>\n\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Error Alert */}\n {error && <Alert>{error}</Alert>}\n\n {/* Email Input */}\n <div className=\"space-y-2\">\n <label htmlFor=\"email\" className=\"text-sm font-semibold text-gray-700 block\">\n {t.emailLabel}\n </label>\n <Input\n id=\"email\"\n type=\"email\"\n value={email}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}\n placeholder={t.emailPlaceholder}\n required\n disabled={loading}\n />\n </div>\n\n {/* Password Input */}\n <div className=\"space-y-2\">\n <label htmlFor=\"password\" className=\"text-sm font-semibold text-gray-700 block\">\n {t.passwordLabel}\n </label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n type={showPassword ? 'text' : 'password'}\n value={password}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setPassword(e.target.value)\n }\n placeholder={t.passwordPlaceholder}\n required\n disabled={loading}\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors p-1\"\n disabled={loading}\n title={showPassword ? '隐藏密码' : '显示密码'}\n >\n {showPassword ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z\" clipRule=\"evenodd\" />\n <path d=\"M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z\" />\n </svg>\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 12a2 2 0 100-4 2 2 0 000 4z\" />\n <path fillRule=\"evenodd\" d=\"M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z\" clipRule=\"evenodd\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n\n {/* Dev Mode: Test Account Button */}\n {isDevelopment && (\n <div className=\"pt-2\">\n <button\n type=\"button\"\n onClick={fillTestAccount}\n className=\"w-full bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-dashed border-blue-300 text-blue-700 hover:from-blue-100 hover:to-indigo-100 hover:border-blue-400 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 transform hover:scale-105 active:scale-95\"\n disabled={loading}\n >\n {t.fillTestAccount}\n </button>\n </div>\n )}\n\n {/* Submit Button */}\n <div className=\"pt-3\">\n <Button type=\"submit\" disabled={loading}>\n {loading ? t.loggingInButton : t.loginButton}\n </Button>\n </div>\n </form>\n </div>\n </Card>\n </div>\n </Container>\n );\n}\n\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/components/LoginForm.tsx","../../../src/auth/components/RegisterForm.tsx","../../../src/auth/components/AdminLoginPage.tsx"],"names":["useAuth","useState","React","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Auth Components - LoginForm (Headless)\n * 无样式的登录表单组件\n */\n\nimport React, { useState } from 'react';\nimport { useAuth } from '../hooks';\nimport type { HeadlessLoginFormProps, LoginFormState } from './types';\n\n/**\n * Headless 登录表单组件\n *\n * 提供登录逻辑但不包含任何 UI 样式,\n * 使用 render props 模式让用户完全控制 UI\n *\n * @example\n * ```tsx\n * <LoginForm apiClient={apiClient}>\n * {({ email, password, loading, error, handleEmailChange, handlePasswordChange, handleSubmit }) => (\n * <form onSubmit={handleSubmit}>\n * <input\n * value={email}\n * onChange={(e) => handleEmailChange(e.target.value)}\n * />\n * <input\n * type=\"password\"\n * value={password}\n * onChange={(e) => handlePasswordChange(e.target.value)}\n * />\n * {error && <div>{error}</div>}\n * <button disabled={loading}>\n * {loading ? '登录中...' : '登录'}\n * </button>\n * </form>\n * )}\n * </LoginForm>\n * ```\n */\nexport function LoginForm({ apiClient, onSuccess, onError, children }: HeadlessLoginFormProps) {\n const { login, loading, error: authError, clearError } = useAuth(apiClient);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n\n const handleSubmit = async (e?: React.FormEvent) => {\n if (e) {\n e.preventDefault();\n }\n\n clearError();\n\n const result = await login(email, password);\n\n if (result.success) {\n // 登录成功后 user 会自动更新到 state\n const currentUser = apiClient.getUser();\n if (currentUser) {\n onSuccess?.(currentUser);\n }\n } else {\n onError?.(result.error || '登录失败');\n }\n };\n\n const state: LoginFormState = {\n email,\n password,\n loading,\n error: authError,\n handleEmailChange: setEmail,\n handlePasswordChange: setPassword,\n handleSubmit,\n };\n\n return <>{children(state)}</>;\n}\n\n","/**\n * Auth Components - RegisterForm (Headless)\n * 无样式的注册表单组件\n */\n\nimport React, { useState } from 'react';\nimport { useAuth } from '../hooks';\nimport type { HeadlessRegisterFormProps, RegisterFormState } from './types';\n\n/**\n * Headless 注册表单组件\n *\n * 提供注册逻辑但不包含任何 UI 样式,\n * 使用 render props 模式让用户完全控制 UI\n *\n * @example\n * ```tsx\n * <RegisterForm apiClient={apiClient}>\n * {({ email, password, username, loading, error, handleEmailChange, handlePasswordChange, handleUsernameChange, handleSubmit }) => (\n * <form onSubmit={handleSubmit}>\n * <input\n * value={email}\n * onChange={(e) => handleEmailChange(e.target.value)}\n * />\n * <input\n * value={username}\n * onChange={(e) => handleUsernameChange(e.target.value)}\n * />\n * <input\n * type=\"password\"\n * value={password}\n * onChange={(e) => handlePasswordChange(e.target.value)}\n * />\n * {error && <div>{error}</div>}\n * <button disabled={loading}>\n * {loading ? '注册中...' : '注册'}\n * </button>\n * </form>\n * )}\n * </RegisterForm>\n * ```\n */\nexport function RegisterForm({\n apiClient,\n onSuccess,\n onError,\n children,\n}: HeadlessRegisterFormProps) {\n const { register, loading, error: authError, clearError } = useAuth(apiClient);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [username, setUsername] = useState('');\n\n const handleSubmit = async (e?: React.FormEvent) => {\n if (e) {\n e.preventDefault();\n }\n\n clearError();\n\n // 基础验证\n if (!email || !password || !username) {\n const errorMsg = '请填写所有字段';\n onError?.(errorMsg);\n return;\n }\n\n if (password.length < 6) {\n const errorMsg = '密码长度至少为 6 位';\n onError?.(errorMsg);\n return;\n }\n\n const result = await register(email, password, username);\n\n if (result.success) {\n // 注册成功后 user 会自动更新到 state\n const currentUser = apiClient.getUser();\n if (currentUser) {\n onSuccess?.(currentUser);\n }\n } else {\n onError?.(result.error || '注册失败');\n }\n };\n\n const state: RegisterFormState = {\n email,\n password,\n username,\n loading,\n error: authError,\n handleEmailChange: setEmail,\n handlePasswordChange: setPassword,\n handleUsernameChange: setUsername,\n handleSubmit,\n };\n\n return <>{children(state)}</>;\n}\n\n","/**\n * Admin Login Page Component\n * 完整的管理后台登录页面组件\n *\n * 功能:\n * - 邮箱密码登录\n * - 开发环境测试账户自动填充\n * - Analytics 埋点集成\n * - 角色权限检查\n * - 响应式设计\n */\n\nimport React, { useState, useEffect } from 'react';\nimport { useAuth } from '../hooks';\nimport type { BaseApiClient } from '../client/base-api-client';\nimport type { User } from '../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AdminLoginPageProps {\n /**\n * API 客户端实例\n */\n apiClient: BaseApiClient;\n\n /**\n * 登录成功后的回调\n */\n onLoginSuccess?: (user: User) => void;\n\n /**\n * 登录失败的回调\n */\n onLoginError?: (error: string) => void;\n\n /**\n * 权限检查函数(可选)\n * 返回 true 表示有权限,false 表示无权限\n */\n checkPermission?: (user: User) => boolean;\n\n /**\n * 权限不足时的错误消息\n */\n permissionDeniedMessage?: string;\n\n /**\n * 开发环境配置\n */\n devConfig?: {\n /**\n * 是否启用开发模式功能(自动填充等)\n */\n enabled?: boolean;\n\n /**\n * 测试账户邮箱\n */\n testEmail?: string;\n\n /**\n * 测试账户密码\n */\n testPassword?: string;\n\n /**\n * 自动填充延迟(毫秒)\n */\n autoFillDelay?: number;\n };\n\n /**\n * 页面文本配置\n */\n texts?: {\n appName?: string;\n appDescription?: string;\n pageTitle?: string;\n pageSubtitle?: string;\n emailLabel?: string;\n emailPlaceholder?: string;\n passwordLabel?: string;\n passwordPlaceholder?: string;\n loginButton?: string;\n loggingInButton?: string;\n fillTestAccount?: string;\n copyCredentials?: string;\n devModeLabel?: string;\n testAccountInfo?: string;\n testAccountFilled?: string;\n footer?: string;\n };\n\n /**\n * Analytics 集成(可选)\n */\n analytics?: {\n /**\n * 页面访问埋点\n */\n trackPageView?: (data: Record<string, any>) => void;\n\n /**\n * 登录成功埋点\n */\n trackLoginSuccess?: (user: User) => void;\n\n /**\n * 登录失败埋点\n */\n trackLoginFailed?: (error: string, email: string) => void;\n\n /**\n * 权限拒绝埋点\n */\n trackPermissionDenied?: (user: User) => void;\n\n /**\n * 设置用户信息\n */\n setUser?: (user: { userId: string; email: string; role: string }) => void;\n };\n\n /**\n * UI 组件(可选,用于自定义样式)\n */\n components?: {\n Container?: React.ComponentType<{ children: React.ReactNode }>;\n Card?: React.ComponentType<{ children: React.ReactNode }>;\n Input?: React.ComponentType<any>;\n Button?: React.ComponentType<any>;\n Alert?: React.ComponentType<{ children: React.ReactNode }>;\n Badge?: React.ComponentType<{ children: React.ReactNode; variant?: string }>;\n };\n\n /**\n * className 配置(用于 Tailwind CSS)\n */\n classNames?: {\n container?: string;\n card?: string;\n header?: string;\n form?: string;\n input?: string;\n button?: string;\n alert?: string;\n };\n}\n\n// ============================================================================\n// Default Components (Tailwind CSS based) - Modern & Beautiful Design\n// ============================================================================\n\nconst DefaultContainer: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"min-h-screen bg-gradient-to-br from-indigo-100 via-purple-50 to-pink-100 flex items-center justify-center px-4 py-12 relative overflow-hidden\">\n {/* Animated background elements */}\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n <div\n className=\"absolute -top-40 -right-40 w-80 h-80 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n }}\n ></div>\n <div\n className=\"absolute -bottom-40 -left-40 w-80 h-80 bg-indigo-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n animationDelay: '2s',\n }}\n ></div>\n <div\n className=\"absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-80 h-80 bg-pink-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n animationDelay: '4s',\n }}\n ></div>\n </div>\n <div className=\"relative z-[10]\">\n {children}\n </div>\n <style dangerouslySetInnerHTML={{__html: `\n @keyframes blob {\n 0%, 100% { transform: translate(0, 0) scale(1); }\n 25% { transform: translate(20px, -50px) scale(1.1); }\n 50% { transform: translate(-20px, 20px) scale(0.9); }\n 75% { transform: translate(50px, 50px) scale(1.05); }\n }\n `}} />\n </div>\n);\n\nconst DefaultCard: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"w-full max-w-md bg-white/95 backdrop-blur-xl rounded-2xl shadow-2xl border border-white/20 overflow-hidden\">\n {children}\n </div>\n);\n\nconst DefaultInput: React.FC<any> = (props) => (\n <input\n {...props}\n className=\"w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200 placeholder-gray-400 text-gray-900 hover:border-gray-300\"\n />\n);\n\nconst DefaultButton: React.FC<any> = ({ children, disabled, type, ...props }) => (\n <button\n type={type || 'button'}\n disabled={disabled}\n {...props}\n className={`w-full bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-dashed border-blue-300 text-blue-700 hover:from-blue-100 hover:to-indigo-100 hover:border-blue-400 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 transform hover:scale-105 active:scale-95 ${\n disabled ? 'opacity-60 cursor-not-allowed hover:scale-100 hover:shadow-none' : 'block'}\n }`}\n style={{\n backgroundSize: '200% 100%',\n backgroundPosition: disabled ? '0% 0%' : '0% 0%',\n display: 'block',\n }}\n onMouseEnter={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundPosition = '100% 0%';\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundPosition = '0% 0%';\n }\n }}\n >\n {children}\n </button>\n);\n\nconst DefaultAlert: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"bg-red-50 border-l-4 border-red-500 text-red-700 px-4 py-3 rounded-lg relative flex items-start space-x-3 shadow-sm\">\n <svg className=\"w-5 h-5 text-red-500 mt-0.5 flex-shrink-0\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clipRule=\"evenodd\"/>\n </svg>\n <div className=\"flex-1 text-sm\">{children}</div>\n </div>\n);\n\nconst DefaultBadge: React.FC<{ children: React.ReactNode; variant?: string; className?: string }> = ({\n children,\n variant,\n className = '',\n}) => (\n <span\n className={`inline-flex items-center px-3 py-1.5 rounded-full text-xs font-semibold shadow-sm ${\n variant === 'dev'\n ? 'bg-gradient-to-r from-orange-400 to-amber-500 text-white border-0'\n : 'bg-gray-100 text-gray-700 border border-gray-200'\n } ${className}`}\n >\n {children}\n </span>\n);\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function AdminLoginPage(props: AdminLoginPageProps) {\n const {\n apiClient,\n onLoginSuccess,\n onLoginError,\n checkPermission,\n permissionDeniedMessage = '访问被拒绝:需要管理员权限',\n devConfig,\n texts = {},\n analytics,\n components,\n classNames = {},\n } = props;\n\n // Use custom or default components\n const Container = components?.Container || DefaultContainer;\n const Card = components?.Card || DefaultCard;\n const Input = components?.Input || DefaultInput;\n const Button = components?.Button || DefaultButton;\n const Alert = components?.Alert || DefaultAlert;\n const Badge = components?.Badge || DefaultBadge;\n\n // Default texts\n const t = {\n appName: texts.appName || 'LyricNote',\n appDescription: texts.appDescription || '智能歌词管理平台',\n pageTitle: texts.pageTitle || '管理员登录',\n pageSubtitle: texts.pageSubtitle || '请使用管理员账户登录系统',\n emailLabel: texts.emailLabel || '管理员邮箱',\n emailPlaceholder: texts.emailPlaceholder || 'admin@example.com',\n passwordLabel: texts.passwordLabel || '密码',\n passwordPlaceholder: texts.passwordPlaceholder || '请输入密码',\n loginButton: texts.loginButton || '登录管理后台',\n loggingInButton: texts.loggingInButton || '登录中...',\n fillTestAccount: texts.fillTestAccount || '填充测试账户',\n copyCredentials: texts.copyCredentials || '复制',\n devModeLabel: texts.devModeLabel || '开发环境',\n testAccountInfo: texts.testAccountInfo || '测试账户已填充,可直接登录',\n testAccountFilled: texts.testAccountFilled || '已自动填充测试账户信息',\n footer: texts.footer || '仅限管理员访问 • 系统安全保护',\n };\n\n // State\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [showPassword, setShowPassword] = useState(false);\n const [autoFilled, setAutoFilled] = useState(false);\n const [localError, setLocalError] = useState('');\n\n // Check if development mode\n const isDevelopment =\n devConfig?.enabled ??\n (typeof window !== 'undefined' &&\n (process.env.NODE_ENV === 'development' ||\n window.location.hostname === 'localhost' ||\n window.location.hostname === '127.0.0.1'));\n\n // Test account config\n const testEmail = devConfig?.testEmail || 'admin@example.com';\n const testPassword = devConfig?.testPassword || 'admin123';\n const autoFillDelay = devConfig?.autoFillDelay || 2000;\n\n // Use auth hook\n const { user, isLoggedIn, loading, error: authError, login, clearError } = useAuth(apiClient as any);\n\n const error = authError || localError;\n\n // Track page view\n useEffect(() => {\n if (typeof window !== 'undefined' && analytics?.trackPageView) {\n analytics.trackPageView({\n pageName: 'admin_login_page',\n pageUrl: window.location.pathname,\n });\n }\n }, [analytics]);\n\n // Auto-fill test account in development\n useEffect(() => {\n if (isDevelopment && !email && !password) {\n const timer = setTimeout(() => {\n if (!email && !password) {\n setEmail(testEmail);\n setPassword(testPassword);\n setAutoFilled(true);\n }\n }, autoFillDelay);\n\n return () => clearTimeout(timer);\n }\n return; // Explicit return for all code paths\n }, [isDevelopment, email, password, testEmail, testPassword, autoFillDelay]);\n\n // Check permission after login\n useEffect(() => {\n if (user && isLoggedIn) {\n // Check permission if provided\n if (checkPermission && !checkPermission(user)) {\n setLocalError(permissionDeniedMessage);\n analytics?.trackPermissionDenied?.(user);\n return;\n }\n\n // Track login success\n analytics?.trackLoginSuccess?.(user);\n analytics?.setUser?.({\n userId: user.id,\n email: user.email,\n role: user.role,\n });\n\n // Call success callback\n onLoginSuccess?.(user);\n }\n }, [user, isLoggedIn, checkPermission, permissionDeniedMessage, analytics, onLoginSuccess]);\n\n // Handle login submit\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setLocalError('');\n clearError();\n\n try {\n const result = await login(email, password);\n\n if (!result.success) {\n const errorMsg = result.error || '登录失败';\n setLocalError(errorMsg);\n analytics?.trackLoginFailed?.(errorMsg, email);\n onLoginError?.(errorMsg);\n }\n } catch (err) {\n const errorMsg = '登录失败:网络错误或服务器错误';\n setLocalError(errorMsg);\n analytics?.trackLoginFailed?.(errorMsg, email);\n onLoginError?.(errorMsg);\n }\n };\n\n // Fill test account\n const fillTestAccount = () => {\n setEmail(testEmail);\n setPassword(testPassword);\n setLocalError('');\n setAutoFilled(true);\n };\n\n // Copy test credentials\n const copyTestCredentials = async () => {\n const credentials = `邮箱: ${testEmail}\\n密码: ${testPassword}`;\n try {\n await navigator.clipboard.writeText(credentials);\n } catch (err) {\n console.warn('复制失败,请手动复制');\n }\n };\n\n return (\n <Container>\n <div className=\"w-full max-w-md\">\n {/* Login Form Card */}\n <Card>\n <div className=\"p-8\">\n {/* Title */}\n <div className=\"pb-8\">\n <h2 className=\"text-2xl font-bold text-center text-gray-800\">{t.pageTitle}</h2>\n </div>\n\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Error Alert */}\n {error && <Alert>{error}</Alert>}\n\n {/* Email Input */}\n <div className=\"space-y-2\">\n <label htmlFor=\"email\" className=\"text-sm font-semibold text-gray-700 block\">\n {t.emailLabel}\n </label>\n <Input\n id=\"email\"\n type=\"email\"\n value={email}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}\n placeholder={t.emailPlaceholder}\n required\n disabled={loading}\n />\n </div>\n\n {/* Password Input */}\n <div className=\"space-y-2\">\n <label htmlFor=\"password\" className=\"text-sm font-semibold text-gray-700 block\">\n {t.passwordLabel}\n </label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n type={showPassword ? 'text' : 'password'}\n value={password}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setPassword(e.target.value)\n }\n placeholder={t.passwordPlaceholder}\n required\n disabled={loading}\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors p-1\"\n disabled={loading}\n title={showPassword ? '隐藏密码' : '显示密码'}\n >\n {showPassword ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z\" clipRule=\"evenodd\" />\n <path d=\"M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z\" />\n </svg>\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 12a2 2 0 100-4 2 2 0 000 4z\" />\n <path fillRule=\"evenodd\" d=\"M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z\" clipRule=\"evenodd\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n\n {/* Dev Mode: Test Account Button */}\n {isDevelopment && (\n <div className=\"pt-2\">\n <button\n type=\"button\"\n onClick={fillTestAccount}\n className=\"w-full bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-dashed border-blue-300 text-blue-700 hover:from-blue-100 hover:to-indigo-100 hover:border-blue-400 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 transform hover:scale-105 active:scale-95\"\n disabled={loading}\n >\n {t.fillTestAccount}\n </button>\n </div>\n )}\n\n {/* Submit Button */}\n <div className=\"pt-3\">\n <Button type=\"submit\" disabled={loading}>\n {loading ? t.loggingInButton : t.loginButton}\n </Button>\n </div>\n </form>\n </div>\n </Card>\n </div>\n </Container>\n );\n}\n\n"]}
|
|
@@ -106,7 +106,7 @@ var DefaultContainer = ({ children }) => /* @__PURE__ */ React3.createElement("d
|
|
|
106
106
|
animationDelay: "4s"
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
)), /* @__PURE__ */ React3.createElement("div", { className: "relative z-10" }, children), /* @__PURE__ */ React3.createElement("style", { dangerouslySetInnerHTML: { __html: `
|
|
109
|
+
)), /* @__PURE__ */ React3.createElement("div", { className: "relative z-[10]" }, children), /* @__PURE__ */ React3.createElement("style", { dangerouslySetInnerHTML: { __html: `
|
|
110
110
|
@keyframes blob {
|
|
111
111
|
0%, 100% { transform: translate(0, 0) scale(1); }
|
|
112
112
|
25% { transform: translate(20px, -50px) scale(1.1); }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/auth/components/LoginForm.tsx","../../../src/auth/components/RegisterForm.tsx","../../../src/auth/components/AdminLoginPage.tsx"],"names":["React","useState"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Auth Components - LoginForm (Headless)\n * 无样式的登录表单组件\n */\n\nimport React, { useState } from 'react';\nimport { useAuth } from '../hooks';\nimport type { HeadlessLoginFormProps, LoginFormState } from './types';\n\n/**\n * Headless 登录表单组件\n *\n * 提供登录逻辑但不包含任何 UI 样式,\n * 使用 render props 模式让用户完全控制 UI\n *\n * @example\n * ```tsx\n * <LoginForm apiClient={apiClient}>\n * {({ email, password, loading, error, handleEmailChange, handlePasswordChange, handleSubmit }) => (\n * <form onSubmit={handleSubmit}>\n * <input\n * value={email}\n * onChange={(e) => handleEmailChange(e.target.value)}\n * />\n * <input\n * type=\"password\"\n * value={password}\n * onChange={(e) => handlePasswordChange(e.target.value)}\n * />\n * {error && <div>{error}</div>}\n * <button disabled={loading}>\n * {loading ? '登录中...' : '登录'}\n * </button>\n * </form>\n * )}\n * </LoginForm>\n * ```\n */\nexport function LoginForm({ apiClient, onSuccess, onError, children }: HeadlessLoginFormProps) {\n const { login, loading, error: authError, clearError } = useAuth(apiClient);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n\n const handleSubmit = async (e?: React.FormEvent) => {\n if (e) {\n e.preventDefault();\n }\n\n clearError();\n\n const result = await login(email, password);\n\n if (result.success) {\n // 登录成功后 user 会自动更新到 state\n const currentUser = apiClient.getUser();\n if (currentUser) {\n onSuccess?.(currentUser);\n }\n } else {\n onError?.(result.error || '登录失败');\n }\n };\n\n const state: LoginFormState = {\n email,\n password,\n loading,\n error: authError,\n handleEmailChange: setEmail,\n handlePasswordChange: setPassword,\n handleSubmit,\n };\n\n return <>{children(state)}</>;\n}\n\n","/**\n * Auth Components - RegisterForm (Headless)\n * 无样式的注册表单组件\n */\n\nimport React, { useState } from 'react';\nimport { useAuth } from '../hooks';\nimport type { HeadlessRegisterFormProps, RegisterFormState } from './types';\n\n/**\n * Headless 注册表单组件\n *\n * 提供注册逻辑但不包含任何 UI 样式,\n * 使用 render props 模式让用户完全控制 UI\n *\n * @example\n * ```tsx\n * <RegisterForm apiClient={apiClient}>\n * {({ email, password, username, loading, error, handleEmailChange, handlePasswordChange, handleUsernameChange, handleSubmit }) => (\n * <form onSubmit={handleSubmit}>\n * <input\n * value={email}\n * onChange={(e) => handleEmailChange(e.target.value)}\n * />\n * <input\n * value={username}\n * onChange={(e) => handleUsernameChange(e.target.value)}\n * />\n * <input\n * type=\"password\"\n * value={password}\n * onChange={(e) => handlePasswordChange(e.target.value)}\n * />\n * {error && <div>{error}</div>}\n * <button disabled={loading}>\n * {loading ? '注册中...' : '注册'}\n * </button>\n * </form>\n * )}\n * </RegisterForm>\n * ```\n */\nexport function RegisterForm({\n apiClient,\n onSuccess,\n onError,\n children,\n}: HeadlessRegisterFormProps) {\n const { register, loading, error: authError, clearError } = useAuth(apiClient);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [username, setUsername] = useState('');\n\n const handleSubmit = async (e?: React.FormEvent) => {\n if (e) {\n e.preventDefault();\n }\n\n clearError();\n\n // 基础验证\n if (!email || !password || !username) {\n const errorMsg = '请填写所有字段';\n onError?.(errorMsg);\n return;\n }\n\n if (password.length < 6) {\n const errorMsg = '密码长度至少为 6 位';\n onError?.(errorMsg);\n return;\n }\n\n const result = await register(email, password, username);\n\n if (result.success) {\n // 注册成功后 user 会自动更新到 state\n const currentUser = apiClient.getUser();\n if (currentUser) {\n onSuccess?.(currentUser);\n }\n } else {\n onError?.(result.error || '注册失败');\n }\n };\n\n const state: RegisterFormState = {\n email,\n password,\n username,\n loading,\n error: authError,\n handleEmailChange: setEmail,\n handlePasswordChange: setPassword,\n handleUsernameChange: setUsername,\n handleSubmit,\n };\n\n return <>{children(state)}</>;\n}\n\n","/**\n * Admin Login Page Component\n * 完整的管理后台登录页面组件\n *\n * 功能:\n * - 邮箱密码登录\n * - 开发环境测试账户自动填充\n * - Analytics 埋点集成\n * - 角色权限检查\n * - 响应式设计\n */\n\nimport React, { useState, useEffect } from 'react';\nimport { useAuth } from '../hooks';\nimport type { BaseApiClient } from '../client/base-api-client';\nimport type { User } from '../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AdminLoginPageProps {\n /**\n * API 客户端实例\n */\n apiClient: BaseApiClient;\n\n /**\n * 登录成功后的回调\n */\n onLoginSuccess?: (user: User) => void;\n\n /**\n * 登录失败的回调\n */\n onLoginError?: (error: string) => void;\n\n /**\n * 权限检查函数(可选)\n * 返回 true 表示有权限,false 表示无权限\n */\n checkPermission?: (user: User) => boolean;\n\n /**\n * 权限不足时的错误消息\n */\n permissionDeniedMessage?: string;\n\n /**\n * 开发环境配置\n */\n devConfig?: {\n /**\n * 是否启用开发模式功能(自动填充等)\n */\n enabled?: boolean;\n\n /**\n * 测试账户邮箱\n */\n testEmail?: string;\n\n /**\n * 测试账户密码\n */\n testPassword?: string;\n\n /**\n * 自动填充延迟(毫秒)\n */\n autoFillDelay?: number;\n };\n\n /**\n * 页面文本配置\n */\n texts?: {\n appName?: string;\n appDescription?: string;\n pageTitle?: string;\n pageSubtitle?: string;\n emailLabel?: string;\n emailPlaceholder?: string;\n passwordLabel?: string;\n passwordPlaceholder?: string;\n loginButton?: string;\n loggingInButton?: string;\n fillTestAccount?: string;\n copyCredentials?: string;\n devModeLabel?: string;\n testAccountInfo?: string;\n testAccountFilled?: string;\n footer?: string;\n };\n\n /**\n * Analytics 集成(可选)\n */\n analytics?: {\n /**\n * 页面访问埋点\n */\n trackPageView?: (data: Record<string, any>) => void;\n\n /**\n * 登录成功埋点\n */\n trackLoginSuccess?: (user: User) => void;\n\n /**\n * 登录失败埋点\n */\n trackLoginFailed?: (error: string, email: string) => void;\n\n /**\n * 权限拒绝埋点\n */\n trackPermissionDenied?: (user: User) => void;\n\n /**\n * 设置用户信息\n */\n setUser?: (user: { userId: string; email: string; role: string }) => void;\n };\n\n /**\n * UI 组件(可选,用于自定义样式)\n */\n components?: {\n Container?: React.ComponentType<{ children: React.ReactNode }>;\n Card?: React.ComponentType<{ children: React.ReactNode }>;\n Input?: React.ComponentType<any>;\n Button?: React.ComponentType<any>;\n Alert?: React.ComponentType<{ children: React.ReactNode }>;\n Badge?: React.ComponentType<{ children: React.ReactNode; variant?: string }>;\n };\n\n /**\n * className 配置(用于 Tailwind CSS)\n */\n classNames?: {\n container?: string;\n card?: string;\n header?: string;\n form?: string;\n input?: string;\n button?: string;\n alert?: string;\n };\n}\n\n// ============================================================================\n// Default Components (Tailwind CSS based) - Modern & Beautiful Design\n// ============================================================================\n\nconst DefaultContainer: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"min-h-screen bg-gradient-to-br from-indigo-100 via-purple-50 to-pink-100 flex items-center justify-center px-4 py-12 relative overflow-hidden\">\n {/* Animated background elements */}\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n <div\n className=\"absolute -top-40 -right-40 w-80 h-80 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n }}\n ></div>\n <div\n className=\"absolute -bottom-40 -left-40 w-80 h-80 bg-indigo-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n animationDelay: '2s',\n }}\n ></div>\n <div\n className=\"absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-80 h-80 bg-pink-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n animationDelay: '4s',\n }}\n ></div>\n </div>\n <div className=\"relative z-10\">\n {children}\n </div>\n <style dangerouslySetInnerHTML={{__html: `\n @keyframes blob {\n 0%, 100% { transform: translate(0, 0) scale(1); }\n 25% { transform: translate(20px, -50px) scale(1.1); }\n 50% { transform: translate(-20px, 20px) scale(0.9); }\n 75% { transform: translate(50px, 50px) scale(1.05); }\n }\n `}} />\n </div>\n);\n\nconst DefaultCard: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"w-full max-w-md bg-white/95 backdrop-blur-xl rounded-2xl shadow-2xl border border-white/20 overflow-hidden\">\n {children}\n </div>\n);\n\nconst DefaultInput: React.FC<any> = (props) => (\n <input\n {...props}\n className=\"w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200 placeholder-gray-400 text-gray-900 hover:border-gray-300\"\n />\n);\n\nconst DefaultButton: React.FC<any> = ({ children, disabled, type, ...props }) => (\n <button\n type={type || 'button'}\n disabled={disabled}\n {...props}\n className={`w-full bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-dashed border-blue-300 text-blue-700 hover:from-blue-100 hover:to-indigo-100 hover:border-blue-400 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 transform hover:scale-105 active:scale-95 ${\n disabled ? 'opacity-60 cursor-not-allowed hover:scale-100 hover:shadow-none' : 'block'}\n }`}\n style={{\n backgroundSize: '200% 100%',\n backgroundPosition: disabled ? '0% 0%' : '0% 0%',\n display: 'block',\n }}\n onMouseEnter={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundPosition = '100% 0%';\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundPosition = '0% 0%';\n }\n }}\n >\n {children}\n </button>\n);\n\nconst DefaultAlert: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"bg-red-50 border-l-4 border-red-500 text-red-700 px-4 py-3 rounded-lg relative flex items-start space-x-3 shadow-sm\">\n <svg className=\"w-5 h-5 text-red-500 mt-0.5 flex-shrink-0\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clipRule=\"evenodd\"/>\n </svg>\n <div className=\"flex-1 text-sm\">{children}</div>\n </div>\n);\n\nconst DefaultBadge: React.FC<{ children: React.ReactNode; variant?: string; className?: string }> = ({\n children,\n variant,\n className = '',\n}) => (\n <span\n className={`inline-flex items-center px-3 py-1.5 rounded-full text-xs font-semibold shadow-sm ${\n variant === 'dev'\n ? 'bg-gradient-to-r from-orange-400 to-amber-500 text-white border-0'\n : 'bg-gray-100 text-gray-700 border border-gray-200'\n } ${className}`}\n >\n {children}\n </span>\n);\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function AdminLoginPage(props: AdminLoginPageProps) {\n const {\n apiClient,\n onLoginSuccess,\n onLoginError,\n checkPermission,\n permissionDeniedMessage = '访问被拒绝:需要管理员权限',\n devConfig,\n texts = {},\n analytics,\n components,\n classNames = {},\n } = props;\n\n // Use custom or default components\n const Container = components?.Container || DefaultContainer;\n const Card = components?.Card || DefaultCard;\n const Input = components?.Input || DefaultInput;\n const Button = components?.Button || DefaultButton;\n const Alert = components?.Alert || DefaultAlert;\n const Badge = components?.Badge || DefaultBadge;\n\n // Default texts\n const t = {\n appName: texts.appName || 'LyricNote',\n appDescription: texts.appDescription || '智能歌词管理平台',\n pageTitle: texts.pageTitle || '管理员登录',\n pageSubtitle: texts.pageSubtitle || '请使用管理员账户登录系统',\n emailLabel: texts.emailLabel || '管理员邮箱',\n emailPlaceholder: texts.emailPlaceholder || 'admin@example.com',\n passwordLabel: texts.passwordLabel || '密码',\n passwordPlaceholder: texts.passwordPlaceholder || '请输入密码',\n loginButton: texts.loginButton || '登录管理后台',\n loggingInButton: texts.loggingInButton || '登录中...',\n fillTestAccount: texts.fillTestAccount || '填充测试账户',\n copyCredentials: texts.copyCredentials || '复制',\n devModeLabel: texts.devModeLabel || '开发环境',\n testAccountInfo: texts.testAccountInfo || '测试账户已填充,可直接登录',\n testAccountFilled: texts.testAccountFilled || '已自动填充测试账户信息',\n footer: texts.footer || '仅限管理员访问 • 系统安全保护',\n };\n\n // State\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [showPassword, setShowPassword] = useState(false);\n const [autoFilled, setAutoFilled] = useState(false);\n const [localError, setLocalError] = useState('');\n\n // Check if development mode\n const isDevelopment =\n devConfig?.enabled ??\n (typeof window !== 'undefined' &&\n (process.env.NODE_ENV === 'development' ||\n window.location.hostname === 'localhost' ||\n window.location.hostname === '127.0.0.1'));\n\n // Test account config\n const testEmail = devConfig?.testEmail || 'admin@example.com';\n const testPassword = devConfig?.testPassword || 'admin123';\n const autoFillDelay = devConfig?.autoFillDelay || 2000;\n\n // Use auth hook\n const { user, isLoggedIn, loading, error: authError, login, clearError } = useAuth(apiClient as any);\n\n const error = authError || localError;\n\n // Track page view\n useEffect(() => {\n if (typeof window !== 'undefined' && analytics?.trackPageView) {\n analytics.trackPageView({\n pageName: 'admin_login_page',\n pageUrl: window.location.pathname,\n });\n }\n }, [analytics]);\n\n // Auto-fill test account in development\n useEffect(() => {\n if (isDevelopment && !email && !password) {\n const timer = setTimeout(() => {\n if (!email && !password) {\n setEmail(testEmail);\n setPassword(testPassword);\n setAutoFilled(true);\n }\n }, autoFillDelay);\n\n return () => clearTimeout(timer);\n }\n return; // Explicit return for all code paths\n }, [isDevelopment, email, password, testEmail, testPassword, autoFillDelay]);\n\n // Check permission after login\n useEffect(() => {\n if (user && isLoggedIn) {\n // Check permission if provided\n if (checkPermission && !checkPermission(user)) {\n setLocalError(permissionDeniedMessage);\n analytics?.trackPermissionDenied?.(user);\n return;\n }\n\n // Track login success\n analytics?.trackLoginSuccess?.(user);\n analytics?.setUser?.({\n userId: user.id,\n email: user.email,\n role: user.role,\n });\n\n // Call success callback\n onLoginSuccess?.(user);\n }\n }, [user, isLoggedIn, checkPermission, permissionDeniedMessage, analytics, onLoginSuccess]);\n\n // Handle login submit\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setLocalError('');\n clearError();\n\n try {\n const result = await login(email, password);\n\n if (!result.success) {\n const errorMsg = result.error || '登录失败';\n setLocalError(errorMsg);\n analytics?.trackLoginFailed?.(errorMsg, email);\n onLoginError?.(errorMsg);\n }\n } catch (err) {\n const errorMsg = '登录失败:网络错误或服务器错误';\n setLocalError(errorMsg);\n analytics?.trackLoginFailed?.(errorMsg, email);\n onLoginError?.(errorMsg);\n }\n };\n\n // Fill test account\n const fillTestAccount = () => {\n setEmail(testEmail);\n setPassword(testPassword);\n setLocalError('');\n setAutoFilled(true);\n };\n\n // Copy test credentials\n const copyTestCredentials = async () => {\n const credentials = `邮箱: ${testEmail}\\n密码: ${testPassword}`;\n try {\n await navigator.clipboard.writeText(credentials);\n } catch (err) {\n console.warn('复制失败,请手动复制');\n }\n };\n\n return (\n <Container>\n <div className=\"w-full max-w-md\">\n {/* Login Form Card */}\n <Card>\n <div className=\"p-8\">\n {/* Title */}\n <div className=\"pb-8\">\n <h2 className=\"text-2xl font-bold text-center text-gray-800\">{t.pageTitle}</h2>\n </div>\n\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Error Alert */}\n {error && <Alert>{error}</Alert>}\n\n {/* Email Input */}\n <div className=\"space-y-2\">\n <label htmlFor=\"email\" className=\"text-sm font-semibold text-gray-700 block\">\n {t.emailLabel}\n </label>\n <Input\n id=\"email\"\n type=\"email\"\n value={email}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}\n placeholder={t.emailPlaceholder}\n required\n disabled={loading}\n />\n </div>\n\n {/* Password Input */}\n <div className=\"space-y-2\">\n <label htmlFor=\"password\" className=\"text-sm font-semibold text-gray-700 block\">\n {t.passwordLabel}\n </label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n type={showPassword ? 'text' : 'password'}\n value={password}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setPassword(e.target.value)\n }\n placeholder={t.passwordPlaceholder}\n required\n disabled={loading}\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors p-1\"\n disabled={loading}\n title={showPassword ? '隐藏密码' : '显示密码'}\n >\n {showPassword ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z\" clipRule=\"evenodd\" />\n <path d=\"M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z\" />\n </svg>\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 12a2 2 0 100-4 2 2 0 000 4z\" />\n <path fillRule=\"evenodd\" d=\"M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z\" clipRule=\"evenodd\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n\n {/* Dev Mode: Test Account Button */}\n {isDevelopment && (\n <div className=\"pt-2\">\n <button\n type=\"button\"\n onClick={fillTestAccount}\n className=\"w-full bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-dashed border-blue-300 text-blue-700 hover:from-blue-100 hover:to-indigo-100 hover:border-blue-400 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 transform hover:scale-105 active:scale-95\"\n disabled={loading}\n >\n {t.fillTestAccount}\n </button>\n </div>\n )}\n\n {/* Submit Button */}\n <div className=\"pt-3\">\n <Button type=\"submit\" disabled={loading}>\n {loading ? t.loggingInButton : t.loginButton}\n </Button>\n </div>\n </form>\n </div>\n </Card>\n </div>\n </Container>\n );\n}\n\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/auth/components/LoginForm.tsx","../../../src/auth/components/RegisterForm.tsx","../../../src/auth/components/AdminLoginPage.tsx"],"names":["React","useState"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Auth Components - LoginForm (Headless)\n * 无样式的登录表单组件\n */\n\nimport React, { useState } from 'react';\nimport { useAuth } from '../hooks';\nimport type { HeadlessLoginFormProps, LoginFormState } from './types';\n\n/**\n * Headless 登录表单组件\n *\n * 提供登录逻辑但不包含任何 UI 样式,\n * 使用 render props 模式让用户完全控制 UI\n *\n * @example\n * ```tsx\n * <LoginForm apiClient={apiClient}>\n * {({ email, password, loading, error, handleEmailChange, handlePasswordChange, handleSubmit }) => (\n * <form onSubmit={handleSubmit}>\n * <input\n * value={email}\n * onChange={(e) => handleEmailChange(e.target.value)}\n * />\n * <input\n * type=\"password\"\n * value={password}\n * onChange={(e) => handlePasswordChange(e.target.value)}\n * />\n * {error && <div>{error}</div>}\n * <button disabled={loading}>\n * {loading ? '登录中...' : '登录'}\n * </button>\n * </form>\n * )}\n * </LoginForm>\n * ```\n */\nexport function LoginForm({ apiClient, onSuccess, onError, children }: HeadlessLoginFormProps) {\n const { login, loading, error: authError, clearError } = useAuth(apiClient);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n\n const handleSubmit = async (e?: React.FormEvent) => {\n if (e) {\n e.preventDefault();\n }\n\n clearError();\n\n const result = await login(email, password);\n\n if (result.success) {\n // 登录成功后 user 会自动更新到 state\n const currentUser = apiClient.getUser();\n if (currentUser) {\n onSuccess?.(currentUser);\n }\n } else {\n onError?.(result.error || '登录失败');\n }\n };\n\n const state: LoginFormState = {\n email,\n password,\n loading,\n error: authError,\n handleEmailChange: setEmail,\n handlePasswordChange: setPassword,\n handleSubmit,\n };\n\n return <>{children(state)}</>;\n}\n\n","/**\n * Auth Components - RegisterForm (Headless)\n * 无样式的注册表单组件\n */\n\nimport React, { useState } from 'react';\nimport { useAuth } from '../hooks';\nimport type { HeadlessRegisterFormProps, RegisterFormState } from './types';\n\n/**\n * Headless 注册表单组件\n *\n * 提供注册逻辑但不包含任何 UI 样式,\n * 使用 render props 模式让用户完全控制 UI\n *\n * @example\n * ```tsx\n * <RegisterForm apiClient={apiClient}>\n * {({ email, password, username, loading, error, handleEmailChange, handlePasswordChange, handleUsernameChange, handleSubmit }) => (\n * <form onSubmit={handleSubmit}>\n * <input\n * value={email}\n * onChange={(e) => handleEmailChange(e.target.value)}\n * />\n * <input\n * value={username}\n * onChange={(e) => handleUsernameChange(e.target.value)}\n * />\n * <input\n * type=\"password\"\n * value={password}\n * onChange={(e) => handlePasswordChange(e.target.value)}\n * />\n * {error && <div>{error}</div>}\n * <button disabled={loading}>\n * {loading ? '注册中...' : '注册'}\n * </button>\n * </form>\n * )}\n * </RegisterForm>\n * ```\n */\nexport function RegisterForm({\n apiClient,\n onSuccess,\n onError,\n children,\n}: HeadlessRegisterFormProps) {\n const { register, loading, error: authError, clearError } = useAuth(apiClient);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [username, setUsername] = useState('');\n\n const handleSubmit = async (e?: React.FormEvent) => {\n if (e) {\n e.preventDefault();\n }\n\n clearError();\n\n // 基础验证\n if (!email || !password || !username) {\n const errorMsg = '请填写所有字段';\n onError?.(errorMsg);\n return;\n }\n\n if (password.length < 6) {\n const errorMsg = '密码长度至少为 6 位';\n onError?.(errorMsg);\n return;\n }\n\n const result = await register(email, password, username);\n\n if (result.success) {\n // 注册成功后 user 会自动更新到 state\n const currentUser = apiClient.getUser();\n if (currentUser) {\n onSuccess?.(currentUser);\n }\n } else {\n onError?.(result.error || '注册失败');\n }\n };\n\n const state: RegisterFormState = {\n email,\n password,\n username,\n loading,\n error: authError,\n handleEmailChange: setEmail,\n handlePasswordChange: setPassword,\n handleUsernameChange: setUsername,\n handleSubmit,\n };\n\n return <>{children(state)}</>;\n}\n\n","/**\n * Admin Login Page Component\n * 完整的管理后台登录页面组件\n *\n * 功能:\n * - 邮箱密码登录\n * - 开发环境测试账户自动填充\n * - Analytics 埋点集成\n * - 角色权限检查\n * - 响应式设计\n */\n\nimport React, { useState, useEffect } from 'react';\nimport { useAuth } from '../hooks';\nimport type { BaseApiClient } from '../client/base-api-client';\nimport type { User } from '../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AdminLoginPageProps {\n /**\n * API 客户端实例\n */\n apiClient: BaseApiClient;\n\n /**\n * 登录成功后的回调\n */\n onLoginSuccess?: (user: User) => void;\n\n /**\n * 登录失败的回调\n */\n onLoginError?: (error: string) => void;\n\n /**\n * 权限检查函数(可选)\n * 返回 true 表示有权限,false 表示无权限\n */\n checkPermission?: (user: User) => boolean;\n\n /**\n * 权限不足时的错误消息\n */\n permissionDeniedMessage?: string;\n\n /**\n * 开发环境配置\n */\n devConfig?: {\n /**\n * 是否启用开发模式功能(自动填充等)\n */\n enabled?: boolean;\n\n /**\n * 测试账户邮箱\n */\n testEmail?: string;\n\n /**\n * 测试账户密码\n */\n testPassword?: string;\n\n /**\n * 自动填充延迟(毫秒)\n */\n autoFillDelay?: number;\n };\n\n /**\n * 页面文本配置\n */\n texts?: {\n appName?: string;\n appDescription?: string;\n pageTitle?: string;\n pageSubtitle?: string;\n emailLabel?: string;\n emailPlaceholder?: string;\n passwordLabel?: string;\n passwordPlaceholder?: string;\n loginButton?: string;\n loggingInButton?: string;\n fillTestAccount?: string;\n copyCredentials?: string;\n devModeLabel?: string;\n testAccountInfo?: string;\n testAccountFilled?: string;\n footer?: string;\n };\n\n /**\n * Analytics 集成(可选)\n */\n analytics?: {\n /**\n * 页面访问埋点\n */\n trackPageView?: (data: Record<string, any>) => void;\n\n /**\n * 登录成功埋点\n */\n trackLoginSuccess?: (user: User) => void;\n\n /**\n * 登录失败埋点\n */\n trackLoginFailed?: (error: string, email: string) => void;\n\n /**\n * 权限拒绝埋点\n */\n trackPermissionDenied?: (user: User) => void;\n\n /**\n * 设置用户信息\n */\n setUser?: (user: { userId: string; email: string; role: string }) => void;\n };\n\n /**\n * UI 组件(可选,用于自定义样式)\n */\n components?: {\n Container?: React.ComponentType<{ children: React.ReactNode }>;\n Card?: React.ComponentType<{ children: React.ReactNode }>;\n Input?: React.ComponentType<any>;\n Button?: React.ComponentType<any>;\n Alert?: React.ComponentType<{ children: React.ReactNode }>;\n Badge?: React.ComponentType<{ children: React.ReactNode; variant?: string }>;\n };\n\n /**\n * className 配置(用于 Tailwind CSS)\n */\n classNames?: {\n container?: string;\n card?: string;\n header?: string;\n form?: string;\n input?: string;\n button?: string;\n alert?: string;\n };\n}\n\n// ============================================================================\n// Default Components (Tailwind CSS based) - Modern & Beautiful Design\n// ============================================================================\n\nconst DefaultContainer: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"min-h-screen bg-gradient-to-br from-indigo-100 via-purple-50 to-pink-100 flex items-center justify-center px-4 py-12 relative overflow-hidden\">\n {/* Animated background elements */}\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n <div\n className=\"absolute -top-40 -right-40 w-80 h-80 bg-purple-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n }}\n ></div>\n <div\n className=\"absolute -bottom-40 -left-40 w-80 h-80 bg-indigo-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n animationDelay: '2s',\n }}\n ></div>\n <div\n className=\"absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-80 h-80 bg-pink-300 rounded-full mix-blend-multiply filter blur-xl opacity-70\"\n style={{\n animation: 'blob 7s infinite',\n animationDelay: '4s',\n }}\n ></div>\n </div>\n <div className=\"relative z-[10]\">\n {children}\n </div>\n <style dangerouslySetInnerHTML={{__html: `\n @keyframes blob {\n 0%, 100% { transform: translate(0, 0) scale(1); }\n 25% { transform: translate(20px, -50px) scale(1.1); }\n 50% { transform: translate(-20px, 20px) scale(0.9); }\n 75% { transform: translate(50px, 50px) scale(1.05); }\n }\n `}} />\n </div>\n);\n\nconst DefaultCard: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"w-full max-w-md bg-white/95 backdrop-blur-xl rounded-2xl shadow-2xl border border-white/20 overflow-hidden\">\n {children}\n </div>\n);\n\nconst DefaultInput: React.FC<any> = (props) => (\n <input\n {...props}\n className=\"w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200 placeholder-gray-400 text-gray-900 hover:border-gray-300\"\n />\n);\n\nconst DefaultButton: React.FC<any> = ({ children, disabled, type, ...props }) => (\n <button\n type={type || 'button'}\n disabled={disabled}\n {...props}\n className={`w-full bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-dashed border-blue-300 text-blue-700 hover:from-blue-100 hover:to-indigo-100 hover:border-blue-400 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 transform hover:scale-105 active:scale-95 ${\n disabled ? 'opacity-60 cursor-not-allowed hover:scale-100 hover:shadow-none' : 'block'}\n }`}\n style={{\n backgroundSize: '200% 100%',\n backgroundPosition: disabled ? '0% 0%' : '0% 0%',\n display: 'block',\n }}\n onMouseEnter={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundPosition = '100% 0%';\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundPosition = '0% 0%';\n }\n }}\n >\n {children}\n </button>\n);\n\nconst DefaultAlert: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"bg-red-50 border-l-4 border-red-500 text-red-700 px-4 py-3 rounded-lg relative flex items-start space-x-3 shadow-sm\">\n <svg className=\"w-5 h-5 text-red-500 mt-0.5 flex-shrink-0\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clipRule=\"evenodd\"/>\n </svg>\n <div className=\"flex-1 text-sm\">{children}</div>\n </div>\n);\n\nconst DefaultBadge: React.FC<{ children: React.ReactNode; variant?: string; className?: string }> = ({\n children,\n variant,\n className = '',\n}) => (\n <span\n className={`inline-flex items-center px-3 py-1.5 rounded-full text-xs font-semibold shadow-sm ${\n variant === 'dev'\n ? 'bg-gradient-to-r from-orange-400 to-amber-500 text-white border-0'\n : 'bg-gray-100 text-gray-700 border border-gray-200'\n } ${className}`}\n >\n {children}\n </span>\n);\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function AdminLoginPage(props: AdminLoginPageProps) {\n const {\n apiClient,\n onLoginSuccess,\n onLoginError,\n checkPermission,\n permissionDeniedMessage = '访问被拒绝:需要管理员权限',\n devConfig,\n texts = {},\n analytics,\n components,\n classNames = {},\n } = props;\n\n // Use custom or default components\n const Container = components?.Container || DefaultContainer;\n const Card = components?.Card || DefaultCard;\n const Input = components?.Input || DefaultInput;\n const Button = components?.Button || DefaultButton;\n const Alert = components?.Alert || DefaultAlert;\n const Badge = components?.Badge || DefaultBadge;\n\n // Default texts\n const t = {\n appName: texts.appName || 'LyricNote',\n appDescription: texts.appDescription || '智能歌词管理平台',\n pageTitle: texts.pageTitle || '管理员登录',\n pageSubtitle: texts.pageSubtitle || '请使用管理员账户登录系统',\n emailLabel: texts.emailLabel || '管理员邮箱',\n emailPlaceholder: texts.emailPlaceholder || 'admin@example.com',\n passwordLabel: texts.passwordLabel || '密码',\n passwordPlaceholder: texts.passwordPlaceholder || '请输入密码',\n loginButton: texts.loginButton || '登录管理后台',\n loggingInButton: texts.loggingInButton || '登录中...',\n fillTestAccount: texts.fillTestAccount || '填充测试账户',\n copyCredentials: texts.copyCredentials || '复制',\n devModeLabel: texts.devModeLabel || '开发环境',\n testAccountInfo: texts.testAccountInfo || '测试账户已填充,可直接登录',\n testAccountFilled: texts.testAccountFilled || '已自动填充测试账户信息',\n footer: texts.footer || '仅限管理员访问 • 系统安全保护',\n };\n\n // State\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [showPassword, setShowPassword] = useState(false);\n const [autoFilled, setAutoFilled] = useState(false);\n const [localError, setLocalError] = useState('');\n\n // Check if development mode\n const isDevelopment =\n devConfig?.enabled ??\n (typeof window !== 'undefined' &&\n (process.env.NODE_ENV === 'development' ||\n window.location.hostname === 'localhost' ||\n window.location.hostname === '127.0.0.1'));\n\n // Test account config\n const testEmail = devConfig?.testEmail || 'admin@example.com';\n const testPassword = devConfig?.testPassword || 'admin123';\n const autoFillDelay = devConfig?.autoFillDelay || 2000;\n\n // Use auth hook\n const { user, isLoggedIn, loading, error: authError, login, clearError } = useAuth(apiClient as any);\n\n const error = authError || localError;\n\n // Track page view\n useEffect(() => {\n if (typeof window !== 'undefined' && analytics?.trackPageView) {\n analytics.trackPageView({\n pageName: 'admin_login_page',\n pageUrl: window.location.pathname,\n });\n }\n }, [analytics]);\n\n // Auto-fill test account in development\n useEffect(() => {\n if (isDevelopment && !email && !password) {\n const timer = setTimeout(() => {\n if (!email && !password) {\n setEmail(testEmail);\n setPassword(testPassword);\n setAutoFilled(true);\n }\n }, autoFillDelay);\n\n return () => clearTimeout(timer);\n }\n return; // Explicit return for all code paths\n }, [isDevelopment, email, password, testEmail, testPassword, autoFillDelay]);\n\n // Check permission after login\n useEffect(() => {\n if (user && isLoggedIn) {\n // Check permission if provided\n if (checkPermission && !checkPermission(user)) {\n setLocalError(permissionDeniedMessage);\n analytics?.trackPermissionDenied?.(user);\n return;\n }\n\n // Track login success\n analytics?.trackLoginSuccess?.(user);\n analytics?.setUser?.({\n userId: user.id,\n email: user.email,\n role: user.role,\n });\n\n // Call success callback\n onLoginSuccess?.(user);\n }\n }, [user, isLoggedIn, checkPermission, permissionDeniedMessage, analytics, onLoginSuccess]);\n\n // Handle login submit\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setLocalError('');\n clearError();\n\n try {\n const result = await login(email, password);\n\n if (!result.success) {\n const errorMsg = result.error || '登录失败';\n setLocalError(errorMsg);\n analytics?.trackLoginFailed?.(errorMsg, email);\n onLoginError?.(errorMsg);\n }\n } catch (err) {\n const errorMsg = '登录失败:网络错误或服务器错误';\n setLocalError(errorMsg);\n analytics?.trackLoginFailed?.(errorMsg, email);\n onLoginError?.(errorMsg);\n }\n };\n\n // Fill test account\n const fillTestAccount = () => {\n setEmail(testEmail);\n setPassword(testPassword);\n setLocalError('');\n setAutoFilled(true);\n };\n\n // Copy test credentials\n const copyTestCredentials = async () => {\n const credentials = `邮箱: ${testEmail}\\n密码: ${testPassword}`;\n try {\n await navigator.clipboard.writeText(credentials);\n } catch (err) {\n console.warn('复制失败,请手动复制');\n }\n };\n\n return (\n <Container>\n <div className=\"w-full max-w-md\">\n {/* Login Form Card */}\n <Card>\n <div className=\"p-8\">\n {/* Title */}\n <div className=\"pb-8\">\n <h2 className=\"text-2xl font-bold text-center text-gray-800\">{t.pageTitle}</h2>\n </div>\n\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Error Alert */}\n {error && <Alert>{error}</Alert>}\n\n {/* Email Input */}\n <div className=\"space-y-2\">\n <label htmlFor=\"email\" className=\"text-sm font-semibold text-gray-700 block\">\n {t.emailLabel}\n </label>\n <Input\n id=\"email\"\n type=\"email\"\n value={email}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}\n placeholder={t.emailPlaceholder}\n required\n disabled={loading}\n />\n </div>\n\n {/* Password Input */}\n <div className=\"space-y-2\">\n <label htmlFor=\"password\" className=\"text-sm font-semibold text-gray-700 block\">\n {t.passwordLabel}\n </label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n type={showPassword ? 'text' : 'password'}\n value={password}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n setPassword(e.target.value)\n }\n placeholder={t.passwordPlaceholder}\n required\n disabled={loading}\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors p-1\"\n disabled={loading}\n title={showPassword ? '隐藏密码' : '显示密码'}\n >\n {showPassword ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z\" clipRule=\"evenodd\" />\n <path d=\"M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z\" />\n </svg>\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path d=\"M10 12a2 2 0 100-4 2 2 0 000 4z\" />\n <path fillRule=\"evenodd\" d=\"M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z\" clipRule=\"evenodd\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n\n {/* Dev Mode: Test Account Button */}\n {isDevelopment && (\n <div className=\"pt-2\">\n <button\n type=\"button\"\n onClick={fillTestAccount}\n className=\"w-full bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-dashed border-blue-300 text-blue-700 hover:from-blue-100 hover:to-indigo-100 hover:border-blue-400 px-4 py-2.5 rounded-xl text-sm font-medium transition-all duration-200 transform hover:scale-105 active:scale-95\"\n disabled={loading}\n >\n {t.fillTestAccount}\n </button>\n </div>\n )}\n\n {/* Submit Button */}\n <div className=\"pt-3\">\n <Button type=\"submit\" disabled={loading}>\n {loading ? t.loggingInButton : t.loginButton}\n </Button>\n </div>\n </form>\n </div>\n </Card>\n </div>\n </Container>\n );\n}\n\n"]}
|
package/dist/calendar/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkPXVELWYK_js = require('../chunk-PXVELWYK.js');
|
|
4
4
|
require('../chunk-7Z5LLJ3A.js');
|
|
5
5
|
require('../chunk-6PRFP5EG.js');
|
|
6
6
|
require('../chunk-DGUM43GV.js');
|
|
@@ -577,7 +577,7 @@ function EventList({
|
|
|
577
577
|
);
|
|
578
578
|
}));
|
|
579
579
|
return /* @__PURE__ */ React2__default.default.createElement("div", { className: `space-y-6 ${className}` }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 p-4" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex-1 max-w-md" }, /* @__PURE__ */ React2__default.default.createElement(
|
|
580
|
-
|
|
580
|
+
chunkPXVELWYK_js.SearchBox,
|
|
581
581
|
{
|
|
582
582
|
searchQuery: config.filter.searchText || "",
|
|
583
583
|
onSearchChange: handleSearchChange,
|
|
@@ -641,7 +641,7 @@ function EventList({
|
|
|
641
641
|
},
|
|
642
642
|
"\u4E0B\u4E00\u9875"
|
|
643
643
|
)))), !loading && paginatedEvents.length === 0 && /* @__PURE__ */ React2__default.default.createElement("div", { className: "text-center py-12" }, /* @__PURE__ */ React2__default.default.createElement("svg", { className: "w-16 h-16 mx-auto mb-4 text-gray-300", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" }, /* @__PURE__ */ React2__default.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" })), /* @__PURE__ */ React2__default.default.createElement("h3", { className: "text-lg font-medium text-gray-900 mb-2" }, "\u6682\u65E0\u4E8B\u4EF6"), /* @__PURE__ */ React2__default.default.createElement("p", { className: "text-gray-600" }, config.filter.searchText || config.filter.priority || config.filter.color || config.filter.dateRange ? "\u6CA1\u6709\u627E\u5230\u7B26\u5408\u6761\u4EF6\u7684\u4E8B\u4EF6" : "\u8FD8\u6CA1\u6709\u521B\u5EFA\u4EFB\u4F55\u4E8B\u4EF6")), /* @__PURE__ */ React2__default.default.createElement(
|
|
644
|
-
|
|
644
|
+
chunkPXVELWYK_js.ConfirmModal,
|
|
645
645
|
{
|
|
646
646
|
isOpen: showBatchDeleteConfirm,
|
|
647
647
|
onClose: () => setShowBatchDeleteConfirm(false),
|
|
@@ -1823,7 +1823,7 @@ var ImprovedEventModal = ({
|
|
|
1823
1823
|
placeholder: "\u8F93\u5165\u91CD\u590D\u6B21\u6570"
|
|
1824
1824
|
}
|
|
1825
1825
|
))), /* @__PURE__ */ React2__default.default.createElement("div", { className: "p-3 bg-purple-50 rounded-lg text-sm text-purple-700" }, /* @__PURE__ */ React2__default.default.createElement("strong", null, "\u793A\u4F8B"), '\uFF1A\u9009\u62E9"\u6BCF\u5929\u91CD\u590D3\u6B21"\u5C06\u521B\u5EFA3\u4E2A\u72EC\u7ACB\u7684\u4E8B\u4EF6\u5B9E\u4F8B\uFF0C\u5206\u522B\u5728\u8FDE\u7EED\u76843\u5929\u53D1\u751F\u3002'));
|
|
1826
|
-
return /* @__PURE__ */ React2__default.default.createElement(React2__default.default.Fragment, null, /* @__PURE__ */ React2__default.default.createElement(
|
|
1826
|
+
return /* @__PURE__ */ React2__default.default.createElement(React2__default.default.Fragment, null, /* @__PURE__ */ React2__default.default.createElement(chunkPXVELWYK_js.Modal, { isOpen, onClose: handleClose, width: "800px", height: "auto" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "relative" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "px-6 py-4 border-b border-gray-200 bg-gradient-to-r from-blue-50 to-indigo-50" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center space-x-3" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center" }, /* @__PURE__ */ React2__default.default.createElement("span", { className: "text-blue-600 text-lg" }, isEditMode ? "\u270F\uFE0F" : "\u2795")), /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("h2", { className: "text-xl font-semibold text-gray-900" }, isEditMode ? "\u7F16\u8F91\u4E8B\u4EF6" : "\u521B\u5EFA\u65B0\u4E8B\u4EF6"), /* @__PURE__ */ React2__default.default.createElement("p", { className: "text-sm text-gray-600" }, isEditMode ? "\u4FEE\u6539\u4E8B\u4EF6\u4FE1\u606F" : "\u586B\u5199\u4E8B\u4EF6\u8BE6\u7EC6\u4FE1\u606F"))), /* @__PURE__ */ React2__default.default.createElement(
|
|
1827
1827
|
"button",
|
|
1828
1828
|
{
|
|
1829
1829
|
type: "button",
|
|
@@ -1860,7 +1860,7 @@ var ImprovedEventModal = ({
|
|
|
1860
1860
|
/* @__PURE__ */ React2__default.default.createElement("span", { className: "mr-2" }, isEditMode ? "\u{1F4BE}" : "\u2728"),
|
|
1861
1861
|
isLoading ? "\u4FDD\u5B58\u4E2D..." : isEditMode ? "\u66F4\u65B0\u4E8B\u4EF6" : "\u521B\u5EFA\u4E8B\u4EF6"
|
|
1862
1862
|
)))))), /* @__PURE__ */ React2__default.default.createElement(
|
|
1863
|
-
|
|
1863
|
+
chunkPXVELWYK_js.ConfirmModal,
|
|
1864
1864
|
{
|
|
1865
1865
|
isOpen: showDeleteConfirm,
|
|
1866
1866
|
onClose: () => setShowDeleteConfirm(false),
|
|
@@ -2133,7 +2133,7 @@ var DraggableEvent = ({
|
|
|
2133
2133
|
${dragSupported ? "cursor-grab active:cursor-grabbing" : "cursor-pointer"}
|
|
2134
2134
|
transition-all duration-150 ease-in-out text-xs
|
|
2135
2135
|
${getEventColorClasses(event.color)}
|
|
2136
|
-
${isDragActive || isDragging ? "opacity-60 shadow-md z-40" : "opacity-100"}
|
|
2136
|
+
${isDragActive || isDragging ? "opacity-60 shadow-md z-[40]" : "opacity-100"}
|
|
2137
2137
|
${className}
|
|
2138
2138
|
`,
|
|
2139
2139
|
...dragSupported ? listeners : {},
|
|
@@ -2379,7 +2379,7 @@ var DraggableMonthView = ({
|
|
|
2379
2379
|
className: "shadow-lg border border-blue-400 bg-opacity-90"
|
|
2380
2380
|
}
|
|
2381
2381
|
)))
|
|
2382
|
-
) : renderCalendarContent(), dragSupported && dragState.isDragging && /* @__PURE__ */ React2__default.default.createElement("div", { className: "fixed bottom-4 right-4 bg-blue-600 text-white px-4 py-2 rounded-lg shadow-lg z-50" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center space-x-2" }, /* @__PURE__ */ React2__default.default.createElement("svg", { className: "w-4 h-4 animate-pulse", fill: "currentColor", viewBox: "0 0 20 20" }, /* @__PURE__ */ React2__default.default.createElement("path", { d: "M10 12a2 2 0 100-4 2 2 0 000 4z" }), /* @__PURE__ */ React2__default.default.createElement("path", { fillRule: "evenodd", d: "M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z", clipRule: "evenodd" })), /* @__PURE__ */ React2__default.default.createElement("span", { className: "text-sm" }, '\u62D6\u62FD "', dragState.draggedEvent?.title, '" \u5230\u76EE\u6807\u65E5\u671F'))));
|
|
2382
|
+
) : renderCalendarContent(), dragSupported && dragState.isDragging && /* @__PURE__ */ React2__default.default.createElement("div", { className: "fixed bottom-4 right-4 bg-blue-600 text-white px-4 py-2 rounded-lg shadow-lg z-[50]" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center space-x-2" }, /* @__PURE__ */ React2__default.default.createElement("svg", { className: "w-4 h-4 animate-pulse", fill: "currentColor", viewBox: "0 0 20 20" }, /* @__PURE__ */ React2__default.default.createElement("path", { d: "M10 12a2 2 0 100-4 2 2 0 000 4z" }), /* @__PURE__ */ React2__default.default.createElement("path", { fillRule: "evenodd", d: "M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z", clipRule: "evenodd" })), /* @__PURE__ */ React2__default.default.createElement("span", { className: "text-sm" }, '\u62D6\u62FD "', dragState.draggedEvent?.title, '" \u5230\u76EE\u6807\u65E5\u671F'))));
|
|
2383
2383
|
};
|
|
2384
2384
|
var DraggableMonthView_default = DraggableMonthView;
|
|
2385
2385
|
var COLOR_THEMES = {
|
|
@@ -3356,7 +3356,7 @@ var EventModal = ({
|
|
|
3356
3356
|
onClose();
|
|
3357
3357
|
};
|
|
3358
3358
|
return /* @__PURE__ */ React2__default.default.createElement(
|
|
3359
|
-
|
|
3359
|
+
chunkPXVELWYK_js.Modal,
|
|
3360
3360
|
{
|
|
3361
3361
|
isOpen,
|
|
3362
3362
|
onClose: handleClose,
|
|
@@ -3640,7 +3640,7 @@ var EventModal = ({
|
|
|
3640
3640
|
isLoading ? "\u4FDD\u5B58\u4E2D..." : isEditMode ? "\u66F4\u65B0\u4E8B\u4EF6" : "\u521B\u5EFA\u4E8B\u4EF6"
|
|
3641
3641
|
)))),
|
|
3642
3642
|
/* @__PURE__ */ React2__default.default.createElement(
|
|
3643
|
-
|
|
3643
|
+
chunkPXVELWYK_js.ConfirmModal,
|
|
3644
3644
|
{
|
|
3645
3645
|
isOpen: showDeleteConfirm,
|
|
3646
3646
|
onClose: () => setShowDeleteConfirm(false),
|
|
@@ -3786,7 +3786,7 @@ var EventDetailPage = ({
|
|
|
3786
3786
|
event
|
|
3787
3787
|
}
|
|
3788
3788
|
), /* @__PURE__ */ React2__default.default.createElement(
|
|
3789
|
-
|
|
3789
|
+
chunkPXVELWYK_js.ConfirmModal,
|
|
3790
3790
|
{
|
|
3791
3791
|
isOpen: showDeleteConfirm,
|
|
3792
3792
|
onClose: () => setShowDeleteConfirm(false),
|