lesson edit (add 阶段/步骤)
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# views/lesson.py
|
||||
from flask import Blueprint, jsonify, request, render_template, session, current_app
|
||||
from werkzeug.exceptions import BadRequest
|
||||
from bson import ObjectId
|
||||
from datetime import datetime
|
||||
from ..auth.decorators import require_role
|
||||
from ..services.course_service import load_material
|
||||
from ..services.course_service import load_material,save_materials_markdown_cos
|
||||
|
||||
bp = Blueprint('lesson', __name__)
|
||||
|
||||
@@ -18,7 +19,7 @@ def edit_lesson_detail(material_id, chapter_name, lesson_name):
|
||||
if chapter.chapter_name == chapter_name:
|
||||
for lesson in chapter.lessons:
|
||||
if lesson.lesson_name == lesson_name:
|
||||
return render_template('lesson.html', lesson=lesson.model_dump(), role="teacher", material=material.model_dump())
|
||||
return render_template('lesson.html', lesson=lesson.model_dump(), role="teacher", material={**material.model_dump(), "material_id": material_id}, chapter=chapter.model_dump())
|
||||
return jsonify({"message": "课时不存在"}), 404
|
||||
|
||||
# 返回某份 markdown 文件内容(你也可以直接返回 S3/OSS 的直链)
|
||||
@@ -32,10 +33,64 @@ def get_markdown_file(material_id, chapter_name, lesson_name, filename):
|
||||
}
|
||||
return demo_map.get(filename, ""), 200
|
||||
|
||||
# 保存(更新)某一份 markdown(前端会把编辑后的文本整体传回)
|
||||
@bp.route('/api/lesson_file/<material_id>/<chapter_name>/<lesson_name>/<filename>', methods=['PUT'])
|
||||
def save_markdown_file(material_id, chapter_name, lesson_name, filename):
|
||||
text = request.get_data(as_text=True)
|
||||
# TODO: 写入存储,并做版本/审计
|
||||
# 返回更新时间等
|
||||
return jsonify({"saved": True, "updated_at": datetime.utcnow().isoformat()}), 200
|
||||
@bp.route("/api/materials/save/<material_id>/<chapter_name>/<lesson_name>", methods=['POST'])
|
||||
@require_role(roles='teacher')
|
||||
def save_materials_markdown(material_id, chapter_name, lesson_name):
|
||||
payload = request.get_json(silent=True, force=True)
|
||||
if not payload:
|
||||
raise BadRequest("缺少 JSON payload")
|
||||
|
||||
# 基础校验
|
||||
required_keys = ("lesson", "prompt", "score")
|
||||
for k in required_keys:
|
||||
if k not in payload or not isinstance(payload[k], dict):
|
||||
raise BadRequest(f"缺少或非法字段: {k}")
|
||||
if "cdn_link" not in payload[k] or "content" not in payload[k]:
|
||||
raise BadRequest(f"{k} 需要包含 cdn_link 与 content 字段")
|
||||
if not isinstance(payload[k]["cdn_link"], str) or not isinstance(payload[k]["content"], str):
|
||||
raise BadRequest(f"{k}.cdn_link 与 {k}.content 必须为字符串")
|
||||
|
||||
# 可选:版本/并发控制(若你前端传了)
|
||||
version = payload.get("version")
|
||||
|
||||
docs = {
|
||||
"lesson": {
|
||||
"cdn_link": payload["lesson"]["cdn_link"].strip(),
|
||||
"content" : payload["lesson"]["content"]
|
||||
},
|
||||
"prompt": {
|
||||
"cdn_link": payload["prompt"]["cdn_link"].strip(),
|
||||
"content" : payload["prompt"]["content"]
|
||||
},
|
||||
"score": {
|
||||
"cdn_link": payload["score"]["cdn_link"].strip(),
|
||||
"content" : payload["score"]["content"]
|
||||
}
|
||||
}
|
||||
|
||||
# 轻量防御:限制单次大小(自行按需调整)
|
||||
max_size = 4 * 1024 * 1024 # 2MB/份
|
||||
for name, doc in docs.items():
|
||||
if len(doc["content"].encode("utf-8")) > max_size:
|
||||
raise BadRequest(f"{name} 文档过大,超过 {max_size} 字节限制")
|
||||
|
||||
# 调用服务层保存:写源站、刷新/回写 CDN、更新索引等
|
||||
# 建议服务层返回新版本/新链接等元信息
|
||||
result = save_materials_markdown_cos(
|
||||
material_id=material_id,
|
||||
chapter_name=chapter_name,
|
||||
lesson_name=lesson_name,
|
||||
docs=docs,
|
||||
version=version, # 可选,用于并发检测
|
||||
actor=getattr(request, "user", None) # 若你的鉴权中注入了当前教师
|
||||
)
|
||||
|
||||
# 统一响应
|
||||
return jsonify({
|
||||
"ok": True,
|
||||
"material_id": material_id,
|
||||
"chapter_name": chapter_name,
|
||||
"lesson_name": lesson_name,
|
||||
"result": result # e.g. {"lesson":{"cdn_link": "...", "version":"..."}, ...}
|
||||
}), 200
|
||||
|
||||
|
||||
Reference in New Issue
Block a user