5th
This commit is contained in:
@@ -25,7 +25,16 @@
|
||||
"Bash(start chrome:*)",
|
||||
"Bash(taskkill:*)",
|
||||
"Bash(TASKKILL:*)",
|
||||
"Bash(wmic process where:*)"
|
||||
"Bash(wmic process where:*)",
|
||||
"Bash(\"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --remote-debugging-port=9222 --user-data-dir=\"%TEMP%\\chrome-debug\" http://localhost:3000/todos)",
|
||||
"Bash(timeout:*)",
|
||||
"Bash(ping:*)",
|
||||
"mcp__puppeteer__puppeteer_navigate",
|
||||
"mcp__puppeteer__puppeteer_screenshot",
|
||||
"mcp__puppeteer__puppeteer_fill",
|
||||
"mcp__puppeteer__puppeteer_click",
|
||||
"mcp__puppeteer__puppeteer_evaluate",
|
||||
"Bash(tree:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
@@ -1,11 +1,11 @@
|
||||
# 暫時規範管理系統 V3 - 開發者最佳實踐指南
|
||||
# PANJIT To-Do System - 開發者最佳實踐指南
|
||||
|
||||
> **⚠️ 重要提醒**:本文件包含敏感的系統配置和最佳實踐資訊,僅供開發團隊內部使用。
|
||||
> 此文件已在 .gitignore 中排除,請勿提交至版本控制系統。
|
||||
|
||||
## 🎯 文件目的
|
||||
|
||||
本文件記錄在開發暫時規範管理系統 V3 過程中遇到的技術難點及最佳解決方案,避免後續開發者重複踩坑。
|
||||
本文件記錄在開發 PANJIT To-Do System 過程中遇到的技術難點及最佳解決方案,包含前後端整合、資料庫設計、LDAP整合、郵件系統等關鍵技術決策,避免後續開發者重複踩坑。
|
||||
|
||||
---
|
||||
|
||||
@@ -541,18 +541,549 @@ tar -czf uploads_${DATE}.tar.gz uploads/
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## 🎨 前端開發最佳實踐
|
||||
|
||||
### 1. Next.js + TypeScript 架構
|
||||
|
||||
**關鍵發現**:App Router 架構提供更好的開發體驗和效能。
|
||||
|
||||
#### 推薦的專案結構
|
||||
```
|
||||
frontend/src/
|
||||
├── app/ # Next.js 13+ App Router
|
||||
│ ├── (auth)/ # Route Groups
|
||||
│ ├── dashboard/ # Dashboard 路由
|
||||
│ ├── todos/ # 待辦事項頁面
|
||||
│ ├── layout.tsx # 根版面
|
||||
│ └── page.tsx # 首頁
|
||||
├── components/ # React 組件
|
||||
│ ├── layout/ # 版面組件
|
||||
│ ├── todos/ # 待辦事項組件
|
||||
│ └── ui/ # 通用 UI 組件
|
||||
├── lib/ # 工具函數
|
||||
├── store/ # Redux 狀態管理
|
||||
├── types/ # TypeScript 類型定義
|
||||
└── providers/ # Context Providers
|
||||
```
|
||||
|
||||
#### TypeScript 最佳實踐
|
||||
```typescript
|
||||
// types/todo.ts - 完整的類型定義
|
||||
export interface TodoItem {
|
||||
id: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
status: 'NEW' | 'DOING' | 'BLOCKED' | 'DONE';
|
||||
priority: 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT';
|
||||
due_date?: string;
|
||||
created_at: string;
|
||||
creator_ad: string;
|
||||
starred: boolean;
|
||||
is_public: boolean;
|
||||
tags: string[];
|
||||
responsible_users: string[];
|
||||
followers: string[];
|
||||
}
|
||||
|
||||
// API 回應類型
|
||||
export interface ApiResponse<T> {
|
||||
data: T;
|
||||
message?: string;
|
||||
total?: number;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Material-UI 整合
|
||||
|
||||
**關鍵發現**:主題系統和組件客制化是關鍵。
|
||||
|
||||
#### 主題設計
|
||||
```typescript
|
||||
// providers/ThemeProvider.tsx
|
||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||
|
||||
const lightTheme = createTheme({
|
||||
palette: {
|
||||
mode: 'light',
|
||||
primary: {
|
||||
main: '#3b82f6', // 藍色主題
|
||||
},
|
||||
secondary: {
|
||||
main: '#10b981', // 綠色輔助
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: '"Noto Sans TC", "Roboto", sans-serif',
|
||||
},
|
||||
});
|
||||
|
||||
const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
primary: {
|
||||
main: '#60a5fa',
|
||||
},
|
||||
background: {
|
||||
default: '#0f172a',
|
||||
paper: '#1e293b',
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
#### 響應式設計
|
||||
```typescript
|
||||
// hooks/useResponsive.ts
|
||||
import { useTheme, useMediaQuery } from '@mui/material';
|
||||
|
||||
export const useResponsive = () => {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const isTablet = useMediaQuery(theme.breakpoints.between('md', 'lg'));
|
||||
const isDesktop = useMediaQuery(theme.breakpoints.up('lg'));
|
||||
|
||||
return { isMobile, isTablet, isDesktop };
|
||||
};
|
||||
```
|
||||
|
||||
### 3. 狀態管理策略
|
||||
|
||||
**關鍵發現**:Redux Toolkit + React Query 組合提供最佳的開發體驗。
|
||||
|
||||
#### Redux Store 設計
|
||||
```typescript
|
||||
// store/todoSlice.ts
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
interface TodoState {
|
||||
filterMode: 'all' | 'created' | 'responsible' | 'following';
|
||||
appliedFilters: TodoFilters;
|
||||
selectedItems: string[];
|
||||
viewMode: 'list' | 'card' | 'calendar';
|
||||
}
|
||||
|
||||
const todoSlice = createSlice({
|
||||
name: 'todo',
|
||||
initialState,
|
||||
reducers: {
|
||||
setFilterMode: (state, action: PayloadAction<FilterMode>) => {
|
||||
state.filterMode = action.payload;
|
||||
},
|
||||
toggleSelectItem: (state, action: PayloadAction<string>) => {
|
||||
const id = action.payload;
|
||||
if (state.selectedItems.includes(id)) {
|
||||
state.selectedItems = state.selectedItems.filter(item => item !== id);
|
||||
} else {
|
||||
state.selectedItems.push(id);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
#### React Query 集成
|
||||
```typescript
|
||||
// lib/api/todos.ts
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
export const useTodos = (filters: TodoFilters) => {
|
||||
return useQuery({
|
||||
queryKey: ['todos', filters],
|
||||
queryFn: () => fetchTodos(filters),
|
||||
staleTime: 30000, // 30秒內數據視為新鮮
|
||||
});
|
||||
};
|
||||
|
||||
export const useCreateTodo = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: createTodo,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['todos'] });
|
||||
toast.success('待辦事項建立成功!');
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(error.message || '建立失敗');
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 後端 API 設計最佳實踐
|
||||
|
||||
### 1. Flask 應用架構
|
||||
|
||||
**關鍵發現**:Blueprint 和工廠模式提供最佳的可維護性。
|
||||
|
||||
#### 應用程式工廠模式
|
||||
```python
|
||||
# app.py - 推薦的應用程式結構
|
||||
def create_app(config_name=None):
|
||||
if config_name is None:
|
||||
config_name = os.environ.get('FLASK_ENV', 'development')
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(config[config_name])
|
||||
|
||||
# 初始化擴展
|
||||
db.init_app(app)
|
||||
migrate.init_app(app, db)
|
||||
jwt.init_app(app)
|
||||
mail.init_app(app)
|
||||
CORS(app, origins=app.config['CORS_ORIGINS'])
|
||||
|
||||
# 註冊 Blueprint
|
||||
from routes import register_blueprints
|
||||
register_blueprints(app)
|
||||
|
||||
# 設定錯誤處理
|
||||
setup_error_handlers(app)
|
||||
|
||||
return app
|
||||
```
|
||||
|
||||
#### RESTful API 設計
|
||||
```python
|
||||
# routes/todos.py - 標準化的 API 結構
|
||||
@todos_bp.route('', methods=['GET'])
|
||||
@jwt_required()
|
||||
def get_todos():
|
||||
try:
|
||||
# 參數驗證
|
||||
page = request.args.get('page', 1, type=int)
|
||||
per_page = min(request.args.get('per_page', 20, type=int), 100)
|
||||
|
||||
# 業務邏輯
|
||||
todos, total = todo_service.get_user_todos(
|
||||
user_ad=get_jwt_identity(),
|
||||
page=page,
|
||||
per_page=per_page,
|
||||
filters=request.args
|
||||
)
|
||||
|
||||
# 統一回應格式
|
||||
return jsonify({
|
||||
'data': [todo.to_dict() for todo in todos],
|
||||
'pagination': {
|
||||
'page': page,
|
||||
'per_page': per_page,
|
||||
'total': total,
|
||||
'pages': (total + per_page - 1) // per_page
|
||||
}
|
||||
}), 200
|
||||
|
||||
except ValidationError as e:
|
||||
return jsonify({'error': str(e)}), 400
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting todos: {str(e)}")
|
||||
return jsonify({'error': 'Internal server error'}), 500
|
||||
```
|
||||
|
||||
### 2. 資料驗證策略
|
||||
|
||||
**關鍵發現**:輸入驗證和序列化分離提供更好的可維護性。
|
||||
|
||||
```python
|
||||
# validators/todo.py
|
||||
from marshmallow import Schema, fields, validate
|
||||
|
||||
class CreateTodoSchema(Schema):
|
||||
title = fields.Str(required=True, validate=validate.Length(min=1, max=200))
|
||||
description = fields.Str(missing=None, validate=validate.Length(max=2000))
|
||||
status = fields.Str(missing='NEW', validate=validate.OneOf(['NEW', 'DOING', 'BLOCKED', 'DONE']))
|
||||
priority = fields.Str(missing='MEDIUM', validate=validate.OneOf(['LOW', 'MEDIUM', 'HIGH', 'URGENT']))
|
||||
due_date = fields.Date(missing=None)
|
||||
responsible_users = fields.List(fields.Str(), missing=list)
|
||||
followers = fields.List(fields.Str(), missing=list)
|
||||
tags = fields.List(fields.Str(), missing=list)
|
||||
is_public = fields.Bool(missing=False)
|
||||
starred = fields.Bool(missing=False)
|
||||
|
||||
# 使用裝飾器進行驗證
|
||||
def validate_json(schema):
|
||||
def decorator(f):
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
data = schema.load(request.json or {})
|
||||
return f(data, *args, **kwargs)
|
||||
except ValidationError as e:
|
||||
return jsonify({'error': e.messages}), 400
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
@todos_bp.route('', methods=['POST'])
|
||||
@jwt_required()
|
||||
@validate_json(CreateTodoSchema())
|
||||
def create_todo(data):
|
||||
# 已驗證的資料直接使用
|
||||
todo = todo_service.create_todo(
|
||||
creator_ad=get_jwt_identity(),
|
||||
**data
|
||||
)
|
||||
return jsonify({'data': todo.to_dict()}), 201
|
||||
```
|
||||
|
||||
### 3. 服務層架構
|
||||
|
||||
**關鍵發現**:業務邏輯分離到服務層提供更好的測試性。
|
||||
|
||||
```python
|
||||
# services/todo_service.py
|
||||
class TodoService:
|
||||
def __init__(self):
|
||||
self.logger = get_logger(__name__)
|
||||
|
||||
def create_todo(self, creator_ad: str, **kwargs) -> TodoItem:
|
||||
"""建立新的待辦事項"""
|
||||
try:
|
||||
# 驗證負責人帳號
|
||||
if kwargs.get('responsible_users'):
|
||||
valid_users = validate_ad_accounts(kwargs['responsible_users'])
|
||||
if len(valid_users) != len(kwargs['responsible_users']):
|
||||
invalid_users = set(kwargs['responsible_users']) - set(valid_users.keys())
|
||||
raise ValidationError(f"無效的負責人帳號: {', '.join(invalid_users)}")
|
||||
|
||||
# 建立待辦事項
|
||||
todo = TodoItem(
|
||||
title=kwargs['title'],
|
||||
description=kwargs.get('description'),
|
||||
status=kwargs.get('status', 'NEW'),
|
||||
priority=kwargs.get('priority', 'MEDIUM'),
|
||||
due_date=kwargs.get('due_date'),
|
||||
creator_ad=creator_ad,
|
||||
is_public=kwargs.get('is_public', False),
|
||||
starred=kwargs.get('starred', False),
|
||||
tags=kwargs.get('tags', [])
|
||||
)
|
||||
|
||||
# 設定使用者資訊
|
||||
user_info = get_user_info(creator_ad)
|
||||
if user_info:
|
||||
todo.creator_display_name = user_info['display_name']
|
||||
todo.creator_email = user_info['email']
|
||||
|
||||
db.session.add(todo)
|
||||
db.session.flush() # 取得 ID
|
||||
|
||||
# 新增負責人和追蹤者
|
||||
self._add_users_to_todo(todo.id, kwargs.get('responsible_users', []), 'responsible')
|
||||
self._add_users_to_todo(todo.id, kwargs.get('followers', []), 'follower')
|
||||
|
||||
db.session.commit()
|
||||
|
||||
# 發送通知
|
||||
self._send_assignment_notifications(todo)
|
||||
|
||||
# 記錄稽核日誌
|
||||
self._log_audit(todo.id, creator_ad, 'CREATE', '建立待辦事項')
|
||||
|
||||
return todo
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
self.logger.error(f"Error creating todo: {str(e)}")
|
||||
raise
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Excel 處理最佳實踐
|
||||
|
||||
### 1. 安全的檔案處理
|
||||
|
||||
**關鍵發現**:檔案上傳和處理需要多層驗證。
|
||||
|
||||
```python
|
||||
# utils/excel_utils.py
|
||||
import pandas as pd
|
||||
from openpyxl import load_workbook
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
class ExcelProcessor:
|
||||
ALLOWED_EXTENSIONS = {'.xlsx', '.xls', '.csv'}
|
||||
MAX_FILE_SIZE = 16 * 1024 * 1024 # 16MB
|
||||
MAX_ROWS = 10000
|
||||
|
||||
def validate_file(self, file):
|
||||
"""檔案安全驗證"""
|
||||
# 檔案大小檢查
|
||||
if len(file.read()) > self.MAX_FILE_SIZE:
|
||||
raise ValidationError("檔案大小超過限制 (16MB)")
|
||||
|
||||
file.seek(0) # 重置檔案指針
|
||||
|
||||
# 檔案類型檢查
|
||||
filename = secure_filename(file.filename)
|
||||
if not any(filename.lower().endswith(ext) for ext in self.ALLOWED_EXTENSIONS):
|
||||
raise ValidationError("不支援的檔案格式")
|
||||
|
||||
return filename
|
||||
|
||||
def parse_excel_file(self, file):
|
||||
"""安全的 Excel 解析"""
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
||||
file.save(temp_file.name)
|
||||
|
||||
# 使用 pandas 讀取檔案
|
||||
if temp_file.name.endswith('.csv'):
|
||||
df = pd.read_csv(temp_file.name, encoding='utf-8')
|
||||
else:
|
||||
df = pd.read_excel(temp_file.name)
|
||||
|
||||
# 行數限制
|
||||
if len(df) > self.MAX_ROWS:
|
||||
raise ValidationError(f"資料列數超過限制 ({self.MAX_ROWS})")
|
||||
|
||||
return self.validate_and_transform_data(df)
|
||||
|
||||
finally:
|
||||
# 清理暫存檔案
|
||||
if 'temp_file' in locals():
|
||||
os.unlink(temp_file.name)
|
||||
|
||||
def validate_and_transform_data(self, df):
|
||||
"""資料驗證和轉換"""
|
||||
required_columns = ['標題', '負責人']
|
||||
missing_columns = [col for col in required_columns if col not in df.columns]
|
||||
|
||||
if missing_columns:
|
||||
raise ValidationError(f"缺少必要欄位: {', '.join(missing_columns)}")
|
||||
|
||||
validated_data = []
|
||||
errors = []
|
||||
|
||||
for index, row in df.iterrows():
|
||||
try:
|
||||
todo_data = self.validate_row(row, index + 2) # +2 因為標題行
|
||||
validated_data.append(todo_data)
|
||||
except ValidationError as e:
|
||||
errors.append(f"第 {index + 2} 行: {str(e)}")
|
||||
|
||||
return {
|
||||
'data': validated_data,
|
||||
'errors': errors,
|
||||
'total': len(df)
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 模板生成
|
||||
|
||||
**關鍵發現**:動態模板生成提供更好的使用者體驗。
|
||||
|
||||
```python
|
||||
# routes/excel.py
|
||||
@excel_bp.route('/template', methods=['GET'])
|
||||
@jwt_required()
|
||||
def download_template():
|
||||
"""生成並下載 Excel 匯入模板"""
|
||||
try:
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font, PatternFill, Alignment
|
||||
from openpyxl.worksheet.datavalidation import DataValidation
|
||||
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "待辦事項匯入模板"
|
||||
|
||||
# 標題行
|
||||
headers = [
|
||||
'標題*', '描述', '狀態', '優先級',
|
||||
'到期日', '負責人*', '追蹤人員', '標籤', '備註'
|
||||
]
|
||||
|
||||
# 設定標題樣式
|
||||
title_font = Font(bold=True, color='FFFFFF')
|
||||
title_fill = PatternFill(start_color='366092', end_color='366092', fill_type='solid')
|
||||
|
||||
for col, header in enumerate(headers, 1):
|
||||
cell = ws.cell(row=1, column=col, value=header)
|
||||
cell.font = title_font
|
||||
cell.fill = title_fill
|
||||
cell.alignment = Alignment(horizontal='center')
|
||||
|
||||
# 資料驗證
|
||||
status_validation = DataValidation(
|
||||
type="list",
|
||||
formula1='"NEW,DOING,BLOCKED,DONE"',
|
||||
showErrorMessage=True,
|
||||
errorTitle="狀態錯誤",
|
||||
error="請選擇: NEW, DOING, BLOCKED, DONE"
|
||||
)
|
||||
priority_validation = DataValidation(
|
||||
type="list",
|
||||
formula1='"LOW,MEDIUM,HIGH,URGENT"',
|
||||
showErrorMessage=True,
|
||||
errorTitle="優先級錯誤",
|
||||
error="請選擇: LOW, MEDIUM, HIGH, URGENT"
|
||||
)
|
||||
|
||||
ws.add_data_validation(status_validation)
|
||||
ws.add_data_validation(priority_validation)
|
||||
status_validation.add(f'C2:C{MAX_ROWS}')
|
||||
priority_validation.add(f'D2:D{MAX_ROWS}')
|
||||
|
||||
# 範例資料
|
||||
sample_data = [
|
||||
['完成月報撰寫', '包含各部門數據統計和分析', 'NEW', 'HIGH', '2024/01/15', 'user1', 'manager1', '報告,月度', '請於期限內完成'],
|
||||
['系統維護檢查', '定期檢查伺服器狀態', 'DOING', 'MEDIUM', '2024/01/20', 'user2', 'user1,user3', 'IT,維護', ''],
|
||||
]
|
||||
|
||||
for row, data in enumerate(sample_data, 2):
|
||||
for col, value in enumerate(data, 1):
|
||||
ws.cell(row=row, column=col, value=value)
|
||||
|
||||
# 調整欄寬
|
||||
column_widths = [20, 30, 12, 12, 12, 15, 20, 15, 20]
|
||||
for col, width in enumerate(column_widths, 1):
|
||||
ws.column_dimensions[ws.cell(row=1, column=col).column_letter].width = width
|
||||
|
||||
# 生成檔案
|
||||
from io import BytesIO
|
||||
output = BytesIO()
|
||||
wb.save(output)
|
||||
output.seek(0)
|
||||
|
||||
return send_file(
|
||||
output,
|
||||
as_attachment=True,
|
||||
download_name=f'todo_import_template_{datetime.now().strftime("%Y%m%d")}.xlsx',
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating template: {str(e)}")
|
||||
return jsonify({'error': '模板生成失敗'}), 500
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 總結
|
||||
|
||||
本文件記錄了開發暫時規範管理系統 V3 過程中的關鍵技術決策和最佳實踐。這些經驗可以幫助後續開發者:
|
||||
本文件記錄了開發 PANJIT To-Do System 過程中的關鍵技術決策和最佳實踐。這些經驗可以幫助後續開發者:
|
||||
|
||||
1. **避免常見陷阱**:特別是 LDAP 配置和 SMTP 設定
|
||||
2. **提升開發效率**:使用經過驗證的架構模式
|
||||
3. **確保系統穩定性**:採用完整的錯誤處理和監控機制
|
||||
4. **簡化部署流程**:使用 Docker 和自動化腳本
|
||||
1. **避免常見陷阱**:特別是 LDAP 配置、前後端整合、Excel 處理
|
||||
2. **提升開發效率**:使用經過驗證的架構模式和工具鏈
|
||||
3. **確保程式碼品質**:遵循 TypeScript、Python 最佳實踐
|
||||
4. **提升使用者體驗**:響應式設計、效能優化、錯誤處理
|
||||
5. **簡化維護工作**:清晰的架構分離、完整的日誌記錄
|
||||
|
||||
**重要技術決策總結**:
|
||||
- **前端**:Next.js 14 App Router + TypeScript + Material-UI + Redux Toolkit
|
||||
- **後端**:Flask + SQLAlchemy + Celery + Redis + JWT
|
||||
- **資料庫**:MySQL 8.0 + 適當索引設計
|
||||
- **部署**:Docker + Nginx + 健康檢查
|
||||
|
||||
**重要提醒**:本文件包含敏感資訊,請勿外洩或提交至公開版本控制系統。
|
||||
|
||||
---
|
||||
|
||||
*最後更新:2025年1月*
|
||||
*文件版本:V1.0*
|
||||
*文件版本:V2.0*
|
||||
*適用系統:PANJIT To-Do System v1.0*
|
@@ -1,149 +0,0 @@
|
||||
# 對話記憶 - PANJIT To-Do List System V1
|
||||
|
||||
## 最新狀態 (2025-08-29)
|
||||
|
||||
### 已完成的主要功能
|
||||
1. **Fire Email 功能修復** - 修正 AD 帳號轉換郵件地址的問題
|
||||
2. **重複錯誤提示修復** - 解決 axios 攔截器重複顯示錯誤的問題
|
||||
3. **增強型郵件通知設定** - 支援彈性提醒天數、週/月摘要
|
||||
4. **CORS 網路錯誤修復** - 新增 port 3002 支援
|
||||
5. **通知系統實作** - 完整的通知顯示與互動功能
|
||||
6. **通知面板互動功能** - 查看、標記已讀等按鈕功能完成
|
||||
7. **公開/私人 Todo 功能** - ✅ 完整實現並測試通過
|
||||
8. **載入效能優化** - ✅ 添加骨架屏 Loading 狀態
|
||||
|
||||
### 核心技術架構
|
||||
- **前端**: Next.js 14 + TypeScript + Material-UI + React Hook Form
|
||||
- **後端**: Flask + SQLAlchemy + JWT + MySQL
|
||||
- **認證**: LDAP 整合 + JWT Token 刷新機制
|
||||
- **郵件**: SMTP 服務整合 (mail.panjit.com.tw:25)
|
||||
- **資料庫**: MySQL with enhanced notification models
|
||||
|
||||
### 重要修復記錄
|
||||
|
||||
#### 1. Fire Email 核心問題修復
|
||||
**檔案**: `backend/utils/email_service.py:_get_user_email`
|
||||
```python
|
||||
# 修正前
|
||||
user_info.get('mail') # 錯誤的欄位名稱
|
||||
|
||||
# 修正後
|
||||
user_info.get('email') # 正確的欄位名稱
|
||||
```
|
||||
|
||||
#### 2. 通知系統 API 實作
|
||||
**檔案**: `backend/routes/notifications.py`
|
||||
- 新增 `/api/notifications/` - 獲取用戶通知
|
||||
- 新增 `/api/notifications/mark-read` - 標記單個通知已讀
|
||||
- 新增 `/api/notifications/mark-all-read` - 標記全部通知已讀
|
||||
|
||||
#### 3. 前端通知面板功能
|
||||
**檔案**: `frontend/src/components/layout/NotificationPanel.tsx`
|
||||
- 實作查看按鈕 - 導航到對應 todo
|
||||
- 實作標記已讀按鈕 - 更新通知狀態
|
||||
- 實作全部標記已讀 - 批量更新
|
||||
- 實作查看全部 - 導航到主頁
|
||||
|
||||
### 資料庫模型增強
|
||||
**檔案**: `backend/models.py`
|
||||
```python
|
||||
class TodoUserPref(db.Model):
|
||||
monthly_summary_enabled = db.Column(db.Boolean, default=False)
|
||||
reminder_days_before = db.Column(JSON, default=lambda: [1, 3])
|
||||
weekly_summary_time = db.Column(db.String(5), default='09:00')
|
||||
monthly_summary_time = db.Column(db.String(5), default='09:00')
|
||||
# ... 其他增強欄位
|
||||
```
|
||||
|
||||
### 2025-08-29 修復進度記錄
|
||||
|
||||
#### ✅ 已完成修復
|
||||
1. **公開任務頁面 showSnackbar 錯誤**
|
||||
- 移除錯誤的 `showSnackbar` 導入,替換為 `react-hot-toast`
|
||||
- 將公開任務頁面包裝在 `DashboardLayout` 中
|
||||
|
||||
2. **公開/私人 Todo 功能完整實現**
|
||||
- 資料庫:成功新增 `is_public` 和 `tags` 欄位
|
||||
- 後端 API:完整實現公開 todo 查詢、追蹤、可見性切換功能
|
||||
- 跨用戶測試:成功驗證權限控制正確運作
|
||||
|
||||
3. **載入效能和 Loading 狀態改善**
|
||||
- 為所有頁面添加詳細的骨架屏 loading 狀態
|
||||
- 使用 Material-UI `Skeleton` 組件提供流暢的使用者體驗
|
||||
|
||||
4. **編譯錯誤修復**
|
||||
- 修復 `Sidebar.tsx` 中圖標導入錯誤
|
||||
- 重新編寫 `dashboard/page.tsx` 解決 JSX 語法錯誤
|
||||
- 清理 Next.js 緩存,確保前端在 3000 端口正常運行
|
||||
|
||||
#### ❌ 實際測試後仍需修復的問題
|
||||
根據用戶實際測試結果:
|
||||
|
||||
1. **Sidebar 消失問題 - 未修復**
|
||||
- 問題:打開篩選功能時 sidebar 仍會消失,需要重新整理頁面
|
||||
- 待處理:檢查 DashboardLayout 的狀態管理和動畫邏輯
|
||||
|
||||
2. **篩選功能不正常運作 - 未修復**
|
||||
- 問題:根本不會照著篩選條件顯示結果
|
||||
- 待處理:重新檢查前端篩選邏輯的實際執行
|
||||
|
||||
### 公開 Todo 功能實現詳情 (已完成)
|
||||
#### 後端 API 端點
|
||||
- `GET /api/todos/public` - 獲取公開 todos
|
||||
- `GET /api/todos/following` - 獲取追蹤的 todos
|
||||
- `PATCH /api/todos/<id>/visibility` - 切換可見性
|
||||
- `POST /api/todos/<id>/follow` - 追蹤 todo
|
||||
- `DELETE /api/todos/<id>/follow` - 取消追蹤
|
||||
|
||||
#### 測試帳號 (已驗證)
|
||||
- ymirliu@panjit.com.tw (密碼: 3EDC4rfv5tgb)
|
||||
- uthuang@panjit.com.tw (密碼: 3EDC4rfv5tgb)
|
||||
|
||||
### 待修復問題清單
|
||||
1. **Sidebar 消失問題** - 需要檢查狀態管理衝突
|
||||
2. **篩選功能實際運作** - 需要重新測試和調試前端邏輯
|
||||
3. **通知已讀狀態持久化** - 目前僅在記憶體中,需要資料庫儲存
|
||||
|
||||
### 環境配置
|
||||
```bash
|
||||
# 前端 (Port 3000)
|
||||
cd frontend && npm run dev
|
||||
|
||||
# 後端 (Port 5000)
|
||||
cd backend && ./venv/Scripts/activate && python app.py
|
||||
```
|
||||
|
||||
### 測試用戶帳號
|
||||
- **uthuang** (92509) - uthuang@panjit.com.tw
|
||||
- **ymirliu** - ymirliu@panjit.com.tw
|
||||
- **minjiesyu** (92453) - minjiesyu@panjit.com.tw
|
||||
|
||||
### API 端點清單
|
||||
- `GET /api/notifications/` - 獲取通知清單
|
||||
- `POST /api/notifications/mark-read` - 標記單個通知已讀
|
||||
- `POST /api/notifications/mark-all-read` - 標記全部通知已讀
|
||||
- `POST /api/notifications/fire-email` - 發送緊急郵件
|
||||
- `GET/PATCH /api/notifications/settings` - 通知設定管理
|
||||
|
||||
### 重要設定檔案
|
||||
- **後端 .env**: 包含 CORS_ORIGINS 設定 (支援 3000,3001,3002)
|
||||
- **前端 api.ts**: 包含完整的 notificationsApi 客戶端
|
||||
- **資料庫連線**: mysql.theaken.com:33306/db_A060
|
||||
|
||||
## 開發原則提醒
|
||||
1. 必須提供完整可執行的程式碼
|
||||
2. 所有功能都需要單元測試
|
||||
3. 確保 Windows 環境相容性
|
||||
4. 遵循 MUI 設計規範
|
||||
5. 實作適當的錯誤處理
|
||||
|
||||
---
|
||||
## 系統當前狀態
|
||||
- **前端**: http://localhost:3000 ✅ 正常編譯運行
|
||||
- **後端**: http://localhost:5000 ✅ 正常運行
|
||||
- **公開任務功能**: ✅ 完全正常
|
||||
- **載入狀態**: ✅ 已優化
|
||||
- **篩選功能**: ❌ 需要修復 (不會照著篩選)
|
||||
- **Sidebar**: ❌ 消失問題需要修復 (打開篩選時消失)
|
||||
|
||||
*最後更新: 2025-08-29 18:50 - 根據實際測試結果更新*
|
176
PRD.md
176
PRD.md
@@ -1,176 +0,0 @@
|
||||
# PANJIT|To-Do List(Web UI)V1 產品需求文件(PRD)
|
||||
**版本**:V1(定版)
|
||||
**最後更新**:2025-08-28
|
||||
**資料庫**:MySQL(所有資料表皆採前綴 `todo_`)
|
||||
**登入**:AD/LDAP(不限僅內網)
|
||||
**DueDate 精度**:到 **「日」**
|
||||
**Email 寄件者**:以**建立者的 AD Mail**發送(SMTP 需允許代寄或以 Envelope From 配合)
|
||||
|
||||
**Excel 匯入**:提供正式模板(含下拉驗證、README)
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景與目標
|
||||
- 以 AD 帳號辨識使用者,提供個人/協作化的待辦管理。
|
||||
- 除固定排程提醒外,提供「**Fire 一鍵提醒**」降低漏辦風險。
|
||||
- 提供**正式 Excel 模板**以降低匯入錯誤率。
|
||||
|
||||
### 成功指標(示例)
|
||||
- 90% 使用者在 2 週內完成首次建立/匯入待辦。
|
||||
- 逾期數較導入前下降 30%。
|
||||
- 主要操作 P95 < 1s;匯入任務成功率 99%。
|
||||
|
||||
---
|
||||
|
||||
## 2. 使用者與場景
|
||||
- **建立者**:建立待辦者,預設可見/可編輯。
|
||||
- **負責人(多人)**:可見/可編輯(與建立者同等)。
|
||||
- **追蹤者(多人)**:可見但預設不可編輯;可收信。
|
||||
|
||||
主要場景:
|
||||
1) 新增/編輯待辦(可設定多負責人、多追蹤者)。
|
||||
2) 清單/日曆檢視、篩選、批次操作。
|
||||
3) Fire 一鍵提醒:立即寄發、可寫附註、冷卻與限額管控。
|
||||
4) 排程提醒:到期前/當天/逾期 + 週摘要(可開關)。
|
||||
5) 匯入:下載模板→填寫→上傳驗證→導入。
|
||||
|
||||
---
|
||||
|
||||
## 3. 功能需求
|
||||
|
||||
### 3.1 待辦 CRUD 與視圖
|
||||
- 欄位:
|
||||
- 必填:`title`
|
||||
- 選填:`description`, `priority(LOW|MEDIUM|HIGH|URGENT)`, `status(NEW|DOING|BLOCKED|DONE)`, `due_date(YYYY-MM-DD)`, `starred`
|
||||
- 系統:`id(uuid)`, `created_at`, `completed_at`, `creator_ad`, `creator_display_name`, `creator_email`
|
||||
- 視圖:列表 + 日曆;支援篩選(狀態、到期區間、加星)與批次操作(狀態、到期日)。
|
||||
- 可見性:建立者/負責人/追蹤者可見;可編輯者為建立者與負責人。
|
||||
|
||||
### 3.2 多負責人/多追蹤者
|
||||
- 以 AD 帳號多選加入;維護表 `todo_item_responsible`, `todo_item_follower`。
|
||||
|
||||
### 3.3 Email 通知
|
||||
- **排程提醒**(可開關):到期前 X 天、到期日、逾期 Y 天;週一 09:00 摘要(建議)。
|
||||
- **Fire 一鍵提醒**:
|
||||
- 受信人預設:負責人 + 追蹤者 + 建立者(可調整/去重)。
|
||||
- 冷卻/限額:**同一待辦 2 分鐘冷卻**,**每人每日 20 封**。
|
||||
- 可附註;所有寄送寫入 `todo_mail_log`。
|
||||
|
||||
### 3.4 Excel 匯入
|
||||
- 下載正式模板(含 README 與下拉驗證)。
|
||||
- 驗證:必填、日期格式、AD 帳號存在性、重複(同標題 + 近日期)。
|
||||
- 逐列錯誤報告與「問題列下載」。
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 4. 非功能需求
|
||||
- 效能:一般操作 P95 < 1s;匯入以背景 Job 執行,提供進度查詢。
|
||||
- 可用性:SMTP 故障不影響 CRUD;提供降級邏輯。
|
||||
- 監控:`/healthz`(DB/SMTP);寄送/匯入皆留 `todo_audit_log`。
|
||||
- 備份:每日快照;保留 7/30 天。
|
||||
|
||||
---
|
||||
|
||||
## 5. 資料庫(MySQL,前綴 `todo_`)
|
||||
|
||||
- `todo_item`:主表(待辦)
|
||||
- `todo_item_responsible`:多負責人
|
||||
- `todo_item_follower`:多追蹤者
|
||||
- `todo_mail_log`:排程/Fire 寄信紀錄
|
||||
- `todo_audit_log`:稽核日誌
|
||||
- `todo_user_pref`:使用者偏好
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
todo_item ||--o{ todo_item_responsible : has
|
||||
todo_item ||--o{ todo_item_follower : has
|
||||
todo_item ||--o{ todo_mail_log : logs
|
||||
todo_item ||--o{ todo_audit_log : audits
|
||||
|
||||
todo_item {{
|
||||
char(36) id PK
|
||||
varchar title
|
||||
text description
|
||||
enum status
|
||||
enum priority
|
||||
date due_date
|
||||
datetime created_at
|
||||
datetime completed_at
|
||||
varchar creator_ad
|
||||
varchar creator_display_name
|
||||
varchar creator_email
|
||||
tinyint starred
|
||||
}}
|
||||
|
||||
todo_item_responsible {{
|
||||
char(36) todo_id FK
|
||||
varchar ad_account
|
||||
datetime added_at
|
||||
}}
|
||||
|
||||
todo_item_follower {{
|
||||
char(36) todo_id FK
|
||||
varchar ad_account
|
||||
datetime added_at
|
||||
}}
|
||||
|
||||
todo_mail_log {{
|
||||
bigint id PK
|
||||
char(36) todo_id FK
|
||||
enum type
|
||||
varchar triggered_by_ad
|
||||
text recipients
|
||||
varchar subject
|
||||
enum status
|
||||
varchar provider_msg_id
|
||||
text error_text
|
||||
datetime created_at
|
||||
datetime sent_at
|
||||
}}
|
||||
|
||||
todo_audit_log {{
|
||||
bigint id PK
|
||||
varchar actor_ad
|
||||
char(36) todo_id FK nullable
|
||||
enum action
|
||||
json detail
|
||||
datetime created_at
|
||||
}}
|
||||
|
||||
todo_user_pref {{
|
||||
varchar ad_account PK
|
||||
varchar email
|
||||
datetime updated_at
|
||||
}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. API(摘要)
|
||||
- `GET /api/todos`、`POST /api/todos`、`PATCH /api/todos/{{id}}`、`DELETE /api/todos/{{id}}`
|
||||
- `POST /api/todos/{{id}}/responsibles`、`POST /api/todos/{{id}}/followers`
|
||||
- `POST /api/todos/{{id}}/fire-email`
|
||||
- `GET /api/imports/template`、`POST /api/imports`、`GET /api/imports/{{job_id}}`
|
||||
|
||||
---
|
||||
|
||||
## 7. 驗收標準
|
||||
1) AD 登入成功;首登寫入個資。
|
||||
2) 多負責人/多追蹤者運作;可見/可編輯權限如預期。
|
||||
3) Fire 寄信:預設收件人、冷卻/限額、附註、寄送紀錄。
|
||||
4) 排程提醒、週摘要可開關且寄送正確。
|
||||
5) 匯入:模板下載、驗證逐列錯誤、成功導入。
|
||||
6) 稽核:CRUD/匯入/寄信皆可查。
|
||||
|
||||
---
|
||||
|
||||
## 8. 風險與對策
|
||||
- SMTP 代寄受限 → 以系統 Envelope From + `Reply-To:` 建立者。
|
||||
|
||||
- 匯入錯誤率高 → 強制模板、下拉驗證、逐列錯誤檔回饋。
|
||||
|
||||
---
|
||||
|
||||
## 9. 附件
|
||||
- 正式 Excel 模板:`todo_import_template_v1_formal.xlsx`
|
36
README.md
36
README.md
@@ -1,16 +1,32 @@
|
||||
# PANJIT To-Do List System V1
|
||||
# PANJIT To-Do System
|
||||
|
||||
一個基於 Next.js + Flask 的企業級待辦事項管理系統,支援 AD/LDAP 登入、多人協作、Email 提醒等功能。
|
||||
一個功能完整的企業級待辦事項管理系統,支援 LDAP 認證、郵件通知、Excel 匯入匯出,以及豐富的協作功能。
|
||||
|
||||
## 🚀 系統特色
|
||||
## 🚀 功能特色
|
||||
|
||||
- ✅ **AD/LDAP 登入** - 企業級身份驗證
|
||||
- ✅ **多人協作** - 支援多負責人/多追蹤者
|
||||
- ✅ **Fire 一鍵提醒** - 立即郵件提醒功能 (2分鐘冷卻 + 每日20封限額)
|
||||
- ✅ **排程提醒** - 到期前/當天/逾期自動提醒 + 週摘要
|
||||
- ✅ **Excel 匯入** - 完整模板驗證與錯誤處理
|
||||
- ✅ **完整稽核** - 所有操作記錄追蹤
|
||||
- ✅ **響應式設計** - 支援桌面與行動裝置
|
||||
### 核心功能
|
||||
- **待辦事項管理**:建立、編輯、刪除、狀態管理
|
||||
- **多人協作**:負責人指派、追蹤人員、權限控制
|
||||
- **狀態管理**:新建立 → 進行中 → 已阻礙 → 已完成
|
||||
- **優先級分類**:低、中、高、緊急
|
||||
- **到期日管理**:日期設定、逾期提醒
|
||||
|
||||
### 高級功能
|
||||
- **LDAP/Active Directory 整合**:企業帳號統一認證
|
||||
- **智能搜尋**:模糊搜尋、多條件篩選
|
||||
- **Excel 匯入匯出**:批量資料處理
|
||||
- **郵件通知系統**:自動提醒、狀態變更通知
|
||||
- **行事曆檢視**:時間軸管理
|
||||
- **批量操作**:多項目同時處理
|
||||
- **公開/私人模式**:靈活的可見性控制
|
||||
|
||||
### 技術特色
|
||||
- **現代化架構**:前後端分離設計
|
||||
- **響應式設計**:支援桌面和行動裝置
|
||||
- **深色/淺色主題**:使用者體驗優化
|
||||
- **即時更新**:React Query 資料同步
|
||||
- **任務排程**:Celery 背景處理
|
||||
- **健康檢查**:系統狀態監控
|
||||
|
||||
## 🏗️ 技術架構
|
||||
|
||||
|
@@ -51,10 +51,15 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ children }) => {
|
||||
const { user, logout } = useAuth();
|
||||
const { themeMode, actualTheme, setThemeMode } = useTheme();
|
||||
const muiTheme = useMuiTheme();
|
||||
const isMobile = useMediaQuery(muiTheme.breakpoints.down('lg'));
|
||||
const isMobile = useMediaQuery('(max-width: 1200px)'); // 降低斷點確保覆蓋所有小螢幕
|
||||
|
||||
// 響應式處理
|
||||
useEffect(() => {
|
||||
console.log('Responsive handling:', {
|
||||
isMobile,
|
||||
windowWidth: window.innerWidth,
|
||||
currentSidebarOpen: sidebarOpen
|
||||
});
|
||||
if (isMobile) {
|
||||
setSidebarOpen(false);
|
||||
setSidebarCollapsed(false);
|
||||
@@ -136,10 +141,27 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ children }) => {
|
||||
};
|
||||
|
||||
|
||||
const toggleSidebar = () => {
|
||||
const toggleSidebar = (event?: React.MouseEvent) => {
|
||||
console.log('🔧 Toggle sidebar clicked:', {
|
||||
isMobile,
|
||||
sidebarOpen,
|
||||
sidebarCollapsed,
|
||||
windowWidth: window.innerWidth,
|
||||
eventTarget: event?.target,
|
||||
eventCurrentTarget: event?.currentTarget
|
||||
});
|
||||
|
||||
// 防止事件冒泡
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
if (isMobile) {
|
||||
console.log('📱 Mobile: Setting sidebar open to:', !sidebarOpen);
|
||||
setSidebarOpen(!sidebarOpen);
|
||||
} else {
|
||||
console.log('🖥️ Desktop: Toggling collapsed to:', !sidebarCollapsed);
|
||||
setSidebarCollapsed(!sidebarCollapsed);
|
||||
}
|
||||
};
|
||||
@@ -162,8 +184,8 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ children }) => {
|
||||
position="fixed"
|
||||
elevation={0}
|
||||
sx={{
|
||||
width: { lg: `calc(100% - ${getDrawerWidth()}px)` },
|
||||
ml: { lg: `${getDrawerWidth()}px` },
|
||||
width: isMobile ? '100%' : `calc(100% - ${getDrawerWidth()}px)`,
|
||||
ml: isMobile ? 0 : `${getDrawerWidth()}px`,
|
||||
backgroundColor: actualTheme === 'dark'
|
||||
? 'rgba(17, 24, 39, 0.9)'
|
||||
: 'rgba(255, 255, 255, 0.9)',
|
||||
@@ -183,11 +205,23 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ children }) => {
|
||||
onClick={toggleSidebar}
|
||||
sx={{
|
||||
mr: 2,
|
||||
display: { lg: sidebarCollapsed ? 'inline-flex' : 'none' },
|
||||
display: isMobile || sidebarCollapsed ? 'flex' : 'none',
|
||||
zIndex: 1301, // 確保按鈕在 Drawer modal 之上
|
||||
position: 'relative',
|
||||
pointerEvents: 'auto',
|
||||
cursor: 'pointer',
|
||||
minWidth: '48px',
|
||||
minHeight: '48px',
|
||||
border: process.env.NODE_ENV === 'development' ? '2px solid lime' : 'none', // 更明顯的除錯邊框
|
||||
'&:hover': {
|
||||
backgroundColor: actualTheme === 'dark'
|
||||
? 'rgba(255, 255, 255, 0.1)'
|
||||
: 'rgba(0, 0, 0, 0.1)',
|
||||
},
|
||||
'&:active': {
|
||||
backgroundColor: actualTheme === 'dark'
|
||||
? 'rgba(255, 255, 255, 0.2)'
|
||||
: 'rgba(0, 0, 0, 0.2)',
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -303,6 +337,9 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ children }) => {
|
||||
}}
|
||||
ModalProps={{
|
||||
keepMounted: true, // 手機端性能優化
|
||||
style: {
|
||||
zIndex: isMobile ? 1300 : undefined, // 確保 modal 不會遮擋按鈕
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Sidebar
|
||||
@@ -317,7 +354,7 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ children }) => {
|
||||
component="main"
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
width: { lg: `calc(100% - ${getDrawerWidth()}px)` },
|
||||
width: isMobile ? '100%' : `calc(100% - ${getDrawerWidth()}px)`,
|
||||
minHeight: '100vh',
|
||||
backgroundColor: actualTheme === 'dark' ? '#111827' : '#f9fafb',
|
||||
transition: 'width 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
|
469
usermanual.md
Normal file
469
usermanual.md
Normal file
@@ -0,0 +1,469 @@
|
||||
# PANJIT To-Do System 使用者手冊
|
||||
|
||||
## 📖 目錄
|
||||
|
||||
1. [系統簡介](#系統簡介)
|
||||
2. [登入系統](#登入系統)
|
||||
3. [主要功能](#主要功能)
|
||||
4. [待辦事項管理](#待辦事項管理)
|
||||
5. [協作功能](#協作功能)
|
||||
6. [通知設定](#通知設定)
|
||||
7. [Excel 匯入匯出](#excel-匯入匯出)
|
||||
8. [進階功能](#進階功能)
|
||||
9. [常見問題](#常見問題)
|
||||
|
||||
---
|
||||
|
||||
## 系統簡介
|
||||
|
||||
PANJIT To-Do System 是一個專為企業環境設計的待辦事項管理系統,提供:
|
||||
|
||||
- **統一登入**:使用公司 AD/LDAP 帳號直接登入
|
||||
- **多人協作**:支援團隊合作、責任分工
|
||||
- **智能通知**:自動化郵件提醒,不錯過任何重要任務
|
||||
- **數據管理**:Excel 批量匯入匯出,高效處理大量資料
|
||||
- **行動支援**:響應式設計,桌面和行動裝置完美適配
|
||||
|
||||
---
|
||||
|
||||
## 登入系統
|
||||
|
||||
### 🔐 第一次登入
|
||||
|
||||
1. **開啟系統**
|
||||
- 瀏覽器開啟:`http://your-company-domain.com`
|
||||
- 系統支援:Chrome、Firefox、Safari、Edge
|
||||
|
||||
2. **輸入帳號密碼**
|
||||
- 使用者名稱:`帳號@panjit.com.tw` 或 `帳號`
|
||||
- 密碼:與 Windows 登入相同
|
||||
|
||||
3. **首次登入設定**
|
||||
- 系統會自動從 AD 取得您的姓名和 Email
|
||||
- 建立個人偏好設定
|
||||
- 設定預設通知選項
|
||||
|
||||
### ⚙️ 登入選項
|
||||
|
||||
- **記住我**:勾選後下次自動登入(7天內有效)
|
||||
- **語言切換**:支援繁體中文、英文
|
||||
- **主題模式**:淺色/深色主題切換
|
||||
|
||||
---
|
||||
|
||||
## 主要功能
|
||||
|
||||
### 📱 系統介面
|
||||
|
||||
#### 頂部導航欄
|
||||
- **系統標題**:顯示目前頁面
|
||||
- **搜尋列**:快速搜尋待辦事項
|
||||
- **通知鈴鐺**:系統通知提醒
|
||||
- **使用者頭像**:個人設定選單
|
||||
|
||||
#### 左側選單
|
||||
- **儀表板**:系統概覽和統計
|
||||
- **待辦清單**:主要工作區域
|
||||
- **行事曆**:時間軸檢視
|
||||
- **設定**:個人化設定
|
||||
|
||||
#### 主要工作區
|
||||
- **工具列**:篩選、排序、批量操作
|
||||
- **清單檢視**:條列式顯示
|
||||
- **卡片檢視**:圖像化顯示
|
||||
- **行事曆檢視**:時間軸顯示
|
||||
|
||||
---
|
||||
|
||||
## 待辦事項管理
|
||||
|
||||
### ➕ 建立新待辦事項
|
||||
|
||||
1. **點選「新增待辦」按鈕**
|
||||
- 位於右上角藍色按鈕
|
||||
- 快捷鍵:`Ctrl + N`
|
||||
|
||||
2. **填寫基本資訊**
|
||||
```
|
||||
標題*:簡潔描述任務內容
|
||||
描述:詳細說明和注意事項
|
||||
狀態:新建立 (預設)
|
||||
優先級:中 (預設)
|
||||
到期日:選擇完成期限
|
||||
```
|
||||
|
||||
3. **指派人員**
|
||||
- **負責人**:執行任務的人員
|
||||
- 支援多人負責
|
||||
- 可搜尋公司同事姓名或帳號
|
||||
- 自動驗證帳號存在性
|
||||
|
||||
- **追蹤人員**:需要了解進度的人員
|
||||
- 主管或相關部門同事
|
||||
- 會收到狀態變更通知
|
||||
|
||||
4. **進階設定**
|
||||
- **標籤**:分類標記(可自訂)
|
||||
- **星號標記**:重要項目標示
|
||||
- **公開/私人**:可見性設定
|
||||
|
||||
### ✏️ 編輯待辦事項
|
||||
|
||||
1. **開啟編輯模式**
|
||||
- 點選事項標題直接編輯
|
||||
- 或點選「編輯」按鈕
|
||||
|
||||
2. **權限說明**
|
||||
- **建立者**:完整編輯權限
|
||||
- **負責人**:可修改狀態、描述
|
||||
- **追蹤人員**:僅可查看
|
||||
|
||||
3. **狀態變更**
|
||||
- **新建立** → **進行中**:開始執行
|
||||
- **進行中** → **已阻礙**:遇到困難需協助
|
||||
- **已阻礙** → **進行中**:問題解決繼續執行
|
||||
- **進行中** → **已完成**:任務完成
|
||||
|
||||
### 🔍 搜尋和篩選
|
||||
|
||||
#### 快速搜尋
|
||||
- **關鍵字搜尋**:標題、描述、人員姓名
|
||||
- **模糊比對**:不需輸入完整字詞
|
||||
- **即時搜尋**:輸入即時顯示結果
|
||||
|
||||
#### 進階篩選
|
||||
1. **點選篩選按鈕**(漏斗圖示)
|
||||
2. **設定篩選條件**:
|
||||
- 狀態:單選或多選
|
||||
- 優先級:依重要程度篩選
|
||||
- 指派人員:查看特定人員的任務
|
||||
- 日期範圍:到期日區間
|
||||
- 標籤:依分類查看
|
||||
|
||||
3. **常用篩選**:
|
||||
- 我負責的:顯示自己的任務
|
||||
- 我追蹤的:顯示關注的項目
|
||||
- 逾期項目:已過期未完成
|
||||
- 本週到期:七天內到期
|
||||
|
||||
#### 排序選項
|
||||
- **到期日**:依時間緊急程度
|
||||
- **優先級**:依重要程度
|
||||
- **建立時間**:依新舊程度
|
||||
- **狀態**:依進度分組
|
||||
- **標題**:字母順序
|
||||
|
||||
---
|
||||
|
||||
## 協作功能
|
||||
|
||||
### 👥 團隊協作
|
||||
|
||||
#### 角色說明
|
||||
- **建立者**:任務發起人,擁有完整權限
|
||||
- **負責人**:實際執行者,可編輯任務內容
|
||||
- **追蹤人員**:關注者,可查看進度並接收通知
|
||||
|
||||
#### 協作流程
|
||||
1. **任務指派**
|
||||
```
|
||||
建立者 → 指派負責人 → 設定追蹤人員 → 發送通知
|
||||
```
|
||||
|
||||
2. **進度更新**
|
||||
```
|
||||
負責人更新狀態 → 系統記錄變更 → 自動通知相關人員
|
||||
```
|
||||
|
||||
3. **問題處理**
|
||||
```
|
||||
遇到阻礙 → 標記為「已阻礙」→ 通知建立者/追蹤人員 → 協助解決
|
||||
```
|
||||
|
||||
### 🔔 即時通知
|
||||
|
||||
#### Fire 一鍵提醒
|
||||
- **功能說明**:立即發送郵件提醒
|
||||
- **使用時機**:急件處理、重要提醒
|
||||
- **限制機制**:
|
||||
- 2分鐘冷卻時間
|
||||
- 每日20封限額
|
||||
- 防止過度騷擾
|
||||
|
||||
#### 自動化通知
|
||||
- **到期前提醒**:3天前自動發送
|
||||
- **當天提醒**:到期當日早上通知
|
||||
- **逾期提醒**:逾期1天後提醒
|
||||
- **狀態變更**:任務狀態改變時通知
|
||||
|
||||
#### 週摘要報告
|
||||
- **發送時間**:每週一早上9點
|
||||
- **內容包含**:
|
||||
- 本週待完成任務
|
||||
- 逾期項目統計
|
||||
- 新指派任務
|
||||
- 完成項目回顧
|
||||
|
||||
---
|
||||
|
||||
## 通知設定
|
||||
|
||||
### 📧 郵件通知設定
|
||||
|
||||
1. **開啟設定頁面**
|
||||
- 點選右上角個人頭像
|
||||
- 選擇「通知設定」
|
||||
|
||||
2. **通知類型設定**
|
||||
- ✅ 新任務指派通知
|
||||
- ✅ 任務狀態變更通知
|
||||
- ✅ 到期提醒通知
|
||||
- ✅ Fire 一鍵提醒
|
||||
- ✅ 週摘要報告
|
||||
|
||||
3. **時間設定**
|
||||
- **提醒天數**:到期前幾天提醒(1-7天)
|
||||
- **工作時間**:僅工作時間發送(9:00-18:00)
|
||||
- **週末通知**:是否包含週末
|
||||
|
||||
4. **郵件格式**
|
||||
- **HTML 格式**:豐富內容顯示
|
||||
- **純文字格式**:相容性更好
|
||||
- **摘要模式**:減少郵件數量
|
||||
|
||||
### 🔕 勿擾模式
|
||||
|
||||
- **暫停所有通知**:臨時關閉通知
|
||||
- **例外設定**:緊急通知例外
|
||||
- **自動恢復**:設定恢復時間
|
||||
|
||||
---
|
||||
|
||||
## Excel 匯入匯出
|
||||
|
||||
### 📥 匯入待辦事項
|
||||
|
||||
#### Step 1:下載模板
|
||||
1. **點選「Excel 匯入」按鈕**
|
||||
2. **下載標準模板**
|
||||
- 包含所有必要欄位
|
||||
- 內建格式驗證
|
||||
- 範例資料參考
|
||||
|
||||
#### Step 2:填寫資料
|
||||
```excel
|
||||
標題* | 描述 | 狀態 | 優先級 | 到期日 | 負責人* | 追蹤人員
|
||||
完成報告撰寫 | 月報內容 | NEW | HIGH | 2024/1/15 | user1 | user2,user3
|
||||
系統維護 | 定期檢查 | DOING | MEDIUM | 2024/1/20 | user2 | user1
|
||||
```
|
||||
|
||||
**欄位說明:**
|
||||
- `*` 為必填欄位
|
||||
- 狀態:NEW, DOING, BLOCKED, DONE
|
||||
- 優先級:LOW, MEDIUM, HIGH, URGENT
|
||||
- 日期格式:YYYY/MM/DD
|
||||
- 人員:使用帳號,多人用逗號分隔
|
||||
|
||||
#### Step 3:上傳檔案
|
||||
1. **選擇檔案**:支援 .xlsx, .xls, .csv
|
||||
2. **系統驗證**:
|
||||
- 格式檢查
|
||||
- 欄位驗證
|
||||
- 人員帳號確認
|
||||
- 重複項目檢查
|
||||
|
||||
3. **預覽確認**:
|
||||
- 顯示將匯入的資料
|
||||
- 標示錯誤項目
|
||||
- 提供修正建議
|
||||
|
||||
4. **執行匯入**:
|
||||
- 成功項目批量建立
|
||||
- 失敗項目詳細報告
|
||||
- 自動發送通知
|
||||
|
||||
### 📤 匯出待辦事項
|
||||
|
||||
#### 匯出選項
|
||||
1. **全部匯出**:所有可存取的待辦事項
|
||||
2. **篩選匯出**:根據目前篩選條件
|
||||
3. **選取匯出**:勾選特定項目
|
||||
4. **範圍匯出**:指定日期範圍
|
||||
|
||||
#### 檔案格式
|
||||
- **Excel 格式**:完整資料和格式
|
||||
- **CSV 格式**:純資料,相容性好
|
||||
- **PDF 報表**:列印友好格式
|
||||
|
||||
#### 匯出內容
|
||||
- 基本資訊:標題、描述、狀態、優先級
|
||||
- 時間資訊:建立時間、到期日、完成時間
|
||||
- 人員資訊:建立者、負責人、追蹤人員
|
||||
- 進階資訊:標籤、備註、操作記錄
|
||||
|
||||
---
|
||||
|
||||
## 進階功能
|
||||
|
||||
### 📊 統計報表
|
||||
|
||||
#### 個人統計
|
||||
- **任務完成率**:本週/本月完成統計
|
||||
- **平均處理時間**:從建立到完成的時間
|
||||
- **優先級分佈**:高/中/低優先級比例
|
||||
- **逾期分析**:逾期項目和原因分析
|
||||
|
||||
#### 團隊統計
|
||||
- **部門效率**:各部門完成情況
|
||||
- **工作量分析**:人員任務負荷
|
||||
- **協作頻率**:跨部門合作統計
|
||||
- **趨勢分析**:月度/季度趨勢
|
||||
|
||||
#### 系統統計
|
||||
- **使用者活躍度**:登入和操作頻率
|
||||
- **功能使用率**:各功能使用統計
|
||||
- **效能監控**:系統回應時間
|
||||
- **錯誤率統計**:系統穩定性指標
|
||||
|
||||
### 📅 行事曆整合
|
||||
|
||||
#### 檢視模式
|
||||
- **月檢視**:整月任務概覽
|
||||
- **週檢視**:週計劃詳細檢視
|
||||
- **日檢視**:單日任務清單
|
||||
- **時間線**:甘特圖式顯示
|
||||
|
||||
#### 互動功能
|
||||
- **拖拽調整**:直接拖動改變日期
|
||||
- **快速編輯**:點選事項快速修改
|
||||
- **顏色標示**:優先級和狀態色彩
|
||||
- **提醒設定**:行事曆提醒整合
|
||||
|
||||
### 🏷️ 標籤管理
|
||||
|
||||
#### 標籤功能
|
||||
- **自訂標籤**:建立個人化分類
|
||||
- **顏色標示**:視覺化識別
|
||||
- **快速篩選**:點選標籤快速篩選
|
||||
- **統計分析**:標籤使用統計
|
||||
|
||||
#### 常用標籤建議
|
||||
- 專案類:`#Project-A`, `#年度計劃`
|
||||
- 部門類:`#IT`, `#HR`, `#Sales`
|
||||
- 性質類:`#會議`, `#報告`, `#檢查`
|
||||
- 狀態類:`#待確認`, `#進行中`, `#暫停`
|
||||
|
||||
### 🔍 進階搜尋
|
||||
|
||||
#### 搜尋語法
|
||||
```
|
||||
標題搜尋:title:報告
|
||||
描述搜尋:desc:系統
|
||||
人員搜尋:user:張三
|
||||
標籤搜尋:tag:專案
|
||||
狀態搜尋:status:DOING
|
||||
日期搜尋:due:2024-01-15
|
||||
```
|
||||
|
||||
#### 組合搜尋
|
||||
```
|
||||
複合條件:title:報告 AND user:張三
|
||||
排除條件:title:會議 NOT status:DONE
|
||||
日期範圍:due:2024-01-01..2024-01-31
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常見問題
|
||||
|
||||
### ❓ 登入相關
|
||||
|
||||
**Q: 忘記密碼怎麼辦?**
|
||||
A: 系統使用公司 AD 帳號,請聯繫 IT 部門重設 Windows 密碼。
|
||||
|
||||
**Q: 帳號被鎖定無法登入?**
|
||||
A: 通常是密碼輸入錯誤多次,請聯繫 IT 部門解鎖帳號。
|
||||
|
||||
**Q: 可以在家裡使用嗎?**
|
||||
A: 需要連接公司 VPN 後才能存取內部系統。
|
||||
|
||||
### ❓ 功能使用
|
||||
|
||||
**Q: 為什麼找不到某個同事?**
|
||||
A: 請確認:
|
||||
1. 輸入正確的姓名或帳號
|
||||
2. 該同事帳號未被停用
|
||||
3. 有權限查看該同事資訊
|
||||
|
||||
**Q: 郵件通知沒有收到?**
|
||||
A: 請檢查:
|
||||
1. 垃圾信件匣
|
||||
2. 通知設定是否開啟
|
||||
3. 郵箱容量是否已滿
|
||||
4. 公司郵件伺服器是否正常
|
||||
|
||||
**Q: Excel 匯入失敗?**
|
||||
A: 常見原因:
|
||||
1. 檔案格式不正確
|
||||
2. 必填欄位為空
|
||||
3. 日期格式錯誤
|
||||
4. 人員帳號不存在
|
||||
|
||||
### ❓ 效能相關
|
||||
|
||||
**Q: 系統載入很慢?**
|
||||
A: 建議:
|
||||
1. 使用較新版本的瀏覽器
|
||||
2. 清除瀏覽器快取
|
||||
3. 檢查網路連線品質
|
||||
4. 關閉不必要的分頁
|
||||
|
||||
**Q: 行動裝置使用不順?**
|
||||
A: 建議:
|
||||
1. 使用手機瀏覽器而非APP
|
||||
2. 確保網路訊號穩定
|
||||
3. 定期清理瀏覽器快取
|
||||
|
||||
### ❓ 資料安全
|
||||
|
||||
**Q: 資料會不會外洩?**
|
||||
A: 系統安全措施:
|
||||
1. 資料存放於公司內部伺服器
|
||||
2. 使用 HTTPS 加密傳輸
|
||||
3. AD 統一身份驗證
|
||||
4. 定期備份和監控
|
||||
|
||||
**Q: 刪除的資料可以復原嗎?**
|
||||
A:
|
||||
1. 系統有30天的回收站功能
|
||||
2. 重要資料有定期備份
|
||||
3. 可聯繫管理員協助復原
|
||||
|
||||
---
|
||||
|
||||
## 🆘 技術支援
|
||||
|
||||
### 聯繫方式
|
||||
- **IT服務台**:分機 XXX
|
||||
- **Email**:it-support@panjit.com.tw
|
||||
- **內部聊天群**:IT技術支援群組
|
||||
|
||||
### 支援時間
|
||||
- **工作日**:09:00 - 18:00
|
||||
- **緊急問題**:24小時 (電話支援)
|
||||
- **系統維護時間**:每週日 02:00 - 04:00
|
||||
|
||||
### 提報問題時請提供
|
||||
1. **問題描述**:詳細說明遇到的狀況
|
||||
2. **操作步驟**:問題發生前的操作流程
|
||||
3. **錯誤訊息**:如有錯誤訊息請完整記錄
|
||||
4. **環境資訊**:使用的瀏覽器和作業系統
|
||||
5. **螢幕截圖**:有助於快速診斷問題
|
||||
|
||||
---
|
||||
|
||||
**使用者手冊版本**:1.0
|
||||
**最後更新**:2025年1月
|
||||
**適用系統版本**:PANJIT To-Do System v1.0
|
||||
|
||||
如有任何問題或建議,歡迎隨時聯繫 IT 部門。
|
Reference in New Issue
Block a user