155 lines
5.2 KiB
Python
155 lines
5.2 KiB
Python
"""写入继续教育「教育公告」演示条目。
|
|
|
|
同标题已存在则跳过,不覆盖工作人员后来改过的正文。
|
|
口令只从环境变量读取。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from html import escape, unescape
|
|
from pathlib import Path
|
|
|
|
from sqlalchemy import select
|
|
|
|
from app.db import Base, SessionLocal, get_engine
|
|
from app.models.content import AdminFile
|
|
from app.models.home import HomeArticle, create_article
|
|
from app.services.storage import ensure_buckets, make_object_key, upload_object
|
|
|
|
ROOT = Path(__file__).resolve().parents[3]
|
|
SOURCE = ROOT / "docs" / "参考" / "现站" / "基础数据"
|
|
COURSE = SOURCE / "继续教育" / "文章" / "557316" / "content.txt"
|
|
CAROUSEL = SOURCE / "首页轮播"
|
|
CATEGORY = "edu_notices"
|
|
|
|
|
|
def _paragraphs_from_lines(lines: list[str]) -> str:
|
|
return "".join(f"<p>{escape(line)}</p>" for line in lines if line.strip())
|
|
|
|
|
|
def _course_html() -> str:
|
|
if not COURSE.is_file():
|
|
return _paragraphs_from_lines(["2020 年线上继续教育课程安排整理中。"])
|
|
text = unescape(COURSE.read_text(encoding="utf-8"))
|
|
lines = [line.strip() for line in text.splitlines() if line.strip()]
|
|
body = _paragraphs_from_lines(lines)
|
|
body += "<p>整理自现站公开页面:http://www.gsrea.org.cn/newsinfo/557316.html</p>"
|
|
return body
|
|
|
|
|
|
def _content_type(path: Path) -> str:
|
|
suffix = path.suffix.lower()
|
|
if suffix == ".png":
|
|
return "image/png"
|
|
if suffix == ".webp":
|
|
return "image/webp"
|
|
if suffix == ".gif":
|
|
return "image/gif"
|
|
return "image/jpeg"
|
|
|
|
|
|
def _store_public(db, path: Path, filename: str) -> AdminFile | None:
|
|
if not path.is_file():
|
|
return None
|
|
row = db.scalar(
|
|
select(AdminFile).where(AdminFile.bucket == "public", AdminFile.filename == filename)
|
|
)
|
|
if row is not None:
|
|
return row
|
|
data = path.read_bytes()
|
|
key = make_object_key(filename)
|
|
upload_object("public", key, data, _content_type(path))
|
|
row = AdminFile(
|
|
bucket="public",
|
|
object_key=key,
|
|
filename=filename,
|
|
content_type=_content_type(path),
|
|
size=len(data),
|
|
created_by=None,
|
|
)
|
|
db.add(row)
|
|
db.commit()
|
|
db.refresh(row)
|
|
return row
|
|
|
|
|
|
def _samples(cover_id: int | None) -> list[dict]:
|
|
return [
|
|
{
|
|
"title": "2026年度房地产估价师继续教育培训安排",
|
|
"publishedAt": "2026-03-02T08:00:00",
|
|
"imageFileId": cover_id,
|
|
"bodyHtml": _paragraphs_from_lines(
|
|
[
|
|
"本条为演示库样例,正式安排以协会最新通知为准。",
|
|
"培训对象:本会注册房地产估价师及从业人员。",
|
|
"时间安排:2026年4月至11月,线上课程与兰州集中面授结合。",
|
|
"学时要求:完成规定学时并通过学习记录核验后,计入当年度继续教育。",
|
|
"报名与缴费仍通过现有甘肃省继续教育系统办理,本站只发布计划与公告。",
|
|
]
|
|
),
|
|
},
|
|
{
|
|
"title": "关于开展2025年估价师继续教育补学的通知",
|
|
"publishedAt": "2025-09-18T08:00:00",
|
|
"imageFileId": cover_id,
|
|
"bodyHtml": _paragraphs_from_lines(
|
|
[
|
|
"本条为演示库样例。",
|
|
"尚未完成2025年度规定学时的会员,可于10月31日前通过继续教育系统补学。",
|
|
"补学课程包括估价报告常见问题、城市更新估价要点与行业诚信要求。",
|
|
"咨询电话:0931-8126195。",
|
|
]
|
|
),
|
|
},
|
|
{
|
|
"title": "2020年豫甘两会线上估价师继续教育课程安排",
|
|
"publishedAt": "2020-07-03T08:00:00",
|
|
"imageFileId": None,
|
|
"bodyHtml": _course_html(),
|
|
},
|
|
]
|
|
|
|
|
|
def seed() -> None:
|
|
import app.models.content # noqa: F401
|
|
import app.models.home # noqa: F401
|
|
|
|
ensure_buckets()
|
|
engine = get_engine()
|
|
Base.metadata.create_all(bind=engine)
|
|
SessionLocal.configure(bind=engine)
|
|
db = SessionLocal()
|
|
try:
|
|
cover = _store_public(db, CAROUSEL / "8488214.jpg", "edu-notice-cover.jpg")
|
|
added = 0
|
|
for item in _samples(cover.id if cover else None):
|
|
exists = db.scalar(
|
|
select(HomeArticle.id).where(
|
|
HomeArticle.category == CATEGORY,
|
|
HomeArticle.title == item["title"],
|
|
)
|
|
)
|
|
if exists is not None:
|
|
continue
|
|
create_article(
|
|
db,
|
|
{
|
|
"category": CATEGORY,
|
|
"title": item["title"],
|
|
"publishedAt": item["publishedAt"],
|
|
"published": True,
|
|
"bodyHtml": item["bodyHtml"],
|
|
"imageFileId": item["imageFileId"],
|
|
"attachmentFileIds": [],
|
|
},
|
|
)
|
|
added += 1
|
|
print(f"教育公告演示数据:新增 {added} 条。")
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
seed()
|