网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
@model Dpz.Core.Auth.Models.ChangePasswordModel
@{
    Layout = null;
}

<!DOCTYPE html>

<html lang="zh-Hans">
<head>
    <title>修改密码 - 认证中心</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <link rel="stylesheet" href="@Url.Content("~/css/global.css")" asp-append-version="true"/>
</head>
<body class="change-password-page">
    <div class="container">
        <div class="header">
            <h1>修改密码</h1>
            <p>为了您的账户安全,请设置一个强密码</p>
        </div>
        
        <form method="post" asp-action="HandleChangePassword" autocomplete="off" data-submit-loading="true">
            @Html.AntiForgeryToken()
            
            <!-- 当前密码 -->
            <div class="input-section">
                <label class="input-label" for="Password">当前密码</label>
                <div class="input-wrapper">
                    <input 
                        asp-for="Password"
                        type="password" 
                        class="text-input" 
                        placeholder="请输入当前密码"
                        autocomplete="current-password"
                        required
                        autofocus
                    />
                    <button type="button" class="toggle-visibility" onclick="togglePasswordVisibility('Password')" aria-label="显示或隐藏密码">
                        <svg class="eye-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                            <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
                            <circle cx="12" cy="12" r="3"></circle>
                        </svg>
                    </button>
                </div>
                <span asp-validation-for="Password" class="field-validation-error"></span>
            </div>

            <!-- 新密码 -->
            <div class="input-section">
                <label class="input-label" for="NewPassword">新密码</label>
                <div class="input-wrapper">
                    <input 
                        asp-for="NewPassword"
                        type="password" 
                        class="text-input" 
                        placeholder="请输入新密码"
                        autocomplete="new-password"
                        required
                    />
                    <button type="button" class="toggle-visibility" onclick="togglePasswordVisibility('NewPassword')" aria-label="显示或隐藏密码">
                        <svg class="eye-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                            <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
                            <circle cx="12" cy="12" r="3"></circle>
                        </svg>
                    </button>
                </div>
                <span asp-validation-for="NewPassword" class="field-validation-error"></span>
                
                <!-- 密码强度指示器 -->
                <div class="password-strength-container">
                    <div class="password-strength-label">密码强度:</div>
                    <div class="password-strength-indicator">
                        <div class="strength-bar" id="strengthBar"></div>
                    </div>
                    <div class="password-strength-text" id="strengthText">请输入密码</div>
                </div>
                
                <!-- 密码要求提示 -->
                <div class="password-requirements">
                    <div class="requirement-item" id="req-length">
                        <span class="requirement-icon">○</span>
                        至少8个字符
                    </div>
                    <div class="requirement-item" id="req-ascii">
                        <span class="requirement-icon">○</span>
                        只包含ASCII可打印字符
                    </div>
                    <div class="requirement-item" id="req-no-space">
                        <span class="requirement-icon">○</span>
                        不包含空格
                    </div>
                </div>
            </div>

            <!-- 确认新密码 -->
            <div class="input-section">
                <label class="input-label" for="NewRepeatPassword">确认新密码</label>
                <div class="input-wrapper">
                    <input 
                        asp-for="NewRepeatPassword"
                        type="password" 
                        class="text-input" 
                        placeholder="请再次输入新密码"
                        autocomplete="new-password"
                        required
                    />
                    <button type="button" class="toggle-visibility" onclick="togglePasswordVisibility('NewRepeatPassword')" aria-label="显示或隐藏密码">
                        <svg class="eye-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                            <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
                            <circle cx="12" cy="12" r="3"></circle>
                        </svg>
                    </button>
                </div>
                <span asp-validation-for="NewRepeatPassword" class="field-validation-error"></span>
                <div class="password-match-indicator" id="passwordMatch"></div>
            </div>

            <!-- 双因素验证码(如已启用) -->
            <div class="input-section">
                <label class="input-label" for="PinCode">双因素验证码(如已启用)</label>
                <div class="input-wrapper">
                    <input 
                        asp-for="PinCode"
                        type="text" 
                        class="pin-input" 
                        placeholder="请输入6位验证码(可选)"
                        pattern="[0-9]{6}"
                        maxlength="6"
                        minlength="6"
                        autocomplete="one-time-code"
                        inputmode="numeric"
                    />
                </div>
                <span asp-validation-for="PinCode" class="field-validation-error"></span>
                <div class="input-hint">
                    如果您已启用双因素验证,请输入当前验证码
                </div>
            </div>
            
            @if (TempData["Msg"] is string message)
            {
                <div class="error-message">
                    @message
                </div>
            }
            
            @if (TempData["Message"] is string successMessage)
            {
                <div class="success-message">
                    @successMessage
                </div>
            }
            
            <!-- 操作按钮 -->
            <div class="action-buttons">
                <button type="submit" class="submit-button" data-loading-text="修改中..." id="submitBtn" disabled>
                    确认修改密码
                </button>
                <a href="@Url.Action("Index", "Home")" class="cancel-button">
                    取消修改
                </a>
            </div>
        </form>
        
        <div class="footer">
            <p>修改密码后,您需要重新登录所有设备</p>
        </div>
    </div>

    <script src="@Url.Content("~/js/ui-components.js")" asp-append-version="true"></script>
    <script>
        // 密码可见性切换
        function togglePasswordVisibility(fieldId) {
            const field = document.getElementById(fieldId);
            const button = field.nextElementSibling;
            const icon = button.querySelector('.eye-icon');
            
            if (field.type === 'password') {
                field.type = 'text';
                icon.innerHTML = `
                    <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
                    <line x1="1" y1="1" x2="23" y2="23"></line>
                `;
            } else {
                field.type = 'password';
                icon.innerHTML = `
                    <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
                    <circle cx="12" cy="12" r="3"></circle>
                `;
            }
        }

        // 密码强度检测
        function checkPasswordStrength(password) {
            let score = 0;
            const requirements = {
                length: password.length >= 8,
                ascii: /^[\x21-\x7E]*$/.test(password) && password.length > 0,
                'no-space': !/\s/.test(password)
            };

            // 更新要求指示器
            Object.keys(requirements).forEach(req => {
                const element = document.getElementById(`req-${req}`);
                const icon = element.querySelector('.requirement-icon');
                if (requirements[req]) {
                    element.classList.add('met');
                    icon.textContent = '✓';
                    score++;
                } else {
                    element.classList.remove('met');
                    icon.textContent = '○';
                }
            });

            // 计算额外的强度因子
            let strengthScore = score;
            if (password.length >= 8) {
                // 基于密码复杂度的额外评分
                if (/[a-z]/.test(password)) strengthScore += 0.5; // 小写字母
                if (/[A-Z]/.test(password)) strengthScore += 0.5; // 大写字母
                if (/\d/.test(password)) strengthScore += 0.5; // 数字
                if (/[^\da-zA-Z]/.test(password)) strengthScore += 0.5; // 特殊字符
                if (password.length >= 12) strengthScore += 0.5; // 长度奖励
            }

            // 更新强度指示器
            const strengthBar = document.getElementById('strengthBar');
            const strengthText = document.getElementById('strengthText');
            
            let strengthLevel = '';
            let strengthClass = '';
            
            if (score < 3) {
                strengthLevel = '不符合要求';
                strengthClass = 'weak';
            } else if (strengthScore <= 4) {
                strengthLevel = '基本';
                strengthClass = 'weak';
            } else if (strengthScore <= 5) {
                strengthLevel = '中等';
                strengthClass = 'medium';
            } else {
                strengthLevel = '强';
                strengthClass = 'strong';
            }
            
            strengthBar.className = `strength-bar ${strengthClass}`;
            strengthBar.style.width = `${Math.min(strengthScore / 6 * 100, 100)}%`;
            strengthText.textContent = strengthLevel;
            
            // 只有满足所有基本要求才算有效
            return score === 3;
        }

        // 检查密码匹配
        function checkPasswordMatch() {
            const newPassword = document.getElementById('NewPassword').value;
            const confirmPassword = document.getElementById('NewRepeatPassword').value;
            const matchIndicator = document.getElementById('passwordMatch');
            
            if (confirmPassword === '') {
                matchIndicator.textContent = '';
                matchIndicator.className = 'password-match-indicator';
                return false;
            }
            
            if (newPassword === confirmPassword) {
                matchIndicator.textContent = '✓ 密码匹配';
                matchIndicator.className = 'password-match-indicator match';
                return true;
            } else {
                matchIndicator.textContent = '✗ 密码不匹配';
                matchIndicator.className = 'password-match-indicator no-match';
                return false;
            }
        }

        // 验证表单并启用/禁用提交按钮
        function validateForm() {
            const currentPassword = document.getElementById('Password').value;
            const newPassword = document.getElementById('NewPassword').value;
            const confirmPassword = document.getElementById('NewRepeatPassword').value;
            const submitBtn = document.getElementById('submitBtn');
            
            const isPasswordStrong = checkPasswordStrength(newPassword);
            const isPasswordMatch = checkPasswordMatch();
            const hasCurrentPassword = currentPassword.length > 0;
            
            const isValid = hasCurrentPassword && isPasswordStrong && isPasswordMatch;
            submitBtn.disabled = !isValid;
        }

        // 事件监听器
        document.addEventListener('DOMContentLoaded', function() {
            const passwordField = document.getElementById('Password');
            const newPasswordField = document.getElementById('NewPassword');
            const confirmPasswordField = document.getElementById('NewRepeatPassword');
            const pinCodeField = document.getElementById('PinCode');

            // 密码输入事件
            [passwordField, newPasswordField, confirmPasswordField].forEach(field => {
                field.addEventListener('input', validateForm);
            });

            // PIN码格式化
            pinCodeField.addEventListener('input', function(e) {
                this.value = this.value.replace(/[^0-9]/g, '');
            });

            // 初始验证
            validateForm();
        });
    </script>
</body>
</html>
loading