diff --git a/crop-x-new/next-env.d.ts b/crop-x-new/next-env.d.ts index c4b7818..9edff1c 100644 --- a/crop-x-new/next-env.d.ts +++ b/crop-x-new/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/dev/types/routes.d.ts"; +import "./.next/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/crop-x-new/src/app/(app)/central-config/personal-center/account-security/page.tsx b/crop-x-new/src/app/(app)/central-config/personal-center/account-security/page.tsx index ca19f5a..27ff59f 100644 --- a/crop-x-new/src/app/(app)/central-config/personal-center/account-security/page.tsx +++ b/crop-x-new/src/app/(app)/central-config/personal-center/account-security/page.tsx @@ -1,6 +1,13 @@ +/** + * filekorolheader: 账户安全页面 - 用户账户安全设置管理 + * 功能:密码修改、安全验证、账户信息展示、登录记录查看 + * 路径:/central-config/personal-center/account-security + * 规范:遵循crop-x-new/docs/开发项目规范.md,使用useReducer状态管理,集成真实用户数据 + */ 'use client'; -import { useReducer } from 'react'; +import { useReducer, useEffect } from 'react'; +import { useAuthStore } from '@/stores/modules/auth'; import { Card } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; @@ -27,6 +34,7 @@ interface SecurityState { lastLoginIp: string; }; showPasswordDialog: boolean; + isLoading: boolean; showOldPassword: boolean; showNewPassword: boolean; showConfirmPassword: boolean; @@ -50,19 +58,22 @@ type SecurityAction = | { type: 'TOGGLE_NEW_PASSWORD_VISIBILITY' } | { type: 'TOGGLE_CONFIRM_PASSWORD_VISIBILITY' } | { type: 'UPDATE_PASSWORD_FORM'; payload: Partial } - | { type: 'UPDATE_PASSWORD_STRENGTH'; payload: SecurityState['passwordStrength'] }; + | { type: 'UPDATE_PASSWORD_STRENGTH'; payload: SecurityState['passwordStrength'] } + | { type: 'UPDATE_USER_DATA'; payload: SecurityState['user'] } + | { type: 'SET_LOADING'; payload: boolean }; // Initial state const initialState: SecurityState = { user: { - username: 'admin', - phone: '13800138000', - email: 'admin@smart-agriculture.com', - lastLoginTime: '2024-10-14 09:30:00', - lastLoginDevice: 'Windows PC - Chrome 120.0', - lastLoginIp: '192.168.1.100' + username: '', + phone: '', + email: '', + lastLoginTime: '', + lastLoginDevice: '', + lastLoginIp: '' }, showPasswordDialog: false, + isLoading: true, showOldPassword: false, showNewPassword: false, showConfirmPassword: false, @@ -132,6 +143,18 @@ function securityReducer(state: SecurityState, action: SecurityAction): Security passwordStrength: action.payload }; + case 'UPDATE_USER_DATA': + return { + ...state, + user: action.payload + }; + + case 'SET_LOADING': + return { + ...state, + isLoading: action.payload + }; + default: return state; } @@ -192,6 +215,50 @@ const getStrengthText = (strength: 'weak' | 'medium' | 'strong') => { export default function AccountSecurity() { const [state, dispatch] = useReducer(securityReducer, initialState); + const { getAuthUser } = useAuthStore(); + + // 加载用户数据 + useEffect(() => { + const loadUserData = () => { + const authUser = getAuthUser(); + if (authUser) { + // 格式化最后登录时间 + const formatLastLoginTime = (loginTime: string) => { + try { + const date = new Date(loginTime); + return date.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }); + } catch { + return loginTime; + } + }; + + // 更新用户数据到状态 + dispatch({ + type: 'UPDATE_USER_DATA', + payload: { + username: authUser.username || '', + phone: authUser.phone || '', + email: authUser.email || '', + lastLoginTime: authUser.last_login_at ? formatLastLoginTime(authUser.last_login_at) : '', + lastLoginDevice: 'Web Browser', // 可以从user-agent或其他地方获取 + lastLoginIp: '192.168.1.100' // 可以从登录记录中获取 + } + }); + } + + // 数据加载完成,设置加载状态为false + dispatch({ type: 'SET_LOADING', payload: false }); + }; + + loadUserData(); + }, [getAuthUser]); const handleChangePassword = () => { dispatch({ type: 'UPDATE_PASSWORD_FORM', payload: { oldPassword: '', newPassword: '', confirmPassword: '' } }); @@ -257,58 +324,81 @@ export default function AccountSecurity() { return (
+ {/* Loading State */} + {state.isLoading && ( + +
+
+ 加载用户数据中... +
+
+ )} + {/* Page Header */} - -
- -
-

