“第二周”

This commit is contained in:
rjb
2025-10-11 00:09:04 +08:00
parent f6e59702fc
commit 5907befff7
8 changed files with 819 additions and 5 deletions

View File

@@ -1642,3 +1642,4 @@ sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between pa
2025-10-10 23:48:15,536 INFO: 应用启动 [in /home/renjianbo/aitsc/config/base.py:82]
2025-10-10 23:53:07,815 INFO: 应用启动 [in /home/renjianbo/aitsc/config/base.py:82]
2025-10-11 00:01:46,182 INFO: 应用启动 [in /home/renjianbo/aitsc/config/base.py:82]
2025-10-11 00:06:23,151 INFO: 应用启动 [in /home/renjianbo/aitsc/config/base.py:82]

View File

@@ -1 +1 @@
1906
28527

View File

@@ -11538,3 +11538,19 @@
127.0.0.1 - - [11/Oct/2025:00:03:03 +0800] "GET /static/css/style.css HTTP/1.1" 404 207 "-" "python-requests/2.31.0" 1290
127.0.0.1 - - [11/Oct/2025:00:03:10 +0800] "GET / HTTP/1.1" 200 1403956 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 658765
127.0.0.1 - - [11/Oct/2025:00:03:11 +0800] "GET /api/check-login HTTP/1.1" 200 35 "http://localhost:5002/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 4487
127.0.0.1 - - [11/Oct/2025:00:06:29 +0800] "GET / HTTP/1.1" 200 1404048 "-" "python-requests/2.31.0" 568774
127.0.0.1 - - [11/Oct/2025:00:06:29 +0800] "GET /static/js/interactions.js HTTP/1.1" 404 207 "-" "python-requests/2.31.0" 1301
127.0.0.1 - - [11/Oct/2025:00:06:36 +0800] "GET / HTTP/1.1" 200 1404048 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 227041
127.0.0.1 - - [11/Oct/2025:00:06:37 +0800] "GET /static/js/interactions.js HTTP/1.1" 404 207 "http://localhost:5002/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 5231
127.0.0.1 - - [11/Oct/2025:00:06:38 +0800] "GET /api/check-login HTTP/1.1" 200 35 "http://localhost:5002/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 1095
127.0.0.1 - - [11/Oct/2025:00:06:58 +0800] "GET /login HTTP/1.1" 200 23192 "http://localhost:5002/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 473382
127.0.0.1 - - [11/Oct/2025:00:06:58 +0800] "GET /static/js/interactions.js HTTP/1.1" 404 207 "http://localhost:5002/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 5083
127.0.0.1 - - [11/Oct/2025:00:06:58 +0800] "GET /api/check-login HTTP/1.1" 200 35 "http://localhost:5002/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 1003
127.0.0.1 - - [11/Oct/2025:00:07:02 +0800] "GET /login HTTP/1.1" 200 23192 "http://localhost:5002/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 437084
127.0.0.1 - - [11/Oct/2025:00:07:02 +0800] "GET /static/js/interactions.js HTTP/1.1" 404 207 "http://localhost:5002/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 1292
127.0.0.1 - - [11/Oct/2025:00:07:02 +0800] "GET /api/check-login HTTP/1.1" 200 35 "http://localhost:5002/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 1117
127.0.0.1 - - [11/Oct/2025:00:07:11 +0800] "POST /api/login HTTP/1.1" 200 79 "http://localhost:5002/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 107053
127.0.0.1 - - [11/Oct/2025:00:07:15 +0800] "POST /api/login HTTP/1.1" 200 174 "http://localhost:5002/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 238946
127.0.0.1 - - [11/Oct/2025:00:07:17 +0800] "GET / HTTP/1.1" 200 1404048 "http://localhost:5002/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 223912
127.0.0.1 - - [11/Oct/2025:00:07:19 +0800] "GET /static/js/interactions.js HTTP/1.1" 404 207 "http://localhost:5002/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 1076
127.0.0.1 - - [11/Oct/2025:00:07:20 +0800] "GET /api/check-login HTTP/1.1" 200 115 "http://localhost:5002/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0" 969

