优化结果
This commit is contained in:
878
InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/css/style.css
Normal file
878
InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/css/style.css
Normal file
@@ -0,0 +1,878 @@
|
||||
/* 基础样式重置 */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #2c3e50;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* 容器布局 */
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 头部样式 */
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
padding: 40px 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 1.2rem;
|
||||
opacity: 0.9;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* 主内容区域 */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
/* 输入容器 */
|
||||
.input-container {
|
||||
background: #ffffff;
|
||||
border-radius: 20px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #e8ecf4;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
display: block;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.password-input-wrapper {
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.password-input {
|
||||
width: 100%;
|
||||
padding: 18px 60px 18px 20px;
|
||||
border: 2px solid #e8ecf4;
|
||||
border-radius: 12px;
|
||||
font-size: 1.1rem;
|
||||
font-family: 'Courier New', monospace;
|
||||
background: #f8fafc;
|
||||
transition: all 0.3s ease;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.password-input:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.password-input::placeholder {
|
||||
color: #94a3b8;
|
||||
letter-spacing: normal;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
}
|
||||
|
||||
.toggle-visibility {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
border-radius: 6px;
|
||||
color: #64748b;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.toggle-visibility:hover {
|
||||
background: #f1f5f9;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.input-hint {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: #64748b;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.hint-icon {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* 检测按钮 */
|
||||
.check-btn {
|
||||
width: 100%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 18px 32px;
|
||||
border-radius: 12px;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 20px rgba(102, 126, 234, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.check-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 25px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.check-btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.check-btn:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
/* 结果容器 */
|
||||
.result-container {
|
||||
background: #ffffff;
|
||||
border-radius: 20px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #e8ecf4;
|
||||
animation: slideIn 0.5s ease-out;
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 强度概览 */
|
||||
.strength-overview {
|
||||
margin-bottom: 40px;
|
||||
padding: 30px;
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
||||
border-radius: 16px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.strength-score {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.score-circle {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(from 0deg, #e2e8f0 0deg, #e2e8f0 360deg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.score-circle::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.score-value {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: #2c3e50;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.score-label {
|
||||
font-size: 0.9rem;
|
||||
color: #64748b;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.strength-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.strength-level {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.strength-description {
|
||||
font-size: 1.1rem;
|
||||
color: #64748b;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.strength-bar {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.bar-background {
|
||||
width: 100%;
|
||||
height: 12px;
|
||||
background: #e2e8f0;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.bar-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #ef4444, #f97316, #eab308, #22c55e);
|
||||
border-radius: 6px;
|
||||
width: 0%;
|
||||
transition: width 0.8s ease;
|
||||
}
|
||||
|
||||
.bar-labels {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.85rem;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
/* 详细信息网格 */
|
||||
.details-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 25px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
background: #f8fafc;
|
||||
border-radius: 16px;
|
||||
padding: 25px;
|
||||
border: 1px solid #e2e8f0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.detail-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card-header h3 {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-weight: 500;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
/* 字符类型分析 */
|
||||
.character-types {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.char-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 12px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e2e8f0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.char-type.has-type {
|
||||
background: #dcfce7;
|
||||
border-color: #bbf7d0;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
.char-type.has-type .type-icon {
|
||||
color: #22c55e;
|
||||
}
|
||||
|
||||
.type-icon {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.character-issues {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.issue-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
background: #fef2f2;
|
||||
border: 1px solid #fecaca;
|
||||
border-radius: 8px;
|
||||
color: #dc2626;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.issue-item.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.issue-icon {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* 建议和提示区域 */
|
||||
.recommendations-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
gap: 25px;
|
||||
}
|
||||
|
||||
.recommendations-card,
|
||||
.security-tips-card {
|
||||
background: #f8fafc;
|
||||
border-radius: 16px;
|
||||
padding: 25px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.recommendations-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.recommendations-list li {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 12px 16px;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #e2e8f0;
|
||||
color: #2c3e50;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.recommendations-list li::before {
|
||||
content: '💡';
|
||||
font-size: 1rem;
|
||||
margin-top: 2px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tips-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #e2e8f0;
|
||||
color: #2c3e50;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
font-size: 1rem;
|
||||
margin-top: 2px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 错误容器 */
|
||||
.error-container {
|
||||
background: #ffffff;
|
||||
border-radius: 20px;
|
||||
padding: 50px 40px;
|
||||
text-align: center;
|
||||
box-shadow: 0 10px 40px rgba(239, 68, 68, 0.1);
|
||||
border: 1px solid #fecaca;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 4rem;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.error-container h3 {
|
||||
color: #dc2626;
|
||||
margin-bottom: 15px;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.error-container p {
|
||||
color: #64748b;
|
||||
margin-bottom: 25px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
background: #dc2626;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 14px 28px;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.retry-btn:hover {
|
||||
background: #b91c1c;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* 页脚 */
|
||||
.footer {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: #64748b;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
margin-bottom: 8px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.footer-note {
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 提示框 */
|
||||
.toast {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: #22c55e;
|
||||
color: white;
|
||||
padding: 16px 24px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 20px rgba(34, 197, 94, 0.3);
|
||||
z-index: 1000;
|
||||
animation: toastSlide 0.3s ease-out;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@keyframes toastSlide {
|
||||
from {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 强度等级颜色 */
|
||||
.strength-weak {
|
||||
color: #dc2626 !important;
|
||||
}
|
||||
|
||||
.strength-medium {
|
||||
color: #f59e0b !important;
|
||||
}
|
||||
|
||||
.strength-strong {
|
||||
color: #059669 !important;
|
||||
}
|
||||
|
||||
.strength-very-strong {
|
||||
color: #047857 !important;
|
||||
}
|
||||
|
||||
/* 分数圆圈颜色 */
|
||||
.score-weak {
|
||||
background: conic-gradient(from 0deg, #dc2626 0deg, #dc2626 var(--score-deg), #e2e8f0 var(--score-deg), #e2e8f0 360deg) !important;
|
||||
}
|
||||
|
||||
.score-medium {
|
||||
background: conic-gradient(from 0deg, #f59e0b 0deg, #f59e0b var(--score-deg), #e2e8f0 var(--score-deg), #e2e8f0 360deg) !important;
|
||||
}
|
||||
|
||||
.score-strong {
|
||||
background: conic-gradient(from 0deg, #059669 0deg, #059669 var(--score-deg), #e2e8f0 var(--score-deg), #e2e8f0 360deg) !important;
|
||||
}
|
||||
|
||||
.score-very-strong {
|
||||
background: conic-gradient(from 0deg, #047857 0deg, #047857 var(--score-deg), #e2e8f0 var(--score-deg), #e2e8f0 360deg) !important;
|
||||
}
|
||||
|
||||
/* 平板端适配 (768px - 1024px) */
|
||||
@media (min-width: 768px) and (max-width: 1024px) {
|
||||
.container {
|
||||
max-width: 900px;
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
|
||||
.input-container,
|
||||
.result-container {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.details-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.recommendations-section {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.strength-score {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
gap: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 手机端适配 (最大767px) */
|
||||
@media (max-width: 767px) {
|
||||
.container {
|
||||
padding: 15px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 25px 15px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.input-container,
|
||||
.result-container {
|
||||
padding: 25px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.password-input {
|
||||
padding: 16px 50px 16px 16px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.check-btn {
|
||||
padding: 16px 28px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.strength-overview {
|
||||
padding: 20px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.strength-score {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.score-circle {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.score-circle::before {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
}
|
||||
|
||||
.score-value {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.strength-level {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.details-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.character-types {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.recommendations-section {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.recommendations-card,
|
||||
.security-tips-card {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.toast {
|
||||
right: 15px;
|
||||
left: 15px;
|
||||
top: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* 小屏手机适配 (最大480px) */
|
||||
@media (max-width: 480px) {
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 20px 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.input-container,
|
||||
.result-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.password-input {
|
||||
padding: 14px 45px 14px 14px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.check-btn {
|
||||
padding: 14px 24px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.card-header h3 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* 触摸设备优化 */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
.check-btn,
|
||||
.retry-btn,
|
||||
.toggle-visibility {
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.toggle-visibility {
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 高对比度模式支持 */
|
||||
@media (prefers-contrast: high) {
|
||||
.input-container,
|
||||
.result-container,
|
||||
.detail-card {
|
||||
border: 2px solid #2c3e50;
|
||||
}
|
||||
|
||||
.password-input {
|
||||
border: 2px solid #2c3e50;
|
||||
}
|
||||
}
|
||||
|
||||
/* 减少动画模式支持 */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 深色模式支持 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: #0f172a;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.input-container,
|
||||
.result-container,
|
||||
.detail-card,
|
||||
.recommendations-card,
|
||||
.security-tips-card {
|
||||
background: #1e293b;
|
||||
border-color: #334155;
|
||||
}
|
||||
|
||||
.password-input {
|
||||
background: #334155;
|
||||
border-color: #475569;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.password-input:focus {
|
||||
background: #1e293b;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.strength-overview {
|
||||
background: #1e293b;
|
||||
border-color: #334155;
|
||||
}
|
||||
|
||||
.char-type,
|
||||
.recommendations-list li,
|
||||
.tip-item {
|
||||
background: #334155;
|
||||
border-color: #475569;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 打印样式 */
|
||||
@media print {
|
||||
.header {
|
||||
background: none !important;
|
||||
color: black !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.check-btn,
|
||||
.retry-btn,
|
||||
.toggle-visibility,
|
||||
.toast {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.input-container,
|
||||
.result-container {
|
||||
box-shadow: none !important;
|
||||
border: 1px solid #ccc !important;
|
||||
}
|
||||
}
|
||||
218
InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/index.html
Normal file
218
InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/index.html
Normal file
@@ -0,0 +1,218 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="在线密码强度检测工具,实时分析密码安全性,提供专业的密码安全建议">
|
||||
<meta name="keywords" content="密码强度检测,密码安全,密码分析,在线工具">
|
||||
<title>🔒 密码强度检测器</title>
|
||||
<link rel="preconnect" href="https://60s.api.shumengya.top">
|
||||
<link rel="dns-prefetch" href="https://60s.api.shumengya.top">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<link rel="stylesheet" href="css/background.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header class="header">
|
||||
<h1>🔒 密码强度检测器</h1>
|
||||
<p class="subtitle">实时分析密码安全性,保护您的数字生活</p>
|
||||
</header>
|
||||
|
||||
<main class="main-content">
|
||||
<!-- 密码输入区域 -->
|
||||
<div class="input-container">
|
||||
<div class="input-group">
|
||||
<label for="passwordInput" class="input-label">请输入要检测的密码</label>
|
||||
<div class="password-input-wrapper">
|
||||
<input
|
||||
type="password"
|
||||
id="passwordInput"
|
||||
class="password-input"
|
||||
placeholder="输入您的密码进行安全性检测..."
|
||||
autocomplete="new-password"
|
||||
spellcheck="false"
|
||||
>
|
||||
<button type="button" class="toggle-visibility" id="toggleVisibility" title="显示/隐藏密码">
|
||||
<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>
|
||||
<svg class="eye-off-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display: none;">
|
||||
<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>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="input-hint">
|
||||
<span class="hint-icon">💡</span>
|
||||
<span class="hint-text">输入密码后将实时显示安全性分析结果</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="check-btn" id="checkBtn">
|
||||
<span class="btn-icon">🔍</span>
|
||||
<span class="btn-text">检测密码强度</span>
|
||||
<span class="btn-loading" style="display: none;">检测中...</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 结果显示区域 -->
|
||||
<div class="result-container" id="resultContainer" style="display: none;">
|
||||
<!-- 密码强度概览 -->
|
||||
<div class="strength-overview">
|
||||
<div class="strength-score">
|
||||
<div class="score-circle" id="scoreCircle">
|
||||
<div class="score-value" id="scoreValue">0</div>
|
||||
<div class="score-label">分</div>
|
||||
</div>
|
||||
<div class="strength-info">
|
||||
<div class="strength-level" id="strengthLevel">未知</div>
|
||||
<div class="strength-description" id="strengthDescription">请输入密码进行检测</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="strength-bar">
|
||||
<div class="bar-background">
|
||||
<div class="bar-fill" id="strengthBar"></div>
|
||||
</div>
|
||||
<div class="bar-labels">
|
||||
<span>弱</span>
|
||||
<span>中等</span>
|
||||
<span>强</span>
|
||||
<span>非常强</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 详细信息 -->
|
||||
<div class="details-grid">
|
||||
<div class="detail-card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon">📏</span>
|
||||
<h3>基本信息</h3>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="info-row">
|
||||
<span class="info-label">密码长度:</span>
|
||||
<span class="info-value" id="passwordLength">-</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">熵值:</span>
|
||||
<span class="info-value" id="entropyValue">-</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">破解时间:</span>
|
||||
<span class="info-value" id="crackTime">-</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">字符种类:</span>
|
||||
<span class="info-value" id="characterVariety">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon">🔤</span>
|
||||
<h3>字符分析</h3>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="character-types" id="characterTypes">
|
||||
<div class="char-type" id="hasLowercase">
|
||||
<span class="type-icon">❌</span>
|
||||
<span class="type-text">小写字母</span>
|
||||
</div>
|
||||
<div class="char-type" id="hasUppercase">
|
||||
<span class="type-icon">❌</span>
|
||||
<span class="type-text">大写字母</span>
|
||||
</div>
|
||||
<div class="char-type" id="hasNumbers">
|
||||
<span class="type-icon">❌</span>
|
||||
<span class="type-text">数字</span>
|
||||
</div>
|
||||
<div class="char-type" id="hasSymbols">
|
||||
<span class="type-icon">❌</span>
|
||||
<span class="type-text">特殊符号</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="character-issues" id="characterIssues">
|
||||
<div class="issue-item" id="hasRepeated">
|
||||
<span class="issue-icon">⚠️</span>
|
||||
<span class="issue-text">包含重复字符</span>
|
||||
</div>
|
||||
<div class="issue-item" id="hasSequential">
|
||||
<span class="issue-icon">⚠️</span>
|
||||
<span class="issue-text">包含连续字符</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 建议和提示 -->
|
||||
<div class="recommendations-section">
|
||||
<div class="recommendations-card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon">💡</span>
|
||||
<h3>改进建议</h3>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<ul class="recommendations-list" id="recommendationsList">
|
||||
<li>请输入密码进行分析</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="security-tips-card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon">🛡️</span>
|
||||
<h3>安全提示</h3>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="tips-container" id="securityTips">
|
||||
<div class="tip-item">
|
||||
<span class="tip-icon">🔐</span>
|
||||
<span class="tip-text">使用密码管理器生成和存储复杂密码</span>
|
||||
</div>
|
||||
<div class="tip-item">
|
||||
<span class="tip-icon">🔄</span>
|
||||
<span class="tip-text">为不同账户使用不同的密码</span>
|
||||
</div>
|
||||
<div class="tip-item">
|
||||
<span class="tip-icon">⏰</span>
|
||||
<span class="tip-text">定期更换重要账户的密码</span>
|
||||
</div>
|
||||
<div class="tip-item">
|
||||
<span class="tip-icon">🔒</span>
|
||||
<span class="tip-text">启用双因素认证(2FA)增强安全性</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 错误显示区域 -->
|
||||
<div class="error-container" id="errorContainer" style="display: none;">
|
||||
<div class="error-icon">⚠️</div>
|
||||
<h3>检测失败</h3>
|
||||
<p id="errorMessage">请检查网络连接后重试</p>
|
||||
<button class="retry-btn" id="retryBtn">重新检测</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<p>🔒 保护您的数字安全,从强密码开始</p>
|
||||
<p class="footer-note">本工具不会存储您的密码信息</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- 提示框 -->
|
||||
<div class="toast" id="toast" style="display: none;">
|
||||
<span id="toastMessage">操作成功</span>
|
||||
</div>
|
||||
|
||||
<script src="js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
516
InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/js/script.js
Normal file
516
InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/js/script.js
Normal file
@@ -0,0 +1,516 @@
|
||||
/**
|
||||
* 密码强度检测器
|
||||
* 提供密码强度分析和安全建议
|
||||
*/
|
||||
class PasswordStrengthChecker {
|
||||
constructor() {
|
||||
this.apiUrl = 'https://60s.api.shumengya.top/v2/password/check';
|
||||
this.isChecking = false;
|
||||
this.currentPassword = '';
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化应用
|
||||
*/
|
||||
init() {
|
||||
this.bindEvents();
|
||||
this.setupFormValidation();
|
||||
this.hideResultContainer();
|
||||
this.hideErrorContainer();
|
||||
console.log('密码强度检测器初始化完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定事件监听器
|
||||
*/
|
||||
bindEvents() {
|
||||
// 密码输入框事件
|
||||
const passwordInput = document.getElementById('passwordInput');
|
||||
if (passwordInput) {
|
||||
passwordInput.addEventListener('input', this.handlePasswordInput.bind(this));
|
||||
passwordInput.addEventListener('keypress', this.handleKeyPress.bind(this));
|
||||
}
|
||||
|
||||
// 显示/隐藏密码按钮
|
||||
const toggleBtn = document.getElementById('toggleVisibility');
|
||||
if (toggleBtn) {
|
||||
toggleBtn.addEventListener('click', this.togglePasswordVisibility.bind(this));
|
||||
}
|
||||
|
||||
// 检测按钮
|
||||
const checkBtn = document.getElementById('checkBtn');
|
||||
if (checkBtn) {
|
||||
checkBtn.addEventListener('click', this.handleCheckPassword.bind(this));
|
||||
}
|
||||
|
||||
// 重试按钮
|
||||
const retryBtn = document.getElementById('retryBtn');
|
||||
if (retryBtn) {
|
||||
retryBtn.addEventListener('click', this.handleRetry.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表单验证
|
||||
*/
|
||||
setupFormValidation() {
|
||||
const form = document.querySelector('.input-container');
|
||||
if (form) {
|
||||
form.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
this.handleCheckPassword();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理密码输入
|
||||
*/
|
||||
handlePasswordInput(event) {
|
||||
const password = event.target.value;
|
||||
this.currentPassword = password;
|
||||
|
||||
// 更新按钮状态
|
||||
this.updateCheckButtonState();
|
||||
|
||||
// 如果密码为空,隐藏结果
|
||||
if (!password.trim()) {
|
||||
this.hideResultContainer();
|
||||
this.hideErrorContainer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理键盘事件
|
||||
*/
|
||||
handleKeyPress(event) {
|
||||
if (event.key === 'Enter' && !this.isChecking) {
|
||||
event.preventDefault();
|
||||
this.handleCheckPassword();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换密码可见性
|
||||
*/
|
||||
togglePasswordVisibility() {
|
||||
const passwordInput = document.getElementById('passwordInput');
|
||||
const toggleBtn = document.getElementById('toggleVisibility');
|
||||
|
||||
if (passwordInput && toggleBtn) {
|
||||
const isPassword = passwordInput.type === 'password';
|
||||
passwordInput.type = isPassword ? 'text' : 'password';
|
||||
toggleBtn.innerHTML = isPassword ? '🙈' : '👁️';
|
||||
toggleBtn.title = isPassword ? '隐藏密码' : '显示密码';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新检测按钮状态
|
||||
*/
|
||||
updateCheckButtonState() {
|
||||
const checkBtn = document.getElementById('checkBtn');
|
||||
const hasPassword = this.currentPassword.trim().length > 0;
|
||||
|
||||
if (checkBtn) {
|
||||
checkBtn.disabled = !hasPassword || this.isChecking;
|
||||
|
||||
if (this.isChecking) {
|
||||
checkBtn.innerHTML = '<span class="btn-icon">⏳</span>检测中...';
|
||||
} else if (hasPassword) {
|
||||
checkBtn.innerHTML = '<span class="btn-icon">🔍</span>检测密码强度';
|
||||
} else {
|
||||
checkBtn.innerHTML = '<span class="btn-icon">🔍</span>请输入密码';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理密码检测
|
||||
*/
|
||||
async handleCheckPassword() {
|
||||
const password = this.currentPassword.trim();
|
||||
|
||||
if (!password) {
|
||||
this.showToast('请输入要检测的密码', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isChecking) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.setLoadingState(true);
|
||||
this.hideErrorContainer();
|
||||
|
||||
const result = await this.checkPasswordStrength(password);
|
||||
|
||||
if (result.code === 200 && result.data) {
|
||||
this.displayResults(result.data);
|
||||
this.showResultContainer();
|
||||
this.showToast('密码强度检测完成', 'success');
|
||||
} else {
|
||||
throw new Error(result.message || '检测失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('密码检测错误:', error);
|
||||
this.showError(error.message || '检测服务暂时不可用,请稍后重试');
|
||||
} finally {
|
||||
this.setLoadingState(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用API检测密码强度
|
||||
*/
|
||||
async checkPasswordStrength(password) {
|
||||
const url = new URL(this.apiUrl);
|
||||
url.searchParams.append('password', password);
|
||||
url.searchParams.append('encoding', 'utf-8');
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示检测结果
|
||||
*/
|
||||
displayResults(data) {
|
||||
this.updateStrengthOverview(data);
|
||||
this.updateDetailedInfo(data);
|
||||
this.updateRecommendations(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新强度概览
|
||||
*/
|
||||
updateStrengthOverview(data) {
|
||||
// 更新分数圆圈
|
||||
const scoreCircle = document.getElementById('scoreCircle');
|
||||
const scoreValue = document.getElementById('scoreValue');
|
||||
const strengthLevel = document.getElementById('strengthLevel');
|
||||
const strengthDescription = document.getElementById('strengthDescription');
|
||||
const barFill = document.getElementById('strengthBar');
|
||||
|
||||
if (scoreValue) {
|
||||
scoreValue.textContent = data.score || 0;
|
||||
}
|
||||
|
||||
if (strengthLevel) {
|
||||
strengthLevel.textContent = this.getStrengthText(data.strength);
|
||||
const strengthClass = this.getStrengthClass(data.strength);
|
||||
strengthLevel.className = `strength-level strength-${strengthClass}`;
|
||||
}
|
||||
|
||||
if (strengthDescription) {
|
||||
strengthDescription.textContent = this.getStrengthDescription(data.strength);
|
||||
}
|
||||
|
||||
// 更新分数圆圈
|
||||
if (scoreCircle) {
|
||||
const percentage = (data.score / 100) * 360;
|
||||
scoreCircle.style.setProperty('--score-deg', `${percentage}deg`);
|
||||
// 将中文强度转换为CSS类名
|
||||
const strengthClass = this.getStrengthClass(data.strength);
|
||||
scoreCircle.className = `score-circle score-${strengthClass}`;
|
||||
}
|
||||
|
||||
// 更新强度条
|
||||
if (barFill) {
|
||||
setTimeout(() => {
|
||||
barFill.style.width = `${data.score}%`;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新详细信息
|
||||
*/
|
||||
updateDetailedInfo(data) {
|
||||
// 基本信息
|
||||
this.updateElement('passwordLength', data.length || 0);
|
||||
this.updateElement('entropyValue', data.entropy ? data.entropy.toFixed(2) : '0.00');
|
||||
this.updateElement('crackTime', data.time_to_crack || '未知');
|
||||
|
||||
// 字符类型分析
|
||||
this.updateCharacterAnalysis(data.character_analysis || {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新字符类型分析
|
||||
*/
|
||||
updateCharacterAnalysis(analysis) {
|
||||
const types = {
|
||||
'has_lowercase': { element: 'hasLowercase', label: '小写字母', icon: '🔤' },
|
||||
'has_uppercase': { element: 'hasUppercase', label: '大写字母', icon: '🔠' },
|
||||
'has_numbers': { element: 'hasNumbers', label: '数字', icon: '🔢' },
|
||||
'has_symbols': { element: 'hasSymbols', label: '特殊符号', icon: '🔣' }
|
||||
};
|
||||
|
||||
Object.keys(types).forEach(key => {
|
||||
const element = document.getElementById(types[key].element);
|
||||
if (element) {
|
||||
const hasType = analysis[key] || false;
|
||||
element.className = `char-type ${hasType ? 'has-type' : ''}`;
|
||||
element.innerHTML = `
|
||||
<span class="type-icon">${hasType ? '✅' : '❌'}</span>
|
||||
<span>${types[key].label}</span>
|
||||
`;
|
||||
}
|
||||
});
|
||||
|
||||
// 更新字符种类数量
|
||||
this.updateElement('characterVariety', analysis.character_variety || 0);
|
||||
|
||||
// 更新问题提示
|
||||
this.updateCharacterIssues(analysis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新字符问题提示
|
||||
*/
|
||||
updateCharacterIssues(analysis) {
|
||||
const issues = [
|
||||
{ id: 'hasRepeated', condition: analysis.has_repeated, text: '包含重复字符' },
|
||||
{ id: 'hasSequential', condition: analysis.has_sequential, text: '包含连续字符' }
|
||||
];
|
||||
|
||||
issues.forEach(issue => {
|
||||
const element = document.getElementById(issue.id);
|
||||
if (element) {
|
||||
if (issue.condition) {
|
||||
element.style.display = 'flex';
|
||||
element.innerHTML = `
|
||||
<span class="issue-icon">⚠️</span>
|
||||
<span class="issue-text">${issue.text}</span>
|
||||
`;
|
||||
} else {
|
||||
element.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新建议和提示
|
||||
*/
|
||||
updateRecommendations(data) {
|
||||
// 更新建议列表
|
||||
const recommendationsList = document.getElementById('recommendationsList');
|
||||
if (recommendationsList && data.recommendations) {
|
||||
recommendationsList.innerHTML = '';
|
||||
data.recommendations.forEach(recommendation => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = recommendation;
|
||||
recommendationsList.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
// 更新安全提示
|
||||
const tipsContainer = document.getElementById('securityTips');
|
||||
if (tipsContainer && data.security_tips) {
|
||||
tipsContainer.innerHTML = '';
|
||||
data.security_tips.forEach((tip, index) => {
|
||||
const tipElement = document.createElement('div');
|
||||
tipElement.className = 'tip-item';
|
||||
tipElement.innerHTML = `
|
||||
<span class="tip-icon">${this.getTipIcon(index)}</span>
|
||||
<span class="tip-text">${tip}</span>
|
||||
`;
|
||||
tipsContainer.appendChild(tipElement);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提示图标
|
||||
*/
|
||||
getTipIcon(index) {
|
||||
const icons = ['🛡️', '🔐', '⚡', '🎯', '💡', '🔄'];
|
||||
return icons[index % icons.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取强度文本
|
||||
*/
|
||||
getStrengthText(strength) {
|
||||
// API直接返回中文强度,无需映射
|
||||
return strength || '未知';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取强度CSS类名
|
||||
*/
|
||||
getStrengthClass(strength) {
|
||||
const classMap = {
|
||||
'弱': 'weak',
|
||||
'中等': 'medium',
|
||||
'强': 'strong',
|
||||
'非常强': 'very-strong'
|
||||
};
|
||||
return classMap[strength] || 'unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取强度描述
|
||||
*/
|
||||
getStrengthDescription(strength) {
|
||||
const descriptions = {
|
||||
'弱': '密码强度较弱,建议增加复杂度',
|
||||
'中等': '密码强度中等,可以进一步优化',
|
||||
'强': '密码强度良好,安全性较高',
|
||||
'非常强': '密码强度非常好,安全性很高'
|
||||
};
|
||||
return descriptions[strength] || '无法评估密码强度';
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置加载状态
|
||||
*/
|
||||
setLoadingState(loading) {
|
||||
this.isChecking = loading;
|
||||
this.updateCheckButtonState();
|
||||
|
||||
const passwordInput = document.getElementById('passwordInput');
|
||||
if (passwordInput) {
|
||||
passwordInput.disabled = loading;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示结果容器
|
||||
*/
|
||||
showResultContainer() {
|
||||
const container = document.getElementById('resultContainer');
|
||||
if (container) {
|
||||
container.style.display = 'block';
|
||||
container.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏结果容器
|
||||
*/
|
||||
hideResultContainer() {
|
||||
const container = document.getElementById('resultContainer');
|
||||
if (container) {
|
||||
container.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示错误
|
||||
*/
|
||||
showError(message) {
|
||||
const errorContainer = document.getElementById('errorContainer');
|
||||
const errorMessage = document.getElementById('errorMessage');
|
||||
|
||||
if (errorContainer && errorMessage) {
|
||||
errorMessage.textContent = message;
|
||||
errorContainer.style.display = 'block';
|
||||
this.hideResultContainer();
|
||||
errorContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏错误容器
|
||||
*/
|
||||
hideErrorContainer() {
|
||||
const container = document.getElementById('errorContainer');
|
||||
if (container) {
|
||||
container.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理重试
|
||||
*/
|
||||
handleRetry() {
|
||||
this.hideErrorContainer();
|
||||
const passwordInput = document.getElementById('passwordInput');
|
||||
if (passwordInput) {
|
||||
passwordInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新元素内容
|
||||
*/
|
||||
updateElement(id, content) {
|
||||
const element = document.getElementById(id);
|
||||
if (element) {
|
||||
element.textContent = content;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示提示消息
|
||||
*/
|
||||
showToast(message, type = 'success') {
|
||||
const toast = document.getElementById('toast');
|
||||
const toastMessage = document.getElementById('toastMessage');
|
||||
|
||||
if (toast && toastMessage) {
|
||||
toastMessage.textContent = message;
|
||||
toast.className = `toast toast-${type}`;
|
||||
toast.style.display = 'block';
|
||||
|
||||
// 3秒后自动隐藏
|
||||
setTimeout(() => {
|
||||
toast.style.display = 'none';
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载完成后初始化
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
try {
|
||||
window.passwordChecker = new PasswordStrengthChecker();
|
||||
console.log('密码强度检测器已启动');
|
||||
} catch (error) {
|
||||
console.error('初始化失败:', error);
|
||||
}
|
||||
});
|
||||
|
||||
// 页面可见性变化处理
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (document.visibilityState === 'visible' && window.passwordChecker) {
|
||||
console.log('页面重新激活');
|
||||
}
|
||||
});
|
||||
|
||||
// 全局错误处理
|
||||
window.addEventListener('error', (event) => {
|
||||
console.error('全局错误:', event.error);
|
||||
if (window.passwordChecker) {
|
||||
window.passwordChecker.showToast('发生了意外错误,请刷新页面重试', 'error');
|
||||
}
|
||||
});
|
||||
|
||||
// 网络状态监听
|
||||
window.addEventListener('online', () => {
|
||||
if (window.passwordChecker) {
|
||||
window.passwordChecker.showToast('网络连接已恢复', 'success');
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('offline', () => {
|
||||
if (window.passwordChecker) {
|
||||
window.passwordChecker.showToast('网络连接已断开', 'error');
|
||||
}
|
||||
});
|
||||
37
InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/返回接口.json
Normal file
37
InfoGenie-frontend/public/60sapi/实用功能/密码强度检测/返回接口.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841",
|
||||
"data": {
|
||||
"password": "adasdasdasdadasd",
|
||||
"length": 16,
|
||||
"score": 68,
|
||||
"strength": "中等",
|
||||
"entropy": 75.21,
|
||||
"time_to_crack": "数百万年",
|
||||
"character_analysis": {
|
||||
"has_lowercase": true,
|
||||
"has_uppercase": false,
|
||||
"has_numbers": false,
|
||||
"has_symbols": false,
|
||||
"has_repeated": false,
|
||||
"has_sequential": true,
|
||||
"character_variety": 26
|
||||
},
|
||||
"recommendations": [
|
||||
"建议包含大写字母",
|
||||
"建议包含数字",
|
||||
"建议包含特殊符号",
|
||||
"避免使用连续序列字符"
|
||||
],
|
||||
"security_tips": [
|
||||
"使用密码管理器生成和存储复杂密码",
|
||||
"为不同账户使用不同的密码",
|
||||
"定期更换重要账户的密码",
|
||||
"启用双因素认证(2FA)增强安全性",
|
||||
"避免在公共场合输入密码",
|
||||
"不要将密码保存在浏览器中(除非使用可信的密码管理器)",
|
||||
"避免使用个人信息作为密码",
|
||||
"长密码比复杂密码更安全"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user