账户安全

-

- 管理您的账户安全设置,包括密码修改、安全验证等,确保账户安全 -

-
- - - 密码管理 - - - - 安全验证 - - - - 隐私保护 - + {!state.isLoading && ( + +
+ +
+

账户安全

+

+ 管理您的账户安全设置,包括密码修改、安全验证等,确保账户安全 +

+
+ + + 密码管理 + + + + 安全验证 + + + + 隐私保护 + +
-
- + + )} {/* Account Overview */} - + {!state.isLoading && ( +

账户信息

用户名
-
{state.user.username}
+
+ {state.user.username || (state.isLoading ? '加载中...' : '未设置')} +
手机号
-
{state.user.phone}
+
+ {state.user.phone || (state.isLoading ? '加载中...' : '未绑定')} +
邮箱
-
{state.user.email}
+
+ {state.user.email || (state.isLoading ? '加载中...' : '未设置')} +
最后登录时间
-
{state.user.lastLoginTime}
+
+ {state.user.lastLoginTime || (state.isLoading ? '加载中...' : '暂无登录记录')} +
+ )} {/* Password Management */} - + {!state.isLoading && ( +

登录密码

@@ -336,9 +426,11 @@ export default function AccountSecurity() {
+ )} {/* Security Settings */} - + {!state.isLoading && ( +

安全设置

@@ -348,7 +440,9 @@ export default function AccountSecurity() {
手机验证
-
已绑定手机号:{state.user.phone}
+
+ 已绑定手机号:{state.user.phone || '未绑定'} +
已启用 @@ -374,16 +468,20 @@ export default function AccountSecurity() {
邮箱验证
-
已绑定邮箱:{state.user.email}
+
+ 已绑定邮箱:{state.user.email || '未设置'} +
已启用
+ )} {/* Recent Login Records */} - + {!state.isLoading && ( +

最近登录记录

@@ -392,18 +490,19 @@ export default function AccountSecurity() {
当前会话
- {state.user.lastLoginDevice} · {state.user.lastLoginIp} + {state.user.lastLoginDevice || 'Web Browser'} · {state.user.lastLoginIp || '局域网'}
- {state.user.lastLoginTime} + {state.user.lastLoginTime || '首次登录'}
+ )} {/* End of loading state check */} - {/* Change Password Dialog */} + {/* Change Password Dialog - always visible regardless of loading state */} dispatch({ type: 'TOGGLE_PASSWORD_DIALOG', payload: open })}> diff --git a/crop-x-new/src/app/(app)/central-config/tenant/user-management/page.tsx b/crop-x-new/src/app/(app)/central-config/tenant/user-management/page.tsx index 9a2b968..0f110b6 100644 --- a/crop-x-new/src/app/(app)/central-config/tenant/user-management/page.tsx +++ b/crop-x-new/src/app/(app)/central-config/tenant/user-management/page.tsx @@ -277,7 +277,6 @@ export default function TenantUserManagementPage() { const loadUsers = useCallback(async (resetPage = false) => { try { dispatch({ type: 'SET_LOADING', payload: true }); - debugger const params: UsersQueryParams = { page: resetPage ? 1 : state.pagination.page, size: state.pagination.size, diff --git a/crop-x/src/app/(app)/central-config/tenant/user-management/page.tsx b/crop-x/src/app/(app)/central-config/tenant/user-management/page.tsx index 9a2b968..55a725b 100644 --- a/crop-x/src/app/(app)/central-config/tenant/user-management/page.tsx +++ b/crop-x/src/app/(app)/central-config/tenant/user-management/page.tsx @@ -277,7 +277,6 @@ export default function TenantUserManagementPage() { const loadUsers = useCallback(async (resetPage = false) => { try { dispatch({ type: 'SET_LOADING', payload: true }); - debugger const params: UsersQueryParams = { page: resetPage ? 1 : state.pagination.page, size: state.pagination.size, @@ -327,7 +326,7 @@ export default function TenantUserManagementPage() { payload: error instanceof Error ? error.message : '加载用户数据失败' }); } - }, []); + }, [state.pagination.page, state.pagination.size, state.sortBy, state.sortOrder, searchFilters]); // 搜索处理 const handleSearch = useCallback((filters: Record) => {