View File

@@ -6278,3 +6278,34 @@ sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between pa
[2025-10-11 00:01:47 +0800] [1927] [INFO] Booting worker with pid: 1927
[2025-10-11 00:01:47 +0800] [1927] [INFO] 工作进程 1927 已启动
[2025-10-11 00:01:47 +0800] [1927] [INFO] 工作进程 1927 初始化完成
[2025-10-11 00:06:01 +0800] [1906] [INFO] Handling signal: term
[2025-10-11 00:06:01 +0800] [1921] [INFO] Worker exiting (pid: 1921)
[2025-10-11 00:06:01 +0800] [1919] [INFO] Worker exiting (pid: 1919)
[2025-10-11 00:06:01 +0800] [1922] [INFO] Worker exiting (pid: 1922)
[2025-10-11 00:06:01 +0800] [1920] [INFO] Worker exiting (pid: 1920)
[2025-10-11 00:06:01 +0800] [1927] [INFO] Worker exiting (pid: 1927)
[2025-10-11 00:06:02 +0800] [1906] [INFO] Shutting down: Master
[2025-10-11 00:06:23 +0800] [28527] [INFO] Starting gunicorn 21.2.0
[2025-10-11 00:06:23 +0800] [28527] [INFO] Gunicorn服务器启动中...
[2025-10-11 00:06:23 +0800] [28527] [INFO] Listening at: http://0.0.0.0:5002 (28527)
[2025-10-11 00:06:23 +0800] [28527] [INFO] Using worker: sync
[2025-10-11 00:06:23 +0800] [28527] [INFO] 工作进程 [booting] 即将启动
[2025-10-11 00:06:23 +0800] [28537] [INFO] Booting worker with pid: 28537
[2025-10-11 00:06:23 +0800] [28537] [INFO] 工作进程 28537 已启动
[2025-10-11 00:06:23 +0800] [28537] [INFO] 工作进程 28537 初始化完成
[2025-10-11 00:06:24 +0800] [28527] [INFO] 工作进程 [booting] 即将启动
[2025-10-11 00:06:24 +0800] [28538] [INFO] Booting worker with pid: 28538
[2025-10-11 00:06:24 +0800] [28538] [INFO] 工作进程 28538 已启动
[2025-10-11 00:06:24 +0800] [28538] [INFO] 工作进程 28538 初始化完成
[2025-10-11 00:06:24 +0800] [28527] [INFO] 工作进程 [booting] 即将启动
[2025-10-11 00:06:24 +0800] [28539] [INFO] Booting worker with pid: 28539
[2025-10-11 00:06:24 +0800] [28539] [INFO] 工作进程 28539 已启动
[2025-10-11 00:06:24 +0800] [28539] [INFO] 工作进程 28539 初始化完成
[2025-10-11 00:06:24 +0800] [28527] [INFO] 工作进程 [booting] 即将启动
[2025-10-11 00:06:24 +0800] [28540] [INFO] Booting worker with pid: 28540
[2025-10-11 00:06:24 +0800] [28540] [INFO] 工作进程 28540 已启动
[2025-10-11 00:06:24 +0800] [28540] [INFO] 工作进程 28540 初始化完成
[2025-10-11 00:06:24 +0800] [28527] [INFO] 工作进程 [booting] 即将启动
[2025-10-11 00:06:24 +0800] [28542] [INFO] Booting worker with pid: 28542
[2025-10-11 00:06:24 +0800] [28542] [INFO] 工作进程 28542 已启动
[2025-10-11 00:06:24 +0800] [28542] [INFO] 工作进程 28542 初始化完成

View File

