164
社区成员
发帖
与我相关
我的任务
分享| Course | 2501_MU_SE_FZU |
|---|---|
| Assignment Requirement | Teamwork—beta Spring |
| Team name | FocusFlow |
| Author | Zhihao Liu |
| Goal of this Assignment | Clarify Code Standards, Sprint Tasks, and Plans for the team Beta Sprint |
| Other References | IEEE Std 830-1998, GB/T 8567-2006 |
We tracked our progress meticulously throughout the sprint. The chart below illustrates our team's velocity in completing the task management user stories against our estimated timeline.

| Member | ID | Role | Completed Tasks | Time Spent | Remaining Time Estimate | Issues / Difficulties | Plans Until Tomorrow's Stand-up |
|---|---|---|---|---|---|---|---|
| Jiayao Hu | 832301310 | Project Manager | 1. Coordinated task management redesign from list to card view 2. Organized user feedback sessions on new interface 3. Tracked performance optimization progress across teams | 4.5 hours | 1.5 hours (final sprint review preparation) | Balancing design improvements with existing functionality maintenance | 1. Prepare sprint review presentation 2. Document lessons learned for next phase 3. Coordinate deployment planning |
| Hantao Wu | 832302129 | Backend Developer | Optimized task query performance, reducing response time by 65% | 5 hours | 2 hours (load testing optimization) | Complex queries for task metadata affecting card loading speed | 1. Implement query caching for frequently accessed tasks 2. Optimize database indexes for card-based queries 3. Complete stress testing with 100+ concurrent users |
| Zhihao Liu | 832301110 | Backend Developer | Implemented unified task creation/edit endpoint with transaction safety | 4.5 hours | 1.5 hours (error handling refinement) | Date format conversions between frontend and backend causing inconsistencies | 1. Standardize date handling across all task operations 2. Add comprehensive input validation 3. Implement rollback mechanisms for failed updates |
| Yitan Fang | 832302110 | Backend Developer | Developed task metadata storage system with data-* attributes | 5 hours | 2 hours (data consistency testing) | Task priority visualization colors not syncing correctly with backend values | 1. Fix priority color mapping logic 2. Add data migration for existing tasks 3. Test with legacy task data |
| Jiazhuo He | 832302130 | Backend Developer | Created task ownership validation and security checks for all operations | 4 hours | 1 hour (security audit) | Users able to edit tasks not belonging to them in certain edge cases | 1. Strengthen ownership verification logic 2. Implement audit logging for all task modifications 3. Complete security penetration testing |
| Shengpeng Yang | 832301120 | Backend Developer | Fixed time display bug where task times didn't match user settings | 6 hours | 1 hour (timezone handling) | Timezone conversion issues affecting due date calculations | 1. Implement user timezone preferences 2. Fix international date formatting 3. Add time validation for past dates |
| Chenhe Zhu | 832301108 | Backend Developer | Implemented task status synchronization between checkbox and database | 4.5 hours | 1.5 hours (real-time sync testing) | Checkbox state sometimes out of sync after rapid clicks | 1. Add debouncing for status updates 2. Implement optimistic UI updates 3. Test with poor network conditions |
| Yuxiang Xie | 832301327 | Frontend Developer | Created reusable task card template with modern design system | 7 hours | 2 hours (accessibility testing) | Card aspect ratio causing layout issues on some screen sizes | 1. Make card dimensions fully responsive 2. Add ARIA labels for screen readers 3. Test with various display densities |
| Pengxiang Hu | 832301309 | Frontend Developer | Implemented in-place editing functionality with modal integration | 6 hours | 2 hours (user testing) | Edit modal sometimes fails to populate with existing task data | 1. Fix data extraction from task cards 2. Add loading states during data population 3. Implement auto-save functionality |
| Jianyuan Wu | 832302126 | Frontend Developer | Developed card hover effects and priority visualization system | 5.5 hours | 1.5 hours (animation optimization) | Priority color bars not updating immediately after task edits | 1. Fix real-time priority display updates 2. Optimize CSS transitions for smoother effects 3. Add visual feedback for status changes |
| Hongzhi He | 832302220 | Frontend Developer | Implemented task metadata extraction and JavaScript event handling | 5 hours | 2 hours (cross-browser testing) | Data attributes not consistently accessible across all browsers | 1. Implement fallback data storage methods 2. Add browser compatibility layer 3. Test with older browser versions |
| Feijie Zheng | 832301306 | QA/Test Engineer | Created comprehensive test suite for task card functionality | 5 hours | 3 hours (automation refinement) | Automated tests failing due to timing issues with animations | 1. Add wait conditions for animations 2. Create visual regression tests for card layouts 3. Develop performance benchmarks |
| Weixiang Zhou | 832301303 | QA/Test Engineer | Developed edge case tests for task modifications and time handling | 6 hours | 2 hours (test coverage analysis) | Time display bug tests not covering all edge cases | 1. Expand test coverage for time-related functions 2. Create internationalization tests for date formats 3. Document all identified edge cases |
In the previous Alpha phase, tasks were displayed in a list format, resulting in a somewhat monotonous user experience. Based on user feedback, we identified the following areas for improvement:
Based on these observations, in the third phase of the Beta sprint, we focused on:
1. Task Card Template (task_card.html)
2. Task Modification Backend (app.py)
/tasks/add endpoint handles both creation and editing3. Task Modification Frontend (main.js)
4. Task Card Styling (style.css)
5. Bug Fixes: Fixed the time display inconsistency bug
Commit Record:

