fix timezone bug
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, flash, send_file, current_app, jsonify, abort
|
||||
from flask_login import login_required, current_user
|
||||
from datetime import datetime, timedelta
|
||||
from utils.timezone import taiwan_now, format_taiwan_time
|
||||
from models import TempSpec, db, Upload, SpecHistory
|
||||
from utils import editor_or_admin_required, add_history_log, admin_required, send_email, process_recipients
|
||||
from ldap_utils import get_ldap_group_members
|
||||
@@ -27,7 +28,7 @@ def _generate_next_spec_code():
|
||||
產生下一個暫時規範編號。
|
||||
規則: PE + 民國年(3碼) + 月份(2碼) + 流水號(2碼)
|
||||
"""
|
||||
now = datetime.now()
|
||||
now = taiwan_now()
|
||||
roc_year = now.year - 1911
|
||||
prefix = f"PE{roc_year}{now.strftime('%m')}"
|
||||
|
||||
@@ -54,7 +55,7 @@ def create_temp_spec():
|
||||
if request.method == 'POST':
|
||||
spec_code = _generate_next_spec_code()
|
||||
form_data = request.form
|
||||
now = datetime.now()
|
||||
now = taiwan_now()
|
||||
|
||||
# 1. 在資料庫中建立紀錄
|
||||
spec = TempSpec(
|
||||
@@ -140,20 +141,25 @@ def edit_spec(spec_id):
|
||||
doc_url = get_file_uri(doc_filename)
|
||||
callback_url = url_for('temp_spec.onlyoffice_callback', spec_id=spec_id, _external=True)
|
||||
|
||||
# 2. 如果是在開發環境,將 URL 中的 localhost 替換為 Docker 可存取的地址
|
||||
# 2. 修正容器間通訊的 URL,使用正確的容器名稱
|
||||
if '127.0.0.1' in doc_url or 'localhost' in doc_url:
|
||||
# 同時修正 doc_url 和 callback_url
|
||||
doc_url = doc_url.replace('127.0.0.1', 'host.docker.internal').replace('localhost', 'host.docker.internal')
|
||||
callback_url = callback_url.replace('127.0.0.1', 'host.docker.internal').replace('localhost', 'host.docker.internal')
|
||||
# 在 Docker Compose 環境中,OnlyOffice 應該透過 nginx 存取 Flask 應用
|
||||
doc_url = doc_url.replace('127.0.0.1:12013', 'panjit-tempspec-nginx:80').replace('localhost:12013', 'panjit-tempspec-nginx:80')
|
||||
doc_url = doc_url.replace('127.0.0.1', 'panjit-tempspec-nginx').replace('localhost', 'panjit-tempspec-nginx')
|
||||
callback_url = callback_url.replace('127.0.0.1:12013', 'panjit-tempspec-nginx:80').replace('localhost:12013', 'panjit-tempspec-nginx:80')
|
||||
callback_url = callback_url.replace('127.0.0.1', 'panjit-tempspec-nginx').replace('localhost', 'panjit-tempspec-nginx')
|
||||
|
||||
# --- END: 修正文件下載與回呼的 URL ---
|
||||
|
||||
oo_secret = current_app.config['ONLYOFFICE_JWT_SECRET']
|
||||
|
||||
# 生成唯一的文件密鑰,包含更新時間戳
|
||||
file_key = f"{spec.id}_{int(os.path.getmtime(doc_physical_path))}"
|
||||
|
||||
payload = {
|
||||
"document": {
|
||||
"fileType": "docx",
|
||||
"key": f"{spec.id}_{int(os.path.getmtime(doc_physical_path))}",
|
||||
"key": file_key,
|
||||
"title": doc_filename,
|
||||
"url": doc_url # <-- 使用修正後的 doc_url
|
||||
},
|
||||
@@ -161,7 +167,14 @@ def edit_spec(spec_id):
|
||||
"editorConfig": {
|
||||
"callbackUrl": callback_url, # <-- 使用修正後的回呼 URL
|
||||
"user": { "id": str(current_user.id), "name": current_user.username },
|
||||
"customization": { "autosave": True, "forcesave": True }
|
||||
"customization": {
|
||||
"autosave": True,
|
||||
"forcesave": True,
|
||||
"chat": False,
|
||||
"comments": True,
|
||||
"help": False
|
||||
},
|
||||
"mode": "edit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,22 +194,78 @@ def edit_spec(spec_id):
|
||||
@temp_spec_bp.route('/onlyoffice-callback/<int:spec_id>', methods=['POST'])
|
||||
def onlyoffice_callback(spec_id):
|
||||
data = request.json
|
||||
|
||||
if data.get('status') == 2:
|
||||
status = data.get('status')
|
||||
|
||||
# 記錄所有回調狀態以便調試
|
||||
current_app.logger.info(f"OnlyOffice callback for spec {spec_id}: status={status}, data={data}")
|
||||
|
||||
# OnlyOffice 狀態說明:
|
||||
# 0 - 文件未找到
|
||||
# 1 - 文件編輯中
|
||||
# 2 - 文件準備保存
|
||||
# 3 - 文件保存中
|
||||
# 4 - 文件已關閉,無變更
|
||||
# 6 - 文件編輯中,但已強制保存
|
||||
# 7 - 發生錯誤
|
||||
|
||||
if status in [2, 6]: # 文件需要保存或已強制保存
|
||||
try:
|
||||
response = requests.get(data['url'], timeout=10)
|
||||
if 'url' not in data:
|
||||
current_app.logger.error(f"OnlyOffice callback missing URL for spec {spec_id}")
|
||||
return jsonify({"error": 1, "message": "Missing document URL"})
|
||||
|
||||
# 驗證 JWT Token (如果有)
|
||||
token = data.get('token')
|
||||
if token:
|
||||
try:
|
||||
oo_secret = current_app.config['ONLYOFFICE_JWT_SECRET']
|
||||
jwt.decode(token, oo_secret, algorithms=['HS256'])
|
||||
except jwt.InvalidTokenError:
|
||||
current_app.logger.error(f"Invalid JWT token in OnlyOffice callback for spec {spec_id}")
|
||||
return jsonify({"error": 1, "message": "Invalid token"})
|
||||
|
||||
# 修正 OnlyOffice 回調中的 URL 以供容器間通信使用
|
||||
download_url = data['url']
|
||||
# 將外部訪問 URL 轉換為容器間通信 URL
|
||||
download_url = download_url.replace('localhost:12015', 'panjit-tempspec-onlyoffice:80')
|
||||
download_url = download_url.replace('127.0.0.1:12015', 'panjit-tempspec-onlyoffice:80')
|
||||
|
||||
current_app.logger.info(f"Downloading updated document from: {data['url']} -> {download_url}")
|
||||
response = requests.get(download_url, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
|
||||
# 保存文件
|
||||
spec = TempSpec.query.get_or_404(spec_id)
|
||||
doc_filename = f"{spec.spec_code}.docx"
|
||||
file_path = os.path.join(current_app.static_folder, 'generated', doc_filename)
|
||||
|
||||
# 確保目錄存在
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
|
||||
with open(file_path, 'wb') as f:
|
||||
f.write(response.content)
|
||||
|
||||
current_app.logger.info(f"Successfully saved updated document for spec {spec_id} to {file_path}")
|
||||
|
||||
# 更新資料庫中的修改時間
|
||||
spec.updated_at = taiwan_now()
|
||||
db.session.commit()
|
||||
|
||||
except requests.RequestException as e:
|
||||
current_app.logger.error(f"Failed to download document from OnlyOffice for spec {spec_id}: {e}")
|
||||
return jsonify({"error": 1, "message": f"Download failed: {str(e)}"})
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"ONLYOFFICE callback error for spec {spec_id}: {e}")
|
||||
current_app.logger.error(f"OnlyOffice callback error for spec {spec_id}: {e}")
|
||||
return jsonify({"error": 1, "message": str(e)})
|
||||
|
||||
elif status == 1:
|
||||
current_app.logger.info(f"Document {spec_id} is being edited")
|
||||
elif status == 4:
|
||||
current_app.logger.info(f"Document {spec_id} closed without changes")
|
||||
elif status == 7:
|
||||
current_app.logger.error(f"OnlyOffice error for document {spec_id}")
|
||||
return jsonify({"error": 1, "message": "OnlyOffice reported an error"})
|
||||
|
||||
return jsonify({"error": 0})
|
||||
|
||||
# --- 其他既有路由 ---
|
||||
@@ -251,7 +320,7 @@ def activate_spec(spec_id):
|
||||
flash('您必須上傳一個檔案。', 'danger')
|
||||
return redirect(url_for('temp_spec.activate_spec', spec_id=spec.id))
|
||||
|
||||
filename = secure_filename(f"{spec.spec_code}_signed_{datetime.now().strftime('%Y%m%d%H%M%S')}.pdf")
|
||||
filename = secure_filename(f"{spec.spec_code}_signed_{taiwan_now().strftime('%Y%m%d%H%M%S')}.pdf")
|
||||
upload_folder = os.path.join(BASE_DIR, current_app.config['UPLOAD_FOLDER'])
|
||||
os.makedirs(upload_folder, exist_ok=True)
|
||||
file_path = os.path.join(upload_folder, filename)
|
||||
@@ -260,7 +329,7 @@ def activate_spec(spec_id):
|
||||
new_upload = Upload(
|
||||
temp_spec_id=spec.id,
|
||||
filename=filename,
|
||||
upload_time=datetime.now()
|
||||
upload_time=taiwan_now()
|
||||
)
|
||||
db.session.add(new_upload)
|
||||
|
||||
@@ -313,7 +382,7 @@ def terminate_spec(spec_id):
|
||||
|
||||
spec.status = 'terminated'
|
||||
spec.termination_reason = reason
|
||||
spec.end_date = datetime.today().date()
|
||||
spec.end_date = taiwan_now().date()
|
||||
add_history_log(spec.id, '終止', f"原因: {reason}")
|
||||
|
||||
# --- Start of Dynamic Email Notification ---
|
||||
@@ -382,7 +451,12 @@ def download_signed_pdf(spec_id):
|
||||
@editor_or_admin_required
|
||||
def extend_spec(spec_id):
|
||||
spec = TempSpec.query.get_or_404(spec_id)
|
||||
|
||||
|
||||
# 檢查展延次數限制(最多展延2次)
|
||||
if spec.extension_count >= 2:
|
||||
flash('此暫時規範已達展延次數上限(2次),無法再次展延。總效期已達90天上限。', 'danger')
|
||||
return redirect(url_for('temp_spec.spec_list'))
|
||||
|
||||
if request.method == 'POST':
|
||||
new_end_date_str = request.form.get('new_end_date')
|
||||
uploaded_file = request.files.get('new_file')
|
||||
@@ -399,7 +473,7 @@ def extend_spec(spec_id):
|
||||
spec.extension_count += 1
|
||||
spec.status = 'active'
|
||||
|
||||
filename = secure_filename(f"{spec.spec_code}_extension_{spec.extension_count}_{datetime.now().strftime('%Y%m%d')}.pdf")
|
||||
filename = secure_filename(f"{spec.spec_code}_extension_{spec.extension_count}_{taiwan_now().strftime('%Y%m%d')}.pdf")
|
||||
upload_folder = os.path.join(BASE_DIR, current_app.config['UPLOAD_FOLDER'])
|
||||
os.makedirs(upload_folder, exist_ok=True)
|
||||
file_path = os.path.join(upload_folder, filename)
|
||||
@@ -408,7 +482,7 @@ def extend_spec(spec_id):
|
||||
new_upload = Upload(
|
||||
temp_spec_id=spec.id,
|
||||
filename=filename,
|
||||
upload_time=datetime.now()
|
||||
upload_time=taiwan_now()
|
||||
)
|
||||
db.session.add(new_upload)
|
||||
|
||||
|
Reference in New Issue
Block a user