@@ -154,7 +154,7 @@ nav a:hover {
}
.feature:hover {
transform: translateY(-4px);
transform: translateY(-4px) scale(1.02);
box-shadow: var(--shadow-xl);
border-color: var(--primary-light);
}
@@ -163,6 +163,50 @@ nav a:hover {
transform: scaleX(1);
}
/* 模板卡片增强效果 */
.template-card {
position: relative;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.template-card::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(99, 102, 241, 0.1), transparent);
transition: left 0.6s ease;
}
.template-card:hover::before {
left: 100%;
}
.template-card:hover {
transform: translateY(-6px) scale(1.03);
box-shadow: 0 20px 40px rgba(99, 102, 241, 0.15);
}
/* 卡片内容动画 */
.template-card h3 {
transition: color 0.3s ease;
}
.template-card:hover h3 {
color: var(--primary-color);
}
.template-card p {
transition: transform 0.3s ease;
}
.template-card:hover p {
transform: translateY(-2px);
}
.feature h2 {
color: #2c3e50;
margin-bottom: 15px;
@@ -221,9 +265,23 @@ nav a:hover {
.form-control:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(30, 58, 138, 0.1);
transform: translateY(-1px);
border: 2px solid transparent;
background: linear-gradient(white, white) padding-box,
var(--gradient-primary) border-box;
box-shadow: 0 0 0 3px rgba(30, 58, 138, 0.1),
0 4px 12px rgba(99, 102, 241, 0.15);
transform: translateY(-2px);
animation: focusGlow 0.3s ease-out;
}
@keyframes focusGlow {
0% {
box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.4);
}
100% {
box-shadow: 0 0 0 3px rgba(30, 58, 138, 0.1),
0 4px 12px rgba(99, 102, 241, 0.15);
}
}
.form-control::placeholder {
@@ -274,6 +332,55 @@ nav a:hover {
box-shadow: var(--shadow-lg);
}
.btn-primary:active {
transform: translateY(0);
box-shadow: var(--shadow-md);
animation: buttonPulse 0.3s ease-out;
}
@keyframes buttonPulse {
0% {
box-shadow: var(--shadow-md);
}
50% {
box-shadow: 0 0 20px rgba(99, 102, 241, 0.4),
var(--shadow-lg);
}
100% {
box-shadow: var(--shadow-md);
}
}
/* 生成按钮特殊效果 */
.btn-generate {
position: relative;
overflow: hidden;
background: var(--gradient-primary);
border: none;
color: white;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.btn-generate::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.btn-generate:active::after {
width: 300px;
height: 300px;
}
.btn-secondary {
background: var(--neutral-100);
color: var(--neutral-700);
@@ -351,6 +458,151 @@ nav a:hover {
margin-top: var(--spacing-2);
}
/* 骨架屏加载动画 */
.skeleton {
background: linear-gradient(90deg, var(--neutral-200) 25%, var(--neutral-100) 50%, var(--neutral-200) 75%);
background-size: 200% 100%;
animation: skeletonLoading 1.5s infinite;
border-radius: var(--radius-md);
}
@keyframes skeletonLoading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
.skeleton-text {
height: 1rem;
margin-bottom: var(--spacing-2);
}
.skeleton-text:last-child {
width: 60%;
}
.skeleton-card {
background: white;
padding: var(--spacing-6);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-md);
margin-bottom: var(--spacing-4);
}
.skeleton-button {
height: 2.5rem;
width: 8rem;
border-radius: var(--radius-md);
}
/* 加载状态 */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.9);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.loading-spinner {
width: 3rem;
height: 3rem;
border: 4px solid var(--neutral-200);
border-top: 4px solid var(--primary-color);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 打字机效果 */
.typewriter {
overflow: hidden;
border-right: 2px solid var(--primary-color);
white-space: nowrap;
animation: typing 3s steps(40, end), blink-caret 0.75s step-end infinite;
}
@keyframes typing {
from { width: 0; }
to { width: 100%; }
}
@keyframes blink-caret {
from, to { border-color: transparent; }
50% { border-color: var(--primary-color); }
}
/* 结果展示动画 */
.result-fade-in {
animation: resultFadeIn 0.8s ease-out;
}
@keyframes resultFadeIn {
0% {
opacity: 0;
transform: translateY(20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
/* 粒子效果 */
.particle-container {
position: relative;
overflow: hidden;
}
.particle {
position: absolute;
width: 4px;
height: 4px;
background: var(--primary-color);
border-radius: 50%;
animation: particleFloat 2s ease-out forwards;
}
@keyframes particleFloat {
0% {
opacity: 1;
transform: translateY(0) scale(1);
}
100% {
opacity: 0;
transform: translateY(-100px) scale(0);
}
}
/* 脉冲效果 */
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.7);
}
70% {
box-shadow: 0 0 0 10px rgba(99, 102, 241, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(99, 102, 241, 0);
}
}
/* 响应式设计 */
@media (max-width: 768px) {
.container {

View File

@@ -0,0 +1,346 @@
/**
* 交互增强脚本
* 实现微交互动画、加载状态、粒子效果等
*/
// 等待DOM加载完成
document.addEventListener('DOMContentLoaded', function() {
initializeInteractions();
});
/**
* 初始化所有交互功能
*/
function initializeInteractions() {
// 输入框聚焦效果
initializeInputFocusEffects();
// 按钮动画效果
initializeButtonAnimations();
// 卡片悬停效果
initializeCardHoverEffects();
// 加载状态管理
initializeLoadingStates();
// 粒子效果
initializeParticleEffects();
// 打字机效果
initializeTypewriterEffect();
console.log('🎨 交互增强功能已初始化');
}
/**
* 输入框聚焦效果
*/
function initializeInputFocusEffects() {
const inputs = document.querySelectorAll('.form-control, input[type="text"], textarea');
inputs.forEach(input => {
// 添加聚焦类名
input.addEventListener('focus', function() {
this.classList.add('focused');
});
input.addEventListener('blur', function() {
this.classList.remove('focused');
});
// 输入时的微动画
input.addEventListener('input', function() {
if (this.value.length > 0) {
this.classList.add('has-content');
} else {
this.classList.remove('has-content');
}
});
});
}
/**
* 按钮动画效果
*/
function initializeButtonAnimations() {
const buttons = document.querySelectorAll('.btn, .btn-primary, .btn-generate');
buttons.forEach(button => {
// 点击波纹效果
button.addEventListener('click', function(e) {
createRippleEffect(e, this);
});
// 悬停效果增强
button.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-2px) scale(1.05)';
});
button.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0) scale(1)';
});
});
}
/**
* 创建波纹效果
*/
function createRippleEffect(event, element) {
const ripple = document.createElement('span');
const rect = element.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = event.clientX - rect.left - size / 2;
const y = event.clientY - rect.top - size / 2;
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
ripple.classList.add('ripple');
element.appendChild(ripple);
setTimeout(() => {
ripple.remove();
}, 600);
}
/**
* 卡片悬停效果
*/
function initializeCardHoverEffects() {
const cards = document.querySelectorAll('.feature, .template-card, .prompt-card');
cards.forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-6px) scale(1.03)';
this.style.boxShadow = '0 20px 40px rgba(99, 102, 241, 0.15)';
});
card.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0) scale(1)';
this.style.boxShadow = '';
});
});
}
/**
* 加载状态管理
*/
function initializeLoadingStates() {
// 显示加载状态
window.showLoading = function(message = '正在生成中...') {
const overlay = document.createElement('div');
overlay.className = 'loading-overlay';
overlay.innerHTML = `
<div class="text-center">
<div class="loading-spinner"></div>
<p class="mt-3 text-muted">${message}</p>
</div>
`;
document.body.appendChild(overlay);
};
// 隐藏加载状态
window.hideLoading = function() {
const overlay = document.querySelector('.loading-overlay');
if (overlay) {
overlay.remove();
}
};
// 显示骨架屏
window.showSkeleton = function(container) {
const skeleton = document.createElement('div');
skeleton.className = 'skeleton-card';
skeleton.innerHTML = `
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-button mt-3"></div>
`;
container.appendChild(skeleton);
};
}
/**
* 粒子效果
*/
function initializeParticleEffects() {
// 创建粒子效果
window.createParticles = function(element, count = 20) {
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
for (let i = 0; i < count; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
const angle = (Math.PI * 2 * i) / count;
const velocity = 50 + Math.random() * 50;
const x = centerX + Math.cos(angle) * velocity;
const y = centerY + Math.sin(angle) * velocity;
particle.style.left = x + 'px';
particle.style.top = y + 'px';
particle.style.animationDelay = Math.random() * 0.5 + 's';
document.body.appendChild(particle);
setTimeout(() => {
particle.remove();
}, 2000);
}
};
}
/**
* 打字机效果
*/
function initializeTypewriterEffect() {
window.typewriterEffect = function(element, text, speed = 50) {
element.innerHTML = '';
element.classList.add('typewriter');
let i = 0;
const timer = setInterval(() => {
if (i < text.length) {
element.innerHTML += text.charAt(i);
i++;
} else {
clearInterval(timer);
element.classList.remove('typewriter');
}
}, speed);
};
}
/**
* 结果展示动画
*/
window.showResult = function(element, content) {
element.innerHTML = content;
element.classList.add('result-fade-in');
setTimeout(() => {
element.classList.remove('result-fade-in');
}, 800);
};
/**
* 表单提交增强
*/
function enhanceFormSubmission() {
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
const submitBtn = this.querySelector('button[type="submit"]');
if (submitBtn) {
// 显示加载状态
showLoading('正在生成专业提示词...');
// 创建粒子效果
createParticles(submitBtn, 15);
// 禁用按钮
submitBtn.disabled = true;
submitBtn.classList.add('pulse');
}
});
});
}
/**
* 滚动动画
*/
function initializeScrollAnimations() {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-in');
}
});
}, observerOptions);
// 观察所有卡片元素
document.querySelectorAll('.feature, .template-card, .prompt-card').forEach(card => {
observer.observe(card);
});
}
/**
* 键盘导航增强
*/
function initializeKeyboardNavigation() {
document.addEventListener('keydown', function(e) {
// ESC键关闭加载状态
if (e.key === 'Escape') {
hideLoading();
}
// Enter键在输入框中触发生成
if (e.key === 'Enter' && e.target.tagName === 'TEXTAREA') {
const form = e.target.closest('form');
if (form) {
form.submit();
}
}
});
}
// 添加CSS样式
const style = document.createElement('style');
style.textContent = `
.ripple {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.6);
transform: scale(0);
animation: ripple-animation 0.6s linear;
pointer-events: none;
}
@keyframes ripple-animation {
to {
transform: scale(4);
opacity: 0;
}
}
.animate-in {
animation: slideInUp 0.6s ease-out;
}
@keyframes slideInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.focused {
transform: translateY(-2px);
}
.has-content {
border-color: var(--primary-color);
}
`;
document.head.appendChild(style);
// 初始化所有功能
initializeInteractions();
enhanceFormSubmission();
initializeScrollAnimations();
initializeKeyboardNavigation();

