diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 68486bc..a881140 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,7 +1,8 @@ { "permissions": { "allow": [ - "Bash(dir)" + "Bash(dir)", + "Bash(docker:*)" ], "deny": [], "ask": [] diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..d73755c --- /dev/null +++ b/.env.production @@ -0,0 +1,113 @@ +# =========================================== +# 生產環境配置文件 +# =========================================== + +# =========================================== +# MySQL 資料庫連線 +# =========================================== +DATABASE_URL=mysql+pymysql://A060:WLeSCi0yhtc7@mysql.theaken.com:33306/db_A060 +MYSQL_HOST=mysql.theaken.com +MYSQL_PORT=33306 +MYSQL_USER=A060 +MYSQL_PASSWORD=WLeSCi0yhtc7 +MYSQL_DATABASE=db_A060 +MYSQL_CHARSET=utf8mb4 + +# =========================================== +# Flask 應用配置 +# =========================================== +FLASK_ENV=production +SECRET_KEY=prod-todo-secret-key-2024-change-me +JWT_SECRET_KEY=prod-jwt-secret-key-2024-change-me +JWT_ACCESS_TOKEN_EXPIRES=3600 + +# =========================================== +# AD/LDAP 設定 (生產環境) +# =========================================== +USE_MOCK_LDAP=false +LDAP_SERVER=panjit.com.tw +LDAP_PORT=389 +LDAP_USE_SSL=false +LDAP_BIND_USER_DN=CN=LdapBind,CN=Users,DC=PANJIT,DC=COM,DC=TW +LDAP_BIND_USER_PASSWORD=panjit2481 +LDAP_SEARCH_BASE=OU=PANJIT,DC=panjit,DC=com,DC=tw +LDAP_USER_LOGIN_ATTR=userPrincipalName + +# =========================================== +# SMTP 設定 +# =========================================== +SMTP_SERVER=mail.panjit.com.tw +SMTP_PORT=25 +SMTP_USE_TLS=false +SMTP_USE_SSL=false +SMTP_AUTH_REQUIRED=false +SMTP_SENDER_EMAIL=todo-system@panjit.com.tw +SMTP_SENDER_PASSWORD= + +# =========================================== +# CORS 設定 +# =========================================== +CORS_ORIGINS=http://localhost:12012 + +# =========================================== +# 日誌設定 +# =========================================== +LOG_LEVEL=INFO +LOG_FILE_PATH=logs/app.log +LOG_MAX_BYTES=10485760 +LOG_BACKUP_COUNT=5 + +# =========================================== +# Redis 設定 (如果使用) +# =========================================== +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_DB=0 +REDIS_PASSWORD= + +# =========================================== +# Celery 設定 (如果使用) +# =========================================== +CELERY_BROKER_URL=redis://localhost:6379/0 +CELERY_RESULT_BACKEND=redis://localhost:6379/0 + +# =========================================== +# 前端配置 +# =========================================== +NEXT_PUBLIC_API_URL=http://localhost:12011 + +# =========================================== +# 服務端口配置 +# =========================================== +BACKEND_PORT=12011 +FRONTEND_PORT=12012 + +# =========================================== +# 安全設定 +# =========================================== +ALLOWED_HOSTS=localhost,127.0.0.1 +SECURE_SSL_REDIRECT=false +SESSION_COOKIE_SECURE=false +CSRF_COOKIE_SECURE=false + +# =========================================== +# 檔案上傳設定 +# =========================================== +MAX_CONTENT_LENGTH=16777216 +UPLOAD_FOLDER=uploads +ALLOWED_EXTENSIONS=xlsx,xls,csv + +# =========================================== +# 郵件配額設定 +# =========================================== +DAILY_EMAIL_LIMIT=100 +MONTHLY_EMAIL_LIMIT=1000 + +# =========================================== +# 系統設定 +# =========================================== +SYSTEM_NAME=TODO管理系統 +SYSTEM_VERSION=1.0.0 +ADMIN_EMAIL=ymirliu@panjit.com.tw +DEFAULT_ADMIN_USER=ymirliu@panjit.com.tw + diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..5d39197 --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,279 @@ +# TODO管理系統 - 生產環境部署指南 + +## 📋 概述 + +本文件提供TODO管理系統的完整生產環境部署指南,包含所有必要的配置和步驟。 + +## 🏗️ 系統架構 + +``` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ 前端 (Next.js) │ │ 後端 (Flask) │ │ MySQL DB │ +│ Port: 12012 │◄───┤ Port: 12011 │◄───┤ theaken.com │ +│ Docker容器 │ │ Docker容器 │ │ Port: 33306 │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ + ▼ + ┌─────────────────┐ + │ LDAP/AD │ + │ panjit.com.tw │ + │ Port: 389 │ + └─────────────────┘ +``` + +## 🚀 快速部署 + +### Windows 環境 + +```batch +# 1. 克隆專案(如果尚未克隆) +git clone +cd TODOLIST + +# 2. 執行部署腳本 +deploy.bat +``` + +### Linux/Mac 環境 + +```bash +# 1. 克隆專案(如果尚未克隆) +git clone +cd TODOLIST + +# 2. 設置執行權限並執行部署腳本 +chmod +x deploy.sh +./deploy.sh +``` + +## 📁 部署文件結構 + +``` +TODOLIST/ +├── backend/ # 後端代碼 +│ ├── Dockerfile # 後端Docker構建文件 +│ ├── requirements.txt # Python依賴 +│ └── ... +├── frontend/ # 前端代碼 +│ ├── Dockerfile # 前端Docker構建文件 +│ ├── package.json # Node.js依賴 +│ └── ... +├── docker-compose.prod.yml # 生產環境Docker Compose配置 +├── .env.production # 生產環境變量配置 +├── deploy.bat # Windows部署腳本 +├── deploy.sh # Linux/Mac部署腳本 +└── DEPLOYMENT.md # 部署說明文件 +``` + +## 🔧 環境配置 + +### 生產環境變量 (`.env.production`) + +本系統使用以下生產環境配置: + +#### 🗄️ 資料庫配置 +- **MySQL主機**: `mysql.theaken.com:33306` +- **資料庫**: `db_A060` +- **用戶**: `A060` + +#### 🔐 LDAP認證配置 +- **LDAP服務器**: `panjit.com.tw:389` +- **搜索基礎**: `OU=PANJIT,DC=panjit,DC=com,DC=tw` +- **認證方式**: Active Directory集成 + +#### 📧 郵件服務配置 +- **SMTP服務器**: `mail.panjit.com.tw:25` +- **發送者**: `todo-system@panjit.com.tw` + +#### 🌐 服務端口 +- **前端**: `12012` +- **後端API**: `12011` + +## 🐳 Docker配置 + +### 服務組成 + +1. **todo-backend-prod**: Flask後端容器 + - 端口映射: `12011:12011` + - 健康檢查: `/api/health` + - 自動重啟: `unless-stopped` + +2. **todo-frontend-prod**: Next.js前端容器 + - 端口映射: `12012:12012` + - 健康檢查: 根路徑檢查 + - 自動重啟: `unless-stopped` + +### 網路配置 + +- 使用自定義橋接網路 `todolist-network` +- 容器間可通過服務名稱通信 +- 外部訪問通過端口映射 + +## 🔍 手動部署步驟 + +如果需要手動部署,請按以下步驟執行: + +### 1. 停止現有服務 + +```bash +# 停止並移除現有容器 +docker stop todo-backend-prod todo-frontend-prod +docker rm todo-backend-prod todo-frontend-prod +``` + +### 2. 建置Docker鏡像 + +```bash +# 建置後端鏡像 +docker build -t todolist-backend:latest ./backend + +# 建置前端鏡像 +docker build -t todo-frontend:latest \ + --build-arg NEXT_PUBLIC_API_URL=http://localhost:12011 \ + ./frontend +``` + +### 3. 啟動服務 + +```bash +# 使用Docker Compose啟動 +docker-compose -f docker-compose.prod.yml up -d +``` + +### 4. 驗證部署 + +```bash +# 檢查容器狀態 +docker ps + +# 檢查服務健康 +curl http://localhost:12011/api/health +curl http://localhost:12012 +``` + +## 🧪 測試與驗證 + + +### API測試 + +```bash +# 健康檢查 +curl http://localhost:12011/api/health + +# CORS測試 +curl -H "Origin: http://localhost:12012" \ + -H "Access-Control-Request-Method: POST" \ + -H "Access-Control-Request-Headers: Content-Type,Authorization" \ + -X OPTIONS http://localhost:12011/api/auth/login +``` + +## 🛠️ 維護指令 + +### 日誌查看 + +```bash +# 查看所有服務日誌 +docker-compose -f docker-compose.prod.yml logs -f + +# 查看特定服務日誌 +docker logs todo-backend-prod -f +docker logs todo-frontend-prod -f +``` + +### 服務管理 + +```bash +# 重啟服務 +docker-compose -f docker-compose.prod.yml restart + +# 停止服務 +docker-compose -f docker-compose.prod.yml down + +# 更新並重啟 +docker-compose -f docker-compose.prod.yml down +docker-compose -f docker-compose.prod.yml up -d --build +``` + +### 資源監控 + +```bash +# 查看容器狀態 +docker ps + +# 查看資源使用 +docker stats + +# 查看容器詳情 +docker inspect todo-backend-prod +docker inspect todo-frontend-prod +``` + +## 🚨 故障排除 + +### 常見問題 + +#### 1. 容器無法啟動 +```bash +# 檢查日誌 +docker logs todo-backend-prod +docker logs todo-frontend-prod + +# 檢查端口占用 +netstat -ano | findstr :12011 +netstat -ano | findstr :12012 +``` + +#### 2. 資料庫連接失敗 +- 確認網路連通性到 `mysql.theaken.com:33306` +- 驗證資料庫憑證 +- 檢查防火牆設置 + +#### 3. LDAP認證失敗 +- 確認網路連通性到 `panjit.com.tw:389` +- 驗證LDAP服務帳號憑證 +- 檢查搜索基礎設置 + +#### 4. CORS錯誤 +- 確認前後端URL配置 +- 檢查 `CORS_ORIGINS` 環境變量 +- 驗證前端請求標頭 + +### 健康檢查端點 + +- **後端健康檢查**: `GET http://localhost:12011/api/health` +- **前端健康檢查**: `GET http://localhost:12012` + +## 🔒 安全考量 + +### 生產環境安全設置 + +1. **更改默認密鑰**: + - 修改 `SECRET_KEY` 和 `JWT_SECRET_KEY` + - 使用強密碼策略 + +2. **網路安全**: + - 考慮使用反向代理(Nginx) + - 配置HTTPS證書 + - 限制外部訪問 + +3. **監控與日誌**: + - 設置日誌輪轉 + - 監控系統資源 + - 設置告警機制 + +## 📞 支援聯繫 + +- **系統管理員**: `ymirliu@panjit.com.tw` +- **技術支援**: 參考專案文檔或聯繫開發團隊 + +## 📝 版本資訊 + +- **系統版本**: 1.0.0 +- **Docker映像**: + - Backend: `todolist-backend:latest` + - Frontend: `todo-frontend:latest` +- **部署日期**: 自動生成 + +--- + +**注意**: 本文件包含敏感配置資訊,請妥善保管,僅限授權人員查看。 \ No newline at end of file diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..b82b7d4 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,99 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Virtual environments +venv/ +env/ +ENV/ +.venv/ +.env/ + +# Environment files +.env +.env.local +.env.development +.env.production + +# Flask +instance/ +.webassets-cache + +# Celery +celerybeat-schedule +celerybeat.pid + +# Logs +logs/ +*.log + +# Uploads +uploads/ +temp/ +tmp/ + +# Database +*.db +*.sqlite +*.sqlite3 + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db +*.tmp +*.temp + +# Git +.git/ +.gitignore +.gitattributes + +# Documentation +README.md +CHANGELOG.md +LICENSE +docs/ + +# Docker files +Dockerfile* +.dockerignore +docker-compose*.yml + +# Testing +.pytest_cache/ +.coverage +htmlcov/ +.tox/ +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ \ No newline at end of file diff --git a/deploy.bat b/deploy.bat new file mode 100644 index 0000000..3a3eeb2 --- /dev/null +++ b/deploy.bat @@ -0,0 +1,103 @@ +@echo off +REM =========================================== +REM TODO管理系統 - 生產環境部署腳本 +REM =========================================== + +echo. +echo ======================================== +echo TODO管理系統 - 生產環境部署 +echo ======================================== +echo. + +REM 檢查Docker是否運行 +echo [INFO] 檢查Docker狀態... +docker info >nul 2>&1 +if %errorlevel% neq 0 ( + echo [ERROR] Docker未運行,請啟動Docker Desktop後再執行此腳本 + pause + exit /b 1 +) +echo [SUCCESS] Docker運行正常 + +REM 停止現有容器 +echo. +echo [INFO] 停止現有容器... +docker stop todo-backend-prod todo-frontend-prod 2>nul +docker rm todo-backend-prod todo-frontend-prod 2>nul + +REM 建置Docker鏡像 +echo. +echo [INFO] 建置Docker鏡像... +echo [INFO] 建置後端鏡像... +docker build -t todolist-backend:latest ./backend +if %errorlevel% neq 0 ( + echo [ERROR] 後端鏡像建置失敗 + pause + exit /b 1 +) +echo [SUCCESS] 後端鏡像建置完成 + +echo [INFO] 建置前端鏡像... +docker build -t todo-frontend:latest --build-arg NEXT_PUBLIC_API_URL=http://localhost:12011 ./frontend +if %errorlevel% neq 0 ( + echo [ERROR] 前端鏡像建置失敗 + pause + exit /b 1 +) +echo [SUCCESS] 前端鏡像建置完成 + +REM 啟動服務 +echo. +echo [INFO] 啟動生產環境服務... +docker-compose -f docker-compose.prod.yml up -d +if %errorlevel% neq 0 ( + echo [ERROR] 服務啟動失敗 + pause + exit /b 1 +) + +REM 等待服務啟動 +echo [INFO] 等待服務啟動... +timeout /t 10 /nobreak >nul + +REM 檢查服務狀態 +echo. +echo [INFO] 檢查服務狀態... +docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | findstr todo- + +REM 健康檢查 +echo. +echo [INFO] 執行健康檢查... + +echo [INFO] 檢查後端API... +curl -s -w "%%{http_code}" -o nul http://localhost:12011/api/health >nul 2>&1 +if %errorlevel% equ 0 ( + echo [SUCCESS] 後端API響應正常 +) else ( + echo [WARNING] 後端API可能尚未完全啟動,請稍後手動檢查 +) + +echo [INFO] 檢查前端... +curl -s -w "%%{http_code}" -o nul http://localhost:12012 >nul 2>&1 +if %errorlevel% equ 0 ( + echo [SUCCESS] 前端響應正常 +) else ( + echo [WARNING] 前端可能尚未完全啟動,請稍後手動檢查 +) + +echo. +echo ======================================== +echo 部署完成! +echo ======================================== +echo. +echo 服務地址: +echo 前端: http://localhost:12012 +echo 後端API: http://localhost:12011 +echo. +echo. +echo 管理指令: +echo 查看日誌: docker-compose -f docker-compose.prod.yml logs -f +echo 停止服務: docker-compose -f docker-compose.prod.yml down +echo 重啟服務: docker-compose -f docker-compose.prod.yml restart +echo. +pause \ No newline at end of file diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..40f6a82 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# =========================================== +# TODO管理系統 - 生產環境部署腳本 (Linux/Mac) +# =========================================== + +echo "" +echo "========================================" +echo "TODO管理系統 - 生產環境部署" +echo "========================================" +echo "" + +# 檢查Docker是否運行 +echo "[INFO] 檢查Docker狀態..." +if ! docker info >/dev/null 2>&1; then + echo "[ERROR] Docker未運行,請啟動Docker後再執行此腳本" + exit 1 +fi +echo "[SUCCESS] Docker運行正常" + +# 停止現有容器 +echo "" +echo "[INFO] 停止現有容器..." +docker stop todo-backend-prod todo-frontend-prod 2>/dev/null || true +docker rm todo-backend-prod todo-frontend-prod 2>/dev/null || true + +# 建置Docker鏡像 +echo "" +echo "[INFO] 建置Docker鏡像..." +echo "[INFO] 建置後端鏡像..." +if ! docker build -t todolist-backend:latest ./backend; then + echo "[ERROR] 後端鏡像建置失敗" + exit 1 +fi +echo "[SUCCESS] 後端鏡像建置完成" + +echo "[INFO] 建置前端鏡像..." +if ! docker build -t todo-frontend:latest --build-arg NEXT_PUBLIC_API_URL=http://localhost:12011 ./frontend; then + echo "[ERROR] 前端鏡像建置失敗" + exit 1 +fi +echo "[SUCCESS] 前端鏡像建置完成" + +# 啟動服務 +echo "" +echo "[INFO] 啟動生產環境服務..." +if ! docker-compose -f docker-compose.prod.yml up -d; then + echo "[ERROR] 服務啟動失敗" + exit 1 +fi + +# 等待服務啟動 +echo "[INFO] 等待服務啟動..." +sleep 10 + +# 檢查服務狀態 +echo "" +echo "[INFO] 檢查服務狀態..." +docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep todo- + +# 健康檢查 +echo "" +echo "[INFO] 執行健康檢查..." + +echo "[INFO] 檢查後端API..." +if curl -s -f http://localhost:12011/api/health >/dev/null 2>&1; then + echo "[SUCCESS] 後端API響應正常" +else + echo "[WARNING] 後端API可能尚未完全啟動,請稍後手動檢查" +fi + +echo "[INFO] 檢查前端..." +if curl -s -f http://localhost:12012 >/dev/null 2>&1; then + echo "[SUCCESS] 前端響應正常" +else + echo "[WARNING] 前端可能尚未完全啟動,請稍後手動檢查" +fi + +echo "" +echo "========================================" +echo "部署完成!" +echo "========================================" +echo "" +echo "服務地址:" +echo " 前端: http://localhost:12012" +echo " 後端API: http://localhost:12011" +echo "" +echo "" +echo "管理指令:" +echo " 查看日誌: docker-compose -f docker-compose.prod.yml logs -f" +echo " 停止服務: docker-compose -f docker-compose.prod.yml down" +echo " 重啟服務: docker-compose -f docker-compose.prod.yml restart" +echo "" \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..469ae3c --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,94 @@ +version: '3.8' + +services: + todo-backend: + build: + context: ./backend + dockerfile: Dockerfile + image: todolist-backend:latest + container_name: todo-backend-prod + ports: + - "12011:12011" + environment: + # MySQL Database Configuration + - DATABASE_URL=mysql+pymysql://A060:WLeSCi0yhtc7@mysql.theaken.com:33306/db_A060 + - MYSQL_HOST=mysql.theaken.com + - MYSQL_PORT=33306 + - MYSQL_USER=A060 + - MYSQL_PASSWORD=WLeSCi0yhtc7 + - MYSQL_DATABASE=db_A060 + - MYSQL_CHARSET=utf8mb4 + + # CORS Configuration + - CORS_ORIGINS=http://localhost:12012 + + # LDAP Configuration (Production) + - USE_MOCK_LDAP=false + - LDAP_SERVER=panjit.com.tw + - LDAP_PORT=389 + - LDAP_USE_SSL=false + - LDAP_BIND_USER_DN=CN=LdapBind,CN=Users,DC=PANJIT,DC=COM,DC=TW + - LDAP_BIND_USER_PASSWORD=panjit2481 + - LDAP_SEARCH_BASE=OU=PANJIT,DC=panjit,DC=com,DC=tw + - LDAP_USER_LOGIN_ATTR=userPrincipalName + + # SMTP Configuration + - SMTP_SERVER=mail.panjit.com.tw + - SMTP_PORT=25 + - SMTP_USE_TLS=false + - SMTP_USE_SSL=false + - SMTP_AUTH_REQUIRED=false + - SMTP_SENDER_EMAIL=todo-system@panjit.com.tw + - SMTP_SENDER_PASSWORD= + + # Flask Configuration + - FLASK_ENV=production + - SECRET_KEY=your-production-secret-key-change-me + - JWT_SECRET_KEY=your-jwt-secret-key-change-me + + # Logging + - LOG_LEVEL=INFO + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:12011/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - todolist-network + + todo-frontend: + build: + context: ./frontend + dockerfile: Dockerfile + args: + - NEXT_PUBLIC_API_URL=http://localhost:12011 + image: todo-frontend:latest + container_name: todo-frontend-prod + ports: + - "12012:12012" + environment: + - NODE_ENV=production + - NEXT_PUBLIC_API_URL=http://localhost:12011 + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:12012"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - todolist-network + depends_on: + - todo-backend + +networks: + todolist-network: + driver: bridge + +volumes: + backend-logs: + driver: local + frontend-logs: + driver: local \ No newline at end of file diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..55fbeca --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,60 @@ +node_modules +.git +.next +out +build +dist +coverage + +# Environment files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +*.log + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ +*.lcov + +# nyc test coverage +.nyc_output + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db +*.tmp +*.temp + +# Documentation +README.md +CHANGELOG.md +LICENSE +docs/ + +# Docker files +Dockerfile* +.dockerignore +docker-compose*.yml + +# Git files +.gitignore +.gitattributes \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 31e615c..979dec1 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -7,7 +7,7 @@ WORKDIR /app # Install dependencies based on the preferred package manager COPY package.json package-lock.json* ./ -RUN npm ci --only=production +RUN npm ci # Rebuild the source code only when needed FROM base AS builder @@ -15,6 +15,10 @@ WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . +# Set build-time environment variables +ARG NEXT_PUBLIC_API_URL=http://localhost:12011 +ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL + # Build the application RUN npm run build diff --git a/frontend/src/components/todos/ExcelImport.tsx b/frontend/src/components/todos/ExcelImport.tsx index c1d7784..388399d 100644 --- a/frontend/src/components/todos/ExcelImport.tsx +++ b/frontend/src/components/todos/ExcelImport.tsx @@ -52,6 +52,7 @@ interface TodoImportData { due_date: string | null; responsible_users: string[]; followers: string[]; + is_public: boolean; } const ExcelImport: React.FC = ({ open, onClose, onImportComplete }) => { diff --git a/frontend/src/components/todos/TodoDialog.tsx b/frontend/src/components/todos/TodoDialog.tsx index 5d27b7e..67daecd 100644 --- a/frontend/src/components/todos/TodoDialog.tsx +++ b/frontend/src/components/todos/TodoDialog.tsx @@ -67,6 +67,7 @@ interface LocalTodo { creator?: User; responsible: User[]; isPublic: boolean; + tags?: string[]; } interface TodoDialogProps { diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 14f268d..69ce251 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -24,6 +24,7 @@ export interface Todo { followers: string[]; responsible_users_details?: UserDetail[]; followers_details?: UserDetail[]; + tags?: string[]; } export interface TodoCreate { @@ -36,6 +37,7 @@ export interface TodoCreate { is_public?: boolean; responsible_users?: string[]; followers?: string[]; + tags?: string[]; } export interface TodoUpdate extends Partial { diff --git a/manage.bat b/manage.bat new file mode 100644 index 0000000..7f99955 --- /dev/null +++ b/manage.bat @@ -0,0 +1,74 @@ +@echo off +REM =========================================== +REM TODO管理系統 - 管理腳本 +REM =========================================== + +if "%1"=="" ( + echo. + echo TODO管理系統 - 管理指令 + echo. + echo 用法: manage.bat [指令] + echo. + echo 可用指令: + echo start - 啟動服務 + echo stop - 停止服務 + echo restart - 重啟服務 + echo logs - 查看日誌 + echo status - 查看服務狀態 + echo build - 重新建置並啟動 + echo clean - 清理未使用的Docker資源 + echo. + exit /b 0 +) + +if "%1"=="start" ( + echo [INFO] 啟動TODO管理系統... + docker-compose -f docker-compose.prod.yml up -d + goto end +) + +if "%1"=="stop" ( + echo [INFO] 停止TODO管理系統... + docker-compose -f docker-compose.prod.yml down + goto end +) + +if "%1"=="restart" ( + echo [INFO] 重啟TODO管理系統... + docker-compose -f docker-compose.prod.yml restart + goto end +) + +if "%1"=="logs" ( + echo [INFO] 查看服務日誌 (Ctrl+C 退出)... + docker-compose -f docker-compose.prod.yml logs -f + goto end +) + +if "%1"=="status" ( + echo [INFO] 服務狀態: + docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | findstr todo- + goto end +) + +if "%1"=="build" ( + echo [INFO] 重新建置並啟動服務... + docker-compose -f docker-compose.prod.yml down + docker build -t todolist-backend:latest ./backend + docker build -t todo-frontend:latest --build-arg NEXT_PUBLIC_API_URL=http://localhost:12011 ./frontend + docker-compose -f docker-compose.prod.yml up -d + goto end +) + +if "%1"=="clean" ( + echo [INFO] 清理未使用的Docker資源... + docker system prune -f + echo [SUCCESS] 清理完成 + goto end +) + +echo [ERROR] 未知指令: %1 +echo 使用 'manage.bat' 查看可用指令 + +:end +echo. \ No newline at end of file