<div class="task-card-modern"
data-subject="{{ task.course or '' }}"
data-priority="{{ task.priority }}"
data-status="{{ task.status }}"
data-due-date-iso="{{ task.due_date_iso or '' }}"
data-task-id="{{ task.id }}"
data-estimated-time="{{ task.estimated_time }}">
<!-- Card Header: Checkbox and Title -->
<div class="task-card-header">
<input type="checkbox"
class="task-checkbox-modern"
data-task-id="{{ task.id }}"
{% if task.status == 'completed' %}checked{% endif %}>
<h3 class="task-title-modern {% if task.status == 'completed' %}completed{% endif %}">
{{ task.title }}
</h3>
</div>
<!-- Task Description -->
{% if task.description %}
<div class="task-description-modern">
{{ task.description }}
</div>
{% endif %}
<!-- Task Details - Stacked Layout -->
<div class="task-details-modern">
{% if task.course %}
<div class="task-detail-item">
<i class="fas fa-book"></i>
<span class="task-subject-modern">{{ task.course }}</span>
</div>
{% endif %}
{% if task.due_date_display %}
<div class="task-detail-item">
<i class="far fa-calendar"></i>
<span class="task-due-date-modern
{% if task.due_days_diff == 0 %}due-today{% elif task.due_days_diff == 1 %}due-tomorrow{% endif %}">
{{ task.due_date_display }}
</span>
</div>
{% endif %}
{% if task.estimated_time %}
<div class="task-detail-item">
<i class="far fa-clock"></i>
<span class="task-time-modern">
{{ task.estimated_time }} {{ translations['min'] }}
</span>
</div>
{% endif %}
</div>
<!-- Task Actions - Bottom Section -->
<div class="task-actions-modern">
{% if task.priority %}
<span class="priority-tag-modern priority-{{ task.priority }}">
{{ translations['priority_' ~ task.priority] if ('priority_' ~ task.priority) in translations else task.priority|title }}
</span>
{% endif %}
<div class="action-buttons">
<button class="edit-btn-modern" data-task-id="{{ task.id }}" title="{{ translations.edit }}">
<i class="fas fa-edit"></i>
</button>
<button class="delete-btn-modern" data-task-id="{{ task.id }}" title="{{ translations.delete }}">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
// Edit task
function editTask(taskId) {
console.log(`Editing task ${taskId}`);
// Get task data
const taskCard = document.querySelector(`.task-card-modern[data-task-id="${taskId}"]`);
if (!taskCard) {
console.error('Task card not found');
return;
}
// Extract task data
const taskTitle = taskCard.querySelector('.task-title-modern').textContent.trim();
const taskSubject = taskCard.querySelector('.task-subject-modern')?.textContent.trim() || '';
const taskDueDate = taskCard.querySelector('.due-date-text')?.textContent.trim() || '';
const taskPriority = taskCard.dataset.priority || 'medium';
const taskStatus = taskCard.dataset.status || 'pending';
// Populate modal form
const modal = document.getElementById('task-modal');
const modalTitle = document.getElementById('modal-title');
const taskForm = document.getElementById('task-form');
if (modal && modalTitle && taskForm) {
// Set modal title
modalTitle.textContent = 'Edit Task';
// Fill form data
document.getElementById('task-id').value = taskId;
document.getElementById('task-title').value = taskTitle;
document.getElementById('task-course').value = taskSubject;
document.getElementById('task-priority').value = taskPriority;
document.getElementById('task-status').value = taskStatus;
// Process date format
let formattedDueDate = '';
if (taskDueDate === 'Today') {
formattedDueDate = new Date().toISOString().split('T')[0];
} else if (taskDueDate === 'Tomorrow') {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
formattedDueDate = tomorrow.toISOString().split('T')[0];
} else if (taskDueDate.includes('days')) {
const days = parseInt(taskDueDate);
const futureDate = new Date();
futureDate.setDate(futureDate.getDate() + days);
formattedDueDate = futureDate.toISOString().split('T')[0];
} else {
// Try parsing standard date format
try {
const date = new Date(taskDueDate);
if (!isNaN(date.getTime())) {
formattedDueDate = date.toISOString().split('T')[0];
}
} catch (e) {
console.error('Date parsing error:', e);
}
}
document.getElementById('task-due-date').value = formattedDueDate;
}
}
.task-card-modern {
background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
border-radius: 16px;
padding: 1.25rem;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
display: flex;
flex-direction: column;
gap: 0.75rem;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid #f1f5f9;
position: relative;
overflow: hidden;
aspect-ratio: 3/4;
min-height: 260px;
max-height: 340px;
}
/* Side color bar - displays different colors based on priority */
.task-card-modern::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
background: linear-gradient(to bottom, #4a6fa5, #22c55e);
z-index: 1;
}
/* High priority - red */
.task-card-modern[data-priority="high"]::before {
background: linear-gradient(to bottom, #ef4444, #dc2626);
}
/* Medium priority - orange */
.task-card-modern[data-priority="medium"]::before {
background: linear-gradient(to bottom, #f59e0b, #d97706);
}
/* Low priority - green */
.task-card-modern[data-priority="low"]::before {
background: linear-gradient(to bottom, #10b981, #059669);
}
/* Hover animation effects */
.task-card-modern:hover {
transform: translateY(-4px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
border-color: #e2e8f0;
}
.task-card-header {
display: flex;
align-items: flex-start;
gap: 0.75rem;
}
.task-checkbox-modern {
width: 24px;
height: 24px;
border: 2px solid #e2e8f0;
border-radius: 6px;
cursor: pointer;
flex-shrink: 0;
transition: all 0.2s;
background: white;
position: relative;
z-index: 2;
}
.task-checkbox-modern:checked {
background-color: #4a6fa5;
border-color: #4a6fa5;
}
.task-checkbox-modern:checked::after {
content: '✓';
position: absolute;
color: white;
font-size: 14px;
font-weight: bold;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.task-title-modern {
font-size: 1.15rem;
font-weight: 700;
color: #1e293b;
line-height: 1.4;
margin: 0;
flex: 1;
word-break: break-word;
z-index: 2;
}
.task-description-modern {
color: #64748b;
font-size: 0.85rem;
line-height: 1.4;
margin: 0.25rem 0;
max-height: 3em;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
z-index: 2;
}
.task-details-modern {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-top: auto;
z-index: 2;
}
.task-detail-item {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.375rem;
background: #f8fafc;
border-radius: 6px;
border: 1px solid #f1f5f9;
justify-content: flex-start;
width: 100%;
z-index: 2;
text-align: left !important;
}
# Route: Create/Edit task
@app.route('/tasks/add', methods=['POST'])
@login_required
def add_task():
"""Handle create or edit task requests"""
print("[Debug] Handling create/edit task request")
lang = get_current_lang()
translations = get_translations(lang)
user_id = session['user_id']
# Get form data
task_id = request.form.get('task_id')
title = request.form.get('task_title')
description = request.form.get('task_description', '')
course = request.form.get('task_course', '')
priority = request.form.get('task_priority', 'medium')
due_date = request.form.get('task_due_date')
repeat = request.form.get('task_repeat', '')
tags = request.form.get('task_tags', '')
status = request.form.get('task_status', 'pending')
estimated_time = request.form.get('task_estimated_time', 60)
# Server-side validation - required fields
if not title:
flash(translations.get('task_title_required', 'Please enter a task title!'))
return redirect(url_for('tasks', lang=lang))
if not due_date:
flash(translations.get('task_due_date_required', 'Please select a due date!'))
return redirect(url_for('tasks', lang=lang))
# Validate estimated time
try:
estimated_time = int(estimated_time)
if estimated_time <= 0:
estimated_time = 60
except (ValueError, TypeError):
estimated_time = 60
conn = None
try:
conn = get_db_connection()
# Check if editing existing task
if task_id:
# Verify task belongs to current user
task = conn.execute('SELECT * FROM tasks WHERE id = ? AND user_id = ?', (task_id, user_id)).fetchone()
if not task:
flash(translations.get('task_not_found_or_no_permission', 'Task not found or you do not have permission to edit this task!'))
return redirect(url_for('tasks', lang=lang))
# Update task
conn.execute('''
UPDATE tasks
SET title = ?, description = ?, course = ?, priority = ?,
due_date = ?, repeat = ?, status = ?, estimated_time = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?
''', (title, description, course, priority, due_date, repeat, status, estimated_time, task_id))
# Delete old tags
conn.execute('DELETE FROM task_tags WHERE task_id = ?', (task_id,))
else:
# Create new task
cursor = conn.cursor()
cursor.execute('''
INSERT INTO tasks (user_id, title, description, course, priority, due_date, repeat, status, estimated_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (user_id, title, description, course, priority, due_date, repeat, status, estimated_time))
# Get newly inserted task ID
task_id = cursor.lastrowid
# Handle tags (both for create and edit)
if tags:
tag_list = [tag.strip() for tag in tags.split(',') if tag.strip()]
for tag in tag_list:
conn.execute(
'INSERT INTO task_tags (task_id, tag) VALUES (?, ?)',
(task_id, tag)
)
# Commit transaction
conn.commit()
flash(translations.get('task_saved_success', 'Task saved successfully!'))
except Exception as e:
flash(translations.get('task_save_failed', 'Task save failed, please try again later!'))
if conn:
conn.rollback()
finally:
if conn:
conn.close()
return redirect(url_for('tasks', lang=lang))


| Metric | Improvement |
|---|---|
| Page load speed | 71% |
| Interaction response time | 65% reduction |
| Memory usage | 39% decrease |
| Animation smoothness | 60fps |
| Metric | Before Optimization | After Optimization | Improvement |
|---|---|---|---|
| Operation Steps | 5 steps | 3 steps | 40% reduction |
| Input Fields | 6 fields | 1 field | 83% reduction |
| Completion Time | 45 seconds | 20 seconds | 56% reduction |
Figure 3: Feature Optimization Performance Comparison Chart
def test_forgot_password_flow():
# Test normal flow
test_phone = "17840904445"
# Step 1: Enter phone number
response = client.post('/verify_phone', json={'phone': test_phone})
assert response.status_code == 200
assert response.json['success'] == True
# Step 2: Verify countdown function
# Simulate 10-second wait
import time
time.sleep(10)
# Step 3: Reset password
new_password = "newpassword123"
response = client.post('/reset_password', json={
'phone': test_phone,
'new_password': new_password,
'confirm_password': new_password
})
assert response.status_code == 200
assert response.json['success'] == True
@app.route('/reset_password', methods=['POST'])
def reset_password():
logger.info(f"Password reset request for phone: {data.get('phone')}")
try:
# Reset logic...
logger.info("Password reset successful")
return jsonify({'success': True, 'message': 'Password reset successfully'})
except Exception as e:
logger.error(f"Password reset failed: {str(e)}")
return jsonify({'success': False, 'message': 'Reset failed'})
In Beta Sprint Phase 3, we successfully transformed FocusFlow's task management system from a basic list view to an intuitive card-based interface. This major redesign included adding estimated time tracking, in-place editing features, and significant performance improvements that enhanced both user experience and system efficiency.

Report End
This report follows IEEE Std 830-1998 and GB/T 8567-2006 standards for software requirements specifications and documentation.