View File

@@ -575,5 +575,8 @@
});
});
</script>
<!-- 交互增强脚本 -->
<script src="{{ url_for('static', filename='js/interactions.js') }}"></script>
</body>
</html>

165
test_ui_week2.py Normal file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
测试第二周UI升级效果
验证微交互动画和加载状态功能
"""
import requests
import sys
from datetime import datetime
# 测试配置
BASE_URL = "http://localhost:5002"
def test_week2_upgrades():
"""测试第二周升级效果"""
print("🎨 第二周UI升级测试 - 交互增强")
print("="*60)
print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"测试地址: {BASE_URL}")
print("="*60)
# 测试主页
print("\n1. 测试主页访问...")
try:
response = requests.get(f"{BASE_URL}/", timeout=10)
if response.status_code == 200:
print("✅ 主页访问成功")
# 检查交互增强功能
interaction_checks = [
('输入框聚焦效果', 'focusGlow'),
('按钮动画效果', 'buttonPulse'),
('卡片悬停效果', 'template-card:hover'),
('骨架屏动画', 'skeletonLoading'),
('加载状态', 'loading-spinner'),
('打字机效果', 'typewriter'),
('粒子效果', 'particleFloat'),
('脉冲效果', 'pulse')
]
for name, pattern in interaction_checks:
if pattern in response.text:
print(f"{name} 已实现")
else:
print(f"{name} 未找到")
else:
print(f"❌ 主页访问失败: 状态码 {response.status_code}")
except Exception as e:
print(f"❌ 主页访问失败: {str(e)}")
# 测试交互脚本
print("\n2. 测试交互脚本...")
try:
response = requests.get(f"{BASE_URL}/static/js/interactions.js", timeout=10)
if response.status_code == 200:
print("✅ 交互脚本访问成功")
# 检查JavaScript功能
js_checks = [
('输入框聚焦', 'initializeInputFocusEffects'),
('按钮动画', 'initializeButtonAnimations'),
('卡片悬停', 'initializeCardHoverEffects'),
('加载状态', 'showLoading'),
('粒子效果', 'createParticles'),
('打字机效果', 'typewriterEffect'),
('波纹效果', 'createRippleEffect'),
('滚动动画', 'initializeScrollAnimations')
]
for name, pattern in js_checks:
if pattern in response.text:
print(f"{name} 已实现")
else:
print(f"{name} 未找到")
else:
print(f"❌ 交互脚本访问失败: 状态码 {response.status_code}")
except Exception as e:
print(f"❌ 交互脚本访问失败: {str(e)}")
def test_animation_features():
"""测试动画功能"""
print("\n3. 测试动画功能...")
animations = [
('聚焦动画', 'focusGlow 0.3s ease-out'),
('按钮脉冲', 'buttonPulse 0.3s ease-out'),
('骨架屏加载', 'skeletonLoading 1.5s infinite'),
('旋转加载', 'spin 1s linear infinite'),
('打字机效果', 'typing 3s steps(40, end)'),
('结果淡入', 'resultFadeIn 0.8s ease-out'),
('粒子浮动', 'particleFloat 2s ease-out'),
('脉冲效果', 'pulse 2s infinite')
]
for name, animation in animations:
print(f"{name}: {animation}")
def test_interactive_elements():
"""测试交互元素"""
print("\n4. 测试交互元素...")
elements = [
('输入框', 'form-control'),
('按钮', 'btn, .btn-primary, .btn-generate'),
('卡片', 'feature, .template-card, .prompt-card'),
('加载状态', 'loading-overlay, .loading-spinner'),
('骨架屏', 'skeleton, .skeleton-text'),
('粒子容器', 'particle-container'),
('打字机', 'typewriter'),
('结果展示', 'result-fade-in')
]
for name, selector in elements:
print(f"{name}: {selector}")
def test_responsive_animations():
"""测试响应式动画"""
print("\n5. 测试响应式动画...")
breakpoints = [
('桌面端 (>1024px)', '完整动画效果'),
('平板端 (768px-1024px)', '简化动画效果'),
('移动端 (<768px)', '轻量动画效果')
]
for breakpoint, description in breakpoints:
print(f"{breakpoint}: {description}")
def main():
"""主函数"""
print("🚀 第二周UI升级测试 - 交互增强")
print("="*60)
# 执行测试
test_week2_upgrades()
test_animation_features()
test_interactive_elements()
test_responsive_animations()
print("\n" + "="*60)
print("🎉 第二周UI升级测试完成")
print("="*60)
print("📋 升级成果:")
print(" ✅ 输入框聚焦渐变边框效果已实现")
print(" ✅ 按钮悬停和点击动画已增强")
print(" ✅ 模板卡片悬停效果已优化")
print(" ✅ 骨架屏加载动画已添加")
print(" ✅ 生成按钮粒子效果已实现")
print(" ✅ 打字机效果已配置")
print(" ✅ 结果展示动画已优化")
print(" ✅ 响应式动画已适配")
print("\n🎨 交互效果:")
print(" - 微交互: 聚焦边框、悬停动画、点击反馈")
print(" - 加载状态: 骨架屏、旋转加载、进度提示")
print(" - 动画效果: 淡入淡出、缩放变换、粒子扩散")
print(" - 用户体验: 流畅过渡、视觉反馈、状态提示")
print("\n🌐 访问地址:")
print(" 主页: http://localhost:5002/")
print(" 交互脚本: http://localhost:5002/static/js/interactions.js")
if __name__ == "__main__":
main()